@botiverse/oar 0.0.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.
Files changed (183) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +13 -0
  3. package/dist/contracts/account-usage.d.ts +33 -0
  4. package/dist/contracts/account-usage.d.ts.map +1 -0
  5. package/dist/contracts/account-usage.js +2 -0
  6. package/dist/contracts/account-usage.js.map +1 -0
  7. package/dist/contracts/installation.d.ts +27 -0
  8. package/dist/contracts/installation.d.ts.map +1 -0
  9. package/dist/contracts/installation.js +2 -0
  10. package/dist/contracts/installation.js.map +1 -0
  11. package/dist/contracts/runtime.d.ts +12 -0
  12. package/dist/contracts/runtime.d.ts.map +1 -0
  13. package/dist/contracts/runtime.js +4 -0
  14. package/dist/contracts/runtime.js.map +1 -0
  15. package/dist/contracts/session.d.ts +188 -0
  16. package/dist/contracts/session.d.ts.map +1 -0
  17. package/dist/contracts/session.js +2 -0
  18. package/dist/contracts/session.js.map +1 -0
  19. package/dist/index.d.ts +28 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +23 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/installation.d.ts +15 -0
  24. package/dist/installation.d.ts.map +1 -0
  25. package/dist/installation.js +60 -0
  26. package/dist/installation.js.map +1 -0
  27. package/dist/observe/agent-status.d.ts +39 -0
  28. package/dist/observe/agent-status.d.ts.map +1 -0
  29. package/dist/observe/agent-status.js +31 -0
  30. package/dist/observe/agent-status.js.map +1 -0
  31. package/dist/observe/aggregate-events.d.ts +15 -0
  32. package/dist/observe/aggregate-events.d.ts.map +1 -0
  33. package/dist/observe/aggregate-events.js +70 -0
  34. package/dist/observe/aggregate-events.js.map +1 -0
  35. package/dist/observe/index.d.ts +17 -0
  36. package/dist/observe/index.d.ts.map +1 -0
  37. package/dist/observe/index.js +13 -0
  38. package/dist/observe/index.js.map +1 -0
  39. package/dist/observe/observe-agent.d.ts +38 -0
  40. package/dist/observe/observe-agent.d.ts.map +1 -0
  41. package/dist/observe/observe-agent.js +61 -0
  42. package/dist/observe/observe-agent.js.map +1 -0
  43. package/dist/observe/stall-observer.d.ts +19 -0
  44. package/dist/observe/stall-observer.d.ts.map +1 -0
  45. package/dist/observe/stall-observer.js +36 -0
  46. package/dist/observe/stall-observer.js.map +1 -0
  47. package/dist/observe/tool-activity.d.ts +21 -0
  48. package/dist/observe/tool-activity.d.ts.map +1 -0
  49. package/dist/observe/tool-activity.js +87 -0
  50. package/dist/observe/tool-activity.js.map +1 -0
  51. package/dist/registry.d.ts +10 -0
  52. package/dist/registry.d.ts.map +1 -0
  53. package/dist/registry.js +30 -0
  54. package/dist/registry.js.map +1 -0
  55. package/dist/runtimes/claude/account-usage.d.ts +29 -0
  56. package/dist/runtimes/claude/account-usage.d.ts.map +1 -0
  57. package/dist/runtimes/claude/account-usage.js +179 -0
  58. package/dist/runtimes/claude/account-usage.js.map +1 -0
  59. package/dist/runtimes/claude/context-usage.d.ts +10 -0
  60. package/dist/runtimes/claude/context-usage.d.ts.map +1 -0
  61. package/dist/runtimes/claude/context-usage.js +23 -0
  62. package/dist/runtimes/claude/context-usage.js.map +1 -0
  63. package/dist/runtimes/claude/index.d.ts +9 -0
  64. package/dist/runtimes/claude/index.d.ts.map +1 -0
  65. package/dist/runtimes/claude/index.js +13 -0
  66. package/dist/runtimes/claude/index.js.map +1 -0
  67. package/dist/runtimes/claude/installation.d.ts +2 -0
  68. package/dist/runtimes/claude/installation.d.ts.map +1 -0
  69. package/dist/runtimes/claude/installation.js +3 -0
  70. package/dist/runtimes/claude/installation.js.map +1 -0
  71. package/dist/runtimes/claude/projection.d.ts +46 -0
  72. package/dist/runtimes/claude/projection.d.ts.map +1 -0
  73. package/dist/runtimes/claude/projection.js +110 -0
  74. package/dist/runtimes/claude/projection.js.map +1 -0
  75. package/dist/runtimes/claude/session.d.ts +3 -0
  76. package/dist/runtimes/claude/session.d.ts.map +1 -0
  77. package/dist/runtimes/claude/session.js +166 -0
  78. package/dist/runtimes/claude/session.js.map +1 -0
  79. package/dist/runtimes/codex/account-usage.d.ts +40 -0
  80. package/dist/runtimes/codex/account-usage.d.ts.map +1 -0
  81. package/dist/runtimes/codex/account-usage.js +185 -0
  82. package/dist/runtimes/codex/account-usage.js.map +1 -0
  83. package/dist/runtimes/codex/app-server-client.d.ts +17 -0
  84. package/dist/runtimes/codex/app-server-client.d.ts.map +1 -0
  85. package/dist/runtimes/codex/app-server-client.js +68 -0
  86. package/dist/runtimes/codex/app-server-client.js.map +1 -0
  87. package/dist/runtimes/codex/context-usage.d.ts +10 -0
  88. package/dist/runtimes/codex/context-usage.d.ts.map +1 -0
  89. package/dist/runtimes/codex/context-usage.js +16 -0
  90. package/dist/runtimes/codex/context-usage.js.map +1 -0
  91. package/dist/runtimes/codex/index.d.ts +9 -0
  92. package/dist/runtimes/codex/index.d.ts.map +1 -0
  93. package/dist/runtimes/codex/index.js +13 -0
  94. package/dist/runtimes/codex/index.js.map +1 -0
  95. package/dist/runtimes/codex/installation.d.ts +2 -0
  96. package/dist/runtimes/codex/installation.d.ts.map +1 -0
  97. package/dist/runtimes/codex/installation.js +17 -0
  98. package/dist/runtimes/codex/installation.js.map +1 -0
  99. package/dist/runtimes/codex/item-detail.d.ts +4 -0
  100. package/dist/runtimes/codex/item-detail.d.ts.map +1 -0
  101. package/dist/runtimes/codex/item-detail.js +47 -0
  102. package/dist/runtimes/codex/item-detail.js.map +1 -0
  103. package/dist/runtimes/codex/projection.d.ts +28 -0
  104. package/dist/runtimes/codex/projection.d.ts.map +1 -0
  105. package/dist/runtimes/codex/projection.js +98 -0
  106. package/dist/runtimes/codex/projection.js.map +1 -0
  107. package/dist/runtimes/codex/reasoning.d.ts +4 -0
  108. package/dist/runtimes/codex/reasoning.d.ts.map +1 -0
  109. package/dist/runtimes/codex/reasoning.js +23 -0
  110. package/dist/runtimes/codex/reasoning.js.map +1 -0
  111. package/dist/runtimes/codex/session.d.ts +3 -0
  112. package/dist/runtimes/codex/session.d.ts.map +1 -0
  113. package/dist/runtimes/codex/session.js +199 -0
  114. package/dist/runtimes/codex/session.js.map +1 -0
  115. package/dist/runtimes/pi/index.d.ts +12 -0
  116. package/dist/runtimes/pi/index.d.ts.map +1 -0
  117. package/dist/runtimes/pi/index.js +15 -0
  118. package/dist/runtimes/pi/index.js.map +1 -0
  119. package/dist/runtimes/pi/installation.d.ts +10 -0
  120. package/dist/runtimes/pi/installation.d.ts.map +1 -0
  121. package/dist/runtimes/pi/installation.js +33 -0
  122. package/dist/runtimes/pi/installation.js.map +1 -0
  123. package/dist/runtimes/pi/projection.d.ts +39 -0
  124. package/dist/runtimes/pi/projection.d.ts.map +1 -0
  125. package/dist/runtimes/pi/projection.js +112 -0
  126. package/dist/runtimes/pi/projection.js.map +1 -0
  127. package/dist/runtimes/pi/session.d.ts +11 -0
  128. package/dist/runtimes/pi/session.d.ts.map +1 -0
  129. package/dist/runtimes/pi/session.js +201 -0
  130. package/dist/runtimes/pi/session.js.map +1 -0
  131. package/dist/runtimes/pi/tool-detail.d.ts +4 -0
  132. package/dist/runtimes/pi/tool-detail.d.ts.map +1 -0
  133. package/dist/runtimes/pi/tool-detail.js +14 -0
  134. package/dist/runtimes/pi/tool-detail.js.map +1 -0
  135. package/dist/shared/diagnostic-text.d.ts +2 -0
  136. package/dist/shared/diagnostic-text.d.ts.map +1 -0
  137. package/dist/shared/diagnostic-text.js +15 -0
  138. package/dist/shared/diagnostic-text.js.map +1 -0
  139. package/dist/shared/executable/index.d.ts +8 -0
  140. package/dist/shared/executable/index.d.ts.map +1 -0
  141. package/dist/shared/executable/index.js +5 -0
  142. package/dist/shared/executable/index.js.map +1 -0
  143. package/dist/shared/executable/process.d.ts +27 -0
  144. package/dist/shared/executable/process.d.ts.map +1 -0
  145. package/dist/shared/executable/process.js +77 -0
  146. package/dist/shared/executable/process.js.map +1 -0
  147. package/dist/shared/executable/resolve.d.ts +16 -0
  148. package/dist/shared/executable/resolve.d.ts.map +1 -0
  149. package/dist/shared/executable/resolve.js +63 -0
  150. package/dist/shared/executable/resolve.js.map +1 -0
  151. package/dist/shared/executable/run.d.ts +13 -0
  152. package/dist/shared/executable/run.d.ts.map +1 -0
  153. package/dist/shared/executable/run.js +26 -0
  154. package/dist/shared/executable/run.js.map +1 -0
  155. package/dist/shared/executable/version.d.ts +6 -0
  156. package/dist/shared/executable/version.d.ts.map +1 -0
  157. package/dist/shared/executable/version.js +17 -0
  158. package/dist/shared/executable/version.js.map +1 -0
  159. package/dist/shared/failure-class.d.ts +8 -0
  160. package/dist/shared/failure-class.d.ts.map +1 -0
  161. package/dist/shared/failure-class.js +24 -0
  162. package/dist/shared/failure-class.js.map +1 -0
  163. package/dist/shared/installation.d.ts +9 -0
  164. package/dist/shared/installation.d.ts.map +1 -0
  165. package/dist/shared/installation.js +53 -0
  166. package/dist/shared/installation.js.map +1 -0
  167. package/dist/shared/instant.d.ts +4 -0
  168. package/dist/shared/instant.d.ts.map +1 -0
  169. package/dist/shared/instant.js +4 -0
  170. package/dist/shared/instant.js.map +1 -0
  171. package/dist/shared/json.d.ts +10 -0
  172. package/dist/shared/json.d.ts.map +1 -0
  173. package/dist/shared/json.js +29 -0
  174. package/dist/shared/json.js.map +1 -0
  175. package/dist/shared/seal-session.d.ts +8 -0
  176. package/dist/shared/seal-session.d.ts.map +1 -0
  177. package/dist/shared/seal-session.js +24 -0
  178. package/dist/shared/seal-session.js.map +1 -0
  179. package/dist/shared/session-kernel.d.ts +25 -0
  180. package/dist/shared/session-kernel.d.ts.map +1 -0
  181. package/dist/shared/session-kernel.js +64 -0
  182. package/dist/shared/session-kernel.js.map +1 -0
  183. package/package.json +47 -0
