@zhushanwen/subagent-core 0.2.0
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/README.md +114 -0
- package/dist/chunk-3VOERJPJ.js +22 -0
- package/dist/chunk-A4IVZWVX.js +31 -0
- package/dist/execution/engine/engines/zcode/constants.cjs +54 -0
- package/dist/execution/engine/engines/zcode/constants.d.cts +31 -0
- package/dist/execution/engine/engines/zcode/constants.d.ts +31 -0
- package/dist/execution/engine/engines/zcode/constants.js +22 -0
- package/dist/execution/engine/engines/zcode/reader.cjs +276 -0
- package/dist/execution/engine/engines/zcode/reader.d.cts +20 -0
- package/dist/execution/engine/engines/zcode/reader.d.ts +20 -0
- package/dist/execution/engine/engines/zcode/reader.js +239 -0
- package/dist/execution/engine/paths.cjs +55 -0
- package/dist/execution/engine/paths.d.cts +8 -0
- package/dist/execution/engine/paths.d.ts +8 -0
- package/dist/execution/engine/paths.js +26 -0
- package/dist/execution/relay-env.cjs +62 -0
- package/dist/execution/relay-env.d.cts +33 -0
- package/dist/execution/relay-env.d.ts +33 -0
- package/dist/execution/relay-env.js +20 -0
- package/dist/index.cjs +1852 -0
- package/dist/index.d.cts +1184 -0
- package/dist/index.d.ts +1184 -0
- package/dist/index.js +1810 -0
- package/dist/types-BxyAidGf.d.cts +875 -0
- package/dist/types-BxyAidGf.d.ts +875 -0
- package/package.json +99 -0
- package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +142 -0
- package/src/__tests__/append-system-prompt-assembly.test.ts +242 -0
- package/src/__tests__/builtin-workflows-structure.test.ts +180 -0
- package/src/__tests__/derive-closed-display-parity.test.ts +93 -0
- package/src/__tests__/fr4-get-state-handshake.test.ts +125 -0
- package/src/__tests__/fr8-orphan-recovery.test.ts +259 -0
- package/src/__tests__/m2-append-content-probe.test.ts +73 -0
- package/src/__tests__/manifest-store.test.ts +368 -0
- package/src/__tests__/record-store-cache.test.ts +335 -0
- package/src/__tests__/record-store-index.test.ts +560 -0
- package/src/__tests__/record-store-last-line.test.ts +129 -0
- package/src/__tests__/review-fix-loop-script.test.ts +288 -0
- package/src/__tests__/review-fix-loop-utils.test.ts +2377 -0
- package/src/__tests__/robustness-low-batch1.test.ts +286 -0
- package/src/__tests__/robustness-medium-batch1.test.ts +69 -0
- package/src/__tests__/robustness-medium-batch2.test.ts +65 -0
- package/src/__tests__/robustness-medium-batch3.test.ts +30 -0
- package/src/__tests__/robustness-medium-batch4.test.ts +358 -0
- package/src/__tests__/session-runner.test.ts +69 -0
- package/src/__tests__/smoke.test.ts +9 -0
- package/src/__tests__/stream-sink.test.ts +203 -0
- package/src/core/__tests__/host-services.test.ts +144 -0
- package/src/core/__tests__/logger.test.ts +78 -0
- package/src/core/__tests__/notify-ports.test.ts +104 -0
- package/src/core/host-services.ts +97 -0
- package/src/core/logger.ts +47 -0
- package/src/core/notify-ports.ts +126 -0
- package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +53 -0
- package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +1 -0
- package/src/execution/__tests__/agent-result-mapper.test.ts +150 -0
- package/src/execution/__tests__/alive-store.test.ts +147 -0
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +490 -0
- package/src/execution/__tests__/channel-registry-handshake.test.ts +242 -0
- package/src/execution/__tests__/chat-engine-routing.test.ts +610 -0
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +190 -0
- package/src/execution/__tests__/concurrency-pool.test.ts +250 -0
- package/src/execution/__tests__/config.test.ts +302 -0
- package/src/execution/__tests__/delivery-methods.test.ts +424 -0
- package/src/execution/__tests__/dialog-queue.test.ts +299 -0
- package/src/execution/__tests__/epipe-fallback.test.ts +241 -0
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +243 -0
- package/src/execution/__tests__/execute-nesting.test.ts +323 -0
- package/src/execution/__tests__/execute-options-mapper.test.ts +200 -0
- package/src/execution/__tests__/execution-record.test.ts +1394 -0
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +171 -0
- package/src/execution/__tests__/finalize-record.test.ts +367 -0
- package/src/execution/__tests__/finalized-marker.test.ts +104 -0
- package/src/execution/__tests__/format-schema-instruction.test.ts +169 -0
- package/src/execution/__tests__/gc-timer.test.ts +184 -0
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +254 -0
- package/src/execution/__tests__/helpers/mock-extension-api.ts +30 -0
- package/src/execution/__tests__/helpers/spawn-mock.ts +242 -0
- package/src/execution/__tests__/host-mode.test.ts +87 -0
- package/src/execution/__tests__/lifecycle-manager-lock.test.ts +211 -0
- package/src/execution/__tests__/lifecycle-manager.test.ts +383 -0
- package/src/execution/__tests__/lifecycle-predicates.test.ts +116 -0
- package/src/execution/__tests__/manifest-parentid.test.ts +117 -0
- package/src/execution/__tests__/model-resolver.test.ts +465 -0
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +287 -0
- package/src/execution/__tests__/nested-visibility.test.ts +325 -0
- package/src/execution/__tests__/output-collector.test.ts +358 -0
- package/src/execution/__tests__/path-encoding.test.ts +104 -0
- package/src/execution/__tests__/pi-invocation.test.ts +134 -0
- package/src/execution/__tests__/record-store.test.ts +1057 -0
- package/src/execution/__tests__/records-cwd-isolation.test.ts +91 -0
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +339 -0
- package/src/execution/__tests__/recursive-visibility-env.test.ts +273 -0
- package/src/execution/__tests__/relay-env.test.ts +42 -0
- package/src/execution/__tests__/resource-policy.test.ts +109 -0
- package/src/execution/__tests__/rpc-mode.test.ts +89 -0
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +267 -0
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +253 -0
- package/src/execution/__tests__/run-spawn-edges.test.ts +687 -0
- package/src/execution/__tests__/run-spawn-integration.test.ts +933 -0
- package/src/execution/__tests__/run-spawn-resume.test.ts +322 -0
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +196 -0
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +199 -0
- package/src/execution/__tests__/session-context-resolver.test.ts +167 -0
- package/src/execution/__tests__/session-file-gc.test.ts +293 -0
- package/src/execution/__tests__/session-reconstructor.test.ts +379 -0
- package/src/execution/__tests__/session-runner-epipe.test.ts +178 -0
- package/src/execution/__tests__/session-runner-schema-env.test.ts +350 -0
- package/src/execution/__tests__/spawn-args.test.ts +445 -0
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +189 -0
- package/src/execution/__tests__/spawn-event-adapter.test.ts +167 -0
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +207 -0
- package/src/execution/__tests__/spawned-children.test.ts +92 -0
- package/src/execution/__tests__/start-sync-model-guard.test.ts +150 -0
- package/src/execution/__tests__/stdin-writer.test.ts +462 -0
- package/src/execution/__tests__/stream-sink-retirement.test.ts +261 -0
- package/src/execution/__tests__/subagent-service-abort.test.ts +60 -0
- package/src/execution/__tests__/subagent-service-message-close.test.ts +629 -0
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +180 -0
- package/src/execution/__tests__/subagent-service.test.ts +788 -0
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +310 -0
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +612 -0
- package/src/execution/__tests__/temp-prompt.test.ts +53 -0
- package/src/execution/__tests__/timeout-integration.test.ts +615 -0
- package/src/execution/__tests__/tombstone-store.test.ts +73 -0
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +194 -0
- package/src/execution/__tests__/turn-limiter.test.ts +65 -0
- package/src/execution/__tests__/ui-channels.test.ts +187 -0
- package/src/execution/__tests__/ui-interaction-model.test.ts +67 -0
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +369 -0
- package/src/execution/__tests__/ui-request-handler.test.ts +204 -0
- package/src/execution/__tests__/ui-request-observability.test.ts +113 -0
- package/src/execution/__tests__/ui-request-queue.test.ts +133 -0
- package/src/execution/__tests__/worktree-manager.test.ts +633 -0
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +229 -0
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +181 -0
- package/src/execution/__tests__/worktree-registry.test.ts +199 -0
- package/src/execution/agent-registry.ts +199 -0
- package/src/execution/agent-result-mapper.ts +90 -0
- package/src/execution/alive-store.ts +119 -0
- package/src/execution/argv-mirror.ts +113 -0
- package/src/execution/best-effort.ts +38 -0
- package/src/execution/channel-registry-access.ts +144 -0
- package/src/execution/concurrency-pool.ts +116 -0
- package/src/execution/config.ts +165 -0
- package/src/execution/dialog-queue.ts +330 -0
- package/src/execution/engine/__tests__/common/data-dir.test.ts +78 -0
- package/src/execution/engine/__tests__/common/errors.test.ts +132 -0
- package/src/execution/engine/__tests__/common/event-journal.test.ts +177 -0
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +192 -0
- package/src/execution/engine/__tests__/common/nesting-guard.test.ts +81 -0
- package/src/execution/engine/__tests__/common/persona-router.test.ts +123 -0
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +154 -0
- package/src/execution/engine/__tests__/common/schema-emulation.test.ts +128 -0
- package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +28 -0
- package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +141 -0
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +109 -0
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +101 -0
- package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +77 -0
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +104 -0
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +201 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +76 -0
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +79 -0
- package/src/execution/engine/__tests__/engine-discovery.test.ts +87 -0
- package/src/execution/engine/__tests__/model-prompt.test.ts +197 -0
- package/src/execution/engine/__tests__/paths.test.ts +39 -0
- package/src/execution/engine/__tests__/registry.test.ts +120 -0
- package/src/execution/engine/__tests__/routing.test.ts +231 -0
- package/src/execution/engine/common/data-dir.ts +66 -0
- package/src/execution/engine/common/errors.ts +183 -0
- package/src/execution/engine/common/event-journal.ts +254 -0
- package/src/execution/engine/common/journal-replay.ts +62 -0
- package/src/execution/engine/common/kill-chain.ts +221 -0
- package/src/execution/engine/common/nesting-guard.ts +50 -0
- package/src/execution/engine/common/persona-router.ts +108 -0
- package/src/execution/engine/common/pool-manager.ts +226 -0
- package/src/execution/engine/common/schema-emulation.ts +189 -0
- package/src/execution/engine/common/session-view-projection.ts +51 -0
- package/src/execution/engine/engine-discovery.ts +65 -0
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +469 -0
- package/src/execution/engine/engines/pi/__tests__/reader.test.ts +155 -0
- package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +164 -0
- package/src/execution/engine/engines/pi/pi-engine.ts +415 -0
- package/src/execution/engine/engines/pi/reader.ts +48 -0
- package/src/execution/engine/engines/pi/registration.ts +35 -0
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +100 -0
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +39 -0
- package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +150 -0
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +246 -0
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +228 -0
- package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +210 -0
- package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +71 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +127 -0
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +580 -0
- package/src/execution/engine/engines/zcode/constants.ts +43 -0
- package/src/execution/engine/engines/zcode/golden-sample.ts +39 -0
- package/src/execution/engine/engines/zcode/launcher.ts +161 -0
- package/src/execution/engine/engines/zcode/parser.ts +436 -0
- package/src/execution/engine/engines/zcode/preparer.ts +363 -0
- package/src/execution/engine/engines/zcode/reader.ts +381 -0
- package/src/execution/engine/engines/zcode/registration.ts +37 -0
- package/src/execution/engine/engines/zcode/zcode-engine.ts +658 -0
- package/src/execution/engine/host-task-spec.ts +47 -0
- package/src/execution/engine/model-prompt.ts +158 -0
- package/src/execution/engine/paths.ts +42 -0
- package/src/execution/engine/port.ts +153 -0
- package/src/execution/engine/registry.ts +133 -0
- package/src/execution/engine/routing.ts +218 -0
- package/src/execution/engine/types.ts +309 -0
- package/src/execution/execute-options-mapper.ts +115 -0
- package/src/execution/execution-record.ts +984 -0
- package/src/execution/finalize-record.ts +254 -0
- package/src/execution/finalized-marker.ts +70 -0
- package/src/execution/get-state-handshake.ts +104 -0
- package/src/execution/host-mode.ts +56 -0
- package/src/execution/idle-gc.ts +47 -0
- package/src/execution/lifecycle-manager.ts +513 -0
- package/src/execution/lifecycle-predicates.ts +65 -0
- package/src/execution/manifest-store.ts +256 -0
- package/src/execution/model-config-service.ts +250 -0
- package/src/execution/model-resolver.ts +248 -0
- package/src/execution/notifier.ts +372 -0
- package/src/execution/notify-ledger.ts +580 -0
- package/src/execution/output-collector.ts +228 -0
- package/src/execution/path-encoding.ts +60 -0
- package/src/execution/pi-invocation.ts +120 -0
- package/src/execution/record-entry.ts +132 -0
- package/src/execution/record-store.ts +1265 -0
- package/src/execution/relay-env.ts +37 -0
- package/src/execution/session-context-resolver.ts +64 -0
- package/src/execution/session-file-gc.ts +120 -0
- package/src/execution/session-pending.ts +170 -0
- package/src/execution/session-reconstructor.ts +678 -0
- package/src/execution/session-runner.ts +1789 -0
- package/src/execution/sessions-index.ts +304 -0
- package/src/execution/spawn-event-adapter.ts +363 -0
- package/src/execution/stdin-writer.ts +198 -0
- package/src/execution/stream-sink.ts +126 -0
- package/src/execution/subagent-service.ts +2268 -0
- package/src/execution/subprocess-agent-runner.ts +317 -0
- package/src/execution/temp-prompt.ts +62 -0
- package/src/execution/tombstone-store.ts +72 -0
- package/src/execution/turn-limiter.ts +102 -0
- package/src/execution/types.ts +1023 -0
- package/src/execution/ui-channels.ts +216 -0
- package/src/execution/ui-interaction-model.ts +48 -0
- package/src/execution/ui-request-handler-factory.ts +243 -0
- package/src/execution/ui-request-observability.ts +81 -0
- package/src/execution/ui-request-queue.ts +184 -0
- package/src/execution/worktree-manager.ts +688 -0
- package/src/execution/worktree-registry.ts +279 -0
- package/src/index.ts +87 -0
- package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +349 -0
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +202 -0
- package/src/orchestration/__tests__/agent-call-stream.test.ts +152 -0
- package/src/orchestration/__tests__/args-validator.test.ts +143 -0
- package/src/orchestration/__tests__/config-loader.test.ts +503 -0
- package/src/orchestration/__tests__/error-recovery-handlers.test.ts +809 -0
- package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +404 -0
- package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +56 -0
- package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +166 -0
- package/src/orchestration/__tests__/execute-agent-call.test.ts +451 -0
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +600 -0
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +96 -0
- package/src/orchestration/__tests__/lifecycle.test.ts +659 -0
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +95 -0
- package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +183 -0
- package/src/orchestration/__tests__/script-lint.test.ts +831 -0
- package/src/orchestration/__tests__/skill-discovery.test.ts +210 -0
- package/src/orchestration/__tests__/test-mocks.ts +197 -0
- package/src/orchestration/__tests__/worker-exit-without-result.test.ts +368 -0
- package/src/orchestration/__tests__/worker-host.test.ts +120 -0
- package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +164 -0
- package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +563 -0
- package/src/orchestration/__tests__/worker-script-builder.test.ts +309 -0
- package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +129 -0
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +317 -0
- package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +110 -0
- package/src/orchestration/agent-opts-resolver.ts +174 -0
- package/src/orchestration/args-validator.ts +127 -0
- package/src/orchestration/config-loader.ts +316 -0
- package/src/orchestration/error-recovery.ts +1018 -0
- package/src/orchestration/execute-agent-call.ts +256 -0
- package/src/orchestration/launcher.ts +455 -0
- package/src/orchestration/lifecycle.ts +399 -0
- package/src/orchestration/models/__tests__/budget.test.ts +307 -0
- package/src/orchestration/models/agent-call.ts +83 -0
- package/src/orchestration/models/budget.ts +118 -0
- package/src/orchestration/models/ports.ts +164 -0
- package/src/orchestration/models/run-runtime.ts +104 -0
- package/src/orchestration/models/run-spec.ts +83 -0
- package/src/orchestration/models/run-state.ts +44 -0
- package/src/orchestration/models/trace.ts +183 -0
- package/src/orchestration/models/types.ts +301 -0
- package/src/orchestration/models/workflow-run.ts +254 -0
- package/src/orchestration/models/workflow-script-registry.ts +35 -0
- package/src/orchestration/models/workflow-script.ts +117 -0
- package/src/orchestration/script-lint.ts +766 -0
- package/src/orchestration/skill-discovery.ts +135 -0
- package/src/orchestration/worker-handle.ts +115 -0
- package/src/orchestration/worker-host.ts +98 -0
- package/src/orchestration/worker-script-builder.ts +421 -0
- package/src/orchestration/workflow-files.ts +85 -0
- package/src/orchestration/workflow-script-registry-impl.ts +133 -0
- package/src/shared/__tests__/agent-ref.test.ts +34 -0
- package/src/shared/__tests__/meta-parser.test.ts +304 -0
- package/src/shared/__tests__/model-ref.test.ts +306 -0
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +288 -0
- package/src/shared/__tests__/resource-discovery.test.ts +749 -0
- package/src/shared/__tests__/resource-meta.test.ts +51 -0
- package/src/shared/__tests__/schema-jsonify.test.ts +81 -0
- package/src/shared/__tests__/timer-delay.test.ts +61 -0
- package/src/shared/agent-event.ts +13 -0
- package/src/shared/agent-ref.ts +57 -0
- package/src/shared/meta-parser.ts +261 -0
- package/src/shared/model-ref.ts +286 -0
- package/src/shared/resource-discovery.ts +835 -0
- package/src/shared/resource-meta.ts +65 -0
- package/src/shared/schema-env.ts +44 -0
- package/src/shared/schema-jsonify.ts +58 -0
- package/src/shared/timer-delay.ts +54 -0
- package/src/shared/xml-injection.ts +35 -0
- package/workflows/README.md +81 -0
- package/workflows/_shared/agent-refs.cjs +40 -0
- package/workflows/chain.js +137 -0
- package/workflows/map-reduce.js +180 -0
- package/workflows/parallel.js +154 -0
- package/workflows/review-fix-loop-utils.cjs +1542 -0
- package/workflows/review-fix-loop.js +1605 -0
- package/workflows/scatter-gather.js +184 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Extension — Engine 共享类型
|
|
3
|
+
*
|
|
4
|
+
* Engine 层全局基础类型。零 infra 依赖——不 import 任何 infra 文件,
|
|
5
|
+
* 可独立编译测试(D-12 三层架构,AC-1)。
|
|
6
|
+
*
|
|
7
|
+
* 核心内容:
|
|
8
|
+
* - 状态机:RunStatus = "running" | "done"(2 态,一次性生命周期,FR-3)
|
|
9
|
+
* + DoneReason(completed/failed/aborted/budget_limited/time_limited)
|
|
10
|
+
* - AgentCallOpts / AgentResult / AgentUsage(单次 agent 调用的输入/输出)
|
|
11
|
+
* - ExecutionTraceNode / TracePatch / ToolCallEntry / WorkerLogEntry(trace 数据)
|
|
12
|
+
*
|
|
13
|
+
* 层归属:Engine(数据结构 + 不变式守卫)。
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { ExecutionRecord } from "../../execution/types.ts";
|
|
17
|
+
|
|
18
|
+
// ── 状态机 ────────────────────────────────────────────────────
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 状态机:2 态(D-12 / FR-3,一次性生命周期——run 不可挂起)。
|
|
22
|
+
*
|
|
23
|
+
* running → done
|
|
24
|
+
*
|
|
25
|
+
* `done` 是唯一终态,具体原因由 DoneReason 区分。
|
|
26
|
+
*/
|
|
27
|
+
export type RunStatus = "running" | "done";
|
|
28
|
+
|
|
29
|
+
/** 终态原因。done 时必有(WorkflowRun 不变式)。 */
|
|
30
|
+
export type DoneReason =
|
|
31
|
+
| "completed"
|
|
32
|
+
| "failed"
|
|
33
|
+
| "aborted"
|
|
34
|
+
| "budget_limited"
|
|
35
|
+
| "time_limited"
|
|
36
|
+
// m3:runAndWait 合成返回值专用——参数校验失败(run 从未创建,不进入 run.state.reason)
|
|
37
|
+
| "invalid_args";
|
|
38
|
+
|
|
39
|
+
/** 合法的状态转换。空数组 = 无出边(done 终态)。 */
|
|
40
|
+
export const VALID_RUN_TRANSITIONS: Record<RunStatus, readonly RunStatus[]> = {
|
|
41
|
+
running: ["done"] as const,
|
|
42
|
+
done: [] as const,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const ALL_RUN_STATUSES: readonly RunStatus[] = ["running", "done"] as const;
|
|
46
|
+
|
|
47
|
+
export const ALL_DONE_REASONS: readonly DoneReason[] = [
|
|
48
|
+
"completed",
|
|
49
|
+
"failed",
|
|
50
|
+
"aborted",
|
|
51
|
+
"invalid_args",
|
|
52
|
+
"budget_limited",
|
|
53
|
+
"time_limited",
|
|
54
|
+
] as const;
|
|
55
|
+
|
|
56
|
+
/** done 为终态,无出边。 */
|
|
57
|
+
export function isDone(status: RunStatus): boolean {
|
|
58
|
+
return status === "done";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function canRunTransition(from: RunStatus, to: RunStatus): boolean {
|
|
62
|
+
return (VALID_RUN_TRANSITIONS[from] as readonly RunStatus[]).includes(to);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ── Agent 调用 ────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 单次 agent 调用的输入选项。
|
|
69
|
+
*
|
|
70
|
+
* D-12 仅重组执行编排,AgentCallOpts 形状保持兼容。
|
|
71
|
+
*/
|
|
72
|
+
export interface AgentCallOpts {
|
|
73
|
+
/** The task prompt to send to the agent. */
|
|
74
|
+
prompt: string;
|
|
75
|
+
/**
|
|
76
|
+
* Optional JSON schema for structured output.
|
|
77
|
+
* When provided, the schema is passed via PI_WORKFLOW_SCHEMA env to the subprocess,
|
|
78
|
+
* which activates the structured-output tool + turn_end hook.
|
|
79
|
+
* The tool's execute validates model output against the schema.
|
|
80
|
+
* On success, `parsedOutput` on the result is set to `tool_execution_end.result.details`
|
|
81
|
+
* (the validated, parsed data object — not the raw tool call args).
|
|
82
|
+
*/
|
|
83
|
+
schema?: Record<string, unknown>;
|
|
84
|
+
/**
|
|
85
|
+
* Model to use (e.g. "router-openai/glm-5.1").
|
|
86
|
+
* When omitted, pi's default model is used.
|
|
87
|
+
*/
|
|
88
|
+
model?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Thinking level override (e.g. "high", "medium", "low").
|
|
91
|
+
* M2: Added to align with subagent path's ExecuteOptions.thinkingLevel.
|
|
92
|
+
* When omitted, agent .md frontmatter thinkingLevel is used (via resolveIdentity/getAgentConfig).
|
|
93
|
+
*/
|
|
94
|
+
thinkingLevel?: string;
|
|
95
|
+
/** Scene name passed through to the worker for model-selection hints. */
|
|
96
|
+
scene?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Wall-clock timeout in milliseconds. When > 0, aborts the subprocess
|
|
99
|
+
* if it runs longer than this, regardless of external signal.
|
|
100
|
+
* Per-call,归 AgentCall 实体(G-027)。
|
|
101
|
+
*/
|
|
102
|
+
timeoutMs?: number;
|
|
103
|
+
/**
|
|
104
|
+
* Turn 上限(turn limiter 用)。
|
|
105
|
+
*
|
|
106
|
+
* [预算语义对齐] 未传或 <=0 = 不限 turn;此时也不按 turns 估算 spawn watchdog——
|
|
107
|
+
* 仅当 env XYZ_SUBAGENT_SPAWN_WATCHDOG_MS 设置时才按绝对时限挂 watchdog(见
|
|
108
|
+
* session-runner.resolveSpawnWatchdogMs)。mapToExecuteOptions 原样透传到
|
|
109
|
+
* ExecuteOptions.maxTurns → 引擎 task-spec → runSpawn。
|
|
110
|
+
*/
|
|
111
|
+
maxTurns?: number;
|
|
112
|
+
/**
|
|
113
|
+
* Skill name to load (e.g. "code-review"). Resolved to SKILL.md path
|
|
114
|
+
* and injected via --skill flag in the subprocess.
|
|
115
|
+
*/
|
|
116
|
+
skill?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Resolved absolute path to the skill directory or SKILL.md file.
|
|
119
|
+
* Set by agent-opts-resolver when opts.skill is present.
|
|
120
|
+
*/
|
|
121
|
+
skillPath?: string;
|
|
122
|
+
/** Human-readable description for logging and debugging. */
|
|
123
|
+
description?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Agent ref (absolute .md path). Resolved by resolveIdentity via getAgentConfig,
|
|
126
|
+
* which injects the agent's systemPrompt/model/tools/thinkingLevel. Not handled by
|
|
127
|
+
* resolveAgentOpts (single-responsibility: agent ref ownership belongs to resolveIdentity,
|
|
128
|
+
* M2 fix — previously overlapped causing double-injection + model-tier confusion).
|
|
129
|
+
*/
|
|
130
|
+
agent?: string;
|
|
131
|
+
/**
|
|
132
|
+
* System prompt injection CONTENT (not file paths).
|
|
133
|
+
* Set by agent-opts-resolver: schema structured-output instruction string.
|
|
134
|
+
* Agent systemPrompt is NOT included here (handled by resolveIdentity/agentConfig).
|
|
135
|
+
* mapToExecuteOptions passes this through to ExecuteOptions.appendSystemPrompt
|
|
136
|
+
* (same name/semantics, transparent passthrough).
|
|
137
|
+
*/
|
|
138
|
+
appendSystemPrompt?: string[];
|
|
139
|
+
/**
|
|
140
|
+
* Schema JSON for PI_WORKFLOW_SCHEMA env var.
|
|
141
|
+
* Set by agent-opts-resolver when opts.schema is present; passed as env var
|
|
142
|
+
* to activate the structured-output tool + hook.
|
|
143
|
+
*/
|
|
144
|
+
schemaEnv?: string;
|
|
145
|
+
/**
|
|
146
|
+
* Per-call 工作目录(ADR-029 决策 1)。传给 child_process.spawn 的 cwd option。
|
|
147
|
+
*
|
|
148
|
+
* 用于 worktree 隔离:传入 worktree 绝对路径,spawn 的 pi 子进程绑定到该目录,
|
|
149
|
+
* 其内部的 createAgentSession/ResourceLoader/bash 工具都在该目录运行。
|
|
150
|
+
* undefined 时 spawn 继承 workflow 进程的 cwd(向后兼容)。
|
|
151
|
+
*/
|
|
152
|
+
cwd?: string;
|
|
153
|
+
/** Inherit parent session context (fork mode). Independent of worktree (file isolation). */
|
|
154
|
+
fork?: boolean;
|
|
155
|
+
/**
|
|
156
|
+
* 执行引擎 id(P4 D9 三层优先级的第一层:调用参数级,workflow step 显式指定)。
|
|
157
|
+
* 仅限「必须某引擎独有能力」的场景使用并注释原因(D9③ workflow 脚本不写死
|
|
158
|
+
* engine——环境差异由 frontmatter/全局默认承载);透传链 worker-script-builder
|
|
159
|
+
* agent() → execute-agent-call → SAR 路由层。
|
|
160
|
+
*/
|
|
161
|
+
engine?: string;
|
|
162
|
+
/** Filesystem isolation: when true, creates a new git worktree for the agent. Independent of fork. */
|
|
163
|
+
worktree?: boolean;
|
|
164
|
+
/** When true, agent() resolves {value, sessionFile, worktreePath, error} instead of a bare value.
|
|
165
|
+
* Worker-layer flag only — not forwarded to ExecuteOptions (mapToExecuteOptions drops it). */
|
|
166
|
+
returnMeta?: boolean;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 单次 agent 调用的资源用量(FR-7 跨 turn 累积)。
|
|
171
|
+
*/
|
|
172
|
+
export interface AgentUsage {
|
|
173
|
+
input: number;
|
|
174
|
+
output: number;
|
|
175
|
+
cacheRead: number;
|
|
176
|
+
cacheWrite: number;
|
|
177
|
+
cost: number;
|
|
178
|
+
contextTokens: number;
|
|
179
|
+
turns: number;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 单次 tool 调用记录(FR-7 从 agent JSONL 流采)。
|
|
184
|
+
*/
|
|
185
|
+
export interface ToolCallEntry {
|
|
186
|
+
/** Tool name. */
|
|
187
|
+
name: string;
|
|
188
|
+
/** Args preview string. */
|
|
189
|
+
input: string;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 单次 agent 调用的结果(统一形态)。
|
|
194
|
+
*
|
|
195
|
+
* Engine 直接消费 SubprocessAgentRunner 返回值;callCache replay 时 worker
|
|
196
|
+
* 取 parsedOutput ?? content(见 worker-script-builder.ts 消息处理)。
|
|
197
|
+
*/
|
|
198
|
+
export interface AgentResult {
|
|
199
|
+
/** Raw text output from the agent. */
|
|
200
|
+
content: string;
|
|
201
|
+
/**
|
|
202
|
+
* Parsed structured output.
|
|
203
|
+
* Present when `schema` was provided and the output was valid JSON.
|
|
204
|
+
* Source: tool_execution_end.result.details(validated data object)。
|
|
205
|
+
*/
|
|
206
|
+
parsedOutput?: unknown;
|
|
207
|
+
/** Token and cost usage accumulated across all assistant turns. */
|
|
208
|
+
usage?: AgentUsage;
|
|
209
|
+
/** Wall-clock duration in milliseconds. */
|
|
210
|
+
durationMs?: number;
|
|
211
|
+
/** True when the pi process exited with code 0. */
|
|
212
|
+
error?: string;
|
|
213
|
+
/**
|
|
214
|
+
* Pi session ID for the subagent process (uuidv7).
|
|
215
|
+
* Present when pi emits a session header (default in --mode json).
|
|
216
|
+
* Can be used to locate the session JSONL file for post-run inspection (G-017)。
|
|
217
|
+
*/
|
|
218
|
+
sessionId?: string;
|
|
219
|
+
/**
|
|
220
|
+
* Session JSONL 绝对路径(不含目录的文件名在 subagents 侧 AgentResult.sessionFile)。
|
|
221
|
+
* 由 mapToWorkflowAgentResult 从 subagents AgentResult 透传——让 workflow 编排层
|
|
222
|
+
* 继承 subagent 执行管道产出的 session 文件路径,overlay/GUI 可直接定位。
|
|
223
|
+
* 窗口期内可能 undefined(session 尚未创建成功)。
|
|
224
|
+
*/
|
|
225
|
+
sessionFile?: string;
|
|
226
|
+
/**
|
|
227
|
+
* Absolute path of the git worktree used for filesystem isolation (set when
|
|
228
|
+
* worktree isolation is active). Injected by executeAndAwait from record.worktreeHandle.path.
|
|
229
|
+
*
|
|
230
|
+
* ⚠️ Diagnostic only, may not exist: executeAndAwait's finalizeRecord cleans up the
|
|
231
|
+
* worktree (git worktree remove --force) before returning, so by the time this field
|
|
232
|
+
* reaches the caller the directory has typically been deleted. Use it only for log/trace
|
|
233
|
+
* correlation (e.g. attributing a session jsonl to its worktree origin) — never as a cwd
|
|
234
|
+
* for a subsequent agent or filesystem operation (would ENOENT).
|
|
235
|
+
*/
|
|
236
|
+
worktreePath?: string;
|
|
237
|
+
/** All tool calls collected from JSONL stream (FR-7). */
|
|
238
|
+
toolCalls?: ToolCallEntry[];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// ── Trace ─────────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* 执行追踪节点(事件流 D-10 单一来源)。
|
|
245
|
+
*/
|
|
246
|
+
export interface ExecutionTraceNode {
|
|
247
|
+
stepIndex: number;
|
|
248
|
+
agent: string;
|
|
249
|
+
task: string;
|
|
250
|
+
model: string;
|
|
251
|
+
status: "pending" | "running" | "completed" | "failed";
|
|
252
|
+
/** Phase name for TUI grouping. Set from explicit opts.phase or global _currentPhase. */
|
|
253
|
+
phase?: string;
|
|
254
|
+
startedAt?: string;
|
|
255
|
+
completedAt?: string;
|
|
256
|
+
result?: AgentResult;
|
|
257
|
+
error?: string;
|
|
258
|
+
/**
|
|
259
|
+
* Pi session ID (uuidv7) for the subagent process.
|
|
260
|
+
* Used to locate the session JSONL for post-run inspection.
|
|
261
|
+
*/
|
|
262
|
+
sessionId?: string;
|
|
263
|
+
/**
|
|
264
|
+
* Session JSONL 绝对路径。finalizeCall 从 result.sessionFile 透传。
|
|
265
|
+
* 持久化到快照(serializeRun),跨 session 重水合后保留。
|
|
266
|
+
*/
|
|
267
|
+
sessionFile?: string;
|
|
268
|
+
/**
|
|
269
|
+
* Live 执行进度对象(running 时存在,done 时由 dispatchAgentCall 清除)。
|
|
270
|
+
*
|
|
271
|
+
* 挂在 node 上(D-10 单源延伸:AgentCall.traceNode 与 Trace.nodes 共享同一引用)。
|
|
272
|
+
* TUI 通过 trace.toArray() 读 node.live,派生 getEventLog/getCurrentActivity 实时展示。
|
|
273
|
+
* 不持久化(序列化时 strip;重跑时由 dispatchAgentCall 重建)。
|
|
274
|
+
*/
|
|
275
|
+
live?: ExecutionRecord;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Trace.update 用的 patch(字段全可选)。
|
|
280
|
+
*
|
|
281
|
+
* 不变式:只改单个 node 的 status/result/error/completedAt/sessionId。
|
|
282
|
+
* callId 不存在时 update 为 no-op(D-10)。
|
|
283
|
+
*/
|
|
284
|
+
export interface TracePatch {
|
|
285
|
+
status?: "pending" | "running" | "completed" | "failed";
|
|
286
|
+
result?: AgentResult;
|
|
287
|
+
error?: string;
|
|
288
|
+
completedAt?: string;
|
|
289
|
+
sessionId?: string;
|
|
290
|
+
sessionFile?: string;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// ── Worker 诊断 ───────────────────────────────────────────────
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Worker console.* 捕获条目(run 级诊断,仅展示在 TUI widget,不泄漏到 input area)。
|
|
297
|
+
*/
|
|
298
|
+
export interface WorkerLogEntry {
|
|
299
|
+
level: "log" | "warn" | "error" | "info";
|
|
300
|
+
message: string;
|
|
301
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Extension — WorkflowRun
|
|
3
|
+
*
|
|
4
|
+
* 单次 workflow run 的聚合根。封装状态机 + runtime 生命周期 + 不变式守卫。
|
|
5
|
+
* 架构核心——所有字段变更通过方法(transition/assignRuntime/releaseRuntime/
|
|
6
|
+
* replaceRuntime),engine 模块不直接打洞(AC-3)。
|
|
7
|
+
*
|
|
8
|
+
* 层归属:Engine。依赖 RunRuntime(具体类,D-12 允许)+ RunSpec/RunState + 类型。
|
|
9
|
+
*
|
|
10
|
+
* 关键不变式(必须全测):
|
|
11
|
+
* I1: state.status === "running" ⟺ runtime !== undefined
|
|
12
|
+
* I2: state.status === "done" ⟹ state.reason !== undefined
|
|
13
|
+
*
|
|
14
|
+
* 状态机(一次性生命周期,2 态):
|
|
15
|
+
* 构造(status="running",I1 构造期跳过——runtime 由 assignRuntime 注入)
|
|
16
|
+
* running ──transition("done", reason)──→ done (releaseRuntime + completedAt)
|
|
17
|
+
* done ──(no out edges, zombie)
|
|
18
|
+
*
|
|
19
|
+
* 「创建即 running」与 I1 的协调(F4):构造瞬间 running 而 runtime 尚未注入,
|
|
20
|
+
* I1 在构造期跳过(仅查 I2),完整校验由 assignRuntime/transition/replaceRuntime
|
|
21
|
+
* 末尾的 validateInvariants 维持;构造到 assignRuntime 的 I1 窗口由调用方
|
|
22
|
+
* (lifecycle.runWorkflow 在 assignRuntime 之后才 runs.set)保证对外不可见。
|
|
23
|
+
*
|
|
24
|
+
* worker-error-retry(G5-001 + G6-001):
|
|
25
|
+
* - replaceRuntime(newRt): 前置 status==="running"(G6-001),原子释放前一个 runtime
|
|
26
|
+
* + 绑定新 runtime,全程保持不变式 I1(中间不经过 runtime===undefined 的可见状态)。
|
|
27
|
+
*
|
|
28
|
+
* 参考:domain-models.md §1(聚合根定义)、clarification.md G3-001/G5-001/G6-001。
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { RunRuntime } from "./run-runtime.ts";
|
|
32
|
+
import type { RunSpec } from "./run-spec.ts";
|
|
33
|
+
import type { RunState } from "./run-state.ts";
|
|
34
|
+
import type { DoneReason, RunStatus } from "./types.ts";
|
|
35
|
+
import { canRunTransition } from "./types.ts";
|
|
36
|
+
|
|
37
|
+
// ── WorkflowRunMeta ──────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 聚合根级 meta(非 RunState 的一部分,不随 trace 持久化到 worker JSONL)。
|
|
41
|
+
*
|
|
42
|
+
* workerErrorCount/scriptErrorCount 跨 runtime 存活(C.5:error-recovery 重试计数载体),
|
|
43
|
+
* 因为 retry 会 replaceRuntime,但计数是 run 级而非 runtime 级。
|
|
44
|
+
*/
|
|
45
|
+
export interface WorkflowRunMeta {
|
|
46
|
+
/** ISO 时间戳,run 创建/启动时刻。 */
|
|
47
|
+
startedAt: string;
|
|
48
|
+
/** ISO 时间戳,transition("done") 时设置。 */
|
|
49
|
+
completedAt?: string;
|
|
50
|
+
/** Worker 线程错误计数(C.5:跨 runtime 存活,重试计数载体)。 */
|
|
51
|
+
workerErrorCount?: number;
|
|
52
|
+
/** 脚本错误计数(C.5:跨 runtime 存活)。 */
|
|
53
|
+
scriptErrorCount?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ── WorkflowRun ──────────────────────────────────────────────
|
|
57
|
+
|
|
58
|
+
export class WorkflowRun {
|
|
59
|
+
readonly runId: string;
|
|
60
|
+
readonly spec: RunSpec;
|
|
61
|
+
state: RunState;
|
|
62
|
+
runtime?: RunRuntime;
|
|
63
|
+
meta: WorkflowRunMeta;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 创建聚合根。初始状态 "running"(一次性生命周期:run 从创建起即在执行,
|
|
67
|
+
* runtime 由紧随其后的 assignRuntime 注入)。也可传入 done 状态用于重水合
|
|
68
|
+
* 已完成的 run(loadAll 后的只读聚合)。
|
|
69
|
+
*
|
|
70
|
+
* 不变式 I1 构造期跳过——「创建即 running」要求构造瞬间 runtime===undefined
|
|
71
|
+
* 合法(runtime 必须由 assignRuntime 注入,构造函数无从持有);重水合的
|
|
72
|
+
* running 快照同样无 worker。I1 的运行时校验在 assignRuntime/transition/
|
|
73
|
+
* replaceRuntime 末尾的 validateInvariants 处生效。
|
|
74
|
+
*/
|
|
75
|
+
constructor(
|
|
76
|
+
runId: string,
|
|
77
|
+
spec: RunSpec,
|
|
78
|
+
state: RunState,
|
|
79
|
+
meta: WorkflowRunMeta,
|
|
80
|
+
) {
|
|
81
|
+
this.runId = runId;
|
|
82
|
+
this.spec = spec;
|
|
83
|
+
this.state = state;
|
|
84
|
+
this.meta = meta;
|
|
85
|
+
// runtime 在构造时始终为 undefined——run 创建时无活 worker,loadAll 重水合
|
|
86
|
+
// 时也不恢复 runtime(worker 必须由 lifecycle 重新 start)。
|
|
87
|
+
this.runtime = undefined;
|
|
88
|
+
// 构造期仅校验 I2(I1 跳过,见方法 doc);I1 由 assignRuntime 末尾
|
|
89
|
+
// validateInvariants 恢复。
|
|
90
|
+
this.validateInvariantI2();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 从持久化快照重水合聚合根。与构造函数同语义(构造期跳过 I1——持久化的
|
|
95
|
+
* running 状态没有 worker,进程被杀后 worker 不可能还活着)。保留独立工厂
|
|
96
|
+
* 标注重水合意图;调用方(D-4 kill-9 恢复)负责在 session_start 时把残留
|
|
97
|
+
* running 转 done,failed,恢复 I1。
|
|
98
|
+
*
|
|
99
|
+
* @throws I2 违反(done 快照缺 reason 仍是 bug,不可跳过)
|
|
100
|
+
*/
|
|
101
|
+
static reconstruct(runId: string, spec: RunSpec, state: RunState, meta: WorkflowRunMeta): WorkflowRun {
|
|
102
|
+
return new WorkflowRun(runId, spec, state, meta);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ── 不变式校验 ─────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* 校验不变式 I1 + I2。违反抛错(聚合根自我保护,fail-fast)。
|
|
109
|
+
* 在每个 mutation 方法末尾调用(防御式编程 + 测试可断言)。
|
|
110
|
+
*/
|
|
111
|
+
private validateInvariants(): void {
|
|
112
|
+
this.validateInvariantI2();
|
|
113
|
+
// I1: status==="running" ⟺ runtime!==undefined
|
|
114
|
+
if (this.state.status === "running" && this.runtime === undefined) {
|
|
115
|
+
throw new Error(
|
|
116
|
+
`WorkflowRun invariant I1 violated: status==="running" but runtime is undefined (runId=${this.runId})`,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (this.state.status !== "running" && this.runtime !== undefined) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`WorkflowRun invariant I1 violated: status!=="running" but runtime is defined (runId=${this.runId})`,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 仅校验不变式 I2(done ⟹ reason)。构造期用——「创建即 running」与重水合的
|
|
128
|
+
* running 快照都无 runtime(I1 构造期跳过),但 I2 必须保证(done 缺 reason 是真 bug)。
|
|
129
|
+
*/
|
|
130
|
+
private validateInvariantI2(): void {
|
|
131
|
+
if (this.state.status === "done" && this.state.reason === undefined) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
`WorkflowRun invariant I2 violated: status==="done" but reason is undefined (runId=${this.runId})`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ── 状态机转换 ─────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 状态机转换。合法转换:running→done。
|
|
142
|
+
*
|
|
143
|
+
* running 的进入不走 transition——构造即 running,replaceRuntime 保持 running。
|
|
144
|
+
* 调用 transition("running") 抛错,防止绕过 runtime 注入直接改状态。
|
|
145
|
+
*
|
|
146
|
+
* 副作用:
|
|
147
|
+
* - →done: releaseRuntime + 设 state.reason + meta.completedAt
|
|
148
|
+
*
|
|
149
|
+
* @param target 目标状态(不允许 "running"——runtime 注入只走 assignRuntime/replaceRuntime)
|
|
150
|
+
* @param reason →done 时必填(done ⟹ reason,不变式 I2)
|
|
151
|
+
* @throws 非法转换 / done 缺 reason / target==="running"
|
|
152
|
+
*/
|
|
153
|
+
transition(target: RunStatus, reason?: DoneReason): void {
|
|
154
|
+
// "running" 必须经 assignRuntime(需 runtime 参数,transition 无法提供)
|
|
155
|
+
if (target === "running") {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`WorkflowRun.transition: cannot transition to "running" directly — use assignRuntime() (runId=${this.runId})`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!canRunTransition(this.state.status, target)) {
|
|
162
|
+
throw new Error(
|
|
163
|
+
`WorkflowRun.transition: illegal transition ${this.state.status} → ${target} (runId=${this.runId})`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// →done 需 reason(不变式 I2)
|
|
168
|
+
if (target === "done" && reason === undefined) {
|
|
169
|
+
throw new Error(
|
|
170
|
+
`WorkflowRun.transition: transition to "done" requires a reason (runId=${this.runId})`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 副作用:先清理 runtime(releaseRuntime 守不变式 I1),再改 status
|
|
175
|
+
// (canRunTransition 已排除 target==="running",此处 target 恒为 "done")
|
|
176
|
+
this.releaseRuntime();
|
|
177
|
+
this.state.status = target;
|
|
178
|
+
this.state.reason = reason;
|
|
179
|
+
this.meta.completedAt = new Date().toISOString();
|
|
180
|
+
|
|
181
|
+
this.validateInvariants();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ── Runtime 生命周期 ───────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 绑定 runtime(run 创建后注入执行资源)。
|
|
188
|
+
*
|
|
189
|
+
* 前置:status==="running" && runtime===undefined(runWorkflow 创建路径——
|
|
190
|
+
* 构造即 running 但 runtime 延迟到此处注入)。
|
|
191
|
+
* 原子地:设 runtime 后末尾 validateInvariants,恢复构造期跳过的 I1
|
|
192
|
+
* (running ⟺ runtime!==undefined)。
|
|
193
|
+
*
|
|
194
|
+
* @throws runtime 已定义 / status 不是 "running"(done 僵尸不可复活)
|
|
195
|
+
*/
|
|
196
|
+
assignRuntime(rt: RunRuntime): void {
|
|
197
|
+
if (this.runtime !== undefined) {
|
|
198
|
+
throw new Error(
|
|
199
|
+
`WorkflowRun.assignRuntime: runtime already defined (runId=${this.runId})`,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
if (this.state.status !== "running") {
|
|
203
|
+
throw new Error(
|
|
204
|
+
`WorkflowRun.assignRuntime: requires status==="running" (current: ${this.state.status}, runId=${this.runId})`,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
// 原子绑定:构造期 I1 处于跳过窗口(running 而 runtime undefined),设 runtime
|
|
208
|
+
// 后末尾 validateInvariants 恢复 I1。调用方在 assignRuntime 后才对外注册
|
|
209
|
+
// (lifecycle.runWorkflow 的 runs.set 后移),窗口外部不可见。
|
|
210
|
+
this.runtime = rt;
|
|
211
|
+
this.validateInvariants();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* 解绑 runtime(done 时由 transition 调用,也可独立调用)。
|
|
216
|
+
*
|
|
217
|
+
* 前置:无(runtime===undefined 时 no-op,幂等)。
|
|
218
|
+
* 副作用:调 runtime.release("terminal") 释放 worker/controller,置 runtime=undefined。
|
|
219
|
+
*/
|
|
220
|
+
releaseRuntime(): void {
|
|
221
|
+
if (this.runtime === undefined) return;
|
|
222
|
+
this.runtime.release("terminal");
|
|
223
|
+
this.runtime = undefined;
|
|
224
|
+
// 不改 status——调用方(transition)负责。独立调用时调用方需自行确保
|
|
225
|
+
// status 一致(如 worker-error-retry 用 replaceRuntime 而非 release+assign)。
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* 原地替换 runtime(G5-001:worker-error-retry)。
|
|
230
|
+
*
|
|
231
|
+
* 前置:status==="running"(G6-001:终态 run 拒绝重建)。
|
|
232
|
+
* 原子地:释放旧 runtime(worker.terminate + abort)+ 绑定新 runtime,
|
|
233
|
+
* 全程 status 保持 "running",不变式 I1 不违反(中间无 runtime===undefined 可见态)。
|
|
234
|
+
*
|
|
235
|
+
* 与 release+assign 的区别:replaceRuntime 不改 status,中间同步完成,
|
|
236
|
+
* 外部观察不到违反不变式的瞬间。
|
|
237
|
+
*
|
|
238
|
+
* @throws status!=="running"
|
|
239
|
+
*/
|
|
240
|
+
replaceRuntime(rt: RunRuntime): void {
|
|
241
|
+
if (this.state.status !== "running") {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`WorkflowRun.replaceRuntime: requires status==="running" (current: ${this.state.status}, runId=${this.runId})`,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
// 原子替换:旧 runtime 释放(terminate+abort),新 runtime 绑定。
|
|
247
|
+
// status 保持 "running",runtime 全程 !== undefined,I1 不违反。
|
|
248
|
+
if (this.runtime !== undefined) {
|
|
249
|
+
this.runtime.release("terminal");
|
|
250
|
+
}
|
|
251
|
+
this.runtime = rt;
|
|
252
|
+
this.validateInvariants();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow Extension — WorkflowScriptRegistry 仓库接口
|
|
3
|
+
*
|
|
4
|
+
* workflow 脚本的仓库(repository)接口——Engine 定义、Infra 实现。
|
|
5
|
+
*
|
|
6
|
+
* 与 Ports 节的 3 个注入 port(AgentRunner/RunStore/WorkerHost)的区别:
|
|
7
|
+
* - 3 个 port 是"执行依赖"(子进程/文件系统/线程),注入到 LifecycleDeps
|
|
8
|
+
* - WorkflowScriptRegistry 是"发现依赖"(扫描文件系统),是 repository(§8),
|
|
9
|
+
* 不进 LifecycleDeps,由 Interface 层 tool 直接调用(list/get 脚本)
|
|
10
|
+
*
|
|
11
|
+
* 优先级:tmp > project > user(domain-models.md §8)。60s TTL,按 workspaceRoot 分桶。
|
|
12
|
+
* 实现在 Infra 层 WorkflowScriptRegistryImpl(扫描 + 缓存 + 去重)。
|
|
13
|
+
*
|
|
14
|
+
* 层归属:Engine(interface),Infra(impl)。
|
|
15
|
+
*
|
|
16
|
+
* 参考:domain-models.md §8。
|
|
17
|
+
*/
|
|
18
|
+
import type { WorkflowScript } from "./workflow-script.ts";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* workflow 脚本仓库接口(repository,需 mock 文件扫描)。
|
|
22
|
+
*/
|
|
23
|
+
export interface WorkflowScriptRegistry {
|
|
24
|
+
/** 扫描并返回所有 workflow 脚本(含 available=false 的解析失败项)。去重按 tmp>project>user。 */
|
|
25
|
+
loadAll(): Promise<WorkflowScript[]>;
|
|
26
|
+
|
|
27
|
+
/** 按名查单个脚本(含缓存)。返回 undefined 当 name 不存在。 */
|
|
28
|
+
get(name: string): Promise<WorkflowScript | undefined>;
|
|
29
|
+
|
|
30
|
+
/** 按绝对路径加载单个脚本(workflowRef 统一解析入口——S2 路径统一)。 */
|
|
31
|
+
getPath(ref: string): Promise<WorkflowScript | undefined>;
|
|
32
|
+
|
|
33
|
+
/** 失效缓存——下次 loadAll/get 重新扫描文件系统。 */
|
|
34
|
+
invalidate(): void;
|
|
35
|
+
}
|