@selesai/code 0.5.28 → 0.5.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +117 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -3
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +11 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +10 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/llama/provider.d.ts.map +1 -1
- package/dist/core/llama/provider.js +8 -3
- package/dist/core/llama/provider.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +20 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +13 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +24 -11
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +15 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +66 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
- package/dist/extensions/pi-intercom/README.md +102 -39
- package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
- package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
- package/dist/extensions/pi-intercom/broker/client.ts +315 -12
- package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
- package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
- package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
- package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
- package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
- package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
- package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
- package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
- package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
- package/dist/extensions/pi-intercom/config.test.ts +93 -0
- package/dist/extensions/pi-intercom/config.ts +55 -6
- package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
- package/dist/extensions/pi-intercom/cwd.ts +31 -0
- package/dist/extensions/pi-intercom/extension-api.ts +44 -0
- package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
- package/dist/extensions/pi-intercom/format-context.ts +32 -0
- package/dist/extensions/pi-intercom/index.ts +742 -145
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
- package/dist/extensions/pi-intercom/package.json +15 -5
- package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
- package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
- package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
- package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
- package/dist/extensions/pi-intercom/types.ts +94 -4
- package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
- package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
- package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
- package/dist/extensions/pi-subagents/CHANGELOG.md +85 -0
- package/dist/extensions/pi-subagents/LICENSE +21 -0
- package/dist/extensions/pi-subagents/README.md +146 -52
- package/dist/extensions/pi-subagents/agents/architect.md +1 -0
- package/dist/extensions/pi-subagents/agents/builder.md +1 -0
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +3 -3
- package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +21 -989
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +256 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +430 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +282 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +71 -30
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
- package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
- package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +16 -12
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +17 -7
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +31 -6
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +8 -7
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +63 -16
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +29 -4
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +29 -6
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +372 -28
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +143 -43
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +527 -247
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +426 -123
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +15 -7
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
- package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
- package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +155 -10
- package/dist/extensions/pi-subagents/src/shared/utils.ts +73 -4
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +5 -0
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
- package/dist/extensions/pi-subagents/src/tui/render.ts +27 -28
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +348 -7
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +213 -13
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +118 -12
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +850 -7
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +102 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +11 -11
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +10 -2
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +46 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +34 -2
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +3 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +43 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +10 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +4 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -64
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +14 -5
- package/docs/environment-variables.md +86 -0
- package/docs/extensions.md +15 -5
- package/docs/index.md +1 -0
- package/docs/models.md +9 -2
- package/docs/providers.md +21 -2
- package/docs/rpc.md +23 -6
- package/docs/session-format.md +2 -0
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -13
- package/examples/extensions/custom-compaction.ts +5 -2
- package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +11 -3
- package/examples/extensions/message-renderer.ts +3 -3
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +5 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/12-full-control.ts +3 -1
- package/package.json +15 -6
- package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
|
@@ -44,11 +44,15 @@ describe("resolveIntercomBridgeMode", () => {
|
|
|
44
44
|
|
|
45
45
|
describe("resolveIntercomSessionTarget", () => {
|
|
46
46
|
it("prefers an explicit session name", () => {
|
|
47
|
-
assert.equal(resolveIntercomSessionTarget("planner", "session-12345678"), "planner");
|
|
47
|
+
assert.equal(resolveIntercomSessionTarget("planner", "session-12345678", "session-stableabcdef"), "planner");
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
it("uses a runtime-only subagent chat alias when unnamed", () => {
|
|
51
|
-
assert.equal(resolveIntercomSessionTarget(undefined, "session-12345678"), "subagent-chat-12345678");
|
|
51
|
+
assert.equal(resolveIntercomSessionTarget(undefined, "session-12345678", ""), "subagent-chat-12345678");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("uses the current pi-intercom runtime id for unnamed fallback when present", () => {
|
|
55
|
+
assert.equal(resolveIntercomSessionTarget(undefined, "session-12345678", "session-stableabcdef"), "subagent-chat-stableab");
|
|
52
56
|
});
|
|
53
57
|
});
|
|
54
58
|
|
|
@@ -94,10 +98,21 @@ describe("resolveIntercomBridge", () => {
|
|
|
94
98
|
});
|
|
95
99
|
|
|
96
100
|
assert.equal(bridge.active, true);
|
|
101
|
+
assert.equal(bridge.resultDelivery, true);
|
|
97
102
|
assert.equal(bridge.orchestratorTarget, "main");
|
|
98
103
|
assert.equal(bridge.extensionDir, NATIVE_INTERCOM_EXTENSION_DIR);
|
|
99
104
|
});
|
|
100
105
|
|
|
106
|
+
it("can disable external grouped-result delivery without disabling supervisor coordination", () => {
|
|
107
|
+
const bridge = resolveIntercomBridge({
|
|
108
|
+
config: { mode: "always", resultDelivery: false },
|
|
109
|
+
context: "fresh",
|
|
110
|
+
orchestratorTarget: "main",
|
|
111
|
+
});
|
|
112
|
+
assert.equal(bridge.active, true);
|
|
113
|
+
assert.equal(bridge.resultDelivery, false);
|
|
114
|
+
});
|
|
115
|
+
|
|
101
116
|
it("stays inactive for fresh context when mode is fork-only", () => {
|
|
102
117
|
const bridge = resolveIntercomBridge({
|
|
103
118
|
config: { mode: "fork-only" },
|
|
@@ -144,6 +159,7 @@ describe("applyIntercomBridgeToAgent", () => {
|
|
|
144
159
|
const activeBridge: IntercomBridgeState = {
|
|
145
160
|
active: true,
|
|
146
161
|
mode: "always",
|
|
162
|
+
resultDelivery: true,
|
|
147
163
|
orchestratorTarget: "main",
|
|
148
164
|
extensionDir: NATIVE_INTERCOM_EXTENSION_DIR,
|
|
149
165
|
instruction: "Intercom orchestration channel:\n- Need a decision or blocked: contact_supervisor({ reason: \"need_decision\", message: \"<question>\" })\n- Blocked/update: contact_supervisor({ reason: \"progress_update\", message: \"UPDATE: <summary>\" })",
|
|
@@ -5,7 +5,7 @@ import * as path from "node:path";
|
|
|
5
5
|
import { afterEach, describe, it } from "node:test";
|
|
6
6
|
import registerFanoutChildSubagentExtension from "../../src/extension/fanout-child.ts";
|
|
7
7
|
import { createSubagentExecutor } from "../../src/runs/foreground/subagent-executor.ts";
|
|
8
|
-
import { createNestedRoute, projectNestedEvents, readNestedControlRequests, readNestedControlResults, writeNestedControlRequest, writeNestedControlResult, writeNestedEvent } from "../../src/runs/shared/nested-events.ts";
|
|
8
|
+
import { createNestedRoute, findNestedControlResult, projectNestedEvents, readNestedControlRequests, readNestedControlResults, snapshotNestedEventFiles, writeNestedControlRequest, writeNestedControlResult, writeNestedEvent } from "../../src/runs/shared/nested-events.ts";
|
|
9
9
|
import {
|
|
10
10
|
SUBAGENT_CHILD_ENV,
|
|
11
11
|
SUBAGENT_FANOUT_CHILD_ENV,
|
|
@@ -129,6 +129,25 @@ async function waitFor(predicate: () => boolean, timeoutMs = 1_000): Promise<voi
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
describe("nested control routing", () => {
|
|
132
|
+
it("finds a control result without considering files present before its request", () => {
|
|
133
|
+
const route = createNestedRoute("root-targeted-result");
|
|
134
|
+
routeRoots.push(path.dirname(route.eventSink));
|
|
135
|
+
const requestedAt = Date.now();
|
|
136
|
+
writeNestedControlResult(route, { ts: requestedAt, requestId: "older", targetRunId: "child", ok: true, message: "older result" });
|
|
137
|
+
writeNestedEvent(route, {
|
|
138
|
+
type: "subagent.nested.updated",
|
|
139
|
+
ts: requestedAt + 1,
|
|
140
|
+
parentRunId: route.rootRunId,
|
|
141
|
+
child: { id: "child", parentRunId: route.rootRunId, depth: 1, path: [], state: "running" },
|
|
142
|
+
});
|
|
143
|
+
const ignoredFiles = snapshotNestedEventFiles(route);
|
|
144
|
+
writeNestedControlResult(route, { ts: requestedAt - 1, requestId: "target", targetRunId: "child", ok: true, message: "target result" });
|
|
145
|
+
|
|
146
|
+
assert.equal(findNestedControlResult(route, "target", "child", ignoredFiles)?.message, "target result");
|
|
147
|
+
assert.equal(findNestedControlResult(route, "older", "child", ignoredFiles), undefined);
|
|
148
|
+
assert.equal(readNestedControlResults(route).length, 2);
|
|
149
|
+
});
|
|
150
|
+
|
|
132
151
|
it("routes interrupt to an explicit nested id through the control inbox", async () => {
|
|
133
152
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-nested-control-"));
|
|
134
153
|
try {
|
|
@@ -157,14 +157,18 @@ describe("nested event parsing and projection", () => {
|
|
|
157
157
|
ts: 200,
|
|
158
158
|
parentRunId: "root-run",
|
|
159
159
|
parentStepIndex: 1,
|
|
160
|
-
child: {
|
|
160
|
+
child: {
|
|
161
|
+
...child("nested-a", "running", 200),
|
|
162
|
+
currentTool: "read",
|
|
163
|
+
runtimeAcknowledgedExtensions: { version: 1, source: "child-runtime", ids: ["ext.ok", "bad/path", "ext.ok"], omitted: 1 },
|
|
164
|
+
},
|
|
161
165
|
});
|
|
162
166
|
writeNestedEvent(route, {
|
|
163
167
|
type: "subagent.nested.completed",
|
|
164
168
|
ts: 300,
|
|
165
169
|
parentRunId: "root-run",
|
|
166
170
|
parentStepIndex: 1,
|
|
167
|
-
child: child("nested-a", "complete", 300),
|
|
171
|
+
child: { ...child("nested-a", "complete", 300), runtimeAcknowledgedExtensions: { version: 1, source: "child-runtime", ids: ["ext.ok", "bad/path", "ext.ok"], omitted: 1 } },
|
|
168
172
|
});
|
|
169
173
|
|
|
170
174
|
const registry = projectNestedEvents(route);
|
|
@@ -172,6 +176,12 @@ describe("nested event parsing and projection", () => {
|
|
|
172
176
|
assert.equal(registry.children[0]?.id, "nested-a");
|
|
173
177
|
assert.equal(registry.children[0]?.state, "complete");
|
|
174
178
|
assert.equal(registry.children[0]?.steps?.[0]?.agent, "leaf");
|
|
179
|
+
assert.deepEqual(registry.children[0]?.runtimeAcknowledgedExtensions, {
|
|
180
|
+
version: 1,
|
|
181
|
+
source: "child-runtime",
|
|
182
|
+
ids: ["ext.ok"],
|
|
183
|
+
omitted: 1,
|
|
184
|
+
});
|
|
175
185
|
|
|
176
186
|
const job: AsyncJobState = {
|
|
177
187
|
asyncId: "root-run",
|
|
@@ -349,6 +359,24 @@ describe("nested event parsing and projection", () => {
|
|
|
349
359
|
assert.equal(summary.steps?.[0]?.processTerminal?.reason, "proof-write-failed");
|
|
350
360
|
});
|
|
351
361
|
|
|
362
|
+
it("sanitizes runtime acknowledged extensions in nested status summaries", () => {
|
|
363
|
+
const summary = nestedSummaryFromAsyncStatus({
|
|
364
|
+
runId: "child-run",
|
|
365
|
+
mode: "single",
|
|
366
|
+
state: "complete",
|
|
367
|
+
startedAt: 1,
|
|
368
|
+
runtimeAcknowledgedExtensions: { version: 1, source: "child-runtime", ids: ["/Users/alice/.secret-extension", "ok-ext", "x".repeat(5000)], omitted: 0 } as never,
|
|
369
|
+
steps: [{
|
|
370
|
+
agent: "worker",
|
|
371
|
+
status: "complete",
|
|
372
|
+
runtimeAcknowledgedExtensions: { version: 1, source: "child-runtime", ids: ["C:/Users/alice/secret"], omitted: 0 } as never,
|
|
373
|
+
}],
|
|
374
|
+
}, "/tmp/child-run", { id: "child-run", parentRunId: "parent-run", depth: 1, mode: "single", ts: 2 });
|
|
375
|
+
|
|
376
|
+
assert.deepEqual(summary.runtimeAcknowledgedExtensions?.ids, ["ok-ext"]);
|
|
377
|
+
assert.equal(summary.steps?.[0]?.runtimeAcknowledgedExtensions, undefined);
|
|
378
|
+
});
|
|
379
|
+
|
|
352
380
|
it("removes evicted status files without replaying completed children", () => {
|
|
353
381
|
const route = trackRoute();
|
|
354
382
|
for (let index = 0; index < 1000; index++) {
|
|
@@ -140,6 +140,12 @@ describe("registerSubagentNotify", () => {
|
|
|
140
140
|
assert.equal(sent.length, 1);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
it("suppresses local delivery after an acknowledged grouped intercom relay", async () => {
|
|
144
|
+
const { notifier, sent } = createPi("session-a");
|
|
145
|
+
assert.equal(await notifier.deliver(completionResult({ id: "intercom-delivered", intercomDelivered: true })), true);
|
|
146
|
+
assert.equal(sent.length, 0);
|
|
147
|
+
});
|
|
148
|
+
|
|
143
149
|
it("rejects a pending batch when the notifier is disposed", async () => {
|
|
144
150
|
const clock = createFakeClock();
|
|
145
151
|
const { notifier, sent } = createBatchingPi(clock);
|
|
@@ -466,10 +472,12 @@ describe("completion formatting helpers", () => {
|
|
|
466
472
|
notifier.dispose();
|
|
467
473
|
});
|
|
468
474
|
|
|
469
|
-
it("buildCompletionDetails derives paused
|
|
475
|
+
it("buildCompletionDetails derives paused and stopped statuses", () => {
|
|
470
476
|
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success: false, state: "paused", summary: "Paused after interrupt.", timestamp: 1 }).status, "paused");
|
|
471
477
|
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success: false, summary: "boom", exitCode: 1, timestamp: 1 }).status, "failed");
|
|
472
|
-
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success:
|
|
478
|
+
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success: false, summary: "terminated", exitCode: 1, processSignal: "SIGTERM", timestamp: 1 }).status, "stopped");
|
|
479
|
+
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success: false, summary: "terminated", results: [{ success: false, exitCode: 1, processSignal: "SIGTERM" }], timestamp: 1 }).status, "stopped");
|
|
480
|
+
assert.equal(buildCompletionDetails({ id: "x", agent: "w", success: true, summary: "ok", exitCode: 0, processSignal: "SIGTERM", timestamp: 1 }).status, "completed");
|
|
473
481
|
});
|
|
474
482
|
|
|
475
483
|
it("buildCompletionDetails falls back to the unknown agent label", () => {
|
|
@@ -153,6 +153,28 @@ describe("mapConcurrent", () => {
|
|
|
153
153
|
assert.ok(d2 < 20, `worker 2 should start immediately, got ${d2}ms delay`);
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
+
it("notifies scheduling settlement only after workers outliving an early rejection stop", async () => {
|
|
157
|
+
let release!: () => void;
|
|
158
|
+
const gate = new Promise<void>((resolve) => { release = resolve; });
|
|
159
|
+
const started: number[] = [];
|
|
160
|
+
let schedulingSettled = false;
|
|
161
|
+
const run = mapConcurrent([0, 1, 2], 2, async (item) => {
|
|
162
|
+
started.push(item);
|
|
163
|
+
if (item === 0) throw new Error("early rejection");
|
|
164
|
+
await gate;
|
|
165
|
+
return item;
|
|
166
|
+
}, undefined, () => { schedulingSettled = true; });
|
|
167
|
+
|
|
168
|
+
await assert.rejects(run, /early rejection/);
|
|
169
|
+
assert.equal(schedulingSettled, false);
|
|
170
|
+
release();
|
|
171
|
+
for (let attempt = 0; attempt < 20 && !schedulingSettled; attempt++) {
|
|
172
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
173
|
+
}
|
|
174
|
+
assert.equal(schedulingSettled, true);
|
|
175
|
+
assert.deepEqual(started, [0, 1, 2]);
|
|
176
|
+
});
|
|
177
|
+
|
|
156
178
|
it("respects a shared global semaphore across simultaneous calls", async () => {
|
|
157
179
|
const globalSemaphore = new Semaphore(2);
|
|
158
180
|
let running = 0;
|
|
@@ -23,8 +23,12 @@ import {
|
|
|
23
23
|
SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV,
|
|
24
24
|
SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV,
|
|
25
25
|
SUBAGENT_RUN_ID_ENV,
|
|
26
|
+
PI_INTERCOM_STABLE_ID_ENV,
|
|
27
|
+
PI_INTERCOM_SESSION_ID_ENV,
|
|
26
28
|
applyThinkingSuffix,
|
|
27
29
|
buildPiArgs,
|
|
30
|
+
projectLaunchResolvedChildExtensions,
|
|
31
|
+
resolvePiLaunchToolPlan,
|
|
28
32
|
} from "../../src/runs/shared/pi-args.ts";
|
|
29
33
|
|
|
30
34
|
const originalEnv = {
|
|
@@ -45,6 +49,10 @@ const originalEnv = {
|
|
|
45
49
|
[MCP_DIRECT_CHILD_TOOLS_ENV]: process.env[MCP_DIRECT_CHILD_TOOLS_ENV],
|
|
46
50
|
[TOOL_BUDGET_ZERO_AUTH_ENV]: process.env[TOOL_BUDGET_ZERO_AUTH_ENV],
|
|
47
51
|
[SELESAI_CODING_AGENT_PACKAGE_ROOT_ENV]: process.env[SELESAI_CODING_AGENT_PACKAGE_ROOT_ENV],
|
|
52
|
+
[PI_INTERCOM_STABLE_ID_ENV]: process.env[PI_INTERCOM_STABLE_ID_ENV],
|
|
53
|
+
[PI_INTERCOM_SESSION_ID_ENV]: process.env[PI_INTERCOM_SESSION_ID_ENV],
|
|
54
|
+
MCP_HASH_ROOT: process.env.MCP_HASH_ROOT,
|
|
55
|
+
MCP_HASH_TOKEN: process.env.MCP_HASH_TOKEN,
|
|
48
56
|
};
|
|
49
57
|
const originalCwd = process.cwd();
|
|
50
58
|
const tempRoots: string[] = [];
|
|
@@ -126,6 +134,29 @@ afterEach(() => {
|
|
|
126
134
|
});
|
|
127
135
|
|
|
128
136
|
describe("buildPiArgs session wiring", () => {
|
|
137
|
+
it("projects launch-resolved extension identifiers without raw paths", () => {
|
|
138
|
+
const privateExt = path.join(os.tmpdir(), "private-extension-root", "secret-extension.ts");
|
|
139
|
+
const toolExt = path.join(os.tmpdir(), "tool-extension-root", "tool-extension.ts");
|
|
140
|
+
const plan = resolvePiLaunchToolPlan({
|
|
141
|
+
tools: ["read", toolExt],
|
|
142
|
+
extensions: [privateExt],
|
|
143
|
+
subagentOnlyExtensions: ["package-extension"],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
const projection = projectLaunchResolvedChildExtensions(plan);
|
|
147
|
+
|
|
148
|
+
assert.equal(projection.version, 1);
|
|
149
|
+
assert.equal(projection.source, "launch-resolved");
|
|
150
|
+
assert.equal(projection.disableAmbientExtensions, true);
|
|
151
|
+
assert.equal(projection.runtime.length, 1);
|
|
152
|
+
assert.equal(projection.configured.length, 3);
|
|
153
|
+
assert.equal(projection.effective.length, 4);
|
|
154
|
+
for (const id of [...projection.runtime, ...projection.configured, ...projection.effective]) {
|
|
155
|
+
assert.match(id, /^sha256:[a-f0-9]{16}$/);
|
|
156
|
+
}
|
|
157
|
+
assert.ok(!JSON.stringify(projection).includes(os.tmpdir()), "projection should not expose raw extension paths");
|
|
158
|
+
});
|
|
159
|
+
|
|
129
160
|
it("uses --session when sessionFile is provided", () => {
|
|
130
161
|
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-args-session-"));
|
|
131
162
|
try {
|
|
@@ -415,11 +446,24 @@ describe("buildPiArgs system prompt mode wiring", () => {
|
|
|
415
446
|
|
|
416
447
|
const extensionArgs = args.filter((arg, index) => args[index - 1] === "--extension");
|
|
417
448
|
assert.ok(extensionArgs.some((arg) => arg.endsWith(path.join("src", "runs", "shared", "subagent-prompt-runtime.ts"))));
|
|
449
|
+
assert.ok(args.includes("--no-context-files"));
|
|
418
450
|
assert.equal(env.SELESAI_SUBAGENT_CHILD, "1");
|
|
419
451
|
assert.equal(env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT, "0");
|
|
420
452
|
assert.equal(env.SELESAI_SUBAGENT_INHERIT_SKILLS, "1");
|
|
421
453
|
});
|
|
422
454
|
|
|
455
|
+
it("keeps context file loading enabled when project context is inherited", () => {
|
|
456
|
+
const { args } = buildPiArgs({
|
|
457
|
+
baseArgs: ["-p"],
|
|
458
|
+
task: "hello",
|
|
459
|
+
sessionEnabled: false,
|
|
460
|
+
inheritProjectContext: true,
|
|
461
|
+
inheritSkills: true,
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
assert.equal(args.includes("--no-context-files"), false);
|
|
465
|
+
});
|
|
466
|
+
|
|
423
467
|
it("passes tool budget through env", () => {
|
|
424
468
|
const { env } = buildPiArgs({
|
|
425
469
|
baseArgs: ["-p"],
|
|
@@ -475,6 +519,8 @@ describe("buildPiArgs system prompt mode wiring", () => {
|
|
|
475
519
|
});
|
|
476
520
|
|
|
477
521
|
it("passes child intercom and orchestrator metadata through env", () => {
|
|
522
|
+
process.env[PI_INTERCOM_STABLE_ID_ENV] = "subagent-chat-parent";
|
|
523
|
+
process.env[PI_INTERCOM_SESSION_ID_ENV] = "session-parent-runtime";
|
|
478
524
|
const { env } = buildPiArgs({
|
|
479
525
|
baseArgs: ["-p"],
|
|
480
526
|
task: "hello",
|
|
@@ -490,6 +536,8 @@ describe("buildPiArgs system prompt mode wiring", () => {
|
|
|
490
536
|
});
|
|
491
537
|
|
|
492
538
|
assert.equal(env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME, "subagent-worker-78f659a3");
|
|
539
|
+
assert.equal(env[PI_INTERCOM_STABLE_ID_ENV], "subagent-worker-78f659a3");
|
|
540
|
+
assert.equal(env[PI_INTERCOM_SESSION_ID_ENV], undefined);
|
|
493
541
|
assert.equal(env.SELESAI_SUBAGENT_ORCHESTRATOR_TARGET, "subagent-chat-parent");
|
|
494
542
|
assert.equal(env[SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV], "session-parent-123");
|
|
495
543
|
assert.equal(env.SELESAI_SUBAGENT_RUN_ID, "78f659a3");
|
|
@@ -499,6 +547,21 @@ describe("buildPiArgs system prompt mode wiring", () => {
|
|
|
499
547
|
assert.match(env[SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV] ?? "", /supervisor-channels/);
|
|
500
548
|
});
|
|
501
549
|
|
|
550
|
+
it("clears inherited pi-intercom identity when no child intercom session name is set", () => {
|
|
551
|
+
process.env[PI_INTERCOM_STABLE_ID_ENV] = "subagent-chat-parent";
|
|
552
|
+
process.env[PI_INTERCOM_SESSION_ID_ENV] = "session-parent-runtime";
|
|
553
|
+
const { env } = buildPiArgs({
|
|
554
|
+
baseArgs: ["-p"],
|
|
555
|
+
task: "hello",
|
|
556
|
+
sessionEnabled: false,
|
|
557
|
+
inheritProjectContext: true,
|
|
558
|
+
inheritSkills: true,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
assert.equal(env[PI_INTERCOM_STABLE_ID_ENV], undefined);
|
|
562
|
+
assert.equal(env[PI_INTERCOM_SESSION_ID_ENV], undefined);
|
|
563
|
+
});
|
|
564
|
+
|
|
502
565
|
it("does not create a supervisor channel without an exact parent session id", () => {
|
|
503
566
|
const { env } = buildPiArgs({
|
|
504
567
|
baseArgs: ["-p"],
|
|
@@ -592,6 +655,46 @@ describe("buildPiArgs system prompt mode wiring", () => {
|
|
|
592
655
|
assert.equal(args[args.indexOf("--tools") + 1], "read,bash");
|
|
593
656
|
});
|
|
594
657
|
|
|
658
|
+
it("includes adapter tool filters in MCP cache identity", () => {
|
|
659
|
+
const base = { command: "npx", args: ["browser-mcp"] };
|
|
660
|
+
|
|
661
|
+
assert.notEqual(
|
|
662
|
+
computeMcpServerHash(base),
|
|
663
|
+
computeMcpServerHash({ ...base, includeTools: ["browser_navigate"] }),
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it("matches pi-mcp-adapter 2.15.0 metadata cache hashes", () => {
|
|
668
|
+
process.env.MCP_HASH_ROOT = "/tmp/mcp-root";
|
|
669
|
+
process.env.MCP_HASH_TOKEN = "token-value";
|
|
670
|
+
|
|
671
|
+
assert.deepEqual(
|
|
672
|
+
[
|
|
673
|
+
computeMcpServerHash({
|
|
674
|
+
command: "npx",
|
|
675
|
+
args: ["-y", "browser-mcp"],
|
|
676
|
+
env: { ROOT: "{env:MCP_HASH_ROOT}", SECRET_COMMAND: "!op read test" },
|
|
677
|
+
cwd: "${MCP_HASH_ROOT}/server",
|
|
678
|
+
exposeResources: false,
|
|
679
|
+
includeTools: ["browser_navigate"],
|
|
680
|
+
excludeTools: ["browser_close"],
|
|
681
|
+
}),
|
|
682
|
+
computeMcpServerHash({
|
|
683
|
+
url: "https://example.test/$env:MCP_HASH_TOKEN",
|
|
684
|
+
headers: { Authorization: "Bearer ${MCP_HASH_TOKEN}", Secret: "!op read test" },
|
|
685
|
+
auth: "bearer",
|
|
686
|
+
bearerTokenEnv: "MCP_HASH_TOKEN",
|
|
687
|
+
}),
|
|
688
|
+
computeMcpServerHash({ socket: "{env:MCP_HASH_ROOT}/rmcp.sock" }),
|
|
689
|
+
],
|
|
690
|
+
[
|
|
691
|
+
"8af47bd5a801f42bd252789826df883c6f4db6f1d425b82f8561d75063fbe3a8",
|
|
692
|
+
"77db141e556d24c3740a4b4f0cd50d8c23309a28062282cc1ca724207359ef5a",
|
|
693
|
+
"77f7f77a3e8df990d8c78e99ca81508fd8d1f954e814ee7cbfa46719f71eb46b",
|
|
694
|
+
],
|
|
695
|
+
);
|
|
696
|
+
});
|
|
697
|
+
|
|
595
698
|
it("augments explicit builtin allowlists with selected direct MCP tool names", () => {
|
|
596
699
|
const fixture = createMcpFixture();
|
|
597
700
|
writeMcpFixture(fixture);
|
|
@@ -252,6 +252,24 @@ Package skill content.
|
|
|
252
252
|
assert.equal(history[1]?.taskHash, taskHash("legacy customer secret"));
|
|
253
253
|
});
|
|
254
254
|
|
|
255
|
+
it("re-sanitizes run history after an external write", () => {
|
|
256
|
+
recordRun("env-agent", "first secret", 0, 1);
|
|
257
|
+
const historyPath = path.join(agentDir, "run-history.jsonl");
|
|
258
|
+
fs.appendFileSync(historyPath, `${JSON.stringify({
|
|
259
|
+
agent: "env-agent",
|
|
260
|
+
task: "externally written secret",
|
|
261
|
+
ts: 2,
|
|
262
|
+
status: "ok",
|
|
263
|
+
duration: 2,
|
|
264
|
+
})}\n`);
|
|
265
|
+
|
|
266
|
+
recordRun("env-agent", "second secret", 0, 3);
|
|
267
|
+
|
|
268
|
+
const rawHistory = fs.readFileSync(historyPath, "utf-8");
|
|
269
|
+
assert.doesNotMatch(rawHistory, /first secret|externally written secret|second secret/);
|
|
270
|
+
assert.equal(loadRunsForAgent("env-agent").length, 3);
|
|
271
|
+
});
|
|
272
|
+
|
|
255
273
|
it("uses the configured agent dir for subagent bridge instruction files", () => {
|
|
256
274
|
const instructionPath = path.join(agentDir, "extensions", "subagent", "bridge.md");
|
|
257
275
|
writeFile(instructionPath, "Native bridge for {orchestratorTarget}");
|
|
@@ -153,6 +153,52 @@ Project prompt.
|
|
|
153
153
|
}
|
|
154
154
|
});
|
|
155
155
|
|
|
156
|
+
it("resolves agent aliases to the canonical launch contract agent", async () => {
|
|
157
|
+
const cwd = path.join(tempDir, "repo-alias");
|
|
158
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
159
|
+
writeAgent(path.join(cwd, ".selesai", "agents", "worker.md"), `---
|
|
160
|
+
name: worker
|
|
161
|
+
description: Project worker
|
|
162
|
+
aliases: shipper, worker-alias
|
|
163
|
+
---
|
|
164
|
+
Project prompt.
|
|
165
|
+
`);
|
|
166
|
+
|
|
167
|
+
const result = await resolveSubagentLaunchContract({
|
|
168
|
+
agent: "shipper",
|
|
169
|
+
cwd,
|
|
170
|
+
task: "Implement the change",
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
assert.equal(result.ok, true);
|
|
174
|
+
assert.equal(result.contract.agent.name, "worker");
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it("reports alias collisions as ambiguous agents", async () => {
|
|
178
|
+
const cwd = path.join(tempDir, "repo-alias-collision");
|
|
179
|
+
fs.mkdirSync(cwd, { recursive: true });
|
|
180
|
+
writeAgent(path.join(cwd, ".selesai", "agents", "worker.md"), `---
|
|
181
|
+
name: worker
|
|
182
|
+
description: Project worker
|
|
183
|
+
aliases: shared-alias
|
|
184
|
+
---
|
|
185
|
+
Project prompt.
|
|
186
|
+
`);
|
|
187
|
+
writeAgent(path.join(cwd, ".selesai", "agents", "reviewer.md"), `---
|
|
188
|
+
name: reviewer
|
|
189
|
+
description: Project reviewer
|
|
190
|
+
aliases: shared-alias
|
|
191
|
+
---
|
|
192
|
+
Review prompt.
|
|
193
|
+
`);
|
|
194
|
+
|
|
195
|
+
const result = await resolveSubagentLaunchContract({ agent: "shared-alias", cwd });
|
|
196
|
+
|
|
197
|
+
assert.equal(result.ok, false);
|
|
198
|
+
assert.equal(result.code, "ambiguous_agent");
|
|
199
|
+
assert.match(result.message, /Ambiguous agent alias 'shared-alias': reviewer, worker|Ambiguous agent alias 'shared-alias': worker, reviewer/);
|
|
200
|
+
});
|
|
201
|
+
|
|
156
202
|
it("changes definition and launch digests when selected agent content changes", async () => {
|
|
157
203
|
const cwd = path.join(tempDir, "repo");
|
|
158
204
|
fs.mkdirSync(cwd, { recursive: true });
|
|
@@ -3,7 +3,7 @@ import assert from "node:assert/strict";
|
|
|
3
3
|
|
|
4
4
|
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
5
5
|
import { row } from "../../src/tui/render-helpers.ts";
|
|
6
|
-
import { renderSubagentResult } from "../../src/tui/render.ts";
|
|
6
|
+
import { renderSubagentResult, truncLine } from "../../src/tui/render.ts";
|
|
7
7
|
|
|
8
8
|
const theme = {
|
|
9
9
|
fg(_name: string, text: string): string {
|
|
@@ -49,6 +49,18 @@ test("row keeps styled multiline content within the available width", () => {
|
|
|
49
49
|
assert.doesNotMatch(rendered, /[\r\n\t]/);
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
test("truncLine preserves ANSI styles and resets through the ellipsis", () => {
|
|
53
|
+
assert.equal(truncLine("\u001b[31mabcdef\u001b[0m", 4), "\u001b[31mabc\u001b[31m…");
|
|
54
|
+
assert.equal(truncLine("\u001b[31mab\u001b[0mcdef", 4), "\u001b[31mab\u001b[0mc…");
|
|
55
|
+
assert.equal(truncLine("ab\u001b[xcd", 4), "ab\u001b[…");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("truncLine respects grapheme display width", () => {
|
|
59
|
+
const rendered = truncLine("🙂🙂🙂", 5);
|
|
60
|
+
assert.equal(rendered, "🙂🙂…");
|
|
61
|
+
assert.equal(visibleWidth(rendered), 5);
|
|
62
|
+
});
|
|
63
|
+
|
|
52
64
|
test("compact chain rendering uses workflow graph spans for dynamic fanout results", () => {
|
|
53
65
|
const component = renderSubagentResult({
|
|
54
66
|
content: [{ type: "text", text: "done" }],
|
|
@@ -43,13 +43,14 @@ describe("result intercom formatter", () => {
|
|
|
43
43
|
assert.match(payload.message, /^subagent results/m);
|
|
44
44
|
assert.match(payload.message, /Run: run-123/);
|
|
45
45
|
assert.match(payload.message, /Mode: chain/);
|
|
46
|
-
assert.match(payload.message, /
|
|
46
|
+
assert.match(payload.message, /Process status: failed/);
|
|
47
47
|
assert.match(payload.message, /Children: 1 completed, 1 failed/);
|
|
48
|
+
assert.match(payload.message, /Outputs: 2 unknown \(semantic adequacy unassessed\)/);
|
|
48
49
|
assert.match(payload.message, /Chain steps: 4/);
|
|
49
50
|
assert.match(payload.message, /Intercom targets below identify child sessions used while they were running/);
|
|
50
|
-
assert.match(payload.message, /1\. reviewer-a — completed/);
|
|
51
|
+
assert.match(payload.message, /1\. reviewer-a — process completed · output unknown/);
|
|
51
52
|
assert.match(payload.message, /Run intercom target: subagent-reviewer-a-run-123-1/);
|
|
52
|
-
assert.match(payload.message, /2\. reviewer-b — failed/);
|
|
53
|
+
assert.match(payload.message, /2\. reviewer-b — process failed · output unknown/);
|
|
53
54
|
assert.match(payload.message, /Output artifact: \/tmp\/a\.md/);
|
|
54
55
|
assert.match(payload.message, /Session: \/tmp\/a-session\.jsonl/);
|
|
55
56
|
});
|
|
@@ -161,6 +162,27 @@ describe("result intercom formatter", () => {
|
|
|
161
162
|
assert.match(payload.message, /↳ reviewer — complete \[nested-a\]/);
|
|
162
163
|
});
|
|
163
164
|
|
|
165
|
+
it("separates process failure from output presence and gives salvage guidance", () => {
|
|
166
|
+
const payload = buildSubagentResultIntercomPayload({
|
|
167
|
+
to: "chat",
|
|
168
|
+
runId: "run-salvage",
|
|
169
|
+
mode: "parallel",
|
|
170
|
+
source: "foreground",
|
|
171
|
+
children: [
|
|
172
|
+
{ agent: "a", status: "completed", outputState: "present", summary: "answer a" },
|
|
173
|
+
{ agent: "b", status: "failed", outputState: "present", summary: "runner crashed after answer b" },
|
|
174
|
+
{ agent: "c", status: "failed", outputState: "absent", summary: "startup failed" },
|
|
175
|
+
],
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
assert.equal(payload.status, "failed");
|
|
179
|
+
assert.equal(payload.children[1]?.outputState, "present");
|
|
180
|
+
assert.match(payload.message, /Process status: failed/);
|
|
181
|
+
assert.match(payload.message, /Outputs: 2 present, 1 absent \(semantic adequacy unassessed\)/);
|
|
182
|
+
assert.match(payload.message, /Inspect that output before retrying/);
|
|
183
|
+
assert.match(payload.message, /2\. b — process failed · output present/);
|
|
184
|
+
});
|
|
185
|
+
|
|
164
186
|
it("keeps full child summaries inside grouped payloads", () => {
|
|
165
187
|
const longSummary = `${"x".repeat(2000)}\n${"y".repeat(2000)}`;
|
|
166
188
|
const payload = buildSubagentResultIntercomPayload({
|
|
@@ -217,9 +239,12 @@ describe("result intercom formatter", () => {
|
|
|
217
239
|
assert.equal(stripped.results[0]?.truncation, undefined);
|
|
218
240
|
});
|
|
219
241
|
|
|
220
|
-
it("resolves paused and
|
|
242
|
+
it("resolves paused, detached, and signal-terminated statuses", () => {
|
|
221
243
|
assert.equal(resolveSubagentResultStatus({ interrupted: true }), "paused");
|
|
222
244
|
assert.equal(resolveSubagentResultStatus({ detached: true }), "detached");
|
|
245
|
+
assert.equal(resolveSubagentResultStatus({ processSignal: "SIGTERM", exitCode: 1 }), "stopped");
|
|
246
|
+
assert.equal(resolveSubagentResultStatus({ processSignal: "SIGTERM", exitCode: 1, timedOut: true }), "failed");
|
|
247
|
+
assert.equal(resolveSubagentResultStatus({ processSignal: "SIGTERM", exitCode: 0, success: true }), "completed");
|
|
223
248
|
assert.equal(resolveSubagentResultStatus({ success: true }), "completed");
|
|
224
249
|
assert.equal(resolveSubagentResultStatus({ exitCode: 1 }), "failed");
|
|
225
250
|
});
|