@@ -0,0 +1,112 @@
1
+ import { classifyFailure } from "../../shared/failure-class.js";
2
+ export const initialPiProjection = {
3
+ inTurn: false,
4
+ adopted: false,
5
+ abortRequested: false,
6
+ reasoningHadText: false,
7
+ providerError: undefined,
8
+ };
9
+ /** Control plane → state: a prompt opens a non-adopted turn, resetting per-turn accumulators. */
10
+ export function piPrompted() {
11
+ return { ...initialPiProjection, inTurn: true };
12
+ }
13
+ export function piAbortRequested(state) {
14
+ return { ...state, abortRequested: true };
15
+ }
16
+ /** The outcome for a prompt-initiated turn (the fold settles adopted turns itself). */
17
+ export function piSettledOutcome(state) {
18
+ if (state.abortRequested) {
19
+ return { kind: "aborted" };
20
+ }
21
+ if (state.providerError !== undefined) {
22
+ return { kind: "failed", reason: state.providerError, failure: classifyFailure(state.providerError) };
23
+ }
24
+ return { kind: "completed" };
25
+ }
26
+ const drop = (state) => ({ state, commands: [] });
27
+ const emit = (state, body) => ({ state, commands: [{ kind: "emit", body }] });
28
+ function foldMessageUpdate(state, inner) {
29
+ switch (inner.type) {
30
+ case "text_delta":
31
+ return emit(state, { kind: "text_delta", text: inner.delta });
32
+ case "thinking_delta":
33
+ return inner.delta.length > 0
34
+ ? emit({ ...state, reasoningHadText: true }, { kind: "reasoning", content: { kind: "text", text: inner.delta } })
35
+ : drop(state);
36
+ case "error":
37
+ // pi's prompt() RESOLVES even when the provider errored — the failure
38
+ // only surfaces here (pinned by the pi vendor 400 test).
39
+ return drop({ ...state, providerError: inner.error.errorMessage ?? inner.reason });
40
+ case "thinking_start":
41
+ return drop({ ...state, reasoningHadText: false });
42
+ case "thinking_end":
43
+ return state.reasoningHadText ? drop(state) : emit(state, { kind: "reasoning", content: { kind: "empty" } });
44
+ // Explicitly dropped: block boundaries and toolcall framing carry no v1
45
+ // turn event (toolcalls arrive via the outer tool_execution_* events).
46
+ case "start":
47
+ case "done":
48
+ case "text_start":
49
+ case "text_end":
50
+ case "toolcall_start":
51
+ case "toolcall_delta":
52
+ case "toolcall_end":
53
+ return drop(state);
54
+ }
55
+ return drop(state);
56
+ }
57
+ /** Fold one pi SDK event into the next state plus commands. */
58
+ export function foldPiEvent(state, event) {
59
+ if (event.type === "agent_start") {
60
+ // A run pi starts that we did not prompt (a drained followUp) becomes an
61
+ // adopted turn, settled here on agent_end.
62
+ return state.inTurn
63
+ ? drop(state)
64
+ : { state: { ...piPrompted(), adopted: true }, commands: [{ kind: "begin" }] };
65
+ }
66
+ if (!state.inTurn) {
67
+ return drop(state);
68
+ }
69
+ switch (event.type) {
70
+ case "agent_end":
71
+ // Adopted turns settle here; prompt-initiated turns are settled by the
72
+ // adapter's prompt promise (which reads piSettledOutcome).
73
+ return state.adopted
74
+ ? { state: initialPiProjection, commands: [{ kind: "settle", outcome: piSettledOutcome(state) }] }
75
+ : { state: { ...state, inTurn: false }, commands: [] };
76
+ case "message_update":
77
+ return foldMessageUpdate(state, event.assistantMessageEvent);
78
+ case "tool_execution_start":
79
+ return emit(state, { kind: "tool_call_started", callId: event.toolCallId, tool: event.toolName });
80
+ case "tool_execution_end":
81
+ return emit(state, { kind: "tool_call_ended", callId: event.toolCallId });
82
+ case "turn_end":
83
+ // A provider failure surfaces only as stopReason "error" on the turn's
84
+ // final assistant message (pinned by the pi vendor 400 test).
85
+ return event.message.role === "assistant" && event.message.stopReason === "error"
86
+ ? drop({ ...state, providerError: event.message.errorMessage ?? "provider error" })
87
+ : drop(state);
88
+ // Explicitly dropped: session-scoped events with no turn mapping in v1 (an
89
+ // exhaustive switch makes a NEW pi event type a compile error, forcing a
90
+ // conscious mapped-or-dropped decision on each future addition).
91
+ case "agent_settled":
92
+ case "turn_start":
93
+ case "message_start":
94
+ case "message_end":
95
+ case "tool_execution_update":
96
+ case "bash_execution_update":
97
+ case "compaction_start":
98
+ case "compaction_end":
99
+ case "queue_update":
100
+ case "entry_appended":
101
+ case "session_info_changed":
102
+ case "thinking_level_changed":
103
+ case "auto_retry_start":
104
+ case "auto_retry_end":
105
+ case "summarization_retry_scheduled":
106
+ case "summarization_retry_attempt_start":
107
+ case "summarization_retry_finished":
108
+ return drop(state);
109
+ }
110
+ return drop(state);
111
+ }
112
+ //# sourceMappingURL=projection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projection.js","sourceRoot":"","sources":["../../../src/runtimes/pi/projection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { CreateAgentSessionOptions } from "@earendil-works/pi-coding-agent";
2
+ import type { StartSession } from "../../contracts/session.js";
3
+ /**
4
+ * The bash tool that carries SessionOptions.env into the agent's spawned
5
+ * processes: same builtin bash, plus a spawnHook overlaying the env. pi's
6
+ * defineTool keeps the definition assignable to customTools, where it
7
+ * replaces the builtin by name. Exported for direct unit verification.
8
+ */
9
+ export declare function piEnvBashTool(cwd: string, overlay: Readonly<Record<string, string>>): Promise<NonNullable<CreateAgentSessionOptions["customTools"]>[number]>;
10
+ export declare const piSession: StartSession;
11
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../../src/runtimes/pi/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC;AACjF,OAAO,KAAK,EAAW,YAAY,EAAQ,MAAM,4BAA4B,CAAC;AAqB9E;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACxC,OAAO,CAAC,WAAW,CAAC,yBAAyB,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAKxE;AAED,eAAO,MAAM,SAAS,EAAE,YAkLvB,CAAC"}
@@ -0,0 +1,201 @@
1
+ import { classifyFailure } from "../../shared/failure-class.js";
2
+ import { sealSession } from "../../shared/seal-session.js";
3
+ import { createSessionKernel } from "../../shared/session-kernel.js";
4
+ import { foldPiEvent, initialPiProjection, piAbortRequested, piPrompted, piSettledOutcome, } from "./projection.js";
5
+ /*
6
+ * Bundled pi SDK mapping (in-process, no fork — settled 2026-08-21):
7
+ * prompt resolves on settlement; steer acceptance means entry into pi's
8
+ * queue; abort is cooperative. Turn deltas/tools map, session events drop.
9
+ * Model selection needs ModelRuntime rather than options.model. Process-global
10
+ * lazy env reads mean another embedded pi cannot safely share this process.
11
+ */
12
+ /**
13
+ * The bash tool that carries SessionOptions.env into the agent's spawned
14
+ * processes: same builtin bash, plus a spawnHook overlaying the env. pi's
15
+ * defineTool keeps the definition assignable to customTools, where it
16
+ * replaces the builtin by name. Exported for direct unit verification.
17
+ */
18
+ export async function piEnvBashTool(cwd, overlay) {
19
+ const sdk = await import("@earendil-works/pi-coding-agent");
20
+ return sdk.defineTool(sdk.createBashToolDefinition(cwd, {
21
+ spawnHook: (context) => ({ ...context, env: { ...context.env, ...overlay } }),
22
+ }));
23
+ }
24
+ export const piSession = async (installation, options) => {
25
+ if (installation.via !== "bundled") {
26
+ throw new Error("The pi session adapter needs the bundled sdk installation");
27
+ }
28
+ if (options.resume !== undefined) {
29
+ // pi resumes by session FILE (SessionManager.open(path)), not by bare id;
30
+ // wiring the id→file lookup waits for a consumer with configured pi.
31
+ throw new Error("pi session resume is not implemented yet");
32
+ }
33
+ const sdk = await import("@earendil-works/pi-coding-agent");
34
+ // Per-session env on an in-process runtime: the runtime itself has no own
35
+ // process, but the processes the AGENT spawns do — a bash tool built with a
36
+ // spawnHook overlaying the env replaces the builtin by name (custom tools
37
+ // win the SDK's tool registry). Provider config (keys, base URLs) does NOT
38
+ // travel this way for pi; that needs its native modelRuntime/agentDir
39
+ // channel. Tool-level spawn verified in SDK source, not yet live (no
40
+ // configured pi on this machine).
41
+ const overlay = options.env;
42
+ // OAR_PI_AGENT_DIR pins pi's global config home (models.json/auth.json/
43
+ // settings) — same namespaced-env-pin pattern as OAR_CLAUDE_BIN. This is
44
+ // how a host (or the pi-aimock behavior backend) points the in-process
45
+ // model plane somewhere else.
46
+ const agentDir = process.env.OAR_PI_AGENT_DIR;
47
+ // YOLO by default (repo policy): pi gates tool execution on project trust,
48
+ // which is an approval prompt no embedded host can answer — pre-trust the
49
+ // session cwd the same way pi's own Trust button would (auditable in
50
+ // <agentDir>/trust.json).
51
+ new sdk.ProjectTrustStore(agentDir ?? sdk.getAgentDir()).set(options.cwd, true);
52
+ // System prompt seams: pi's DefaultResourceLoader natively supports both
53
+ // replace (systemPrompt) and append (appendSystemPrompt).
54
+ const wantsSystemPrompt = options.systemPrompt !== undefined || options.appendSystemPrompt !== undefined;
55
+ const resourceLoader = wantsSystemPrompt
56
+ ? new sdk.DefaultResourceLoader({
57
+ cwd: options.cwd,
58
+ agentDir: agentDir ?? sdk.getAgentDir(),
59
+ ...(options.systemPrompt === undefined ? {} : { systemPrompt: options.systemPrompt }),
60
+ ...(options.appendSystemPrompt === undefined ? {} : { appendSystemPrompt: [options.appendSystemPrompt] }),
61
+ })
62
+ : undefined;
63
+ // A CALLER-provided loader is the caller's to load — createAgentSession
64
+ // only reloads the one it builds itself.
65
+ await resourceLoader?.reload();
66
+ const { session: piAgentSession } = await sdk.createAgentSession({
67
+ cwd: options.cwd,
68
+ ...(agentDir === undefined ? {} : { agentDir }),
69
+ ...(resourceLoader === undefined ? {} : { resourceLoader }),
70
+ ...(overlay === undefined ? {} : { customTools: [await piEnvBashTool(options.cwd, overlay)] }),
71
+ });
72
+ const kernel = createSessionKernel(piAgentSession.sessionId);
73
+ let currentTurn = null;
74
+ let projection = initialPiProjection;
75
+ let disposed = false;
76
+ // Adapter-held queue, drained one input per turn end. pi's native followUp
77
+ // CONTINUES the active run (more internal turns, one agent_end), which
78
+ // would land the queued input inside the same OAR turn — the queue contract
79
+ // promises a later turn of its own, so the adapter owns the handoff.
80
+ const held = [];
81
+ const drainHeld = () => {
82
+ if (disposed || kernel.active() !== null) {
83
+ return;
84
+ }
85
+ const next = held.shift();
86
+ if (next === undefined) {
87
+ return;
88
+ }
89
+ // The run this starts is adopted as a spontaneous turn by agent_start.
90
+ void (async () => {
91
+ try {
92
+ await piAgentSession.prompt(next);
93
+ }
94
+ catch (error) {
95
+ // Never drop a taken-over delivery silently: surface the loss as a
96
+ // failed turn if one can still be attributed.
97
+ const reason = error instanceof Error ? error.message : "queued prompt failed";
98
+ kernel.begin()?.settle({ kind: "failed", reason, failure: classifyFailure(reason) });
99
+ }
100
+ })();
101
+ };
102
+ // Drive the pure projection fold, applying its commands to the kernel; the
103
+ // fold owns turn framing and event translation. Adopted turns settle in the
104
+ // fold (agent_end); prompt-initiated turns settle in prompt() below.
105
+ piAgentSession.subscribe((event) => {
106
+ const { state: nextProjection, commands } = foldPiEvent(projection, event);
107
+ projection = nextProjection;
108
+ for (const command of commands) {
109
+ switch (command.kind) {
110
+ case "begin":
111
+ currentTurn = kernel.begin();
112
+ break;
113
+ case "emit":
114
+ currentTurn?.emit(command.body);
115
+ break;
116
+ case "settle":
117
+ currentTurn?.settle(command.outcome);
118
+ currentTurn = null;
119
+ drainHeld();
120
+ break;
121
+ default:
122
+ break;
123
+ }
124
+ }
125
+ });
126
+ const makeTurn = (turn) => ({
127
+ id: turn.id,
128
+ outcome: turn.outcome,
129
+ abort: async () => {
130
+ if (turn.settled()) {
131
+ return;
132
+ }
133
+ projection = piAbortRequested(projection);
134
+ await piAgentSession.abort();
135
+ await turn.outcome;
136
+ },
137
+ steer: async (input) => {
138
+ if (turn.settled()) {
139
+ return { kind: "not_steerable", reason: "turn already ended" };
140
+ }
141
+ await piAgentSession.steer(input);
142
+ return { kind: "accepted" };
143
+ },
144
+ });
145
+ const session = sealSession({
146
+ id: kernel.sessionId,
147
+ prompt(input) {
148
+ const turn = kernel.begin();
149
+ if (turn === null) {
150
+ return { kind: "busy" };
151
+ }
152
+ currentTurn = turn;
153
+ projection = piPrompted();
154
+ void (async () => {
155
+ try {
156
+ await piAgentSession.prompt(input);
157
+ turn.settle(piSettledOutcome(projection));
158
+ }
159
+ catch (error) {
160
+ const reason = error instanceof Error ? error.message : "pi prompt failed";
161
+ turn.settle({ kind: "failed", reason, failure: classifyFailure(reason) });
162
+ }
163
+ projection = initialPiProjection;
164
+ currentTurn = null;
165
+ drainHeld();
166
+ })();
167
+ return { kind: "turn", turn: makeTurn(turn) };
168
+ },
169
+ subscribe: (observer) => kernel.subscribe(observer),
170
+ contextUsage: () => {
171
+ // pi is authoritative: getContextUsage() returns tokens (null right
172
+ // after compaction, before the next response), contextWindow, percent.
173
+ const usage = piAgentSession.getContextUsage();
174
+ return usage === undefined
175
+ ? null
176
+ : { tokens: usage.tokens, contextWindow: usage.contextWindow, percent: usage.percent };
177
+ },
178
+ queue: {
179
+ durable: false,
180
+ add: async (input) => {
181
+ await Promise.resolve();
182
+ held.push(input);
183
+ drainHeld();
184
+ },
185
+ },
186
+ dispose: async () => {
187
+ if (disposed) {
188
+ return;
189
+ }
190
+ disposed = true;
191
+ const active = kernel.active();
192
+ if (active !== null) {
193
+ await piAgentSession.abort();
194
+ active.settle({ kind: "aborted" });
195
+ }
196
+ piAgentSession.dispose();
197
+ },
198
+ });
199
+ return session;
200
+ };
201
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/runtimes/pi/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SessionEventBody } from "../../contracts/session.js";
2
+ export declare function piToolStarted(callId: string, tool: string, args: unknown): SessionEventBody;
3
+ export declare function piToolEnded(callId: string, result: unknown): SessionEventBody;
4
+ //# sourceMappingURL=tool-detail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-detail.d.ts","sourceRoot":"","sources":["../../../src/runtimes/pi/tool-detail.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAGnE,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,GACZ,gBAAgB,CAKlB;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAK7E"}
@@ -0,0 +1,14 @@
1
+ import { diagnosticText } from "../../shared/diagnostic-text.js";
2
+ export function piToolStarted(callId, tool, args) {
3
+ const input = diagnosticText(args);
4
+ return input === undefined
5
+ ? { kind: "tool_call_started", callId, tool }
6
+ : { kind: "tool_call_started", callId, tool, input };
7
+ }
8
+ export function piToolEnded(callId, result) {
9
+ const output = diagnosticText(result);
10
+ return output === undefined
11
+ ? { kind: "tool_call_ended", callId }
12
+ : { kind: "tool_call_ended", callId, output };
13
+ }
14
+ //# sourceMappingURL=tool-detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-detail.js","sourceRoot":"","sources":["../../../src/runtimes/pi/tool-detail.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,IAAY,EACZ,IAAa;IAEb,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,KAAK,KAAK,SAAS;QACxB,CAAC,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE;QAC7C,CAAC,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,MAAe;IACzD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACtC,OAAO,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE;QACrC,CAAC,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAClD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function diagnosticText(value: unknown): string | undefined;
2
+ //# sourceMappingURL=diagnostic-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-text.d.ts","sourceRoot":"","sources":["../../src/shared/diagnostic-text.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAYjE"}
@@ -0,0 +1,15 @@
1
+ export function diagnosticText(value) {
2
+ if (value === undefined || value === null) {
3
+ return undefined;
4
+ }
5
+ if (typeof value === "string") {
6
+ return value;
7
+ }
8
+ try {
9
+ return JSON.stringify(value);
10
+ }
11
+ catch {
12
+ return "[unserializable diagnostic value]";
13
+ }
14
+ }
15
+ //# sourceMappingURL=diagnostic-text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-text.js","sourceRoot":"","sources":["../../src/shared/diagnostic-text.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,mCAAmC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type { ExecFileSyncLike, ExecutableResolveOptions } from "./resolve.js";
2
+ export { resolveExecutable } from "./resolve.js";
3
+ export type { ExecutableResult, ExecutableRunner, ExecutableRunOptions } from "./run.js";
4
+ export { runExecutable } from "./run.js";
5
+ export { readExecutableVersion } from "./version.js";
6
+ export type { LineProcess } from "./process.js";
7
+ export { requiresShell, spawnLineProcess } from "./process.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shared/executable/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { resolveExecutable } from "./resolve.js";
2
+ export { runExecutable } from "./run.js";
3
+ export { readExecutableVersion } from "./version.js";
4
+ export { requiresShell, spawnLineProcess } from "./process.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shared/executable/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A long-lived child process spoken to line-by-line — the transport shape both
3
+ * session adapters use (JSONL protocols over stdio). Owns the details raw
4
+ * spawn callers keep re-implementing: stdio wiring, line buffering with a
5
+ * trailing partial buffer, exit fan-out, teardown, and the Windows quirk that
6
+ * npm-installed CLIs are .cmd shims which modern Node refuses to spawn without
7
+ * a shell (EINVAL). Windows handling follows Node's documented `shell` option
8
+ * and is honest about being untested here (no Windows machine in the loop).
9
+ */
10
+ export interface LineProcess {
11
+ /** Resolves once the OS process exists; rejects when it cannot be spawned. */
12
+ readonly spawned: Promise<void>;
13
+ /** Resolves when the process is truly gone — the release point for any state it held (locks, sockets). */
14
+ readonly exited: Promise<number | null>;
15
+ write(text: string): void;
16
+ onLine(handler: (line: string) => void): void;
17
+ /** Fires exactly once, for exit or spawn-level error alike. */
18
+ onExit(handler: (code: number | null) => void): void;
19
+ kill(): void;
20
+ }
21
+ /** Windows npm shims are .cmd/.bat files, which modern Node refuses to spawn without a shell (EINVAL). Line processes go through cross-spawn instead (correct cmd arg quoting); this predicate remains for one-shot execFile calls, whose args must stay SINGLE-WORD on Windows because shell:true does not quote. */
22
+ export declare function requiresShell(command: string, platform: NodeJS.Platform): boolean;
23
+ export declare function spawnLineProcess(command: string, args: readonly string[], options?: {
24
+ readonly cwd?: string;
25
+ readonly env?: NodeJS.ProcessEnv;
26
+ }): LineProcess;
27
+ //# sourceMappingURL=process.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.d.ts","sourceRoot":"","sources":["../../../src/shared/executable/process.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,0GAA0G;IAC1G,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC9C,+DAA+D;IAC/D,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC;IACrD,IAAI,IAAI,IAAI,CAAC;CACd;AAED,sTAAsT;AACtT,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,OAAO,CAEjF;AAED,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE;IAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CAAO,GACxE,WAAW,CAwEb"}
@@ -0,0 +1,77 @@
1
+ import spawn from "cross-spawn";
2
+ /** Windows npm shims are .cmd/.bat files, which modern Node refuses to spawn without a shell (EINVAL). Line processes go through cross-spawn instead (correct cmd arg quoting); this predicate remains for one-shot execFile calls, whose args must stay SINGLE-WORD on Windows because shell:true does not quote. */
3
+ export function requiresShell(command, platform) {
4
+ return platform === "win32" && /\.(?:cmd|bat)$/iu.test(command);
5
+ }
6
+ export function spawnLineProcess(command, args, options = {}) {
7
+ // cross-spawn, not node's spawn: Windows .cmd shims need a shell, and
8
+ // node's shell:true joins args UNQUOTED — a multi-word argument (e.g. a
9
+ // --system-prompt value) silently truncates at its first space (caught by
10
+ // the system-prompt snapshots on Windows CI). cross-spawn does the cmd
11
+ // escaping correctly and is a no-op wrapper elsewhere.
12
+ const child = spawn(command, [...args], {
13
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
14
+ env: options.env ?? process.env,
15
+ // OAR_CHILD_STDERR=inherit surfaces child stderr on the parent's — the
16
+ // debugging knob for "the process died and nobody knows why".
17
+ stdio: ["pipe", "pipe", process.env.OAR_CHILD_STDERR === "inherit" ? "inherit" : "ignore"],
18
+ });
19
+ const { stdin, stdout } = child;
20
+ if (stdin === null || stdout === null) {
21
+ throw new Error("line process stdio must be piped");
22
+ }
23
+ const lineHandlers = [];
24
+ const exitHandlers = [];
25
+ let buffer = "";
26
+ let ended = false;
27
+ const { promise: spawned, resolve: spawnOk, reject: spawnFailed } = Promise.withResolvers();
28
+ const { promise: exited, resolve: exitDone } = Promise.withResolvers();
29
+ child.once("spawn", spawnOk);
30
+ const end = (code) => {
31
+ if (!ended) {
32
+ ended = true;
33
+ for (const handler of exitHandlers) {
34
+ handler(code);
35
+ }
36
+ exitDone(code);
37
+ }
38
+ };
39
+ stdout.on("data", (chunk) => {
40
+ buffer += chunk.toString();
41
+ const lines = buffer.split("\n");
42
+ buffer = lines.pop() ?? "";
43
+ for (const raw of lines) {
44
+ const line = raw.trim();
45
+ if (line.length > 0) {
46
+ for (const handler of lineHandlers) {
47
+ handler(line);
48
+ }
49
+ }
50
+ }
51
+ });
52
+ child.on("exit", (code) => {
53
+ end(code);
54
+ });
55
+ child.on("error", (error) => {
56
+ spawnFailed(error);
57
+ end(null);
58
+ });
59
+ return {
60
+ spawned,
61
+ exited,
62
+ write(text) {
63
+ stdin.write(text);
64
+ },
65
+ onLine(handler) {
66
+ lineHandlers.push(handler);
67
+ },
68
+ onExit(handler) {
69
+ exitHandlers.push(handler);
70
+ },
71
+ kill() {
72
+ stdin.end();
73
+ child.kill("SIGTERM");
74
+ },
75
+ };
76
+ }
77
+ //# sourceMappingURL=process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process.js","sourceRoot":"","sources":["../../../src/shared/executable/process.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,aAAa,CAAC;AAuBhC,sTAAsT;AACtT,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,QAAyB;IACtE,OAAO,QAAQ,KAAK,OAAO,IAAI,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,OAAe,EACf,IAAuB,EACvB,UAAuE,EAAE;IAEzE,sEAAsE;IACtE,wEAAwE;IACxE,0EAA0E;IAC1E,uEAAuE;IACvE,uDAAuD;IACvD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;QACtC,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1D,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG;QAC/B,uEAAuE;QACvE,8DAA8D;QAC9D,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC;KAC3F,CAAC,CAAC;IACH,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAChC,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,YAAY,GAA+B,EAAE,CAAC;IACpD,MAAM,YAAY,GAAsC,EAAE,CAAC;IAC3D,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAClG,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,aAAa,EAAiB,CAAC;IACtF,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,CAAC,IAAmB,EAAQ,EAAE;QACxC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,CAAC;YACb,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,CAAC;YAChB,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;QAC3C,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpB,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE,CAAC;oBACnC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACxB,GAAG,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1B,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,GAAG,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO;QACP,MAAM;QACN,KAAK,CAAC,IAAI;YACR,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,MAAM,CAAC,OAAO;YACZ,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,CAAC,OAAO;YACZ,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,CAAC;QACD,IAAI;YACF,KAAK,CAAC,GAAG,EAAE,CAAC;YACZ,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /** The one execFileSync shape resolution needs — a typed seam for tests. */
2
+ export type ExecFileSyncLike = (command: string, args: readonly string[], options: {
3
+ readonly env: NodeJS.ProcessEnv;
4
+ readonly encoding: "utf8";
5
+ readonly stdio: readonly ["ignore", "pipe", "ignore"];
6
+ readonly timeout?: number;
7
+ }) => string | Buffer;
8
+ export interface ExecutableResolveOptions {
9
+ readonly platform?: NodeJS.Platform;
10
+ readonly env?: NodeJS.ProcessEnv;
11
+ readonly execFileSyncFn?: ExecFileSyncLike;
12
+ readonly existsSyncFn?: (filePath: string) => boolean;
13
+ }
14
+ /** Resolve one executable without invoking a shell. */
15
+ export declare function resolveExecutable(executable: string, options?: ExecutableResolveOptions): string | null;
16
+ //# sourceMappingURL=resolve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/shared/executable/resolve.ts"],"names":[],"mappings":"AAIA,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE;IACP,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B,KACE,MAAM,GAAG,MAAM,CAAC;AAErB,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC;IAC3C,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;CACvD;AAkDD,uDAAuD;AACvD,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,wBAA6B,GACrC,MAAM,GAAG,IAAI,CAiBf"}
@@ -0,0 +1,63 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import path from "node:path";
4
+ function firstLine(value) {
5
+ const line = (typeof value === "string" ? value : value.toString()).trim().split(/\r?\n/u)[0];
6
+ return line === undefined || line.length === 0 ? null : line;
7
+ }
8
+ function resolveWindows(executable, env, execFile, exists) {
9
+ // The name travels via env, NOT as a trailing argument: powershell -Command
10
+ // appends trailing arguments to the command string instead of binding $args,
11
+ // which silently resolved nothing (caught by CI once Windows ran for real).
12
+ const script = [
13
+ "$cmd = Get-Command -Name $env:OAR_RESOLVE_TARGET -ErrorAction Stop | Select-Object -First 1",
14
+ "if ($cmd.Path) { $cmd.Path } elseif ($cmd.Source) { $cmd.Source }",
15
+ ].join("; ");
16
+ try {
17
+ const resolved = firstLine(execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script],
18
+ // Cold powershell startup on CI runners routinely exceeds 1s; keep this
19
+ // generous — resolution is rare and cached by callers, not hot-path.
20
+ {
21
+ env: { ...env, OAR_RESOLVE_TARGET: executable },
22
+ encoding: "utf8",
23
+ stdio: ["ignore", "pipe", "ignore"],
24
+ timeout: 15_000,
25
+ }));
26
+ if (resolved === null || !resolved.toLowerCase().endsWith(".ps1")) {
27
+ return resolved;
28
+ }
29
+ const directory = path.dirname(resolved);
30
+ const base = path.basename(resolved, ".ps1");
31
+ for (const extension of [".cmd", ".bat", ".exe", ""]) {
32
+ const candidate = path.join(directory, `${base}${extension}`);
33
+ if (exists(candidate)) {
34
+ return candidate;
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ }
43
+ /** Resolve one executable without invoking a shell. */
44
+ export function resolveExecutable(executable, options = {}) {
45
+ const platform = options.platform ?? process.platform;
46
+ const env = options.env ?? process.env;
47
+ const execFile = options.execFileSyncFn ?? execFileSync;
48
+ const exists = options.existsSyncFn ?? existsSync;
49
+ if (platform === "win32") {
50
+ return resolveWindows(executable, env, execFile, exists);
51
+ }
52
+ try {
53
+ return firstLine(execFile("which", [executable], {
54
+ env,
55
+ encoding: "utf8",
56
+ stdio: ["ignore", "pipe", "ignore"],
57
+ }));
58
+ }
59
+ catch {
60
+ return null;
61
+ }
62
+ }
63
+ //# sourceMappingURL=resolve.js.map