@zhushanwen/pi-subagent-workflow 8.6.0 → 8.8.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 +5 -11
- package/package.json +13 -20
- package/relay/relay.mjs +1 -1
- package/skills/workflow-script-format/SKILL.md +32 -13
- package/src/host/__tests__/pi-host.test.ts +235 -0
- package/src/host/pi-host.ts +163 -0
- package/src/index.ts +141 -138
- package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
- package/src/injectors/__tests__/engine-section-stability.test.ts +343 -0
- package/src/injectors/__tests__/model-list-injector.test.ts +18 -21
- package/src/injectors/__tests__/subagent-list-injector.test.ts +59 -19
- package/src/injectors/__tests__/workflow-list-injector.test.ts +31 -17
- package/src/injectors/engine-awareness.ts +119 -0
- package/src/injectors/model-list-injector.ts +15 -58
- package/src/injectors/subagent-list-injector.ts +56 -114
- package/src/injectors/workflow-list-injector.ts +37 -70
- package/src/interface/__tests__/detectors.test.ts +48 -37
- package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
- package/src/interface/__tests__/subagent-tool-prompt.test.ts +6 -3
- package/src/interface/__tests__/tool-workflow-run-builtin-name.test.ts +216 -0
- package/src/interface/__tests__/tool-workflow-script-generate.test.ts +17 -6
- package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +38 -2
- package/src/interface/bg-notify-render.ts +7 -17
- package/src/interface/command-actions.ts +5 -15
- package/src/interface/commands.ts +4 -4
- package/src/interface/format.ts +17 -6
- package/src/interface/gui-mappers.ts +18 -22
- package/src/interface/helpers.ts +9 -130
- package/src/interface/list-component.ts +5 -5
- package/src/interface/list-shared.ts +3 -3
- package/src/interface/list-view.ts +3 -3
- package/src/interface/subagent-actions.ts +66 -439
- package/src/interface/subagent-tool-schema.ts +21 -17
- package/src/interface/subagent-tool.ts +12 -7
- package/src/interface/subagents.ts +4 -4
- package/src/interface/tool-render.ts +37 -15
- package/src/interface/tool-workflow-script.ts +34 -76
- package/src/interface/tool-workflow.ts +57 -94
- package/src/interface/views/WorkflowsView.ts +8 -16
- package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
- package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
- package/src/interface/views/detail-content.ts +4 -4
- package/src/interface/views/format.ts +23 -62
- package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +137 -225
- package/agents/analyst.md +0 -61
- package/agents/coder.md +0 -70
- package/agents/debugger.md +0 -67
- package/agents/doc-reviewer.md +0 -50
- package/agents/explorer.md +0 -64
- package/agents/general-purpose.md +0 -32
- package/agents/orchestrator.md +0 -63
- package/agents/planner.md +0 -54
- package/agents/researcher.md +0 -65
- package/agents/reviewer.md +0 -74
- package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
- package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
- package/src/execution/__tests__/agent-registry.test.ts +0 -363
- package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
- package/src/execution/__tests__/alive-store.test.ts +0 -147
- package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
- package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
- package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
- package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
- package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
- package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
- package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
- package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
- package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
- package/src/execution/__tests__/config.test.ts +0 -110
- package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
- package/src/execution/__tests__/crash-recovery.test.ts +0 -320
- package/src/execution/__tests__/delivery-methods.test.ts +0 -422
- package/src/execution/__tests__/dialog-queue.test.ts +0 -299
- package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
- package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
- package/src/execution/__tests__/execute-nesting.test.ts +0 -323
- package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
- package/src/execution/__tests__/execution-record.test.ts +0 -1394
- package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
- package/src/execution/__tests__/finalize-record.test.ts +0 -368
- package/src/execution/__tests__/finalized-marker.test.ts +0 -82
- package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
- package/src/execution/__tests__/format.test.ts +0 -458
- package/src/execution/__tests__/gc-timer.test.ts +0 -184
- package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
- package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
- package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
- package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
- package/src/execution/__tests__/host-mode.test.ts +0 -87
- package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
- package/src/execution/__tests__/index-session-start.test.ts +0 -672
- package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
- package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
- package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
- package/src/execution/__tests__/list-component.test.ts +0 -401
- package/src/execution/__tests__/list-fields.test.ts +0 -140
- package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
- package/src/execution/__tests__/model-resolver.test.ts +0 -465
- package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
- package/src/execution/__tests__/nested-visibility.test.ts +0 -325
- package/src/execution/__tests__/notifier-flush.test.ts +0 -612
- package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
- package/src/execution/__tests__/notify-ledger.test.ts +0 -826
- package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
- package/src/execution/__tests__/output-collector.test.ts +0 -358
- package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
- package/src/execution/__tests__/path-encoding.test.ts +0 -104
- package/src/execution/__tests__/pi-invocation.test.ts +0 -134
- package/src/execution/__tests__/record-store.test.ts +0 -1057
- package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
- package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
- package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
- package/src/execution/__tests__/relay-agent.test.ts +0 -448
- package/src/execution/__tests__/relay-env.test.ts +0 -42
- package/src/execution/__tests__/resource-policy.test.ts +0 -109
- package/src/execution/__tests__/rpc-mode.test.ts +0 -89
- package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
- package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
- package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
- package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
- package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
- package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
- package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
- package/src/execution/__tests__/sdk-contract.test.ts +0 -273
- package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
- package/src/execution/__tests__/session-file-gc.test.ts +0 -293
- package/src/execution/__tests__/session-pending.test.ts +0 -197
- package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
- package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
- package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
- package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
- package/src/execution/__tests__/spawn-args.test.ts +0 -445
- package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
- package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
- package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
- package/src/execution/__tests__/spawned-children.test.ts +0 -92
- package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
- package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
- package/src/execution/__tests__/status-refactor.test.ts +0 -345
- package/src/execution/__tests__/stdin-writer.test.ts +0 -463
- package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
- package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
- package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
- package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
- package/src/execution/__tests__/subagent-service.test.ts +0 -788
- package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
- package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
- package/src/execution/__tests__/temp-prompt.test.ts +0 -53
- package/src/execution/__tests__/timeout-integration.test.ts +0 -615
- package/src/execution/__tests__/tombstone-store.test.ts +0 -73
- package/src/execution/__tests__/tool-action.test.ts +0 -476
- package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
- package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
- package/src/execution/__tests__/turn-limiter.test.ts +0 -65
- package/src/execution/__tests__/ui-channels.test.ts +0 -187
- package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
- package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
- package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
- package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
- package/src/execution/__tests__/worktree-manager.test.ts +0 -633
- package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
- package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
- package/src/execution/__tests__/worktree-registry.test.ts +0 -199
- package/src/execution/agent-registry.ts +0 -199
- package/src/execution/agent-result-mapper.ts +0 -90
- package/src/execution/alive-store.ts +0 -92
- package/src/execution/argv-mirror.ts +0 -113
- package/src/execution/best-effort.ts +0 -38
- package/src/execution/channel-registry-access.ts +0 -144
- package/src/execution/concurrency-pool.ts +0 -116
- package/src/execution/config.ts +0 -96
- package/src/execution/dialog-queue.ts +0 -330
- package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
- package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
- package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
- package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
- package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
- package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
- package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
- package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
- package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
- package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
- package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
- package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
- package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
- package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
- package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
- package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
- package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
- package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
- package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
- package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
- package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
- package/src/execution/engine/__tests__/paths.test.ts +0 -39
- package/src/execution/engine/__tests__/registry.test.ts +0 -120
- package/src/execution/engine/__tests__/routing.test.ts +0 -231
- package/src/execution/engine/common/data-dir.ts +0 -62
- package/src/execution/engine/common/errors.ts +0 -183
- package/src/execution/engine/common/event-journal.ts +0 -254
- package/src/execution/engine/common/journal-replay.ts +0 -62
- package/src/execution/engine/common/kill-chain.ts +0 -221
- package/src/execution/engine/common/nesting-guard.ts +0 -50
- package/src/execution/engine/common/persona-router.ts +0 -108
- package/src/execution/engine/common/pool-manager.ts +0 -226
- package/src/execution/engine/common/schema-emulation.ts +0 -189
- package/src/execution/engine/common/session-view-projection.ts +0 -51
- package/src/execution/engine/engine-discovery.ts +0 -65
- package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
- package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
- package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
- package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
- package/src/execution/engine/engines/pi/reader.ts +0 -48
- package/src/execution/engine/engines/pi/registration.ts +0 -35
- package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
- package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
- package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
- package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
- package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
- package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
- package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
- package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
- package/src/execution/engine/engines/zcode/constants.ts +0 -43
- package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
- package/src/execution/engine/engines/zcode/launcher.ts +0 -161
- package/src/execution/engine/engines/zcode/parser.ts +0 -436
- package/src/execution/engine/engines/zcode/preparer.ts +0 -363
- package/src/execution/engine/engines/zcode/reader.ts +0 -381
- package/src/execution/engine/engines/zcode/registration.ts +0 -37
- package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
- package/src/execution/engine/host-task-spec.ts +0 -47
- package/src/execution/engine/model-prompt.ts +0 -59
- package/src/execution/engine/paths.ts +0 -42
- package/src/execution/engine/port.ts +0 -153
- package/src/execution/engine/registry.ts +0 -123
- package/src/execution/engine/routing.ts +0 -218
- package/src/execution/engine/types.ts +0 -309
- package/src/execution/execute-options-mapper.ts +0 -112
- package/src/execution/execution-record.ts +0 -965
- package/src/execution/finalize-record.ts +0 -251
- package/src/execution/finalized-marker.ts +0 -51
- package/src/execution/get-state-handshake.ts +0 -104
- package/src/execution/host-mode.ts +0 -56
- package/src/execution/idle-gc.ts +0 -47
- package/src/execution/lifecycle-manager.ts +0 -513
- package/src/execution/lifecycle-predicates.ts +0 -65
- package/src/execution/manifest-store.ts +0 -256
- package/src/execution/model-config-service.ts +0 -219
- package/src/execution/model-resolver.ts +0 -248
- package/src/execution/notifier.ts +0 -330
- package/src/execution/notify-ledger.ts +0 -580
- package/src/execution/output-collector.ts +0 -228
- package/src/execution/path-encoding.ts +0 -60
- package/src/execution/pi-invocation.ts +0 -120
- package/src/execution/record-entry.ts +0 -132
- package/src/execution/record-store.ts +0 -1234
- package/src/execution/relay-env.ts +0 -37
- package/src/execution/session-context-resolver.ts +0 -64
- package/src/execution/session-file-gc.ts +0 -120
- package/src/execution/session-pending.ts +0 -164
- package/src/execution/session-reconstructor.ts +0 -678
- package/src/execution/session-runner.ts +0 -1781
- package/src/execution/sessions-index.ts +0 -304
- package/src/execution/spawn-event-adapter.ts +0 -363
- package/src/execution/stdin-writer.ts +0 -198
- package/src/execution/stream-sink.ts +0 -126
- package/src/execution/subagent-service.ts +0 -2141
- package/src/execution/subprocess-agent-runner.ts +0 -317
- package/src/execution/temp-prompt.ts +0 -62
- package/src/execution/tombstone-store.ts +0 -72
- package/src/execution/turn-limiter.ts +0 -102
- package/src/execution/types.ts +0 -973
- package/src/execution/ui-channels.ts +0 -216
- package/src/execution/ui-interaction-model.ts +0 -48
- package/src/execution/ui-request-handler-factory.ts +0 -212
- package/src/execution/ui-request-observability.ts +0 -81
- package/src/execution/ui-request-queue.ts +0 -184
- package/src/execution/worktree-manager.ts +0 -688
- package/src/execution/worktree-registry.ts +0 -222
- package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
- package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
- package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
- package/src/orchestration/__tests__/args-validator.test.ts +0 -143
- package/src/orchestration/__tests__/config-loader.test.ts +0 -503
- package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
- package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
- package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
- package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
- package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
- package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
- package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
- package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
- package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
- package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
- package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
- package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
- package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
- package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
- package/src/orchestration/__tests__/script-lint.test.ts +0 -831
- package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
- package/src/orchestration/__tests__/test-mocks.ts +0 -197
- package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
- package/src/orchestration/__tests__/worker-host.test.ts +0 -120
- package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
- package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
- package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
- package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
- package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
- package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
- package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
- package/src/orchestration/agent-opts-resolver.ts +0 -174
- package/src/orchestration/args-validator.ts +0 -127
- package/src/orchestration/config-loader.ts +0 -315
- package/src/orchestration/error-recovery.ts +0 -1018
- package/src/orchestration/execute-agent-call.ts +0 -256
- package/src/orchestration/launcher.ts +0 -455
- package/src/orchestration/lifecycle.ts +0 -399
- package/src/orchestration/models/__tests__/budget.test.ts +0 -307
- package/src/orchestration/models/__tests__/trace.test.ts +0 -408
- package/src/orchestration/models/agent-call.ts +0 -83
- package/src/orchestration/models/budget.ts +0 -118
- package/src/orchestration/models/ports.ts +0 -164
- package/src/orchestration/models/run-runtime.ts +0 -104
- package/src/orchestration/models/run-spec.ts +0 -83
- package/src/orchestration/models/run-state.ts +0 -44
- package/src/orchestration/models/trace.ts +0 -183
- package/src/orchestration/models/types.ts +0 -301
- package/src/orchestration/models/workflow-run.ts +0 -254
- package/src/orchestration/models/workflow-script-registry.ts +0 -35
- package/src/orchestration/models/workflow-script.ts +0 -117
- package/src/orchestration/script-lint.ts +0 -766
- package/src/orchestration/skill-discovery.ts +0 -115
- package/src/orchestration/worker-handle.ts +0 -115
- package/src/orchestration/worker-host.ts +0 -98
- package/src/orchestration/worker-script-builder.ts +0 -421
- package/src/orchestration/workflow-files.ts +0 -85
- package/src/orchestration/workflow-script-registry-impl.ts +0 -133
- package/src/shared/__tests__/agent-ref.test.ts +0 -34
- package/src/shared/__tests__/meta-parser.test.ts +0 -304
- package/src/shared/__tests__/model-ref.test.ts +0 -306
- package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
- package/src/shared/__tests__/resource-discovery.test.ts +0 -736
- package/src/shared/__tests__/resource-meta.test.ts +0 -51
- package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
- package/src/shared/__tests__/timer-delay.test.ts +0 -61
- package/src/shared/agent-event.ts +0 -13
- package/src/shared/agent-ref.ts +0 -57
- package/src/shared/meta-parser.ts +0 -261
- package/src/shared/model-ref.ts +0 -286
- package/src/shared/resource-discovery.ts +0 -811
- package/src/shared/resource-meta.ts +0 -65
- package/src/shared/schema-env.ts +0 -44
- package/src/shared/schema-jsonify.ts +0 -58
- package/src/shared/timer-delay.ts +0 -54
- package/src/shared/xml-injection.ts +0 -35
- package/workflows/README.md +0 -81
- package/workflows/_shared/agent-refs.cjs +0 -40
- package/workflows/chain.js +0 -131
- package/workflows/map-reduce.js +0 -174
- package/workflows/parallel.js +0 -148
- package/workflows/review-fix-loop-utils.cjs +0 -1309
- package/workflows/review-fix-loop.js +0 -1404
- package/workflows/scatter-gather.js +0 -178
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
import { Key, matchesKey } from "@earendil-works/pi-tui";
|
|
14
14
|
|
|
15
|
-
import { getAllToolCalls, projectLiveProgress } from "
|
|
16
|
-
import type { AgentEventLogEntry } from "
|
|
17
|
-
import type { ExecutionTraceNode } from "
|
|
18
|
-
import type { WorkflowRun } from "
|
|
15
|
+
import { getAllToolCalls, projectLiveProgress } from "@zhushanwen/subagent-core/execution/execution-record.ts";
|
|
16
|
+
import type { AgentEventLogEntry } from "@zhushanwen/subagent-core/execution/types.ts";
|
|
17
|
+
import type { ExecutionTraceNode } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
|
|
18
|
+
import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
|
|
19
19
|
import {
|
|
20
20
|
BOX_BORDER_CHARS,
|
|
21
21
|
BUDGET_TOKENS_DIVISOR,
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
9
9
|
|
|
10
|
-
import type { AgentEventLogEntry } from "
|
|
11
|
-
import type { ExecutionTraceNode, ToolCallEntry } from "
|
|
12
|
-
import type { DoneReason, RunStatus } from "
|
|
13
|
-
import { displayAgentName } from "
|
|
10
|
+
import type { AgentEventLogEntry } from "@zhushanwen/subagent-core/execution/types.ts";
|
|
11
|
+
import type { ExecutionTraceNode, ToolCallEntry } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
|
|
12
|
+
import type { DoneReason, RunStatus } from "@zhushanwen/subagent-core/orchestration/models/types.ts";
|
|
13
|
+
import { displayAgentName } from "@zhushanwen/subagent-core/shared/agent-ref.ts";
|
|
14
|
+
|
|
15
|
+
import type { ThemeLike as BaseThemeLike } from "../format.ts";
|
|
14
16
|
|
|
15
17
|
// ── Constants ─────────────────────────────────────────────────
|
|
16
18
|
|
|
@@ -53,10 +55,12 @@ type StatusText =
|
|
|
53
55
|
|
|
54
56
|
// ── Theme interface (avoids importing Pi runtime) ─────────────
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
/**
|
|
59
|
+
* views 侧主题形状:仅 fg/bold——本文件所有函数只消费这两个方法。
|
|
60
|
+
* 单源派生自 src/interface/format.ts 的 ThemeLike(Pick 收窄),不再独立声明;
|
|
61
|
+
* 保留窄形状是为了让只有 fg/bold 的 duck-typed theme(含测试 stub)可直接传入。
|
|
62
|
+
*/
|
|
63
|
+
export type ThemeLike = Pick<BaseThemeLike, "fg" | "bold">;
|
|
60
64
|
|
|
61
65
|
// ── Status helpers ────────────────────────────────────────────
|
|
62
66
|
|
|
@@ -128,17 +132,7 @@ export function formatElapsed(startedAt?: string, now: number = Date.now()): str
|
|
|
128
132
|
return `${mins}m${remSecs}s`;
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
|
|
132
|
-
* Format elapsed time from integer seconds(live 路径用)。
|
|
133
|
-
* 与 formatElapsed 输出格式一致,但输入是 computeElapsedSeconds 的秒数(非时间戳)。
|
|
134
|
-
*/
|
|
135
|
-
export function formatElapsedSeconds(seconds: number): string {
|
|
136
|
-
if (seconds < 1) return "0s";
|
|
137
|
-
if (seconds < SECS_PER_MIN) return `${seconds}s`;
|
|
138
|
-
const mins = Math.floor(seconds / SECS_PER_MIN);
|
|
139
|
-
const remSecs = seconds % SECS_PER_MIN;
|
|
140
|
-
return `${mins}m${remSecs}s`;
|
|
141
|
-
}
|
|
135
|
+
// formatElapsedSeconds 单源自 src/interface/format.ts(见文末「单源折叠垫片」)。
|
|
142
136
|
|
|
143
137
|
/**
|
|
144
138
|
* Format a live eventLog entry(live 路径 Activity 区用)。
|
|
@@ -204,48 +198,15 @@ export function formatActivityLine(entry: ToolCallEntry, maxWidth: number): stri
|
|
|
204
198
|
return `${entry.name}(${truncated})`;
|
|
205
199
|
}
|
|
206
200
|
|
|
207
|
-
// ──
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/** Pad an ANSI-escaped string to a target *visible* width.
|
|
217
|
-
* 只 pad 不截断:超宽时原样返回(调用方负责先截断)。
|
|
218
|
-
* 对齐 subagents 的 padToVisible 语义。
|
|
219
|
-
*/
|
|
220
|
-
export function padVisible(s: string, width: number): string {
|
|
221
|
-
const vl = visibleLen(s);
|
|
222
|
-
if (vl >= width) return s;
|
|
223
|
-
return s + " ".repeat(width - vl);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* 分段着色版填充:title 和 fill 都已着色(含 ANSI),拼接时各自 ANSI 延续。
|
|
228
|
-
* 解决 ANSI 嵌套失色:若用 fg("c1", fill(title, "─", n)),
|
|
229
|
-
* title 内的 \x1b[0m 会重置外层 c1,导致 title 之后的 ─ 失去 c1。
|
|
230
|
-
* 改成 title + fill.repeat(后),fill 整段保持自己的 ANSI,不依赖外层包裹。
|
|
231
|
-
*
|
|
232
|
-
* 对齐 subagents format.ts segFillColored(同源移植)。
|
|
233
|
-
*/
|
|
234
|
-
export function segFillColored(
|
|
235
|
-
titleStyled: string | undefined,
|
|
236
|
-
fillStyled: string,
|
|
237
|
-
width: number,
|
|
238
|
-
): string {
|
|
239
|
-
if (width <= 0) return "";
|
|
240
|
-
const fillW = visibleLen(fillStyled);
|
|
241
|
-
if (!titleStyled || fillW === 0) {
|
|
242
|
-
return fillStyled.repeat(width);
|
|
243
|
-
}
|
|
244
|
-
const tw = visibleLen(titleStyled);
|
|
245
|
-
if (tw >= width) return truncateToWidth(titleStyled, width);
|
|
246
|
-
const fillCount = width - tw;
|
|
247
|
-
return titleStyled + fillStyled.repeat(fillCount);
|
|
248
|
-
}
|
|
201
|
+
// ── 单源折叠垫片(设计 U11 宿主内合并)─────────────────────────
|
|
202
|
+
// 通用文本 helper 已折叠单源到 src/interface/format.ts——truncLine 为自研
|
|
203
|
+
// ANSI 安全实现(pi-tui truncateToWidth 会在省略号处插 \x1b[0m 断裂背景色,
|
|
204
|
+
// 见 interface/format.ts truncLine 注释),统一取 interface 侧实现。
|
|
205
|
+
// 此处按原名 re-export:WorkflowsView / detail-content(本 wave 只读)的
|
|
206
|
+
// import 面不变即完成单源切换。segFillColored 无 views 侧消费方,直接删除。
|
|
207
|
+
export { formatElapsedSeconds } from "../format.ts";
|
|
208
|
+
export { padToVisible as padVisible } from "../format.ts";
|
|
209
|
+
export { visibleWidth as visibleLen } from "@earendil-works/pi-tui";
|
|
249
210
|
|
|
250
211
|
// ── Phase group (filters empty phases) ────────────────────────
|
|
251
212
|
|
|
@@ -290,7 +251,7 @@ export function formatPhaseLine(
|
|
|
290
251
|
// pointer(2) + dot(1) + space(1)
|
|
291
252
|
const PHASE_PREFIX_WIDTH = 4;
|
|
292
253
|
const budget = maxWidth - PHASE_PREFIX_WIDTH;
|
|
293
|
-
const truncated =
|
|
254
|
+
const truncated = visibleWidth(label) > budget
|
|
294
255
|
? truncateToWidth(label, budget - 1) + ELLIPSIS
|
|
295
256
|
: label;
|
|
296
257
|
return `${pointer}${dot} ${truncated}`;
|
|
@@ -17,6 +17,9 @@
|
|
|
17
17
|
* 快照 entry(pi.appendEntry)——pi 文件(session JSONL)是 workflow 数据持久化
|
|
18
18
|
* 权威,state 文件降级为纯性能缓存(读序 = entry > state 文件 > 空,写路径保留)。
|
|
19
19
|
* 旧 `workflow-state-link` 指针 entry 退役(loadAll 保留兼容读,存量 run 不丢)。
|
|
20
|
+
* [B-1/OR-5 同源] entry append 按 runId 节流(见 save 注释「entry append 节流」),
|
|
21
|
+
* pi session JSONL 是 append-only 文件,节流前每次 flush 全量 append 会随 run
|
|
22
|
+
* 时长累积出单 run O(n²) 磁盘占用。
|
|
20
23
|
*
|
|
21
24
|
* save 去抖语义(cw swf-perf wave2):
|
|
22
25
|
* - **热路径**(running 中间态,本实例已写过):per-runId pending 批合并——窗口内
|
|
@@ -27,18 +30,25 @@
|
|
|
27
30
|
* 同步挂链 flush 绕过 timer——首写立即可见(跨 session 重启后 loadAll 从 entry
|
|
28
31
|
* 发现 run)、done 立即落盘(终态优先持久化:transition("done") 后的 save
|
|
29
32
|
* 不进去抖批,去抖窗口内的崩溃不吞终态)。
|
|
30
|
-
* - workflow-record entry
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
+
* - workflow-record entry append 节流([B-1],语义对齐 core FileRunStore.save
|
|
34
|
+
* 的 OR-5 ⑥a 节流,间隔常量单源复用 core DEFAULT_SAVE_MIN_INTERVAL_MS):
|
|
35
|
+
* running 中间态的 entry append 有最小间隔(缺省 60s;0 = 禁用),终态 flush
|
|
36
|
+
* 的 entry 永不节流(最终状态必进 pi 权威文件,loadAll/恢复不丢终态);
|
|
37
|
+
* state 文件 writeFile 不节流(rewrite mode 覆盖写,无累积)。节流窗口内的
|
|
38
|
+
* entry 跳过 = pi 文件最后一条 entry 最多落后真实状态一个窗口,崩溃语义与
|
|
39
|
+
* 未落盘 running 尾部丢失同源(kill-9 恢复收编)。
|
|
33
40
|
* - per-runId 串行 flush 链:同 runId 的 flush 排队顺序执行(不跳过、永不并发
|
|
34
41
|
* writeFile),链尾吞错防断链——错误只经各 save() Promise 的 settlers 传播。
|
|
35
42
|
* - dispose():幂等(缓存自身 Promise);刷全部 pending 批 + await 全部 in-flight
|
|
36
43
|
* 链后返回。dispose 后 save 静默 no-op + debug 日志(session_shutdown 编排收尾)。
|
|
37
44
|
*
|
|
38
|
-
*
|
|
39
|
-
* -
|
|
40
|
-
*
|
|
41
|
-
*
|
|
45
|
+
* 序列化策略(下沉收口 D4 后):
|
|
46
|
+
* - 快照投影/重水合/版本 guard 全部消费 core run-snapshot codec(toRunSnapshot/
|
|
47
|
+
* fromRunSnapshot)——字段演进单点(G2);本 store 只保留 IO 策略(rewrite/
|
|
48
|
+
* 去抖/append,D4 裁决:IO 差异归属宿主 store 层)。
|
|
49
|
+
* - 版本值沿用 core SNAPSHOT_VERSION "wf-run-v2"(D4 裁决①:pi 存量逐字节可读)。
|
|
50
|
+
* - pi 侧版本不匹配静默跳过语义保持(D-5);「缺 v 宽容」是 core FileRunStore
|
|
51
|
+
* 侧的存量预处理职责,不内聚进 codec(D4 裁决②),故本侧零改动即保持。
|
|
42
52
|
*
|
|
43
53
|
* [S3 查证结论] pi 0.84.1 实装(node_modules/@earendil-works/pi-coding-agent/dist,
|
|
44
54
|
* core/session-manager.js,PS-19)的 session 生命周期管理不含自动 GC:
|
|
@@ -49,9 +59,10 @@
|
|
|
49
59
|
* 里用户手动删除选中的单个顶层 session 文件(trash CLI → unlink fallback,
|
|
50
60
|
* dist/modes/interactive/components/session-selector.js:539-550),非自动、
|
|
51
61
|
* 不递归子目录。**推论:workflow-state state 文件无限累积,
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
62
|
+
* 保留策略由本包自担**——磁盘侧保留默认开(OR-5 ⑥b):每次新 run state 文件首写
|
|
63
|
+
* 成功即按 mtime 裁剪到上限(未设 {@link STATE_MAX_RUNS_ENV} 时取
|
|
64
|
+
* {@link DEFAULT_STATE_MAX_RUNS} 默认值,见 pruneStateFilesBeyondCap;显式非法值
|
|
65
|
+
* 是 opt-out 通道);内存侧由 evictDoneRunsBeyondCap 淘汰。W17 后 state 文件
|
|
55
66
|
* 已降级为纯性能缓存(权威数据在 session JSONL 的 workflow-record entry),随 session
|
|
56
67
|
* 文件被用户删除时一并消失。
|
|
57
68
|
*
|
|
@@ -62,76 +73,19 @@ import * as fs from "node:fs";
|
|
|
62
73
|
import * as path from "node:path";
|
|
63
74
|
|
|
64
75
|
import type { CustomEntry, ExtensionAPI, ExtensionContext, SessionEntry } from "@earendil-works/pi-coding-agent";
|
|
65
|
-
import {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
import
|
|
70
|
-
|
|
71
|
-
import {
|
|
72
|
-
import
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* 快照格式版本。D-5:旧 session(无此字段或值不匹配)被 loadAll 忽略。
|
|
81
|
-
*
|
|
82
|
-
* 版本历史:
|
|
83
|
-
* - wf-run-v1:status 三态(含 paused)、meta 含 pausedAt。
|
|
84
|
-
* - wf-run-v2(当前):status 两态(running/done)、meta 无 pausedAt(随一次性
|
|
85
|
-
* 生命周期收窄,F6/F8)。v1 文件 loadAll 静默跳过——含 v1 running 残留跳过 =
|
|
86
|
-
* 静默消失不显示,接受(父文档 D-5 边界声明:旧 run 历史价值低,不做兼容迁移)。
|
|
87
|
-
*
|
|
88
|
-
* 升级格式时 bump 此常量并在 deserializeRun 中适配——旧文件返回 null(被 loadAll 跳过)。
|
|
89
|
-
*/
|
|
90
|
-
export const SNAPSHOT_VERSION = "wf-run-v2" as const;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* 持久化快照形态——WorkflowRun 公共字段的 JSON 可序列化投影。
|
|
94
|
-
*
|
|
95
|
-
* calls 序列化为数组(Map 不能直接 JSON.stringify);反序列化时重建 Map。
|
|
96
|
-
* budget/trace 在 deserialize 时重建实例(带方法的 class)。
|
|
97
|
-
*/
|
|
98
|
-
interface RunSnapshot {
|
|
99
|
-
v: typeof SNAPSHOT_VERSION;
|
|
100
|
-
runId: string;
|
|
101
|
-
spec: RunSpec;
|
|
102
|
-
state: {
|
|
103
|
-
status: RunStatus;
|
|
104
|
-
reason?: DoneReason;
|
|
105
|
-
budget: {
|
|
106
|
-
maxTokens?: number;
|
|
107
|
-
maxCost?: number;
|
|
108
|
-
maxTimeMs?: number;
|
|
109
|
-
usedTokens: number;
|
|
110
|
-
usedCost: number;
|
|
111
|
-
totalCallCount: number;
|
|
112
|
-
};
|
|
113
|
-
calls: Array<{
|
|
114
|
-
id: number;
|
|
115
|
-
opts: AgentCallOpts;
|
|
116
|
-
status: "pending" | "running" | "done";
|
|
117
|
-
attempts: number;
|
|
118
|
-
result?: AgentResult;
|
|
119
|
-
sessionId?: string;
|
|
120
|
-
sessionFile?: string;
|
|
121
|
-
traceNode: ExecutionTraceNode;
|
|
122
|
-
}>;
|
|
123
|
-
trace: ExecutionTraceNode[];
|
|
124
|
-
errorLogs: WorkerLogEntry[];
|
|
125
|
-
error?: string;
|
|
126
|
-
scriptResult?: unknown;
|
|
127
|
-
};
|
|
128
|
-
meta: {
|
|
129
|
-
startedAt: string;
|
|
130
|
-
completedAt?: string;
|
|
131
|
-
workerErrorCount?: number;
|
|
132
|
-
scriptErrorCount?: number;
|
|
133
|
-
};
|
|
134
|
-
}
|
|
76
|
+
import {
|
|
77
|
+
DEFAULT_SAVE_MIN_INTERVAL_MS,
|
|
78
|
+
DEFAULT_STATE_MAX_RUNS,
|
|
79
|
+
} from "@zhushanwen/subagent-core/orchestration/file-run-store.ts";
|
|
80
|
+
import { getLogger } from "@zhushanwen/subagent-core/core/logger.ts";
|
|
81
|
+
|
|
82
|
+
import { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
|
|
83
|
+
import {
|
|
84
|
+
SNAPSHOT_VERSION,
|
|
85
|
+
fromRunSnapshot,
|
|
86
|
+
toRunSnapshot,
|
|
87
|
+
type RunSnapshot,
|
|
88
|
+
} from "@zhushanwen/subagent-core/orchestration/run-snapshot.ts";
|
|
135
89
|
|
|
136
90
|
// ── Workflow-record self-describing entry (W17, D4) ─────────
|
|
137
91
|
|
|
@@ -147,7 +101,7 @@ export const WORKFLOW_RECORD_CUSTOM_TYPE = "workflow-record";
|
|
|
147
101
|
*
|
|
148
102
|
* = 完整 RunSnapshot 快照(runId/status/calls/trace 等全部重建需要的字段)+ 版本号。
|
|
149
103
|
* 读取方无需逆向解析 state 文件或指针(D4 自描述原则);snapshot 内部自带 D-5
|
|
150
|
-
* snapshotVersion guard(
|
|
104
|
+
* snapshotVersion guard(fromRunSnapshot 检查),entry 层 v 与 snapshot 层 v 是两级
|
|
151
105
|
* 独立版本(entry schema 演化 vs 快照格式演化)。
|
|
152
106
|
*/
|
|
153
107
|
// 模块内类型(不导出:无外部消费方,fallow unused_types/private_type_leaks 双轨判定;
|
|
@@ -166,117 +120,25 @@ function toWorkflowRecordEntryData(snapshot: RunSnapshot): WorkflowRecordEntryDa
|
|
|
166
120
|
return { v: 1, snapshot, updatedAt: new Date().toISOString() };
|
|
167
121
|
}
|
|
168
122
|
|
|
169
|
-
// ── Serialization
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
state: {
|
|
177
|
-
status: run.state.status,
|
|
178
|
-
reason: run.state.reason,
|
|
179
|
-
budget: {
|
|
180
|
-
maxTokens: run.state.budget.maxTokens,
|
|
181
|
-
maxCost: run.state.budget.maxCost,
|
|
182
|
-
maxTimeMs: run.state.budget.maxTimeMs,
|
|
183
|
-
usedTokens: run.state.budget.usedTokens,
|
|
184
|
-
usedCost: run.state.budget.usedCost,
|
|
185
|
-
totalCallCount: run.state.budget.totalCallCount,
|
|
186
|
-
},
|
|
187
|
-
calls: Array.from(run.state.calls.values()).map((c) => {
|
|
188
|
-
// strip live(同 trace 序列化,不持久化运行期对象)
|
|
189
|
-
const { live: _live, ...traceNodeRest } = c.traceNode;
|
|
190
|
-
return {
|
|
191
|
-
id: c.id,
|
|
192
|
-
opts: c.opts,
|
|
193
|
-
status: c.status,
|
|
194
|
-
attempts: c.attempts,
|
|
195
|
-
result: c.result,
|
|
196
|
-
sessionId: c.sessionId,
|
|
197
|
-
sessionFile: c.sessionFile,
|
|
198
|
-
traceNode: traceNodeRest,
|
|
199
|
-
};
|
|
200
|
-
}),
|
|
201
|
-
// trace 节点浅拷贝时 strip live 字段——ExecutionRecord 含可变 turns[]/controller,
|
|
202
|
-
// 不适合序列化;live 是运行期对象(done 时由 dispatchAgentCall 清除,重跑时重建)。
|
|
203
|
-
trace: run.state.trace.toArray().map(({ live: _live, ...rest }) => rest),
|
|
204
|
-
errorLogs: run.state.errorLogs,
|
|
205
|
-
error: run.state.error,
|
|
206
|
-
scriptResult: run.state.scriptResult,
|
|
207
|
-
},
|
|
208
|
-
meta: run.meta,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* 反序列化快照为 WorkflowRun。D-5:版本不匹配返回 null(旧 session)。
|
|
214
|
-
*/
|
|
215
|
-
function deserializeRun(snapshot: RunSnapshot): WorkflowRun | null {
|
|
216
|
-
// D-5 version guard
|
|
217
|
-
if (snapshot.v !== SNAPSHOT_VERSION) return null;
|
|
218
|
-
|
|
219
|
-
const budget = new Budget({
|
|
220
|
-
maxTokens: snapshot.state.budget.maxTokens,
|
|
221
|
-
maxCost: snapshot.state.budget.maxCost,
|
|
222
|
-
maxTimeMs: snapshot.state.budget.maxTimeMs,
|
|
223
|
-
usedTokens: snapshot.state.budget.usedTokens,
|
|
224
|
-
usedCost: snapshot.state.budget.usedCost,
|
|
225
|
-
});
|
|
226
|
-
budget.totalCallCount = snapshot.state.budget.totalCallCount;
|
|
227
|
-
|
|
228
|
-
const calls = new Map<number, AgentCall>();
|
|
229
|
-
for (const c of snapshot.state.calls) {
|
|
230
|
-
const call = new AgentCall(c.id, c.opts, c.traceNode);
|
|
231
|
-
call.status = c.status;
|
|
232
|
-
call.attempts = c.attempts;
|
|
233
|
-
// Restore result directly — bypasses markRunning/markDone state-machine guards
|
|
234
|
-
// because we're reconstructing a known-good persisted state, not transitioning.
|
|
235
|
-
if (c.result !== undefined) {
|
|
236
|
-
call.result = c.result;
|
|
237
|
-
}
|
|
238
|
-
if (c.sessionId !== undefined) {
|
|
239
|
-
call.setSessionId(c.sessionId);
|
|
240
|
-
}
|
|
241
|
-
if (c.sessionFile !== undefined) {
|
|
242
|
-
call.setSessionFile(c.sessionFile);
|
|
243
|
-
}
|
|
244
|
-
calls.set(c.id, call);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
const trace = Trace.fromArray(snapshot.state.trace);
|
|
248
|
-
|
|
249
|
-
const state: RunState = {
|
|
250
|
-
status: snapshot.state.status,
|
|
251
|
-
reason: snapshot.state.reason,
|
|
252
|
-
budget,
|
|
253
|
-
calls,
|
|
254
|
-
trace,
|
|
255
|
-
errorLogs: snapshot.state.errorLogs,
|
|
256
|
-
error: snapshot.state.error,
|
|
257
|
-
scriptResult: snapshot.state.scriptResult,
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
const meta: WorkflowRunMeta = {
|
|
261
|
-
startedAt: snapshot.meta.startedAt,
|
|
262
|
-
completedAt: snapshot.meta.completedAt,
|
|
263
|
-
workerErrorCount: snapshot.meta.workerErrorCount,
|
|
264
|
-
scriptErrorCount: snapshot.meta.scriptErrorCount,
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
// WorkflowRun.reconstruct 跳过 I1 校验——持久化的 running 状态没有 worker
|
|
268
|
-
// (进程被杀后 worker 不可能还活着),违反 I1。D-4 kill-9 恢复在 session_start
|
|
269
|
-
// 时把残留 running 转 done,failed,恢复 I1(见 index.ts session_start handler)。
|
|
270
|
-
return WorkflowRun.reconstruct(snapshot.runId, snapshot.spec, state, meta);
|
|
271
|
-
}
|
|
123
|
+
// ── Serialization → core codec(下沉收口 D4)──────────────────
|
|
124
|
+
//
|
|
125
|
+
// serializeRun/deserializeRun 本地投影已退役:快照投影/重水合/版本 guard 单源消费
|
|
126
|
+
// core run-snapshot codec(toRunSnapshot/fromRunSnapshot)。键序与 strip live 语义
|
|
127
|
+
// 与原本地实现逐字节一致(⛔5 快照锚定:__tests__/jsonl-run-store-snapshot-codec.test.ts);
|
|
128
|
+
// 唯一投影差异 = spec.budgetRef 剔除(codec 单源裁决,嵌套 run 落盘少一脏字段,
|
|
129
|
+
// 性质同 strip live——同偏差登记)。
|
|
272
130
|
|
|
273
131
|
/** workflow-record entry → 重建 run 写入 recordRuns(v1 entry guard + D-5 版本不匹配
|
|
274
132
|
* 跳过;同 runId 后写覆盖 = 最后一条 entry 胜出)。返回 entry 是否命中该类型。
|
|
275
133
|
*
|
|
276
|
-
*
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
*
|
|
134
|
+
* 版本可见性分层(D4 裁决③宿主侧落地):v 不匹配(v1 存量/未来版本)→ 静默跳过
|
|
135
|
+
* (既有语义);v 匹配但形状损坏(codec 返回 undefined——codec 形状校验不抛)→
|
|
136
|
+
* warn 留证。
|
|
137
|
+
*
|
|
138
|
+
* [SO-DATA-2] per-entry 隔离:残缺 entry(截断/手改/半写)不得让 loadAll 返回空。
|
|
139
|
+
* 原实现靠「deserializeRun 抛 TypeError → catch → warn」;codec 收敛后形状损坏
|
|
140
|
+
* 走 undefined 返回(warn 分支保持同等留证),try/catch 保留兜底 codec 唯一抛点
|
|
141
|
+
* (done 快照缺 reason 的 WorkflowRun I2 不变式)。
|
|
280
142
|
*/
|
|
281
143
|
function collectRecordRun(entry: CustomEntry, entryIndex: number, recordRuns: Map<string, WorkflowRun>): boolean {
|
|
282
144
|
if (entry.customType !== WORKFLOW_RECORD_CUSTOM_TYPE) return false;
|
|
@@ -284,9 +146,17 @@ function collectRecordRun(entry: CustomEntry, entryIndex: number, recordRuns: Ma
|
|
|
284
146
|
const data = entry.data as WorkflowRecordEntryData | undefined;
|
|
285
147
|
if (data?.v !== 1 || !data.snapshot) return true;
|
|
286
148
|
try {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
149
|
+
if (data.snapshot.v === SNAPSHOT_VERSION) {
|
|
150
|
+
const run = fromRunSnapshot(data.snapshot);
|
|
151
|
+
if (run) {
|
|
152
|
+
recordRuns.set(run.runId, run); // 后写覆盖 = 最后一条 entry 胜出
|
|
153
|
+
} else {
|
|
154
|
+
logger.warn(
|
|
155
|
+
`[subagent-workflow] workflow-record entry #${entryIndex} corrupted, skipped run rebuild: snapshot shape invalid`,
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// D-5: 版本不匹配 = old snapshot format / future version — skip silently
|
|
290
160
|
} catch (err) {
|
|
291
161
|
const reason = err instanceof Error ? err.message : String(err);
|
|
292
162
|
logger.warn(
|
|
@@ -325,24 +195,24 @@ function collectEntrySources(entries: SessionEntry[]): {
|
|
|
325
195
|
return { recordRuns, pointers };
|
|
326
196
|
}
|
|
327
197
|
|
|
328
|
-
/** 旧 link 指针指向的 state 文件读取:末行 JSON
|
|
329
|
-
* (单文件失败不阻断其余 run
|
|
198
|
+
/** 旧 link 指针指向的 state 文件读取:末行 JSON 解析重建。损坏/不可读/版本不匹配
|
|
199
|
+
* 返回 null(单文件失败不阻断其余 run 重建;D-5 静默跳过语义保持)。 */
|
|
330
200
|
async function loadRunFromStateFile(filePath: string): Promise<WorkflowRun | null> {
|
|
331
201
|
try {
|
|
332
202
|
const content = await fs.promises.readFile(filePath, "utf8");
|
|
333
203
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
334
204
|
const lastLine = lines[lines.length - 1];
|
|
335
205
|
if (!lastLine) return null;
|
|
336
|
-
const parsed = JSON.parse(lastLine)
|
|
337
|
-
// D-5:
|
|
338
|
-
return
|
|
206
|
+
const parsed: unknown = JSON.parse(lastLine);
|
|
207
|
+
// D-5: undefined = old format / version mismatch / corrupt shape — skip silently
|
|
208
|
+
return fromRunSnapshot(parsed) ?? null;
|
|
339
209
|
} catch {
|
|
340
210
|
// Corrupt/unreadable state file — skip (don't crash loadAll).
|
|
341
211
|
return null;
|
|
342
212
|
}
|
|
343
213
|
}
|
|
344
214
|
|
|
345
|
-
// ── State file retention (
|
|
215
|
+
// ── State file retention (OR-5 ⑥b, default-on) ───────────────
|
|
346
216
|
|
|
347
217
|
/** run state 文件名 glob:runId 形如 `wf-<ts>-<rand>`(lifecycle.ts 生成),只删命中者。
|
|
348
218
|
* 同目录可能存在的非 state 文件(及 session JSONL——在父目录,本就不在扫描范围)永不碰。 */
|
|
@@ -412,16 +282,21 @@ const logger = getLogger("subagents");
|
|
|
412
282
|
* save 去抖窗口默认值(ms)。区间 100-250 内取值——agent-call 间隔秒级,
|
|
413
283
|
* 200ms 足以合并同一 call 周期内的多次状态 mutation,又不至于让崩溃窗口
|
|
414
284
|
* (未 flush 的 running 尾部丢失,等价崩溃链由 kill-9 恢复收编)明显放大。
|
|
415
|
-
*
|
|
285
|
+
* 模块私有:无外部消费方(构造参数 saveDebounceMs 可调窗口,测试经其注入)。
|
|
416
286
|
*/
|
|
417
|
-
|
|
287
|
+
const DEFAULT_SAVE_DEBOUNCE_MS = 200;
|
|
418
288
|
|
|
419
289
|
/**
|
|
420
|
-
*
|
|
290
|
+
* 磁盘保留清理的上限 env(OR-5 ⑥b 默认开):workflow-state 目录内 run state
|
|
291
|
+
* 文件上限。
|
|
421
292
|
*
|
|
422
|
-
*
|
|
423
|
-
*
|
|
424
|
-
*
|
|
293
|
+
* 解析语义与 core FileRunStore envName 通道一致(两实现面单源 {@link
|
|
294
|
+
* DEFAULT_STATE_MAX_RUNS}):
|
|
295
|
+
* - 未设/空 → 按默认上限 {@link DEFAULT_STATE_MAX_RUNS} 裁剪(**默认开**——
|
|
296
|
+
* OR-5 修复前的 opt-in「默认关」正是跨 run 无界累积缺陷本身);
|
|
297
|
+
* - 有限正数 → 上限 = env 值(显式覆盖默认值);
|
|
298
|
+
* - 非法值(非有限数/≤0)→ 不清理(显式 opt-out 通道:用户意图不明时不动
|
|
299
|
+
* 磁盘,对齐 prune 内部「任何失败都不抛」的保守哲学)。
|
|
425
300
|
*
|
|
426
301
|
* 用 XYZ_ 前缀而非 PI_:本 env 是 pi 进程内读的配置 env,xyz-agent 桌面 spawn 链按
|
|
427
302
|
* ENV_WHITELIST_PREFIXES(只有 XYZ_ 等)过滤,PI_ 前缀在桌面场景被静默丢弃——
|
|
@@ -429,10 +304,10 @@ export const DEFAULT_SAVE_DEBOUNCE_MS = 200;
|
|
|
429
304
|
*/
|
|
430
305
|
export const STATE_MAX_RUNS_ENV = "XYZ_SUBAGENT_STATE_MAX_RUNS";
|
|
431
306
|
|
|
432
|
-
/** 解析保留上限;env
|
|
307
|
+
/** 解析保留上限;env 未设/空 → 默认上限,显式非法/≤0 → undefined(不清理)。 */
|
|
433
308
|
function getEnvStateMaxRuns(): number | undefined {
|
|
434
309
|
const raw = process.env[STATE_MAX_RUNS_ENV];
|
|
435
|
-
if (
|
|
310
|
+
if (raw === undefined || raw === "") return DEFAULT_STATE_MAX_RUNS;
|
|
436
311
|
const parsed = Number(raw);
|
|
437
312
|
if (!Number.isFinite(parsed) || parsed <= 0) return undefined;
|
|
438
313
|
return parsed;
|
|
@@ -453,7 +328,7 @@ interface PendingSaveBatch {
|
|
|
453
328
|
settlers: Array<{ resolve: () => void; reject: (e: unknown) => void }>;
|
|
454
329
|
}
|
|
455
330
|
|
|
456
|
-
|
|
331
|
+
interface JsonlRunStoreOptions {
|
|
457
332
|
/** Session directory root (state files live under <sessionDir>/workflow-state/). */
|
|
458
333
|
sessionDir: string;
|
|
459
334
|
/** Pi ExtensionAPI for workflow-record appendEntry writes (optional for testing). */
|
|
@@ -462,6 +337,12 @@ export interface JsonlRunStoreOptions {
|
|
|
462
337
|
ctx?: ExtensionContext;
|
|
463
338
|
/** save 去抖窗口(ms),默认 {@link DEFAULT_SAVE_DEBOUNCE_MS}。 */
|
|
464
339
|
saveDebounceMs?: number;
|
|
340
|
+
/**
|
|
341
|
+
* workflow-record entry append 节流最小间隔(ms);0 = 禁用节流。缺省
|
|
342
|
+
* {@link DEFAULT_SAVE_MIN_INTERVAL_MS}(单源复用 core 常量)。测试经此注入小窗口
|
|
343
|
+
* (fake timers 推进)。
|
|
344
|
+
*/
|
|
345
|
+
entryAppendMinIntervalMs?: number;
|
|
465
346
|
}
|
|
466
347
|
|
|
467
348
|
export class JsonlRunStore {
|
|
@@ -469,10 +350,19 @@ export class JsonlRunStore {
|
|
|
469
350
|
private readonly pi?: ExtensionAPI;
|
|
470
351
|
private readonly ctx?: ExtensionContext;
|
|
471
352
|
private readonly saveDebounceMs: number;
|
|
353
|
+
/** workflow-record entry append 节流最小间隔(ms),0 = 禁用。 */
|
|
354
|
+
private readonly entryAppendMinIntervalMs: number;
|
|
472
355
|
/** per-runId 去抖批(热路径)。 */
|
|
473
356
|
private readonly pending = new Map<string, PendingSaveBatch>();
|
|
474
357
|
/** 本实例已至少成功发起过一次 flush 的 runId(冷/热路径判据)。 */
|
|
475
358
|
private readonly writtenOnce = new Set<string>();
|
|
359
|
+
/**
|
|
360
|
+
* per-runId 上次 workflow-record entry append 时刻(节流判据,时间源 Date.now()——
|
|
361
|
+
* fake timers 下可推进)。终态 append 后删(终态后 runId 不再 save);残留条目
|
|
362
|
+
* 只出现在 running 中 run 消失场景,单条可忽略(对齐 core FileRunStore.lastSavedAt
|
|
363
|
+
* 的取舍先例)。
|
|
364
|
+
*/
|
|
365
|
+
private readonly lastEntryAppendAt = new Map<string, number>();
|
|
476
366
|
/**
|
|
477
367
|
* per-runId 串行 flush 链。同 runId 的 flush 排队顺序执行(排队不跳过——
|
|
478
368
|
* 跳过会丢最新状态且打破后写覆盖前写的单调性),不同 runId 互不阻塞。
|
|
@@ -488,6 +378,10 @@ export class JsonlRunStore {
|
|
|
488
378
|
this.pi = opts.pi;
|
|
489
379
|
this.ctx = opts.ctx;
|
|
490
380
|
this.saveDebounceMs = opts.saveDebounceMs ?? DEFAULT_SAVE_DEBOUNCE_MS;
|
|
381
|
+
this.entryAppendMinIntervalMs = Math.max(
|
|
382
|
+
0,
|
|
383
|
+
opts.entryAppendMinIntervalMs ?? DEFAULT_SAVE_MIN_INTERVAL_MS,
|
|
384
|
+
);
|
|
491
385
|
}
|
|
492
386
|
|
|
493
387
|
/** State directory: <sessionDir>/workflow-state/ */
|
|
@@ -646,16 +540,36 @@ export class JsonlRunStore {
|
|
|
646
540
|
throw err;
|
|
647
541
|
}
|
|
648
542
|
// serialize-at-flush:写 flush 时刻的最新聚合状态(latestRun 语义)
|
|
649
|
-
const snapshot =
|
|
543
|
+
const snapshot = toRunSnapshot(run);
|
|
650
544
|
await fs.promises.writeFile(filePath, JSON.stringify(snapshot) + "\n", "utf8");
|
|
651
|
-
// W17 [D4]
|
|
652
|
-
//
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
//
|
|
545
|
+
// W17 [D4]:成功 flush 同步 append 自描述 workflow-record entry(同一份 snapshot,
|
|
546
|
+
// entry 与 state 文件内容一致)。pi 文件是 workflow 数据持久化权威(loadAll 优先
|
|
547
|
+
// 从 entry 重建),state 文件降级纯性能缓存。pi 未注入(测试)时跳过。
|
|
548
|
+
// [B-1] entry append 节流(语义对齐 core FileRunStore.save OR-5 ⑥a):running
|
|
549
|
+
// 中间态距上次 append 不足间隔 → 跳过(pi session JSONL append-only,节流前
|
|
550
|
+
// 每次 flush 全量 append 累积单 run O(n²) 磁盘);终态永不节流(最终状态必进
|
|
551
|
+
// pi 权威文件);间隔 0 禁用。判据在 append 成功后更新——本调用点位于 writeFile
|
|
552
|
+
// 成功之后,writeFile 抛错时判据不更新,不吞下一次重试机会。
|
|
553
|
+
const isTerminal = run.state.status !== "running";
|
|
554
|
+
const now = Date.now();
|
|
555
|
+
const lastAppendAt = this.lastEntryAppendAt.get(runId);
|
|
556
|
+
if (
|
|
557
|
+
this.entryAppendMinIntervalMs <= 0 ||
|
|
558
|
+
isTerminal ||
|
|
559
|
+
lastAppendAt === undefined ||
|
|
560
|
+
now - lastAppendAt >= this.entryAppendMinIntervalMs
|
|
561
|
+
) {
|
|
562
|
+
this.pi?.appendEntry(
|
|
563
|
+
WORKFLOW_RECORD_CUSTOM_TYPE,
|
|
564
|
+
toWorkflowRecordEntryData(snapshot),
|
|
565
|
+
);
|
|
566
|
+
if (isTerminal) {
|
|
567
|
+
this.lastEntryAppendAt.delete(runId);
|
|
568
|
+
} else {
|
|
569
|
+
this.lastEntryAppendAt.set(runId, now);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// OR-5 ⑥b 磁盘保留清理(默认开):新 run state 文件首写成功后触发(rollbackFirstWrite
|
|
659
573
|
// 即 save() 冷路径传入的 isFirstWrite——「本实例首次写该 runId」≈ 新文件落盘时刻,
|
|
660
574
|
// 每个 run 只清一次,热路径 flush 不重复扫描目录)。prune 内部吞错不抛,
|
|
661
575
|
// 在串行链上 await:save 返回即清理已定,测试可同步断言目录终态。
|
|
@@ -711,15 +625,13 @@ export class JsonlRunStore {
|
|
|
711
625
|
|
|
712
626
|
private async doDispose(): Promise<void> {
|
|
713
627
|
// 同步置位:阻断新 save 进入去抖/冷路径(R5 no-op 分支接住 shutdown 后
|
|
714
|
-
// in-flight 链的迟到 save
|
|
628
|
+
// in-flight 链的迟到 save)。置位必须先于 flushPendingSaves——async 函数体
|
|
629
|
+
// 在调用时同步执行到第一个 await,批收集发生在置位后的同一同步段,时序与
|
|
630
|
+
// 折叠前的内联收集逐分支等值。
|
|
715
631
|
this.disposed = true;
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
this.pending.delete(runId);
|
|
720
|
-
flushes.push(this.enqueueFlush(runId, batch.latestRun, batch.settlers, false));
|
|
721
|
-
}
|
|
722
|
-
await Promise.allSettled(flushes);
|
|
632
|
+
// 复用 flushPendingSaves(批收集循环与 await allSettled 与折叠前内联实现逐行等价;
|
|
633
|
+
// flushPendingSaves 自身不动 disposed——dispose 语义仍由本方法的置位与缓存 Promise 承担)
|
|
634
|
+
await this.flushPendingSaves();
|
|
723
635
|
// await 全部 in-flight 链(ES4:flush 全部落定后才返回)
|
|
724
636
|
await Promise.allSettled(Array.from(this.chains.values()));
|
|
725
637
|
}
|
|
@@ -729,8 +641,8 @@ export class JsonlRunStore {
|
|
|
729
641
|
*
|
|
730
642
|
* 1. 优先扫描自描述 `workflow-record` entry(重建源——同一 runId 多条时最后一条
|
|
731
643
|
* 胜出,等价「最后一次成功 flush」)。entry 层 v1 guard:不认识的版本跳过而非
|
|
732
|
-
* 猜测;snapshot 层 D-5 snapshotVersion guard 保持(版本不匹配 →
|
|
733
|
-
* 返回
|
|
644
|
+
* 猜测;snapshot 层 D-5 snapshotVersion guard 保持(版本不匹配 → fromRunSnapshot
|
|
645
|
+
* 返回 undefined → 跳过,不做兼容迁移)。
|
|
734
646
|
* 2. 旧 `workflow-state-link` 指针 entry 兼容读取(优先级低——存量 run 不静默
|
|
735
647
|
* 丢失,父文档 #9 踩坑):entry 未覆盖的 runId 经指针读 state 文件最后行。
|
|
736
648
|
*
|