@selesai/code 0.9.10 → 0.9.12
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/CHANGELOG.md +271 -255
- package/dist/cli/args.js +13 -2
- package/dist/cli/args.test.js +8 -0
- package/dist/cli/credential-print.js +4 -4
- package/dist/cli.js +0 -0
- package/dist/config.d.ts +4 -6
- package/dist/config.js +10 -14
- package/dist/core/agent-session-auto-handoff.test.js +24 -1
- package/dist/core/agent-session.d.ts +10 -4
- package/dist/core/agent-session.js +61 -46
- package/dist/core/compaction/branch-summarization.js +30 -30
- package/dist/core/compaction/compaction.js +81 -81
- package/dist/core/compaction/utils.js +2 -2
- package/dist/core/defaults.d.ts +1 -0
- package/dist/core/defaults.js +9 -0
- package/dist/core/export-html/template.css +1066 -1066
- package/dist/core/export-html/template.html +55 -55
- package/dist/core/export-html/template.js +1864 -1864
- package/dist/core/export-html/vendor/highlight.min.js +1212 -1212
- package/dist/core/export-html/vendor/marked.min.js +78 -78
- package/dist/core/extensions/loader.js +108 -35
- package/dist/core/extensions/loader.test.js +21 -0
- package/dist/core/extensions/types.d.ts +12 -4
- package/dist/core/keybindings.d.ts +2 -2
- package/dist/core/messages.js +7 -7
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.js +10 -4
- package/dist/core/package-manager.js +4 -4
- package/dist/core/sdk.d.ts +5 -5
- package/dist/core/sdk.js +16 -4
- package/dist/core/settings-manager.d.ts +6 -2
- package/dist/core/settings-manager.js +22 -3
- package/dist/core/tools/bash.d.ts +18 -1
- package/dist/core/tools/bash.js +41 -23
- package/dist/core/tools/index.d.ts +4 -2
- package/dist/core/tools/index.js +9 -2
- package/dist/core/tools/powershell.d.ts +15 -0
- package/dist/core/tools/powershell.js +38 -0
- package/dist/core/tools/powershell.test.d.ts +1 -0
- package/dist/core/tools/powershell.test.js +20 -0
- package/dist/defaults/settings.json +0 -1
- package/dist/extensions/context-compaction-reminder.test.ts +82 -82
- package/dist/extensions/context-compaction-reminder.ts +28 -28
- package/dist/extensions/model-prompt-injector/index.test.ts +0 -10
- package/dist/extensions/model-prompt-injector/index.ts +0 -3
- package/dist/extensions/pi-intercom/CHANGELOG.md +53 -16
- package/dist/extensions/pi-intercom/LICENSE +21 -21
- package/dist/extensions/pi-intercom/README.md +41 -8
- package/dist/extensions/pi-intercom/banner.png +0 -0
- package/dist/extensions/pi-intercom/broker/broker.ts +498 -215
- package/dist/extensions/pi-intercom/broker/client.test.ts +83 -83
- package/dist/extensions/pi-intercom/broker/client.ts +39 -12
- package/dist/extensions/pi-intercom/broker/extension.test.ts +486 -387
- package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -114
- package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -153
- package/dist/extensions/pi-intercom/broker/paths.ts +134 -134
- package/dist/extensions/pi-intercom/broker/protocol.ts +26 -0
- package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -34
- package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -21
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +5 -20
- package/dist/extensions/pi-intercom/config.test.ts +41 -0
- package/dist/extensions/pi-intercom/config.ts +21 -0
- package/dist/extensions/pi-intercom/cwd.test.ts +40 -40
- package/dist/extensions/pi-intercom/cwd.ts +31 -31
- package/dist/extensions/pi-intercom/extension-api.ts +84 -44
- package/dist/extensions/pi-intercom/format-context.test.ts +31 -31
- package/dist/extensions/pi-intercom/format-context.ts +32 -32
- package/dist/extensions/pi-intercom/index.ts +362 -26
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +819 -13
- package/dist/extensions/pi-intercom/package.json +1 -1
- package/dist/extensions/pi-intercom/project-agent.ts +2 -2
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +8 -110
- package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -66
- package/dist/extensions/pi-intercom/types.ts +32 -5
- package/dist/extensions/pi-intercom/ui/compose.ts +143 -143
- package/dist/extensions/pi-intercom/ui/inline-message.ts +6 -0
- package/dist/extensions/pi-intercom/ui/session-list.ts +166 -166
- package/dist/extensions/pi-powerline-footer/bash-mode/shell-session.ts +286 -286
- package/dist/extensions/pi-powerline-footer/bash-mode/transcript.ts +108 -108
- package/dist/extensions/pi-powerline-footer/separators.ts +57 -57
- package/dist/extensions/pi-powerline-footer/tests/session-usage.test.ts +47 -47
- package/dist/extensions/pi-powerline-footer/tests/tps.test.ts +39 -39
- package/dist/extensions/pi-powerline-footer/theme.example.json +24 -24
- package/dist/extensions/pi-powerline-footer/theme.json +12 -12
- package/dist/extensions/pi-powerline-footer/tps.ts +345 -345
- package/dist/extensions/pi-rewind-hook/README.md +245 -245
- package/dist/extensions/pi-rewind-hook/index.ts +1445 -1445
- package/dist/extensions/pi-rewind-hook/package.json +29 -29
- package/dist/extensions/pi-subagents/.github/assets/subagent-fleet-inspector.png +0 -0
- package/dist/extensions/pi-subagents/.github/workflows/release.yml +28 -0
- package/dist/extensions/pi-subagents/.github/workflows/test.yml +51 -0
- package/dist/extensions/pi-subagents/.greptile/config.json +33 -0
- package/dist/extensions/pi-subagents/.greptile/files.json +8 -0
- package/dist/extensions/pi-subagents/.greptile/rules.md +16 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +309 -87
- package/dist/extensions/pi-subagents/README.md +15 -17
- package/dist/extensions/pi-subagents/agents/oracle.md +3 -1
- package/dist/extensions/pi-subagents/agents/researcher.md +32 -13
- package/dist/extensions/pi-subagents/agents/reviewer.md +13 -2
- package/dist/extensions/pi-subagents/agents/scout.md +2 -2
- package/dist/extensions/pi-subagents/agents/worker.md +2 -1
- package/dist/extensions/pi-subagents/async-retention-discovery-worker.mjs +180 -0
- package/dist/extensions/pi-subagents/docs/configuration.md +106 -27
- package/dist/extensions/pi-subagents/docs/extension-api.md +85 -21
- package/dist/extensions/pi-subagents/docs/missions.md +41 -4
- package/dist/extensions/pi-subagents/docs/models.md +52 -9
- package/dist/extensions/pi-subagents/docs/observability.md +103 -16
- package/dist/extensions/pi-subagents/docs/tool-reference.md +60 -45
- package/dist/extensions/pi-subagents/docs/watchdog.md +60 -3
- package/dist/extensions/pi-subagents/docs/workflows.md +181 -7
- package/dist/extensions/pi-subagents/index.ts +10 -1
- package/dist/extensions/pi-subagents/install.mjs +4 -4
- package/dist/extensions/pi-subagents/package-lock.json +1483 -1470
- package/dist/extensions/pi-subagents/package.json +6 -3
- package/dist/extensions/pi-subagents/prompts/council.md +60 -0
- package/dist/extensions/pi-subagents/prompts/parallel-review.md +5 -1
- package/dist/extensions/pi-subagents/prompts/review-loop.md +9 -5
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +254 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +18 -17
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +107 -140
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +44 -92
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +261 -368
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +6 -2
- package/dist/extensions/pi-subagents/src/agents/agents.ts +388 -85
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +14 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +418 -0
- package/dist/extensions/pi-subagents/src/agents/skills.ts +1 -1
- package/dist/extensions/pi-subagents/src/api/agents.ts +7 -0
- package/dist/extensions/pi-subagents/src/api/external-job-provider.ts +195 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +88 -27
- package/dist/extensions/pi-subagents/src/api/project-panes.ts +2 -0
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +20 -11
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +14 -6
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -4
- package/dist/extensions/pi-subagents/src/extension/index.ts +270 -187
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +65 -28
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +120 -11
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +46 -64
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +51 -37
- package/dist/extensions/pi-subagents/src/extension/tool-result.ts +19 -0
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -2
- package/dist/extensions/pi-subagents/src/inspectors/herdr/client.ts +3 -3
- package/dist/extensions/pi-subagents/src/inspectors/herdr/focus.ts +55 -0
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/project-panes.ts +230 -46
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +26 -4
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +32 -10
- package/dist/extensions/pi-subagents/src/missions/lifecycle.ts +6 -1
- package/dist/extensions/pi-subagents/src/missions/store.ts +4 -9
- package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +2 -2
- package/dist/extensions/pi-subagents/src/policy/authority.ts +2 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/background/active-run-index.ts +31 -8
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +210 -52
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +63 -33
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +71 -17
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +886 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +14 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +49 -56
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +1 -0
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +3 -33
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +5 -0
- package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +5 -1
- package/dist/extensions/pi-subagents/src/runs/background/completion-replay.ts +22 -12
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +105 -71
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +68 -19
- package/dist/extensions/pi-subagents/src/runs/background/index-segment.ts +59 -0
- package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +443 -0
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +94 -10
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +158 -90
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +141 -53
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +8 -5
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +14 -4
- package/dist/extensions/pi-subagents/src/runs/background/run-id-query.ts +7 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +13 -14
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +46 -25
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +823 -0
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +9 -3
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +11 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +594 -216
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +17 -13
- package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +138 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +23 -4
- package/dist/extensions/pi-subagents/src/runs/background/wait-subscriptions.ts +82 -4
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +5 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +21 -14
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +23 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +153 -58
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +7 -9
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1283 -1657
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +274 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +6 -5
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +59 -10
- package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +1 -3
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +36 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +52 -2
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/extension-bindings.ts +78 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-job-bridge.ts +460 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-job-runner.ts +389 -0
- package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +10 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +14 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +243 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +201 -85
- package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +106 -39
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +145 -0
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +150 -27
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +46 -4
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +19 -15
- package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +5 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +86 -2
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +9 -9
- package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +0 -6
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +18 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +51 -7
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +62 -21
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +1 -3
- package/dist/extensions/pi-subagents/src/runs/shared/tool-timeout.ts +1 -3
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +1 -23
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +14 -2
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +2 -2
- package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +22 -2
- package/dist/extensions/pi-subagents/src/shared/capacity-resilient-json.ts +102 -0
- package/dist/extensions/pi-subagents/src/shared/completion-owner.ts +14 -0
- package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +49 -1
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +59 -1
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +12 -5
- package/dist/extensions/pi-subagents/src/shared/model-info.ts +20 -0
- package/dist/extensions/pi-subagents/src/shared/prompt-resources.ts +0 -40
- package/dist/extensions/pi-subagents/src/shared/settings.ts +11 -30
- package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +52 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +228 -49
- package/dist/extensions/pi-subagents/src/shared/utils.ts +11 -3
- package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +10 -0
- package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +0 -162
- package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +2 -5
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +105 -13
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +6 -36
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +829 -0
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +1415 -0
- package/dist/extensions/pi-subagents/src/tui/render.ts +78 -7
- package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +1 -1
- package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +1 -0
- package/dist/extensions/pi-subagents/src/watchdog/permission-arbiter.ts +59 -51
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +8 -2
- package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +2 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +4 -4
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +471 -86
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +140 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/cli.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/register-bedrock.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/bun/restore-sandbox-env.d.ts +17 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/args.d.ts +57 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/config-selector.d.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/file-processor.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/initial-message.d.ts +18 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/list-models.d.ts +9 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/project-trust.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/session-picker.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli/startup-ui.d.ts +20 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/cli.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/config.d.ts +96 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-runtime.d.ts +119 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session-services.d.ts +85 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/agent-session.d.ts +620 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-guidance.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/auth-storage.d.ts +56 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/bash-executor.d.ts +32 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/cache-stats.d.ts +49 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/branch-summarization.d.ts +93 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/compaction.d.ts +128 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/index.d.ts +7 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/compaction/utils.d.ts +38 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/defaults.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/diagnostics.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/event-bus.d.ts +9 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/exec.d.ts +29 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/experimental.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/index.d.ts +37 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/export-html/tool-renderer.d.ts +34 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/index.d.ts +12 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/loader.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/runner.d.ts +171 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/types.d.ts +1261 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/extensions/wrapper.d.ts +20 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/footer-data-provider.d.ts +54 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/http-dispatcher.d.ts +22 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/index.d.ts +13 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/keybindings.d.ts +358 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/messages.d.ts +77 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-config.d.ts +512 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-registry.d.ts +43 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-resolver.d.ts +121 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/model-runtime.d.ts +82 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/models-store.d.ts +17 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/output-guard.d.ts +7 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/package-manager.d.ts +210 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/project-trust.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/prompt-templates.d.ts +54 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-attribution.d.ts +4 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/provider-composer.d.ts +55 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/radius.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/remote-catalog-provider.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resolve-config-value.d.ts +30 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/resource-loader.d.ts +206 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/runtime-credentials.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/sdk.d.ts +106 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-cwd.d.ts +19 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/session-manager.d.ts +356 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/settings-manager.d.ts +297 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/skills.d.ts +60 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/slash-commands.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/source-info.d.ts +18 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/system-prompt.d.ts +28 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/telemetry.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/timings.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/bash.d.ts +68 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit-diff.d.ts +106 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/edit.d.ts +51 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/find.d.ts +35 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/grep.d.ts +37 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/index.d.ts +40 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/ls.d.ts +37 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/output-accumulator.d.ts +52 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/path-utils.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/read.d.ts +35 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/render-utils.d.ts +24 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/tool-definition-wrapper.d.ts +14 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/truncate.d.ts +70 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/tools/write.d.ts +26 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/trust-manager.d.ts +36 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/core/usage-totals.d.ts +19 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/client.d.ts +61 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/huggingface.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/index.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/provider.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/extensions/llama/ui.d.ts +42 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/index.d.ts +35 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/main.d.ts +12 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/migrations.d.ts +33 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/index.d.ts +9 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/armin.d.ts +34 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/assistant-message.d.ts +22 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bash-execution.d.ts +34 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/config-selector.d.ts +102 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-editor.d.ts +21 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/custom-message.d.ts +20 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/daxnuts.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/earendil-announcement.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-editor.d.ts +22 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/extension-selector.d.ts +26 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/footer.d.ts +32 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/index.d.ts +34 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/keybinding-hints.d.ts +13 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/login-dialog.d.ts +52 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/model-selector.d.ts +54 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/oauth-selector.d.ts +33 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/scoped-models-selector.d.ts +42 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/session-selector.d.ts +95 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/settings-selector.d.ts +77 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/status-indicator.d.ts +28 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tool-execution.d.ts +63 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/tree-selector.d.ts +94 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/user-message.d.ts +14 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/interactive-mode.d.ts +394 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/model-search.d.ts +12 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme-controller.d.ts +29 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/interactive/theme/theme.d.ts +120 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/print-mode.d.ts +28 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/jsonl.d.ts +17 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-client.d.ts +246 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/modes/rpc/rpc-types.d.ts +457 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/package-manager-cli.d.ts +8 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/rpc-entry.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/ansi.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/changelog.d.ts +22 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/child-process.d.ts +18 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard-native.d.ts +11 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/clipboard.d.ts +4 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/deprecation.d.ts +4 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/exif-orientation.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/frontmatter.d.ts +8 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/fs-watch.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/git.d.ts +26 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/html.d.ts +7 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-convert.d.ts +10 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-process.d.ts +18 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/image-resize.d.ts +16 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/json.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/mime.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/open-browser.d.ts +9 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/paths.d.ts +31 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/photon.d.ts +21 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/shell.d.ts +31 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/sleep.d.ts +5 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/tools-manager.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/version-check.d.ts +15 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/dist/utils/windows-self-update.d.ts +3 -0
- package/dist/extensions/pi-subagents/test/fixtures/pi-coding-agent-shim/index.mjs +1 -1
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +0 -54
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1053 -414
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +194 -4
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +59 -4
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +0 -77
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +107 -6
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +211 -897
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +265 -375
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +77 -7
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +10 -10
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +547 -30
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +2112 -310
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +274 -34
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +20 -3
- package/dist/extensions/pi-subagents/test/support/isolated-temp-root.mjs +9 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +30 -5
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +4 -2
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +1 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +197 -0
- package/dist/extensions/pi-subagents/test/unit/agent-contract.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +204 -27
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +444 -145
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +256 -4
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +9 -7
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +152 -22
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +29 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +205 -23
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +579 -0
- package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/authority-policy.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/capacity-resilient-json.test.ts +155 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +7 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +123 -0
- package/dist/extensions/pi-subagents/test/unit/completion-replay.test.ts +81 -3
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +109 -7
- package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +5 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +3 -2
- package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +79 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/external-job-runner.test.ts +961 -0
- package/dist/extensions/pi-subagents/test/unit/file-system-retry.test.ts +64 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +1110 -0
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +1664 -0
- package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +81 -1
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +138 -11
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +41 -2
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +210 -79
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +95 -0
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +596 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +3 -5
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +167 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +319 -18
- package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +19 -5
- package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +129 -0
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +231 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +28 -1
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +106 -2
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +204 -7
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +59 -4
- package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +2 -6
- package/dist/extensions/pi-subagents/test/unit/pi-args-permission-system.test.ts +34 -2
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +116 -6
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +12 -3
- package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +56 -61
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +416 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +9 -2
- package/dist/extensions/pi-subagents/test/unit/project-panes-public-api.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +21 -30
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +86 -11
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +233 -5
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +28 -5
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +323 -20
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +66 -10
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +68 -5
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +174 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +679 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-store-root.test.ts +67 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +55 -44
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +399 -84
- package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +13 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +15 -10
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +11 -7
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +40 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +10 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +38 -3
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +110 -12
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +204 -19
- package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +25 -0
- package/dist/extensions/pi-subagents/test/unit/thinking-ceiling.test.ts +73 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +90 -50
- package/dist/extensions/pi-subagents/test/unit/tool-timeout.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +234 -7
- package/dist/extensions/pi-subagents/test/unit/watch-strategy.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-permission-arbiter.test.ts +36 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +37 -9
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +302 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +167 -7
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +113 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +6 -6
- package/dist/extensions/pi-web-agent/package.json +31 -31
- package/dist/extensions/pi-web-agent/src/backends/config.ts +205 -205
- package/dist/extensions/pi-web-agent/src/backends/doctor.ts +136 -136
- package/dist/extensions/pi-web-agent/src/backends/factory.ts +152 -152
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +25 -25
- package/dist/extensions/pi-web-agent/src/cache/ttl-cache.ts +28 -28
- package/dist/extensions/pi-web-agent/src/changelog-notice.ts +136 -136
- package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +946 -946
- package/dist/extensions/pi-web-agent/src/extension.ts +126 -126
- package/dist/extensions/pi-web-agent/src/extract/readability.ts +118 -118
- package/dist/extensions/pi-web-agent/src/fetch/browser-resolution.ts +199 -199
- package/dist/extensions/pi-web-agent/src/fetch/firecrawl-fetch.ts +100 -100
- package/dist/extensions/pi-web-agent/src/fetch/headless-fetch.ts +117 -117
- package/dist/extensions/pi-web-agent/src/fetch/http-fetch.ts +67 -67
- package/dist/extensions/pi-web-agent/src/orchestration/answer-synthesizer.ts +60 -60
- package/dist/extensions/pi-web-agent/src/orchestration/candidate-selector.ts +50 -50
- package/dist/extensions/pi-web-agent/src/orchestration/direct-url.ts +52 -52
- package/dist/extensions/pi-web-agent/src/orchestration/evidence-quality.ts +105 -105
- package/dist/extensions/pi-web-agent/src/orchestration/evidence-ranker.ts +45 -45
- package/dist/extensions/pi-web-agent/src/orchestration/index.ts +28 -28
- package/dist/extensions/pi-web-agent/src/orchestration/query-planner.ts +47 -47
- package/dist/extensions/pi-web-agent/src/orchestration/research-orchestrator.ts +376 -376
- package/dist/extensions/pi-web-agent/src/orchestration/research-types.ts +64 -64
- package/dist/extensions/pi-web-agent/src/orchestration/research-worker.ts +181 -181
- package/dist/extensions/pi-web-agent/src/orchestration/source-profile.ts +101 -101
- package/dist/extensions/pi-web-agent/src/orchestration/stop-decider.ts +81 -81
- package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +210 -210
- package/dist/extensions/pi-web-agent/src/presentation/config.ts +75 -75
- package/dist/extensions/pi-web-agent/src/presentation/explore-presentation.ts +61 -61
- package/dist/extensions/pi-web-agent/src/presentation/fetch-presentation.ts +54 -54
- package/dist/extensions/pi-web-agent/src/presentation/search-presentation.ts +41 -41
- package/dist/extensions/pi-web-agent/src/presentation/select-view.ts +20 -20
- package/dist/extensions/pi-web-agent/src/presentation/types.ts +63 -63
- package/dist/extensions/pi-web-agent/src/search/brave.ts +114 -114
- package/dist/extensions/pi-web-agent/src/search/duckduckgo.ts +72 -72
- package/dist/extensions/pi-web-agent/src/search/searxng.ts +96 -96
- package/dist/extensions/pi-web-agent/src/tools/web-explore.ts +71 -71
- package/dist/extensions/pi-web-agent/src/tools/web-fetch-headless.ts +31 -31
- package/dist/extensions/pi-web-agent/src/tools/web-fetch.ts +31 -31
- package/dist/extensions/pi-web-agent/src/tools/web-search.ts +157 -157
- package/dist/extensions/pi-web-agent/src/types.ts +88 -88
- package/dist/extensions/ponytail/index.js +31 -25
- package/dist/extensions/ponytail/package.json +8 -8
- package/dist/extensions/ponytail/ponytail-config.cjs +34 -7
- package/dist/extensions/ponytail/ponytail-instructions.cjs +7 -9
- package/dist/extensions/ponytail/test/extension.test.js +7 -8
- package/dist/extensions/ponytail/test/helpers.test.js +1 -1
- package/dist/extensions/question/batch.ts +103 -103
- package/dist/extensions/question/constants.ts +30 -30
- package/dist/extensions/question/helpers.ts +58 -58
- package/dist/extensions/question/navigation.ts +14 -14
- package/dist/extensions/question/package.json +19 -19
- package/dist/extensions/question/schemas.ts +43 -43
- package/dist/extensions/question/selection-mode.ts +46 -46
- package/dist/extensions/question/shortcuts.ts +44 -44
- package/dist/extensions/question/types.ts +132 -132
- package/dist/extensions/test-resolve-hook-impl.mjs +6 -6
- package/dist/extensions/test-resolve-hook.mjs +6 -6
- package/dist/extensions/web-agent-onboarding.ts +222 -222
- package/dist/extensions/workflow/package.json +17 -17
- package/dist/package-manager-cli.js +71 -71
- package/dist/rpc-entry.js +0 -0
- package/dist/skills/agent-browser/SKILL.md +52 -52
- package/dist/skills/batch-grill-me/SKILL.md +19 -19
- package/dist/skills/brandkit/SKILL.md +799 -0
- package/dist/skills/design-taste-frontend/SKILL.md +1207 -0
- package/dist/skills/design-taste-frontend-v1/SKILL.md +227 -0
- package/dist/skills/full-output-enforcement/SKILL.md +50 -0
- package/dist/skills/gpt-taste/SKILL.md +75 -0
- package/dist/skills/grill-me/SKILL.md +10 -10
- package/dist/skills/handoff/SKILL.md +16 -16
- package/dist/skills/handoff-text/SKILL.md +14 -14
- package/dist/skills/high-end-visual-design/SKILL.md +99 -0
- package/dist/skills/image-to-code/SKILL.md +1229 -0
- package/dist/skills/imagegen-frontend-mobile/SKILL.md +1466 -0
- package/dist/skills/imagegen-frontend-web/SKILL.md +988 -0
- package/dist/skills/implanger/SKILL.md +69 -69
- package/dist/skills/improve-codebase/REFERENCE.md +78 -78
- package/dist/skills/improve-codebase/SKILL.md +178 -178
- package/dist/skills/industrial-brutalist-ui/SKILL.md +93 -0
- package/dist/skills/minimalist-ui/SKILL.md +86 -0
- package/dist/skills/pi-subagents/SKILL.md +18 -17
- package/dist/skills/pi-subagents/references/constraints-and-recipes.md +31 -9
- package/dist/skills/pi-subagents/references/execution-controls.md +95 -143
- package/dist/skills/pi-subagents/references/management-authoring-rpc.md +9 -12
- package/dist/skills/pi-subagents/references/multi-lane-orchestration.md +39 -0
- package/dist/skills/pi-subagents/references/prompting-and-roles.md +45 -94
- package/dist/skills/planger/SKILL.md +166 -166
- package/dist/skills/ponytail/SKILL.md +120 -116
- package/dist/skills/ponytail-audit/SKILL.md +41 -42
- package/dist/skills/ponytail-debt/SKILL.md +44 -45
- package/dist/skills/ponytail-gain/SKILL.md +50 -51
- package/dist/skills/ponytail-help/SKILL.md +71 -70
- package/dist/skills/ponytail-review/SKILL.md +57 -58
- package/dist/skills/redesign-existing-projects/SKILL.md +179 -0
- package/dist/skills/selesai-handoff/SKILL.md +20 -20
- package/dist/skills/stitch-design-taste/SKILL.md +185 -0
- package/dist/skills/unlazy/CHANGELOG.md +100 -0
- package/dist/skills/unlazy/CONTRIBUTING.md +66 -0
- package/dist/skills/unlazy/LICENSE +21 -0
- package/dist/skills/unlazy/README.md +242 -0
- package/dist/skills/unlazy/SECURITY.md +70 -0
- package/dist/skills/unlazy/SKILL.md +100 -0
- package/dist/skills/unlazy/package.json +13 -0
- package/dist/skills/unlazy/references/dispatch.md +82 -0
- package/dist/skills/unlazy/references/gates.md +132 -0
- package/dist/skills/unlazy/references/method.md +49 -0
- package/dist/skills/unlazy/references/orchestration.md +99 -0
- package/dist/skills/unlazy/references/parallel.md +123 -0
- package/dist/skills/unlazy/references/token-economy.md +39 -0
- package/dist/skills/unlazy/research/validation-protocol.md +81 -0
- package/dist/skills/unlazy/scripts/dispatch-check.mjs +108 -0
- package/dist/skills/unlazy/scripts/gate-check.mjs +894 -0
- package/dist/skills/unlazy/scripts/gate-lint.mjs +178 -0
- package/dist/skills/unlazy/scripts/install-hooks.mjs +206 -0
- package/dist/skills/unlazy/scripts/lib/check-supervisor.mjs +46 -0
- package/dist/skills/unlazy/scripts/lib/dispatch.mjs +283 -0
- package/dist/skills/unlazy/scripts/lib/gates.mjs +629 -0
- package/dist/skills/unlazy/scripts/lib/process-tree.mjs +161 -0
- package/dist/skills/unlazy/scripts/lib/regex-worker.mjs +9 -0
- package/dist/skills/unlazy/scripts/stop-hook.mjs +174 -0
- package/dist/skills/unlazy/templates/PLAN.md +65 -0
- package/dist/skills/unlazy/templates/gates-leaf.md +51 -0
- package/dist/skills/unlazy/templates/gates-node.md +50 -0
- package/dist/skills/unlazy/tests/contract-tests.mjs +127 -0
- package/dist/skills/unlazy/tests/dispatch-tests.mjs +481 -0
- package/dist/skills/unlazy/tests/hardening-tests.mjs +903 -0
- package/dist/skills/unlazy/tests/lint-tests.mjs +242 -0
- package/dist/skills/unlazy/tests/run-tests.mjs +554 -0
- package/dist/skills/unlazy/tests/self-check.mjs +165 -0
- package/dist/skills/unlazy/tests/stress-tests.mjs +356 -0
- package/dist/skills/web-design-guidelines/SKILL.md +40 -0
- package/dist/skills/workflow-creation/SKILL.md +73 -73
- package/dist/themes/powerline-footer/theme.json +33 -33
- package/dist/utils/shell.d.ts +3 -0
- package/dist/utils/shell.js +17 -5
- package/docs/compaction.md +396 -396
- package/docs/containerization.md +111 -111
- package/docs/development.md +71 -71
- package/docs/docs.json +164 -164
- package/docs/environment-variables.md +86 -86
- package/docs/index.md +83 -83
- package/docs/json.md +82 -82
- package/docs/models.md +502 -502
- package/docs/packages.md +227 -227
- package/docs/plans/subagent-delegation/phase-0-correctness.md +264 -264
- package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +485 -485
- package/docs/plans/subagent-delegation/phase-2-context-controls.md +281 -281
- package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +361 -361
- package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +380 -380
- package/docs/prompt-templates.md +95 -95
- package/docs/providers.md +293 -293
- package/docs/sdk.md +1144 -1143
- package/docs/security.md +59 -59
- package/docs/session-format.md +414 -414
- package/docs/sessions.md +145 -145
- package/docs/settings.md +0 -5
- package/docs/shared-host-extensions.md +109 -109
- package/docs/shell-aliases.md +13 -13
- package/docs/skills.md +231 -231
- package/docs/terminal-setup.md +142 -142
- package/docs/termux.md +127 -127
- package/docs/themes.md +295 -295
- package/docs/tmux.md +63 -63
- package/docs/tui.md +927 -927
- package/docs/windows.md +17 -17
- package/examples/README.md +25 -25
- package/examples/extensions/README.md +211 -211
- package/examples/extensions/auto-commit-on-exit.ts +49 -49
- package/examples/extensions/bash-spawn-hook.ts +30 -30
- package/examples/extensions/bookmark.ts +50 -50
- package/examples/extensions/border-status-editor.ts +150 -150
- package/examples/extensions/built-in-tool-renderer.ts +249 -249
- package/examples/extensions/claude-rules.ts +86 -86
- package/examples/extensions/commands.ts +72 -72
- package/examples/extensions/confirm-destructive.ts +59 -59
- package/examples/extensions/custom-compaction.ts +130 -130
- package/examples/extensions/custom-footer.ts +64 -64
- package/examples/extensions/custom-header.ts +73 -73
- package/examples/extensions/custom-provider-anthropic/index.ts +610 -610
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -24
- package/examples/extensions/custom-provider-anthropic/package.json +19 -19
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +404 -404
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -16
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -82
- package/examples/extensions/dirty-repo-guard.ts +56 -56
- package/examples/extensions/doom-overlay/README.md +46 -46
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -21
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -152
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -72
- package/examples/extensions/doom-overlay/doom-component.ts +132 -132
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -173
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -104
- package/examples/extensions/doom-overlay/index.ts +74 -74
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -51
- package/examples/extensions/dynamic-resources/SKILL.md +8 -8
- package/examples/extensions/dynamic-resources/dynamic.json +79 -79
- package/examples/extensions/dynamic-resources/dynamic.md +5 -5
- package/examples/extensions/dynamic-resources/index.ts +15 -15
- package/examples/extensions/dynamic-tools.ts +74 -74
- package/examples/extensions/event-bus.ts +43 -43
- package/examples/extensions/file-trigger.ts +41 -41
- package/examples/extensions/git-checkpoint.ts +53 -53
- package/examples/extensions/git-merge-and-resolve.ts +115 -115
- package/examples/extensions/github-issue-autocomplete.ts +185 -185
- package/examples/extensions/gondolin/index.ts +531 -531
- package/examples/extensions/gondolin/package-lock.json +185 -185
- package/examples/extensions/gondolin/package.json +19 -19
- package/examples/extensions/handoff.ts +199 -199
- package/examples/extensions/hello.ts +26 -26
- package/examples/extensions/hidden-thinking-label.ts +53 -53
- package/examples/extensions/inline-bash.ts +94 -94
- package/examples/extensions/input-transform-streaming.ts +39 -39
- package/examples/extensions/input-transform.ts +43 -43
- package/examples/extensions/interactive-shell.ts +196 -196
- package/examples/extensions/mac-system-theme.ts +47 -47
- package/examples/extensions/message-renderer.ts +59 -59
- package/examples/extensions/minimal-mode.ts +426 -426
- package/examples/extensions/modal-editor.ts +85 -85
- package/examples/extensions/model-status.ts +31 -31
- package/examples/extensions/notify.ts +55 -55
- package/examples/extensions/overlay-qa-tests.ts +1450 -1450
- package/examples/extensions/overlay-test.ts +153 -153
- package/examples/extensions/permission-gate.ts +34 -34
- package/examples/extensions/pirate.ts +47 -47
- package/examples/extensions/plan-mode/README.md +66 -66
- package/examples/extensions/plan-mode/index.ts +390 -390
- package/examples/extensions/plan-mode/utils.ts +168 -168
- package/examples/extensions/preset.ts +436 -436
- package/examples/extensions/project-trust.ts +64 -64
- package/examples/extensions/prompt-customizer.ts +97 -97
- package/examples/extensions/protected-paths.ts +30 -30
- package/examples/extensions/provider-payload.ts +18 -18
- package/examples/extensions/qna.ts +122 -122
- package/examples/extensions/question.ts +285 -285
- package/examples/extensions/questionnaire.ts +448 -448
- package/examples/extensions/rainbow-editor.ts +88 -88
- package/examples/extensions/reload-runtime.ts +37 -37
- package/examples/extensions/rpc-demo.ts +118 -118
- package/examples/extensions/sandbox/index.ts +321 -321
- package/examples/extensions/sandbox/package-lock.json +92 -92
- package/examples/extensions/sandbox/package.json +19 -19
- package/examples/extensions/send-user-message.ts +97 -97
- package/examples/extensions/session-name.ts +27 -27
- package/examples/extensions/shutdown-command.ts +63 -63
- package/examples/extensions/snake.ts +343 -343
- package/examples/extensions/space-invaders.ts +560 -560
- package/examples/extensions/ssh.ts +220 -220
- package/examples/extensions/status-line.ts +32 -32
- package/examples/extensions/structured-output.ts +65 -65
- package/examples/extensions/subagent/README.md +175 -175
- package/examples/extensions/subagent/agents/planner.md +37 -37
- package/examples/extensions/subagent/agents/reviewer.md +35 -35
- package/examples/extensions/subagent/agents/scout.md +50 -50
- package/examples/extensions/subagent/agents/worker.md +24 -24
- package/examples/extensions/subagent/agents.ts +126 -126
- package/examples/extensions/subagent/index.ts +1015 -1015
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -10
- package/examples/extensions/subagent/prompts/implement.md +10 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -9
- package/examples/extensions/summarize.ts +209 -209
- package/examples/extensions/system-prompt-header.ts +17 -17
- package/examples/extensions/tic-tac-toe.ts +1008 -1008
- package/examples/extensions/timed-confirm.ts +70 -70
- package/examples/extensions/titlebar-spinner.ts +58 -58
- package/examples/extensions/todo.ts +297 -297
- package/examples/extensions/tool-override.ts +144 -144
- package/examples/extensions/tools.ts +146 -146
- package/examples/extensions/trigger-compact.ts +50 -50
- package/examples/extensions/truncated-tool.ts +195 -195
- package/examples/extensions/widget-placement.ts +9 -9
- package/examples/extensions/with-deps/index.ts +32 -32
- package/examples/extensions/with-deps/package-lock.json +31 -31
- package/examples/extensions/with-deps/package.json +22 -22
- package/examples/extensions/working-indicator.ts +123 -123
- package/examples/extensions/working-message-test.ts +25 -25
- package/examples/rpc-extension-ui.ts +632 -632
- package/examples/sdk/01-minimal.ts +26 -26
- package/examples/sdk/02-custom-model.ts +53 -53
- package/examples/sdk/03-custom-prompt.ts +75 -75
- package/examples/sdk/04-skills.ts +55 -55
- package/examples/sdk/05-tools.ts +48 -48
- package/examples/sdk/06-extensions.ts +99 -99
- package/examples/sdk/07-context-files.ts +47 -47
- package/examples/sdk/08-prompt-templates.ts +51 -51
- package/examples/sdk/09-api-keys-and-oauth.ts +52 -52
- package/examples/sdk/10-settings.ts +53 -53
- package/examples/sdk/11-sessions.ts +52 -52
- package/examples/sdk/12-full-control.ts +79 -79
- package/examples/sdk/13-session-runtime.ts +67 -67
- package/examples/sdk/README.md +144 -144
- package/package.json +4 -4
- package/dist/core/tools/schema-prune.d.ts +0 -16
- package/dist/core/tools/schema-prune.js +0 -39
- package/dist/core/tools/schema-prune.test.js +0 -111
- package/dist/extensions/pi-subagents/UPSTREAM-V0.50-MAPPING.md +0 -172
- package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +0 -55
- package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +0 -61
- package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +0 -132
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +0 -181
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +0 -1354
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +0 -1581
- package/dist/extensions/pi-subagents/src/shared/env.ts +0 -16
- package/dist/extensions/pi-subagents/src/shared/session-lineage.ts +0 -71
- package/dist/extensions/pi-subagents/src/slash/inline-subagents.ts +0 -136
- package/dist/extensions/pi-subagents/src/workflows/workflow-auto-relaunch.ts +0 -41
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +0 -466
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +0 -1859
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +0 -733
- package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +0 -63
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +0 -326
- package/dist/extensions/pi-subagents/test/unit/handoff-adoption.test.ts +0 -103
- package/dist/extensions/pi-subagents/test/unit/inline-subagents.test.ts +0 -127
- package/dist/extensions/pi-subagents/test/unit/session-lineage.test.ts +0 -73
- package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +0 -213
- package/dist/extensions/pi-subagents/test/unit/workflow-auto-relaunch.test.ts +0 -65
- /package/dist/core/{tools/schema-prune.test.d.ts → extensions/loader.test.d.ts} +0 -0
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
3
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { EventEmitter, once } from "node:events";
|
|
7
7
|
import { spawn, type ChildProcess } from "node:child_process";
|
|
8
8
|
import { ReplyTracker } from "./reply-tracker.ts";
|
|
9
9
|
import type { BrokerMessage, Message, SessionInfo } from "./types.ts";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
INTERCOM_EXTENSION_REGISTER_EVENT,
|
|
12
|
+
INTERCOM_OUTBOX_REQUEST_EVENT,
|
|
13
|
+
INTERCOM_OUTBOX_RESULT_EVENT,
|
|
14
|
+
type IntercomExtensionChannel,
|
|
15
|
+
type IntercomOutboxResultV1,
|
|
16
|
+
} from "./extension-api.ts";
|
|
11
17
|
|
|
12
18
|
const repoDir = process.cwd();
|
|
13
19
|
const childEnvKeys = [
|
|
@@ -21,19 +27,45 @@ const childEnvKeys = [
|
|
|
21
27
|
"SELESAI_SUBAGENT_INTERCOM_SESSION_NAME",
|
|
22
28
|
"SELESAI_SUBAGENT_SUPERVISOR_CHANNEL_DIR",
|
|
23
29
|
] as const;
|
|
24
|
-
const sharedHomeDir = mkdtempSync(path.join(tmpdir(), "
|
|
30
|
+
const sharedHomeDir = mkdtempSync(path.join(tmpdir(), "pi-intercom-home-"));
|
|
25
31
|
const previousHome = process.env.HOME;
|
|
26
32
|
const previousUserProfile = process.env.USERPROFILE;
|
|
27
33
|
process.env.HOME = sharedHomeDir;
|
|
28
34
|
process.env.USERPROFILE = sharedHomeDir;
|
|
29
35
|
const { IntercomClient } = await import("./broker/client.ts");
|
|
30
36
|
const { getTsxCliPath } = await import("./broker/spawn.ts");
|
|
37
|
+
const { getAskTimeoutMs, getConfigPath } = await import("./config.ts");
|
|
31
38
|
process.on("exit", () => {
|
|
32
39
|
process.env.HOME = previousHome;
|
|
33
40
|
process.env.USERPROFILE = previousUserProfile;
|
|
34
41
|
rmSync(sharedHomeDir, { recursive: true, force: true });
|
|
35
42
|
});
|
|
36
43
|
|
|
44
|
+
async function withIntercomConfig<T>(config: Record<string, unknown>, fn: () => T | Promise<T>): Promise<T> {
|
|
45
|
+
const configPath = getConfigPath();
|
|
46
|
+
const previous = existsSync(configPath) ? readFileSync(configPath, "utf-8") : undefined;
|
|
47
|
+
mkdirSync(path.dirname(configPath), { recursive: true });
|
|
48
|
+
writeFileSync(configPath, JSON.stringify(config));
|
|
49
|
+
try {
|
|
50
|
+
return await fn();
|
|
51
|
+
} finally {
|
|
52
|
+
if (previous === undefined) rmSync(configPath, { force: true });
|
|
53
|
+
else writeFileSync(configPath, previous);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function withIntercomScope<T>(scopeId: string | undefined, fn: () => T | Promise<T>): Promise<T> {
|
|
58
|
+
const previous = process.env.PI_INTERCOM_SCOPE_ID;
|
|
59
|
+
if (scopeId === undefined) delete process.env.PI_INTERCOM_SCOPE_ID;
|
|
60
|
+
else process.env.PI_INTERCOM_SCOPE_ID = scopeId;
|
|
61
|
+
try {
|
|
62
|
+
return await fn();
|
|
63
|
+
} finally {
|
|
64
|
+
if (previous === undefined) delete process.env.PI_INTERCOM_SCOPE_ID;
|
|
65
|
+
else process.env.PI_INTERCOM_SCOPE_ID = previous;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
37
69
|
async function waitForBrokerReady(broker: ChildProcess): Promise<void> {
|
|
38
70
|
const stdout = broker.stdout;
|
|
39
71
|
if (!stdout) throw new Error("Broker stdout is unavailable");
|
|
@@ -145,13 +177,15 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
|
|
|
145
177
|
mode?: "tui" | "rpc" | "json" | "print";
|
|
146
178
|
ui?: unknown;
|
|
147
179
|
sessionId?: string | (() => string);
|
|
180
|
+
activeTools?: string[];
|
|
148
181
|
} = {}) {
|
|
149
182
|
const events = new EventEmitter();
|
|
150
183
|
const lifecycleHandlers = new Map<string, Array<(event: unknown, ctx: unknown) => unknown>>();
|
|
151
184
|
const commands = new Map<string, (args: string, ctx: unknown) => unknown>();
|
|
152
185
|
const tools: CapturedTool[] = [];
|
|
186
|
+
let activeToolNames = [...(options.activeTools ?? [])];
|
|
153
187
|
const entries: Array<{ type: string; data: unknown }> = [];
|
|
154
|
-
const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string } }> = [];
|
|
188
|
+
const sentMessages: Array<{ message: { customType?: string; content?: string; details?: unknown }; options?: { triggerTurn?: boolean; deliverAs?: string }; activeTools: string[] }> = [];
|
|
155
189
|
const pi = {
|
|
156
190
|
getSessionName: () => typeof sessionName === "function" ? sessionName() : sessionName,
|
|
157
191
|
events: {
|
|
@@ -169,13 +203,16 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
|
|
|
169
203
|
registerMessageRenderer: () => undefined,
|
|
170
204
|
registerTool: (tool: CapturedTool) => {
|
|
171
205
|
tools.push(tool);
|
|
206
|
+
if (!activeToolNames.includes(tool.name)) activeToolNames.push(tool.name);
|
|
172
207
|
},
|
|
208
|
+
getActiveTools: () => [...activeToolNames],
|
|
209
|
+
setActiveTools: (names: string[]) => { activeToolNames = [...names]; },
|
|
173
210
|
registerCommand: (name: string, command: { handler: (args: string, ctx: unknown) => unknown }) => {
|
|
174
211
|
commands.set(name, command.handler);
|
|
175
212
|
},
|
|
176
213
|
registerShortcut: () => undefined,
|
|
177
214
|
sendMessage: (message: { customType?: string; content?: string; details?: unknown }, options?: { triggerTurn?: boolean; deliverAs?: string }) => {
|
|
178
|
-
sentMessages.push({ message, options });
|
|
215
|
+
sentMessages.push({ message, options, activeTools: [...activeToolNames] });
|
|
179
216
|
},
|
|
180
217
|
appendEntry: (type: string, data: unknown) => entries.push({ type, data }),
|
|
181
218
|
};
|
|
@@ -196,6 +233,7 @@ function createExtensionHarness(sessionName: string | (() => string) = "child-wo
|
|
|
196
233
|
commands,
|
|
197
234
|
entries,
|
|
198
235
|
sentMessages,
|
|
236
|
+
getActiveTools: () => pi.getActiveTools(),
|
|
199
237
|
async emitLifecycle(event: string, payload: unknown = {}, eventContext: unknown = ctx) {
|
|
200
238
|
for (const handler of lifecycleHandlers.get(event) ?? []) {
|
|
201
239
|
await handler(payload, eventContext);
|
|
@@ -353,7 +391,7 @@ test("opt-in TCP broker requires endpoint state for health and registration", {
|
|
|
353
391
|
assert.deepEqual(registerMessages, [{
|
|
354
392
|
type: "registered",
|
|
355
393
|
sessionId: "authorized-tcp-client",
|
|
356
|
-
features: ["extension-bus-v1"],
|
|
394
|
+
features: ["extension-bus-v1", "exact-send-v1"],
|
|
357
395
|
}]);
|
|
358
396
|
} finally {
|
|
359
397
|
if (broker.exitCode === null && broker.signalCode === null) {
|
|
@@ -410,6 +448,17 @@ async function setupClients() {
|
|
|
410
448
|
}
|
|
411
449
|
}
|
|
412
450
|
|
|
451
|
+
async function connectClientWithScope(client: InstanceType<typeof IntercomClient>, scopeId: string | undefined, sessionId: string, name: string): Promise<void> {
|
|
452
|
+
await withIntercomScope(scopeId, () => client.connect({
|
|
453
|
+
name,
|
|
454
|
+
cwd: repoDir,
|
|
455
|
+
model: "test-model",
|
|
456
|
+
pid: process.pid,
|
|
457
|
+
startedAt: Date.now(),
|
|
458
|
+
lastActivity: Date.now(),
|
|
459
|
+
}, sessionId));
|
|
460
|
+
}
|
|
461
|
+
|
|
413
462
|
function waitForReply(client: InstanceType<typeof IntercomClient>, replyTo: string, timeoutMs = 5000): Promise<{ from: SessionInfo; message: Message; }> {
|
|
414
463
|
return new Promise((resolve, reject) => {
|
|
415
464
|
const timeout = setTimeout(() => {
|
|
@@ -428,6 +477,54 @@ function waitForReply(client: InstanceType<typeof IntercomClient>, replyTo: stri
|
|
|
428
477
|
});
|
|
429
478
|
}
|
|
430
479
|
|
|
480
|
+
function waitForOutboxResults(results: IntercomOutboxResultV1[], count: number, timeoutMs = 3000): Promise<IntercomOutboxResultV1[]> {
|
|
481
|
+
return new Promise((resolve, reject) => {
|
|
482
|
+
const deadline = Date.now() + timeoutMs;
|
|
483
|
+
const check = () => {
|
|
484
|
+
if (results.length >= count) {
|
|
485
|
+
resolve(results.slice(0, count));
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (Date.now() >= deadline) {
|
|
489
|
+
reject(new Error(`Timed out waiting for ${count} outbox result(s); saw ${JSON.stringify(results)}`));
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
setTimeout(check, 10);
|
|
493
|
+
};
|
|
494
|
+
check();
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
async function waitForReplyMessage(messages: Message[], messageId: string, timeoutMs = 3000): Promise<Message> {
|
|
499
|
+
const deadline = Date.now() + timeoutMs;
|
|
500
|
+
while (Date.now() < deadline) {
|
|
501
|
+
const message = messages.find((candidate) => candidate.id === messageId);
|
|
502
|
+
if (message) return message;
|
|
503
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
504
|
+
}
|
|
505
|
+
throw new Error(`Timed out waiting for message ${messageId}`);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function pendingAskRecordPath(messageId: string): string {
|
|
509
|
+
return path.join(sharedHomeDir, ".selesai", "agent", "intercom", "pending-asks", `${encodeURIComponent(messageId)}.json`);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
function readPendingAskRecord(messageId: string): Record<string, unknown> {
|
|
513
|
+
return JSON.parse(readFileSync(pendingAskRecordPath(messageId), "utf-8")) as Record<string, unknown>;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
async function waitForPendingAskRecordRemoved(messageId: string): Promise<void> {
|
|
517
|
+
const filePath = pendingAskRecordPath(messageId);
|
|
518
|
+
const deadline = Date.now() + 1000;
|
|
519
|
+
while (Date.now() < deadline) {
|
|
520
|
+
if (!existsSync(filePath)) {
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
524
|
+
}
|
|
525
|
+
assert.equal(existsSync(filePath), false);
|
|
526
|
+
}
|
|
527
|
+
|
|
431
528
|
async function waitForSessionByName(client: InstanceType<typeof IntercomClient>, name: string): Promise<SessionInfo> {
|
|
432
529
|
const deadline = Date.now() + 2000;
|
|
433
530
|
while (Date.now() < deadline) {
|
|
@@ -558,6 +655,300 @@ test("broker accepts caller supplied stable IDs across reconnect", { concurrency
|
|
|
558
655
|
}
|
|
559
656
|
});
|
|
560
657
|
|
|
658
|
+
test("broker scopes discovery, routing, mailbox, and presence", { concurrency: false }, async () => {
|
|
659
|
+
const broker = spawn(process.execPath, [getTsxCliPath(), path.join(repoDir, "broker", "broker.ts")], {
|
|
660
|
+
cwd: repoDir,
|
|
661
|
+
env: { ...process.env, HOME: sharedHomeDir, USERPROFILE: sharedHomeDir },
|
|
662
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
663
|
+
});
|
|
664
|
+
const clients: Array<InstanceType<typeof IntercomClient>> = [];
|
|
665
|
+
try {
|
|
666
|
+
await waitForBrokerReady(broker);
|
|
667
|
+
const unscopedA = new IntercomClient();
|
|
668
|
+
const unscopedB = new IntercomClient();
|
|
669
|
+
const alphaSender = new IntercomClient();
|
|
670
|
+
const alphaTarget = new IntercomClient();
|
|
671
|
+
const betaTarget = new IntercomClient();
|
|
672
|
+
clients.push(unscopedA, unscopedB, alphaSender, alphaTarget, betaTarget);
|
|
673
|
+
|
|
674
|
+
const alphaEvents: BrokerMessage[] = [];
|
|
675
|
+
const alphaMessages: Message[] = [];
|
|
676
|
+
const betaMessages: Message[] = [];
|
|
677
|
+
alphaSender.onBrokerMessage((message) => alphaEvents.push(message));
|
|
678
|
+
alphaTarget.on("message", (_from: SessionInfo, message: Message) => alphaMessages.push(message));
|
|
679
|
+
betaTarget.on("message", (_from: SessionInfo, message: Message) => betaMessages.push(message));
|
|
680
|
+
|
|
681
|
+
await connectClientWithScope(unscopedA, undefined, "unscoped-a", "unscoped-a");
|
|
682
|
+
await connectClientWithScope(unscopedB, undefined, "unscoped-b", "unscoped-b");
|
|
683
|
+
await connectClientWithScope(alphaSender, " alpha-scope ", "alpha-sender", "alpha-sender");
|
|
684
|
+
await connectClientWithScope(betaTarget, "beta-scope", "shared-target-id", "shared-target");
|
|
685
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
686
|
+
assert.equal(alphaEvents.some((message) => message.type === "session_joined" && message.session.id === "shared-target-id"), false);
|
|
687
|
+
|
|
688
|
+
await connectClientWithScope(alphaTarget, "alpha-scope", "shared-target-id", "shared-target");
|
|
689
|
+
await waitForSessionByName(alphaSender, "shared-target");
|
|
690
|
+
assert.equal((await unscopedA.listSessions()).some((session) => session.id === "shared-target-id"), false);
|
|
691
|
+
assert.equal((await alphaSender.listSessions()).some((session) => session.id === "unscoped-b"), false);
|
|
692
|
+
assert.equal((await unscopedA.listSessions()).some((session) => session.id === "unscoped-b"), true);
|
|
693
|
+
assert.equal((await alphaSender.listSessions()).filter((session) => session.cwd === repoDir && session.name === "shared-target").length, 1);
|
|
694
|
+
|
|
695
|
+
betaTarget.updatePresence({ status: "beta-only" });
|
|
696
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
697
|
+
assert.equal(alphaEvents.some((message) => message.type === "presence_update" && message.session.status === "beta-only"), false);
|
|
698
|
+
alphaTarget.updatePresence({ status: "alpha-visible" });
|
|
699
|
+
await waitForSessionStatus(alphaSender, "shared-target", "alpha-visible");
|
|
700
|
+
|
|
701
|
+
assert.equal((await unscopedA.send("shared-target-id", { text: "full id must not cross" })).delivered, false);
|
|
702
|
+
assert.equal((await alphaSender.send("unscoped-b", { text: "unscoped id must not cross" })).delivered, false);
|
|
703
|
+
assert.equal((await alphaSender.send("shared-target", { messageId: "alpha-name-scope", text: "name stays in scope" })).delivered, true);
|
|
704
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
705
|
+
assert.equal(alphaMessages.some((message) => message.id === "alpha-name-scope"), true);
|
|
706
|
+
assert.equal(betaMessages.some((message) => message.id === "alpha-name-scope"), false);
|
|
707
|
+
|
|
708
|
+
await alphaTarget.disconnect();
|
|
709
|
+
const crossScopeDisconnected = await unscopedA.send("shared-target-id", {
|
|
710
|
+
messageId: "unscoped-to-scoped-disconnected",
|
|
711
|
+
text: "must not queue across scope",
|
|
712
|
+
});
|
|
713
|
+
assert.equal(crossScopeDisconnected.delivered, false);
|
|
714
|
+
assert.match(crossScopeDisconnected.reason ?? "", /Session not found/);
|
|
715
|
+
|
|
716
|
+
const queued = await alphaSender.send("shared-target-id", {
|
|
717
|
+
messageId: "alpha-scoped-mailbox",
|
|
718
|
+
text: "queued only for alpha",
|
|
719
|
+
});
|
|
720
|
+
assert.equal(queued.delivery, "queued");
|
|
721
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
722
|
+
assert.equal(betaMessages.some((message) => message.id === "alpha-scoped-mailbox"), false);
|
|
723
|
+
|
|
724
|
+
const alphaReplacement = new IntercomClient();
|
|
725
|
+
clients.push(alphaReplacement);
|
|
726
|
+
const recovered: Message[] = [];
|
|
727
|
+
alphaReplacement.on("message", (_from: SessionInfo, message: Message) => recovered.push(message));
|
|
728
|
+
await connectClientWithScope(alphaReplacement, "alpha-scope", "shared-target-id", "shared-target");
|
|
729
|
+
await waitForReplyMessage(recovered, "alpha-scoped-mailbox");
|
|
730
|
+
} finally {
|
|
731
|
+
await Promise.all(clients.map((client) => client.disconnect().catch(() => undefined)));
|
|
732
|
+
if (broker.exitCode === null && broker.signalCode === null) broker.kill("SIGTERM");
|
|
733
|
+
await once(broker, "exit").catch(() => undefined);
|
|
734
|
+
}
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
test("broker rotates endpoint epochs and replays same message ids without duplicate delivery", { concurrency: false }, async () => {
|
|
738
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
739
|
+
const replacement = new IntercomClient();
|
|
740
|
+
const received: Message[] = [];
|
|
741
|
+
orchestrator.on("message", (_from: SessionInfo, message: Message) => received.push(message));
|
|
742
|
+
|
|
743
|
+
try {
|
|
744
|
+
const firstEndpoint = await waitForSessionByName(planner, "orchestrator");
|
|
745
|
+
assert.equal(typeof firstEndpoint.endpointEpoch, "string");
|
|
746
|
+
|
|
747
|
+
const messageId = "endpoint-epoch-replay";
|
|
748
|
+
const first = await planner.send(orchestrator.sessionId!, { text: "deliver once", messageId });
|
|
749
|
+
const replay = await planner.send(orchestrator.sessionId!, { text: "deliver once", messageId });
|
|
750
|
+
assert.deepEqual([first.delivery, replay.delivery], ["socket_delivered", "socket_delivered"]);
|
|
751
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
752
|
+
assert.equal(received.filter((message) => message.id === messageId).length, 1);
|
|
753
|
+
|
|
754
|
+
await replacement.connect({
|
|
755
|
+
name: "orchestrator-replacement",
|
|
756
|
+
cwd: repoDir,
|
|
757
|
+
model: "test-model",
|
|
758
|
+
pid: process.pid,
|
|
759
|
+
startedAt: Date.now(),
|
|
760
|
+
lastActivity: Date.now(),
|
|
761
|
+
}, orchestrator.sessionId!);
|
|
762
|
+
const replacedEndpoint = await waitForSessionId(planner, orchestrator.sessionId!);
|
|
763
|
+
assert.notEqual(replacedEndpoint.endpointEpoch, firstEndpoint.endpointEpoch);
|
|
764
|
+
} finally {
|
|
765
|
+
await replacement.disconnect().catch(() => undefined);
|
|
766
|
+
await cleanup();
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
test("delivery records keep colon-containing sender and message IDs distinct", { concurrency: false }, async () => {
|
|
771
|
+
const { orchestrator, cleanup } = await setupClients();
|
|
772
|
+
const first = new IntercomClient();
|
|
773
|
+
const second = new IntercomClient();
|
|
774
|
+
const received: Message[] = [];
|
|
775
|
+
orchestrator.on("message", (_from: SessionInfo, message: Message) => received.push(message));
|
|
776
|
+
|
|
777
|
+
try {
|
|
778
|
+
await first.connect({ name: "record-key-first", cwd: repoDir, model: "test-model", pid: process.pid, startedAt: Date.now(), lastActivity: Date.now() }, "a:b");
|
|
779
|
+
await second.connect({ name: "record-key-second", cwd: repoDir, model: "test-model", pid: process.pid, startedAt: Date.now(), lastActivity: Date.now() }, "a");
|
|
780
|
+
|
|
781
|
+
assert.equal((await first.send(orchestrator.sessionId!, { messageId: "c", text: "same fingerprint" })).delivered, true);
|
|
782
|
+
assert.equal((await second.send(orchestrator.sessionId!, { messageId: "b:c", text: "same fingerprint" })).delivered, true);
|
|
783
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
784
|
+
assert.deepEqual(received.map((message) => message.id).sort(), ["b:c", "c"]);
|
|
785
|
+
} finally {
|
|
786
|
+
await first.disconnect().catch(() => undefined);
|
|
787
|
+
await second.disconnect().catch(() => undefined);
|
|
788
|
+
await cleanup();
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
test("client re-resolves a rebound exact target once with the same message id", { concurrency: false }, async () => {
|
|
793
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
794
|
+
const replacement = new IntercomClient();
|
|
795
|
+
const replacementReceived = once(replacement, "message") as Promise<[SessionInfo, Message]>;
|
|
796
|
+
const listSessions = planner.listSessions.bind(planner);
|
|
797
|
+
let listCalls = 0;
|
|
798
|
+
|
|
799
|
+
try {
|
|
800
|
+
(planner as unknown as { listSessions: () => Promise<SessionInfo[]> }).listSessions = async () => {
|
|
801
|
+
const sessions = await listSessions();
|
|
802
|
+
listCalls += 1;
|
|
803
|
+
if (listCalls === 1) {
|
|
804
|
+
await replacement.connect({
|
|
805
|
+
name: "orchestrator-replacement",
|
|
806
|
+
cwd: repoDir,
|
|
807
|
+
model: "test-model",
|
|
808
|
+
pid: process.pid,
|
|
809
|
+
startedAt: Date.now(),
|
|
810
|
+
lastActivity: Date.now(),
|
|
811
|
+
}, orchestrator.sessionId!);
|
|
812
|
+
}
|
|
813
|
+
return sessions;
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
const result = await planner.send(orchestrator.sessionId!, { text: "retry after rebound", messageId: "endpoint-rebound-retry" });
|
|
817
|
+
assert.equal(result.delivered, true);
|
|
818
|
+
assert.equal(result.delivery, "socket_delivered");
|
|
819
|
+
const [, message] = await replacementReceived;
|
|
820
|
+
assert.equal(message.id, "endpoint-rebound-retry");
|
|
821
|
+
assert.equal(listCalls, 2);
|
|
822
|
+
} finally {
|
|
823
|
+
await replacement.disconnect().catch(() => undefined);
|
|
824
|
+
await cleanup();
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
test("broker rejects malformed exact target fields instead of falling back to name routing", { concurrency: false }, async () => {
|
|
829
|
+
const { orchestrator, cleanup } = await setupClients();
|
|
830
|
+
const raw = await connectRawRegistered("malformed-exact-sender", "malformed-exact-sender");
|
|
831
|
+
const { createMessageReader } = await import("./broker/framing.ts");
|
|
832
|
+
|
|
833
|
+
try {
|
|
834
|
+
const delivery = new Promise<Record<string, unknown>>((resolve, reject) => {
|
|
835
|
+
const reader = createMessageReader((received) => {
|
|
836
|
+
if (typeof received === "object" && received !== null && "type" in received && received.type === "delivery_failed") {
|
|
837
|
+
raw.socket.off("data", reader);
|
|
838
|
+
resolve(received as Record<string, unknown>);
|
|
839
|
+
}
|
|
840
|
+
}, reject);
|
|
841
|
+
raw.socket.on("data", reader);
|
|
842
|
+
});
|
|
843
|
+
raw.writeMessage(raw.socket, {
|
|
844
|
+
type: "send",
|
|
845
|
+
to: orchestrator.sessionId,
|
|
846
|
+
targetId: "",
|
|
847
|
+
targetEpoch: "",
|
|
848
|
+
message: {
|
|
849
|
+
id: "malformed-exact-target",
|
|
850
|
+
timestamp: Date.now(),
|
|
851
|
+
content: { text: "must not reach orchestrator" },
|
|
852
|
+
},
|
|
853
|
+
});
|
|
854
|
+
const result = await delivery;
|
|
855
|
+
assert.equal(result.code, "E_INVALID_TARGET");
|
|
856
|
+
} finally {
|
|
857
|
+
raw.socket.destroy();
|
|
858
|
+
await cleanup();
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
test("broker rejects changed message content after a rebound exact-target failure", { concurrency: false }, async () => {
|
|
863
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
864
|
+
const raw = await connectRawRegistered("rebound-reuse-sender", "rebound-reuse-sender");
|
|
865
|
+
const replacement = new IntercomClient();
|
|
866
|
+
const { createMessageReader } = await import("./broker/framing.ts");
|
|
867
|
+
|
|
868
|
+
try {
|
|
869
|
+
const targetId = orchestrator.sessionId!;
|
|
870
|
+
const oldTarget = await waitForSessionId(planner, targetId);
|
|
871
|
+
await replacement.connect({
|
|
872
|
+
name: "rebound-reuse-replacement",
|
|
873
|
+
cwd: repoDir,
|
|
874
|
+
model: "test-model",
|
|
875
|
+
pid: process.pid,
|
|
876
|
+
startedAt: Date.now(),
|
|
877
|
+
lastActivity: Date.now(),
|
|
878
|
+
}, targetId);
|
|
879
|
+
const receiveDelivery = () => new Promise<Record<string, unknown>>((resolve, reject) => {
|
|
880
|
+
const reader = createMessageReader((received) => {
|
|
881
|
+
if (typeof received === "object" && received !== null && "type" in received && (received.type === "delivered" || received.type === "delivery_failed")) {
|
|
882
|
+
raw.socket.off("data", reader);
|
|
883
|
+
resolve(received as Record<string, unknown>);
|
|
884
|
+
}
|
|
885
|
+
}, reject);
|
|
886
|
+
raw.socket.on("data", reader);
|
|
887
|
+
});
|
|
888
|
+
const send = (text: string) => raw.writeMessage(raw.socket, {
|
|
889
|
+
type: "send",
|
|
890
|
+
to: targetId,
|
|
891
|
+
targetId,
|
|
892
|
+
targetEpoch: oldTarget.endpointEpoch,
|
|
893
|
+
message: { id: "rebound-id-reuse", timestamp: Date.now(), content: { text } },
|
|
894
|
+
});
|
|
895
|
+
|
|
896
|
+
const firstDelivery = receiveDelivery();
|
|
897
|
+
send("first content");
|
|
898
|
+
assert.equal((await firstDelivery).code, "E_TARGET_REBOUND");
|
|
899
|
+
const secondDelivery = receiveDelivery();
|
|
900
|
+
send("changed content");
|
|
901
|
+
assert.equal((await secondDelivery).code, "E_MESSAGE_ID_REUSE");
|
|
902
|
+
} finally {
|
|
903
|
+
raw.socket.destroy();
|
|
904
|
+
await replacement.disconnect().catch(() => undefined);
|
|
905
|
+
await cleanup();
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
test("broker propagates a session's tmux pane id into the roster", { concurrency: false }, async () => {
|
|
910
|
+
const { planner, cleanup } = await setupClients();
|
|
911
|
+
const worker = new IntercomClient();
|
|
912
|
+
|
|
913
|
+
try {
|
|
914
|
+
await worker.connect({
|
|
915
|
+
name: "tmux-worker",
|
|
916
|
+
cwd: repoDir,
|
|
917
|
+
model: "test-model",
|
|
918
|
+
pid: process.pid,
|
|
919
|
+
startedAt: Date.now(),
|
|
920
|
+
lastActivity: Date.now(),
|
|
921
|
+
tmuxPane: "%212",
|
|
922
|
+
});
|
|
923
|
+
const session = await waitForSessionByName(planner, "tmux-worker");
|
|
924
|
+
assert.equal(session.tmuxPane, "%212");
|
|
925
|
+
} finally {
|
|
926
|
+
await worker.disconnect().catch(() => undefined);
|
|
927
|
+
await cleanup();
|
|
928
|
+
}
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
test("broker omits tmux pane id for sessions outside tmux", { concurrency: false }, async () => {
|
|
932
|
+
const { planner, cleanup } = await setupClients();
|
|
933
|
+
const worker = new IntercomClient();
|
|
934
|
+
|
|
935
|
+
try {
|
|
936
|
+
await worker.connect({
|
|
937
|
+
name: "paneless-worker",
|
|
938
|
+
cwd: repoDir,
|
|
939
|
+
model: "test-model",
|
|
940
|
+
pid: process.pid,
|
|
941
|
+
startedAt: Date.now(),
|
|
942
|
+
lastActivity: Date.now(),
|
|
943
|
+
});
|
|
944
|
+
const session = await waitForSessionByName(planner, "paneless-worker");
|
|
945
|
+
assert.equal(session.tmuxPane, undefined);
|
|
946
|
+
} finally {
|
|
947
|
+
await worker.disconnect().catch(() => undefined);
|
|
948
|
+
await cleanup();
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
|
|
561
952
|
test("broker owns local trust metadata instead of trusting registration payloads", { concurrency: false }, async () => {
|
|
562
953
|
const { planner, cleanup } = await setupClients();
|
|
563
954
|
const raw = await connectRawRegistered("trust-metadata-worker-id", "trust-metadata-worker", {
|
|
@@ -768,7 +1159,7 @@ test("old stable-ID socket cannot mutate the replacement session", { concurrency
|
|
|
768
1159
|
}
|
|
769
1160
|
});
|
|
770
1161
|
|
|
771
|
-
test("stable-ID replacement
|
|
1162
|
+
test("stable-ID replacement preserves old ask edges and ignores stale cancels", { concurrency: false }, async () => {
|
|
772
1163
|
const { orchestrator, cleanup } = await setupClients();
|
|
773
1164
|
const first = await connectRawRegistered("replaceable-asker-id", "replaceable-asker-old");
|
|
774
1165
|
const replacement = new IntercomClient();
|
|
@@ -790,6 +1181,13 @@ test("stable-ID replacement clears old ask edges and ignores stale cancels", { c
|
|
|
790
1181
|
lastActivity: Date.now(),
|
|
791
1182
|
}, "replaceable-asker-id");
|
|
792
1183
|
|
|
1184
|
+
const oldReply = once(replacement, "message") as Promise<[SessionInfo, Message]>;
|
|
1185
|
+
assert.equal((await orchestrator.send("replaceable-asker-id", {
|
|
1186
|
+
text: "Old ask answered after replacement.",
|
|
1187
|
+
replyTo: "old-ask-edge",
|
|
1188
|
+
})).delivered, true);
|
|
1189
|
+
assert.equal((await oldReply)[1].replyTo, "old-ask-edge");
|
|
1190
|
+
|
|
793
1191
|
const reverseAfterReplace = await orchestrator.send("replaceable-asker-id", {
|
|
794
1192
|
messageId: "reverse-after-replace",
|
|
795
1193
|
text: "Can I ask the replacement?",
|
|
@@ -876,6 +1274,9 @@ test("intercom tool prefers exact names over ID prefixes", { concurrency: false
|
|
|
876
1274
|
]);
|
|
877
1275
|
const result = await intercomTool.execute("send-exact-name", { action: "send", to: "orchestrator", message: "exact name wins" }, new AbortController().signal, undefined, harness.ctx);
|
|
878
1276
|
assert.notEqual(result.details?.error, true);
|
|
1277
|
+
assert.equal(result.details?.delivery, "socket_delivered");
|
|
1278
|
+
assert.equal(result.details?.retryable, false);
|
|
1279
|
+
assert.equal(result.details?.outcomeKnown, true);
|
|
879
1280
|
|
|
880
1281
|
const received = await exactNameReceived;
|
|
881
1282
|
assert.notEqual(received, null);
|
|
@@ -929,7 +1330,7 @@ test("intercom-id inserts a stable handoff snippet into the editor", { concurren
|
|
|
929
1330
|
piIntercomExtension(harness.pi as never);
|
|
930
1331
|
await harness.emitLifecycle("session_start");
|
|
931
1332
|
await harness.commands.get("intercom-id")!("", harness.ctx);
|
|
932
|
-
assert.match(editorText, /Existing note\n\nUse
|
|
1333
|
+
assert.match(editorText, /Existing note\n\nUse pi-intercom: intercom\(\{ action: "send", to: "session-child-test", message: "\.\.\." \}\)/);
|
|
933
1334
|
assert.match(notifications.at(-1) ?? "", /Inserted intercom contact target: session-child-test/);
|
|
934
1335
|
await harness.emitLifecycle("session_shutdown");
|
|
935
1336
|
} finally {
|
|
@@ -1062,6 +1463,161 @@ test("late extension registration advertises before an onReady publish", { concu
|
|
|
1062
1463
|
}
|
|
1063
1464
|
});
|
|
1064
1465
|
|
|
1466
|
+
test("extension outbox sends notify-only messages with trace and provenance", { concurrency: false }, async () => {
|
|
1467
|
+
const { planner, cleanup } = await setupClients();
|
|
1468
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1469
|
+
const harness = createExtensionHarness("outbox-worker");
|
|
1470
|
+
const results: IntercomOutboxResultV1[] = [];
|
|
1471
|
+
|
|
1472
|
+
try {
|
|
1473
|
+
harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
|
|
1474
|
+
piIntercomExtension(harness.pi as never);
|
|
1475
|
+
await harness.emitLifecycle("session_start");
|
|
1476
|
+
const delivered = once(planner, "message") as Promise<[SessionInfo, Message]>;
|
|
1477
|
+
|
|
1478
|
+
harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
|
|
1479
|
+
version: 1,
|
|
1480
|
+
requestId: "outbox-success-1",
|
|
1481
|
+
extensionId: "example-extension",
|
|
1482
|
+
extensionName: "Example Extension",
|
|
1483
|
+
to: "planner",
|
|
1484
|
+
message: "Outbox hello.",
|
|
1485
|
+
});
|
|
1486
|
+
|
|
1487
|
+
const [result] = await waitForOutboxResults(results, 1);
|
|
1488
|
+
assert.equal(result?.status, "sent");
|
|
1489
|
+
assert.equal(result?.messageId, "outbox-success-1");
|
|
1490
|
+
const [, message] = await Promise.race([
|
|
1491
|
+
delivered,
|
|
1492
|
+
new Promise<never>((_resolve, reject) => setTimeout(() => reject(new Error("Timed out waiting for outbox delivery")), 3000)),
|
|
1493
|
+
]);
|
|
1494
|
+
assert.equal(message.id, "outbox-success-1");
|
|
1495
|
+
assert.equal(message.content.text, "Outbox hello.");
|
|
1496
|
+
assert.deepEqual(message.provenance, {
|
|
1497
|
+
type: "extension_outbox",
|
|
1498
|
+
extensionId: "example-extension",
|
|
1499
|
+
extensionName: "Example Extension",
|
|
1500
|
+
requestId: "outbox-success-1",
|
|
1501
|
+
});
|
|
1502
|
+
assert.equal(harness.entries.some((entry) => entry.type === "intercom_sent"
|
|
1503
|
+
&& (entry.data as { extension?: { requestId?: string } }).extension?.requestId === "outbox-success-1"), true);
|
|
1504
|
+
assert.equal(harness.entries.some((entry) => entry.type === "intercom_outbox_result"
|
|
1505
|
+
&& (entry.data as { requestId?: string; status?: string }).requestId === "outbox-success-1"
|
|
1506
|
+
&& (entry.data as { requestId?: string; status?: string }).status === "sent"), true);
|
|
1507
|
+
} finally {
|
|
1508
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1509
|
+
await cleanup();
|
|
1510
|
+
}
|
|
1511
|
+
});
|
|
1512
|
+
|
|
1513
|
+
test("extension outbox rejects duplicate request ids without duplicate delivery", { concurrency: false }, async () => {
|
|
1514
|
+
const { planner, cleanup } = await setupClients();
|
|
1515
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1516
|
+
const harness = createExtensionHarness("outbox-duplicate-worker");
|
|
1517
|
+
const results: IntercomOutboxResultV1[] = [];
|
|
1518
|
+
const deliveredMessages: Message[] = [];
|
|
1519
|
+
|
|
1520
|
+
try {
|
|
1521
|
+
planner.on("message", (_from: SessionInfo, message: Message) => deliveredMessages.push(message));
|
|
1522
|
+
harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
|
|
1523
|
+
piIntercomExtension(harness.pi as never);
|
|
1524
|
+
await harness.emitLifecycle("session_start");
|
|
1525
|
+
|
|
1526
|
+
const request = {
|
|
1527
|
+
version: 1,
|
|
1528
|
+
requestId: "outbox-duplicate-1",
|
|
1529
|
+
extensionId: "example-extension",
|
|
1530
|
+
extensionName: "Example Extension",
|
|
1531
|
+
to: "planner",
|
|
1532
|
+
message: "Deliver once.",
|
|
1533
|
+
};
|
|
1534
|
+
harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, request);
|
|
1535
|
+
await waitForOutboxResults(results, 1);
|
|
1536
|
+
harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, request);
|
|
1537
|
+
|
|
1538
|
+
const [, duplicate] = await waitForOutboxResults(results, 2);
|
|
1539
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1540
|
+
assert.equal(duplicate?.status, "rejected");
|
|
1541
|
+
assert.equal(duplicate?.code, "duplicate_request");
|
|
1542
|
+
assert.equal(deliveredMessages.filter((message) => message.id === "outbox-duplicate-1").length, 1);
|
|
1543
|
+
} finally {
|
|
1544
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1545
|
+
await cleanup();
|
|
1546
|
+
}
|
|
1547
|
+
});
|
|
1548
|
+
|
|
1549
|
+
test("extension outbox fails closed when confirmation needs unavailable UI", async () => {
|
|
1550
|
+
await withConfirmSendEnabled(async () => {
|
|
1551
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1552
|
+
const harness = createExtensionHarness("outbox-no-ui", { hasUI: false });
|
|
1553
|
+
const results: IntercomOutboxResultV1[] = [];
|
|
1554
|
+
|
|
1555
|
+
harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
|
|
1556
|
+
piIntercomExtension(harness.pi as never);
|
|
1557
|
+
await harness.emitLifecycle("session_start");
|
|
1558
|
+
harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
|
|
1559
|
+
version: 1,
|
|
1560
|
+
requestId: "outbox-no-ui-1",
|
|
1561
|
+
extensionId: "example-extension",
|
|
1562
|
+
extensionName: "Example Extension",
|
|
1563
|
+
to: "planner",
|
|
1564
|
+
message: "Needs confirmation.",
|
|
1565
|
+
});
|
|
1566
|
+
|
|
1567
|
+
const [result] = await waitForOutboxResults(results, 1);
|
|
1568
|
+
assert.equal(result?.status, "blocked");
|
|
1569
|
+
assert.equal(result?.code, "confirmation_unavailable");
|
|
1570
|
+
assert.equal(harness.entries.some((entry) => entry.type === "intercom_outbox_result"
|
|
1571
|
+
&& (entry.data as { code?: string }).code === "confirmation_unavailable"), true);
|
|
1572
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1573
|
+
});
|
|
1574
|
+
});
|
|
1575
|
+
|
|
1576
|
+
test("extension outbox settles pending confirmation on session shutdown", async () => {
|
|
1577
|
+
await withConfirmSendEnabled(async () => {
|
|
1578
|
+
const { cleanup } = await setupClients();
|
|
1579
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1580
|
+
const confirmCalls: string[] = [];
|
|
1581
|
+
const harness = createExtensionHarness("outbox-shutdown", {
|
|
1582
|
+
hasUI: true,
|
|
1583
|
+
ui: {
|
|
1584
|
+
confirm: (title: string) => {
|
|
1585
|
+
confirmCalls.push(title);
|
|
1586
|
+
return new Promise<boolean>(() => undefined);
|
|
1587
|
+
},
|
|
1588
|
+
},
|
|
1589
|
+
});
|
|
1590
|
+
const results: IntercomOutboxResultV1[] = [];
|
|
1591
|
+
|
|
1592
|
+
try {
|
|
1593
|
+
harness.pi.events.on(INTERCOM_OUTBOX_RESULT_EVENT, (payload) => results.push(payload as IntercomOutboxResultV1));
|
|
1594
|
+
piIntercomExtension(harness.pi as never);
|
|
1595
|
+
await harness.emitLifecycle("session_start");
|
|
1596
|
+
harness.pi.events.emit(INTERCOM_OUTBOX_REQUEST_EVENT, {
|
|
1597
|
+
version: 1,
|
|
1598
|
+
requestId: "outbox-shutdown-1",
|
|
1599
|
+
extensionId: "example-extension",
|
|
1600
|
+
extensionName: "Example Extension",
|
|
1601
|
+
to: "planner",
|
|
1602
|
+
message: "Will shut down.",
|
|
1603
|
+
});
|
|
1604
|
+
const deadline = Date.now() + 3000;
|
|
1605
|
+
while (confirmCalls.length === 0 && Date.now() < deadline) {
|
|
1606
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
1607
|
+
}
|
|
1608
|
+
assert.equal(confirmCalls.length, 1);
|
|
1609
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1610
|
+
|
|
1611
|
+
const [result] = await waitForOutboxResults(results, 1);
|
|
1612
|
+
assert.equal(result?.status, "failed");
|
|
1613
|
+
assert.equal(result?.code, "session_ended");
|
|
1614
|
+
} finally {
|
|
1615
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1616
|
+
await cleanup();
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1065
1621
|
test("intercom tool renders compact call and result rows", async () => {
|
|
1066
1622
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1067
1623
|
const harness = createExtensionHarness();
|
|
@@ -1116,6 +1672,115 @@ test("intercom tool result hook marks failed details as errors", async () => {
|
|
|
1116
1672
|
assert.deepEqual(okResults.filter(Boolean), []);
|
|
1117
1673
|
});
|
|
1118
1674
|
|
|
1675
|
+
test("lazy tool visibility reveals intercom on bundled skill use only", { concurrency: false }, async () => {
|
|
1676
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1677
|
+
|
|
1678
|
+
await withIntercomConfig({ toolVisibility: "after-first-use" }, () => withChildOrchestratorEnv({
|
|
1679
|
+
orchestratorTarget: "orchestrator",
|
|
1680
|
+
runId: "78f659a3",
|
|
1681
|
+
agent: "worker",
|
|
1682
|
+
index: "0",
|
|
1683
|
+
}, async () => {
|
|
1684
|
+
const harness = createExtensionHarness("lazy-skill-worker", { activeTools: ["read", "bash"] });
|
|
1685
|
+
piIntercomExtension(harness.pi as never);
|
|
1686
|
+
|
|
1687
|
+
try {
|
|
1688
|
+
await harness.emitLifecycle("session_start");
|
|
1689
|
+
assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor"]);
|
|
1690
|
+
|
|
1691
|
+
harness.pi.events.emit("subagent:control-intercom", {
|
|
1692
|
+
to: "session-child-test",
|
|
1693
|
+
message: "Local relay traffic should not reveal the generic tool.",
|
|
1694
|
+
});
|
|
1695
|
+
assert.equal(harness.sentMessages.at(-1)?.activeTools.includes("intercom"), false);
|
|
1696
|
+
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1697
|
+
|
|
1698
|
+
await harness.emitLifecycle("tool_result", {
|
|
1699
|
+
toolName: "read",
|
|
1700
|
+
input: { path: path.join(repoDir, "README.md") },
|
|
1701
|
+
isError: false,
|
|
1702
|
+
});
|
|
1703
|
+
await harness.emitLifecycle("tool_result", {
|
|
1704
|
+
toolName: "read",
|
|
1705
|
+
input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
|
|
1706
|
+
isError: true,
|
|
1707
|
+
});
|
|
1708
|
+
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1709
|
+
|
|
1710
|
+
await harness.emitLifecycle("tool_result", {
|
|
1711
|
+
toolName: "read",
|
|
1712
|
+
input: { path: path.join(repoDir, "skills", "pi-intercom", "SKILL.md") },
|
|
1713
|
+
isError: false,
|
|
1714
|
+
});
|
|
1715
|
+
assert.deepEqual(harness.getActiveTools(), ["read", "bash", "contact_supervisor", "intercom"]);
|
|
1716
|
+
|
|
1717
|
+
await harness.emitLifecycle("session_start");
|
|
1718
|
+
assert.equal(harness.getActiveTools().includes("intercom"), false);
|
|
1719
|
+
await harness.emitLifecycle("input", { text: " /skill: pi-intercom", source: "user" });
|
|
1720
|
+
assert.equal(harness.getActiveTools().includes("intercom"), true);
|
|
1721
|
+
} finally {
|
|
1722
|
+
await harness.emitLifecycle("session_shutdown");
|
|
1723
|
+
}
|
|
1724
|
+
}));
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
test("lazy tool visibility reveals intercom before broker injection and after an overlay send", { concurrency: false }, async () => {
|
|
1728
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1729
|
+
|
|
1730
|
+
await withIntercomConfig({ toolVisibility: "after-first-use" }, async () => {
|
|
1731
|
+
const { planner, cleanup } = await setupClients();
|
|
1732
|
+
let selectedSession: SessionInfo | undefined;
|
|
1733
|
+
let overlayStep = 0;
|
|
1734
|
+
const overlayHarness = createExtensionHarness("lazy-overlay-worker", {
|
|
1735
|
+
hasUI: true,
|
|
1736
|
+
activeTools: ["read"],
|
|
1737
|
+
ui: {
|
|
1738
|
+
notify: () => undefined,
|
|
1739
|
+
custom: async () => {
|
|
1740
|
+
overlayStep += 1;
|
|
1741
|
+
return overlayStep === 1
|
|
1742
|
+
? selectedSession
|
|
1743
|
+
: { sent: true, messageId: "overlay-message", text: "Hello from the overlay" };
|
|
1744
|
+
},
|
|
1745
|
+
},
|
|
1746
|
+
});
|
|
1747
|
+
const inboundHarness = createExtensionHarness("lazy-inbound-worker", {
|
|
1748
|
+
hasUI: true,
|
|
1749
|
+
activeTools: ["read"],
|
|
1750
|
+
});
|
|
1751
|
+
|
|
1752
|
+
try {
|
|
1753
|
+
piIntercomExtension(overlayHarness.pi as never);
|
|
1754
|
+
piIntercomExtension(inboundHarness.pi as never);
|
|
1755
|
+
await overlayHarness.emitLifecycle("session_start");
|
|
1756
|
+
await inboundHarness.emitLifecycle("session_start");
|
|
1757
|
+
assert.equal(overlayHarness.getActiveTools().includes("intercom"), false);
|
|
1758
|
+
assert.equal(inboundHarness.getActiveTools().includes("intercom"), false);
|
|
1759
|
+
|
|
1760
|
+
selectedSession = await waitForSessionByName(planner, "planner");
|
|
1761
|
+
const inboundSession = await waitForSessionByName(planner, "lazy-inbound-worker");
|
|
1762
|
+
const delivered = await planner.send(inboundSession.id, {
|
|
1763
|
+
messageId: "lazy-inbound-message",
|
|
1764
|
+
text: "Reveal intercom before injecting this message.",
|
|
1765
|
+
});
|
|
1766
|
+
assert.equal(delivered.delivered, true);
|
|
1767
|
+
const deadline = Date.now() + 1000;
|
|
1768
|
+
while (inboundHarness.sentMessages.length === 0 && Date.now() < deadline) {
|
|
1769
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
1770
|
+
}
|
|
1771
|
+
assert.equal(inboundHarness.sentMessages[0]?.activeTools.includes("intercom"), true);
|
|
1772
|
+
|
|
1773
|
+
await overlayHarness.commands.get("intercom")!("", overlayHarness.ctx);
|
|
1774
|
+
assert.equal(overlayStep, 2);
|
|
1775
|
+
assert.equal(overlayHarness.getActiveTools().includes("intercom"), true);
|
|
1776
|
+
} finally {
|
|
1777
|
+
await overlayHarness.emitLifecycle("session_shutdown");
|
|
1778
|
+
await inboundHarness.emitLifecycle("session_shutdown");
|
|
1779
|
+
await cleanup();
|
|
1780
|
+
}
|
|
1781
|
+
});
|
|
1782
|
+
});
|
|
1783
|
+
|
|
1119
1784
|
test("contact supervisor tool renders reason and reply state", async () => {
|
|
1120
1785
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1121
1786
|
|
|
@@ -1212,7 +1877,7 @@ test("idle name poll propagates /name changes without other activity", { concurr
|
|
|
1212
1877
|
}
|
|
1213
1878
|
});
|
|
1214
1879
|
|
|
1215
|
-
test("turn_start re-registers when
|
|
1880
|
+
test("turn_start re-registers when Selesai replaces the session context", { concurrency: false }, async () => {
|
|
1216
1881
|
const { planner, cleanup } = await setupClients();
|
|
1217
1882
|
let sessionName = "fork-before";
|
|
1218
1883
|
let sessionId = "session-fork-before";
|
|
@@ -1307,7 +1972,7 @@ test("idle interactive sessions trigger a new turn immediately", { concurrency:
|
|
|
1307
1972
|
}
|
|
1308
1973
|
});
|
|
1309
1974
|
|
|
1310
|
-
test("duplicate
|
|
1975
|
+
test("broker rejects changed duplicate message IDs and replays identical sends without reinjection", { concurrency: false }, async () => {
|
|
1311
1976
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
1312
1977
|
const { planner, cleanup } = await setupClients();
|
|
1313
1978
|
const harness = createExtensionHarness("dedupe-worker", { hasUI: true });
|
|
@@ -1322,8 +1987,13 @@ test("duplicate inbound message IDs inject once with visible delivery metadata",
|
|
|
1322
1987
|
});
|
|
1323
1988
|
|
|
1324
1989
|
try {
|
|
1325
|
-
|
|
1326
|
-
|
|
1990
|
+
const first = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "First copy" });
|
|
1991
|
+
const changed = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "Second copy" });
|
|
1992
|
+
const replay = await planner.send(worker.id, { messageId: "duplicate-inbound", text: "First copy" });
|
|
1993
|
+
assert.equal(first.delivered, true);
|
|
1994
|
+
assert.equal(changed.delivered, false);
|
|
1995
|
+
assert.equal(changed.code, "E_MESSAGE_ID_REUSE");
|
|
1996
|
+
assert.equal(replay.delivered, true);
|
|
1327
1997
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1328
1998
|
} finally {
|
|
1329
1999
|
unsubscribeReceipts();
|
|
@@ -1333,7 +2003,6 @@ test("duplicate inbound message IDs inject once with visible delivery metadata",
|
|
|
1333
2003
|
assert.ok(receipts.includes("receiver_received"));
|
|
1334
2004
|
assert.ok(receipts.includes("acknowledged:accepted by receiver"));
|
|
1335
2005
|
assert.ok(receipts.includes("injected"));
|
|
1336
|
-
assert.ok(receipts.includes("acknowledged:duplicate message id suppressed"));
|
|
1337
2006
|
const sent = harness.sentMessages[0]!;
|
|
1338
2007
|
assert.match(sent.message.content ?? "", /id duplicate-inbound/);
|
|
1339
2008
|
assert.match(sent.message.content ?? "", /seq 1/);
|
|
@@ -2042,6 +2711,103 @@ test("regular intercom asks fail safely when started concurrently", { concurrenc
|
|
|
2042
2711
|
}
|
|
2043
2712
|
});
|
|
2044
2713
|
|
|
2714
|
+
test("broker writes a local pending ask record for delivered blocking asks", { concurrency: false }, async () => {
|
|
2715
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2716
|
+
const askId = "pending-record-live-ask";
|
|
2717
|
+
|
|
2718
|
+
try {
|
|
2719
|
+
const result = await planner.send(orchestrator.sessionId!, {
|
|
2720
|
+
messageId: askId,
|
|
2721
|
+
text: "Can you decide?",
|
|
2722
|
+
expectsReply: true,
|
|
2723
|
+
});
|
|
2724
|
+
|
|
2725
|
+
assert.equal(result.delivered, true);
|
|
2726
|
+
const record = readPendingAskRecord(askId);
|
|
2727
|
+
assert.equal(record.askId, askId);
|
|
2728
|
+
assert.equal(record.messageId, askId);
|
|
2729
|
+
assert.deepEqual(record.asker, { sessionId: planner.sessionId, name: "planner" });
|
|
2730
|
+
assert.deepEqual(record.target, { sessionId: orchestrator.sessionId, name: "orchestrator" });
|
|
2731
|
+
assert.equal(record.question, "Can you decide?");
|
|
2732
|
+
assert.equal(Number(record.expiresAt) - Number(record.createdAt), getAskTimeoutMs());
|
|
2733
|
+
if (process.platform !== "win32") {
|
|
2734
|
+
assert.equal(statSync(pendingAskRecordPath(askId)).mode & 0o777, 0o600);
|
|
2735
|
+
}
|
|
2736
|
+
} finally {
|
|
2737
|
+
await cleanup();
|
|
2738
|
+
}
|
|
2739
|
+
});
|
|
2740
|
+
|
|
2741
|
+
test("broker removes a pending ask record after a delivered reply", { concurrency: false }, async () => {
|
|
2742
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2743
|
+
const askId = "pending-record-replied-ask";
|
|
2744
|
+
|
|
2745
|
+
try {
|
|
2746
|
+
assert.equal((await planner.send(orchestrator.sessionId!, {
|
|
2747
|
+
messageId: askId,
|
|
2748
|
+
text: "Can you answer?",
|
|
2749
|
+
expectsReply: true,
|
|
2750
|
+
})).delivered, true);
|
|
2751
|
+
assert.equal(existsSync(pendingAskRecordPath(askId)), true);
|
|
2752
|
+
|
|
2753
|
+
assert.equal((await orchestrator.send(planner.sessionId!, {
|
|
2754
|
+
text: "Answered.",
|
|
2755
|
+
replyTo: askId,
|
|
2756
|
+
})).delivered, true);
|
|
2757
|
+
|
|
2758
|
+
assert.equal(existsSync(pendingAskRecordPath(askId)), false);
|
|
2759
|
+
} finally {
|
|
2760
|
+
await cleanup();
|
|
2761
|
+
}
|
|
2762
|
+
});
|
|
2763
|
+
|
|
2764
|
+
test("broker removes a pending ask record after asker cancellation", { concurrency: false }, async () => {
|
|
2765
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2766
|
+
const askId = "pending-record-cancelled-ask";
|
|
2767
|
+
|
|
2768
|
+
try {
|
|
2769
|
+
assert.equal((await planner.send(orchestrator.sessionId!, {
|
|
2770
|
+
messageId: askId,
|
|
2771
|
+
text: "Should I stop?",
|
|
2772
|
+
expectsReply: true,
|
|
2773
|
+
})).delivered, true);
|
|
2774
|
+
assert.equal(existsSync(pendingAskRecordPath(askId)), true);
|
|
2775
|
+
|
|
2776
|
+
planner.cancelAsk(askId);
|
|
2777
|
+
await waitForPendingAskRecordRemoved(askId);
|
|
2778
|
+
} finally {
|
|
2779
|
+
await cleanup();
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
|
|
2783
|
+
test("broker removes a pending ask record during timeout pruning", { concurrency: false }, async () => {
|
|
2784
|
+
const previousTimeout = process.env.PI_INTERCOM_ASK_TIMEOUT_MS;
|
|
2785
|
+
process.env.PI_INTERCOM_ASK_TIMEOUT_MS = "50";
|
|
2786
|
+
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2787
|
+
const askId = "pending-record-timeout-ask";
|
|
2788
|
+
|
|
2789
|
+
try {
|
|
2790
|
+
assert.equal((await planner.send(orchestrator.sessionId!, {
|
|
2791
|
+
messageId: askId,
|
|
2792
|
+
text: "Will this expire?",
|
|
2793
|
+
expectsReply: true,
|
|
2794
|
+
})).delivered, true);
|
|
2795
|
+
assert.equal(existsSync(pendingAskRecordPath(askId)), true);
|
|
2796
|
+
|
|
2797
|
+
await new Promise((resolve) => setTimeout(resolve, 80));
|
|
2798
|
+
assert.equal((await planner.send(orchestrator.sessionId!, { text: "Prune asks." })).delivered, true);
|
|
2799
|
+
|
|
2800
|
+
assert.equal(existsSync(pendingAskRecordPath(askId)), false);
|
|
2801
|
+
} finally {
|
|
2802
|
+
if (previousTimeout === undefined) {
|
|
2803
|
+
delete process.env.PI_INTERCOM_ASK_TIMEOUT_MS;
|
|
2804
|
+
} else {
|
|
2805
|
+
process.env.PI_INTERCOM_ASK_TIMEOUT_MS = previousTimeout;
|
|
2806
|
+
}
|
|
2807
|
+
await cleanup();
|
|
2808
|
+
}
|
|
2809
|
+
});
|
|
2810
|
+
|
|
2045
2811
|
test("broker refuses reverse mutual asks until the original ask is answered", { concurrency: false }, async () => {
|
|
2046
2812
|
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2047
2813
|
|
|
@@ -2346,6 +3112,42 @@ test("intercom reply targets exact replyTo when multiple asks are pending", { co
|
|
|
2346
3112
|
}
|
|
2347
3113
|
});
|
|
2348
3114
|
|
|
3115
|
+
test("intercom reply sends attachments", { concurrency: false }, async () => {
|
|
3116
|
+
const { planner, cleanup } = await setupClients();
|
|
3117
|
+
const { default: piIntercomExtension } = await import("./index.ts");
|
|
3118
|
+
const harness = createExtensionHarness("reply-attachment-worker");
|
|
3119
|
+
|
|
3120
|
+
try {
|
|
3121
|
+
piIntercomExtension(harness.pi as never);
|
|
3122
|
+
await harness.emitLifecycle("session_start");
|
|
3123
|
+
const worker = await waitForSessionByName(planner, "reply-attachment-worker");
|
|
3124
|
+
|
|
3125
|
+
const askId = "reply-attachment-ask";
|
|
3126
|
+
assert.equal((await planner.send(worker.id, { messageId: askId, text: "Send details?", expectsReply: true })).delivered, true);
|
|
3127
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
3128
|
+
|
|
3129
|
+
const intercomTool = harness.tools.find((tool) => tool.name === "intercom")!;
|
|
3130
|
+
const attachments = [{ type: "snippet" as const, name: "details.md", content: "attached details", language: "md" }];
|
|
3131
|
+
const replyReceived = waitForReply(planner, askId);
|
|
3132
|
+
const result = await intercomTool.execute("reply-with-attachment", {
|
|
3133
|
+
action: "reply",
|
|
3134
|
+
message: "Here are details.",
|
|
3135
|
+
attachments,
|
|
3136
|
+
}, new AbortController().signal, undefined, harness.ctx);
|
|
3137
|
+
|
|
3138
|
+
assert.equal(result.details?.delivered, true);
|
|
3139
|
+
const reply = await replyReceived;
|
|
3140
|
+
assert.equal(reply.message.content.text, "Here are details.");
|
|
3141
|
+
assert.deepEqual(reply.message.content.attachments, attachments);
|
|
3142
|
+
|
|
3143
|
+
const sentEntry = harness.entries.find((entry) => entry.type === "intercom_sent");
|
|
3144
|
+
assert.deepEqual((sentEntry?.data as { message?: { attachments?: unknown } }).message?.attachments, attachments);
|
|
3145
|
+
} finally {
|
|
3146
|
+
await harness.emitLifecycle("session_shutdown");
|
|
3147
|
+
await cleanup();
|
|
3148
|
+
}
|
|
3149
|
+
});
|
|
3150
|
+
|
|
2349
3151
|
test("intercom reply targets one of multiple pending asks by short session ID", { concurrency: false }, async () => {
|
|
2350
3152
|
const { planner, orchestrator, cleanup } = await setupClients();
|
|
2351
3153
|
const { default: piIntercomExtension } = await import("./index.ts");
|
|
@@ -3423,6 +4225,10 @@ test("failed delivery from an inferred reply preserves the pending ask", { concu
|
|
|
3423
4225
|
}, new AbortController().signal, undefined, harness.ctx);
|
|
3424
4226
|
|
|
3425
4227
|
assert.equal(result.details?.delivered, false);
|
|
4228
|
+
assert.equal(result.details?.delivery, "failed");
|
|
4229
|
+
assert.equal(result.details?.code, "E_AMBIGUOUS_TARGET");
|
|
4230
|
+
assert.equal(result.details?.retryable, false);
|
|
4231
|
+
assert.equal(result.details?.outcomeKnown, true);
|
|
3426
4232
|
assert.match(result.content[0]?.text ?? "", /Multiple disconnected sessions named/);
|
|
3427
4233
|
|
|
3428
4234
|
const pending = await intercomTool.execute("pending-after-failure", { action: "pending" }, new AbortController().signal, undefined, harness.ctx);
|