@selesai/code 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +4 -15
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -45
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +8 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/diagnostics.d.ts +1 -0
- package/dist/core/diagnostics.d.ts.map +1 -1
- package/dist/core/diagnostics.js.map +1 -1
- package/dist/core/model-registry.d.ts +4 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +101 -51
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/package-manager.d.ts +10 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +93 -8
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-manager.test.d.ts +2 -0
- package/dist/core/package-manager.test.d.ts.map +1 -0
- package/dist/core/package-manager.test.js +20 -0
- package/dist/core/package-manager.test.js.map +1 -0
- package/dist/core/resource-loader.d.ts +3 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +10 -0
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/defaults/models.json +64 -113
- package/dist/extensions/caveman/caveman-instructions.cjs +39 -0
- package/dist/extensions/caveman/index.js +116 -0
- package/dist/extensions/caveman/package.json +8 -0
- package/dist/extensions/caveman/test/extension.test.js +185 -0
- package/dist/extensions/caveman/test/helpers.test.js +67 -0
- package/dist/extensions/copy-turn.ts +2 -2
- package/dist/extensions/pi-intercom/broker/broker.ts +2 -3
- package/dist/extensions/pi-intercom/broker/paths.ts +10 -5
- package/dist/extensions/pi-intercom/broker/spawn.ts +2 -3
- package/dist/extensions/pi-intercom/config.ts +2 -2
- package/dist/extensions/pi-intercom/index.ts +2 -2
- package/dist/extensions/pi-intercom/package.json +2 -2
- package/dist/extensions/pi-intercom/ui/compose.ts +3 -3
- package/dist/extensions/pi-intercom/ui/inline-message.ts +3 -3
- package/dist/extensions/pi-intercom/ui/session-list.ts +3 -3
- package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +2 -2
- package/dist/extensions/pi-powerline-footer/bash-mode/history.ts +2 -1
- package/dist/extensions/pi-powerline-footer/index.ts +40 -47
- package/dist/extensions/pi-powerline-footer/package.json +2 -2
- package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +10 -10
- package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +1 -1
- package/dist/extensions/pi-powerline-footer/tests/working-vibes.test.ts +2 -2
- package/dist/extensions/pi-powerline-footer/theme.ts +6 -6
- package/dist/extensions/pi-powerline-footer/tps.ts +1 -1
- package/dist/extensions/pi-powerline-footer/types.ts +7 -7
- package/dist/extensions/pi-powerline-footer/welcome.ts +23 -16
- package/dist/extensions/pi-powerline-footer/working-vibes.ts +52 -59
- package/dist/extensions/pi-rewind-hook/index.ts +1 -1
- package/dist/extensions/pi-rewind-hook/package.json +1 -1
- package/dist/extensions/pi-subagents/README.md +224 -52
- package/dist/extensions/pi-subagents/agents/architect.md +188 -0
- package/dist/extensions/pi-subagents/agents/builder.md +120 -0
- package/dist/extensions/pi-subagents/agents/commentator.md +131 -0
- package/dist/extensions/pi-subagents/agents/explorer.md +51 -0
- package/dist/extensions/pi-subagents/agents/recapper.md +21 -0
- package/dist/extensions/pi-subagents/install.mjs +93 -0
- package/dist/extensions/pi-subagents/package.json +4 -5
- package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +1 -1
- package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +76 -13
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +179 -2
- package/dist/extensions/pi-subagents/src/agents/agent-memory.ts +254 -0
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +11 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +193 -19
- package/dist/extensions/pi-subagents/src/agents/chain-serializer.ts +27 -2
- package/dist/extensions/pi-subagents/src/extension/config.ts +27 -4
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +1 -7
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +3 -2
- package/dist/extensions/pi-subagents/src/extension/index.ts +73 -71
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +369 -0
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +54 -10
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +200 -0
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +21 -253
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +519 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +195 -105
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +88 -2
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +67 -10
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +34 -4
- package/dist/extensions/pi-subagents/src/runs/background/completion-batcher.ts +166 -0
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +156 -1
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +515 -0
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +161 -44
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +1 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +3 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +167 -6
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +514 -0
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +28 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +873 -204
- package/dist/extensions/pi-subagents/src/runs/background/wait.ts +353 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +123 -27
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +174 -70
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +569 -81
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +45 -22
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +172 -21
- package/dist/extensions/pi-subagents/src/runs/shared/model-scope.ts +128 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +50 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +35 -4
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +63 -45
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +125 -5
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +74 -0
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +52 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +28 -5
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +16 -1
- package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +15 -2
- package/dist/extensions/pi-subagents/src/shared/child-transcript.ts +212 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +133 -22
- package/dist/extensions/pi-subagents/src/shared/settings.ts +3 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +197 -4
- package/dist/extensions/pi-subagents/src/shared/utils.ts +108 -17
- package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +330 -0
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +135 -4
- package/dist/extensions/pi-subagents/src/tui/render.ts +32 -12
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +2772 -0
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +1107 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +463 -0
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +274 -0
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +1535 -0
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +242 -0
- package/dist/extensions/pi-subagents/test/integration/doctor-executor.test.ts +128 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +252 -0
- package/dist/extensions/pi-subagents/test/integration/foreground-result-size.test.ts +188 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +1306 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +1033 -0
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +397 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +583 -0
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +691 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +892 -0
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1824 -0
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1284 -0
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +299 -0
- package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +37 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +189 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +335 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +129 -0
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +184 -0
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +285 -0
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +15 -0
- package/dist/extensions/pi-subagents/test/support/ts-loader.mjs +108 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +421 -0
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +343 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +1199 -0
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +556 -0
- package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +420 -0
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +579 -0
- package/dist/extensions/pi-subagents/test/unit/agent-scope.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/unit/agent-selection.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +221 -0
- package/dist/extensions/pi-subagents/test/unit/async-permission-session.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +285 -0
- package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +112 -0
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +206 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +159 -0
- package/dist/extensions/pi-subagents/test/unit/chain-serializer.test.ts +229 -0
- package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +225 -0
- package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +101 -0
- package/dist/extensions/pi-subagents/test/unit/completion-batcher.test.ts +228 -0
- package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +36 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +72 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +327 -0
- package/dist/extensions/pi-subagents/test/unit/control-notices.test.ts +161 -0
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +159 -0
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +217 -0
- package/dist/extensions/pi-subagents/test/unit/extra-agent-dirs.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/file-coalescer.test.ts +68 -0
- package/dist/extensions/pi-subagents/test/unit/foreground-tool-call-compaction.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +415 -0
- package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +126 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +271 -0
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +173 -0
- package/dist/extensions/pi-subagents/test/unit/jsonl-writer.test.ts +119 -0
- package/dist/extensions/pi-subagents/test/unit/live-async-resume.test.ts +170 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +346 -0
- package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope-settings.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +145 -0
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +162 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +470 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +329 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +319 -0
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +70 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +247 -0
- package/dist/extensions/pi-subagents/test/unit/path-handling.test.ts +113 -0
- package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +803 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +238 -0
- package/dist/extensions/pi-subagents/test/unit/proactive-skills.test.ts +118 -0
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +299 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-template-bridge.test.ts +408 -0
- package/dist/extensions/pi-subagents/test/unit/prompt-workflows.test.ts +134 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +257 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +226 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +294 -0
- package/dist/extensions/pi-subagents/test/unit/run-id-resolver.test.ts +147 -0
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +997 -0
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +478 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +562 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +438 -0
- package/dist/extensions/pi-subagents/test/unit/slash-bridge.test.ts +54 -0
- package/dist/extensions/pi-subagents/test/unit/slash-chain-groups.test.ts +464 -0
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +255 -0
- package/dist/extensions/pi-subagents/test/unit/status-format.test.ts +19 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +517 -0
- package/dist/extensions/pi-subagents/test/unit/temp-paths.test.ts +72 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +237 -0
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/ts-loader.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +202 -0
- package/dist/extensions/pi-subagents/test/unit/types-fork-preamble.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/wait.test.ts +398 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +88 -0
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +26 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-graph.test.ts +134 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +479 -0
- package/dist/extensions/pi-web-agent/package.json +2 -2
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +2 -2
- package/dist/extensions/pi-web-agent/src/changelog-notice.ts +5 -2
- package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +1 -1
- package/dist/extensions/pi-web-agent/src/extension.ts +1 -1
- package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +6 -4
- package/dist/extensions/question/helpers.ts +3 -3
- package/dist/extensions/question/index.ts +2 -2
- package/dist/extensions/question/navigation.ts +2 -2
- package/dist/extensions/question/package.json +2 -2
- package/dist/extensions/question/question-list.ts +2 -2
- package/dist/extensions/question/tests/question-list.test.ts +2 -2
- package/dist/extensions/question/tui-adapter.ts +2 -2
- package/dist/extensions/question/types.ts +2 -2
- package/dist/extensions/question/ui-protocol.ts +2 -2
- package/dist/extensions/rtk.ts +2 -2
- package/dist/extensions/tokenin-onboarding.ts +2 -2
- package/dist/extensions/undo.ts +1 -1
- package/dist/extensions/web-agent-onboarding.ts +3 -3
- package/dist/extensions/workflow/adapter.ts +16 -8
- package/dist/extensions/workflow/extension.ts +1 -1
- package/dist/extensions/workflow/package.json +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +4 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +2 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +19 -5
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/skills/caveman/SKILL.md +49 -0
- package/dist/skills/handoff-text/SKILL.md +13 -0
- package/dist/utils/thinking-tags.d.ts +7 -0
- package/dist/utils/thinking-tags.d.ts.map +1 -0
- package/dist/utils/thinking-tags.js +63 -0
- package/dist/utils/thinking-tags.js.map +1 -0
- package/docs/docs.json +4 -0
- package/docs/extensions.md +2 -0
- package/docs/settings.md +15 -0
- package/docs/shared-host-extensions.md +109 -0
- package/package.json +2 -2
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* authoritative.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
+
import { randomUUID } from "node:crypto";
|
|
17
18
|
import * as fs from "node:fs";
|
|
18
19
|
import * as path from "node:path";
|
|
19
20
|
import { writeAtomicJson } from "../../shared/atomic-json.ts";
|
|
@@ -26,7 +27,7 @@ import { POLL_INTERVAL_MS } from "../../shared/types.ts";
|
|
|
26
27
|
*/
|
|
27
28
|
export const INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === "win32" ? "SIGBREAK" : "SIGUSR2";
|
|
28
29
|
|
|
29
|
-
export type ControlChannelFs = Pick<typeof fs, "mkdirSync" | "existsSync" | "rmSync" | "watch">;
|
|
30
|
+
export type ControlChannelFs = Pick<typeof fs, "mkdirSync" | "existsSync" | "rmSync" | "watch" | "readdirSync" | "readFileSync">;
|
|
30
31
|
export type ControlChannelTimers = { setInterval: typeof setInterval; clearInterval: typeof clearInterval };
|
|
31
32
|
type KillFn = (pid: number, signal?: NodeJS.Signals | 0) => unknown;
|
|
32
33
|
|
|
@@ -37,6 +38,25 @@ export interface InterruptRequest {
|
|
|
37
38
|
reason?: string;
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
export interface TimeoutRequest {
|
|
42
|
+
type: "timeout";
|
|
43
|
+
ts?: number;
|
|
44
|
+
source?: string;
|
|
45
|
+
reason?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface SteerRequest {
|
|
49
|
+
type: "steer";
|
|
50
|
+
id: string;
|
|
51
|
+
ts: number;
|
|
52
|
+
message: string;
|
|
53
|
+
targetIndex?: number;
|
|
54
|
+
source?: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const STEER_REQUESTS_DIR = "steer-requests";
|
|
58
|
+
const STEER_TARGETS_DIR = "steer-targets";
|
|
59
|
+
|
|
40
60
|
/** Control inbox directory inside an async run dir. */
|
|
41
61
|
export function controlInboxDir(asyncDir: string): string {
|
|
42
62
|
return path.join(asyncDir, "control");
|
|
@@ -47,6 +67,31 @@ export function interruptRequestPath(asyncDir: string): string {
|
|
|
47
67
|
return path.join(controlInboxDir(asyncDir), "interrupt.json");
|
|
48
68
|
}
|
|
49
69
|
|
|
70
|
+
/** Path of the portable timeout request file. */
|
|
71
|
+
export function timeoutRequestPath(asyncDir: string): string {
|
|
72
|
+
return path.join(controlInboxDir(asyncDir), "timeout.json");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** Directory of parent-to-runner steering requests. */
|
|
76
|
+
export function steerRequestsDir(asyncDir: string): string {
|
|
77
|
+
return path.join(controlInboxDir(asyncDir), STEER_REQUESTS_DIR);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Per-child inbox consumed by the child prompt runtime inside the Pi process. */
|
|
81
|
+
export function stepSteerInboxDir(asyncDir: string, index: number): string {
|
|
82
|
+
return path.join(controlInboxDir(asyncDir), STEER_TARGETS_DIR, String(index));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function steerRequestFileName(request: SteerRequest): string {
|
|
86
|
+
return `${String(request.ts).padStart(13, "0")}-${Buffer.from(request.id).toString("base64url")}.json`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function writeSteerRequestToDir(dir: string, request: SteerRequest): string {
|
|
90
|
+
const requestPath = path.join(dir, steerRequestFileName(request));
|
|
91
|
+
writeAtomicJson(requestPath, request);
|
|
92
|
+
return requestPath;
|
|
93
|
+
}
|
|
94
|
+
|
|
50
95
|
/**
|
|
51
96
|
* Parent side: drop a portable interrupt request the runner's inbox watcher will
|
|
52
97
|
* pick up regardless of OS. Written atomically (temp + rename), dir auto-created.
|
|
@@ -62,6 +107,87 @@ export function requestAsyncInterrupt(
|
|
|
62
107
|
return requestPath;
|
|
63
108
|
}
|
|
64
109
|
|
|
110
|
+
export function requestAsyncTimeout(
|
|
111
|
+
asyncDir: string,
|
|
112
|
+
payload: Omit<TimeoutRequest, "type"> = {},
|
|
113
|
+
deps: { now?: () => number } = {},
|
|
114
|
+
): string {
|
|
115
|
+
const requestPath = timeoutRequestPath(asyncDir);
|
|
116
|
+
const request: TimeoutRequest = { ...payload, ts: payload.ts ?? deps.now?.() ?? Date.now(), type: "timeout" };
|
|
117
|
+
writeAtomicJson(requestPath, request);
|
|
118
|
+
return requestPath;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function requestAsyncSteer(
|
|
122
|
+
asyncDir: string,
|
|
123
|
+
payload: { message: string; targetIndex?: number; source?: string; id?: string; ts?: number },
|
|
124
|
+
deps: { now?: () => number; randomId?: () => string } = {},
|
|
125
|
+
): string {
|
|
126
|
+
const message = payload.message.trim();
|
|
127
|
+
if (!message) throw new Error("steer message must not be empty.");
|
|
128
|
+
if (payload.targetIndex !== undefined && (!Number.isInteger(payload.targetIndex) || payload.targetIndex < 0)) {
|
|
129
|
+
throw new Error("steer targetIndex must be a non-negative integer.");
|
|
130
|
+
}
|
|
131
|
+
const request: SteerRequest = {
|
|
132
|
+
type: "steer",
|
|
133
|
+
id: payload.id ?? deps.randomId?.() ?? randomUUID(),
|
|
134
|
+
ts: payload.ts ?? deps.now?.() ?? Date.now(),
|
|
135
|
+
message,
|
|
136
|
+
...(payload.targetIndex !== undefined ? { targetIndex: payload.targetIndex } : {}),
|
|
137
|
+
...(payload.source ? { source: payload.source } : {}),
|
|
138
|
+
};
|
|
139
|
+
return writeSteerRequestToDir(steerRequestsDir(asyncDir), request);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function enqueueStepSteer(asyncDir: string, index: number, request: SteerRequest): string {
|
|
143
|
+
if (!Number.isInteger(index) || index < 0) throw new Error("steer child index must be a non-negative integer.");
|
|
144
|
+
return writeSteerRequestToDir(stepSteerInboxDir(asyncDir, index), { ...request, targetIndex: index, type: "steer" });
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function parseSteerRequest(raw: unknown): SteerRequest | undefined {
|
|
148
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return undefined;
|
|
149
|
+
const input = raw as Partial<SteerRequest>;
|
|
150
|
+
if (input.type !== "steer") return undefined;
|
|
151
|
+
if (typeof input.id !== "string" || !input.id.trim()) return undefined;
|
|
152
|
+
if (typeof input.ts !== "number" || !Number.isFinite(input.ts)) return undefined;
|
|
153
|
+
if (typeof input.message !== "string" || !input.message.trim()) return undefined;
|
|
154
|
+
if (input.targetIndex !== undefined && (!Number.isInteger(input.targetIndex) || input.targetIndex < 0)) return undefined;
|
|
155
|
+
return {
|
|
156
|
+
type: "steer",
|
|
157
|
+
id: input.id.trim(),
|
|
158
|
+
ts: input.ts,
|
|
159
|
+
message: input.message.trim(),
|
|
160
|
+
...(input.targetIndex !== undefined ? { targetIndex: input.targetIndex } : {}),
|
|
161
|
+
...(typeof input.source === "string" && input.source.trim() ? { source: input.source } : {}),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function consumeSteerRequestsFromDir(dir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs): SteerRequest[] {
|
|
166
|
+
if (!fsImpl.existsSync(dir)) return [];
|
|
167
|
+
const requests: SteerRequest[] = [];
|
|
168
|
+
for (const entry of fsImpl.readdirSync(dir).filter((name) => name.endsWith(".json")).sort()) {
|
|
169
|
+
const requestPath = path.join(dir, entry);
|
|
170
|
+
let parsed: SteerRequest | undefined;
|
|
171
|
+
try {
|
|
172
|
+
parsed = parseSteerRequest(JSON.parse(fsImpl.readFileSync(requestPath, "utf-8")));
|
|
173
|
+
} catch {
|
|
174
|
+
parsed = undefined;
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
fsImpl.rmSync(requestPath, { recursive: true });
|
|
178
|
+
} catch {
|
|
179
|
+
// Already removed by a concurrent check — do not execute it twice.
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (parsed) requests.push(parsed);
|
|
183
|
+
}
|
|
184
|
+
return requests.sort((left, right) => left.ts - right.ts || left.id.localeCompare(right.id));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function consumeSteerRequests(asyncDir: string, fsImpl: Pick<typeof fs, "existsSync" | "rmSync" | "readdirSync" | "readFileSync"> = fs): SteerRequest[] {
|
|
188
|
+
return consumeSteerRequestsFromDir(steerRequestsDir(asyncDir), fsImpl);
|
|
189
|
+
}
|
|
190
|
+
|
|
65
191
|
/**
|
|
66
192
|
* Runner side: consume a pending interrupt request. Idempotent — removes the file
|
|
67
193
|
* so each distinct request fires exactly once. Returns whether one was pending.
|
|
@@ -80,6 +206,20 @@ export function consumeInterruptRequest(
|
|
|
80
206
|
return true;
|
|
81
207
|
}
|
|
82
208
|
|
|
209
|
+
export function consumeTimeoutRequest(
|
|
210
|
+
asyncDir: string,
|
|
211
|
+
fsImpl: Pick<typeof fs, "existsSync" | "rmSync"> = fs,
|
|
212
|
+
): boolean {
|
|
213
|
+
const requestPath = timeoutRequestPath(asyncDir);
|
|
214
|
+
if (!fsImpl.existsSync(requestPath)) return false;
|
|
215
|
+
try {
|
|
216
|
+
fsImpl.rmSync(requestPath, { force: true, recursive: true });
|
|
217
|
+
} catch {
|
|
218
|
+
// Already removed by a concurrent check — still counts as consumed.
|
|
219
|
+
}
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
|
|
83
223
|
/**
|
|
84
224
|
* Parent side: portable interrupt = authoritative file request + best-effort OS
|
|
85
225
|
* signal. The signal is only a latency optimization on Unix; ENOSYS on Windows
|
|
@@ -114,6 +254,17 @@ export function deliverInterruptRequest(input: {
|
|
|
114
254
|
}
|
|
115
255
|
}
|
|
116
256
|
|
|
257
|
+
export function deliverTimeoutRequest(input: {
|
|
258
|
+
asyncDir: string;
|
|
259
|
+
pid?: number;
|
|
260
|
+
kill?: KillFn;
|
|
261
|
+
signal?: NodeJS.Signals;
|
|
262
|
+
now?: () => number;
|
|
263
|
+
source?: string;
|
|
264
|
+
}): void {
|
|
265
|
+
requestAsyncTimeout(input.asyncDir, input.source ? { source: input.source } : {}, { now: input.now });
|
|
266
|
+
}
|
|
267
|
+
|
|
117
268
|
/**
|
|
118
269
|
* Runner side: watch the control inbox and route interrupt requests into
|
|
119
270
|
* `onInterrupt`. Uses `fs.watch` when available plus an interval poll as a
|
|
@@ -124,6 +275,8 @@ export function watchAsyncControlInbox(
|
|
|
124
275
|
asyncDir: string,
|
|
125
276
|
opts: {
|
|
126
277
|
onInterrupt: () => void;
|
|
278
|
+
onTimeout?: () => void;
|
|
279
|
+
onSteer?: (request: SteerRequest) => void;
|
|
127
280
|
pollIntervalMs?: number;
|
|
128
281
|
fs?: ControlChannelFs;
|
|
129
282
|
timers?: ControlChannelTimers;
|
|
@@ -142,7 +295,9 @@ export function watchAsyncControlInbox(
|
|
|
142
295
|
const check = (): void => {
|
|
143
296
|
if (disposed) return;
|
|
144
297
|
try {
|
|
298
|
+
if (consumeTimeoutRequest(asyncDir, fsImpl)) opts.onTimeout?.();
|
|
145
299
|
if (consumeInterruptRequest(asyncDir, fsImpl)) opts.onInterrupt();
|
|
300
|
+
for (const request of consumeSteerRequests(asyncDir, fsImpl)) opts.onSteer?.(request);
|
|
146
301
|
} catch {
|
|
147
302
|
// Never let inbox errors crash the runner.
|
|
148
303
|
}
|