@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
|
@@ -2,19 +2,19 @@ import { randomUUID } from "node:crypto";
|
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import type { AgentToolResult } from "@earendil-works/pi-agent-core";
|
|
5
|
-
import type { ExtensionAPI,
|
|
5
|
+
import type { ExtensionAPI, ToolDefinition } from "@selesai/code";
|
|
6
6
|
import { Type } from "typebox";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
SUBAGENT_CHILD_INDEX_ENV,
|
|
10
|
-
SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV,
|
|
11
|
-
SUBAGENT_ORCHESTRATOR_TARGET_ENV,
|
|
12
|
-
SUBAGENT_RUN_ID_ENV,
|
|
13
|
-
SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV,
|
|
14
|
-
} from "../runs/shared/pi-args.ts";
|
|
15
|
-
import { INTERCOM_DETACH_REQUEST_EVENT, POLL_INTERVAL_MS, TEMP_ROOT_DIR, type IntercomEventBus, type SubagentState } from "../shared/types.ts";
|
|
7
|
+
import type { ChildSupervisorMetadata } from "../runs/shared/child-runtime-config.ts";
|
|
8
|
+
import { INTERCOM_DETACH_REQUEST_EVENT, POLL_INTERVAL_MS, TEMP_ROOT_DIR, type ControlEvent, type IntercomEventBus, type SubagentState } from "../shared/types.ts";
|
|
16
9
|
import { writeAtomicJson } from "../shared/atomic-json.ts";
|
|
17
10
|
import { shouldUseNativeFsWatch } from "../shared/watch-strategy.ts";
|
|
11
|
+
import {
|
|
12
|
+
SUPERVISOR_REQUEST_MESSAGE_TYPE,
|
|
13
|
+
SUPERVISOR_REPLY_ENTRY_TYPE,
|
|
14
|
+
supervisorReplyHint,
|
|
15
|
+
type SupervisorReason,
|
|
16
|
+
type SupervisorReplyEntryData,
|
|
17
|
+
} from "./supervisor-ui.ts";
|
|
18
18
|
|
|
19
19
|
const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
|
|
20
20
|
const REQUESTS_DIR = "requests";
|
|
@@ -26,8 +26,10 @@ const CHANNEL_POLL_MS = Math.min(POLL_INTERVAL_MS, 500);
|
|
|
26
26
|
const CHANNEL_SAFETY_POLL_MS = 5000;
|
|
27
27
|
const STALE_EMPTY_CHANNEL_AGE_MS = 60 * 1000;
|
|
28
28
|
const STALE_EMPTY_CHANNEL_CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
29
|
+
const MAX_SUPERVISOR_REQUEST_CORRELATIONS = 256;
|
|
30
|
+
const SUPERVISOR_REQUEST_CORRELATION_RETENTION_MS = 10 * 60 * 1000;
|
|
29
31
|
|
|
30
|
-
type
|
|
32
|
+
export type SupervisorRequestState = "pending" | "resolved" | "unknown";
|
|
31
33
|
|
|
32
34
|
interface SupervisorRequest {
|
|
33
35
|
type: "subagent.supervisor.request";
|
|
@@ -42,6 +44,7 @@ interface SupervisorRequest {
|
|
|
42
44
|
runId: string;
|
|
43
45
|
agent: string;
|
|
44
46
|
childIndex: number;
|
|
47
|
+
toolCallId?: string;
|
|
45
48
|
childTarget?: string;
|
|
46
49
|
interview?: unknown;
|
|
47
50
|
}
|
|
@@ -51,6 +54,12 @@ interface PendingSupervisorRequest extends SupervisorRequest {
|
|
|
51
54
|
requestFile: string;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
interface SupervisorRequestCorrelation {
|
|
58
|
+
request: PendingSupervisorRequest;
|
|
59
|
+
state: Exclude<SupervisorRequestState, "unknown">;
|
|
60
|
+
updatedAt: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
interface SupervisorReply {
|
|
55
64
|
type: "subagent.supervisor.reply";
|
|
56
65
|
requestId: string;
|
|
@@ -65,7 +74,7 @@ interface ContactSupervisorParams {
|
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
interface IntercomParams {
|
|
68
|
-
action: "list" | "
|
|
77
|
+
action: "list" | "pending" | "status" | "reply";
|
|
69
78
|
to?: string;
|
|
70
79
|
message?: string;
|
|
71
80
|
replyTo?: string;
|
|
@@ -74,6 +83,8 @@ interface IntercomParams {
|
|
|
74
83
|
type SupervisorWatch = (filename: fs.PathLike, listener: fs.WatchListener<string>) => fs.FSWatcher;
|
|
75
84
|
|
|
76
85
|
interface NativeSupervisorChannelDeps {
|
|
86
|
+
/** Retained scheduled states for the current runtime owner, never foreign owners. */
|
|
87
|
+
getCurrentOwnerStates?: () => Iterable<SubagentState>;
|
|
77
88
|
platform?: NodeJS.Platform;
|
|
78
89
|
watch?: SupervisorWatch;
|
|
79
90
|
timers?: Pick<typeof globalThis, "setInterval" | "clearInterval" | "setImmediate" | "clearImmediate">;
|
|
@@ -86,7 +97,7 @@ const ContactSupervisorParamsSchema = Type.Object({
|
|
|
86
97
|
}, { additionalProperties: false });
|
|
87
98
|
|
|
88
99
|
const IntercomParamsSchema = Type.Object({
|
|
89
|
-
action: Type.String({ enum: ["list", "
|
|
100
|
+
action: Type.String({ enum: ["list", "pending", "status", "reply"] }),
|
|
90
101
|
to: Type.Optional(Type.String()),
|
|
91
102
|
message: Type.Optional(Type.String()),
|
|
92
103
|
replyTo: Type.Optional(Type.String()),
|
|
@@ -113,71 +124,12 @@ function replyPath(channelDir: string, requestId: string): string {
|
|
|
113
124
|
return path.join(channelDir, REPLIES_DIR, `${safeSegment(requestId)}.json`);
|
|
114
125
|
}
|
|
115
126
|
|
|
116
|
-
function readTextEnv(name: string): string | undefined {
|
|
117
|
-
const value = process.env[name]?.trim();
|
|
118
|
-
return value ? value : undefined;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function readChildMetadata(): {
|
|
122
|
-
channelDir: string;
|
|
123
|
-
runId: string;
|
|
124
|
-
agent: string;
|
|
125
|
-
childIndex: number;
|
|
126
|
-
orchestratorTarget?: string;
|
|
127
|
-
orchestratorSessionId?: string;
|
|
128
|
-
childTarget?: string;
|
|
129
|
-
} | undefined {
|
|
130
|
-
const channelDir = readTextEnv(SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV);
|
|
131
|
-
const runId = readTextEnv(SUBAGENT_RUN_ID_ENV);
|
|
132
|
-
const agent = readTextEnv(SUBAGENT_CHILD_AGENT_ENV);
|
|
133
|
-
const rawIndex = readTextEnv(SUBAGENT_CHILD_INDEX_ENV);
|
|
134
|
-
const orchestratorSessionId = readTextEnv(SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV);
|
|
135
|
-
if (!channelDir || !runId || !agent || !orchestratorSessionId || rawIndex === undefined || !/^\d+$/.test(rawIndex)) return undefined;
|
|
136
|
-
return {
|
|
137
|
-
channelDir,
|
|
138
|
-
runId,
|
|
139
|
-
agent,
|
|
140
|
-
childIndex: Number(rawIndex),
|
|
141
|
-
orchestratorTarget: readTextEnv(SUBAGENT_ORCHESTRATOR_TARGET_ENV),
|
|
142
|
-
orchestratorSessionId,
|
|
143
|
-
childTarget: readTextEnv("SELESAI_SUBAGENT_INTERCOM_SESSION_NAME"),
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
|
|
147
127
|
function reasonHeading(reason: SupervisorReason): string {
|
|
148
128
|
if (reason === "interview_request") return "Subagent requests a structured supervisor interview.";
|
|
149
129
|
if (reason === "progress_update") return "Subagent progress update.";
|
|
150
130
|
return "Subagent needs a supervisor decision.";
|
|
151
131
|
}
|
|
152
132
|
|
|
153
|
-
function formatChildMessage(input: {
|
|
154
|
-
reason: SupervisorReason;
|
|
155
|
-
message?: string;
|
|
156
|
-
interview?: unknown;
|
|
157
|
-
runId: string;
|
|
158
|
-
agent: string;
|
|
159
|
-
childIndex: number;
|
|
160
|
-
childTarget?: string;
|
|
161
|
-
}): string {
|
|
162
|
-
const lines = [
|
|
163
|
-
reasonHeading(input.reason),
|
|
164
|
-
`Run: ${input.runId}`,
|
|
165
|
-
`Agent: ${input.agent}`,
|
|
166
|
-
`Child index: ${input.childIndex}`,
|
|
167
|
-
];
|
|
168
|
-
if (input.childTarget) lines.push(`Child intercom target: ${input.childTarget}`);
|
|
169
|
-
lines.push("");
|
|
170
|
-
if (input.message?.trim()) lines.push(input.message.trim());
|
|
171
|
-
if (input.reason === "interview_request") {
|
|
172
|
-
lines.push(
|
|
173
|
-
"",
|
|
174
|
-
"Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape.",
|
|
175
|
-
);
|
|
176
|
-
if (input.interview !== undefined) lines.push(JSON.stringify(input.interview, null, "\t"));
|
|
177
|
-
}
|
|
178
|
-
return lines.join("\n").trimEnd();
|
|
179
|
-
}
|
|
180
|
-
|
|
181
133
|
function parseStructuredReply(message: string): { value?: unknown; error?: string } {
|
|
182
134
|
const trimmed = message.trim();
|
|
183
135
|
const fenced = trimmed.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i)?.[1]?.trim();
|
|
@@ -231,11 +183,9 @@ async function waitForReply(channelDir: string, requestId: string, deadline: num
|
|
|
231
183
|
throw new Error("Timed out waiting for supervisor reply.");
|
|
232
184
|
}
|
|
233
185
|
|
|
234
|
-
async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: AbortSignal): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
if (params.reason !== "progress_update" && !params.message?.trim() && params.reason !== "interview_request") {
|
|
238
|
-
throw new Error("message is required for supervisor decisions.");
|
|
186
|
+
async function sendSupervisorRequest(params: ContactSupervisorParams, metadata: ChildSupervisorMetadata, signal?: AbortSignal, toolCallId?: string): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
187
|
+
if (!params.message?.trim() && params.reason !== "interview_request") {
|
|
188
|
+
throw new Error("message is required for supervisor decisions and progress updates.");
|
|
239
189
|
}
|
|
240
190
|
ensureSupervisorChannelDir(metadata.channelDir);
|
|
241
191
|
const requestId = randomUUID();
|
|
@@ -243,7 +193,8 @@ async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: A
|
|
|
243
193
|
const createdAt = Date.now();
|
|
244
194
|
const replyDeadline = createdAt + askTimeoutMs();
|
|
245
195
|
const expiresAt = expectsReply ? replyDeadline : undefined;
|
|
246
|
-
const message =
|
|
196
|
+
const message = params.message?.trim() ?? "";
|
|
197
|
+
const requestToolCallId = typeof toolCallId === "string" && toolCallId.length > 0 ? toolCallId : undefined;
|
|
247
198
|
const request: SupervisorRequest = {
|
|
248
199
|
type: "subagent.supervisor.request",
|
|
249
200
|
id: requestId,
|
|
@@ -257,6 +208,7 @@ async function sendSupervisorRequest(params: ContactSupervisorParams, signal?: A
|
|
|
257
208
|
runId: metadata.runId,
|
|
258
209
|
agent: metadata.agent,
|
|
259
210
|
childIndex: metadata.childIndex,
|
|
211
|
+
...(requestToolCallId ? { toolCallId: requestToolCallId } : {}),
|
|
260
212
|
...(metadata.childTarget ? { childTarget: metadata.childTarget } : {}),
|
|
261
213
|
...(params.interview !== undefined ? { interview: params.interview } : {}),
|
|
262
214
|
};
|
|
@@ -297,15 +249,19 @@ function hasTool(pi: ExtensionAPI, name: string): boolean {
|
|
|
297
249
|
}
|
|
298
250
|
}
|
|
299
251
|
|
|
300
|
-
|
|
301
|
-
|
|
252
|
+
/**
|
|
253
|
+
* Register the child-side `contact_supervisor` tool. The host passes the
|
|
254
|
+
* channel metadata in the child runtime config.
|
|
255
|
+
*/
|
|
256
|
+
export function registerNativeSupervisorClient(pi: ExtensionAPI, metadata: ChildSupervisorMetadata | undefined): void {
|
|
257
|
+
if (!metadata || hasTool(pi, "contact_supervisor")) return;
|
|
302
258
|
const tool: ToolDefinition<typeof ContactSupervisorParamsSchema, Record<string, unknown>> = {
|
|
303
259
|
name: "contact_supervisor",
|
|
304
260
|
label: "Contact Supervisor",
|
|
305
261
|
description: "Contact the parent/supervisor session for a blocking decision, structured interview, or progress update.",
|
|
306
262
|
parameters: ContactSupervisorParamsSchema,
|
|
307
|
-
execute(
|
|
308
|
-
return sendSupervisorRequest(params as ContactSupervisorParams, signal);
|
|
263
|
+
execute(id, params, signal) {
|
|
264
|
+
return sendSupervisorRequest(params as ContactSupervisorParams, metadata, signal, id);
|
|
309
265
|
},
|
|
310
266
|
};
|
|
311
267
|
pi.registerTool(tool);
|
|
@@ -317,9 +273,14 @@ function parseRequestFile(file: string, channelDir: string): PendingSupervisorRe
|
|
|
317
273
|
if (parsed.type !== "subagent.supervisor.request") return undefined;
|
|
318
274
|
if (typeof parsed.id !== "string" || !parsed.id) return undefined;
|
|
319
275
|
if (parsed.reason !== "need_decision" && parsed.reason !== "interview_request" && parsed.reason !== "progress_update") return undefined;
|
|
320
|
-
if (typeof parsed.message !== "string" || !parsed.message) return undefined;
|
|
276
|
+
if (typeof parsed.message !== "string" || (!parsed.message.trim() && parsed.reason !== "interview_request")) return undefined;
|
|
321
277
|
if (typeof parsed.runId !== "string" || typeof parsed.agent !== "string" || typeof parsed.childIndex !== "number") return undefined;
|
|
322
|
-
return {
|
|
278
|
+
return {
|
|
279
|
+
...parsed as SupervisorRequest,
|
|
280
|
+
...(typeof parsed.toolCallId === "string" && parsed.toolCallId.length > 0 ? { toolCallId: parsed.toolCallId } : { toolCallId: undefined }),
|
|
281
|
+
channelDir,
|
|
282
|
+
requestFile: file,
|
|
283
|
+
};
|
|
323
284
|
} catch {
|
|
324
285
|
return undefined;
|
|
325
286
|
}
|
|
@@ -422,18 +383,8 @@ function cleanupStaleEmptySupervisorChannels(nowMs = Date.now()): number {
|
|
|
422
383
|
return removed;
|
|
423
384
|
}
|
|
424
385
|
|
|
425
|
-
function
|
|
426
|
-
|
|
427
|
-
const sessionId = ctx.sessionManager.getSessionId();
|
|
428
|
-
if (sessionId) return sessionId;
|
|
429
|
-
} catch {
|
|
430
|
-
// Fall through to the last known identity.
|
|
431
|
-
}
|
|
432
|
-
return state.currentSessionId ?? undefined;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
function requestMatchesContext(request: SupervisorRequest, state: Pick<SubagentState, "currentSessionId">, ctx: ExtensionContext): boolean {
|
|
436
|
-
const currentSessionId = currentContextSessionId(state, ctx);
|
|
386
|
+
function requestMatchesOwner(request: SupervisorRequest, state: Pick<SubagentState, "supervisorOwnerSessionId">): boolean {
|
|
387
|
+
const currentSessionId = state.supervisorOwnerSessionId;
|
|
437
388
|
return Boolean(currentSessionId && request.orchestratorSessionId === currentSessionId);
|
|
438
389
|
}
|
|
439
390
|
|
|
@@ -483,6 +434,7 @@ function removeRequestFile(file: string): void {
|
|
|
483
434
|
}
|
|
484
435
|
|
|
485
436
|
type SupervisorRequestLifecycle = "pending" | "resolved" | "expired" | "inactive" | "missing" | "wrong-session";
|
|
437
|
+
type SupervisorRequestLifecycleObserver = (request: PendingSupervisorRequest, lifecycle: SupervisorRequestLifecycle) => void;
|
|
486
438
|
|
|
487
439
|
function requestExpiresAt(request: SupervisorRequest, now: number): number {
|
|
488
440
|
const expiresAt = (request as { expiresAt?: unknown }).expiresAt;
|
|
@@ -502,12 +454,12 @@ function requestRunInactive(request: SupervisorRequest, state: SubagentState): b
|
|
|
502
454
|
return stepStatus === "complete" || stepStatus === "completed" || stepStatus === "failed" || stepStatus === "paused";
|
|
503
455
|
}
|
|
504
456
|
|
|
505
|
-
function requestLifecycle(request: PendingSupervisorRequest, state: SubagentState,
|
|
506
|
-
if (
|
|
457
|
+
function requestLifecycle(request: PendingSupervisorRequest, state: SubagentState, now: number, runState: SubagentState): SupervisorRequestLifecycle {
|
|
458
|
+
if (!requestMatchesOwner(request, state)) return "wrong-session";
|
|
507
459
|
if (!fs.existsSync(request.requestFile)) return "missing";
|
|
508
460
|
if (request.expectsReply && fs.existsSync(replyPath(request.channelDir, request.id))) return "resolved";
|
|
509
461
|
if (request.expectsReply && now > requestExpiresAt(request, now)) return "expired";
|
|
510
|
-
if (request.expectsReply && requestRunInactive(request,
|
|
462
|
+
if (request.expectsReply && requestRunInactive(request, runState)) return "inactive";
|
|
511
463
|
return "pending";
|
|
512
464
|
}
|
|
513
465
|
|
|
@@ -515,30 +467,44 @@ function cleanupRequestLifecycle(request: PendingSupervisorRequest, lifecycle: S
|
|
|
515
467
|
if (lifecycle === "resolved" || lifecycle === "expired" || lifecycle === "inactive") removeRequestFile(request.requestFile);
|
|
516
468
|
}
|
|
517
469
|
|
|
518
|
-
function refreshPendingRequests(pending: Map<string, PendingSupervisorRequest>, state: SubagentState,
|
|
470
|
+
function refreshPendingRequests(pending: Map<string, PendingSupervisorRequest>, state: SubagentState, onLifecycle: SupervisorRequestLifecycleObserver, runState: (request: SupervisorRequest) => SubagentState): void {
|
|
519
471
|
const now = Date.now();
|
|
520
472
|
for (const request of pending.values()) {
|
|
521
|
-
const lifecycle = requestLifecycle(request, state,
|
|
473
|
+
const lifecycle = requestLifecycle(request, state, now, runState(request));
|
|
522
474
|
if (lifecycle === "pending") continue;
|
|
523
475
|
pending.delete(request.id);
|
|
476
|
+
onLifecycle(request, lifecycle);
|
|
524
477
|
cleanupRequestLifecycle(request, lifecycle);
|
|
525
478
|
}
|
|
526
479
|
}
|
|
527
480
|
|
|
528
481
|
function formatPendingLine(request: PendingSupervisorRequest): string {
|
|
529
|
-
const replyHint = request.expectsReply ? ` Reply: ${
|
|
482
|
+
const replyHint = request.expectsReply ? ` Reply: ${supervisorReplyHint(request.id)}` : "";
|
|
530
483
|
return `- ${request.id}: ${request.agent} [${request.runId}#${request.childIndex}] ${request.reason}.${replyHint}`;
|
|
531
484
|
}
|
|
532
485
|
|
|
533
486
|
function requestVisibleText(request: PendingSupervisorRequest): string {
|
|
534
|
-
const lines = [
|
|
535
|
-
|
|
536
|
-
|
|
487
|
+
const lines = [
|
|
488
|
+
reasonHeading(request.reason),
|
|
489
|
+
`Run: ${request.runId}`,
|
|
490
|
+
`Agent: ${request.agent}`,
|
|
491
|
+
`Child index: ${request.childIndex}`,
|
|
492
|
+
];
|
|
493
|
+
lines.push("");
|
|
494
|
+
if (request.message) lines.push(request.message);
|
|
495
|
+
if (request.reason === "interview_request") {
|
|
496
|
+
lines.push(
|
|
497
|
+
"",
|
|
498
|
+
"Structured response requested. Reply with JSON, optionally fenced in ```json, matching the requested interview shape.",
|
|
499
|
+
);
|
|
500
|
+
if (request.interview !== undefined) lines.push(JSON.stringify(request.interview, null, "\t"));
|
|
537
501
|
}
|
|
538
|
-
|
|
502
|
+
if (request.expectsReply) lines.push("", `Reply with: ${supervisorReplyHint(request.id)}`);
|
|
503
|
+
lines.push("", `Live guidance: subagent({ action: "steer", id: ${JSON.stringify(request.runId)}, index: ${request.childIndex}, message: "..." })${request.expectsReply ? " (Reply to the pending request first.)" : ""}`);
|
|
504
|
+
return lines.join("\n").trimEnd();
|
|
539
505
|
}
|
|
540
506
|
|
|
541
|
-
function writeReply(request: PendingSupervisorRequest, message: string):
|
|
507
|
+
function writeReply(request: PendingSupervisorRequest, message: string): SupervisorReply {
|
|
542
508
|
if (!message.trim()) throw new Error("message is required for supervisor replies.");
|
|
543
509
|
const reply: SupervisorReply = {
|
|
544
510
|
type: "subagent.supervisor.reply",
|
|
@@ -548,6 +514,29 @@ function writeReply(request: PendingSupervisorRequest, message: string): void {
|
|
|
548
514
|
};
|
|
549
515
|
writeAtomicJson(replyPath(request.channelDir, request.id), reply);
|
|
550
516
|
removeRequestFile(request.requestFile);
|
|
517
|
+
return reply;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
function appendSupervisorReplyEntry(pi: ExtensionAPI, request: PendingSupervisorRequest, reply: SupervisorReply): void {
|
|
521
|
+
const appendEntry = (pi as unknown as {
|
|
522
|
+
appendEntry?: (customType: string, data?: SupervisorReplyEntryData) => void;
|
|
523
|
+
}).appendEntry;
|
|
524
|
+
if (typeof appendEntry !== "function") return;
|
|
525
|
+
try {
|
|
526
|
+
appendEntry.call(pi, SUPERVISOR_REPLY_ENTRY_TYPE, {
|
|
527
|
+
requestId: request.id,
|
|
528
|
+
reason: request.reason,
|
|
529
|
+
runId: request.runId,
|
|
530
|
+
agent: request.agent,
|
|
531
|
+
childIndex: request.childIndex,
|
|
532
|
+
...(request.childTarget ? { childTarget: request.childTarget } : {}),
|
|
533
|
+
message: reply.message,
|
|
534
|
+
createdAt: reply.createdAt,
|
|
535
|
+
});
|
|
536
|
+
} catch (error) {
|
|
537
|
+
// The reply file is authoritative; a UI journal failure must not undo a delivered reply.
|
|
538
|
+
console.error("Failed to journal native supervisor reply:", error);
|
|
539
|
+
}
|
|
551
540
|
}
|
|
552
541
|
|
|
553
542
|
function resolvePendingRequest(pending: Map<string, PendingSupervisorRequest>, params: IntercomParams): PendingSupervisorRequest {
|
|
@@ -566,6 +555,7 @@ function resolvePendingRequest(pending: Map<string, PendingSupervisorRequest>, p
|
|
|
566
555
|
);
|
|
567
556
|
if (matches.length === 1) return matches[0]!;
|
|
568
557
|
if (matches.length > 1) throw new Error(`Multiple pending supervisor requests match '${params.to}'. Use replyTo.`);
|
|
558
|
+
throw new Error(`No pending supervisor request matches '${params.to}'. Use replyTo.`);
|
|
569
559
|
}
|
|
570
560
|
if (requests.length === 1) return requests[0]!;
|
|
571
561
|
if (requests.length === 0) throw new Error("No pending supervisor requests need a reply.");
|
|
@@ -583,14 +573,16 @@ function publicPendingRequests(pending: Map<string, PendingSupervisorRequest>):
|
|
|
583
573
|
}));
|
|
584
574
|
}
|
|
585
575
|
|
|
586
|
-
function buildParentSupervisorTool(pending: Map<string, PendingSupervisorRequest>, state: SubagentState): ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> {
|
|
576
|
+
function buildParentSupervisorTool(pi: ExtensionAPI, pending: Map<string, PendingSupervisorRequest>, state: SubagentState, onLifecycle: SupervisorRequestLifecycleObserver, discover: () => void, runState: (request: SupervisorRequest) => SubagentState): ToolDefinition<typeof IntercomParamsSchema, Record<string, unknown>> {
|
|
587
577
|
return {
|
|
588
578
|
name: NATIVE_SUPERVISOR_TOOL_NAME,
|
|
589
579
|
label: "Subagent Supervisor",
|
|
590
580
|
description: "Native pi-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding pi-intercom.",
|
|
591
581
|
parameters: IntercomParamsSchema,
|
|
592
582
|
async execute(_id, params) {
|
|
593
|
-
|
|
583
|
+
// Discover new request files even when demand-gated polling is idle.
|
|
584
|
+
discover();
|
|
585
|
+
refreshPendingRequests(pending, state, onLifecycle, runState);
|
|
594
586
|
const input = params as IntercomParams;
|
|
595
587
|
if (input.action === "status") {
|
|
596
588
|
return { content: [{ type: "text", text: `Native supervisor channel active. Pending replies: ${pending.size}.` }], details: { active: true, pending: pending.size, root: SUPERVISOR_CHANNEL_ROOT } };
|
|
@@ -601,23 +593,85 @@ function buildParentSupervisorTool(pending: Map<string, PendingSupervisorRequest
|
|
|
601
593
|
}
|
|
602
594
|
if (input.action === "reply") {
|
|
603
595
|
const request = resolvePendingRequest(pending, input);
|
|
604
|
-
writeReply(request, input.message ?? "");
|
|
596
|
+
const reply = writeReply(request, input.message ?? "");
|
|
597
|
+
appendSupervisorReplyEntry(pi, request, reply);
|
|
598
|
+
onLifecycle(request, "resolved");
|
|
605
599
|
pending.delete(request.id);
|
|
606
600
|
clearForegroundSupervisorAttention(request, pending, state);
|
|
607
601
|
return { content: [{ type: "text", text: `Replied to supervisor request ${request.id}.` }], details: { replyTo: request.id, runId: request.runId, agent: request.agent } };
|
|
608
602
|
}
|
|
609
|
-
if (input.action === "send" || input.action === "ask") {
|
|
610
|
-
throw new Error("The native subagent supervisor handles replies only. Child agents initiate asks with contact_supervisor.");
|
|
611
|
-
}
|
|
612
603
|
throw new Error(`Unsupported supervisor action: ${input.action}`);
|
|
613
604
|
},
|
|
614
605
|
};
|
|
615
606
|
}
|
|
616
607
|
|
|
617
|
-
export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentState, deps: NativeSupervisorChannelDeps = {}): {
|
|
608
|
+
export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentState, deps: NativeSupervisorChannelDeps = {}): {
|
|
609
|
+
start: () => void;
|
|
610
|
+
activateTransport: () => void;
|
|
611
|
+
findPendingAsks: (target: { runId: string; agent: string; childIndex: number }) => string[];
|
|
612
|
+
dispose: () => void;
|
|
613
|
+
pending: Map<string, PendingSupervisorRequest>;
|
|
614
|
+
getSupervisorRequestState: (event: ControlEvent) => SupervisorRequestState;
|
|
615
|
+
} {
|
|
618
616
|
const watch = deps.watch ?? fs.watch;
|
|
619
617
|
const timers = deps.timers ?? globalThis;
|
|
618
|
+
const runState = (request: SupervisorRequest): SubagentState => {
|
|
619
|
+
for (const ownerState of deps.getCurrentOwnerStates?.() ?? []) {
|
|
620
|
+
if (ownerState.asyncJobs.has(request.runId)) return ownerState;
|
|
621
|
+
}
|
|
622
|
+
return state;
|
|
623
|
+
};
|
|
620
624
|
const pending = new Map<string, PendingSupervisorRequest>();
|
|
625
|
+
const requestCorrelations = new Map<string, SupervisorRequestCorrelation>();
|
|
626
|
+
const correlationKey = (request: { runId: string; agent: string; childIndex: number; toolCallId?: string }): string | undefined => {
|
|
627
|
+
if (!request.toolCallId) return undefined;
|
|
628
|
+
return JSON.stringify([request.runId, request.agent, request.childIndex, request.toolCallId]);
|
|
629
|
+
};
|
|
630
|
+
const pruneRequestCorrelations = (now = Date.now()): void => {
|
|
631
|
+
for (const [key, correlation] of requestCorrelations) {
|
|
632
|
+
if (correlation.state === "resolved" && now - correlation.updatedAt > SUPERVISOR_REQUEST_CORRELATION_RETENTION_MS) requestCorrelations.delete(key);
|
|
633
|
+
}
|
|
634
|
+
while (requestCorrelations.size > MAX_SUPERVISOR_REQUEST_CORRELATIONS) {
|
|
635
|
+
const oldest = requestCorrelations.keys().next().value;
|
|
636
|
+
if (oldest === undefined) break;
|
|
637
|
+
requestCorrelations.delete(oldest);
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
const rememberPendingRequest = (request: PendingSupervisorRequest): void => {
|
|
641
|
+
const key = correlationKey(request);
|
|
642
|
+
if (!key || !request.expectsReply) return;
|
|
643
|
+
requestCorrelations.set(key, { request, state: "pending", updatedAt: Date.now() });
|
|
644
|
+
pruneRequestCorrelations();
|
|
645
|
+
};
|
|
646
|
+
const rememberResolvedRequest = (request: PendingSupervisorRequest): void => {
|
|
647
|
+
const key = correlationKey(request);
|
|
648
|
+
if (!key || !request.expectsReply) return;
|
|
649
|
+
requestCorrelations.set(key, { request, state: "resolved", updatedAt: Date.now() });
|
|
650
|
+
pruneRequestCorrelations();
|
|
651
|
+
};
|
|
652
|
+
const observeRequestLifecycle: SupervisorRequestLifecycleObserver = (request, lifecycle) => {
|
|
653
|
+
if (lifecycle !== "wrong-session") rememberResolvedRequest(request);
|
|
654
|
+
};
|
|
655
|
+
const getSupervisorRequestState = (event: ControlEvent): SupervisorRequestState => {
|
|
656
|
+
if (event.currentTool === "intercom" || event.index === undefined) return "unknown";
|
|
657
|
+
const toolCallId = typeof event.toolCallId === "string" && event.toolCallId.length > 0 ? event.toolCallId : undefined;
|
|
658
|
+
if (!toolCallId) return "unknown";
|
|
659
|
+
pruneRequestCorrelations();
|
|
660
|
+
const key = correlationKey({ runId: event.runId, agent: event.agent, childIndex: event.index, toolCallId });
|
|
661
|
+
if (!key) return "unknown";
|
|
662
|
+
const correlation = requestCorrelations.get(key);
|
|
663
|
+
if (!correlation) return "unknown";
|
|
664
|
+
if (correlation.state === "resolved") return "resolved";
|
|
665
|
+
const now = Date.now();
|
|
666
|
+
if (!fs.existsSync(correlation.request.requestFile)
|
|
667
|
+
|| fs.existsSync(replyPath(correlation.request.channelDir, correlation.request.id))
|
|
668
|
+
|| now > requestExpiresAt(correlation.request, now)
|
|
669
|
+
|| requestRunInactive(correlation.request, runState(correlation.request))) {
|
|
670
|
+
rememberResolvedRequest(correlation.request);
|
|
671
|
+
return "resolved";
|
|
672
|
+
}
|
|
673
|
+
return "pending";
|
|
674
|
+
};
|
|
621
675
|
const seenFiles = new Set<string>();
|
|
622
676
|
const requestWatchers = new Map<string, fs.FSWatcher>();
|
|
623
677
|
let rootWatcher: fs.FSWatcher | undefined;
|
|
@@ -631,11 +685,17 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
631
685
|
const hasTransportDemand = () => {
|
|
632
686
|
if (pending.size > 0) return true;
|
|
633
687
|
if (state.foregroundControls.size > 0) return true;
|
|
634
|
-
|
|
688
|
+
if ([...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running")) return true;
|
|
689
|
+
for (const ownerState of deps.getCurrentOwnerStates?.() ?? []) {
|
|
690
|
+
for (const job of ownerState.asyncJobs.values()) {
|
|
691
|
+
if (job.status === "queued" || job.status === "running") return true;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
return false;
|
|
635
695
|
};
|
|
636
696
|
|
|
637
697
|
const registerParentTools = (): void => {
|
|
638
|
-
if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME)) pi.registerTool(buildParentSupervisorTool(pending, state));
|
|
698
|
+
if (!hasTool(pi, NATIVE_SUPERVISOR_TOOL_NAME)) pi.registerTool(buildParentSupervisorTool(pi, pending, state, observeRequestLifecycle, () => poll(), runState));
|
|
639
699
|
};
|
|
640
700
|
|
|
641
701
|
const cleanupStaleChannelsIfDue = (): void => {
|
|
@@ -651,41 +711,54 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
651
711
|
|
|
652
712
|
const poll = (): void => {
|
|
653
713
|
cleanupStaleChannelsIfDue();
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
refreshPendingRequests(pending, state, ctx);
|
|
714
|
+
// Only display notifications require a live UI context, not request registration.
|
|
715
|
+
refreshPendingRequests(pending, state, observeRequestLifecycle, runState);
|
|
657
716
|
const now = Date.now();
|
|
658
717
|
for (const { channelDir, file } of listRequestFiles()) {
|
|
659
718
|
if (seenFiles.has(file)) continue;
|
|
660
719
|
const request = parseRequestFile(file, channelDir);
|
|
661
|
-
if (!request || !
|
|
662
|
-
const lifecycle = requestLifecycle(request, state,
|
|
720
|
+
if (!request || !requestMatchesOwner(request, state)) continue;
|
|
721
|
+
const lifecycle = requestLifecycle(request, state, now, runState(request));
|
|
663
722
|
if (lifecycle !== "pending") {
|
|
664
723
|
seenFiles.add(file);
|
|
724
|
+
observeRequestLifecycle(request, lifecycle);
|
|
665
725
|
cleanupRequestLifecycle(request, lifecycle);
|
|
666
726
|
continue;
|
|
667
727
|
}
|
|
668
728
|
seenFiles.add(file);
|
|
669
729
|
if (request.expectsReply) {
|
|
730
|
+
rememberPendingRequest(request);
|
|
670
731
|
pending.set(request.id, request);
|
|
671
732
|
markForegroundSupervisorAttention(request, state);
|
|
672
733
|
}
|
|
673
|
-
|
|
674
|
-
|
|
734
|
+
// The ask is already queued above. A sendMessage failure (no UI, stale context) must not
|
|
735
|
+
// lose it, and must not abort the loop before the remaining asks register.
|
|
736
|
+
try {
|
|
737
|
+
pi.sendMessage({
|
|
738
|
+
customType: SUPERVISOR_REQUEST_MESSAGE_TYPE,
|
|
739
|
+
content: requestVisibleText(request),
|
|
740
|
+
display: true,
|
|
741
|
+
details: {
|
|
742
|
+
id: request.id,
|
|
743
|
+
requestId: request.id,
|
|
744
|
+
reason: request.reason,
|
|
745
|
+
expectsReply: request.expectsReply,
|
|
746
|
+
runId: request.runId,
|
|
747
|
+
agent: request.agent,
|
|
748
|
+
childIndex: request.childIndex,
|
|
749
|
+
...(request.childTarget ? { childTarget: request.childTarget } : {}),
|
|
750
|
+
...(request.interview !== undefined ? { interview: request.interview } : {}),
|
|
751
|
+
requestBody: request.message,
|
|
752
|
+
...(request.expectsReply ? { replyHint: supervisorReplyHint(request.id) } : {}),
|
|
753
|
+
},
|
|
754
|
+
}, { triggerTurn: true });
|
|
755
|
+
// sendMessage accepts synchronously; one-way updates stay on disk until it returns.
|
|
756
|
+
if (!request.expectsReply) removeRequestFile(request.requestFile);
|
|
757
|
+
} catch (error) {
|
|
758
|
+
// Allow an existing later scan to retry an unaccepted one-way update.
|
|
759
|
+
if (!request.expectsReply) seenFiles.delete(file);
|
|
760
|
+
console.error(`Failed to surface supervisor request ${request.id} as a user turn:`, error);
|
|
675
761
|
}
|
|
676
|
-
pi.sendMessage({
|
|
677
|
-
customType: "subagent_supervisor_request",
|
|
678
|
-
content: requestVisibleText(request),
|
|
679
|
-
display: true,
|
|
680
|
-
details: {
|
|
681
|
-
id: request.id,
|
|
682
|
-
reason: request.reason,
|
|
683
|
-
expectsReply: request.expectsReply,
|
|
684
|
-
runId: request.runId,
|
|
685
|
-
agent: request.agent,
|
|
686
|
-
childIndex: request.childIndex,
|
|
687
|
-
},
|
|
688
|
-
}, { triggerTurn: true });
|
|
689
762
|
if (request.expectsReply) {
|
|
690
763
|
(pi as { events?: IntercomEventBus }).events?.emit(INTERCOM_DETACH_REQUEST_EVENT, {
|
|
691
764
|
requestId: request.id,
|
|
@@ -762,6 +835,23 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
762
835
|
poll();
|
|
763
836
|
if (!useNativeWatcher() && hasTransportDemand()) startPolling();
|
|
764
837
|
},
|
|
838
|
+
findPendingAsks: (target) => {
|
|
839
|
+
// Receipt-only discovery: no registration, notification, cleanup or reply writes.
|
|
840
|
+
const channelDir = resolveSupervisorChannelDir(target.runId, target.agent, target.childIndex);
|
|
841
|
+
let files: string[];
|
|
842
|
+
try { files = fs.readdirSync(path.join(channelDir, REQUESTS_DIR)); }
|
|
843
|
+
catch (error) {
|
|
844
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return [];
|
|
845
|
+
throw error;
|
|
846
|
+
}
|
|
847
|
+
const now = Date.now();
|
|
848
|
+
return files.filter(file => file.endsWith(".json")).flatMap(file => {
|
|
849
|
+
const request = parseRequestFile(path.join(channelDir, REQUESTS_DIR, file), channelDir);
|
|
850
|
+
return request?.expectsReply && request.runId === target.runId
|
|
851
|
+
&& request.agent === target.agent && request.childIndex === target.childIndex
|
|
852
|
+
&& requestLifecycle(request, state, now, runState(request)) === "pending" ? [request.id] : [];
|
|
853
|
+
}).sort();
|
|
854
|
+
},
|
|
765
855
|
start: () => {
|
|
766
856
|
if (started) return;
|
|
767
857
|
started = true;
|
|
@@ -805,8 +895,10 @@ export function createNativeSupervisorChannel(pi: ExtensionAPI, state: SubagentS
|
|
|
805
895
|
if (deferredWatcherRefresh) timers.clearImmediate(deferredWatcherRefresh);
|
|
806
896
|
deferredWatcherRefresh = undefined;
|
|
807
897
|
pending.clear();
|
|
898
|
+
requestCorrelations.clear();
|
|
808
899
|
seenFiles.clear();
|
|
809
900
|
},
|
|
810
901
|
pending,
|
|
902
|
+
getSupervisorRequestState,
|
|
811
903
|
};
|
|
812
904
|
}
|