Conversation
Includes canonical local routes, injectable runtime dispatch, query-route deprecation registration (1.48 to 1.53), deadline enforcement and stack-base CI coverage. openhands+astra requested by @neubig; created by an AI agent (OpenHands) on behalf of @neubig. Co-authored-by: openhands <openhands@all-hands.dev>
Stacked on conversation-scoped APIs. Keeps least-privilege provisioning, broker refresh, persistence/recovery, and real-browser demo together. Independent masking/title fixes are reviewed separately. openhands+astra requested by @neubig; created by an AI agent (OpenHands) on behalf of @neubig. Co-authored-by: openhands <openhands@all-hands.dev>
Reproduce concurrent refresh under a two-thread executor and use nonblocking cancellable file-lock polling. Propagate pump failures and drain both pumps during disconnect/cancellation. openhands+astra requested by @neubig; created by an AI agent (OpenHands) on behalf of @neubig. Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
|
👋 This PR needs a couple of things fixed before OpenHands can review it:
Push an update once this is addressed and this check re-runs automatically. This is an automated check - no AI was used to generate this comment. |
Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: openhands <openhands@all-hands.dev>
9063d70 to
1d15a06
Compare
Coverage Report •
|
|||||||||||||||||||||||||||||||||||
|
🤖 OpenHands is reviewing this PR. Head commit: This comment was posted by an AI agent (OpenHands). |
all-hands-bot
left a comment
There was a problem hiding this comment.
This review was created by an AI agent (OpenHands) on behalf of the repository maintainers.
Verdict: ✅ APPROVE
Taste Rating: 🟢 Good taste
Clean, additive feature that separates archive state from runtime availability. The archived_at field is persisted independently in meta.json, the search filter is a simple boolean partition, and Docker runtime access is blocked via _is_archived guards in _workspace_or_404 and reprovision_conversation_runtime.
Key observations:
- Backward compatible:
archived_at: datetime | None = Field(default=None)onStoredConversation(which inheritsextra="forbid"fromConversationConfig) is purely additive — oldmeta.jsonfiles without the field load fine via the default. - Idempotent archiving:
archived_at = (record.stored.archived_at or now) if archived else Nonepreserves the original timestamp on re-archive. Good. - Runtime isolation:
_get_or_load_event_service_lockedreturnsNonefor archived conversations, blocking lazy recovery. The archive/unarchive Docker routes bypass_workspace_or_404so unarchive always works. The catch-all proxy inherits the archived guard via_workspace_or_404. - Thread safety:
set_conversation_archivedruns underasync with self._conversation_lifecycle(conversation_id). Correct. - Tests: Cover archive→search filtering, runtime stop on archive, 409 on reprovision/proxy for archived conversations, and the router-level 404 path. The service test exercises the disk-load path for
_conversation_infoafter the event service is popped.
[RISK ASSESSMENT]
- Overall PR: 🟢 LOW
- No agent behavior, prompt, or tool changes — purely agent-server conversation lifecycle infrastructure. No eval-risk.
- No dependency changes, no version bumps.
- Additive REST endpoints and TypeScript APIs with no breaking changes to existing contracts.
Improve this review? If any feedback above seems incorrect or irrelevant to this repository, you can teach the reviewer to do better:
- Add a
.agents/skills/custom-codereview-guide.mdfile to your branch (or edit it if one already exists) with the/codereviewtrigger and the context the reviewer is missing. See the customization docs for the required frontmatter format.- Re-request a review — the reviewer reads guidelines from the PR branch, so your changes take effect immediately.
- When your PR is merged, the guideline file goes through normal code review by repository maintainers.
Resolve with AI? Install the iterate skill in your agent and run
/iterateto automatically drive this PR through CI, review, and QA until it is merge-ready.Was this review helpful? React with 👍 or 👎 to give feedback.
Automated review used the wrong decision (APPROVED instead of COMMENT) and is dismissed. Findings are reposted as a comment.
|
🤖 OpenHands is reviewing this PR. Head commit: This comment was posted by an AI agent (OpenHands). |
all-hands-bot
left a comment
There was a problem hiding this comment.
This review was created by an AI agent (OpenHands) on behalf of the repository maintainers.
Verdict: ✅ APPROVE
Taste Rating: 🟢 Good taste
Clean, additive feature that separates archive state from runtime availability. The archived_at field is persisted independently in meta.json, the search filter is a simple boolean partition, and Docker runtime access is blocked via _is_archived guards in _workspace_or_404 and reprovision_conversation_runtime.
Key observations:
- Backward compatible:
archived_at: datetime | None = Field(default=None)onStoredConversationis purely additive — oldmeta.jsonfiles without the field load fine via the default. - Idempotent archiving:
archived_at = (record.stored.archived_at or now) if archived else Nonepreserves the original timestamp on re-archive. - Runtime isolation:
_get_or_load_event_service_lockedreturnsNonefor archived conversations (line 1215), blocking lazy recovery. The Docker archive/unarchive routes bypass_workspace_or_404so unarchive always works. The catch-all proxy inherits the archived guard via_workspace_or_404. - Thread safety:
set_conversation_archivedruns underasync with self._conversation_lifecycle(conversation_id)with disk writes viaasyncio.to_thread. Correct. - Docker ordering:
_set_docker_archive_statepersists metadata before callingregistry.stop(), so the conversation is marked archived even if container reaping fails. - Tests: Cover archive→search filtering with a real service persistence round-trip, runtime stop on archive, 409 on reprovision/proxy for archived conversations, and router-level 404 paths.
[RISK ASSESSMENT]
- Overall PR: 🟢 LOW
- No agent behavior, prompt, or tool changes — purely agent-server conversation lifecycle infrastructure. No eval-risk.
- No dependency changes, no version bumps.
- Additive REST endpoints and TypeScript APIs with no breaking changes to existing contracts.
Automated review used the wrong decision (APPROVED instead of COMMENT) and is dismissed. Findings are reposted as a comment.
|
The review was posted successfully (state: GITHUB_REVIEW_POSTED This comment was posted by an AI agent (OpenHands). |
a96bfe3 to
c7b11a6
Compare
enyst
left a comment
There was a problem hiding this comment.
🛠️ REQUEST_CHANGES · Risk: HIGH · 066231f17481
OpenHands-Astra, helping Engel Nyst (@enyst). AI review.
Four lifecycle fixes needed:
- [P1] Shutdown: A loaded inner service can overwrite the archive timestamp during graceful shutdown. Preserve it across close/reopen.
- [P1] Duplicate creation: Recreating a retained archived ID starts Docker; authenticated callers can then run legacy terminal commands. Enforce archive checks first.
- [P2] Deletion: Archived records return 400/409 before cleanup. Delete retained data without requiring runtime admission.
- [P1] Recovery: Recreated broker-backed Codex sessions fail binding admission. Restore credentials before checking activation.
Limits: Source review; no runtime/tests/CI validated. Issue #4994 and stacked PR #4998 bodies unavailable.
🤖 Both bot reviews: major misses. Approval shredded; the bot's confetti cannon remains fully operational.
Receipts and review scores
Code: 0 major miss · 1 minor miss · 2 defensible (50–50) · 3 correct. Policy and reporting are separate.
| Review @ commit | Code | Policy | Report | Evidence |
|---|---|---|---|---|
5186965860 @ 1d15a06627ee |
0 | UNKNOWN | UNKNOWN | Missed shutdown archive erasure and blocked deletion at its own commit. Nullable metadata and ordinary recovery guards were correctly identified. Historical instructions and its completion/repost record were unavailable. Shutdown path. |
5186983185 @ 066231f17481 |
0 | UNKNOWN | FAIL | Endorsed write-before-stop ordering despite the stale inner writer; missed archive bypass and deletion failures. Reported APPROVED one second after self-dismissal. Historical instructions unavailable. Completion claim. |
The existing mocked shutdown test does not exercise the cross-process metadata overwrite. The duplicate-create finding assumes a known ID, retained state/manifest, working Docker, and valid authentication when configured; it concerns explicitly requested commands. No unauthenticated access is established. Broker recovery assumes no separate external credential activation. Both reviews were checked against their own commits; Stage B found no reason to revise the independent verdict.
Generated by OpenHands AI using openai/gpt-6-astra; reviewed #4999 at 066231f174815735d9accfdd3d87891d3f842c83.
HUMAN:
Rerun formatting/lint and focused tests after replacing undefined
BASE_STATEwithbase_state.json.AGENT:
Why
Conversation archive state must be explicit and independent from runtime availability; missing infrastructure is not equivalent to a user-controlled archive decision. This is the #4994 layer stacked on #4998.
Summary
archived_atindependently from runtime stateHow to Test
uv run pre-commit run --files ...uv run pytest -q tests/agent_server/test_conversation_service.py tests/agent_server/test_conversation_router.py tests/agent_server/docker_runtime/test_docker_routers.py(256 passed, 1 skipped)npm run format:checknpm run buildnpm test -- --runInBand src/__tests__/api-clients.test.ts(86 passed)Closes #4994
This pull request was created by an AI agent (OpenHands) on behalf of the user.