@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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Cross-OS control channel for async subagent runs.
|
|
3
3
|
*
|
|
4
|
-
* Background runs use
|
|
4
|
+
* Background runs use a detached runner process. Unix detaches it from the parent process.
|
|
5
5
|
* The original control path delivered an interrupt with
|
|
6
6
|
* `process.kill(pid, SIGUSR2|SIGBREAK)`, but Windows cannot
|
|
7
7
|
* deliver those signals cross-process via `process.kill` and throws `ENOSYS`,
|
|
@@ -74,33 +74,10 @@ export interface SteerRequest {
|
|
|
74
74
|
source?: string;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
export interface SteerCapability {
|
|
78
|
-
type: "steer-capability";
|
|
79
|
-
protocolVersion: 1;
|
|
80
|
-
index: number;
|
|
81
|
-
pid: number;
|
|
82
|
-
readyAt: number;
|
|
83
|
-
supported: boolean;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export interface SteerAck {
|
|
87
|
-
type: "steer-ack";
|
|
88
|
-
protocolVersion: 1;
|
|
89
|
-
requestId: string;
|
|
90
|
-
index: number;
|
|
91
|
-
ts: number;
|
|
92
|
-
state: "delivered" | "queued" | "failed";
|
|
93
|
-
deliveryStatus?: SteerDeliveryStatus;
|
|
94
|
-
message: string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
77
|
const STEER_REQUESTS_DIR = "steer-requests";
|
|
98
78
|
const STOP_REQUESTS_DIR = "stop-requests";
|
|
99
79
|
const REVIVAL_BRIEFS_DIR = "revival-briefs";
|
|
100
80
|
export const MAX_STEER_QUEUE_SIZE = 20;
|
|
101
|
-
const STEER_TARGETS_DIR = "steer-targets";
|
|
102
|
-
const STEER_CAPABILITIES_DIR = "steer-capabilities";
|
|
103
|
-
const STEER_ACKS_DIR = "steer-acks";
|
|
104
81
|
const STEER_INBOX_CLOSED_FILE = "steer-inbox-closed.json";
|
|
105
82
|
const MAX_STEER_MESSAGE_BYTES = 128 * 1024;
|
|
106
83
|
const MAX_STEER_REQUEST_ID_LENGTH = 256;
|
|
@@ -143,35 +120,6 @@ export function closeSteerInbox(asyncDir: string, state: string, write: (filePat
|
|
|
143
120
|
write(steerInboxClosedPath(asyncDir), { version: 1, closedAt: Date.now(), state });
|
|
144
121
|
}
|
|
145
122
|
|
|
146
|
-
/** Per-child inbox consumed by the child prompt runtime inside the Pi process. */
|
|
147
|
-
export function stepSteerInboxDir(asyncDir: string, index: number): string {
|
|
148
|
-
assertChildIndex(index);
|
|
149
|
-
return path.join(controlInboxDir(asyncDir), STEER_TARGETS_DIR, String(index));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function steerCapabilitiesDir(asyncDir: string): string {
|
|
153
|
-
return path.join(controlInboxDir(asyncDir), STEER_CAPABILITIES_DIR);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export function steerCapabilityPath(asyncDir: string, index: number): string {
|
|
157
|
-
assertChildIndex(index);
|
|
158
|
-
return path.join(steerCapabilitiesDir(asyncDir), `${index}.json`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function steerAcksDir(asyncDir: string, index: number): string {
|
|
162
|
-
assertChildIndex(index);
|
|
163
|
-
return path.join(controlInboxDir(asyncDir), STEER_ACKS_DIR, String(index));
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function steerAckFileName(requestId: string): string {
|
|
167
|
-
return `${Buffer.from(requestId).toString("base64url")}.json`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
export function steerAckPathFromDir(dir: string, requestId: string): string {
|
|
171
|
-
if (!/^[^\s]+$/.test(requestId) || requestId.length > 256) throw new Error("steer acknowledgment requestId is invalid.");
|
|
172
|
-
return path.join(dir, steerAckFileName(requestId));
|
|
173
|
-
}
|
|
174
|
-
|
|
175
123
|
function assertChildIndex(index: number): void {
|
|
176
124
|
if (!Number.isInteger(index) || index < 0 || index > 1_000_000) throw new Error("child index must be a non-negative integer.");
|
|
177
125
|
}
|
|
@@ -229,45 +177,6 @@ export function writeSteerRequestToExistingDir(dir: string, request: SteerReques
|
|
|
229
177
|
return requestPath;
|
|
230
178
|
}
|
|
231
179
|
|
|
232
|
-
export function writeSteerCapabilityAt(filePath: string, capability: Omit<SteerCapability, "type" | "protocolVersion">): string {
|
|
233
|
-
assertChildIndex(capability.index);
|
|
234
|
-
if (!Number.isInteger(capability.pid) || capability.pid <= 0) throw new Error("steer capability pid must be a positive integer.");
|
|
235
|
-
if (!Number.isFinite(capability.readyAt) || capability.readyAt <= 0) throw new Error("steer capability readyAt must be a finite timestamp.");
|
|
236
|
-
const record: SteerCapability = { type: "steer-capability", protocolVersion: 1, ...capability };
|
|
237
|
-
writeAtomicJson(filePath, record);
|
|
238
|
-
return filePath;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
export function writeSteerCapability(asyncDir: string, capability: Omit<SteerCapability, "type" | "protocolVersion">): string {
|
|
242
|
-
return writeSteerCapabilityAt(steerCapabilityPath(asyncDir, capability.index), capability);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function steerAckWritePath(filePath: string, ack: Omit<SteerAck, "type" | "protocolVersion">): string {
|
|
246
|
-
const parsed = path.parse(filePath);
|
|
247
|
-
const stateOrder = ack.state === "queued" ? "0" : ack.state === "delivered" ? "1" : "2";
|
|
248
|
-
const timestamp = String(Math.trunc(ack.ts)).padStart(13, "0");
|
|
249
|
-
for (let suffix = 0; suffix < 1_000; suffix += 1) {
|
|
250
|
-
const candidate = path.join(parsed.dir, `${parsed.name}-${timestamp}-${stateOrder}-${ack.state}${suffix === 0 ? "" : `-${suffix}`}${parsed.ext}`);
|
|
251
|
-
if (!fs.existsSync(candidate)) return candidate;
|
|
252
|
-
}
|
|
253
|
-
throw new Error("steer acknowledgment queue is full.");
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export function writeSteerAckAt(filePath: string, ack: Omit<SteerAck, "type" | "protocolVersion">): string {
|
|
257
|
-
assertChildIndex(ack.index);
|
|
258
|
-
if (!/^[^\s]+$/.test(ack.requestId) || ack.requestId.length > 256) throw new Error("steer acknowledgment requestId is invalid.");
|
|
259
|
-
if (!Number.isFinite(ack.ts) || ack.ts <= 0) throw new Error("steer acknowledgment ts must be a finite timestamp.");
|
|
260
|
-
if (!ack.message.trim() || ack.message.length > 1000) throw new Error("steer acknowledgment message is invalid.");
|
|
261
|
-
const record: SteerAck = { type: "steer-ack", protocolVersion: 1, ...ack, message: ack.message.trim() };
|
|
262
|
-
const ackPath = steerAckWritePath(filePath, ack);
|
|
263
|
-
writeAtomicJson(ackPath, record);
|
|
264
|
-
return ackPath;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function writeSteerAck(asyncDir: string, ack: Omit<SteerAck, "type" | "protocolVersion">): string {
|
|
268
|
-
return writeSteerAckAt(path.join(steerAcksDir(asyncDir, ack.index), steerAckFileName(ack.requestId)), ack);
|
|
269
|
-
}
|
|
270
|
-
|
|
271
180
|
/**
|
|
272
181
|
* Parent side: drop a portable interrupt request the runner's inbox watcher will
|
|
273
182
|
* pick up regardless of OS. Written atomically (temp + rename), dir auto-created.
|
|
@@ -350,97 +259,6 @@ export function requestAsyncSteer(
|
|
|
350
259
|
return requestPath;
|
|
351
260
|
}
|
|
352
261
|
|
|
353
|
-
export function enqueueStepSteer(asyncDir: string, index: number, request: SteerRequest): string {
|
|
354
|
-
assertChildIndex(index);
|
|
355
|
-
const { targetIndexes: _targetIndexes, ...singleTargetRequest } = request;
|
|
356
|
-
return writeSteerRequestToDir(stepSteerInboxDir(asyncDir, index), { ...singleTargetRequest, targetIndex: index, type: "steer" });
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
function parseSteerCapability(raw: unknown): SteerCapability | undefined {
|
|
360
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
|
|
361
|
-
const input = raw as Partial<SteerCapability>;
|
|
362
|
-
if (input.type !== "steer-capability" || input.protocolVersion !== 1) return undefined;
|
|
363
|
-
const { index, pid, readyAt, supported } = input;
|
|
364
|
-
if (typeof index !== "number" || !Number.isInteger(index) || index < 0 || index > 1_000_000) return undefined;
|
|
365
|
-
if (typeof pid !== "number" || typeof readyAt !== "number" || !Number.isInteger(pid) || pid <= 0 || !Number.isFinite(readyAt) || readyAt <= 0 || typeof supported !== "boolean") return undefined;
|
|
366
|
-
return { type: "steer-capability", protocolVersion: 1, index, pid, readyAt, supported };
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
function parseSteerAck(raw: unknown): SteerAck | undefined {
|
|
370
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
|
|
371
|
-
const input = raw as Partial<SteerAck>;
|
|
372
|
-
if (input.type !== "steer-ack" || input.protocolVersion !== 1 || typeof input.requestId !== "string" || !/^[^\s]+$/.test(input.requestId) || input.requestId.length > 256) return undefined;
|
|
373
|
-
const { index, ts, state, message } = input;
|
|
374
|
-
if (typeof index !== "number" || typeof ts !== "number" || !Number.isInteger(index) || index < 0 || index > 1_000_000 || !Number.isFinite(ts) || ts <= 0) return undefined;
|
|
375
|
-
if (state !== "delivered" && state !== "queued" && state !== "failed") return undefined;
|
|
376
|
-
if (input.deliveryStatus !== undefined && input.deliveryStatus !== "delivered" && input.deliveryStatus !== "queued") return undefined;
|
|
377
|
-
if (typeof message !== "string" || !message.trim() || message.length > 1000) return undefined;
|
|
378
|
-
return { type: "steer-ack", protocolVersion: 1, requestId: input.requestId, index, ts, state, ...(input.deliveryStatus ? { deliveryStatus: input.deliveryStatus } : {}), message: message.trim() };
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
export function readSteerCapability(asyncDir: string, index: number): SteerCapability | undefined {
|
|
382
|
-
try {
|
|
383
|
-
return parseSteerCapability(JSON.parse(fs.readFileSync(steerCapabilityPath(asyncDir, index), "utf-8")));
|
|
384
|
-
} catch {
|
|
385
|
-
return undefined;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
export function consumeSteerCapabilities(asyncDir: string, fsImpl: Pick<typeof fs, "existsSync" | "readdirSync" | "readFileSync"> = fs): SteerCapability[] {
|
|
390
|
-
const dir = steerCapabilitiesDir(asyncDir);
|
|
391
|
-
if (!fsImpl.existsSync(dir)) return [];
|
|
392
|
-
const capabilities: SteerCapability[] = [];
|
|
393
|
-
for (const entry of fsImpl.readdirSync(dir).filter((name) => /^\d+\.json$/.test(name)).sort()) {
|
|
394
|
-
try {
|
|
395
|
-
const capability = parseSteerCapability(JSON.parse(fsImpl.readFileSync(path.join(dir, entry), "utf-8")));
|
|
396
|
-
if (capability) capabilities.push(capability);
|
|
397
|
-
} catch {
|
|
398
|
-
// A partially written or malformed capability is ignored until a valid one arrives.
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return capabilities;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
export function consumeSteerAckFromDir(
|
|
405
|
-
dir: string,
|
|
406
|
-
requestId: string,
|
|
407
|
-
fsImpl: Pick<typeof fs, "existsSync" | "readdirSync" | "readFileSync" | "rmSync"> = fs,
|
|
408
|
-
): SteerAck | undefined {
|
|
409
|
-
if (!fsImpl.existsSync(dir)) return undefined;
|
|
410
|
-
let entries: string[];
|
|
411
|
-
try { entries = fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort(); } catch { return undefined; }
|
|
412
|
-
for (const entry of entries) {
|
|
413
|
-
const target = path.join(dir, entry);
|
|
414
|
-
let ack: SteerAck | undefined;
|
|
415
|
-
try { ack = parseSteerAck(JSON.parse(fsImpl.readFileSync(target, "utf-8"))); } catch { ack = undefined; }
|
|
416
|
-
if (ack?.requestId !== requestId) continue;
|
|
417
|
-
try { fsImpl.rmSync(target, { force: true }); } catch { return undefined; }
|
|
418
|
-
return ack;
|
|
419
|
-
}
|
|
420
|
-
return undefined;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
export function consumeSteerAcks(asyncDir: string, fsImpl: Pick<typeof fs, "existsSync" | "readdirSync" | "readFileSync" | "rmSync"> = fs): SteerAck[] {
|
|
424
|
-
const root = path.join(controlInboxDir(asyncDir), STEER_ACKS_DIR);
|
|
425
|
-
if (!fsImpl.existsSync(root)) return [];
|
|
426
|
-
const acks: SteerAck[] = [];
|
|
427
|
-
let indexNames: string[];
|
|
428
|
-
try { indexNames = fsImpl.readdirSync(root).filter((name) => /^\d+$/.test(name)); } catch { return []; }
|
|
429
|
-
for (const indexName of indexNames) {
|
|
430
|
-
const dir = path.join(root, indexName);
|
|
431
|
-
let entries: string[];
|
|
432
|
-
try { entries = fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort(); } catch { continue; }
|
|
433
|
-
for (const entry of entries) {
|
|
434
|
-
const target = path.join(dir, entry);
|
|
435
|
-
let ack: SteerAck | undefined;
|
|
436
|
-
try { ack = parseSteerAck(JSON.parse(fsImpl.readFileSync(target, "utf-8"))); } catch { ack = undefined; }
|
|
437
|
-
try { fsImpl.rmSync(target, { force: true }); } catch { continue; }
|
|
438
|
-
if (ack) acks.push(ack);
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
return acks;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
262
|
function parseSteerRequest(raw: unknown): SteerRequest | undefined {
|
|
445
263
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
|
|
446
264
|
const input = raw as Partial<SteerRequest>;
|
|
@@ -457,28 +275,36 @@ function parseSteerRequest(raw: unknown): SteerRequest | undefined {
|
|
|
457
275
|
};
|
|
458
276
|
}
|
|
459
277
|
|
|
460
|
-
export function consumeSteerRequestsFromDir(dir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs): SteerRequest[] {
|
|
461
|
-
if (!fsImpl.existsSync(dir)) return [];
|
|
278
|
+
export function consumeSteerRequestsFromDir(dir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs, onError: (error: unknown) => void = () => {}): SteerRequest[] {
|
|
462
279
|
let entries: string[];
|
|
463
280
|
try {
|
|
464
281
|
entries = fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort();
|
|
465
|
-
} catch {
|
|
282
|
+
} catch (error) {
|
|
466
283
|
// Leave requests in place so the periodic poll can retry the scan.
|
|
284
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") onError(error);
|
|
467
285
|
return [];
|
|
468
286
|
}
|
|
469
287
|
const requests: SteerRequest[] = [];
|
|
470
288
|
for (const entry of entries) {
|
|
471
289
|
const requestPath = path.join(dir, entry);
|
|
472
290
|
let parsed: SteerRequest | undefined;
|
|
291
|
+
let text: string;
|
|
473
292
|
try {
|
|
474
|
-
|
|
293
|
+
text = fsImpl.readFileSync(requestPath, "utf-8");
|
|
294
|
+
} catch (error) {
|
|
295
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") onError(error);
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
try {
|
|
299
|
+
parsed = parseSteerRequest(JSON.parse(text));
|
|
475
300
|
} catch {
|
|
476
301
|
parsed = undefined;
|
|
477
302
|
}
|
|
478
303
|
try {
|
|
479
304
|
fsImpl.rmSync(requestPath, { recursive: true });
|
|
480
|
-
} catch {
|
|
305
|
+
} catch (error) {
|
|
481
306
|
// Already removed by a concurrent check — do not execute it twice.
|
|
307
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") onError(error);
|
|
482
308
|
continue;
|
|
483
309
|
}
|
|
484
310
|
if (parsed) requests.push(parsed);
|
|
@@ -486,8 +312,8 @@ export function consumeSteerRequestsFromDir(dir: string, fsImpl: Pick<typeof fs,
|
|
|
486
312
|
return requests.sort((left, right) => left.ts - right.ts || left.id.localeCompare(right.id));
|
|
487
313
|
}
|
|
488
314
|
|
|
489
|
-
export function consumeSteerRequests(asyncDir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs): SteerRequest[] {
|
|
490
|
-
return consumeSteerRequestsFromDir(steerRequestsDir(asyncDir), fsImpl);
|
|
315
|
+
export function consumeSteerRequests(asyncDir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs, onError?: (error: unknown) => void): SteerRequest[] {
|
|
316
|
+
return consumeSteerRequestsFromDir(steerRequestsDir(asyncDir), fsImpl, onError);
|
|
491
317
|
}
|
|
492
318
|
|
|
493
319
|
export function queueRevivalBrief(asyncDir: string, request: SteerRequest): string {
|
|
@@ -569,17 +395,26 @@ function parseStopRequest(raw: unknown): StopRequest | undefined {
|
|
|
569
395
|
function consumeStopRequestFile(
|
|
570
396
|
requestPath: string,
|
|
571
397
|
fsImpl: Pick<typeof fs, "rmSync" | "readFileSync">,
|
|
398
|
+
onError?: (error: unknown) => void,
|
|
572
399
|
): StopRequest | undefined {
|
|
400
|
+
let text: string;
|
|
401
|
+
try {
|
|
402
|
+
text = fsImpl.readFileSync(requestPath, "utf-8");
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) onError?.(error);
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
573
407
|
let request: StopRequest | undefined;
|
|
574
408
|
try {
|
|
575
|
-
request = parseStopRequest(JSON.parse(
|
|
409
|
+
request = parseStopRequest(JSON.parse(text));
|
|
576
410
|
} catch {
|
|
577
411
|
request = undefined;
|
|
578
412
|
}
|
|
579
413
|
try {
|
|
580
414
|
fsImpl.rmSync(requestPath, { force: true, recursive: true });
|
|
581
|
-
} catch {
|
|
582
|
-
//
|
|
415
|
+
} catch (error) {
|
|
416
|
+
// Execute only after successful removal.
|
|
417
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) onError?.(error);
|
|
583
418
|
return undefined;
|
|
584
419
|
}
|
|
585
420
|
return request;
|
|
@@ -588,6 +423,7 @@ function consumeStopRequestFile(
|
|
|
588
423
|
export function consumeStopRequestPayloads(
|
|
589
424
|
asyncDir: string,
|
|
590
425
|
fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs,
|
|
426
|
+
onError?: (error: unknown) => void,
|
|
591
427
|
): StopRequest[] {
|
|
592
428
|
const dir = stopRequestsDir(asyncDir);
|
|
593
429
|
const requests: StopRequest[] = [];
|
|
@@ -595,18 +431,19 @@ export function consumeStopRequestPayloads(
|
|
|
595
431
|
let entries: string[];
|
|
596
432
|
try {
|
|
597
433
|
entries = fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort();
|
|
598
|
-
} catch {
|
|
434
|
+
} catch (error) {
|
|
435
|
+
if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) onError?.(error);
|
|
599
436
|
entries = [];
|
|
600
437
|
}
|
|
601
438
|
for (const entry of entries) {
|
|
602
|
-
const request = consumeStopRequestFile(path.join(dir, entry), fsImpl);
|
|
439
|
+
const request = consumeStopRequestFile(path.join(dir, entry), fsImpl, onError);
|
|
603
440
|
if (request) requests.push(request);
|
|
604
441
|
}
|
|
605
442
|
}
|
|
606
443
|
|
|
607
444
|
const legacyPath = stopRequestPath(asyncDir);
|
|
608
445
|
if (fsImpl.existsSync(legacyPath)) {
|
|
609
|
-
const request = consumeStopRequestFile(legacyPath, fsImpl);
|
|
446
|
+
const request = consumeStopRequestFile(legacyPath, fsImpl, onError);
|
|
610
447
|
if (request) requests.push(request);
|
|
611
448
|
}
|
|
612
449
|
return requests.sort((left, right) => (left.ts ?? 0) - (right.ts ?? 0));
|
|
@@ -652,21 +489,21 @@ export function deliverStopRequest(input: {
|
|
|
652
489
|
requestAsyncStop(input.asyncDir, { ...(input.source ? { source: input.source } : {}), ...(input.targetIndex !== undefined ? { targetIndex: input.targetIndex } : {}), ...(input.childId ? { childId: input.childId } : {}) }, { now: input.now });
|
|
653
490
|
}
|
|
654
491
|
|
|
492
|
+
|
|
655
493
|
/**
|
|
656
|
-
*
|
|
657
|
-
*
|
|
494
|
+
* Active owner: watch and consume only kinds with installed handlers.
|
|
495
|
+
* Uses `fs.watch` when available and starts interval polling
|
|
658
496
|
* only when native watching is unavailable or fails. Fires once per distinct
|
|
659
497
|
* request. Returns a disposer.
|
|
660
498
|
*/
|
|
661
499
|
export function watchAsyncControlInbox(
|
|
662
500
|
asyncDir: string,
|
|
663
501
|
opts: {
|
|
664
|
-
onInterrupt
|
|
502
|
+
onInterrupt?: () => void;
|
|
665
503
|
onTimeout?: () => void;
|
|
666
504
|
onStop?: (request: StopRequest) => void;
|
|
667
505
|
onSteer?: (request: SteerRequest) => void;
|
|
668
|
-
|
|
669
|
-
onSteerAck?: (ack: SteerAck) => void;
|
|
506
|
+
onError?: (error: unknown, phase: "install" | "scan" | "callback", request?: SteerRequest) => void;
|
|
670
507
|
pollIntervalMs?: number;
|
|
671
508
|
safetyPollIntervalMs?: number;
|
|
672
509
|
platform?: NodeJS.Platform;
|
|
@@ -677,24 +514,44 @@ export function watchAsyncControlInbox(
|
|
|
677
514
|
const fsImpl = opts.fs ?? fs;
|
|
678
515
|
const timers = opts.timers ?? { setInterval, clearInterval };
|
|
679
516
|
const dir = controlInboxDir(asyncDir);
|
|
517
|
+
const report = (error: unknown, phase: "install" | "scan" | "callback", request?: SteerRequest): void => {
|
|
518
|
+
try {
|
|
519
|
+
if (opts.onError) opts.onError(error, phase, request);
|
|
520
|
+
else console.error(`Control inbox ${phase} failed:`, error);
|
|
521
|
+
} catch (reportError) {
|
|
522
|
+
console.error("Control inbox error reporter failed:", reportError);
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
const dirs = [
|
|
526
|
+
...(opts.onInterrupt || opts.onTimeout || opts.onStop ? [dir] : []),
|
|
527
|
+
...(opts.onStop ? [stopRequestsDir(asyncDir)] : []),
|
|
528
|
+
...(opts.onSteer ? [steerRequestsDir(asyncDir)] : []),
|
|
529
|
+
];
|
|
530
|
+
if (dirs.length === 0) return () => {};
|
|
680
531
|
try {
|
|
681
|
-
fsImpl.mkdirSync(
|
|
682
|
-
} catch {
|
|
683
|
-
|
|
532
|
+
for (const target of dirs) fsImpl.mkdirSync(target, { recursive: true });
|
|
533
|
+
} catch (error) {
|
|
534
|
+
report(error, "install");
|
|
684
535
|
}
|
|
685
536
|
|
|
686
537
|
let disposed = false;
|
|
687
538
|
const check = (): void => {
|
|
688
539
|
if (disposed) return;
|
|
689
540
|
try {
|
|
690
|
-
for (const
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
541
|
+
if (opts.onStop) for (const request of consumeStopRequestPayloads(asyncDir, fsImpl, (error) => report(error, "scan"))) {
|
|
542
|
+
try { opts.onStop(request); } catch (error) { report(error, "callback"); }
|
|
543
|
+
}
|
|
544
|
+
if (opts.onTimeout && consumeTimeoutRequest(asyncDir, fsImpl)) {
|
|
545
|
+
try { opts.onTimeout(); } catch (error) { report(error, "callback"); }
|
|
546
|
+
}
|
|
547
|
+
if (opts.onInterrupt && consumeInterruptRequest(asyncDir, fsImpl)) {
|
|
548
|
+
try { opts.onInterrupt(); } catch (error) { report(error, "callback"); }
|
|
549
|
+
}
|
|
550
|
+
if (opts.onSteer) for (const request of consumeSteerRequestsFromDir(steerRequestsDir(asyncDir), fsImpl, (error) => report(error, "scan"))) {
|
|
551
|
+
try { opts.onSteer(request); } catch (error) { report(error, "callback", request); }
|
|
552
|
+
}
|
|
553
|
+
} catch (error) {
|
|
554
|
+
report(error, "scan");
|
|
698
555
|
}
|
|
699
556
|
};
|
|
700
557
|
|
|
@@ -702,56 +559,31 @@ export function watchAsyncControlInbox(
|
|
|
702
559
|
check();
|
|
703
560
|
|
|
704
561
|
const watchers: fs.FSWatcher[] = [];
|
|
705
|
-
const watchedDirs = new Set<string>();
|
|
706
562
|
let interval: ReturnType<typeof setInterval> | undefined;
|
|
707
563
|
let safetyInterval: ReturnType<typeof setInterval> | undefined;
|
|
708
564
|
const startPolling = (): void => {
|
|
709
565
|
if (interval || disposed) return;
|
|
566
|
+
if (safetyInterval) { timers.clearInterval(safetyInterval); safetyInterval = undefined; }
|
|
710
567
|
interval = timers.setInterval(check, opts.pollIntervalMs ?? POLL_INTERVAL_MS);
|
|
711
568
|
interval.unref?.();
|
|
712
569
|
};
|
|
713
|
-
const startSafetyPolling = (): void => {
|
|
714
|
-
if (safetyInterval || disposed) return;
|
|
715
|
-
safetyInterval = timers.setInterval(check, opts.safetyPollIntervalMs ?? CONTROL_SAFETY_POLL_INTERVAL_MS);
|
|
716
|
-
safetyInterval.unref?.();
|
|
717
|
-
};
|
|
718
|
-
const watchDir = (target: string, create = false): void => {
|
|
719
|
-
if (disposed || watchedDirs.has(target)) return;
|
|
720
|
-
if (create) fsImpl.mkdirSync(target, { recursive: true });
|
|
721
|
-
const watcher = fsImpl.watch(resolveWatchPath(target, fsImpl.realpathSync.native), () => {
|
|
722
|
-
watchExistingSteerAckDirs();
|
|
723
|
-
check();
|
|
724
|
-
});
|
|
725
|
-
watcher.on?.("error", startPolling);
|
|
726
|
-
watchers.push(watcher);
|
|
727
|
-
watchedDirs.add(target);
|
|
728
|
-
};
|
|
729
|
-
const watchExistingSteerAckDirs = (): void => {
|
|
730
|
-
const ackRoot = path.join(dir, STEER_ACKS_DIR);
|
|
731
|
-
let entries: string[];
|
|
732
|
-
try {
|
|
733
|
-
entries = fsImpl.readdirSync(ackRoot).filter((name) => /^\d+$/.test(name));
|
|
734
|
-
} catch {
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
for (const entry of entries) watchDir(path.join(ackRoot, entry));
|
|
738
|
-
};
|
|
739
570
|
try {
|
|
740
571
|
if (shouldUseNativeFsWatch("runner-control-inbox", opts.platform)) {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
572
|
+
for (const target of dirs) {
|
|
573
|
+
const watcher = fsImpl.watch(resolveWatchPath(target, fsImpl.realpathSync.native), check);
|
|
574
|
+
watcher.on?.("error", startPolling);
|
|
575
|
+
watchers.push(watcher);
|
|
576
|
+
}
|
|
577
|
+
if (!interval) {
|
|
578
|
+
safetyInterval = timers.setInterval(check, opts.safetyPollIntervalMs ?? CONTROL_SAFETY_POLL_INTERVAL_MS);
|
|
579
|
+
safetyInterval.unref?.();
|
|
580
|
+
}
|
|
748
581
|
} else {
|
|
749
582
|
startPolling();
|
|
750
583
|
}
|
|
751
584
|
} catch {
|
|
752
585
|
startPolling();
|
|
753
586
|
}
|
|
754
|
-
|
|
755
587
|
return () => {
|
|
756
588
|
if (disposed) return;
|
|
757
589
|
disposed = true;
|