@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,279 @@
|
|
|
1
|
+
// src/runtime/worktree-registry.ts
|
|
2
|
+
//
|
|
3
|
+
// 全局 worktree 注册表:跨 repo 记录所有活 pi-sub-* worktree。
|
|
4
|
+
//
|
|
5
|
+
// 取代旧的 per-cwd 扫描 + .session mapping sidecar 链。
|
|
6
|
+
// 旧 reaper 的两个根本缺陷由此消除:
|
|
7
|
+
// 1. 触发覆盖:旧 scan 扫「当前 cwd 对应的 repo」,workspace 根 / 非 git 目录启动时
|
|
8
|
+
// rev-parse 报错整个挂掉;且 tmpdir 下的 checkout 永远不会被 pi cwd "看到"。
|
|
9
|
+
// → 新 scan 遍历全局注册表,不依赖 cwd 是否 git repo。
|
|
10
|
+
// 2. 判据脆弱:旧 scan 用 .finalized/.cancelled 终态 marker 作主判据,进程崩溃时
|
|
11
|
+
// 无人写终态 → 孤儿永久泄漏。→ 新判据:pid 死活一条判到底。
|
|
12
|
+
//
|
|
13
|
+
// 并发模型:
|
|
14
|
+
// - 跨进程互斥(D5a):add/updatePid/remove 的 load→mutate→save 全程持
|
|
15
|
+
// proper-lockfile 异步锁(<worktrees.json>.lock,协议登记 data-source-registry.md §6)。
|
|
16
|
+
// 锁不可用(重试耗尽)时降级为无锁 RMW + warn——注册表是 best-effort 数据,
|
|
17
|
+
// 降级不比锁前更差,条目丢失由 reaper 对账兜底(worktree-manager scan 的
|
|
18
|
+
// 双向 diff,见 reconcileWithPhysical)。
|
|
19
|
+
// - 同步 IO(readFileSync/writeFileSync)持锁执行:锁内临界区毫秒级,
|
|
20
|
+
// async 锁 + sync IO 组合在单线程 event loop 内无 interleaving。
|
|
21
|
+
// - 原子写:写 .tmp → rename,防写一半崩溃产生损坏 JSON。
|
|
22
|
+
|
|
23
|
+
import * as fs from "node:fs";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
|
|
26
|
+
import { getLogger } from "../core/logger.ts";
|
|
27
|
+
import lockfile from "proper-lockfile";
|
|
28
|
+
|
|
29
|
+
import { bestEffort } from "./best-effort.ts";
|
|
30
|
+
|
|
31
|
+
const logger = getLogger("subagents");
|
|
32
|
+
|
|
33
|
+
/** create→spawn 宽限期(ms):pid=0 条目超过此阈值判 create 后崩溃。 */
|
|
34
|
+
export const SPAWN_GRACE_MS = 60_000;
|
|
35
|
+
|
|
36
|
+
/** JSON 缩进空格数(可读性 + diff 友好)。 */
|
|
37
|
+
const JSON_INDENT = 2;
|
|
38
|
+
|
|
39
|
+
/** tmp 随机段:36 进制取 8 字符(跳过 "0." 前缀),与 pid 组合保证并发唯一。 */
|
|
40
|
+
const TMP_RANDOM_BASE = 36;
|
|
41
|
+
const TMP_RANDOM_SLICE_START = 2; // 跳过 Math.random 字符串的 "0." 前缀
|
|
42
|
+
const TMP_RANDOM_SLICE_END = 10;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 锁参数:逐项对齐 extensions/shared/file-lock/src/file-lock.ts 的 withFileLock
|
|
46
|
+
* 包装默认值(stale 30s / retries 10)。两侧参数漂移会破坏「同一把
|
|
47
|
+
* <worktrees.json>.lock」的跨进程互斥语义(协议登记 data-source-registry.md §6),
|
|
48
|
+
* 与旧包装共存/替换期间尤其如此。
|
|
49
|
+
*/
|
|
50
|
+
const LOCK_STALE_MS = 30_000;
|
|
51
|
+
const LOCK_RETRIES = 10;
|
|
52
|
+
|
|
53
|
+
/** 注册表 JSON 顶层结构的运行时类型守卫。 */
|
|
54
|
+
function isRegistryData(value: unknown): value is { entries: WorktreeEntry[] } {
|
|
55
|
+
return (
|
|
56
|
+
typeof value === "object" &&
|
|
57
|
+
value !== null &&
|
|
58
|
+
"entries" in value &&
|
|
59
|
+
Array.isArray(value.entries)
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 注册表条目:一条 = 一个活 worktree。
|
|
65
|
+
* 字段全部来自 WorktreeHandle + session-runner 已捕获的 child.pid,零新数据源。
|
|
66
|
+
*/
|
|
67
|
+
export interface WorktreeEntry {
|
|
68
|
+
/** 主仓库根目录(git -C <repo> 操作目标)。 */
|
|
69
|
+
readonly repo: string;
|
|
70
|
+
/** 分支名("pi-sub-<recordId>")。 */
|
|
71
|
+
readonly branch: string;
|
|
72
|
+
/** checkout 目录(tmpdir 下,= WorktreeHandle.path)。 */
|
|
73
|
+
readonly checkout: string;
|
|
74
|
+
/** 子进程 pid(0 = create-spawn 窗口,尚未拿到 pid)。 */
|
|
75
|
+
readonly pid: number;
|
|
76
|
+
/** 创建时间戳(ms,SPAWN_GRACE 判据 + 调试用)。 */
|
|
77
|
+
readonly createdAt: number;
|
|
78
|
+
/**
|
|
79
|
+
* 对应 subagent session jsonl 文件全路径(诊断/兼容字段,reaper 据 pid 死活判孤儿)。
|
|
80
|
+
* session-runner first header 拿到 pid 时补全(create 时 record.sessionFile 尚未确定)。
|
|
81
|
+
* 可选:旧 worktrees.json / 非 worktree 模式无此字段,向后兼容(undefined 时 reaper 走原 pid 判据)。
|
|
82
|
+
*/
|
|
83
|
+
readonly sessionFile?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* 全局 worktree 注册表。
|
|
88
|
+
*
|
|
89
|
+
* 文件位置:<agentDir>/subagents/worktrees.json(repo 无关层级,跨 repo 共享)
|
|
90
|
+
* 格式:{ "entries": WorktreeEntry[] }
|
|
91
|
+
*/
|
|
92
|
+
export class WorktreeRegistry {
|
|
93
|
+
private readonly filePath: string;
|
|
94
|
+
|
|
95
|
+
constructor(agentDir: string) {
|
|
96
|
+
this.filePath = path.join(agentDir, "subagents", "worktrees.json");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 新增条目(create 成功后调,pid=0 占位)。
|
|
101
|
+
* 同 branch 已存在则覆盖(防残留覆盖)。
|
|
102
|
+
* 跨进程锁内 RMW(D5a);锁降级路径见 mutate。
|
|
103
|
+
*/
|
|
104
|
+
async add(entry: WorktreeEntry): Promise<void> {
|
|
105
|
+
await this.mutate((entries) => {
|
|
106
|
+
const idx = entries.findIndex((e) => e.branch === entry.branch);
|
|
107
|
+
if (idx >= 0) {
|
|
108
|
+
entries[idx] = entry;
|
|
109
|
+
} else {
|
|
110
|
+
entries.push(entry);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* 更新 pid(runSpawn spawn() 返回后同步调)。
|
|
117
|
+
* branch 不存在则忽略(create 后崩溃 + reaper 已清的竞态)。
|
|
118
|
+
* sessionFile 可选补全:传入时填入 entry(reaper 据 pid 死活判孤儿,不读本字段)。
|
|
119
|
+
*/
|
|
120
|
+
async updatePid(branch: string, pid: number, sessionFile?: string): Promise<void> {
|
|
121
|
+
await this.mutate(
|
|
122
|
+
(entries) => {
|
|
123
|
+
const idx = entries.findIndex((e) => e.branch === branch);
|
|
124
|
+
if (idx >= 0) {
|
|
125
|
+
entries[idx] = {
|
|
126
|
+
...entries[idx],
|
|
127
|
+
pid,
|
|
128
|
+
...(sessionFile !== undefined ? { sessionFile } : {}),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{ branch, pid },
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 移除条目(cleanup/reaper 清理后调)。
|
|
138
|
+
* branch 不存在则忽略(幂等)。
|
|
139
|
+
*/
|
|
140
|
+
async remove(branch: string): Promise<void> {
|
|
141
|
+
await this.mutate(
|
|
142
|
+
(entries) => {
|
|
143
|
+
const filtered = entries.filter((e) => e.branch !== branch);
|
|
144
|
+
if (filtered.length !== entries.length) {
|
|
145
|
+
entries.length = 0;
|
|
146
|
+
entries.push(...filtered);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{ branch },
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* 锁内 RMW 统一入口:withLock(load → mutate → save)。
|
|
155
|
+
*
|
|
156
|
+
* 降级语义(对齐本类既有 best-effort 约定——注册表写失败不阻断 create/cleanup
|
|
157
|
+
* 主流程):锁获取失败(重试耗尽 ELOCKED 等)→ warn + 无锁执行同一段 RMW
|
|
158
|
+
* (= D5a 之前的 last-write-wins 行为,条目丢失由 reaper 对账兜底),
|
|
159
|
+
* 不抛错、永不 reject(调用方含 session-runner 的 fire-and-forget 回调)。
|
|
160
|
+
*/
|
|
161
|
+
private async mutate(
|
|
162
|
+
mutate: (entries: WorktreeEntry[]) => void,
|
|
163
|
+
context?: { branch?: string; pid?: number },
|
|
164
|
+
): Promise<void> {
|
|
165
|
+
const run = (): void => {
|
|
166
|
+
const entries = this.load();
|
|
167
|
+
mutate(entries);
|
|
168
|
+
this.save(entries, context);
|
|
169
|
+
};
|
|
170
|
+
try {
|
|
171
|
+
await this.withLock(() => {
|
|
172
|
+
run();
|
|
173
|
+
});
|
|
174
|
+
} catch (lockErr) {
|
|
175
|
+
// 锁不可用(ELOCKED 重试耗尽 / 锁目录损坏等):降级无锁 RMW。
|
|
176
|
+
// 竞争窗口内可能丢条目(旧缺陷形态),由 reaper 对账(scan 双向 diff)收敛。
|
|
177
|
+
logger.warn("[worktree] registry lock unavailable, degraded to lock-free RMW", {
|
|
178
|
+
...(context ?? {}),
|
|
179
|
+
err: lockErr instanceof Error ? lockErr.message : String(lockErr),
|
|
180
|
+
});
|
|
181
|
+
try {
|
|
182
|
+
run();
|
|
183
|
+
} catch (err) {
|
|
184
|
+
bestEffort(err, "worktree registry degraded RMW");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* proper-lockfile 直用的跨进程锁(取代已删除的共享 file-lock 包装,抽包去依赖)。
|
|
191
|
+
* 锁协议逐项对齐 extensions/shared/file-lock/src/file-lock.ts 的 withFileLock:
|
|
192
|
+
* - lockfile 路径 = <目标文件>.lock(proper-lockfile 默认,与包装/runtime 侧
|
|
193
|
+
* 同一路径才互斥)
|
|
194
|
+
* - realpath:false —— 目标文件不存在也可锁(realpath 默认 true 时 ENOENT)
|
|
195
|
+
* - stale 30s:持锁进程崩溃后锁可被夺取
|
|
196
|
+
* - async retries 指数退避:10 次 / factor 2 / 100ms~10s / randomize,耗尽抛
|
|
197
|
+
* ELOCKED(调用方 mutate 的 catch 决定降级路径)
|
|
198
|
+
* - onCompromised:锁被 stale 夺取时标记,fn 执行前抛错——防止在失去互斥
|
|
199
|
+
* 保证的锁下写盘(对齐 pi throwIfCompromised 语义)
|
|
200
|
+
* 锁参数值由 LOCK_STALE_MS / LOCK_RETRIES 常量承载(防漂移说明见常量注释)。
|
|
201
|
+
*/
|
|
202
|
+
private async withLock(fn: () => void): Promise<void> {
|
|
203
|
+
// 锁前确保父目录存在:proper-lockfile 创建 lockfile(<目标>.lock)需要目录在
|
|
204
|
+
const dir = path.dirname(this.filePath);
|
|
205
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
206
|
+
|
|
207
|
+
let compromised: Error | undefined;
|
|
208
|
+
const release = await lockfile.lock(this.filePath, {
|
|
209
|
+
realpath: false,
|
|
210
|
+
stale: LOCK_STALE_MS,
|
|
211
|
+
retries: {
|
|
212
|
+
retries: LOCK_RETRIES,
|
|
213
|
+
factor: 2,
|
|
214
|
+
minTimeout: 100,
|
|
215
|
+
maxTimeout: 10_000,
|
|
216
|
+
randomize: true,
|
|
217
|
+
},
|
|
218
|
+
onCompromised: (err: Error) => {
|
|
219
|
+
compromised = err;
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
try {
|
|
223
|
+
if (compromised) throw compromised;
|
|
224
|
+
fn();
|
|
225
|
+
} finally {
|
|
226
|
+
try {
|
|
227
|
+
await release();
|
|
228
|
+
} catch (unlockErr) {
|
|
229
|
+
// 锁已 compromised(被 stale 夺取)时 unlock 必然失败且可忽略——记录留痕
|
|
230
|
+
// 不外抛(对齐被替换的 file-lock 包装 finally catch 语义)。
|
|
231
|
+
logger.debug("unlock failed after compromise (ignorable)", {
|
|
232
|
+
detail: { err: unlockErr instanceof Error ? unlockErr.message : String(unlockErr) },
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 加载全部条目(reaper 遍历用)。
|
|
240
|
+
* 文件不存在 / 解析失败 / IO 错误 → 返回空数组(视为无活 worktree)。
|
|
241
|
+
*/
|
|
242
|
+
load(): WorktreeEntry[] {
|
|
243
|
+
try {
|
|
244
|
+
const raw = fs.readFileSync(this.filePath, "utf-8");
|
|
245
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
246
|
+
if (isRegistryData(parsed)) {
|
|
247
|
+
return parsed.entries;
|
|
248
|
+
}
|
|
249
|
+
return [];
|
|
250
|
+
} catch {
|
|
251
|
+
// 文件不存在(首次运行)/ 解析失败(损坏)/ IO 错误 → 空注册表
|
|
252
|
+
return [];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* 原子写入全部条目。
|
|
258
|
+
* best-effort:写入失败不阻断主流程(create/cleanup 的 git 操作已执行,
|
|
259
|
+
* 注册表与 git 状态的短暂不一致靠下次 reaper 对账收敛)。
|
|
260
|
+
* 写盘失败时 warn 日志(带 branch/pid 上下文,补全失败可观测闭环)。
|
|
261
|
+
*/
|
|
262
|
+
private save(entries: WorktreeEntry[], context?: { branch?: string; pid?: number }): void {
|
|
263
|
+
try {
|
|
264
|
+
fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
|
|
265
|
+
// tmp 名带 pid + 随机段:锁降级(无锁并发 RMW)时多进程 tmp 互不覆盖
|
|
266
|
+
const tmp = `${this.filePath}.tmp_${process.pid}_${Math.random().toString(TMP_RANDOM_BASE).slice(TMP_RANDOM_SLICE_START, TMP_RANDOM_SLICE_END)}`;
|
|
267
|
+
fs.writeFileSync(tmp, JSON.stringify({ entries }, null, JSON_INDENT), "utf-8");
|
|
268
|
+
fs.renameSync(tmp, this.filePath);
|
|
269
|
+
} catch (err) {
|
|
270
|
+
bestEffort(err, "worktree registry save");
|
|
271
|
+
// [worktree-reaper-fix] 补全写盘失败静默吞错时,条目 pid 恒 0、60s 后被 reaper 误删
|
|
272
|
+
// 活 worktree 且无诊断线索。此 warn 与 reaper scan 的 pid=0 warn 呼应,形成闭环。
|
|
273
|
+
logger.warn(
|
|
274
|
+
"[worktree] registry save failed; pid may stay 0 and be reaped by orphan reaper",
|
|
275
|
+
{ ...(context ?? {}), err: err instanceof Error ? err.message : String(err) },
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zhushanwen/subagent-core — 公共 API barrel(D5 定稿)
|
|
3
|
+
*
|
|
4
|
+
* 公共 API 面 = 本文件导出 + package.json exports 的语义子入口
|
|
5
|
+
* (./engines/zcode/reader、./engines/zcode/constants、./engine/paths、./relay-env)
|
|
6
|
+
* + ./workflows/* 资产子入口。exports 面即 semver 契约(D5):收窄不放宽——
|
|
7
|
+
* 新增导出走 minor,本文件刻意不使用 `export *`,逐名列出以使 diff 可审。
|
|
8
|
+
* 内部实现细节(registry / error-recovery / execution 编排件等)不经 barrel 导出,
|
|
9
|
+
* 仓内壳侧深路径消费(`./*` -> src 通配)不受本文件约束。
|
|
10
|
+
*
|
|
11
|
+
* 设计权威源:docs/design/subagent-core-package-extraction.md §3.3 D5;
|
|
12
|
+
* 宿主接入示例见包 README(§3.4 core_host_not_configured 恢复指引的落点)。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const CORE_PACKAGE_VERSION = "0.2.0";
|
|
16
|
+
|
|
17
|
+
// ── 宿主端口接线面(core/)────────────────────────────────────
|
|
18
|
+
// HostServices:dataRoot / log / discoveryRoots 端口 + configureCore 注入;
|
|
19
|
+
// 未 configureCore 即消费 dataRoot 抛 core_host_not_configured(§3.4 错误规格,
|
|
20
|
+
// 恢复指引指向 README 接入示例)。DEFAULT_DATA_ROOT 显式导出供宿主选用——
|
|
21
|
+
// 消除「缺省静默漂目录」。
|
|
22
|
+
export {
|
|
23
|
+
configureCore,
|
|
24
|
+
DEFAULT_DATA_ROOT,
|
|
25
|
+
type DiscoveryRoot,
|
|
26
|
+
type HostServices,
|
|
27
|
+
} from "./core/host-services.ts";
|
|
28
|
+
|
|
29
|
+
// getLogger:facade 代理 logger——每次 log 调用时动态解析当前宿主实现,
|
|
30
|
+
// 模块顶层缓存惯例(`const logger = getLogger(...)`)下 configureCore 前后透明切换。
|
|
31
|
+
// LogLevel 是 HostServices.log 契约的成员类型(宿主实现必读)。
|
|
32
|
+
export { getLogger, type CoreLogger, type LogLevel } from "./core/logger.ts";
|
|
33
|
+
|
|
34
|
+
// NotifyDomainPorts:通知域窄端口(投递内核工厂 + pending 活跃计数),
|
|
35
|
+
// 两成员可选,缺席降级(投递直发 / pending 计零)。
|
|
36
|
+
export {
|
|
37
|
+
configureNotifyDomain,
|
|
38
|
+
type NotifyDomainPorts,
|
|
39
|
+
} from "./core/notify-ports.ts";
|
|
40
|
+
|
|
41
|
+
// ── 引擎契约面(execution/engine)────────────────────────────
|
|
42
|
+
// EnginePort:subagent 执行引擎的唯一契约点(run / interact / read / probe 四能力面)。
|
|
43
|
+
// types.ts:引擎中立类型(宿主与引擎适配器共同消费,宿主不感知具体引擎)。
|
|
44
|
+
export type {
|
|
45
|
+
EnginePort,
|
|
46
|
+
EngineRunResult,
|
|
47
|
+
RunContext,
|
|
48
|
+
} from "./execution/engine/port.ts";
|
|
49
|
+
export type {
|
|
50
|
+
AgentEvent,
|
|
51
|
+
AgentOutcome,
|
|
52
|
+
AgentTaskSpec,
|
|
53
|
+
EngineCapabilities,
|
|
54
|
+
EngineHandle,
|
|
55
|
+
EngineHandleData,
|
|
56
|
+
InteractAction,
|
|
57
|
+
InteractResult,
|
|
58
|
+
PersonaSpec,
|
|
59
|
+
ProbeReport,
|
|
60
|
+
ReplayedTurn,
|
|
61
|
+
SessionView,
|
|
62
|
+
} from "./execution/engine/types.ts";
|
|
63
|
+
// RunContext 的成员类型(ctxModel / stream)——类型闭包随 EnginePort 必然公开,
|
|
64
|
+
// 显式导出免宿主深路径兜圈;type-only(SubagentStream 是 execution 内部实现,禁 new)。
|
|
65
|
+
export type { ModelInfo } from "./execution/model-resolver.ts";
|
|
66
|
+
export type { SubagentStream } from "./execution/stream-sink.ts";
|
|
67
|
+
|
|
68
|
+
// routeEngine:三层路由(调用参数 > frontmatter > 全局默认)+ probe fallback 编排
|
|
69
|
+
// 的单一权威点(engine-abstraction D9/D7)。宿主按 error.code(engine_* 错误族)
|
|
70
|
+
// 判别失败形态,无需导入错误类。
|
|
71
|
+
export {
|
|
72
|
+
routeEngine,
|
|
73
|
+
type EngineRouteOptions,
|
|
74
|
+
type EngineRouteResult,
|
|
75
|
+
type EngineRouting,
|
|
76
|
+
type EngineRoutingInput,
|
|
77
|
+
type EngineRoutingSource,
|
|
78
|
+
} from "./execution/engine/routing.ts";
|
|
79
|
+
|
|
80
|
+
// ── workflow 编排入口(orchestration)────────────────────────
|
|
81
|
+
// runWorkflow / abortRun:run 生命周期 free functions(D-12)——orchestration 的
|
|
82
|
+
// 最小宿主入口。更细粒度编排(terminateRunningRuns / evictDoneRunsBeyondCap /
|
|
83
|
+
// scheduleTimeBudget)与 launcher 层(runAndWait 等)暂不进 barrel:
|
|
84
|
+
// 无宿主触点证据前不放宽(端口演进纪律②);壳侧现经深路径消费,不受影响。
|
|
85
|
+
export { abortRun, runWorkflow } from "./orchestration/lifecycle.ts";
|
|
86
|
+
export type { RunSpec } from "./orchestration/models/run-spec.ts";
|
|
87
|
+
export type { LifecycleDeps } from "./orchestration/models/ports.ts";
|