@sema-agent/server 1.323.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/approval-hmac.d.ts +40 -0
- package/dist/approval-hmac.js +67 -0
- package/dist/approval.d.ts +31 -0
- package/dist/approval.js +72 -4
- package/dist/audit.d.ts +26 -0
- package/dist/audit.js +40 -1
- package/dist/auth-bridge.d.ts +10 -0
- package/dist/auth-bridge.js +47 -4
- package/dist/auth-keys.d.ts +19 -0
- package/dist/auth-keys.js +13 -0
- package/dist/bake-runner/main.d.ts +5 -0
- package/dist/bake-runner/main.js +43 -4
- package/dist/bake-runner/protocol.d.ts +57 -0
- package/dist/bake-runner/protocol.js +58 -3
- package/dist/bake-runner/runner.d.ts +54 -0
- package/dist/bake-runner/runner.js +87 -5
- package/dist/bench/l8/artifact.d.ts +63 -0
- package/dist/bench/l8/artifact.js +61 -2
- package/dist/bench/l8/escape.d.ts +36 -0
- package/dist/bench/l8/escape.js +25 -0
- package/dist/bench/l8/index.d.ts +14 -0
- package/dist/bench/l8/index.js +14 -0
- package/dist/bench/l8/probes.d.ts +74 -0
- package/dist/bench/l8/probes.js +60 -0
- package/dist/bench/l8/run-probes.d.ts +43 -0
- package/dist/bench/l8/run-probes.js +45 -2
- package/dist/bench/s1/arms.d.ts +126 -0
- package/dist/bench/s1/arms.js +188 -13
- package/dist/bench/s1/live-deps.d.ts +66 -0
- package/dist/bench/s1/live-deps.js +249 -11
- package/dist/bench/s1/oracle.d.ts +49 -0
- package/dist/bench/s1/oracle.js +36 -1
- package/dist/bench/s1/repair-oracle-adapter.d.ts +33 -0
- package/dist/bench/s1/repair-oracle-adapter.js +30 -0
- package/dist/bench/s1/reviewer.d.ts +38 -0
- package/dist/bench/s1/reviewer.js +34 -0
- package/dist/bench/s1/row.d.ts +77 -0
- package/dist/bench/s1/row.js +62 -0
- package/dist/bench/s1/run-firm.d.ts +47 -0
- package/dist/bench/s1/run-firm.js +70 -4
- package/dist/bench/s1/runner-ctx.d.ts +71 -0
- package/dist/bench/s1/runner-ctx.js +36 -0
- package/dist/bench/s1/tasks.d.ts +108 -0
- package/dist/bench/s1/tasks.js +115 -0
- package/dist/boot/budget-tracing.d.ts +48 -0
- package/dist/boot/budget-tracing.js +86 -0
- package/dist/boot/config-center.d.ts +62 -0
- package/dist/boot/config-center.js +995 -0
- package/dist/boot/coordinators.d.ts +33 -0
- package/dist/boot/coordinators.js +97 -0
- package/dist/boot/execution-env.d.ts +26 -0
- package/dist/boot/execution-env.js +370 -0
- package/dist/boot/leader.d.ts +27 -0
- package/dist/boot/leader.js +81 -0
- package/dist/boot/reapers.d.ts +53 -0
- package/dist/boot/reapers.js +252 -0
- package/dist/boot/resolve-spec.d.ts +70 -0
- package/dist/boot/resolve-spec.js +1072 -0
- package/dist/boot/runner-deps.d.ts +101 -0
- package/dist/boot/runner-deps.js +343 -0
- package/dist/boot/runtime-caps.d.ts +21 -0
- package/dist/boot/runtime-caps.js +62 -0
- package/dist/boot/session-faces.d.ts +57 -0
- package/dist/boot/session-faces.js +157 -0
- package/dist/boot/shutdown.d.ts +50 -0
- package/dist/boot/shutdown.js +129 -0
- package/dist/boot/stores.d.ts +32 -0
- package/dist/boot/stores.js +361 -0
- package/dist/boot/workflow-orchestration.d.ts +46 -0
- package/dist/boot/workflow-orchestration.js +150 -0
- package/dist/boot-reclaim.d.ts +19 -0
- package/dist/boot-reclaim.js +20 -0
- package/dist/brain.d.ts +25 -0
- package/dist/brain.js +61 -1
- package/dist/budget.d.ts +66 -0
- package/dist/budget.js +128 -4
- package/dist/capabilities/builtin-tools.d.ts +3 -0
- package/dist/capabilities/builtin-tools.js +3 -0
- package/dist/capabilities/center-plugins.d.ts +17 -1
- package/dist/capabilities/center-plugins.js +45 -4
- package/dist/capabilities/center-prompts.d.ts +46 -0
- package/dist/capabilities/center-prompts.js +57 -3
- package/dist/capabilities/code-review-council.d.ts +28 -0
- package/dist/capabilities/code-review-council.js +40 -7
- package/dist/capabilities/collab-wire.d.ts +2 -0
- package/dist/capabilities/collab-workflows.d.ts +7 -0
- package/dist/capabilities/collab-workflows.js +44 -1
- package/dist/capabilities/oa-tools.d.ts +6 -0
- package/dist/capabilities/oa-tools.js +10 -0
- package/dist/capabilities/prompt.d.ts +14 -0
- package/dist/capabilities/prompt.js +14 -0
- package/dist/capabilities/prompts/code-review.d.ts +14 -0
- package/dist/capabilities/prompts/code-review.js +14 -0
- package/dist/capabilities/prompts/identity.d.ts +6 -0
- package/dist/capabilities/prompts/identity.js +6 -0
- package/dist/capabilities/prompts/team.d.ts +4 -0
- package/dist/capabilities/prompts/team.js +4 -0
- package/dist/capabilities/repo-tools.d.ts +11 -0
- package/dist/capabilities/repo-tools.js +8 -0
- package/dist/capabilities/sandbox-file-send.d.ts +95 -0
- package/dist/capabilities/sandbox-file-send.js +91 -3
- package/dist/capabilities/scenarios.d.ts +130 -0
- package/dist/capabilities/scenarios.js +180 -7
- package/dist/capabilities/select-environment-tool.d.ts +7 -0
- package/dist/capabilities/select-environment-tool.js +30 -0
- package/dist/capabilities/send-user-file-tool.d.ts +33 -0
- package/dist/capabilities/send-user-file-tool.js +65 -1
- package/dist/capabilities/skills.d.ts +29 -0
- package/dist/capabilities/skills.js +13 -2
- package/dist/capabilities/team.d.ts +22 -0
- package/dist/capabilities/team.js +22 -2
- package/dist/capabilities/tool-defer.d.ts +26 -0
- package/dist/capabilities/tool-defer.js +3 -0
- package/dist/config-center/apply-effective.d.ts +65 -0
- package/dist/config-center/apply-effective.js +204 -12
- package/dist/config-center/http-client.d.ts +34 -0
- package/dist/config-center/http-client.js +68 -0
- package/dist/config-center/restart-signal.d.ts +22 -0
- package/dist/config-center/restart-signal.js +39 -0
- package/dist/config-center/skills-mcp.d.ts +20 -1
- package/dist/config-center/skills-mcp.js +42 -7
- package/dist/config-center/types.d.ts +92 -1
- package/dist/config-lkg.d.ts +12 -0
- package/dist/config-lkg.js +41 -0
- package/dist/config-provider.d.ts +78 -0
- package/dist/config-provider.js +165 -2
- package/dist/config-types.d.ts +585 -1
- package/dist/config.d.ts +78 -2
- package/dist/config.js +874 -301
- package/dist/degenerate-instrument.d.ts +38 -0
- package/dist/degenerate-instrument.js +55 -3
- package/dist/elicitation.d.ts +39 -0
- package/dist/elicitation.js +87 -3
- package/dist/env-facts.d.ts +61 -0
- package/dist/env-facts.js +73 -7
- package/dist/fleet/fleet-bus.d.ts +185 -0
- package/dist/fleet/fleet-bus.js +333 -27
- package/dist/fleet/subagent-tail-bus.d.ts +11 -0
- package/dist/fleet/subagent-tail-bus.js +33 -2
- package/dist/fleet-client.d.ts +38 -0
- package/dist/fleet-client.js +44 -9
- package/dist/fleet-lease.d.ts +46 -0
- package/dist/fleet-lease.js +73 -5
- package/dist/hooks/branch-transcript.d.ts +8 -0
- package/dist/hooks/branch-transcript.js +33 -0
- package/dist/hooks/cc-stop-prompt.d.ts +42 -0
- package/dist/hooks/cc-stop-prompt.js +43 -1
- package/dist/hooks/hook-llm.d.ts +15 -0
- package/dist/hooks/hook-llm.js +47 -0
- package/dist/hooks/hook-runner.d.ts +89 -0
- package/dist/hooks/hook-runner.js +327 -18
- package/dist/http/idempotency.d.ts +31 -0
- package/dist/http/idempotency.js +34 -0
- package/dist/http/principal-gate.d.ts +17 -0
- package/dist/http/principal-gate.js +35 -3
- package/dist/http/route-ctx.d.ts +36 -0
- package/dist/http/routes/approvals-assistant.d.ts +25 -0
- package/dist/http/routes/approvals-assistant.js +253 -23
- package/dist/http/routes/attachments.js +22 -4
- package/dist/http/routes/capabilities.d.ts +7 -0
- package/dist/http/routes/capabilities.js +202 -1
- package/dist/http/routes/fleet.d.ts +6 -0
- package/dist/http/routes/fleet.js +94 -5
- package/dist/http/routes/images.d.ts +17 -0
- package/dist/http/routes/images.js +222 -14
- package/dist/http/routes/leader.d.ts +7 -0
- package/dist/http/routes/leader.js +10 -0
- package/dist/http/routes/memory-policy.d.ts +6 -0
- package/dist/http/routes/memory-policy.js +38 -6
- package/dist/http/routes/notify-wake.d.ts +10 -0
- package/dist/http/routes/notify-wake.js +19 -3
- package/dist/http/routes/observability.d.ts +6 -0
- package/dist/http/routes/observability.js +19 -2
- package/dist/http/routes/runs.d.ts +15 -0
- package/dist/http/routes/runs.js +464 -41
- package/dist/http/routes/session-sync.d.ts +15 -0
- package/dist/http/routes/session-sync.js +229 -19
- package/dist/http/routes/sessions-list.d.ts +6 -0
- package/dist/http/routes/sessions-list.js +35 -4
- package/dist/http/routes/sessions.d.ts +14 -0
- package/dist/http/routes/sessions.js +176 -31
- package/dist/http/routes/side-query.d.ts +8 -0
- package/dist/http/routes/side-query.js +26 -1
- package/dist/http/routes/tasks.d.ts +18 -0
- package/dist/http/routes/tasks.js +501 -38
- package/dist/http/routes/trace-usage.d.ts +10 -0
- package/dist/http/routes/trace-usage.js +66 -14
- package/dist/http/routes/workflows.d.ts +12 -0
- package/dist/http/routes/workflows.js +180 -19
- package/dist/http/run-meta.d.ts +11 -0
- package/dist/http/run-meta.js +6 -0
- package/dist/http/send.d.ts +19 -0
- package/dist/http/send.js +11 -0
- package/dist/http/server.d.ts +255 -0
- package/dist/http/server.js +921 -75
- package/dist/http/sse-log.d.ts +15 -0
- package/dist/http/sse-log.js +16 -0
- package/dist/http/tar.d.ts +9 -0
- package/dist/http/tar.js +21 -5
- package/dist/http/wire-gate.d.ts +9 -0
- package/dist/http/wire-gate.js +9 -0
- package/dist/http/wire-types.d.ts +187 -0
- package/dist/http/workspace-content.d.ts +8 -0
- package/dist/http/workspace-content.js +10 -0
- package/dist/images/bake-validate.d.ts +63 -0
- package/dist/images/bake-validate.js +71 -1
- package/dist/images/manifest.d.ts +19 -0
- package/dist/images/manifest.js +6 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.js +10 -5
- package/dist/key-resolver.d.ts +23 -0
- package/dist/key-resolver.js +27 -2
- package/dist/leader/diffout.d.ts +23 -0
- package/dist/leader/diffout.js +8 -1
- package/dist/leader/diffup.d.ts +32 -0
- package/dist/leader/diffup.js +43 -0
- package/dist/leader/endpoint.d.ts +20 -0
- package/dist/leader/endpoint.js +25 -2
- package/dist/leader/fanout.d.ts +60 -0
- package/dist/leader/fanout.js +29 -3
- package/dist/leader/grader-env-factory.d.ts +74 -0
- package/dist/leader/grader-env-factory.js +62 -3
- package/dist/leader/leader.d.ts +97 -0
- package/dist/leader/leader.js +151 -4
- package/dist/leader/merge.d.ts +94 -0
- package/dist/leader/merge.js +112 -9
- package/dist/leader/planner.d.ts +52 -0
- package/dist/leader/planner.js +47 -3
- package/dist/leader/repair-oracle.d.ts +61 -0
- package/dist/leader/repair-oracle.js +59 -1
- package/dist/leader/repair-wire.d.ts +78 -0
- package/dist/leader/repair-wire.js +79 -2
- package/dist/leader/wire.d.ts +79 -0
- package/dist/leader/wire.js +255 -8
- package/dist/lsp/e2b-bridge.d.ts +16 -0
- package/dist/lsp/e2b-bridge.js +32 -4
- package/dist/lsp/e2b-manager.d.ts +10 -0
- package/dist/lsp/e2b-manager.js +18 -2
- package/dist/lsp/lsp-frames.d.ts +12 -0
- package/dist/lsp/lsp-frames.js +12 -0
- package/dist/lsp/manager.d.ts +12 -0
- package/dist/lsp/manager.js +35 -2
- package/dist/lsp/types.d.ts +10 -0
- package/dist/lsp/ws-transport.d.ts +12 -0
- package/dist/lsp/ws-transport.js +53 -5
- package/dist/lsp-evict.d.ts +14 -0
- package/dist/lsp-evict.js +15 -1
- package/dist/main.js +530 -2129
- package/dist/memory-export.d.ts +1 -0
- package/dist/memory-export.js +4 -0
- package/dist/memory-scope.d.ts +49 -0
- package/dist/memory-scope.js +87 -4
- package/dist/memory-sync-client.d.ts +24 -0
- package/dist/memory-sync-client.js +41 -2
- package/dist/memory-sync.d.ts +23 -0
- package/dist/memory-sync.js +70 -1
- package/dist/model-select.d.ts +39 -0
- package/dist/model-select.js +42 -1
- package/dist/observability/cost-quota.d.ts +20 -0
- package/dist/observability/cost-quota.js +4 -0
- package/dist/observability/cost-taxonomy.d.ts +45 -0
- package/dist/observability/cost-taxonomy.js +34 -0
- package/dist/observability/logger.d.ts +1 -0
- package/dist/observability/logger.js +6 -0
- package/dist/observability/metrics.d.ts +13 -0
- package/dist/observability/metrics.js +63 -0
- package/dist/observability/otel-exporter.d.ts +9 -0
- package/dist/observability/otel-exporter.js +11 -3
- package/dist/observability/principal-context.d.ts +9 -0
- package/dist/observability/principal-context.js +9 -0
- package/dist/observability/prompt-manifest.d.ts +37 -0
- package/dist/observability/prompt-manifest.js +35 -1
- package/dist/observability/rate-limit.d.ts +10 -0
- package/dist/observability/rate-limit.js +1 -0
- package/dist/observability/tool-trace.d.ts +24 -0
- package/dist/observability/tool-trace.js +41 -1
- package/dist/orchestration/hardened-vm-runner.d.ts +107 -0
- package/dist/orchestration/hardened-vm-runner.js +119 -4
- package/dist/orchestration/hardened-vm-worker-runner.d.ts +14 -0
- package/dist/orchestration/hardened-vm-worker-runner.js +26 -1
- package/dist/orchestration/hardened-vm-worker.js +27 -0
- package/dist/orchestration/subagent-steer.d.ts +44 -0
- package/dist/orchestration/subagent-steer.js +45 -1
- package/dist/orchestration/workflow-agent-steer.d.ts +54 -0
- package/dist/orchestration/workflow-agent-steer.js +80 -1
- package/dist/orchestration/workflow-completion-inbox.d.ts +189 -2
- package/dist/orchestration/workflow-completion-inbox.js +283 -32
- package/dist/orchestration/workflow-notify-journal.d.ts +132 -1
- package/dist/orchestration/workflow-notify-journal.js +187 -13
- package/dist/parked-decide.d.ts +61 -0
- package/dist/parked-decide.js +58 -1
- package/dist/per-task-image.d.ts +54 -0
- package/dist/per-task-image.js +41 -0
- package/dist/plan-cache-probe.d.ts +35 -0
- package/dist/plan-cache-probe.js +18 -3
- package/dist/plugins/approval-exemption-store.d.ts +7 -0
- package/dist/plugins/approval-exemption-store.js +28 -2
- package/dist/plugins/approval-store-sql.d.ts +64 -0
- package/dist/plugins/approval-store-sql.js +32 -0
- package/dist/plugins/background-agent-store-sql.d.ts +55 -0
- package/dist/plugins/background-agent-store-sql.js +91 -4
- package/dist/plugins/background-shell-support.d.ts +98 -0
- package/dist/plugins/background-shell-support.js +117 -13
- package/dist/plugins/blob-backend.d.ts +104 -0
- package/dist/plugins/blob-backend.js +163 -6
- package/dist/plugins/breaker-state-sql.d.ts +65 -1
- package/dist/plugins/breaker-state-sql.js +46 -8
- package/dist/plugins/caching-session-store.d.ts +42 -0
- package/dist/plugins/caching-session-store.js +63 -3
- package/dist/plugins/checkpoint-store-sql.d.ts +179 -0
- package/dist/plugins/checkpoint-store-sql.js +239 -11
- package/dist/plugins/file-outcome-sink.d.ts +4 -0
- package/dist/plugins/file-outcome-sink.js +9 -0
- package/dist/plugins/file-resume-anchor-store.d.ts +20 -0
- package/dist/plugins/file-resume-anchor-store.js +43 -4
- package/dist/plugins/file-run-store.d.ts +90 -0
- package/dist/plugins/file-run-store.js +145 -13
- package/dist/plugins/file-snapshot-store-sql.d.ts +133 -1
- package/dist/plugins/file-snapshot-store-sql.js +178 -10
- package/dist/plugins/file-workflow-journal-store.d.ts +10 -0
- package/dist/plugins/file-workflow-journal-store.js +10 -0
- package/dist/plugins/fork-routing-session-store.d.ts +47 -0
- package/dist/plugins/fork-routing-session-store.js +51 -3
- package/dist/plugins/host-platform.d.ts +69 -0
- package/dist/plugins/host-platform.js +81 -2
- package/dist/plugins/image-bake-store-sql.d.ts +136 -1
- package/dist/plugins/image-bake-store-sql.js +241 -7
- package/dist/plugins/image-index-sql.d.ts +46 -0
- package/dist/plugins/image-index-sql.js +113 -4
- package/dist/plugins/k8s-bg-scripts.d.ts +34 -0
- package/dist/plugins/k8s-bg-scripts.js +88 -4
- package/dist/plugins/k8s-exec-protocol.d.ts +33 -0
- package/dist/plugins/k8s-exec-protocol.js +41 -0
- package/dist/plugins/local-checkpoint-store.d.ts +40 -0
- package/dist/plugins/local-checkpoint-store.js +86 -7
- package/dist/plugins/local-session-store.d.ts +157 -0
- package/dist/plugins/local-session-store.js +289 -34
- package/dist/plugins/local-task-attachment-store.js +14 -2
- package/dist/plugins/mailbox-store-sql.d.ts +38 -0
- package/dist/plugins/mailbox-store-sql.js +39 -6
- package/dist/plugins/memory-engine-pg.d.ts +30 -0
- package/dist/plugins/memory-engine-pg.js +122 -4
- package/dist/plugins/memory-engine-tidb.d.ts +26 -0
- package/dist/plugins/memory-engine-tidb.js +115 -5
- package/dist/plugins/memory-engine-vector-util.d.ts +5 -0
- package/dist/plugins/memory-engine-vector-util.js +5 -0
- package/dist/plugins/memory-resume-anchor-store.d.ts +8 -0
- package/dist/plugins/memory-resume-anchor-store.js +17 -0
- package/dist/plugins/memory-run-store.d.ts +63 -0
- package/dist/plugins/memory-run-store.js +73 -8
- package/dist/plugins/memory-session-policy-store.d.ts +17 -0
- package/dist/plugins/memory-session-policy-store.js +17 -0
- package/dist/plugins/memory-sync-store-pg.d.ts +42 -0
- package/dist/plugins/memory-sync-store-pg.js +45 -2
- package/dist/plugins/memory-sync-store-tidb.d.ts +9 -0
- package/dist/plugins/memory-sync-store-tidb.js +31 -1
- package/dist/plugins/outcome-ledger-sql.d.ts +63 -0
- package/dist/plugins/outcome-ledger-sql.js +97 -3
- package/dist/plugins/pg-approval-store.d.ts +7 -0
- package/dist/plugins/pg-approval-store.js +7 -0
- package/dist/plugins/pg-breaker-state.d.ts +6 -0
- package/dist/plugins/pg-breaker-state.js +6 -0
- package/dist/plugins/pg-checkpoint-store.d.ts +8 -0
- package/dist/plugins/pg-checkpoint-store.js +8 -0
- package/dist/plugins/pg-cost-quota.d.ts +17 -0
- package/dist/plugins/pg-cost-quota.js +6 -0
- package/dist/plugins/pg-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/pg-file-snapshot-store.js +6 -0
- package/dist/plugins/pg-image-bake.d.ts +9 -0
- package/dist/plugins/pg-image-bake.js +9 -0
- package/dist/plugins/pg-image-index.d.ts +9 -0
- package/dist/plugins/pg-image-index.js +9 -0
- package/dist/plugins/pg-outcome-ledger.d.ts +9 -0
- package/dist/plugins/pg-outcome-ledger.js +9 -0
- package/dist/plugins/pg-pool.d.ts +50 -0
- package/dist/plugins/pg-pool.js +78 -0
- package/dist/plugins/pg-query.d.ts +11 -0
- package/dist/plugins/pg-rate-limiter.d.ts +23 -0
- package/dist/plugins/pg-rate-limiter.js +12 -2
- package/dist/plugins/pg-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/pg-resume-anchor-store.js +5 -0
- package/dist/plugins/pg-run-store.d.ts +7 -0
- package/dist/plugins/pg-run-store.js +7 -0
- package/dist/plugins/pg-safe-json.d.ts +13 -0
- package/dist/plugins/pg-safe-json.js +40 -4
- package/dist/plugins/pg-session-policy-store.d.ts +5 -0
- package/dist/plugins/pg-session-policy-store.js +5 -0
- package/dist/plugins/pg-session-storage.d.ts +72 -0
- package/dist/plugins/pg-session-storage.js +152 -20
- package/dist/plugins/pg-session-store.d.ts +10 -0
- package/dist/plugins/pg-session-store.js +10 -0
- package/dist/plugins/pg-tool-result-store.d.ts +7 -0
- package/dist/plugins/pg-tool-result-store.js +7 -0
- package/dist/plugins/pg-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-journal-store.js +7 -0
- package/dist/plugins/pg-workflow-run-store.d.ts +7 -0
- package/dist/plugins/pg-workflow-run-store.js +7 -0
- package/dist/plugins/posix-shell-fs.d.ts +3 -0
- package/dist/plugins/posix-shell-fs.js +31 -1
- package/dist/plugins/remote-env-adb.d.ts +25 -0
- package/dist/plugins/remote-env-adb.js +95 -12
- package/dist/plugins/remote-env-e2b.d.ts +146 -0
- package/dist/plugins/remote-env-e2b.js +371 -40
- package/dist/plugins/remote-env-file-error.d.ts +34 -0
- package/dist/plugins/remote-env-file-error.js +37 -0
- package/dist/plugins/remote-env-host.d.ts +151 -0
- package/dist/plugins/remote-env-host.js +468 -70
- package/dist/plugins/remote-env-k8s.d.ts +135 -0
- package/dist/plugins/remote-env-k8s.js +318 -32
- package/dist/plugins/remote-env-local-docker.d.ts +65 -0
- package/dist/plugins/remote-env-local-docker.js +149 -24
- package/dist/plugins/remote-env-ssh.d.ts +35 -0
- package/dist/plugins/remote-env-ssh.js +117 -20
- package/dist/plugins/remote-scratchpad.d.ts +38 -0
- package/dist/plugins/remote-scratchpad.js +32 -2
- package/dist/plugins/remote-shell.d.ts +22 -0
- package/dist/plugins/remote-shell.js +27 -1
- package/dist/plugins/resume-anchor-store-sql.d.ts +28 -0
- package/dist/plugins/resume-anchor-store-sql.js +11 -0
- package/dist/plugins/roster-store-sql.d.ts +27 -0
- package/dist/plugins/roster-store-sql.js +54 -0
- package/dist/plugins/run-store-sql.d.ts +194 -0
- package/dist/plugins/run-store-sql.js +210 -9
- package/dist/plugins/s3-presign.d.ts +20 -0
- package/dist/plugins/s3-presign.js +49 -2
- package/dist/plugins/scheduler-support.d.ts +12 -0
- package/dist/plugins/scheduler-support.js +75 -3
- package/dist/plugins/send-file-ledger.d.ts +15 -0
- package/dist/plugins/send-file-ledger.js +53 -4
- package/dist/plugins/send-user-file.d.ts +77 -0
- package/dist/plugins/send-user-file.js +92 -4
- package/dist/plugins/session-policy-store-sql.d.ts +15 -0
- package/dist/plugins/session-policy-store-sql.js +75 -3
- package/dist/plugins/session-store.d.ts +45 -0
- package/dist/plugins/session-store.js +51 -0
- package/dist/plugins/sql-driver.d.ts +77 -0
- package/dist/plugins/sql-driver.js +4 -0
- package/dist/plugins/sql-escape.d.ts +8 -0
- package/dist/plugins/sql-escape.js +8 -0
- package/dist/plugins/sql-row-helpers.d.ts +25 -0
- package/dist/plugins/sql-row-helpers.js +25 -0
- package/dist/plugins/store-backend.d.ts +103 -0
- package/dist/plugins/store-backend.js +120 -27
- package/dist/plugins/store-contracts.d.ts +62 -0
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +60 -0
- package/dist/plugins/task-attachment-store.js +49 -3
- package/dist/plugins/task-list-store-sql.d.ts +25 -0
- package/dist/plugins/task-list-store-sql.js +21 -0
- package/dist/plugins/tidb-approval-store.d.ts +6 -0
- package/dist/plugins/tidb-approval-store.js +6 -0
- package/dist/plugins/tidb-breaker-state.d.ts +5 -0
- package/dist/plugins/tidb-breaker-state.js +5 -0
- package/dist/plugins/tidb-checkpoint-store.d.ts +7 -0
- package/dist/plugins/tidb-checkpoint-store.js +7 -0
- package/dist/plugins/tidb-cost-quota.d.ts +6 -0
- package/dist/plugins/tidb-cost-quota.js +1 -0
- package/dist/plugins/tidb-file-snapshot-store.d.ts +6 -0
- package/dist/plugins/tidb-file-snapshot-store.js +6 -0
- package/dist/plugins/tidb-image-bake.d.ts +8 -0
- package/dist/plugins/tidb-image-bake.js +8 -0
- package/dist/plugins/tidb-image-index.d.ts +8 -0
- package/dist/plugins/tidb-image-index.js +8 -0
- package/dist/plugins/tidb-outcome-ledger.d.ts +10 -0
- package/dist/plugins/tidb-outcome-ledger.js +10 -0
- package/dist/plugins/tidb-pool.d.ts +56 -0
- package/dist/plugins/tidb-pool.js +181 -1
- package/dist/plugins/tidb-rate-limiter.d.ts +11 -0
- package/dist/plugins/tidb-rate-limiter.js +5 -2
- package/dist/plugins/tidb-resume-anchor-store.d.ts +5 -0
- package/dist/plugins/tidb-resume-anchor-store.js +5 -0
- package/dist/plugins/tidb-run-store.d.ts +7 -0
- package/dist/plugins/tidb-run-store.js +7 -0
- package/dist/plugins/tidb-session-policy-store.d.ts +5 -0
- package/dist/plugins/tidb-session-policy-store.js +5 -0
- package/dist/plugins/tidb-session-storage.d.ts +43 -0
- package/dist/plugins/tidb-session-storage.js +62 -3
- package/dist/plugins/tidb-session-store.d.ts +142 -0
- package/dist/plugins/tidb-session-store.js +264 -16
- package/dist/plugins/tidb-tool-result-store.d.ts +5 -0
- package/dist/plugins/tidb-tool-result-store.js +7 -0
- package/dist/plugins/tidb-workflow-journal-store.d.ts +7 -0
- package/dist/plugins/tidb-workflow-journal-store.js +7 -0
- package/dist/plugins/tidb-workflow-run-store.d.ts +8 -0
- package/dist/plugins/tidb-workflow-run-store.js +8 -0
- package/dist/plugins/tool-result-store-sql.d.ts +58 -0
- package/dist/plugins/tool-result-store-sql.js +38 -2
- package/dist/plugins/web-search.d.ts +35 -0
- package/dist/plugins/web-search.js +45 -9
- package/dist/plugins/workflow-journal-limits.d.ts +10 -0
- package/dist/plugins/workflow-journal-limits.js +10 -0
- package/dist/plugins/workflow-journal-store-sql.d.ts +78 -0
- package/dist/plugins/workflow-journal-store-sql.js +58 -2
- package/dist/plugins/workflow-run-store-sql.d.ts +84 -0
- package/dist/plugins/workflow-run-store-sql.js +84 -6
- package/dist/plugins/worktree-isolation.d.ts +45 -0
- package/dist/plugins/worktree-isolation.js +105 -6
- package/dist/plugins/write-behind-counter.d.ts +56 -1
- package/dist/plugins/write-behind-counter.js +53 -14
- package/dist/principal-jwt.d.ts +24 -0
- package/dist/principal-jwt.js +60 -5
- package/dist/project-memory.d.ts +22 -0
- package/dist/project-memory.js +144 -15
- package/dist/prompts-domain-validate.d.ts +28 -0
- package/dist/prompts-domain-validate.js +42 -1
- package/dist/question.d.ts +33 -0
- package/dist/question.js +69 -2
- package/dist/resource-suspend.d.ts +21 -0
- package/dist/resource-suspend.js +16 -0
- package/dist/router/route-orchestration.d.ts +78 -0
- package/dist/router/route-orchestration.js +77 -0
- package/dist/run-local.d.ts +32 -0
- package/dist/run-local.js +172 -8
- package/dist/runs.d.ts +189 -4
- package/dist/runs.js +465 -24
- package/dist/runtime-caps-resolver.d.ts +106 -0
- package/dist/runtime-caps-resolver.js +89 -4
- package/dist/runtime-governance.d.ts +84 -0
- package/dist/runtime-governance.js +127 -1
- package/dist/sandbox-pkg-source.d.ts +23 -0
- package/dist/sandbox-pkg-source.js +37 -0
- package/dist/sealed-key.d.ts +54 -0
- package/dist/sealed-key.js +68 -3
- package/dist/security.d.ts +108 -0
- package/dist/security.js +145 -6
- package/dist/sema-registry.d.ts +21 -0
- package/dist/sema-registry.js +21 -0
- package/dist/session-leaf-bus.d.ts +31 -0
- package/dist/session-leaf-bus.js +32 -0
- package/dist/session-sync-content.d.ts +46 -0
- package/dist/session-sync-content.js +47 -1
- package/dist/session-sync-kernel.d.ts +89 -0
- package/dist/session-sync-kernel.js +48 -3
- package/dist/session-sync.d.ts +125 -0
- package/dist/session-sync.js +181 -8
- package/dist/session-titler.d.ts +26 -0
- package/dist/session-titler.js +41 -7
- package/dist/session-watch.d.ts +53 -1
- package/dist/session-watch.js +73 -9
- package/dist/sighup-idle.d.ts +30 -0
- package/dist/sighup-idle.js +12 -1
- package/dist/spec-fields.d.ts +91 -3
- package/dist/spec-fields.js +116 -4
- package/dist/task-cwd.d.ts +50 -0
- package/dist/task-cwd.js +68 -1
- package/dist/task-mcp.d.ts +47 -0
- package/dist/task-mcp.js +29 -0
- package/dist/task-settings.d.ts +175 -0
- package/dist/task-settings.js +226 -11
- package/dist/task-workflow.d.ts +67 -0
- package/dist/task-workflow.js +75 -8
- package/dist/tool-approval.d.ts +91 -0
- package/dist/tool-approval.js +215 -0
- package/dist/trace/artifacts.d.ts +9 -0
- package/dist/trace/artifacts.js +30 -5
- package/dist/trace/core-keyset-guard.d.ts +18 -0
- package/dist/trace/ledger-sink.d.ts +43 -0
- package/dist/trace/ledger-sink.js +64 -5
- package/dist/trace/project.d.ts +133 -0
- package/dist/trace/project.js +189 -2
- package/dist/trace/redact.d.ts +19 -0
- package/dist/trace/redact.js +66 -9
- package/dist/usage-analytics.d.ts +26 -0
- package/dist/usage-analytics.js +26 -3
- package/package.json +1 -1
package/dist/fleet/fleet-bus.js
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MF-Fleet (shell-host data-contract, the dynamic-stream obligation) — the SERVICE-side live fleet
|
|
3
|
+
* aggregation bus + state, backing `GET /v1/fleet/stream`.
|
|
4
|
+
*
|
|
5
|
+
* The fleet view (CC 187 0616_053) animates a MULTI-ROW tree: every active task's `status/elapsedMs/tokens/
|
|
6
|
+
* queuedCount` and every workflow's `doneCount N/M · failedCount` TRANSITION over time. That is a *push* stream,
|
|
7
|
+
* not a one-shot read: the backend must emit every transition for as long as a run is live, with STABLE per-row
|
|
8
|
+
* identity so the UI updates the right row in place.
|
|
9
|
+
*
|
|
10
|
+
* This bus is the in-process aggregator: the run lifecycle (createRun → queued/running, per-turn token accrual,
|
|
11
|
+
* terminal → completed/failed) and the workflow lifecycle (WorkflowRun put/update → doneCount/status) publish
|
|
12
|
+
* their per-row deltas here; `GET /v1/fleet/stream` subscribes, sends a SNAPSHOT on connect, then forwards every
|
|
13
|
+
* delta. Identity: tasks keyed by `id` (the durable runId/taskId), workflows by their workflow runId, subagent
|
|
14
|
+
* sub-rows (round 5, pending core's `task_progress` arm) by `parentId`+agent id (E2 `parentToolCallId`).
|
|
15
|
+
*
|
|
16
|
+
* 🔒 boundary (design/99 §0): the FLEET aggregation + the SSE wire is **service** (UI/deployment-state view over
|
|
17
|
+
* the runs ledger + workflow store). The engine semantics (a run's own events, a subagent's usage ticks) are
|
|
18
|
+
* core's — the bus only AGGREGATES what the lifecycle already produces. It carries NO new engine state.
|
|
19
|
+
*
|
|
20
|
+
* NOT durable / NOT cross-replica: a live fleet is this replica's active runs (mirrors `steerableRuns` —
|
|
21
|
+
* replica-local). A cross-replica fleet roll-up is a fleet-token-gated trace-API concern (separate), not this.
|
|
22
|
+
*/
|
|
1
23
|
import { EventEmitter } from "node:events";
|
|
2
24
|
import { canonicalToolName } from "@sema-agent/core";
|
|
3
25
|
import { redactSecrets } from "../trace/redact.js";
|
|
26
|
+
/**
|
|
27
|
+
* The process-local fleet aggregation bus. Holds the current active set + fans out deltas to SSE subscribers.
|
|
28
|
+
* Upserts MERGE (a partial delta patches the existing row), so a publisher can emit just the field that changed
|
|
29
|
+
* (e.g. only `tokens`) and the row stays whole. Removal drops the row (terminal). Subscribers get a snapshot of
|
|
30
|
+
* the current set immediately, then every subsequent delta.
|
|
31
|
+
*/
|
|
4
32
|
export class FleetEventBus {
|
|
5
33
|
now;
|
|
6
34
|
emitter = new EventEmitter();
|
|
@@ -8,39 +36,51 @@ export class FleetEventBus {
|
|
|
8
36
|
workflows = new Map();
|
|
9
37
|
constructor(now = () => Date.now()) {
|
|
10
38
|
this.now = now;
|
|
11
|
-
this.emitter.setMaxListeners(0);
|
|
39
|
+
this.emitter.setMaxListeners(0); // unbounded SSE subscribers (each /v1/fleet/stream connection)
|
|
12
40
|
}
|
|
41
|
+
/** Upsert a task row (MERGE onto any existing row by `id`) + fan out the merged row. Publishers may send a
|
|
42
|
+
* partial `{ id, tokens }` etc.; the row keeps its other fields. */
|
|
13
43
|
publishTask(delta) {
|
|
14
44
|
const merged = { ...(this.tasks.get(delta.id) ?? { id: delta.id, name: delta.id, status: "running" }), ...delta };
|
|
15
45
|
this.tasks.set(delta.id, merged);
|
|
16
46
|
this.emit({ type: "task", row: merged, ts: this.now() });
|
|
17
47
|
}
|
|
48
|
+
/** 推一帧 hook 判定未完成的观测通知(事件语义,不进 snapshot —— 与 `bg_notification` 同族)。 */
|
|
18
49
|
publishHookNotice(notice) {
|
|
19
50
|
this.emit({ type: "hook_notice", notice, ts: this.now() });
|
|
20
51
|
}
|
|
52
|
+
/** Drop a task row (terminal + swept) + fan out the removal. Idempotent (a no-op if already gone). */
|
|
21
53
|
removeTask(id) {
|
|
22
54
|
if (this.tasks.delete(id))
|
|
23
55
|
this.emit({ type: "task_remove", id, ts: this.now() });
|
|
24
56
|
}
|
|
57
|
+
/** Upsert a workflow row (MERGE by `id`) + fan out. */
|
|
25
58
|
publishWorkflow(delta) {
|
|
26
59
|
const merged = { ...(this.workflows.get(delta.id) ?? { id: delta.id, name: delta.id, status: "running" }), ...delta };
|
|
27
60
|
this.workflows.set(delta.id, merged);
|
|
28
61
|
this.emit({ type: "workflow", row: merged, ts: this.now() });
|
|
29
62
|
}
|
|
63
|
+
/** Drop a workflow row + fan out the removal. Idempotent. */
|
|
30
64
|
removeWorkflow(id) {
|
|
31
65
|
if (this.workflows.delete(id))
|
|
32
66
|
this.emit({ type: "workflow_remove", id, ts: this.now() });
|
|
33
67
|
}
|
|
68
|
+
/** design/129-B 缺口②: fan out a background-child completion notification (EVENT — not stored, never in the
|
|
69
|
+
* snapshot; a subscriber that connects later reads the durable inbox instead). */
|
|
34
70
|
publishBgNotification(notification) {
|
|
35
71
|
this.emit({ type: "bg_notification", notification, ts: this.now() });
|
|
36
72
|
}
|
|
73
|
+
/** The current full state (the connect-time snapshot frame). */
|
|
37
74
|
snapshot() {
|
|
38
75
|
return { type: "snapshot", tasks: [...this.tasks.values()], workflows: [...this.workflows.values()], ts: this.now() };
|
|
39
76
|
}
|
|
77
|
+
/** Subscribe to deltas. Returns an unsubscribe thunk. The caller typically sends `snapshot()` first, then every
|
|
78
|
+
* delta this delivers — the snapshot+delta sequence is the live fleet view. */
|
|
40
79
|
subscribe(cb) {
|
|
41
80
|
this.emitter.on("frame", cb);
|
|
42
81
|
return () => this.emitter.off("frame", cb);
|
|
43
82
|
}
|
|
83
|
+
/** Live counts (test/observability). */
|
|
44
84
|
get size() {
|
|
45
85
|
return { tasks: this.tasks.size, workflows: this.workflows.size };
|
|
46
86
|
}
|
|
@@ -48,18 +88,37 @@ export class FleetEventBus {
|
|
|
48
88
|
this.emitter.emit("frame", frame);
|
|
49
89
|
}
|
|
50
90
|
}
|
|
91
|
+
/** A run-scoped lifecycle publisher — wire it into a run's TaskEvent loop so the fleet row TRANSITIONS with the
|
|
92
|
+
* run. `onStart()` adds the top-level row (running); `onEvent(ev)` accrues tokens (turn_end usage) + adds/updates
|
|
93
|
+
* subagent CHILD rows (core `task_progress`, keyed by its `taskId`, nested under the run via `parentId`);
|
|
94
|
+
* `onTerminal(status)` flips the row terminal + removes it (and its children) from the active set. No-op when no
|
|
95
|
+
* bus is wired. The token accrual is CUMULATIVE across the run's turns (turn_end carries a per-turn delta). */
|
|
51
96
|
export function fleetRunPublisher(bus, run) {
|
|
52
97
|
if (!bus)
|
|
53
98
|
return { onStart: () => undefined, onEvent: () => undefined, onForwardEvent: () => undefined, onChildTerminal: () => false, onTerminal: () => undefined };
|
|
54
99
|
let tokens = 0;
|
|
55
100
|
const startedAt = Date.now();
|
|
101
|
+
// #3 fleet per-session scope (clay 2026-06-30): tag every row of THIS run with its rootTaskId (= sessionId) so
|
|
102
|
+
// /v1/fleet/stream can filter to the caller's CURRENT session (a TUI footer no longer shows other sessions of the
|
|
103
|
+
// same principal). publishTask MERGEs, so tagging the CREATE frame suffices — status/token updates keep the field.
|
|
56
104
|
const sessionField = run.rootTaskId ? { sessionId: run.rootTaskId } : {};
|
|
57
|
-
const children = new Set();
|
|
58
|
-
const childStartedAt = new Map();
|
|
105
|
+
const children = new Set(); // subagent child row ids (removed with the run)
|
|
106
|
+
const childStartedAt = new Map(); // [1332]④:child 行时长轴(首 tick 起表)
|
|
107
|
+
// codex R2:spawning tool-call id → cid。core 的失败/killed 收尾通知不带 sessionId(成功路径才有条件带),
|
|
108
|
+
// 此时 task_id(a*)解不到 uuid 键的 tick 行——但 tick 的 ident() 带 parentToolCallId,通知带同源 toolUseId,
|
|
109
|
+
// 这是两 id 域之外唯一贯穿 spawn→terminal 的关联轴。一次 Task 调用只 spawn 一个 child,键不撞。
|
|
59
110
|
const childByToolCall = new Map();
|
|
111
|
+
// Once the leg SETTLED, a LATE subagent tick must not resurrect a child
|
|
112
|
+
// row — the settle's removeTask IS the shell's release signal (auto-exit watches the evict); a post-settle
|
|
113
|
+
// re-publish left a zombie "running" row with no terminal/remove ever coming. Freeze all publishes after
|
|
114
|
+
// onTerminal (a resume runs on a FRESH publisher — this leg's handle is done).
|
|
60
115
|
let settledLeg = false;
|
|
61
116
|
const childId = (taskId) => `${run.runId} ${taskId}`;
|
|
117
|
+
/** [1415]③:task_progress.status 值域映射(1.354 settle 终态 tick)——completed/failed 直译,其余(含
|
|
118
|
+
* undefined/"running"/suspended 不发的诚实面)恒 running(旧 core 行为逐位不变)。 */
|
|
62
119
|
const tickStatus = (st) => (st === "completed" ? "completed" : st === "failed" ? "failed" : "running");
|
|
120
|
+
/** [1748] 从一拍 usage 里取**累计**工具调用次数。与 `sumTokens` 同样防御式取值(该位在这两处的
|
|
121
|
+
* 静态类型是 `{}`)。⚠️ 缺席就返回 undefined —— 调用点据此**不发这个键**(缺席 ≠ 0)。 */
|
|
63
122
|
const toolUsesOf = (usage) => {
|
|
64
123
|
const t = usage?.toolUses;
|
|
65
124
|
return typeof t === "number" ? t : undefined;
|
|
@@ -70,6 +129,12 @@ export function fleetRunPublisher(bus, run) {
|
|
|
70
129
|
return 0;
|
|
71
130
|
if (typeof u.totalTokens === "number")
|
|
72
131
|
return u.totalTokens;
|
|
132
|
+
// #9 (workflow 2nd-pass re-review): a turn_end.usage has NO totalTokens → this field-sum. core's turn_end.inputTokens
|
|
133
|
+
// is the NORMALIZED TOTAL INPUT *INCLUDING CACHE* (usage-accounting promptTokensOf — input + cacheRead + cacheWrite
|
|
134
|
+
// for the Anthropic family; OpenAI already folds cacheRead into input). So inputTokens + outputTokens ALREADY is the
|
|
135
|
+
// turn total — the old code ALSO added cacheRead/cacheWrite, double-counting them (~2x with prompt caching, the
|
|
136
|
+
// normal case). Display-only (the leader fleet-row token number); billing (costMicroUsd) + context/compaction use
|
|
137
|
+
// totalTokens and were never affected; child rows use task_progress.usage.totalTokens (the early-return) — correct.
|
|
73
138
|
return (u.inputTokens ?? 0) + (u.outputTokens ?? 0);
|
|
74
139
|
};
|
|
75
140
|
return {
|
|
@@ -78,44 +143,105 @@ export function fleetRunPublisher(bus, run) {
|
|
|
78
143
|
},
|
|
79
144
|
onEvent(ev) {
|
|
80
145
|
if (settledLeg)
|
|
81
|
-
return;
|
|
146
|
+
return; // no post-settle publishes (zombie-row resurrection)
|
|
82
147
|
if (ev.type === "turn_end" && !ev.parentToolCallId) {
|
|
83
|
-
|
|
148
|
+
// #9 orchestration token attribution (core 1.180 TaskEventIdentity on turn_end): accrue ONLY the LEADER's own
|
|
149
|
+
// turns onto the run row. A turn_end WITH a parentToolCallId is an orchestration/subagent SUB-turn (a
|
|
150
|
+
// run_workflow agent or a spawned subagent) — its usage belongs to that child's own row / the workflow's
|
|
151
|
+
// budget, NOT the leader. Before core threaded the identity onto turn_end (1.121 left it the only boundary
|
|
152
|
+
// event without it), the leader row over-counted sub-turn usage on self-orchestration runs.
|
|
153
|
+
tokens += sumTokens(ev.usage); // turn_end carries a per-turn usage delta → accumulate
|
|
84
154
|
bus.publishTask({ id: run.runId, tokens, elapsedMs: Date.now() - startedAt });
|
|
85
155
|
}
|
|
86
156
|
else if (ev.type === "task_progress" && ev.taskId) {
|
|
157
|
+
// core 1.147 subagent usage tick (per-turn, cumulative) → a CHILD fleet row nested under the run.
|
|
87
158
|
const cid = childId(ev.taskId);
|
|
88
159
|
children.add(cid);
|
|
160
|
+
// BC-2 (core 1.151): use the subagent's sanitized display `name` (taskName/agent-type) for the child row;
|
|
161
|
+
// fall back to the taskId when absent (an anonymous subagent — core deliberately omits name rather than leak
|
|
162
|
+
// the delegated objective). The row IDENTITY stays `cid` (runId+taskId); only the display label improves.
|
|
163
|
+
// [WF2-A] redact the subagent display name for PARITY with the top-level run name (fleetRunLabels): core
|
|
164
|
+
// sanitizes it for RENDERING (ANSI/NUL strip + truncate) but does NOT secret-redact, so a secret-shaped
|
|
165
|
+
// taskName would leak verbatim on the child row without this.
|
|
166
|
+
// §K-7: `ev.name` IS the subagent TYPE (BC-2: taskName / selected agent-type) → ALSO surface it as
|
|
167
|
+
// `agentType` (the picker's short-label field), not only the display `name`. Absent name (anonymous
|
|
168
|
+
// subagent) → no agentType (the row falls back to name=taskId). One redacted value (name === agentType).
|
|
89
169
|
const childName = redactSecrets(ev.name ?? ev.taskId);
|
|
90
170
|
if (!childStartedAt.has(cid))
|
|
91
171
|
childStartedAt.set(cid, Date.now());
|
|
92
172
|
if (ev.parentToolCallId)
|
|
93
173
|
childByToolCall.set(ev.parentToolCallId, cid);
|
|
174
|
+
// [1415]③ 点亮半场:core 1.354 起 settle 时补终态 tick(status 值域 additive 扩 completed|failed;
|
|
175
|
+
// 此前恒 "running"=行为逐位不变)——workflow 子的 uuid 行终于有完成态可见(running→removed 的
|
|
176
|
+
// [1414]#3 形就此闭)。
|
|
94
177
|
bus.publishTask({ id: cid, name: childName, ...(ev.name ? { agentType: childName } : {}), parentId: run.runId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
95
178
|
}
|
|
96
179
|
else if (ev.type === "tool_start" && ev.toolName) {
|
|
180
|
+
// BC-1 (clay 2026-06-27): the top-level run row's `description` = LIVE ACTIVITY (the tool now running), NOT
|
|
181
|
+
// the objective. `name` already carries an objective preview (fleetRunLabels); ALSO putting the objective in
|
|
182
|
+
// `description` showed it TWICE (the dup the shell flagged). So `description` tracks the current tool, CC-like.
|
|
183
|
+
// Tool NAME only — args are untrusted/redacted, a row label must never leak them. Subagent CHILD rows keep
|
|
184
|
+
// their task_progress display name (BC-2); this updates the TOP-LEVEL run row only.
|
|
185
|
+
// PascalCase double-belt (core 1.176): canonicalize so a legacy snake CONTROL verb (e.g. a
|
|
186
|
+
// pre-1.176 emit / a stray report_blocked) renders as its CC name (ReportBlocked) and the shell's PascalCase
|
|
187
|
+
// suppression Set still hides it — never re-leaking a control verb as fleet-row activity.
|
|
97
188
|
bus.publishTask({ id: run.runId, description: canonicalToolName(ev.toolName) });
|
|
98
189
|
}
|
|
99
190
|
},
|
|
100
191
|
onForwardEvent(ev) {
|
|
192
|
+
// core 1.154 (design/99 nested-subagent live tree): a SUBAGENT's `task_progress` tick forwarded from its
|
|
193
|
+
// ISOLATED stream to the top run's opt-in sink (`RunInternals.onForwardEvent`). This is the ONLY path a
|
|
194
|
+
// subagent tick reaches the top consumer — the top run's own stream does NOT carry it (the tick lives in the
|
|
195
|
+
// child's stream, consumed by the parent's runTask). So this builds the fleet's per-subagent CHILD rows at ANY
|
|
196
|
+
// depth: `parentTaskId` names the spawner — the TOP run (= `rootTaskId` → nest under run.runId) or another
|
|
197
|
+
// subagent (→ nest under that subagent's row). core sets a child's `parentTaskId` = its spawner's task_progress
|
|
198
|
+
// `taskId` (prepare-task.ts), so the tree keys line up. Forwarded ticks are UNTRUSTED display hints (name is
|
|
199
|
+
// core-sanitized; we carry NAME + token rollup only, never args).
|
|
200
|
+
// 🟡 parentTaskId is NOT validated against known runs (documented as LOW). It needn't be: the
|
|
201
|
+
// isolation guarantee is the SCOPE BOUND, not a parentTaskId check — every child row we publish is tagged
|
|
202
|
+
// `scope: run.scope` (this run's owner) and id-prefixed with the real `run.runId`. So a tool forging a
|
|
203
|
+
// `parentTaskId` can at worst MIS-NEST a row WITHIN this run's own scope view (cosmetic); it can never cross
|
|
204
|
+
// into another run / tenant. (core corrected its prepare-task note that had over-promised "deployment
|
|
205
|
+
// validates parentTaskId" — the bound is structural here.) Validation would be optional defense-in-depth only.
|
|
101
206
|
if (settledLeg)
|
|
102
|
-
return;
|
|
207
|
+
return; // a late forwarded tick must not resurrect a removed child row
|
|
103
208
|
if (ev.type !== "task_progress" || !ev.taskId)
|
|
104
209
|
return;
|
|
105
210
|
const cid = childId(ev.taskId);
|
|
106
211
|
children.add(cid);
|
|
107
212
|
const parentId = ev.parentTaskId && ev.parentTaskId !== run.rootTaskId ? childId(ev.parentTaskId) : run.runId;
|
|
213
|
+
// [WF2-A] redact the forwarded subagent name for parity with the top-level run name (see onEvent above).
|
|
214
|
+
// §K-7: ev.name IS the subagent type → also surface it as `agentType` (picker short label). Reuse the value.
|
|
108
215
|
const fwdName = redactSecrets(ev.name ?? ev.taskId);
|
|
109
216
|
if (!childStartedAt.has(cid))
|
|
110
217
|
childStartedAt.set(cid, Date.now());
|
|
111
218
|
if (ev.parentToolCallId)
|
|
112
219
|
childByToolCall.set(ev.parentToolCallId, cid);
|
|
113
|
-
bus.publishTask({ id: cid, name: fwdName, ...(ev.name ? { agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) });
|
|
220
|
+
bus.publishTask({ id: cid, name: fwdName, ...(ev.name ? { agentType: fwdName } : {}), parentId, scope: run.scope, ...sessionField, status: tickStatus(ev.status), tokens: sumTokens(ev.usage), ...(() => { const t = toolUsesOf(ev.usage); return t !== undefined ? { toolUses: t } : {}; })(), elapsedMs: Date.now() - childStartedAt.get(cid) }); // [1415]③ 同上;[1748] toolUses 同 bg lane 口径
|
|
114
221
|
},
|
|
115
222
|
onChildTerminal(taskId, status, altId, toolUseId) {
|
|
223
|
+
// A background subagent/bash CHILD settles — task_progress never emits a terminal tick,
|
|
224
|
+
// so without this the child row sat "running" until the PARENT leg settled (the shell measured 93s of
|
|
225
|
+
// phantom running; its auto-exit release condition never fired). Flip the status so subscribers SEE the
|
|
226
|
+
// terminal frame, then remove (mirroring onTerminal's leave-the-fleet posture). Idempotent on an unknown
|
|
227
|
+
// child. ⚠️ the notification's task_id is the a* domain while ticks key by the child uuid — a live
|
|
228
|
+
// mid-turn flip can therefore miss the tick-built row (flip-through mints the a* row instead); id-domain
|
|
229
|
+
// unification is core's half. Post-settle: rows are ALREADY removed (the settle evict is the
|
|
230
|
+
// shell's release signal) — a flip-through here would mint a fresh orphan row. No-op.
|
|
116
231
|
if (settledLeg)
|
|
117
232
|
return false;
|
|
233
|
+
// [1332]①:id 双域候选——tick 行键域(child sessionId uuid)与通知键域(a* task_id)因 core 版本/
|
|
234
|
+
// lane 而异,单键押注押错=真行永不落 completed(绿点不回,行滞留 running 到父 settle)。两候选谁
|
|
235
|
+
// 有活行翻谁;都没有才按首候选合成瞬态终帧(bash 无 tick 形,原语义)。
|
|
236
|
+
// codex R3:killed 保桶(与 a* 车道 fleetBackgroundChildPublisher 的终态映射一致)——操作员/系统
|
|
237
|
+
// 取消不得错报为执行失败;同一 child 两车道给订阅者的终态必须同色。
|
|
118
238
|
const fleetStatus = status === "completed" ? "completed" : status === "killed" || status === "cancelled" ? "killed" : "failed";
|
|
239
|
+
// codex F1:两 id 域可能**同时**各有一行(重复/版本偏斜投递,onEvent 与 onForwardEvent 各按一域建)
|
|
240
|
+
// ——单选一行会漏掉另一域的行,滞留 running 到父 settle(绿点不回复发)。翻**全部**属本 publisher 的
|
|
241
|
+
// 候选行,逐一终帧+离场。
|
|
242
|
+
// codex R2:第三候选 = 通知 toolUseId 经 spawn 关联解出的 cid。core 的失败/killed 收尾通知缺 sessionId
|
|
243
|
+
// (subagent.js catch 分支两处只带 task_id;成功路径才条件带)——此时前两候选同为 a* 域,tick 建的 uuid
|
|
244
|
+
// 行押不中;toolUseId↔tick.parentToolCallId 是同一次 Task 调用的同源 id,把真行找回来。
|
|
119
245
|
const candidateCids = [childId(taskId)];
|
|
120
246
|
if (altId !== undefined && altId !== taskId)
|
|
121
247
|
candidateCids.push(childId(altId));
|
|
@@ -124,6 +250,7 @@ export function fleetRunPublisher(bus, run) {
|
|
|
124
250
|
candidateCids.push(viaToolCall);
|
|
125
251
|
const liveCids = candidateCids.filter((c) => children.has(c));
|
|
126
252
|
const hadRow = liveCids.length > 0;
|
|
253
|
+
// 都没活行 = bash 无 tick 形:按首候选合成瞬态终帧(建即离,诚实且无害)。
|
|
127
254
|
for (const cid of hadRow ? liveCids : [childId(taskId)]) {
|
|
128
255
|
const startedAtChild = childStartedAt.get(cid);
|
|
129
256
|
bus.publishTask({ id: cid, ...(children.has(cid) ? {} : { name: taskId, parentId: run.runId, scope: run.scope, ...sessionField }), status: fleetStatus, ...(startedAtChild !== undefined ? { elapsedMs: Date.now() - startedAtChild } : {}) });
|
|
@@ -137,8 +264,9 @@ export function fleetRunPublisher(bus, run) {
|
|
|
137
264
|
return hadRow;
|
|
138
265
|
},
|
|
139
266
|
onTerminal(status, residuals) {
|
|
140
|
-
settledLeg = true;
|
|
267
|
+
settledLeg = true; // freeze — nothing publishes on this leg's publisher after the settle
|
|
141
268
|
const fleetStatus = runStatusToFleet(status);
|
|
269
|
+
// [1839]①/(a) 案:真终态帧带残局键(有源才带,键逐挑不 spread);parked 帧不带(行还活着)。
|
|
142
270
|
const terminal = fleetStatus === "completed" || fleetStatus === "failed" || fleetStatus === "killed";
|
|
143
271
|
const res = terminal && residuals
|
|
144
272
|
? {
|
|
@@ -148,17 +276,27 @@ export function fleetRunPublisher(bus, run) {
|
|
|
148
276
|
}
|
|
149
277
|
: {};
|
|
150
278
|
bus.publishTask({ id: run.runId, status: fleetStatus, tokens, elapsedMs: Date.now() - startedAt, ...res });
|
|
279
|
+
// Subagent CHILD rows leave on ANY settle — terminal OR parked (TOC review #8: a suspended/needs_review run
|
|
280
|
+
// keeps its row, but its subagents are NOT running while the parent is parked — their work is checkpointed; a
|
|
281
|
+
// task_progress never emits a terminal, so without this the child rows leak forever as stale "running" under a
|
|
282
|
+
// parked parent). On resume, fresh task_progress/onForwardEvent re-adds the active children.
|
|
151
283
|
for (const cid of children)
|
|
152
284
|
bus.removeTask(cid);
|
|
153
285
|
children.clear();
|
|
154
|
-
childStartedAt.clear();
|
|
155
|
-
childByToolCall.clear();
|
|
286
|
+
childStartedAt.clear(); // codex F2:长寿 bg child 的计时项不得随 publisher 句柄泄漏累积(晚到回调可达期)
|
|
287
|
+
childByToolCall.clear(); // codex R2 同理:spawn 关联表随叶 settle 清空
|
|
288
|
+
// A truly-terminal run LEAVES the fleet (the shell saw the terminal frame first). A PARKED run
|
|
289
|
+
// (suspended→waiting / needs_review→awaiting approval) is still active → its ROW STAYS in the fleet.
|
|
156
290
|
if (terminal) {
|
|
157
291
|
bus.removeTask(run.runId);
|
|
158
292
|
}
|
|
159
293
|
},
|
|
160
294
|
};
|
|
161
295
|
}
|
|
296
|
+
/** [1839]①/(a) 案:TaskResult → 终态行帧残局键映射(sync/background/resume 三条腿各自 settle,共用一处
|
|
297
|
+
* 映射——键名映射写三遍必漂移)。usage 与 {@link BgNotification.usage} 同形:stats.tokens→totalTokens、
|
|
298
|
+
* stats.toolCalls→toolUses(名对齐,消费端一个形状)。errorCode "cancelled" ⇒ stoppedBy:"user"(与
|
|
299
|
+
* markStopSource 的归因值同源);transcriptId 顶层 = run 的 sessionId([1840]§二拍)。缺源的键不铸。 */
|
|
162
300
|
export function fleetRunResiduals(result) {
|
|
163
301
|
if (!result)
|
|
164
302
|
return {};
|
|
@@ -177,6 +315,22 @@ export function fleetRunResiduals(result) {
|
|
|
177
315
|
...(result.sessionId ? { transcriptId: result.sessionId } : {}),
|
|
178
316
|
};
|
|
179
317
|
}
|
|
318
|
+
/**
|
|
319
|
+
* design/129-B (core 1.240.0) — the PROCESS-LEVEL background-child fleet publisher, wired once
|
|
320
|
+
* onto `RunnerDeps.onBackgroundChildEvent`. Unlike {@link fleetRunPublisher} (per-leg: dies at leg settle —
|
|
321
|
+
* the root cause: a session-scoped bg child outliving its turn had NO forward path, fleet showed zero
|
|
322
|
+
* child frames), this observer lives as long as the process and covers the child's WHOLE lifecycle:
|
|
323
|
+
* spawn → row appears the moment the child registers (launch→turn-tail 零帧 fixed: no more waiting for a
|
|
324
|
+
* first tick that a slow child never emits inside the turn);
|
|
325
|
+
* tick → token rollup onto the row; ALSO best-effort removes the per-leg uuid-keyed TWIN row the leg's
|
|
326
|
+
* onForwardEvent built for the same child (`${parentTaskId} ${progressTaskId}` composite — the
|
|
327
|
+
* per-leg childId shape), so the child shows ONCE, keyed by its stable a* handle;
|
|
328
|
+
* terminal → terminal frame under the a* row id, row leaves the fleet, and the contract
|
|
329
|
+
* `bg_notification` frame rides the always-open stream (缺口②'s immediate idle delivery).
|
|
330
|
+
* Rows are tagged `scope` (tenant filter) from the registry scope and `sessionId` (the `?session=` filter)
|
|
331
|
+
* from the registry owner when session-scoped (owner IS the host sessionId; task-scoped children have no
|
|
332
|
+
* session attribution → unscoped, back-compat visible). Names ride the same redactSecrets discipline.
|
|
333
|
+
*/
|
|
180
334
|
export function fleetBackgroundChildPublisher(bus, log) {
|
|
181
335
|
if (!bus)
|
|
182
336
|
return () => undefined;
|
|
@@ -185,6 +339,7 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
185
339
|
log?.(msg, fields);
|
|
186
340
|
}
|
|
187
341
|
catch {
|
|
342
|
+
/* observability must never fault the observer */
|
|
188
343
|
}
|
|
189
344
|
};
|
|
190
345
|
const meta = new Map();
|
|
@@ -194,6 +349,11 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
194
349
|
meta.delete(id);
|
|
195
350
|
meta.set(id, m);
|
|
196
351
|
if (meta.size > MAX) {
|
|
352
|
+
// codex 两轮([1338]④ 复审):逐出**只打墓碑**(done)。R1:逐最老会把在跑 child 的 spawnedAt 挤掉,
|
|
353
|
+
// 下个 tick lazy-mint 重起表=elapsedMs 归零。R2(更重):全活时垫底逐活儿,重生条目 tenantScope 落
|
|
354
|
+
// "default"、owner/parent 全失——**跨租户错归因**(scoped 流按 "default" 键还能收到别家 child 的终态
|
|
355
|
+
// 通知残料)。活溯源绝不逐出:无墓碑=不逐,活基数由 registry 真并发界定(每条 Meta 极小);病态膨胀
|
|
356
|
+
// 打一次 warn 供观测。墓碑仍受 MAX 界(terminal 后条目=墓碑,自然轮换)。
|
|
197
357
|
let victim;
|
|
198
358
|
for (const [k, v] of meta) {
|
|
199
359
|
if (v.done) {
|
|
@@ -210,12 +370,28 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
210
370
|
}
|
|
211
371
|
}
|
|
212
372
|
};
|
|
373
|
+
// [1338]③ 换算臂:core spawn emit 现把 hostSessionId 装进 parentTaskId(会话 id,非行 id)→ 子行
|
|
374
|
+
// parentId 指向不存在的行=孤儿伪影(值域修在 core)。server 兜:parentTaskId 不是现存行 id、却恰是
|
|
375
|
+
// 某 TOP-LEVEL run 行的 sessionId 时,换算成该 run 行 id。guard 式——core 修后 parentTaskId 直接命中
|
|
376
|
+
// 行 id,此臂自然失活;无命中(run 行未起/已离场)保持原值,孤儿顶格渲染,不误挂。
|
|
377
|
+
// codex R3(M1):首次**成功**解析即冻结进 Meta.resolvedParentId——逐拍重解会把跨 run 存活的长寿
|
|
378
|
+
// child 重挂到同会话后起的 run 行(launch 溯源被静默改写);孤儿(未成功)下拍再试。
|
|
213
379
|
const resolveParentId = (parentInput, domain, childScope) => {
|
|
380
|
+
// codex R5:**每一条**解析分支都同租户校验(r.scope === childScope)——submit 收任意 sessionId,
|
|
381
|
+
// 碰撞可让 A 家的孙冻结到 B 家的行(fleet-wide 视图伪嵌套)。跨租户一律按未命中:孤儿顶格,fail-closed。
|
|
382
|
+
// codex(1.350 四轮):解析带**域标**——session 域链接(parentSessionLink)跳过行 id 直查与 uuid 别名
|
|
383
|
+
// 两分支(会话 id 由调用方任报,与既有 run 行 id 撞值时直查会把孩子冻到无关 run 上),只走 sessionId
|
|
384
|
+
// 匹配译臂;task 域三分支全走。
|
|
214
385
|
const rows = bus.snapshot().tasks;
|
|
215
386
|
if (domain === "task") {
|
|
216
387
|
if (rows.some((r) => r.id === parentInput && r.scope === childScope))
|
|
217
388
|
return { id: parentInput, resolved: true };
|
|
218
389
|
}
|
|
390
|
+
// codex R4(M-B)+ PAIR-REVIEW F-1:嵌套 bg 孙的父链接=父 **agent 的 uuid**——core 1.350+ 真实帧形里
|
|
391
|
+
// 该值落 **parentSessionId**(session 域;[1344]② 钳掉了洗域 parentTaskId),所以别名逆查必须对
|
|
392
|
+
// **两个域**开放(此前只挂 task 域=1.351 下三臂死代码,PAIR-REVIEW F-1 CONFIRMED)。scope-safe:
|
|
393
|
+
// 别名命中恒要求同租户(R5 的禁令针对**行 id 直查**分支——那才是任报值撞行的面;别名表是本
|
|
394
|
+
// publisher 自记的 spawn 事实,加租户校验后无跨户面)。
|
|
219
395
|
for (const [aStar, pm] of meta) {
|
|
220
396
|
if (pm.aliasUuid === parentInput && pm.tenantScope === childScope) {
|
|
221
397
|
if (rows.some((r) => r.id === aStar && r.scope === childScope))
|
|
@@ -224,14 +400,20 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
224
400
|
}
|
|
225
401
|
let match;
|
|
226
402
|
for (const r of rows) {
|
|
403
|
+
// codex R7(high):会话译只认**真 run 行**——排除一切本 publisher 记账的 a* child 行(meta 键)。
|
|
404
|
+
// session-scoped a* 孤儿行同样带 sessionId、R6 后无 parentId、同 scope,不排除则孤儿 tick 会把
|
|
405
|
+
// **自己**(或同门孤儿)选成父并冻结=自环树,晚到的真 run 行永远接不上。
|
|
227
406
|
if (r.sessionId === parentInput && r.parentId === undefined && r.scope === childScope && !meta.has(r.id))
|
|
228
|
-
match = r.id;
|
|
407
|
+
match = r.id; // 后写覆盖=取最近的同租户 run 行
|
|
229
408
|
}
|
|
230
409
|
return match !== undefined ? { id: match, resolved: true } : { id: parentInput, resolved: false };
|
|
231
410
|
};
|
|
232
411
|
const rowTags = (m) => {
|
|
412
|
+
// codex R6:未解析成功=**不发 parentId**(原值只留 Meta 供下拍重试)。发原值就是 [1338]③ 伪影本身
|
|
413
|
+
// (悬空 parentId 指向不存在的行),且 fleet-wide 视图上一个撞值的外租户行 id 会在渲染端伪嵌套——
|
|
414
|
+
// 行早发孤儿顶格、解析成功后 MERGE 升级补 parentId,两边都诚实。
|
|
233
415
|
let parentId;
|
|
234
|
-
const parentInput = m.parentTaskId ?? m.parentSessionLink;
|
|
416
|
+
const parentInput = m.parentTaskId ?? m.parentSessionLink; // 1.350 fallback 形:会话域链接同走解析臂(带域标)
|
|
235
417
|
if (parentInput) {
|
|
236
418
|
if (m.resolvedParentId !== undefined) {
|
|
237
419
|
parentId = m.resolvedParentId;
|
|
@@ -248,8 +430,8 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
248
430
|
...(m.tenantScope ? { scope: m.tenantScope } : {}),
|
|
249
431
|
...(m.hostSessionId ? { sessionId: m.hostSessionId } : {}),
|
|
250
432
|
...(parentId !== undefined ? { parentId } : {}),
|
|
251
|
-
...(m.workflowRunId !== undefined ? { workflowRunId: m.workflowRunId } : {}),
|
|
252
|
-
...(m.parentToolCallId !== undefined ? { parentToolCallId: m.parentToolCallId } : {}),
|
|
433
|
+
...(m.workflowRunId !== undefined ? { workflowRunId: m.workflowRunId } : {}), // [1440] 附注位透传
|
|
434
|
+
...(m.parentToolCallId !== undefined ? { parentToolCallId: m.parentToolCallId } : {}), // P1-2(core 1.432)E2 原值域
|
|
253
435
|
...(m.spawnedAt !== undefined ? { startedAt: m.spawnedAt, elapsedMs: Date.now() - m.spawnedAt } : {}),
|
|
254
436
|
};
|
|
255
437
|
};
|
|
@@ -262,25 +444,51 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
262
444
|
return u.tokens;
|
|
263
445
|
return undefined;
|
|
264
446
|
};
|
|
447
|
+
// design/158 A13: the three event-kind branches below are named local functions — same closure scope/capture
|
|
448
|
+
// as when they were inline `if (e.kind === "...") { ... }` blocks in the returned dispatcher (behavior
|
|
449
|
+
// identical), alongside the already-named helpers above (dlog/remember/resolveParentId/rowTags/sumUsage).
|
|
265
450
|
const handleSpawn = (e) => {
|
|
451
|
+
// PAIR-REVIEW F-3:revive spawn(spawn-after-tombstone)缺父字段时**继承墓碑 Meta 的父链**——
|
|
452
|
+
// 上一周期已解析冻结的 parentTaskId/resolvedParentId 不因重建丢失(core 1.351 revive spawn 不回放
|
|
453
|
+
// 父链;1.352 回放件到货后此臂自然让位,双保险)。只在新帧零父字段时继承,新值恒赢。
|
|
266
454
|
const tomb = meta.get(e.taskId);
|
|
267
455
|
const inheritParent = !e.parentTaskId && !e.parentSessionId && tomb?.done === true;
|
|
268
456
|
const m = {
|
|
457
|
+
// codex 两轮(1.350 适配):core 1.350 起 fallback 形不再发洗域 parentTaskId([1364]②),补偿链接改走
|
|
458
|
+
// 声明字段 parentSessionId(/v1/tasks/stream 主车道 spec.taskId 未设=恰此形)。**两域分存**——
|
|
459
|
+
// parentTaskId=真任务域(可直出 wire),parentSessionLink=会话域(仅作行嵌套解析输入,绝不冒充
|
|
460
|
+
// 任务 id 出 bg_notification)。
|
|
269
461
|
...(e.parentTaskId ? { parentTaskId: e.parentTaskId } : {}),
|
|
270
462
|
...(!e.parentTaskId && e.parentSessionId ? { parentSessionLink: e.parentSessionId } : {}),
|
|
271
463
|
...(inheritParent && tomb?.parentTaskId !== undefined ? { parentTaskId: tomb.parentTaskId } : {}),
|
|
272
464
|
...(inheritParent && tomb?.parentSessionLink !== undefined ? { parentSessionLink: tomb.parentSessionLink } : {}),
|
|
273
465
|
...(inheritParent && tomb?.resolvedParentId !== undefined ? { resolvedParentId: tomb.resolvedParentId } : {}),
|
|
466
|
+
// session-scoped: registry owner IS the host sessionId (design/129 owner key); fork spawns also carry
|
|
467
|
+
// the child's uuid sessionId — that is the a*↔uuid cross-system anchor, NOT the host session, so it is not used here.
|
|
468
|
+
// [1522] LOW4:session-scoped 臂同样 root-first(另两臂 1.250 已升)——嵌套 session-scoped 形
|
|
469
|
+
// 的 owner=中间层子会话 uuid,标它=over-filter;显式 root 到货即锚 root(近死码但一处改齐)。
|
|
274
470
|
...(e.sessionScoped && e.owner ? { hostSessionId: e.rootSessionId ?? e.owner } : {}),
|
|
471
|
+
// 🔴 scope DOMAIN mapping: core's registry scope is `ctx.principal ?? deployment scope` —
|
|
472
|
+
// UNDEFINED on a single-user no-principal deployment — while the service fleet domain keys the
|
|
473
|
+
// no-principal caller as "default" (`gatedPrincipal ?? "default"`, streamFleet's callerScope). Without
|
|
474
|
+
// this map the row/notification carried NO scope and the scoped stream dropped EVERYTHING (fail-closed
|
|
475
|
+
// — the "terminal/bg_notification 零帧" repro). Same principal string in both domains when
|
|
476
|
+
// a principal exists, so the map is exact.
|
|
275
477
|
tenantScope: e.scope ?? "default",
|
|
276
478
|
sessionScoped: e.sessionScoped,
|
|
479
|
+
// core 1.367 δ:真 launch 锚(revive=wake 时刻)优先;旧 core 帧回落收帧时刻([1338]④ 原形)
|
|
277
480
|
spawnedAt: e.startedAt ?? Date.now(),
|
|
278
481
|
...(e.rootSessionId ? { rootSessionId: e.rootSessionId } : {}),
|
|
279
|
-
...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
|
|
280
|
-
...(e.sessionId ? { aliasUuid: e.sessionId } : {}),
|
|
281
|
-
...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}),
|
|
482
|
+
...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}), // P1-2(core 1.432,12 发射点全带)
|
|
483
|
+
...(e.sessionId ? { aliasUuid: e.sessionId } : {}), // codex R4(M-B):uuid↔a* 别名(fork spawn 带 forkedId)
|
|
484
|
+
...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}), // [1440] wa* 归属附注
|
|
485
|
+
// codex 1.240-R1/R2(H 行半场):wa\* 帧 sessionScoped:false 无 host owner → 行无 sessionId=
|
|
486
|
+
// 「absent=同 principal 全会话可见」(bg 兼容语义,对 wa\* 是泄露面)。归属源两级:①**信任源**
|
|
487
|
+
// core 帧的 parentSessionId(发起会话,1.350 声明字段——R2:无 runStore 的瞬态 sync 部署没有宿主
|
|
488
|
+
// fleet 行,行查 fallback 必空);②宿主行 sessionId 查表(同租户)兜底。
|
|
282
489
|
...(e.workflowRunId && !(e.sessionScoped && e.owner)
|
|
283
490
|
? (() => {
|
|
491
|
+
// core 1.367 δ:显式 root 锚(spawnAttribution 把 root 传进每个 workflow-agent)——信任源第一
|
|
284
492
|
if (e.rootSessionId)
|
|
285
493
|
return { hostSessionId: e.rootSessionId };
|
|
286
494
|
if (e.parentSessionId)
|
|
@@ -289,6 +497,33 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
289
497
|
return host?.sessionId ? { hostSessionId: host.sessionId } : {};
|
|
290
498
|
})()
|
|
291
499
|
: {}),
|
|
500
|
+
// [1493] cross-session isolation: a NON-session-scoped, non-wa* bg child (owner = the run taskId — the
|
|
501
|
+
// norm when backgroundScope!="session", i.e. every multi-tenant deployment, and any local path where the
|
|
502
|
+
// session isn't adopted at spawn) STILL carries a host session on core's declared parentSessionId
|
|
503
|
+
// (subagent.js registerBackgroundAgent). Without promoting it to hostSessionId the row/notification is
|
|
504
|
+
// session-UNTAGGED → streamFleet's `?session=` filter fails OPEN → the completion is broadcast (and
|
|
505
|
+
// model-injected) into every same-principal shell (clay's dual-shell repro). Promote it so the filter
|
|
506
|
+
// narrows precisely. (Session-scoped children already tag via the `owner` arm above; wa* via its own arm
|
|
507
|
+
// just above — both are excluded by this condition, so no double-write.) The terminal event does NOT
|
|
508
|
+
// repeat parentSessionId (core emits it on spawn only), so this MUST be captured into Meta here at spawn.
|
|
509
|
+
//
|
|
510
|
+
// codex R1 (nested-agent mis-tag): parentSessionId is core's `ctx.sessionId`, which for a NESTED bg child
|
|
511
|
+
// (spawned BY a subagent) is the PARENT AGENT's child-session uuid, NOT the shell's root session. Tagging
|
|
512
|
+
// that uuid as hostSessionId would make the outer host shell FAIL the ownerSessionId check (row +
|
|
513
|
+
// completion suppressed, durable ack fence keyed wrong). So resolve through the alias table (same reverse
|
|
514
|
+
// lookup resolveParentId uses): if some agent Meta's aliasUuid === parentSessionId, this is nested —
|
|
515
|
+
// inherit THAT agent's already-resolved hostSessionId (the root shell session), or stay UNTAGGED when the
|
|
516
|
+
// parent itself is untagged. Only a TOP-LEVEL bg child (parentSessionId is the shell root, aliased by no
|
|
517
|
+
// agent) uses parentSessionId directly. Tenant-scoped like every other alias/parent resolution (R5).
|
|
518
|
+
// fable5 R1 (honest residual): a nested child whose parent Meta is ABSENT (restart lazy-mint edge — live
|
|
519
|
+
// Meta is never evicted, so within one process the parent always exists at spawn time) is
|
|
520
|
+
// INDISTINGUISHABLE from top-level and gets tagged with the given uuid. That is still SAFE: a
|
|
521
|
+
// child-session uuid is never any shell's own session, so no scoped subscriber matches it — the failure
|
|
522
|
+
// direction is over-filtering (the true owner misses live delivery; durable inbox/stream-open drain
|
|
523
|
+
// compensate), never cross-delivery. Root fix = core carrying an explicit root-host-session (or a
|
|
524
|
+
// top-level/nested discriminator) on the spawn event — asked as a core seam follow-up ([1493]).
|
|
525
|
+
// core 1.367 δ:[1493] fable5-R1 注里请的 root fix **到货**——spawn 帧显式带 rootSessionId
|
|
526
|
+
// (固定点语义,嵌套孙代恒=root shell 会话),信任源直用;alias 反查臂降为旧 core 帧回落。
|
|
292
527
|
...(!(e.sessionScoped && e.owner) && !e.workflowRunId && (e.rootSessionId ?? e.parentSessionId)
|
|
293
528
|
? (() => {
|
|
294
529
|
if (e.rootSessionId)
|
|
@@ -296,19 +531,34 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
296
531
|
const childScope = e.scope ?? "default";
|
|
297
532
|
for (const pm of meta.values()) {
|
|
298
533
|
if (pm.aliasUuid === e.parentSessionId && (pm.tenantScope ?? "default") === childScope) {
|
|
299
|
-
return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {};
|
|
534
|
+
return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {}; // nested: inherit root (or stay untagged → Part B)
|
|
300
535
|
}
|
|
301
536
|
}
|
|
302
|
-
return { hostSessionId: e.parentSessionId };
|
|
537
|
+
return { hostSessionId: e.parentSessionId }; // top-level: parentSessionId IS the shell root session
|
|
303
538
|
})()
|
|
304
539
|
: {}),
|
|
305
540
|
};
|
|
306
541
|
remember(e.taskId, m);
|
|
542
|
+
// [1364]③:spawn 帧 1.349+ 也带 agentType(类型名)/name——行 name 位保 description(display 标签,
|
|
543
|
+
// 历史语义),TYPE 列自 spawn 即亮(此前要等首 tick 自愈)。
|
|
544
|
+
// [1827]①(cli):spawn 行也透传 transcriptId(委派 prompt 的映射,详情页运行中即可取件)。
|
|
545
|
+
// 现状 core 只在 terminal 事件带此键(三发射点亲核)⇒ 本透传对旧 core 惰性;core 停 spawn/tick
|
|
546
|
+
// 源头补上即通,tick 臂(下方 :78x)早已同姿。server 不自行以 sessionId 推导——fork lane 的
|
|
547
|
+
// forkTranscriptId 与 sessionId 的等价关系归 core 所有,不在消费端烙死。
|
|
307
548
|
bus.publishTask({ id: e.taskId, name: redactSecrets(e.description ?? e.name ?? e.taskId), ...(e.agentType ? { agentType: redactSecrets(e.agentType) } : {}), ...rowTags(m), status: "running", tokens: 0, ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
|
|
308
549
|
dlog("bg_child_event", { kind: "spawn", taskId: e.taskId, sessionScoped: e.sessionScoped, scope: m.tenantScope, hostSessionId: m.hostSessionId ?? null, parentTaskId: m.parentTaskId ?? null });
|
|
309
550
|
};
|
|
310
551
|
const handleTick = (e, m) => {
|
|
552
|
+
// dedup the per-leg uuid-keyed twin ONCE: the leg's onForwardEvent keys the same child's rows by
|
|
553
|
+
// `${runId} ${uuid}` and on the /v1/runs path runId === the host canonical taskId (spec.taskId is the
|
|
554
|
+
// durable run id). The tick that carries the child's OWN frame has progressParentTaskId === the host
|
|
555
|
+
// taskId (a NESTED grandchild carries the child's uuid instead — never suppressed here). A miss is a
|
|
556
|
+
// no-op remove (best-effort; worst case = a transient duplicate row until the leg settles, old behavior).
|
|
311
557
|
if (!m.suppressedTwin && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
|
|
558
|
+
// The per-leg childId is `${run.runId} ${uuid}` and runId ≠ the core hostTaskId on the
|
|
559
|
+
// sync-stream/resume paths (durableTaskId vs canonical sessionId), so a composite-key guess misses there.
|
|
560
|
+
// Scan-by-suffix instead: the uuid tail uniquely names the child across every leg's runId prefix. One-shot
|
|
561
|
+
// (suppressedTwin) so the O(rows) scan runs once per child.
|
|
312
562
|
const tail = ` ${e.progressTaskId}`;
|
|
313
563
|
for (const row of bus.snapshot().tasks) {
|
|
314
564
|
if (row.id.endsWith(tail))
|
|
@@ -316,6 +566,13 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
316
566
|
}
|
|
317
567
|
m.suppressedTwin = true;
|
|
318
568
|
}
|
|
569
|
+
// codex R8:普通(非 fork)bg producer 的 spawn 不带 sessionId,uuid 别名要等 terminal 才现——嵌套孙
|
|
570
|
+
// 在父运行期解析全 miss。但 child 本人的 tick 恒带 progressTaskId=其 uuid(与双生抑制同一判别形),
|
|
571
|
+
// 首 tick 即学别名;孙侧 retry-until-success 语义随后一拍自然接上(spawn 路径已带 sessionId 的 fork 形
|
|
572
|
+
// 不受影响,??= 只补缺)。
|
|
573
|
+
// codex R9:别名习得**即回填**——快孙可能已无后续帧(spawn+tick+terminal 全在父首 tick 前),等孙自己
|
|
574
|
+
// retry 就永远孤儿。习得此刻主动扫在场未解析孤儿,替它们把行升级(rowTags 内解析+冻结)。彻底闭窗
|
|
575
|
+
// (孙整个生命周期都在别名前走完的瞬态孤儿)在 core:普通形 spawn emit 补 sessionId(fork 形已带)。
|
|
319
576
|
if (m.aliasUuid === undefined && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
|
|
320
577
|
m.aliasUuid = e.progressTaskId;
|
|
321
578
|
for (const [cid, cm] of meta) {
|
|
@@ -326,15 +583,30 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
326
583
|
}
|
|
327
584
|
const tokens = sumUsage(e.usage);
|
|
328
585
|
const name = e.name ? redactSecrets(e.name) : undefined;
|
|
586
|
+
// [1364]③ K-7 换位:TYPE 列取 tick 帧的行级 `agentType`(core 1.350 定谳:`name` 位=display 标签
|
|
587
|
+
// ——description 充是历史语义非 bug,类型名在 agentType 位)。缺省回落 name(旧 core 兼容,原行为)。
|
|
329
588
|
const agentType = e.agentType ? redactSecrets(e.agentType) : name;
|
|
589
|
+
// The sink tick carries core's currentAction (its only attachment point today) —
|
|
590
|
+
// UNTRUSTED (tool argument head) → redact, same discipline as name. Additive; absent until a tool runs.
|
|
330
591
|
const currentAction = e.currentAction ? redactSecrets(e.currentAction) : undefined;
|
|
592
|
+
// [1827]②/core 1.429:结构化同源体。字段 PICKED(不整对象 spread——future core 键不得裸骑);
|
|
593
|
+
// toolName verbatim,target 与 currentAction 同边界(redact + 300 bound,brainStatus.detail 同惯例)。
|
|
331
594
|
const currentTool = e.currentTool
|
|
332
595
|
? { toolName: e.currentTool.toolName, ...(e.currentTool.target !== undefined ? { target: redactSecrets(e.currentTool.target).slice(0, 300) } : {}) }
|
|
333
596
|
: undefined;
|
|
597
|
+
// cli [1748]:两个 additive 位。`toolUses` 是**累计值**(与 turn_end 的每轮增量相反)⇒ 直接上行不累加;
|
|
598
|
+
// 缺席时**不发这个键**(消费方不得把缺席当 0)。`transcriptId` 是委派 prompt 的**映射** ——
|
|
599
|
+
// prompt 本身不在 `BackgroundChildEvent` 上,server 收不到就不造。
|
|
334
600
|
bus.publishTask({ id: e.taskId, ...rowTags(m), status: "running", ...(tokens !== undefined ? { tokens } : {}), ...(name ? { name } : {}), ...(agentType ? { agentType } : {}), ...(currentAction ? { currentAction } : {}), ...(currentTool ? { currentTool } : {}), ...(e.usage?.toolUses !== undefined ? { toolUses: e.usage.toolUses } : {}), ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
|
|
335
601
|
};
|
|
336
602
|
const handleTerminal = (e, m) => {
|
|
603
|
+
// terminal: flip the row so subscribers SEE the terminal frame, then leave the fleet — and push the
|
|
604
|
+
// contract bg_notification on the always-open lane (缺口②: idle delivery is immediate; the durable
|
|
605
|
+
// inbox park stays as the offline/replay belt, shell dedups by (taskId,status)).
|
|
337
606
|
const status = e.status === "completed" ? "completed" : e.status === "killed" ? "killed" : "failed";
|
|
607
|
+
// [1839]①/(a) 案:终态**行帧**同带残局键——此前只有 {id,status},看行卡(不订通知帧)的 idle 观察者
|
|
608
|
+
// 拿不到终局。与下方 bg_notification 同源同姿势:键逐挑不 spread、editedFiles path 过 redactSecrets
|
|
609
|
+
// + 100 界、缺席不铸。(recentSteps 不进行帧——通知卡语义,行卡不渲染步骤列表。)
|
|
338
610
|
bus.publishTask({
|
|
339
611
|
id: e.taskId, ...rowTags(m), status,
|
|
340
612
|
...(e.stoppedBy ? { stoppedBy: e.stoppedBy } : {}),
|
|
@@ -355,6 +627,9 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
355
627
|
: {}),
|
|
356
628
|
});
|
|
357
629
|
bus.removeTask(e.taskId);
|
|
630
|
+
// codex 1.240-R1(M2):1.356 的回调序=bceTick 先于 host forward——tick 处的双生抑制扫在 uuid 双生
|
|
631
|
+
// 行发布**之前**,one-shot 空扫后置旗,双生行永存。terminal 补扫一次(aliasUuid=tick 学到的 child
|
|
632
|
+
// uuid),把 run-leg 的复合键行清场。
|
|
358
633
|
if (m.aliasUuid) {
|
|
359
634
|
const tail = ` ${m.aliasUuid}`;
|
|
360
635
|
for (const row of bus.snapshot().tasks) {
|
|
@@ -362,19 +637,32 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
362
637
|
bus.removeTask(row.id);
|
|
363
638
|
}
|
|
364
639
|
}
|
|
640
|
+
// codex 1.240-R1(H1):wa\*(workflowRunId 在)不走 bg_notification 契约——该帧族=后台任务完成通知
|
|
641
|
+
// (壳注入模型),workflow 的完成通知已有 workflow_complete 专链;且 1.356 wa\* 帧 sessionScoped:false
|
|
642
|
+
// 无 host owner → 通知无 ownerSessionId=同租户**全会话**可见(streamFleet 的 absent-放行是 bg 兼容位,
|
|
643
|
+
// 不是 wa\* 的授权)。per-agent 完成本就不该打断模型(CC 亦无此形)。
|
|
365
644
|
if (m.workflowRunId !== undefined) {
|
|
366
|
-
m.done = true;
|
|
645
|
+
m.done = true; // codex 1.240-R2(M):早退分支必须先落墓碑——迟到/重放 tick 不得复活已离场的 wa* 行
|
|
367
646
|
dlog("bg_child_event", { kind: "terminal-wa-no-notification", taskId: e.taskId, workflowRunId: m.workflowRunId });
|
|
368
647
|
return;
|
|
369
648
|
}
|
|
370
649
|
bus.publishBgNotification({
|
|
371
650
|
taskId: e.taskId,
|
|
372
651
|
...(e.sessionId ? { sessionId: e.sessionId } : {}),
|
|
652
|
+
// [1392]①(PAIR-REVIEW F-1@cli 的 wire 前置):终帧 seq(core 1.352 BackgroundChildEvent.terminal 补位,
|
|
653
|
+
// tolerate-absent——旧 core 无此位=不发,cli 键折 seq 的修依赖它区分 revive 周期)。
|
|
373
654
|
...(typeof e.seq === "number" ? { seq: e.seq } : {}),
|
|
374
655
|
status: e.status ?? "failed",
|
|
375
656
|
...(e.summary ? { summary: redactSecrets(e.summary) } : {}),
|
|
376
657
|
scope: (m.sessionScoped || e.sessionScoped) ? "session" : "task",
|
|
658
|
+
// codex(1.350 二轮):wire 的 parentTaskId 位只出真任务域;fallback 形出解析成功的 run 行 id
|
|
659
|
+
// (=durable run id,消费者拿它绑父行),解析未成=省略,绝不让会话 id 冒充任务 id 出 wire。
|
|
377
660
|
...(m.parentTaskId ? { parentTaskId: m.parentTaskId } : m.resolvedParentId ? { parentTaskId: m.resolvedParentId } : {}),
|
|
661
|
+
// The residual fields must ride THIS lane too (the "kill across turns" main line renders
|
|
662
|
+
// off it). Same posture as project.ts/inbox; fields picked, arrays defensively bounded.
|
|
663
|
+
// P1-3(core 1.452,[1925] 一轮批):completionId=子代完成的幂等锚,消费端(cli)按它对同一完成的
|
|
664
|
+
// 多路通知(bg_notification/task_notification/inbox 重放)去重。verbatim 透传,仅通知帧带
|
|
665
|
+
// (行帧不带——行的身份是 taskId,幂等锚是通知语义)。
|
|
378
666
|
...(e.completionId ? { completionId: e.completionId } : {}),
|
|
379
667
|
...(e.stoppedBy ? { stoppedBy: e.stoppedBy } : {}),
|
|
380
668
|
...(e.resumable !== undefined ? { resumable: e.resumable } : {}),
|
|
@@ -382,6 +670,7 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
382
670
|
? { recentSteps: e.recentSteps.slice(0, 10).map((s) => ({ tool: s.tool, target: redactSecrets(s.target), outcome: redactSecrets(s.outcome) })) }
|
|
383
671
|
: {}),
|
|
384
672
|
...(e.editedFiles !== undefined ? { editedFiles: e.editedFiles.slice(0, 100).map((f) => ({ path: redactSecrets(f.path), edits: f.edits })) } : {}),
|
|
673
|
+
// [1543]§二 LOW:usage/transcriptId 补齐(fields picked——usage 六数值键逐一挑,不整对象 spread)。
|
|
385
674
|
...(e.usage
|
|
386
675
|
? {
|
|
387
676
|
usage: {
|
|
@@ -395,13 +684,14 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
395
684
|
}
|
|
396
685
|
: {}),
|
|
397
686
|
...(e.transcriptId ? { transcriptId: e.transcriptId } : {}),
|
|
398
|
-
...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
|
|
687
|
+
...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}), // P1-2(core 1.432)——通知帧同带,cli「全部生命周期事件在场」
|
|
399
688
|
...(m.tenantScope ? { ownerScope: m.tenantScope } : {}),
|
|
400
689
|
...(m.hostSessionId ? { ownerSessionId: m.hostSessionId } : {}),
|
|
401
690
|
...(m.rootSessionId ? { rootSessionId: m.rootSessionId } : {}),
|
|
402
691
|
});
|
|
692
|
+
// One info line per terminal so the emit-vs-filter bisect is a log-grep, not a rerun.
|
|
403
693
|
dlog("bg_child_event", { kind: "terminal", taskId: e.taskId, status, scope: m.tenantScope ?? null, hostSessionId: m.hostSessionId ?? null, childSessionId: e.sessionId ?? null, bgNotificationPublished: true });
|
|
404
|
-
m.done = true;
|
|
694
|
+
m.done = true; // tombstone (kept in the bounded map) — see Meta.done
|
|
405
695
|
m.suppressedTwin = true;
|
|
406
696
|
};
|
|
407
697
|
return (e) => {
|
|
@@ -409,18 +699,20 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
409
699
|
handleSpawn(e);
|
|
410
700
|
return;
|
|
411
701
|
}
|
|
412
|
-
const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() };
|
|
702
|
+
const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() }; // scope domain map holds on the lazily-minted path too([1338]④ 首见起表)
|
|
413
703
|
if (!meta.has(e.taskId)) {
|
|
414
|
-
remember(e.taskId, m);
|
|
704
|
+
remember(e.taskId, m); // tick/terminal without a seen spawn (restart/eviction edge) — row minted lazily
|
|
415
705
|
dlog("bg_child_event", { kind: `${e.kind}-lazy-mint`, taskId: e.taskId, sessionScoped: e.sessionScoped });
|
|
416
706
|
}
|
|
417
707
|
else {
|
|
418
|
-
remember(e.taskId, m);
|
|
708
|
+
remember(e.taskId, m); // codex:活儿每拍刷新近度——LRU 兜底永远先挤最久没动静的,不挤在跑的
|
|
419
709
|
}
|
|
420
710
|
if (m.done) {
|
|
711
|
+
// tombstone: this child already settled — a late tick must not resurrect a running row (settle-freeze 同族).
|
|
421
712
|
dlog("bg_child_event", { kind: `${e.kind}-after-terminal-ignored`, taskId: e.taskId });
|
|
422
713
|
return;
|
|
423
714
|
}
|
|
715
|
+
// P1-2(core 1.432):lazy-mint/spawn 前旧 core 帧路径——parentToolCallId「出生就在场」,首见即补
|
|
424
716
|
if (m.parentToolCallId === undefined && e.parentToolCallId)
|
|
425
717
|
m.parentToolCallId = e.parentToolCallId;
|
|
426
718
|
if (e.kind === "tick") {
|
|
@@ -430,15 +722,26 @@ export function fleetBackgroundChildPublisher(bus, log) {
|
|
|
430
722
|
handleTerminal(e, m);
|
|
431
723
|
};
|
|
432
724
|
}
|
|
725
|
+
/** BC-1 (clay-decided 2026-06-27): a top-level run's fleet-row `name` = a SHORT, single-line **objective preview**
|
|
726
|
+
* (the readable "what is this task" label) — NOT the full objective dumped in, and NOT duplicated into `description`.
|
|
727
|
+
* `description` is left to the publisher's LIVE-ACTIVITY update (`onEvent` tool_start → the current tool), so the row
|
|
728
|
+
* shows `name`=objective + `description`=current activity (two DISTINCT things, killing the earlier "objective shown
|
|
729
|
+
* twice" dup). Whitespace-collapsed + capped ≤48. (A subagent CHILD row's name = its agent-type — BC-2.)
|
|
730
|
+
* SECRET-SAFE: redact secret shapes (redactSecrets) BEFORE truncating — a secret in the objective must not leak in
|
|
731
|
+
* the row name. The durable objective is already redacted; the name preview was asymmetric (raw) until this. */
|
|
433
732
|
export function fleetRunLabels(objective) {
|
|
434
733
|
const oneLine = redactSecrets((objective ?? "").replace(/\s+/g, " ")).trim();
|
|
435
734
|
if (!oneLine)
|
|
436
735
|
return { name: "task" };
|
|
736
|
+
// [1414]④:控制帧形 objective(注入 turn 的 `<task-notification>…` 等 XML 头)不得当行名——用户底部
|
|
737
|
+
// 会看到「<task-notifica…」尖括号伪影。以 `<` 开头且形如 XML tag 的 objective 给中性名;真实用户
|
|
738
|
+
// objective 以 `<` 开头的形(粘贴 HTML 片段)极罕且中性名无害。
|
|
437
739
|
if (/^<[a-z][a-z0-9_-]*[\s>/]/i.test(oneLine))
|
|
438
740
|
return { name: "(notification turn)" };
|
|
439
741
|
const name = oneLine.length > 48 ? `${oneLine.slice(0, 47)}…` : oneLine;
|
|
440
742
|
return { name };
|
|
441
743
|
}
|
|
744
|
+
/** Map a service run status onto the neutral fleet vocabulary the shell renders. */
|
|
442
745
|
export function runStatusToFleet(status, opts) {
|
|
443
746
|
if (opts?.awaitingPlanApproval)
|
|
444
747
|
return "awaiting approval";
|
|
@@ -451,10 +754,13 @@ export function runStatusToFleet(status, opts) {
|
|
|
451
754
|
return "completed";
|
|
452
755
|
case "failed":
|
|
453
756
|
case "error":
|
|
454
|
-
case "blocked":
|
|
757
|
+
case "blocked": // report_blocked = a non-success TERMINAL outcome (agent gave up) → the "failed" bucket (the
|
|
758
|
+
// neutral fleet vocab has no "blocked"). CRUCIAL: this also lets onTerminal REMOVE the row — the removal set is
|
|
759
|
+
// {completed,failed,killed}, so without mapping "blocked" here it fell through to the "idle" default and a
|
|
760
|
+
// terminal blocked run LEAKED a permanent stale "idle" row on the fleet (caught by on-box e2e, 2026-06-28).
|
|
455
761
|
return "failed";
|
|
456
762
|
case "suspended":
|
|
457
|
-
return "waiting";
|
|
763
|
+
return "waiting"; // a durable suspend = parked, awaiting resume
|
|
458
764
|
case "needs_review":
|
|
459
765
|
return "awaiting approval";
|
|
460
766
|
case "killed":
|