You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(managed-agent): Archive, delete and unarchive Workspace-bound Sessions #13164
Archive, delete and unarchive for Workspace-bound Hosted Sessions, on the public and WebShell lifecycle routes. D4 (#12881) made close, archive and delete durable operations, but only for Sessions without a Workspace binding. #13135 adds close for idle hosted-workspace-files/1 Sessions. A bound Session still cannot be archived, unarchived or deleted.
Where main is today
Refusal.ManagedAgentService.requireLegacyWorkspace answers 409 workspace_unavailable for a bound Session the actor can read, and 404 otherwise. SessionLifecycleService.admit (close, archive, delete) and unarchiveSession both call it, and session_lifecycle is false for a bound Session. Section 4.9 of the D4 design deferred these operations until feat(managed-agent): Stage D follow-ups for durable lifecycle, Turns, Actions, durable admission and AgentDefinition #12867 Q4 decides who may run them.
Close.feat(managed-agent): reliably close workspace-bound sessions #13135 (open) admits close for the creator with current read access. It permanently fences the Session against new writers and warm, releases the saved Runtime Sessions and the original holder, and stops the exact worker with a durable drain receipt before the Session becomes closed. An unverifiable identity leaves it closing with recovery_blocked. It excludes the Shell and MCP profiles, archive and delete, and adds an optional session_close capability.
Hooks. H2 (feat(managed-agent): implement durable Hosted Hooks (H2) #13129, open) runs SessionEnd and SessionDelete on the Harness's explicit deletion, DELETE /session/:id, after draining earlier operations and before releasing Runtime, provider and writer ownership. POST /session/:id/detach runs neither. An unknown SessionEnd or SessionDelete keeps the delete at 503 and retains the owner. Java's HostedHarnessClient.closeSession sends DELETE /session/:id for both a D4 close and a D4 delete, so once H2 lands, closing a bound Session that has Hooks would also run its SessionDelete.
For a closed bound Session, archive completes in the admission transaction as in D4, and unarchive restores closed without lifting the close fence of #13135. Admission follows #13135: the creator with current read access, 404 without read access, 403 for a readable non-creator. History, Artifacts, file-history backups and publications stay.
A replayed key returns the original result on both surfaces. Another actor's key is a separate request. A Session that is not closed answers 409 session_state_conflict. An unarchived Session still refuses input and warm.
L2: delete a closed or archived Session
The D4 tombstone for bound Sessions: Session reads answer 404 and its operations stay readable. The delete commits the O4-1 retirement of private recovery and publication access together with the tombstone. Shared Workspace files and other Sessions' holders stay.
Tombstone and operation reads on both surfaces. Retirement and tombstone commit together or not at all.
L3: delete an active Session
Delete through the Harness's explicit deletion, so SessionEnd and SessionDelete run once, then the settlement of #13135, then L2. Close moves to a Harness call that does not run SessionDelete. A running, cancelling or approval-waiting Turn answers 409 turn_active. An unknown Hook or execution outcome leaves the Session deleting with recovery_blocked; nothing is replayed or provisioned again.
Lost replies and a crash at each step, with claim takeover on a second server. ACL or mount revoked after admission. Each Hook runs once, and a close runs no SessionDelete. Real MySQL concurrency, and Linux identity checks where available.
L4: Shell and MCP profiles
Close and delete for hosted-workspace-shell/1, which settles capture and publications before the O4 retirement, and for hosted-workspace-mcp/1, which detaches and releases its connections through the H1 release receipts.
The L3 matrix for each profile, plus an API delete of a Shell Session followed by O4-2 collection without a seam.
L1 and L2 can start on top of #13135 now and land after it. L3 needs L2, and its Hook part needs #13129. L4 depends on question 1.
Who may delete: only the creator, as for close, or also a Workspace administrator who did not create the Session?
Why is this needed?
Workspace-bound Sessions are the only Sessions that run tools. Once #13135 lands they can be closed on the files profile, and nothing else. A tenant cannot archive or delete them, so their records, backups and publications can never be retired, and O4 collection has no real trigger. The D4 lifecycle contract should hold for bound Sessions as it does for the others: close, archive, and a delete that leaves a tombstone and keeps the shared Workspace.
What would you like to be added?
Archive, delete and unarchive for Workspace-bound Hosted Sessions, on the public and WebShell lifecycle routes. D4 (#12881) made close, archive and delete durable operations, but only for Sessions without a Workspace binding. #13135 adds close for idle
hosted-workspace-files/1Sessions. A bound Session still cannot be archived, unarchived or deleted.Where main is today
ManagedAgentService.requireLegacyWorkspaceanswers409 workspace_unavailablefor a bound Session the actor can read, and404otherwise.SessionLifecycleService.admit(close, archive, delete) andunarchiveSessionboth call it, andsession_lifecycleisfalsefor a bound Session. Section 4.9 of the D4 design deferred these operations until feat(managed-agent): Stage D follow-ups for durable lifecycle, Turns, Actions, durable admission and AgentDefinition #12867 Q4 decides who may run them.closed. An unverifiable identity leaves itclosingwithrecovery_blocked. It excludes the Shell and MCP profiles, archive and delete, and adds an optionalsession_closecapability.DELETE /session/:id, after draining earlier operations and before releasing Runtime, provider and writer ownership.POST /session/:id/detachruns neither. An unknown SessionEnd or SessionDelete keeps the delete at503and retains the owner. Java'sHostedHarnessClient.closeSessionsendsDELETE /session/:idfor both a D4 close and a D4 delete, so once H2 lands, closing a bound Session that has Hooks would also run its SessionDelete.Proposed slices
closedwithout lifting the close fence of #13135. Admission follows #13135: the creator with current read access,404without read access,403for a readable non-creator. History, Artifacts, file-history backups and publications stay.409 session_state_conflict. An unarchived Session still refuses input and warm.404and its operations stay readable. The delete commits the O4-1 retirement of private recovery and publication access together with the tombstone. Shared Workspace files and other Sessions' holders stay.409 turn_active. An unknown Hook or execution outcome leaves the Sessiondeletingwithrecovery_blocked; nothing is replayed or provisioned again.hosted-workspace-shell/1, which settles capture and publications before the O4 retirement, and forhosted-workspace-mcp/1, which detaches and releases its connections through the H1 release receipts.L1 and L2 can start on top of #13135 now and land after it. L3 needs L2, and its Hook part needs #13129. L4 depends on question 1.
Out of scope
Questions before implementation
session_closein feat(managed-agent): reliably close workspace-bound sessions #13135, orsession_lifecycleturningtruefor a Session once all four operations work for its profile?Why is this needed?
Workspace-bound Sessions are the only Sessions that run tools. Once #13135 lands they can be closed on the files profile, and nothing else. A tenant cannot archive or delete them, so their records, backups and publications can never be retired, and O4 collection has no real trigger. The D4 lifecycle contract should hold for bound Sessions as it does for the others: close, archive, and a delete that leaves a tombstone and keeps the shared Workspace.
Part of #12380, under Stage D (#12867). Follows D4 (#12881) and #13135.
中文说明
希望增加什么?
在公开与 WebShell 生命周期路由上,为绑定了 Workspace 的 Hosted 会话提供 archive、delete 与 unarchive。D4(#12881)把 close、archive、delete 做成了持久操作,但只覆盖没有 Workspace 绑定的会话。#13135 为空闲的
hosted-workspace-files/1会话补上了 close。绑定会话目前仍不能归档、取消归档或删除。main 上的现状
ManagedAgentService.requireLegacyWorkspace对调用者可读的绑定会话返回409 workspace_unavailable,不可读时返回404。SessionLifecycleService.admit(close、archive、delete)与unarchiveSession都调用它,绑定会话的session_lifecycle为false。D4 设计第 4.9 节把这些操作推迟到 feat(managed-agent): Stage D follow-ups for durable lifecycle, Turns, Actions, durable admission and AgentDefinition #12867 的 Q4 决定由谁执行之后。closed之前以持久的 drain 回执停止确切的 worker。身份无法核验时,会话保持closing并标记recovery_blocked。它不含 Shell 与 MCP 配置、archive 与 delete,并新增可选的session_close能力。DELETE /session/:id上运行 SessionEnd 与 SessionDelete,先排空之前的操作,再释放 Runtime、provider 与 writer 的所有权。POST /session/:id/detach两者都不运行。SessionEnd 或 SessionDelete 结果未知时,删除保持503并保留所有者。Java 的HostedHarnessClient.closeSession对 D4 的 close 与 delete 都发送DELETE /session/:id,所以 H2 合入后,关闭一个配置了 Hook 的绑定会话也会运行它的 SessionDelete。拆分
closed,不解除 #13135 的关闭围栏。准入沿用 #13135:当前有读权限的创建者可以执行,无读权限返回404,有读权限的非创建者返回403。历史、Artifact、文件历史备份与发布都保留。409 session_state_conflict。取消归档后的会话仍拒绝输入与 warm。404,其操作仍可读取。删除与墓碑一起提交 O4-1 对私有恢复与发布访问的退役。共享的 Workspace 文件与其他会话的持有保留。409 turn_active。Hook 或执行结果未知时,会话保持deleting并标记recovery_blocked,不重放、不重新供给。hosted-workspace-shell/1提供 close 与 delete,在 O4 退役之前结算捕获与发布;为hosted-workspace-mcp/1提供 close 与 delete,通过 H1 的释放回执 detach 并释放连接。L1 与 L2 现在就能在 #13135 之上开始,在它之后合入。L3 依赖 L2,其中的 Hook 部分依赖 #13129。L4 取决于问题 1。
不在范围内
实现前需要确认的问题
session_close那样按操作分别给出,还是某个会话的配置支持全部四种操作后,把它的session_lifecycle置为true?为什么需要?
绑定 Workspace 的会话是唯一会运行工具的会话。#13135 合入后,它们只能在 files 配置下被关闭,别的都做不了。租户无法归档或删除它们,它们的记录、备份与发布永远无法退役,O4 的回收也没有真实的触发入口。D4 的生命周期契约应当像对其他会话一样适用于绑定会话:close、archive,以及留下墓碑并保留共享 Workspace 的 delete。
属于 #12380 的 D 阶段(#12867)。接续 D4(#12881)与 #13135。