@selesai/code 0.13.15 → 0.13.18
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 +37 -0
- package/README.md +2 -14
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.js +3 -9
- package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
- package/dist/bun/sandbox-env-setup.d.ts +1 -0
- package/dist/bun/sandbox-env-setup.js +3 -0
- package/dist/cli/auth-command.d.ts +23 -0
- package/dist/cli/auth-command.js +102 -0
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/setup.d.ts +1 -0
- package/dist/cli/setup.js +11 -0
- package/dist/cli.js +2 -14
- package/dist/config.d.ts +3 -2
- package/dist/config.js +9 -4
- package/dist/core/agent-session-runtime.js +15 -7
- package/dist/core/agent-session.d.ts +2 -6
- package/dist/core/agent-session.js +15 -4
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -1
- package/dist/core/extensions/loader.js +3 -0
- package/dist/core/extensions/types.d.ts +16 -2
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.js +4 -0
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/model-config.d.ts +15 -0
- package/dist/core/model-config.js +3 -0
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.js +5 -2
- package/dist/core/provider-composer.js +8 -2
- package/dist/core/session-export.d.ts +3 -0
- package/dist/core/session-export.js +31 -0
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.js +40 -13
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.js +4 -2
- package/dist/core/system-prompt.js +10 -10
- package/dist/core/tools/bash.js +3 -117
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.js +5 -163
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.js +10 -122
- package/dist/core/tools/renderers/bash.d.ts +11 -0
- package/dist/core/tools/renderers/bash.js +129 -0
- package/dist/core/tools/renderers/edit.d.ts +22 -0
- package/dist/core/tools/renderers/edit.js +166 -0
- package/dist/core/tools/renderers/find.d.ts +9 -0
- package/dist/core/tools/renderers/find.js +63 -0
- package/dist/core/tools/renderers/grep.d.ts +9 -0
- package/dist/core/tools/renderers/grep.js +68 -0
- package/dist/core/tools/renderers/index.d.ts +27 -0
- package/dist/core/tools/renderers/index.js +46 -0
- package/dist/core/tools/renderers/ls.d.ts +9 -0
- package/dist/core/tools/renderers/ls.js +57 -0
- package/dist/core/tools/renderers/read.d.ts +10 -0
- package/dist/core/tools/renderers/read.js +128 -0
- package/dist/core/tools/renderers/write.d.ts +9 -0
- package/dist/core/tools/renderers/write.js +152 -0
- package/dist/core/tools/write.js +5 -146
- package/dist/extensions/capability-gateway/index.ts +12 -1
- package/dist/extensions/capability-gateway/integration.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
- package/dist/extensions/pi-hermes-memory/README.md +16 -12
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
- package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
- package/dist/extensions/pi-hermes-memory/package.json +4 -4
- package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
- package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
- package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
- package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
- package/dist/extensions/pi-intercom/README.md +16 -2
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
- package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
- package/dist/extensions/pi-intercom/index.ts +1 -1
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
- package/dist/extensions/pi-intercom/package.json +1 -1
- package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
- package/dist/extensions/pi-intercom/project-agent.ts +1 -6
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
- package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
- package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
- package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
- package/dist/extensions/pi-subagents/README.md +3 -3
- package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
- package/dist/extensions/pi-subagents/agents/scout.md +1 -1
- package/dist/extensions/pi-subagents/docs/agents.md +32 -16
- package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
- package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
- package/dist/extensions/pi-subagents/docs/missions.md +2 -0
- package/dist/extensions/pi-subagents/docs/models.md +58 -1
- package/dist/extensions/pi-subagents/docs/observability.md +50 -12
- package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
- package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
- package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
- package/dist/extensions/pi-subagents/package-lock.json +747 -177
- package/dist/extensions/pi-subagents/package.json +6 -4
- package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
- package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
- package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
- package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
- package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
- package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
- package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
- package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
- package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
- package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
- package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
- package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
- package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
- package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
- package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
- package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
- package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
- package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
- package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
- package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
- package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
- package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
- package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
- package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
- package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
- package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
- package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
- package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
- package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
- package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
- package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
- package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
- package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
- package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
- package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
- package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
- package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
- package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
- package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
- package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
- package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
- package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
- package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
- package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
- package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
- package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
- package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
- package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
- package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
- package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
- package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
- package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
- package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
- package/dist/extensions/pi-web-agent/src/types.ts +1 -1
- package/dist/extensions/pi-zentui/README.md +17 -0
- package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
- package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
- package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
- package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
- package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
- package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
- package/dist/extensions/pi-zentui/package-lock.json +277 -517
- package/dist/extensions/pi-zentui/package.json +7 -4
- package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
- package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
- package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
- package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
- package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
- package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
- package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
- package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
- package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
- package/dist/index.d.ts +1 -1
- package/dist/main.js +4 -1
- package/dist/modes/interactive/chat-viewport.d.ts +19 -0
- package/dist/modes/interactive/chat-viewport.js +27 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
- package/dist/modes/interactive/components/assistant-message.js +30 -13
- package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
- package/dist/modes/interactive/components/custom-editor.js +39 -1
- package/dist/modes/interactive/components/first-time-setup.js +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
- package/dist/modes/interactive/components/markdown-transform.js +18 -0
- package/dist/modes/interactive/components/model-selector.js +19 -17
- package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
- package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
- package/dist/modes/interactive/components/settings-selector.js +128 -20
- package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
- package/dist/modes/interactive/components/settings-submenu.js +164 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.js +75 -18
- package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
- package/dist/modes/interactive/components/tool-execution.js +35 -33
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts +13 -15
- package/dist/modes/interactive/interactive-mode.js +144 -80
- package/dist/modes/interactive/session-share.d.ts +15 -0
- package/dist/modes/interactive/session-share.js +183 -0
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
- package/dist/modes/interactive/theme/theme-json.js +129 -0
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/tui-renderer.d.ts +20 -0
- package/dist/modes/interactive/tui-renderer.js +65 -0
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/management-http.d.ts +24 -0
- package/dist/utils/management-http.js +53 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.js +8 -0
- package/dist/utils/tools-manager.d.ts +1 -0
- package/dist/utils/tools-manager.js +43 -21
- package/docs/docs.json +0 -4
- package/package.json +4 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
- package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
- package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
- package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
- package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
- package/dist/skills/implanger/SKILL.md +0 -70
- package/dist/skills/output/SKILL.md +0 -49
- package/dist/skills/planger/SKILL.md +0 -167
- package/dist/skills/workflow/SKILL.md +0 -95
- package/docs/workflows.md +0 -18
- /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Foreground children run as in-process pi sessions. These tests drive
|
|
3
|
+
* `runSync` against the scripted child session factory and check the seams
|
|
4
|
+
* the in-process launch owns: hook config, steering, interrupt, timeout,
|
|
5
|
+
* structured output capture, disposal, and detach.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, before, after, beforeEach } from "node:test";
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import * as fs from "node:fs";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import type { MockPi } from "../support/helpers.ts";
|
|
13
|
+
import { createMockPi, createTempDir, makeAgent, makeAgentConfigs, removeTempDir } from "../support/helpers.ts";
|
|
14
|
+
import { runSync } from "../../src/runs/foreground/execution.ts";
|
|
15
|
+
import { childSessionFactory, createDefaultChildSessionFactory, disposeChildSessions, type ChildSessionFactory, type ChildSessionLaunch, type PiCodingAgentModule } from "../../src/runs/shared/child-session.ts";
|
|
16
|
+
import { createNestedRoute } from "../../src/runs/shared/nested-events.ts";
|
|
17
|
+
import { createStructuredOutputRuntime } from "../../src/runs/shared/structured-output.ts";
|
|
18
|
+
import type { ForegroundChildSessionControls, SingleResult } from "../../src/shared/types.ts";
|
|
19
|
+
|
|
20
|
+
async function waitFor(read: () => boolean, timeoutMs = 5_000): Promise<void> {
|
|
21
|
+
const deadline = Date.now() + timeoutMs;
|
|
22
|
+
while (!read()) {
|
|
23
|
+
if (Date.now() > deadline) throw new Error("Timed out waiting for test condition.");
|
|
24
|
+
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe("in-process foreground child", () => {
|
|
29
|
+
let tempDir: string;
|
|
30
|
+
let mockPi: MockPi;
|
|
31
|
+
const savedEnv = { ...process.env };
|
|
32
|
+
|
|
33
|
+
before(() => {
|
|
34
|
+
mockPi = createMockPi();
|
|
35
|
+
mockPi.install();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
after(() => {
|
|
39
|
+
mockPi.uninstall();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
tempDir = createTempDir();
|
|
44
|
+
mockPi.reset();
|
|
45
|
+
process.env.SELESAI_SUBAGENT_CHILD_AGENT = savedEnv.SELESAI_SUBAGENT_CHILD_AGENT ?? "";
|
|
46
|
+
delete process.env.SELESAI_SUBAGENT_CHILD_AGENT;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
after(() => removeTempDir(tempDir));
|
|
50
|
+
|
|
51
|
+
it("passes the child hooks a typed config built without the environment", async () => {
|
|
52
|
+
process.env.SELESAI_SUBAGENT_CHILD_AGENT = "leaked-parent-value";
|
|
53
|
+
try {
|
|
54
|
+
mockPi.onCall({ output: "done" });
|
|
55
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "hooks-config", index: 3, waitToolEnabled: false });
|
|
56
|
+
assert.equal(result.exitCode, 0);
|
|
57
|
+
const [session] = mockPi.sessions;
|
|
58
|
+
assert.ok(session, "child session was created");
|
|
59
|
+
assert.equal(session.launch.runtime.agent, "echo");
|
|
60
|
+
assert.equal(session.launch.runtime.runId, "hooks-config");
|
|
61
|
+
assert.equal(session.launch.runtime.childIndex, 3);
|
|
62
|
+
assert.equal(session.launch.runtime.fanoutChild, false);
|
|
63
|
+
assert.equal(session.launch.runtime.waitTool.enabled, false);
|
|
64
|
+
assert.equal(session.launch.runtime.steerInbox, undefined, "in-process children have no steer inbox");
|
|
65
|
+
assert.equal(session.launch.runtime.depth, 1);
|
|
66
|
+
assert.equal(session.task?.startsWith("Task: Task"), true);
|
|
67
|
+
assert.equal(session.launch.systemPrompt?.startsWith('<active_agent name="echo"/>'), true);
|
|
68
|
+
assert.deepEqual(session.launch.storage, { kind: "memory" });
|
|
69
|
+
} finally {
|
|
70
|
+
delete process.env.SELESAI_SUBAGENT_CHILD_AGENT;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("adds the fanout hook and nested route only for fanout-authorized children", async () => {
|
|
75
|
+
const route = createNestedRoute("hooks-fanout");
|
|
76
|
+
try {
|
|
77
|
+
mockPi.onCall({ output: "done" });
|
|
78
|
+
const result = await runSync(tempDir, [makeAgent("delegator", { tools: ["read", "subagent"] })], "delegator", "Task", {
|
|
79
|
+
runId: "hooks-fanout",
|
|
80
|
+
nestedRoute: route,
|
|
81
|
+
});
|
|
82
|
+
assert.equal(result.exitCode, 0);
|
|
83
|
+
const [session] = mockPi.sessions;
|
|
84
|
+
assert.equal(session?.launch.runtime.fanoutChild, true);
|
|
85
|
+
assert.deepEqual(session?.launch.runtime.nestedRoute, route);
|
|
86
|
+
assert.deepEqual(session?.launch.runtime.nestedParent, { parentRunId: "hooks-fanout", parentChildIndex: 0, depth: 1, path: [{ runId: "hooks-fanout", stepIndex: 0, agent: "delegator" }] });
|
|
87
|
+
assert.deepEqual(session?.launch.tools, ["read", "subagent"]);
|
|
88
|
+
} finally {
|
|
89
|
+
fs.rmSync(path.dirname(route.eventSink), { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("routes steer and follow-up to the child session", async () => {
|
|
94
|
+
const release = path.join(tempDir, "release");
|
|
95
|
+
mockPi.onCall({ steps: [{ waitForPath: release, jsonl: [{ type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "steered" }], model: "mock/test-model", stopReason: "stop", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } }] }] });
|
|
96
|
+
let controls: ForegroundChildSessionControls | undefined;
|
|
97
|
+
const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", {
|
|
98
|
+
runId: "steer-session",
|
|
99
|
+
onChildSession: (next) => { controls = next; },
|
|
100
|
+
});
|
|
101
|
+
await waitFor(() => controls !== undefined);
|
|
102
|
+
await controls!.steer("Focus on tests.");
|
|
103
|
+
await controls!.followUp("Then update docs.");
|
|
104
|
+
fs.writeFileSync(release, "go");
|
|
105
|
+
const result = await run;
|
|
106
|
+
assert.equal(result.exitCode, 0);
|
|
107
|
+
assert.deepEqual(mockPi.sessions[0]?.steers, [
|
|
108
|
+
{ text: "Focus on tests.", mode: "steer" },
|
|
109
|
+
{ text: "Then update docs.", mode: "followUp" },
|
|
110
|
+
]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("aborts the child session on interrupt and disposes it", async () => {
|
|
114
|
+
mockPi.onCall({ hangUntilAbort: true });
|
|
115
|
+
const interrupt = new AbortController();
|
|
116
|
+
const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "interrupt-session", interruptSignal: interrupt.signal });
|
|
117
|
+
await waitFor(() => mockPi.sessions.length === 1);
|
|
118
|
+
await waitFor(() => mockPi.sessions[0]?.task !== undefined);
|
|
119
|
+
interrupt.abort();
|
|
120
|
+
const result = await run;
|
|
121
|
+
assert.equal(result.interrupted, true);
|
|
122
|
+
assert.equal(result.exitCode, 0);
|
|
123
|
+
assert.equal(mockPi.sessions[0]?.aborted, true);
|
|
124
|
+
assert.equal(mockPi.sessions[0]?.disposed, true);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("aborts the child session on timeout and disposes it", async () => {
|
|
128
|
+
mockPi.onCall({ hangUntilAbort: true });
|
|
129
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "timeout-session", timeoutMs: 60 });
|
|
130
|
+
assert.equal(result.timedOut, true);
|
|
131
|
+
assert.equal(result.exitCode, 1);
|
|
132
|
+
assert.match(result.error ?? "", /timed out after 60ms/);
|
|
133
|
+
assert.equal(mockPi.sessions[0]?.aborted, true);
|
|
134
|
+
assert.equal(mockPi.sessions[0]?.disposed, true);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("disposes the child session after a normal completion", async () => {
|
|
138
|
+
mockPi.onCall({ output: "finished" });
|
|
139
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "dispose-session" });
|
|
140
|
+
assert.equal(result.exitCode, 0);
|
|
141
|
+
assert.equal(result.finalOutput, "finished");
|
|
142
|
+
assert.equal(mockPi.sessions[0]?.settled, true);
|
|
143
|
+
assert.equal(mockPi.sessions[0]?.disposed, true);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it("reports the run only after the child session's shutdown work finished", async () => {
|
|
147
|
+
mockPi.onCall({ output: "done" });
|
|
148
|
+
let shutdownDone = false;
|
|
149
|
+
const inner = childSessionFactory();
|
|
150
|
+
const wrapped: ChildSessionFactory = {
|
|
151
|
+
...inner,
|
|
152
|
+
create: async (launch) => {
|
|
153
|
+
const session = await inner.create(launch);
|
|
154
|
+
const dispose = session.dispose.bind(session);
|
|
155
|
+
session.dispose = () => dispose().then(() => new Promise<void>((resolve) => setTimeout(() => { shutdownDone = true; resolve(); }, 30)));
|
|
156
|
+
return session;
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "dispose-order", childSessionFactory: wrapped });
|
|
160
|
+
assert.equal(result.exitCode, 0);
|
|
161
|
+
assert.equal(shutdownDone, true);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("captures structured output in memory", async () => {
|
|
165
|
+
const structured = createStructuredOutputRuntime({ type: "object", required: ["ok"], properties: { ok: { type: "boolean" } } }, tempDir);
|
|
166
|
+
mockPi.onCall({ structuredOutput: { ok: true } });
|
|
167
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "structured-memory", structuredOutput: structured });
|
|
168
|
+
assert.equal(result.exitCode, 0, result.error);
|
|
169
|
+
assert.deepEqual(result.structuredOutput, { ok: true });
|
|
170
|
+
assert.equal(mockPi.sessions[0]?.launch.runtime.structuredOutput?.schema.type, "object");
|
|
171
|
+
assert.deepEqual(JSON.parse(fs.readFileSync(structured.outputPath, "utf-8")), { ok: true });
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("fails when the child never calls structured_output", async () => {
|
|
175
|
+
const structured = createStructuredOutputRuntime({ type: "object" }, tempDir);
|
|
176
|
+
mockPi.onCall({ output: "prose only" });
|
|
177
|
+
const result = await runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "structured-missing", structuredOutput: structured });
|
|
178
|
+
assert.equal(result.exitCode, 1);
|
|
179
|
+
assert.match(result.error ?? "", /Missing structured_output call/);
|
|
180
|
+
assert.equal(result.structuredOutputFailed, true);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("keeps a detached child running in-process and delivers its terminal result", async () => {
|
|
184
|
+
const release = path.join(tempDir, "release-detach");
|
|
185
|
+
mockPi.onCall({ steps: [{ waitForPath: release, jsonl: [{ type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "after detach" }], model: "mock/test-model", stopReason: "stop", usage: { input: 1, output: 1, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } }] }] });
|
|
186
|
+
let detach: ((reason?: string) => boolean) | undefined;
|
|
187
|
+
let terminal: SingleResult | undefined;
|
|
188
|
+
const receipt = await new Promise<SingleResult>((resolve, reject) => {
|
|
189
|
+
runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", {
|
|
190
|
+
runId: "detach-session",
|
|
191
|
+
onDetachReady: (next) => { detach = next; },
|
|
192
|
+
onDetachReceipt: () => true,
|
|
193
|
+
onDetachedExit: (result) => { terminal = result; },
|
|
194
|
+
}).then(resolve, reject);
|
|
195
|
+
void waitFor(() => detach !== undefined && mockPi.sessions[0]?.task !== undefined).then(() => {
|
|
196
|
+
assert.equal(detach!("user request"), true);
|
|
197
|
+
}, reject);
|
|
198
|
+
});
|
|
199
|
+
assert.equal(receipt.detached, true);
|
|
200
|
+
assert.equal(receipt.detachedReason, "user request");
|
|
201
|
+
assert.equal(mockPi.sessions[0]?.aborted, false, "detach must not abort the session");
|
|
202
|
+
await disposeChildSessions();
|
|
203
|
+
assert.equal(mockPi.sessions[0]?.aborted, false, "parent session shutdown must not abort a detached child");
|
|
204
|
+
fs.writeFileSync(release, "go");
|
|
205
|
+
await waitFor(() => terminal !== undefined);
|
|
206
|
+
assert.equal(terminal?.exitCode, 0);
|
|
207
|
+
assert.equal(terminal?.finalOutput, "after detach");
|
|
208
|
+
assert.equal(terminal?.detachedReason, "user request");
|
|
209
|
+
assert.equal(mockPi.sessions[0]?.disposed, true);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
it("reports a parent session shutdown as the reason an attached child stopped", async () => {
|
|
213
|
+
mockPi.onCall({ hangUntilAbort: true });
|
|
214
|
+
const run = runSync(tempDir, makeAgentConfigs(["echo"]), "echo", "Task", { runId: "shutdown-attached" });
|
|
215
|
+
await waitFor(() => mockPi.sessions[0]?.task !== undefined);
|
|
216
|
+
await disposeChildSessions();
|
|
217
|
+
const result = await run;
|
|
218
|
+
assert.equal(result.exitCode, 1);
|
|
219
|
+
assert.equal(result.error, "Subagent stopped because the parent session shut down.");
|
|
220
|
+
});
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
/** A pi module stub whose loader reads `process.env` after an await, the way a real extension load does. */
|
|
224
|
+
function stubPi(session: Record<string, unknown> = {}, onReload?: () => void): PiCodingAgentModule {
|
|
225
|
+
return {
|
|
226
|
+
ModelRuntime: { create: async () => ({}) },
|
|
227
|
+
SettingsManager: { create: () => ({}) },
|
|
228
|
+
DefaultResourceLoader: class { async reload() { await new Promise((resolve) => setTimeout(resolve, 10)); onReload?.(); } },
|
|
229
|
+
SessionManager: { inMemory: () => ({}) },
|
|
230
|
+
resolveCliModel: () => ({}),
|
|
231
|
+
createAgentSession: async () => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", ...session } }),
|
|
232
|
+
} as unknown as PiCodingAgentModule;
|
|
233
|
+
}
|
|
234
|
+
const stubLaunch: ChildSessionLaunch = { cwd: process.cwd(), storage: { kind: "memory" }, extensionPaths: [], ambientExtensions: false, hooks: [], noSkills: true, noContextFiles: true, runtime: { fanoutChild: false, depth: 1, waitTool: { enabled: false }, fast: false } as ChildSessionLaunch["runtime"] };
|
|
235
|
+
|
|
236
|
+
describe("default child session factory", () => {
|
|
237
|
+
it("serializes process env through extension loading and session start across concurrent launches", async () => {
|
|
238
|
+
const seen: string[] = [];
|
|
239
|
+
const bound: string[] = [];
|
|
240
|
+
const bindExtensions = async () => { await new Promise((resolve) => setTimeout(resolve, 10)); bound.push(process.env.SELESAI_SUBAGENT_TEST_ENV ?? ""); };
|
|
241
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi({ bindExtensions }, () => { seen.push(process.env.SELESAI_SUBAGENT_TEST_ENV ?? ""); }) });
|
|
242
|
+
await Promise.all([
|
|
243
|
+
factory.create({ ...stubLaunch, processEnv: { SELESAI_SUBAGENT_TEST_ENV: "a" } }),
|
|
244
|
+
factory.create({ ...stubLaunch, processEnv: { SELESAI_SUBAGENT_TEST_ENV: "b" } }),
|
|
245
|
+
]);
|
|
246
|
+
delete process.env.SELESAI_SUBAGENT_TEST_ENV;
|
|
247
|
+
assert.deepEqual(seen, ["a", "b"]);
|
|
248
|
+
assert.deepEqual(bound, ["a", "b"]);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("marks each child's loader as reloaded so pi resets its extension cache", async () => {
|
|
252
|
+
const flags: boolean[] = [];
|
|
253
|
+
const pi = stubPi();
|
|
254
|
+
pi.DefaultResourceLoader = class { loaded = false; async reload() { flags.push(this.loaded); } } as unknown as PiCodingAgentModule["DefaultResourceLoader"];
|
|
255
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
|
|
256
|
+
await factory.create(stubLaunch);
|
|
257
|
+
await factory.create(stubLaunch);
|
|
258
|
+
assert.deepEqual(flags, [true, true]);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it("resolves models from providers queued during child extension loading", async () => {
|
|
262
|
+
const registeredProviders: string[] = [];
|
|
263
|
+
const registeredNativeProviders: string[] = [];
|
|
264
|
+
let refreshed = false;
|
|
265
|
+
let pendingRuntime: { pendingProviderRegistrations: unknown[]; pendingNativeProviderRegistrations: unknown[] } | undefined;
|
|
266
|
+
const pi = stubPi();
|
|
267
|
+
pi.ModelRuntime = { create: async () => ({ registerProvider: (name: string) => { registeredProviders.push(name); }, registerNativeProvider: (provider: { id: string }) => { registeredNativeProviders.push(provider.id); }, refresh: async () => { refreshed = true; } }) } as unknown as PiCodingAgentModule["ModelRuntime"];
|
|
268
|
+
pi.DefaultResourceLoader = class {
|
|
269
|
+
runtime = {
|
|
270
|
+
pendingProviderRegistrations: [{ name: "router", config: { models: [{ id: "mimo-v2.5" }] }, extensionPath: "/extensions/router.ts" }],
|
|
271
|
+
pendingNativeProviderRegistrations: [{ provider: { id: "native-router", models: [{ id: "native-model" }] }, extensionPath: "/extensions/native-router.ts" }],
|
|
272
|
+
};
|
|
273
|
+
async reload() { pendingRuntime = this.runtime; }
|
|
274
|
+
getExtensions() { return { extensions: [], errors: [], runtime: this.runtime }; }
|
|
275
|
+
} as unknown as PiCodingAgentModule["DefaultResourceLoader"];
|
|
276
|
+
pi.resolveCliModel = (({ cliModel }) => {
|
|
277
|
+
assert.equal(cliModel, "router/mimo-v2.5");
|
|
278
|
+
assert.deepEqual(registeredProviders, ["router"]);
|
|
279
|
+
assert.deepEqual(registeredNativeProviders, ["native-router"]);
|
|
280
|
+
assert.equal(refreshed, true);
|
|
281
|
+
return { model: { provider: "router", id: "mimo-v2.5" } };
|
|
282
|
+
}) as unknown as PiCodingAgentModule["resolveCliModel"];
|
|
283
|
+
pi.createAgentSession = (async ({ model }) => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", model } })) as unknown as PiCodingAgentModule["createAgentSession"];
|
|
284
|
+
|
|
285
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
|
|
286
|
+
const child = await factory.create({ ...stubLaunch, model: "router/mimo-v2.5" });
|
|
287
|
+
|
|
288
|
+
assert.equal(child.modelId, "router/mimo-v2.5");
|
|
289
|
+
assert.deepEqual(pendingRuntime?.pendingProviderRegistrations, []);
|
|
290
|
+
assert.deepEqual(pendingRuntime?.pendingNativeProviderRegistrations, []);
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
it("resolves queued providers when the loader has no native provider queue", async () => {
|
|
294
|
+
const registeredProviders: string[] = [];
|
|
295
|
+
let refreshed = false;
|
|
296
|
+
let pendingRuntime: { pendingProviderRegistrations?: unknown[] } | undefined;
|
|
297
|
+
const pi = stubPi();
|
|
298
|
+
pi.ModelRuntime = { create: async () => ({ registerProvider: (name: string) => { registeredProviders.push(name); }, registerNativeProvider: () => {}, refresh: async () => { refreshed = true; } }) } as unknown as PiCodingAgentModule["ModelRuntime"];
|
|
299
|
+
pi.DefaultResourceLoader = class {
|
|
300
|
+
runtime = {
|
|
301
|
+
pendingProviderRegistrations: [{ name: "router", config: { models: [{ id: "mimo-v2.5" }] }, extensionPath: "/extensions/router.ts" }],
|
|
302
|
+
};
|
|
303
|
+
async reload() { pendingRuntime = this.runtime; }
|
|
304
|
+
getExtensions() { return { extensions: [], errors: [], runtime: this.runtime }; }
|
|
305
|
+
} as unknown as PiCodingAgentModule["DefaultResourceLoader"];
|
|
306
|
+
pi.resolveCliModel = (({ cliModel }) => {
|
|
307
|
+
assert.equal(cliModel, "router/mimo-v2.5");
|
|
308
|
+
assert.deepEqual(registeredProviders, ["router"]);
|
|
309
|
+
assert.equal(refreshed, true);
|
|
310
|
+
return { model: { provider: "router", id: "mimo-v2.5" } };
|
|
311
|
+
}) as unknown as PiCodingAgentModule["resolveCliModel"];
|
|
312
|
+
pi.createAgentSession = (async ({ model }) => ({ session: { bindExtensions: async () => {}, dispose() {}, extensionRunner: { hasHandlers: () => false }, subscribe: () => () => {}, prompt: async () => {}, abort: async () => {}, steer: async () => {}, followUp: async () => {}, messages: [], sessionId: "s", model } })) as unknown as PiCodingAgentModule["createAgentSession"];
|
|
313
|
+
|
|
314
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
|
|
315
|
+
const child = await factory.create({ ...stubLaunch, model: "router/mimo-v2.5" });
|
|
316
|
+
|
|
317
|
+
assert.equal(child.modelId, "router/mimo-v2.5");
|
|
318
|
+
assert.deepEqual(pendingRuntime?.pendingProviderRegistrations, []);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
it("reports a missing extension cache reset when the child loads extension files", async () => {
|
|
322
|
+
const errors: string[] = [];
|
|
323
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi() });
|
|
324
|
+
await factory.create({ ...stubLaunch, onExtensionError: (error) => errors.push(error.extensionPath) });
|
|
325
|
+
await factory.create({ ...stubLaunch, extensionPaths: ["/tmp/ext.ts"], onExtensionError: (error) => errors.push(error.extensionPath) });
|
|
326
|
+
assert.deepEqual(errors, ["<loader>"]);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("initializes the theme from settings before each child session", async () => {
|
|
330
|
+
const themed: Array<string | undefined> = [];
|
|
331
|
+
const pi = stubPi();
|
|
332
|
+
pi.initTheme = ((themeName?: string) => { themed.push(themeName); }) as PiCodingAgentModule["initTheme"];
|
|
333
|
+
pi.SettingsManager = { create: () => ({ getTheme: () => "solarized-dark" }) } as unknown as PiCodingAgentModule["SettingsManager"];
|
|
334
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
|
|
335
|
+
await factory.create(stubLaunch);
|
|
336
|
+
await factory.create(stubLaunch);
|
|
337
|
+
assert.deepEqual(themed, ["solarized-dark", "solarized-dark"]);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
it("skips theme initialization when the pi module has no initTheme export", async () => {
|
|
341
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi() });
|
|
342
|
+
await factory.create(stubLaunch);
|
|
343
|
+
// Reaching here without throwing is the assertion: `settingsManager.getTheme()`
|
|
344
|
+
// must not be evaluated when `initTheme` is unavailable.
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
it("disposes the session when bindExtensions rejects", async () => {
|
|
348
|
+
let disposed = 0;
|
|
349
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => stubPi({ bindExtensions: async () => { throw new Error("bind failed"); }, dispose: () => { disposed += 1; } }) });
|
|
350
|
+
await assert.rejects(factory.create(stubLaunch), /bind failed/);
|
|
351
|
+
assert.equal(disposed, 1);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it("leaves detached children running on dispose and keeps the shared runtime", async () => {
|
|
355
|
+
let aborted = 0;
|
|
356
|
+
let runtimes = 0;
|
|
357
|
+
const pi = stubPi({ abort: async () => { aborted += 1; } });
|
|
358
|
+
pi.ModelRuntime = { create: async () => { runtimes += 1; return {}; } } as unknown as PiCodingAgentModule["ModelRuntime"];
|
|
359
|
+
const factory = createDefaultChildSessionFactory({ loadPiCodingAgent: async () => pi });
|
|
360
|
+
const child = await factory.create(stubLaunch);
|
|
361
|
+
child.detached = true;
|
|
362
|
+
await factory.dispose();
|
|
363
|
+
assert.equal(aborted, 0);
|
|
364
|
+
assert.equal(child.shutDown, undefined);
|
|
365
|
+
await factory.create(stubLaunch);
|
|
366
|
+
assert.equal(runtimes, 1, "runtime is kept while a detached child runs");
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it("bounds the wait for a stuck session_shutdown handler", { timeout: 2_000 }, async () => {
|
|
370
|
+
const factory = createDefaultChildSessionFactory({ shutdownTimeoutMs: 50, loadPiCodingAgent: async () => stubPi({ extensionRunner: { hasHandlers: () => true, emit: () => new Promise(() => {}) } }) });
|
|
371
|
+
(await factory.create(stubLaunch)).dispose();
|
|
372
|
+
await factory.dispose();
|
|
373
|
+
});
|
|
374
|
+
});
|
|
@@ -359,7 +359,8 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
|
|
|
359
359
|
assert.notEqual(revivedIds[1], revivedIds[0], "expected the latest revived run id from pass two");
|
|
360
360
|
assert.equal(value?.firstOutput, "Completed retained follow-up one");
|
|
361
361
|
assert.equal(value?.output, "Completed retained follow-up two");
|
|
362
|
-
|
|
362
|
+
// Awaiting may consume a pending result before the runner promotes its public file.
|
|
363
|
+
assert.equal(mockPi.callCount(), 2, "each retained follow-up must execute once without replay or extra children");
|
|
363
364
|
} finally {
|
|
364
365
|
fs.rmSync(sourceAsyncDir, { recursive: true, force: true });
|
|
365
366
|
for (const id of revivedIds) fs.rmSync(path.join(ASYNC_DIR, id), { recursive: true, force: true });
|
|
@@ -905,7 +906,7 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
|
|
|
905
906
|
}
|
|
906
907
|
});
|
|
907
908
|
|
|
908
|
-
it("resume action revives completed multi-child async runs by index
|
|
909
|
+
for (const workflow of [false, true]) it(`${workflow ? "workflow string resume" : "resume action"} revives completed multi-child async runs by index`, async () => {
|
|
909
910
|
mockPi.onCall({ output: "revived async child b" });
|
|
910
911
|
const runId = `resume-revive-multi-${Date.now()}`;
|
|
911
912
|
const asyncDir = path.join(ASYNC_DIR, runId);
|
|
@@ -933,17 +934,26 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
|
|
|
933
934
|
|
|
934
935
|
const result = await executor.execute(
|
|
935
936
|
"resume-revive-multi",
|
|
936
|
-
|
|
937
|
+
workflow
|
|
938
|
+
? { async: false, workflowScript: `return runs.run("indexed", { resume: ${JSON.stringify(runId)}, index: 1, task: "What did b find?", output: false });` }
|
|
939
|
+
: { action: "resume", id: runId, index: 1, message: "What did b find?" },
|
|
937
940
|
new AbortController().signal,
|
|
938
941
|
undefined,
|
|
939
942
|
makeMinimalCtx(tempDir),
|
|
940
943
|
);
|
|
941
944
|
|
|
942
|
-
assert.equal(result.isError, undefined);
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
945
|
+
assert.equal(result.isError, undefined, result.content[0]?.text);
|
|
946
|
+
if (workflow) {
|
|
947
|
+
const child = result.details!.workflow!.value as { runId: string; agent: string; continuation: { runIds: string[] } };
|
|
948
|
+
assert.equal(child.agent, "b");
|
|
949
|
+
assert.deepEqual(child.continuation.runIds, [runId, child.runId]);
|
|
950
|
+
assert.deepEqual(result.details!.workflow!.receipt!.entries.indexed.continuation, child.continuation);
|
|
951
|
+
} else {
|
|
952
|
+
assert.match(result.content[0]?.text ?? "", /Revived async subagent from/);
|
|
953
|
+
assert.match(result.details?.asyncId ?? "", /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/);
|
|
954
|
+
assert.match(result.content[0]?.text ?? "", /Agent: b/);
|
|
955
|
+
assert.match(result.content[0]?.text ?? "", new RegExp(secondSession.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")));
|
|
956
|
+
}
|
|
947
957
|
const args = await readMockCallArgs(0);
|
|
948
958
|
assert.equal(args[args.indexOf("--session") + 1], secondSession);
|
|
949
959
|
assert.equal(args[args.indexOf("--model") + 1], "anthropic/claude-sonnet-4:high");
|
|
@@ -1238,7 +1248,7 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
|
|
|
1238
1248
|
{
|
|
1239
1249
|
workflowScript: `return await runs.run("gated", { agent: "worker", task: "run", gate: "npm test" });`,
|
|
1240
1250
|
async: true,
|
|
1241
|
-
acceptance:
|
|
1251
|
+
acceptance: "checked",
|
|
1242
1252
|
},
|
|
1243
1253
|
new AbortController().signal,
|
|
1244
1254
|
undefined,
|
|
@@ -1943,4 +1953,4 @@ describe("intercom result delivery cutover", { skip: !available ? "executor not
|
|
|
1943
1953
|
assert.match(message, /process failed · output absent/);
|
|
1944
1954
|
assert.doesNotMatch(message, /Inspect that output before retrying/);
|
|
1945
1955
|
});
|
|
1946
|
-
});
|
|
1956
|
+
});
|
|
@@ -31,6 +31,16 @@ afterEach(() => {
|
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
+
const RUNNER_CHILD_SESSION_FACTORY = path.resolve(import.meta.dirname, "../support/runner-child-session-factory.ts");
|
|
35
|
+
|
|
36
|
+
/** Queue one scripted response every child session the runner creates replays. */
|
|
37
|
+
function scriptChildSessions(dir: string, response: object): string {
|
|
38
|
+
const queueDir = path.join(dir, "child-sessions");
|
|
39
|
+
fs.mkdirSync(queueDir, { recursive: true });
|
|
40
|
+
fs.writeFileSync(path.join(queueDir, "default-response.json"), JSON.stringify(response), "utf-8");
|
|
41
|
+
return queueDir;
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
function runProcess(command: string, args: string[], cwd: string, env: NodeJS.ProcessEnv): Promise<number | null> {
|
|
35
45
|
return new Promise((resolve, reject) => {
|
|
36
46
|
const child = spawn(command, args, { cwd, stdio: "inherit", shell: false, env });
|
|
@@ -56,7 +66,7 @@ async function waitForFileCount(dir: string, count: number): Promise<void> {
|
|
|
56
66
|
}
|
|
57
67
|
|
|
58
68
|
describe("Orca progress-tab observer", () => {
|
|
59
|
-
it("mirrors
|
|
69
|
+
it("mirrors an in-process Pi child without replacing its execution path", { skip: process.platform === "win32" ? "Orca progress tabs are not supported on Windows" : undefined }, async () => {
|
|
60
70
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-orca-native-"));
|
|
61
71
|
tempDirs.push(dir);
|
|
62
72
|
const asyncDir = path.join(dir, "async");
|
|
@@ -72,7 +82,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
72
82
|
{ type: "message_end", message: { role: "assistant", content: [{ type: "text", text: "native Pi result" }], stopReason: "stop", usage: { input: 1, output: 2, cacheRead: 0, cacheWrite: 0, cost: { total: 0 } } } },
|
|
73
83
|
{ type: "agent_settled" },
|
|
74
84
|
];
|
|
75
|
-
const
|
|
85
|
+
const queueDir = scriptChildSessions(dir, { jsonl: childEvents });
|
|
76
86
|
|
|
77
87
|
const resultPath = path.join(dir, "result.json");
|
|
78
88
|
const configPath = path.join(dir, "config.json");
|
|
@@ -93,6 +103,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
93
103
|
artifactConfig: { enabled: false },
|
|
94
104
|
asyncDir,
|
|
95
105
|
resultMode: "single",
|
|
106
|
+
childSessionFactoryModule: RUNNER_CHILD_SESSION_FACTORY,
|
|
96
107
|
}));
|
|
97
108
|
const repo = path.resolve(import.meta.dirname, "../..");
|
|
98
109
|
const exitCode = await runProcess(
|
|
@@ -103,7 +114,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
103
114
|
...process.env,
|
|
104
115
|
SELESAI_CODING_AGENT_DIR: agentDir,
|
|
105
116
|
SELESAI_SUBAGENT_ORCA_BINARY: fakeOrca,
|
|
106
|
-
|
|
117
|
+
MOCK_PI_QUEUE_DIR: queueDir,
|
|
107
118
|
ORCA_TEST_CAPTURE: capture,
|
|
108
119
|
},
|
|
109
120
|
);
|
|
@@ -132,7 +143,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
132
143
|
fs.mkdirSync(path.join(agentDir, "extensions", "subagent"), { recursive: true });
|
|
133
144
|
fs.writeFileSync(path.join(agentDir, "extensions", "subagent", "config.json"), JSON.stringify({ orcaProgressTabs: { enabled: true } }));
|
|
134
145
|
const fakeOrca = writeNodeCommand(dir, "orca", "const fs=require('fs'),path=require('path');const args=process.argv.slice(2);fs.writeFileSync(path.join(process.env.ORCA_TEST_CAPTURE_DIR, process.pid+'.json'),JSON.stringify(args))");
|
|
135
|
-
const
|
|
146
|
+
const queueDir = scriptChildSessions(dir, { output: "parallel result" });
|
|
136
147
|
|
|
137
148
|
const resultPath = path.join(dir, "result.json");
|
|
138
149
|
const configPath = path.join(dir, "config.json");
|
|
@@ -152,6 +163,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
152
163
|
artifactConfig: { enabled: false },
|
|
153
164
|
asyncDir,
|
|
154
165
|
resultMode: "parallel",
|
|
166
|
+
childSessionFactoryModule: RUNNER_CHILD_SESSION_FACTORY,
|
|
155
167
|
}));
|
|
156
168
|
const repo = path.resolve(import.meta.dirname, "../..");
|
|
157
169
|
const exitCode = await runProcess(
|
|
@@ -162,7 +174,7 @@ describe("Orca progress-tab observer", () => {
|
|
|
162
174
|
...process.env,
|
|
163
175
|
SELESAI_CODING_AGENT_DIR: agentDir,
|
|
164
176
|
SELESAI_SUBAGENT_ORCA_BINARY: fakeOrca,
|
|
165
|
-
|
|
177
|
+
MOCK_PI_QUEUE_DIR: queueDir,
|
|
166
178
|
ORCA_TEST_CAPTURE_DIR: captures,
|
|
167
179
|
},
|
|
168
180
|
);
|
|
@@ -211,4 +223,4 @@ describe("Orca progress-tab observer", () => {
|
|
|
211
223
|
const createdOrder = fs.readFileSync(orderFile, "utf-8").trim().split("\n");
|
|
212
224
|
assert.deepEqual(createdOrder, titles);
|
|
213
225
|
});
|
|
214
|
-
});
|
|
226
|
+
});
|