Repository navigation
feat(runtime): add child-session runtime primitive - #1376
Conversation
|
I think two parts of the durable child-session contract need to be completed in this PR before the public spawn path is migrated:
These are both much easier to define now, while the persisted schema is being introduced, than after PR3 starts creating real child sessions that require migration compatibility. |
30c0437 to
35e752b
Compare
|
Follow-up review on 1. [P1] The snapshot tool allowlist is still not enforced by every host
That means a persisted
2. [P1] Legacy relation-only child sessions still activate fail-openStorage intentionally accepts legacy rows with However, activation currently does Legacy rows can remain readable/projectable, but attempting to execute one should fail closed whenever 3. [P1] Deleting the child releases the durable spawn identityThe unique spawn constraint lives only on the live
A retry of the same spawn identity can therefore create a new child and execute the work again after the original child is deleted. The durable spawn claim needs to outlive the deletable session row, for example in a separate 4. [P2] The metadata-only retry path can miss cancellation and calls
|
Summary
Part of #1366. This is PR 2 in the proposed child-session sequence and follows #1368.
spawnChildSessionruntime primitive without switchingagent_spawnoragent_swarm;AgentRun, with noparentRunIdand no parent transcript inheritance;Durable idempotency
SQLite metadata schema v5 owns spawn identities in a dedicated
subagent_spawnsclaim table:(parentSessionId, parentRunId, toolCallId);(swarmId, itemId).Each claim persists the request fingerprint, child session id, initial turn/run ids, and claim time. The v4 migration backfills claims from live child metadata and removes the old live-row unique index. Claims intentionally have no foreign key to
session_metadata, so deleting a child session cannot release its spawn identity and cause the work to execute again; a retry against a deleted target fails closed.Each new child also persists a SHA-256 request fingerprint covering lineage, profile, prompt, and swarm item. On conflict, storage returns the existing child only when its relation, fingerprint, and claim agree. Runtime joins the in-process invocation, returns a completed durable result, or repairs an inactive interrupted run. Reusing the same identity for different work fails closed.
Runtime snapshot and execution boundary
SubagentSessionRuntimestores:Reopening a child no longer resolves the current builtin profile definition. Runtime reconstructs execution directly from the stored snapshot and resolves only the named tool implementations. Catalog prompt/policy changes therefore do not alter an existing child; a missing or disallowed tool implementation fails closed.
BackendFactoryContext.toolsis now explicitly a hard ceiling: hosts may narrow it but may not append or substitute tools. CLI/TUI and Headless consume the persisted prompt and scoped tools directly; Desktop no longer appends plan-control tools or lets the computer-use E2E seam override a child scope. Legacy relation-only child sessions remain readable/projectable but refuse activation when the durable runtime snapshot is absent.Runtime invariants
sessionId + runId + turnIdto still be active.onReadyis exactly-once and fires only after an initial run exists or starts.childSessionId.Exercised profile
local_read/ Local Read:explore;Read,Glob,Grep;Non-goals
agent_spawn/agent_swarmcompatibility paths (PR 3);contextMode: "fork"or copying parent history;Validation
npm run typechecknpm run build:test@maka/storagesuite plus focused SQLite v4→v5/deletion regression/usr/localexecutable-root assumption and Homebrewrgloadingpcre2through the sandbox)git diff --check中文说明
概述
这是 #1366 的第 2 个 PR,承接已合并的 #1368。
spawnChildSessionprimitive,但暂不切换agent_spawn/agent_swarm;AgentRun执行,不设置parentRunId,也不继承父 transcript;持久幂等
SQLite metadata schema v5 新增独立的
subagent_spawnsclaim 表。普通 spawn 的 key 是(parentSessionId, parentRunId, toolCallId),swarm item 再加入(swarmId, itemId)。claim 保存 request fingerprint、child session id、首个 turn/run id 和 claim 时间。v4→v5 迁移会从现有 child metadata 回填 claim。claim 不依赖可删除的
session_metadata行,所以删除 Child Session 不会释放 spawn identity;之后同一调用重试会 fail closed,而不会新建 Child 并重复执行。Runtime snapshot 与执行边界
快照包含 schema version、definition version、精确 system prompt、category policy、tool allowlist、agent identity/profile 和 permission ceiling。Child 重开时不再查询当前 builtin profile definition,而是从持久化 snapshot 恢复,仅按名称解析工具实现。
BackendFactoryContext.tools现在是 host 的硬上限:host 可以进一步收窄,但不能追加或替换工具。CLI/TUI、Desktop、Headless 均遵守该边界。仅有父子 relation、缺少 runtime snapshot 的 legacy Child 仍可读取和展示,但执行时直接 fail closed。metadata-only crash retry 在启动首个 Run 前会重新检查 parent run 与取消信号;
onReady保证 exactly-once,避免之前的双回调和取消后误启动。本 PR 仍只打通
local_read/ Local Read 只读 profile。切换公共 spawn/swarm、legacy execution-reference union、contextMode: "fork"、Child Session UI 投影和 #1341 graph scheduling 留给后续 PR。