@goah/cli 0.13.0 → 0.13.2

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 (236) hide show
  1. package/dist/LICENSE +201 -0
  2. package/dist/THIRD-PARTY-NOTICES.md +2319 -0
  3. package/dist/anthropic-messages-WBFOHES5.js +7214 -0
  4. package/dist/azure-openai-responses-NZFH3PO6.js +253 -0
  5. package/dist/chunk-25XSBFX6.js +639 -0
  6. package/dist/chunk-2QBQZGXF.js +110 -0
  7. package/dist/chunk-2ZP2NBW3.js +345 -0
  8. package/dist/chunk-4KA63VNZ.js +2 -0
  9. package/dist/chunk-4M6TXTT5.js +86 -0
  10. package/dist/chunk-4US7ZHT3.js +20 -0
  11. package/dist/chunk-6M3OOCKO.js +11809 -0
  12. package/dist/chunk-7AXAFDPG.js +17 -0
  13. package/dist/chunk-7E7V6OIU.js +920 -0
  14. package/dist/chunk-BXA47DTF.js +548 -0
  15. package/dist/chunk-D2DVAH37.js +25 -0
  16. package/dist/chunk-FSBUS2BI.js +26 -0
  17. package/dist/chunk-GKDRAHLI.js +4787 -0
  18. package/dist/chunk-H462EFJP.js +89 -0
  19. package/dist/chunk-IIJQ3DW4.js +35 -0
  20. package/dist/chunk-JQD5EWJY.js +34 -0
  21. package/dist/chunk-K26BVR6O.js +61 -0
  22. package/dist/chunk-KAO7WIXG.js +31 -0
  23. package/dist/chunk-KJ4HJCTK.js +1178 -0
  24. package/dist/chunk-LBKI23CC.js +9810 -0
  25. package/dist/chunk-LKBKZEHT.js +41 -0
  26. package/dist/chunk-MD7TLTXZ.js +18 -0
  27. package/dist/chunk-MPXK7QBL.js +868 -0
  28. package/dist/chunk-NRLGWZJC.js +11 -0
  29. package/dist/chunk-QBD6EJ2Z.js +1746 -0
  30. package/dist/chunk-R6I3VKME.js +132 -0
  31. package/dist/chunk-TJON22J4.js +87 -0
  32. package/dist/chunk-ULY36ME4.js +33097 -0
  33. package/dist/chunk-XALZLRYK.js +9221 -0
  34. package/dist/chunk-XPQKM3L7.js +57 -0
  35. package/dist/chunk-YH6YJ2IB.js +1773 -0
  36. package/dist/cli.d.ts +0 -2
  37. package/dist/cli.js +13716 -580
  38. package/dist/console/assets/{index-Rtc_B7cs.js → index-B1vGMXKr.js} +11 -11
  39. package/dist/console/assets/{index-Rtc_B7cs.js.map → index-B1vGMXKr.js.map} +1 -1
  40. package/dist/console/index.html +1 -1
  41. package/dist/dist-65MDQA4Q.js +1126 -0
  42. package/dist/dist-KNR2XL6J.js +39 -0
  43. package/dist/execution.d.ts +557 -2
  44. package/dist/execution.js +37 -2
  45. package/dist/faux-runner-worker.js +128 -0
  46. package/dist/google-generative-ai-YMHXZSFE.js +422 -0
  47. package/dist/google-vertex-X6DB3ZQ6.js +471 -0
  48. package/dist/index.d.ts +853 -25
  49. package/dist/index.js +84 -385
  50. package/dist/kernel.d.ts +39 -2
  51. package/dist/kernel.js +21 -2
  52. package/dist/mistral-conversations-TY3MMD6G.js +718 -0
  53. package/dist/multipart-parser-F6M4NJZU.js +373 -0
  54. package/dist/openai-codex-responses-BRDUMLN5.js +1374 -0
  55. package/dist/openai-completions-CX634XN3.js +1139 -0
  56. package/dist/openai-responses-HMCXJIHT.js +300 -0
  57. package/dist/openrouter-images-KTWET2H2.js +148 -0
  58. package/dist/pi-messages-XL5OEC4K.js +307 -0
  59. package/dist/pi-worker.js +671 -0
  60. package/dist/runner-pi.d.ts +342 -2
  61. package/dist/runner-pi.js +46 -2
  62. package/dist/runner-registry-GD4BYCQC.js +22 -0
  63. package/dist/sqlite.d.ts +446 -2
  64. package/dist/sqlite.js +15 -2
  65. package/dist/src-F2KBSV4T.js +1398 -0
  66. package/dist/supervisor.d.ts +625 -2
  67. package/dist/supervisor.js +39 -2
  68. package/dist/testkit.d.ts +564 -2
  69. package/dist/testkit.js +127 -2
  70. package/dist/transcript.d.ts +84 -2
  71. package/dist/transcript.js +25 -2
  72. package/dist/verification-worker.js +72 -0
  73. package/package.json +2 -26
  74. package/dist/cli.d.ts.map +0 -1
  75. package/dist/cli.js.map +0 -1
  76. package/dist/control.d.ts +0 -106
  77. package/dist/control.d.ts.map +0 -1
  78. package/dist/control.js +0 -242
  79. package/dist/control.js.map +0 -1
  80. package/dist/execution.d.ts.map +0 -1
  81. package/dist/execution.js.map +0 -1
  82. package/dist/index.d.ts.map +0 -1
  83. package/dist/index.js.map +0 -1
  84. package/dist/kernel.d.ts.map +0 -1
  85. package/dist/kernel.js.map +0 -1
  86. package/dist/live-config.d.ts +0 -10
  87. package/dist/live-config.d.ts.map +0 -1
  88. package/dist/live-config.js +0 -44
  89. package/dist/live-config.js.map +0 -1
  90. package/dist/prompt-queue.d.ts +0 -13
  91. package/dist/prompt-queue.d.ts.map +0 -1
  92. package/dist/prompt-queue.js +0 -35
  93. package/dist/prompt-queue.js.map +0 -1
  94. package/dist/runner-pi.d.ts.map +0 -1
  95. package/dist/runner-pi.js.map +0 -1
  96. package/dist/runner-registry.d.ts +0 -8
  97. package/dist/runner-registry.d.ts.map +0 -1
  98. package/dist/runner-registry.js +0 -12
  99. package/dist/runner-registry.js.map +0 -1
  100. package/dist/searchable-select.d.ts +0 -24
  101. package/dist/searchable-select.d.ts.map +0 -1
  102. package/dist/searchable-select.js +0 -61
  103. package/dist/searchable-select.js.map +0 -1
  104. package/dist/secret-input.d.ts +0 -8
  105. package/dist/secret-input.d.ts.map +0 -1
  106. package/dist/secret-input.js +0 -14
  107. package/dist/secret-input.js.map +0 -1
  108. package/dist/setup-wizard.d.ts +0 -22
  109. package/dist/setup-wizard.d.ts.map +0 -1
  110. package/dist/setup-wizard.js +0 -154
  111. package/dist/setup-wizard.js.map +0 -1
  112. package/dist/sqlite.d.ts.map +0 -1
  113. package/dist/sqlite.js.map +0 -1
  114. package/dist/supervisor.d.ts.map +0 -1
  115. package/dist/supervisor.js.map +0 -1
  116. package/dist/testkit.d.ts.map +0 -1
  117. package/dist/testkit.js.map +0 -1
  118. package/dist/thread-inspect.d.ts +0 -47
  119. package/dist/thread-inspect.d.ts.map +0 -1
  120. package/dist/thread-inspect.js +0 -78
  121. package/dist/thread-inspect.js.map +0 -1
  122. package/dist/transcript.d.ts.map +0 -1
  123. package/dist/transcript.js.map +0 -1
  124. package/dist/tui-theme.d.ts +0 -17
  125. package/dist/tui-theme.d.ts.map +0 -1
  126. package/dist/tui-theme.js +0 -19
  127. package/dist/tui-theme.js.map +0 -1
  128. package/dist/tui.d.ts +0 -24
  129. package/dist/tui.d.ts.map +0 -1
  130. package/dist/tui.js +0 -784
  131. package/dist/tui.js.map +0 -1
  132. package/dist/update.d.ts +0 -16
  133. package/dist/update.d.ts.map +0 -1
  134. package/dist/update.js +0 -67
  135. package/dist/update.js.map +0 -1
  136. package/dist/web-console.d.ts +0 -33
  137. package/dist/web-console.d.ts.map +0 -1
  138. package/dist/web-console.js +0 -242
  139. package/dist/web-console.js.map +0 -1
  140. package/dist/welcome.d.ts +0 -30
  141. package/dist/welcome.d.ts.map +0 -1
  142. package/dist/welcome.js +0 -69
  143. package/dist/welcome.js.map +0 -1
  144. package/node_modules/goah-ledger-contract/dist/execution.d.ts +0 -544
  145. package/node_modules/goah-ledger-contract/dist/execution.d.ts.map +0 -1
  146. package/node_modules/goah-ledger-contract/dist/execution.js +0 -52
  147. package/node_modules/goah-ledger-contract/dist/execution.js.map +0 -1
  148. package/node_modules/goah-ledger-contract/dist/index.d.ts +0 -4
  149. package/node_modules/goah-ledger-contract/dist/index.d.ts.map +0 -1
  150. package/node_modules/goah-ledger-contract/dist/index.js +0 -4
  151. package/node_modules/goah-ledger-contract/dist/index.js.map +0 -1
  152. package/node_modules/goah-ledger-contract/dist/kernel.d.ts +0 -37
  153. package/node_modules/goah-ledger-contract/dist/kernel.d.ts.map +0 -1
  154. package/node_modules/goah-ledger-contract/dist/kernel.js +0 -8
  155. package/node_modules/goah-ledger-contract/dist/kernel.js.map +0 -1
  156. package/node_modules/goah-ledger-contract/dist/transcript.d.ts +0 -63
  157. package/node_modules/goah-ledger-contract/dist/transcript.d.ts.map +0 -1
  158. package/node_modules/goah-ledger-contract/dist/transcript.js +0 -115
  159. package/node_modules/goah-ledger-contract/dist/transcript.js.map +0 -1
  160. package/node_modules/goah-ledger-contract/package.json +0 -28
  161. package/node_modules/goah-ledger-sqlite/dist/index.d.ts +0 -86
  162. package/node_modules/goah-ledger-sqlite/dist/index.d.ts.map +0 -1
  163. package/node_modules/goah-ledger-sqlite/dist/index.js +0 -1254
  164. package/node_modules/goah-ledger-sqlite/dist/index.js.map +0 -1
  165. package/node_modules/goah-ledger-sqlite/package.json +0 -26
  166. package/node_modules/goah-runner-pi/dist/configurator.d.ts +0 -20
  167. package/node_modules/goah-runner-pi/dist/configurator.d.ts.map +0 -1
  168. package/node_modules/goah-runner-pi/dist/configurator.js +0 -423
  169. package/node_modules/goah-runner-pi/dist/configurator.js.map +0 -1
  170. package/node_modules/goah-runner-pi/dist/credential-store.d.ts +0 -14
  171. package/node_modules/goah-runner-pi/dist/credential-store.d.ts.map +0 -1
  172. package/node_modules/goah-runner-pi/dist/credential-store.js +0 -163
  173. package/node_modules/goah-runner-pi/dist/credential-store.js.map +0 -1
  174. package/node_modules/goah-runner-pi/dist/env-spec.d.ts +0 -17
  175. package/node_modules/goah-runner-pi/dist/env-spec.d.ts.map +0 -1
  176. package/node_modules/goah-runner-pi/dist/env-spec.js +0 -95
  177. package/node_modules/goah-runner-pi/dist/env-spec.js.map +0 -1
  178. package/node_modules/goah-runner-pi/dist/index.d.ts +0 -76
  179. package/node_modules/goah-runner-pi/dist/index.d.ts.map +0 -1
  180. package/node_modules/goah-runner-pi/dist/index.js +0 -326
  181. package/node_modules/goah-runner-pi/dist/index.js.map +0 -1
  182. package/node_modules/goah-runner-pi/dist/model-provider.d.ts +0 -30
  183. package/node_modules/goah-runner-pi/dist/model-provider.d.ts.map +0 -1
  184. package/node_modules/goah-runner-pi/dist/model-provider.js +0 -96
  185. package/node_modules/goah-runner-pi/dist/model-provider.js.map +0 -1
  186. package/node_modules/goah-runner-pi/dist/pi-worker.d.ts +0 -31
  187. package/node_modules/goah-runner-pi/dist/pi-worker.d.ts.map +0 -1
  188. package/node_modules/goah-runner-pi/dist/pi-worker.js +0 -579
  189. package/node_modules/goah-runner-pi/dist/pi-worker.js.map +0 -1
  190. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.d.ts +0 -2
  191. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.d.ts.map +0 -1
  192. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.js +0 -3
  193. package/node_modules/goah-runner-pi/dist/steering-no-ack.test-fixture.js.map +0 -1
  194. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.d.ts +0 -2
  195. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.d.ts.map +0 -1
  196. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.js +0 -5
  197. package/node_modules/goah-runner-pi/dist/steering-reject.test-fixture.js.map +0 -1
  198. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.d.ts +0 -2
  199. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.d.ts.map +0 -1
  200. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.js +0 -5
  201. package/node_modules/goah-runner-pi/dist/steering-worker.test-fixture.js.map +0 -1
  202. package/node_modules/goah-runner-pi/dist/test-helpers.d.ts +0 -4
  203. package/node_modules/goah-runner-pi/dist/test-helpers.d.ts.map +0 -1
  204. package/node_modules/goah-runner-pi/dist/test-helpers.js +0 -13
  205. package/node_modules/goah-runner-pi/dist/test-helpers.js.map +0 -1
  206. package/node_modules/goah-runner-pi/dist/verification-worker.d.ts +0 -2
  207. package/node_modules/goah-runner-pi/dist/verification-worker.d.ts.map +0 -1
  208. package/node_modules/goah-runner-pi/dist/verification-worker.js +0 -46
  209. package/node_modules/goah-runner-pi/dist/verification-worker.js.map +0 -1
  210. package/node_modules/goah-runner-pi/package.json +0 -28
  211. package/node_modules/goah-supervisor/dist/context-view.d.ts +0 -30
  212. package/node_modules/goah-supervisor/dist/context-view.d.ts.map +0 -1
  213. package/node_modules/goah-supervisor/dist/context-view.js +0 -58
  214. package/node_modules/goah-supervisor/dist/context-view.js.map +0 -1
  215. package/node_modules/goah-supervisor/dist/index.d.ts +0 -96
  216. package/node_modules/goah-supervisor/dist/index.d.ts.map +0 -1
  217. package/node_modules/goah-supervisor/dist/index.js +0 -1075
  218. package/node_modules/goah-supervisor/dist/index.js.map +0 -1
  219. package/node_modules/goah-supervisor/dist/roles.d.ts +0 -4
  220. package/node_modules/goah-supervisor/dist/roles.d.ts.map +0 -1
  221. package/node_modules/goah-supervisor/dist/roles.js +0 -29
  222. package/node_modules/goah-supervisor/dist/roles.js.map +0 -1
  223. package/node_modules/goah-supervisor/dist/verification.d.ts +0 -61
  224. package/node_modules/goah-supervisor/dist/verification.d.ts.map +0 -1
  225. package/node_modules/goah-supervisor/dist/verification.js +0 -135
  226. package/node_modules/goah-supervisor/dist/verification.js.map +0 -1
  227. package/node_modules/goah-supervisor/package.json +0 -26
  228. package/node_modules/goah-testkit/dist/faux-runner-worker.d.ts +0 -2
  229. package/node_modules/goah-testkit/dist/faux-runner-worker.d.ts.map +0 -1
  230. package/node_modules/goah-testkit/dist/faux-runner-worker.js +0 -82
  231. package/node_modules/goah-testkit/dist/faux-runner-worker.js.map +0 -1
  232. package/node_modules/goah-testkit/dist/index.d.ts +0 -49
  233. package/node_modules/goah-testkit/dist/index.d.ts.map +0 -1
  234. package/node_modules/goah-testkit/dist/index.js +0 -96
  235. package/node_modules/goah-testkit/dist/index.js.map +0 -1
  236. package/node_modules/goah-testkit/package.json +0 -29
@@ -0,0 +1,671 @@
1
+ import { createRequire as __goahCreateRequire } from "node:module";
2
+ const require = __goahCreateRequire(import.meta.url);
3
+ import {
4
+ Agent
5
+ } from "./chunk-XALZLRYK.js";
6
+ import {
7
+ runProcessWorker
8
+ } from "./chunk-7E7V6OIU.js";
9
+ import {
10
+ createPiModel,
11
+ fauxAssistantMessage,
12
+ fauxText,
13
+ fauxToolCall,
14
+ typebox_exports
15
+ } from "./chunk-6M3OOCKO.js";
16
+ import "./chunk-K26BVR6O.js";
17
+ import "./chunk-IIJQ3DW4.js";
18
+ import "./chunk-2ZP2NBW3.js";
19
+ import "./chunk-MPXK7QBL.js";
20
+ import "./chunk-2QBQZGXF.js";
21
+ import "./chunk-4KA63VNZ.js";
22
+ import "./chunk-KAO7WIXG.js";
23
+ import {
24
+ TRANSCRIPT_FORMAT_VERSION
25
+ } from "./chunk-R6I3VKME.js";
26
+ import {
27
+ normalizeAssistantText
28
+ } from "./chunk-TJON22J4.js";
29
+ import "./chunk-XPQKM3L7.js";
30
+
31
+ // node_modules/goah-runner-pi/dist/pi-worker.js
32
+ import { spawn } from "node:child_process";
33
+ import { existsSync, mkdtempSync, readdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
34
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
35
+ import { delimiter, dirname, join, resolve, sep } from "node:path";
36
+ import { homedir, tmpdir } from "node:os";
37
+ import { fileURLToPath } from "node:url";
38
+ function compactMessages(messages, maxRecent = 8) {
39
+ if (messages.length <= maxRecent + 1)
40
+ return messages;
41
+ const removed = messages.slice(1, -maxRecent);
42
+ const summary = removed.map((message, index) => `${index + 1}. ${messageText(message).slice(0, 240)}`).join("\n");
43
+ return [
44
+ messages[0],
45
+ { role: "user", content: `Compacted model view. Original trace is unchanged. Source message indexes 1-${removed.length}:
46
+ ${summary}`, timestamp: Date.now() },
47
+ ...messages.slice(-maxRecent)
48
+ ];
49
+ }
50
+ async function runPiWorker() {
51
+ await runProcessWorker(async (request, emit, rpc, controls) => {
52
+ const contextRecord = typeof request.context === "object" && request.context !== null && !Array.isArray(request.context) ? request.context : {};
53
+ const legacyRequest = request.turn === void 0;
54
+ const binding = request.turn?.goalCommitment;
55
+ const goalState = { bound: legacyRequest || binding !== null && binding !== void 0, ...binding ? { binding } : {} };
56
+ const profile = contextRecord.runnerProfile && typeof contextRecord.runnerProfile === "object" && !Array.isArray(contextRecord.runnerProfile) ? contextRecord.runnerProfile : {};
57
+ const runnerConfig = profile.config && typeof profile.config === "object" && !Array.isArray(profile.config) ? profile.config : {};
58
+ const provider = typeof runnerConfig.provider === "string" ? runnerConfig.provider : process.env.GOAH_PI_PROVIDER ?? "anthropic";
59
+ const modelId = typeof runnerConfig.model === "string" ? runnerConfig.model : process.env.GOAH_PI_MODEL;
60
+ if (!modelId)
61
+ throw new Error("GOAH_PI_MODEL is required");
62
+ const configured = createPiModel(provider, modelId);
63
+ const { models } = configured;
64
+ const privateAuth = request.runtime && typeof request.runtime === "object" && !Array.isArray(request.runtime) ? request.runtime : {};
65
+ const protectedPaths = Array.isArray(privateAuth.protectedPaths) ? privateAuth.protectedPaths.filter((value) => typeof value === "string").map((path) => resolve(path)) : [];
66
+ const model = typeof privateAuth.baseUrl === "string" ? { ...configured.model, baseUrl: privateAuth.baseUrl } : configured.model;
67
+ if (provider === "faux") {
68
+ const faux = configured.faux;
69
+ if (process.env.GOAH_PI_FAUX_ERROR) {
70
+ faux.setResponses([fauxAssistantMessage([], { stopReason: "error", errorMessage: process.env.GOAH_PI_FAUX_ERROR })]);
71
+ } else if (goalState.bound && !legacyRequest) {
72
+ const handoff = JSON.parse(process.env.GOAH_PI_FAUX_HANDOFF ?? "{}");
73
+ const current = contextRecord.workRecord && typeof contextRecord.workRecord === "object" && !Array.isArray(contextRecord.workRecord) ? contextRecord.workRecord : {};
74
+ const evidence = Array.isArray(contextRecord.sourceSeqs) ? contextRecord.sourceSeqs.filter((value) => typeof value === "number") : [];
75
+ const outcome = ["progress", "waiting", "blocked", "completion_proposed"].includes(String(handoff.outcome)) ? String(handoff.outcome) : "progress";
76
+ const handoffEvidence = Array.isArray(handoff.evidence) && handoff.evidence.every((value) => typeof value === "number") ? handoff.evidence : evidence.length ? [Math.max(...evidence)] : [];
77
+ const record = `# Current State
78
+
79
+ Faux Goal outcome: ${outcome}.
80
+
81
+ # Observations
82
+
83
+ See the cited Ledger evidence.
84
+
85
+ # Work Completed
86
+
87
+ Executed the scripted faux Goal turn.
88
+
89
+ # Decisions
90
+
91
+ Record the scripted result from ${request.execution.id}.
92
+
93
+ # Blockers
94
+
95
+ ${outcome === "blocked" ? "Blocked." : "None."}
96
+
97
+ # Next Steps
98
+
99
+ Follow the current Goal and explicit tools.
100
+ `;
101
+ const finalResponse = fauxAssistantMessage([fauxText(String(handoff.message ?? `Goal work recorded with outcome ${outcome}.`)), fauxToolCall("handoff", { outcome, evidence: handoffEvidence })], { stopReason: "toolUse" });
102
+ const recordResponse = fauxAssistantMessage(fauxToolCall("work_record_update", { expectedRevision: Number(current.recordRevision ?? 0), content: record, reason: "record faux Goal progress", evidence: evidence.length ? [Math.max(...evidence)] : [] }), { stopReason: "toolUse" });
103
+ const fatalBatch = fauxAssistantMessage([fauxText("Stale completion attempt."), fauxToolCall("handoff", { outcome, evidence: handoffEvidence }), fauxToolCall("write", { path: "fatal.txt", content: "must not be written" })], { stopReason: "toolUse" });
104
+ faux.setResponses(process.env.GOAH_PI_FAUX_FATAL_BATCH === "1" ? [fatalBatch] : process.env.GOAH_PI_FAUX_HANDOFF_REPAIR === "1" ? [fauxAssistantMessage([fauxText("Premature completion attempt."), fauxToolCall("handoff", { outcome, evidence: handoffEvidence })], { stopReason: "toolUse" }), recordResponse, finalResponse] : [recordResponse, finalResponse]);
105
+ } else if (!goalState.bound) {
106
+ faux.setResponses([fauxAssistantMessage([fauxText(process.env.GOAH_PI_FAUX_RESPONSE ?? "Hello from Goah.")])]);
107
+ } else {
108
+ const handoff = JSON.parse(process.env.GOAH_PI_FAUX_HANDOFF ?? "{}");
109
+ const { message, ...handoffData } = handoff;
110
+ faux.setResponses([fauxAssistantMessage([fauxText(String(message ?? "Goal work recorded.")), fauxToolCall("handoff", handoffData)], { stopReason: "toolUse" })]);
111
+ }
112
+ }
113
+ let output = null;
114
+ let acceptedHandoff = null;
115
+ let revokedReason = "";
116
+ let response = "";
117
+ let responseFailure = "";
118
+ let compactions = 0;
119
+ let messageCounter = 0;
120
+ const messageIds = /* @__PURE__ */ new WeakMap();
121
+ const emittedUsers = /* @__PURE__ */ new Set();
122
+ const idFor = (message) => {
123
+ if (typeof message !== "object" || message === null)
124
+ return `message:${++messageCounter}`;
125
+ const existing = messageIds.get(message);
126
+ if (existing)
127
+ return existing;
128
+ const id = `message:${++messageCounter}`;
129
+ messageIds.set(message, id);
130
+ return id;
131
+ };
132
+ const root = resolve(process.cwd());
133
+ const capabilities = Array.isArray(contextRecord.capabilities) ? new Set(contextRecord.capabilities.filter((value) => typeof value === "string")) : void 0;
134
+ if (contextRecord.workRecord && typeof contextRecord.workRecord === "object" && !Array.isArray(contextRecord.workRecord) && typeof contextRecord.workRecord.recordRevision === "number")
135
+ goalState.recordRevision = contextRecord.workRecord.recordRevision;
136
+ const tools = createTools(root, (value) => {
137
+ if (!acceptedHandoff || !sameHandoff(acceptedHandoff.handoff, value))
138
+ throw new Error("Handoff tool executed without accepted validation");
139
+ output = { validationAttemptId: acceptedHandoff.attemptId, validationToken: acceptedHandoff.token, handoff: value };
140
+ }, rpc, capabilities, goalState, protectedPaths);
141
+ const contextPolicy = resolveContextPolicy(model.contextWindow, process.env);
142
+ emit({ type: "transcript.started", data: { formatVersion: TRANSCRIPT_FORMAT_VERSION, provider, model: modelId, runner: "pi", contextWindowTokens: model.contextWindow, maxOutputTokensPerTurn: model.maxTokens } });
143
+ const suppliedPrompt = typeof contextRecord.systemPrompt === "string" ? contextRecord.systemPrompt : void 0;
144
+ const activeContext = typeof contextRecord.text === "string" ? contextRecord.text : JSON.stringify(request.context);
145
+ const sourceSeqs = Array.isArray(contextRecord.sourceSeqs) ? contextRecord.sourceSeqs.filter((value) => Number.isInteger(value)) : [];
146
+ const basePrompt = process.env.GOAH_PI_SYSTEM_PROMPT ?? suppliedPrompt ?? (request.turn?.trigger.kind === "user_message" ? "You are Goah's primary Agent. Respond naturally to the Human." : `You are Goah Agent ${request.agent}. Inspect the supplied context and respond appropriately.`);
147
+ const systemPrompt = goalState.bound ? `${basePrompt}
148
+ This Turn has a Goal commitment. You must update its Work Record, write a concise human-readable assistant message describing what happened, and call handoff exactly once with only machine-readable outcome and evidence. The message and Handoff are separate outputs. Treat the supplied context as authoritative.` : request.turn?.trigger.kind === "user_message" ? `${basePrompt}
149
+ The active Goal, when supplied, is context rather than an assignment. Finish with an ordinary response unless a Goal tool establishes a commitment during this Turn. After commitment, update that Goal's Work Record, write a concise human-readable assistant message, and call handoff exactly once with separate machine-readable outcome and evidence. Treat the supplied context as authoritative.` : `${basePrompt}
150
+ This Turn has no Goal commitment. Finish with an ordinary response and do not call handoff. Treat the supplied context as authoritative.`;
151
+ const agent = new Agent({
152
+ initialState: {
153
+ systemPrompt,
154
+ model,
155
+ thinkingLevel: typeof runnerConfig.thinking === "string" ? runnerConfig.thinking : "off",
156
+ tools
157
+ },
158
+ streamFn: async (requestModel, context, options) => {
159
+ emit({
160
+ type: "request.prepared",
161
+ data: {
162
+ provider: requestModel.provider,
163
+ model: requestModel.id,
164
+ systemPrompt: context.systemPrompt ?? "",
165
+ activeContext,
166
+ messages: JSON.parse(JSON.stringify(context.messages)),
167
+ tools: (context.tools ?? []).map((tool) => ({ name: tool.name, description: tool.description, parameters: tool.parameters })),
168
+ modelConfig: snapshotModelConfig(options),
169
+ sourceSeqs
170
+ }
171
+ });
172
+ const runtimeProvider = models.getProvider(requestModel.provider);
173
+ if (!runtimeProvider)
174
+ throw new Error(`Provider not found: ${requestModel.provider}`);
175
+ const runtimeModel = typeof privateAuth.baseUrl === "string" ? { ...requestModel, baseUrl: privateAuth.baseUrl } : requestModel;
176
+ return runtimeProvider.streamSimple(runtimeModel, context, { ...options, ...typeof privateAuth.apiKey === "string" ? { apiKey: privateAuth.apiKey } : {}, ...privateAuth.headers && typeof privateAuth.headers === "object" && !Array.isArray(privateAuth.headers) ? { headers: privateAuth.headers } : {}, ...process.env.GOAH_PI_CACHE_RETENTION === "none" ? { cacheRetention: "none" } : {} });
177
+ },
178
+ getApiKey: () => typeof privateAuth.apiKey === "string" ? privateAuth.apiKey : void 0,
179
+ transformContext: async (messages) => {
180
+ let view = messages;
181
+ if (estimateMessages(messages) >= contextPolicy.compactAtTokens) {
182
+ compactions += 1;
183
+ view = compactMessagesToTokenBudget(messages, contextPolicy.retainAfterCompactTokens);
184
+ const retained = new Set(view.filter((message) => messages.includes(message)));
185
+ const summary = view.find((message) => !messages.includes(message));
186
+ if (summary)
187
+ emit({ type: "context.compacted", data: { compaction: compactions, sourceMessageCount: messages.length, replacedMessageIds: messages.filter((message) => !retained.has(message)).map(idFor), retainedMessageIds: messages.filter((message) => retained.has(message)).map(idFor), summaryMessageId: idFor(summary), summary: messageText(summary) } });
188
+ }
189
+ return view;
190
+ },
191
+ beforeToolCall: async ({ assistantMessage, toolCall, args }) => {
192
+ if (revokedReason)
193
+ return { block: true, reason: `Turn authority was revoked: ${revokedReason}`, terminate: true };
194
+ if (toolCall.name !== "handoff")
195
+ return;
196
+ acceptedHandoff = null;
197
+ output = null;
198
+ const handoff = args;
199
+ try {
200
+ const result = await rpc("goal.handoff.validate", { handoff, candidateMessage: assistantResponseText(assistantMessage) });
201
+ if (result.accepted) {
202
+ acceptedHandoff = { attemptId: result.attemptId, token: result.token, handoff };
203
+ return;
204
+ }
205
+ const reason = result.issues.map((issue) => `- ${issue.message}`).join("\n");
206
+ if (result.fatal)
207
+ revokedReason = reason;
208
+ return { block: true, reason: `Handoff was not accepted:
209
+ ${reason}`, terminate: result.fatal };
210
+ } catch (error) {
211
+ revokedReason = error instanceof Error ? error.message : String(error);
212
+ return { block: true, reason: `Handoff validation could not continue: ${revokedReason}`, terminate: true };
213
+ }
214
+ },
215
+ shouldStopAfterTurn: () => output !== null || Boolean(revokedReason),
216
+ toolExecution: "sequential"
217
+ });
218
+ let acceptingSteering = true;
219
+ controls.onSteer((message) => {
220
+ if (!acceptingSteering)
221
+ return false;
222
+ agent.steer({ role: "user", content: message, timestamp: Date.now() });
223
+ return true;
224
+ });
225
+ agent.subscribe((event) => {
226
+ if (event.type === "turn_start")
227
+ emit({ type: "turn.started", data: {} });
228
+ else if (event.type === "message_start" && event.message.role === "user") {
229
+ const id = idFor(event.message);
230
+ if (!emittedUsers.has(id)) {
231
+ emittedUsers.add(id);
232
+ emit({ type: "message.user", data: { message: transcriptMessage(event.message, id) } });
233
+ }
234
+ } else if (event.type === "message_update") {
235
+ emit({ type: "message.assistant.delta", data: { messageId: idFor(event.message), delta: JSON.parse(JSON.stringify(event.assistantMessageEvent)) } });
236
+ } else if (event.type === "message_end" && event.message.role === "assistant") {
237
+ response = assistantResponseText(event.message);
238
+ if ((event.message.stopReason === "error" || event.message.stopReason === "aborted") && event.message.errorMessage)
239
+ responseFailure = event.message.errorMessage;
240
+ const handoffIntent = hasAgentToolCall(event.message, "handoff");
241
+ emit({ type: "message.assistant.completed", data: { message: transcriptMessage(event.message, idFor(event.message)), commitState: handoffIntent ? "provisional" : "committed" } });
242
+ } else if (event.type === "tool_execution_start")
243
+ emit({ type: "tool.called", data: { callId: event.toolCallId, name: event.toolName, arguments: JSON.parse(JSON.stringify(event.args)) } });
244
+ else if (event.type === "tool_execution_end")
245
+ emit({ type: "tool.completed", data: { callId: event.toolCallId, messageId: `tool:${event.toolCallId}`, name: event.toolName, result: JSON.parse(JSON.stringify(event.result)), isError: event.isError } });
246
+ else if (event.type === "turn_end")
247
+ emit({ type: "turn.completed", data: {} });
248
+ });
249
+ const abortAgent = () => agent.abort();
250
+ process.once("SIGTERM", abortAgent);
251
+ process.once("SIGINT", abortAgent);
252
+ try {
253
+ await agent.prompt(`Turn started at: ${request.execution.startedAt}
254
+
255
+ ${activeContext}
256
+
257
+ Runner root: ${root}. Manage local files directly when the goal requires them.`);
258
+ } finally {
259
+ acceptingSteering = false;
260
+ process.off("SIGTERM", abortAgent);
261
+ process.off("SIGINT", abortAgent);
262
+ }
263
+ if (revokedReason)
264
+ return { outcome: "abnormal", reason: revokedReason };
265
+ if (!goalState.bound)
266
+ return response ? { outcome: "completed", response: { content: response } } : { outcome: "abnormal", reason: responseFailure || "Pi worker exited without a response" };
267
+ if (responseFailure)
268
+ return { outcome: "abnormal", reason: responseFailure };
269
+ if (!output)
270
+ return { outcome: "abnormal", reason: "Pi worker exited without an accepted Handoff" };
271
+ return { outcome: "completed", response: { content: response }, handoff: output };
272
+ });
273
+ }
274
+ function snapshotModelConfig(options) {
275
+ if (!options || typeof options !== "object" || Array.isArray(options))
276
+ return {};
277
+ const record = options;
278
+ const allowed = ["transport", "toolExecution", "temperature", "topP", "maxTokens", "reasoning", "thinkingLevel", "toolChoice"];
279
+ return Object.fromEntries(allowed.flatMap((key) => isJson(record[key]) ? [[key, JSON.parse(JSON.stringify(record[key]))]] : []));
280
+ }
281
+ function isJson(value) {
282
+ if (value === null || ["string", "number", "boolean"].includes(typeof value))
283
+ return true;
284
+ if (Array.isArray(value))
285
+ return value.every(isJson);
286
+ return Boolean(value && typeof value === "object" && Object.values(value).every(isJson));
287
+ }
288
+ function transcriptMessage(message, id) {
289
+ const value = JSON.parse(JSON.stringify(message));
290
+ const role = message.role === "assistant" ? "assistant" : message.role === "user" ? "user" : "tool";
291
+ return { id, role, content: value.content ?? value, ...value.usage !== void 0 ? { usage: value.usage } : {}, ...typeof value.stopReason === "string" ? { stopReason: value.stopReason } : {}, ...typeof value.errorMessage === "string" ? { errorMessage: value.errorMessage } : {} };
292
+ }
293
+ function createTools(root, handoff, rpc, capabilities, goalState, protectedPaths = []) {
294
+ const handoffTool = {
295
+ name: "handoff",
296
+ label: "Handoff",
297
+ description: "Record a structured handoff and end a Turn with a Goal commitment.",
298
+ parameters: typebox_exports.Object({
299
+ outcome: typebox_exports.Union([typebox_exports.Literal("progress"), typebox_exports.Literal("waiting"), typebox_exports.Literal("blocked"), typebox_exports.Literal("completion_proposed")]),
300
+ evidence: typebox_exports.Array(typebox_exports.Number())
301
+ }),
302
+ execute: async (_id, params) => {
303
+ const input = params;
304
+ const value = { outcome: input.outcome, evidence: input.evidence };
305
+ handoff(value);
306
+ return { content: [{ type: "text", text: "handoff recorded" }], details: value, terminate: true };
307
+ }
308
+ };
309
+ const rpcTools = createRpcTools(rpc, capabilities, (method, result) => {
310
+ if ((method === "goal.create" || method === "goal.work" || method === "goal.resume") && result && typeof result === "object" && !Array.isArray(result) && result.goalCommitment && typeof result.goalCommitment === "object" && !Array.isArray(result.goalCommitment)) {
311
+ const binding = result.goalCommitment;
312
+ if (typeof binding.goalId === "string" && typeof binding.goalRevision === "number") {
313
+ goalState.bound = true;
314
+ goalState.binding = { goalId: binding.goalId, goalRevision: binding.goalRevision };
315
+ }
316
+ }
317
+ if (method === "work_record.update" && result && typeof result === "object" && !Array.isArray(result) && typeof result.recordRevision === "number")
318
+ goalState.recordRevision = result.recordRevision;
319
+ });
320
+ const readTool = {
321
+ name: "read",
322
+ label: "Read",
323
+ description: "Read a UTF-8 file inside the current working directory.",
324
+ parameters: typebox_exports.Object({ path: typebox_exports.String() }),
325
+ execute: async (_id, params) => {
326
+ const input = params;
327
+ return { content: [{ type: "text", text: await readFile(scopedRunnerPath(root, input.path, protectedPaths), "utf8") }], details: {} };
328
+ }
329
+ };
330
+ const writeTool = {
331
+ name: "write",
332
+ label: "Write",
333
+ description: "Create or replace a UTF-8 file inside the current working directory.",
334
+ parameters: typebox_exports.Object({ path: typebox_exports.String(), content: typebox_exports.String() }),
335
+ execute: async (_id, params) => {
336
+ const input = params;
337
+ const path = scopedRunnerPath(root, input.path, protectedPaths);
338
+ await mkdir(dirname(path), { recursive: true });
339
+ await writeFile(path, input.content);
340
+ return { content: [{ type: "text", text: "written" }], details: {} };
341
+ }
342
+ };
343
+ const editTool = {
344
+ name: "edit",
345
+ label: "Edit",
346
+ description: "Replace one exact text occurrence in a UTF-8 file inside the current working directory.",
347
+ parameters: typebox_exports.Object({ path: typebox_exports.String(), oldText: typebox_exports.String(), newText: typebox_exports.String() }),
348
+ execute: async (_id, params) => {
349
+ const input = params;
350
+ const path = scopedRunnerPath(root, input.path, protectedPaths);
351
+ const source = await readFile(path, "utf8");
352
+ const first = source.indexOf(input.oldText);
353
+ if (first < 0)
354
+ throw new Error("edit oldText was not found");
355
+ if (source.indexOf(input.oldText, first + input.oldText.length) >= 0)
356
+ throw new Error("edit oldText is not unique");
357
+ await writeFile(path, `${source.slice(0, first)}${input.newText}${source.slice(first + input.oldText.length)}`);
358
+ return { content: [{ type: "text", text: "edited" }], details: { path: input.path } };
359
+ }
360
+ };
361
+ const bashTool = {
362
+ name: "bash",
363
+ label: "Bash",
364
+ description: "Run a sandboxed shell command inside the local runner root. Goah credential/control state is masked. If protected state shares the root, use the write tool to create new top-level paths. The command's process group is killed after timeout.",
365
+ parameters: typebox_exports.Object({ command: typebox_exports.String(), timeoutMs: typebox_exports.Optional(typebox_exports.Number()) }),
366
+ executionMode: "sequential",
367
+ execute: async (_id, params, signal) => runBashCommand(root, params, signal, protectedPaths)
368
+ };
369
+ return [readTool, writeTool, editTool, bashTool, ...rpcTools, handoffTool];
370
+ }
371
+ var BASH_TIMEOUT_HARD_CAP_MS = 6e5;
372
+ function bashTimeoutMs(requested, env = process.env) {
373
+ const fallback = integerSetting(env.GOAH_PI_BASH_TIMEOUT_MS, 12e4);
374
+ const value = requested ?? fallback;
375
+ return Number.isFinite(value) && value > 0 ? Math.min(value, BASH_TIMEOUT_HARD_CAP_MS) : fallback;
376
+ }
377
+ async function runBashCommand(root, input, signal, protectedPaths = []) {
378
+ const timeoutMs = bashTimeoutMs(input.timeoutMs);
379
+ const sandboxTemp = mkdtempSync(join(tmpdir(), "goah-bash-"));
380
+ const launch = sandboxedShell(input.command, root, protectedPaths, sandboxTemp);
381
+ if (!launch) {
382
+ if (sandboxTemp)
383
+ rmSync(sandboxTemp, { recursive: true, force: true });
384
+ return { content: [{ type: "text", text: "Bash is unavailable because this platform cannot isolate Goah credential and control state." }], details: { command: input.command }, isError: true };
385
+ }
386
+ const child = spawn(launch.command, launch.args, { cwd: root, env: toolEnvironment(sandboxTemp), detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"] });
387
+ let stdout = "";
388
+ let stderr = "";
389
+ let timedOut = false;
390
+ let outputOverflow = false;
391
+ const killGroup = () => {
392
+ if (child.pid) {
393
+ try {
394
+ process.kill(process.platform === "win32" ? child.pid : -child.pid, "SIGKILL");
395
+ } catch {
396
+ }
397
+ }
398
+ };
399
+ const appendOutput = (channel, chunk) => {
400
+ if (outputOverflow)
401
+ return;
402
+ const text = chunk.toString();
403
+ const remaining = Math.max(0, 1e6 - stdout.length - stderr.length);
404
+ if (channel === "stdout")
405
+ stdout += text.slice(0, remaining);
406
+ else
407
+ stderr += text.slice(0, remaining);
408
+ if (text.length > remaining) {
409
+ outputOverflow = true;
410
+ killGroup();
411
+ }
412
+ };
413
+ child.stdout?.on("data", (chunk) => appendOutput("stdout", chunk));
414
+ child.stderr?.on("data", (chunk) => appendOutput("stderr", chunk));
415
+ const timer = setTimeout(() => {
416
+ timedOut = true;
417
+ killGroup();
418
+ }, timeoutMs);
419
+ const onAbort = () => killGroup();
420
+ signal?.addEventListener("abort", onAbort, { once: true });
421
+ const close = new Promise((resolve2, reject) => {
422
+ child.once("error", reject);
423
+ child.once("close", (code, signalName) => resolve2({ code, signal: signalName }));
424
+ });
425
+ try {
426
+ const result = await close;
427
+ if (timedOut)
428
+ return { content: [{ type: "text", text: `Command timed out after ${timeoutMs}ms and its process group was killed. Declare a larger timeoutMs for long-running commands.` }], details: { command: input.command, timedOutAfterMs: timeoutMs }, isError: true };
429
+ if (signal?.aborted)
430
+ return { content: [{ type: "text", text: "Command aborted with the wake." }], details: { command: input.command }, isError: true };
431
+ killGroup();
432
+ const failed = outputOverflow || result.code !== 0 || result.signal !== null;
433
+ return { content: [{ type: "text", text: `${stdout}${stderr}`.slice(-5e4) }], details: { command: input.command, exitCode: result.code, signal: result.signal, ...outputOverflow ? { outputOverflow: true } : {} }, ...failed ? { isError: true } : {} };
434
+ } finally {
435
+ clearTimeout(timer);
436
+ signal?.removeEventListener("abort", onAbort);
437
+ if (sandboxTemp)
438
+ rmSync(sandboxTemp, { recursive: true, force: true });
439
+ }
440
+ }
441
+ function resolveContextPolicy(contextWindowTokens, env) {
442
+ if (!Number.isInteger(contextWindowTokens) || contextWindowTokens <= 0)
443
+ throw new Error("model context window is missing");
444
+ const compactAtTokens = integerSetting(env.GOAH_PI_COMPACT_AT_TOKENS, Math.floor(contextWindowTokens * 0.7));
445
+ const retainAfterCompactTokens = integerSetting(env.GOAH_PI_RETAIN_CONTEXT_TOKENS, Math.floor(contextWindowTokens * 0.2));
446
+ if (retainAfterCompactTokens >= compactAtTokens || compactAtTokens >= contextWindowTokens)
447
+ throw new Error("invalid Pi context policy");
448
+ return { compactAtTokens, retainAfterCompactTokens };
449
+ }
450
+ function compactMessagesToTokenBudget(messages, retainTokens) {
451
+ if (messages.length <= 2 || estimateMessages(messages) <= retainTokens)
452
+ return messages;
453
+ const tailBudget = Math.max(1, Math.floor(retainTokens * 0.6));
454
+ let start = messages.length;
455
+ let retained = 0;
456
+ while (start > 1) {
457
+ const tokens = estimateMessages([messages[start - 1]]);
458
+ if (retained > 0 && retained + tokens > tailBudget)
459
+ break;
460
+ retained += tokens;
461
+ start -= 1;
462
+ }
463
+ const removed = messages.slice(1, start);
464
+ const rawSummary = removed.map((message, index) => `${index + 1}. ${messageText(message).slice(0, 240)}`).join("\n");
465
+ const summaryChars = Math.max(0, (retainTokens - retained - 80) * 4);
466
+ const summary = summaryChars === 0 ? "[older entries truncated]" : rawSummary.length <= summaryChars ? rawSummary : `[older entries truncated]
467
+ ${rawSummary.slice(-summaryChars)}`;
468
+ return [
469
+ messages[0],
470
+ { role: "user", content: `Compacted model view. Original trace is unchanged. Source message indexes 1-${removed.length}:
471
+ ${summary}`, timestamp: Date.now() },
472
+ ...messages.slice(start)
473
+ ];
474
+ }
475
+ function createRpcTools(rpc, allowed, onResult) {
476
+ const tool = (name, description, method, parameters) => ({
477
+ name,
478
+ label: name,
479
+ description,
480
+ parameters,
481
+ execute: async (_id, params) => {
482
+ const result = await rpc(method, params);
483
+ onResult?.(method, result);
484
+ return { content: [{ type: "text", text: JSON.stringify(result) }], details: result };
485
+ }
486
+ });
487
+ const definitions = [
488
+ ["ledger.search", tool("ledger_search", "Search durable ledger facts.", "ledger.search", typebox_exports.Object({ query: typebox_exports.String(), limit: typebox_exports.Optional(typebox_exports.Number()) }))],
489
+ ["memory.append", tool("memory_append", "Append a durable working-memory note that is injected into your future wakes. Record procedural knowledge, active hypotheses, and abandoned approaches with the reason; keep notes concise.", "memory.append", typebox_exports.Object({ note: typebox_exports.String() }))],
490
+ ["mail.send", tool("send_mail", "Send durable Mail to another Goal owner. goalId is required and routes the Mail into that owner's next committed Turn. Human communication must use request_human.", "mail.send", typebox_exports.Object({ to: typebox_exports.String(), goalId: typebox_exports.String(), level: typebox_exports.Union([typebox_exports.Literal("fyi"), typebox_exports.Literal("decision"), typebox_exports.Literal("emergency")]), body: typebox_exports.Any() }))],
491
+ ["schedule.set", tool("schedule_wake", "Schedule this agent's next wake.", "schedule.set", typebox_exports.Object({ at: typebox_exports.String(), reason: typebox_exports.String() }))],
492
+ ["team.list", tool("team_list", "Read the ledger-derived team roster and liveness state.", "team.list", typebox_exports.Object({}))],
493
+ ["goal.get", tool("get_goal", "Read the active Goal visible to this Turn. Visibility does not establish a Goal commitment.", "goal.get", typebox_exports.Object({}))],
494
+ ["goal.create", tool("create_goal", "Create a Root Goal from durable Human intent and bind this Turn. Do not use for greetings, questions, or routine single-turn work.", "goal.create", typebox_exports.Object({ objective: typebox_exports.String(), id: typebox_exports.Optional(typebox_exports.String()) }))],
495
+ ["goal.work", tool("work_on_goal", "Commit this direct CEO Turn to an existing active Root Goal owned by this Agent.", "goal.work", typebox_exports.Object({ goalId: typebox_exports.String() }))],
496
+ ["goal.delegate", tool("delegate_goal", "Atomically create a Child Goal with observation and verification methods, its Work Record, decision brief, and initial Wake.", "goal.delegate", typebox_exports.Object({ id: typebox_exports.String(), parentGoalId: typebox_exports.String(), expectedParentRevision: typebox_exports.Number(), childGoal: typebox_exports.Object({ id: typebox_exports.String(), objective: typebox_exports.String(), observationMethod: typebox_exports.String(), verificationMethod: typebox_exports.String(), owner: typebox_exports.String() }), brief: typebox_exports.Any(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
497
+ ["goal.reassign", tool("reassign_goal", "Atomically transfer a child goal, notify both owners, and queue the new owner.", "goal.reassign", typebox_exports.Object({ id: typebox_exports.String(), goalId: typebox_exports.String(), expectedGoalRevision: typebox_exports.Number(), newOwner: typebox_exports.String(), brief: typebox_exports.Any(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
498
+ ["goal.revise", tool("revise_goal", "Revise a Child Goal objective, observation method, and verification method as one new revision.", "goal.revise", typebox_exports.Object({ goalId: typebox_exports.String(), objective: typebox_exports.String(), observationMethod: typebox_exports.String(), verificationMethod: typebox_exports.String(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
499
+ ["goal.pause", tool("pause_goal", "Pause a child goal and suppress queued motion.", "goal.pause", typebox_exports.Object({ goalId: typebox_exports.String() }))],
500
+ ["goal.resume", tool("resume_goal", "Resume a Goal. A direct Human Root resume binds the current Turn; Child Goal resume requires an already bound parent Turn.", "goal.resume", typebox_exports.Object({ goalId: typebox_exports.String() }))],
501
+ ["goal.complete", tool("complete_goal", "Complete a child goal with evidence produced under its current observation method. Root completion remains human authority.", "goal.complete", typebox_exports.Object({ goalId: typebox_exports.String(), revision: typebox_exports.Number(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
502
+ ["human.request", tool("request_human", "Ask the human for a decision, observation-method confirmation, or root completion with evidence.", "human.request", typebox_exports.Object({ type: typebox_exports.Union([typebox_exports.Literal("decision"), typebox_exports.Literal("observation_method_confirmation"), typebox_exports.Literal("completion_recommendation")]), message: typebox_exports.Any(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
503
+ ["work_record.list", tool("work_record_list", "List the current Work Record for every Goal in the organization.", "work_record.list", typebox_exports.Object({}))],
504
+ ["work_record.read", tool("work_record_read", "Read one current Goal Work Record. Omit goalId to use the committed or visible Goal.", "work_record.read", typebox_exports.Object({ goalId: typebox_exports.Optional(typebox_exports.String()) }))],
505
+ ["work_record.history", tool("work_record_history", "Read the version timeline for a Goal Work Record.", "work_record.history", typebox_exports.Object({ goalId: typebox_exports.Optional(typebox_exports.String()) }))],
506
+ ["work_record.diff", tool("work_record_diff", "Compare two revisions of a Goal Work Record.", "work_record.diff", typebox_exports.Object({ goalId: typebox_exports.Optional(typebox_exports.String()), fromRevision: typebox_exports.Number(), toRevision: typebox_exports.Number() }))],
507
+ ["work_record.search", tool("work_record_search", "Search every Goal Work Record.", "work_record.search", typebox_exports.Object({ query: typebox_exports.String(), limit: typebox_exports.Optional(typebox_exports.Number()) }))],
508
+ ["work_record.update", tool("work_record_update", "Create the next version of the Work Record committed to this Turn with Ledger evidence.", "work_record.update", typebox_exports.Object({ expectedRevision: typebox_exports.Number(), content: typebox_exports.String(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))],
509
+ ["goal.put", tool("put_goal", "Create or update a Goal through the authoritative goal.changed protocol using parent-layer authority.", "goal.put", typebox_exports.Object({ goal: typebox_exports.Any(), reason: typebox_exports.String(), evidence: typebox_exports.Array(typebox_exports.Number()) }))]
510
+ ];
511
+ return definitions.filter(([capability]) => !allowed || allowed.has(capability)).map(([, value]) => value);
512
+ }
513
+ function scopedRunnerPath(root, path, protectedPaths = []) {
514
+ const resolved = canonicalPath(resolve(root, path));
515
+ const canonicalRoot = canonicalPath(root);
516
+ if (resolved !== canonicalRoot && !resolved.startsWith(`${canonicalRoot}${sep}`))
517
+ throw new Error("path escapes runner root");
518
+ if (protectedPaths.map(canonicalPath).some((privatePath) => resolved === privatePath || resolved.startsWith(`${privatePath}${sep}`)))
519
+ throw new Error("path is protected Goah state");
520
+ return resolved;
521
+ }
522
+ function sandboxedShell(command, root, protectedPaths, sandboxTemp) {
523
+ if (process.platform === "darwin" && existsSync("/usr/bin/sandbox-exec")) {
524
+ const workspacePaths = sandboxWorkspacePaths(canonicalPath(root), protectedPaths.map(canonicalPath));
525
+ const workspaceAncestors = pathAncestors(canonicalPath(root));
526
+ const toolchains = toolchainReadPaths(canonicalPath(root));
527
+ const readableAncestors = toolchains.flatMap(pathAncestors);
528
+ const readable = ["/System", "/usr", "/bin", "/sbin", "/Library", "/etc", "/dev", "/private/etc", "/private/var/select", "/Applications", ...toolchains, ...workspacePaths, ...sandboxTemp ? [sandboxTemp] : []].filter(existsSync).map(canonicalPath);
529
+ const writable = [...workspacePaths, ...sandboxTemp ? [sandboxTemp] : [], "/dev"].map(canonicalPath);
530
+ const rules = ["(version 1)", "(deny default)", '(import "system.sb")', "(allow process*)", "(allow signal)", "(allow network*)", "(allow sysctl-read)", "(allow mach-lookup)", ...[.../* @__PURE__ */ new Set([...workspaceAncestors, ...readableAncestors])].map((path) => `(allow file-read* (literal ${JSON.stringify(path)}))`), ...readable.map((path) => `(allow file-read* (subpath ${JSON.stringify(path)}))`), ...writable.map((path) => `(allow file-write* (subpath ${JSON.stringify(path)}))`), ...protectedPaths.map(canonicalPath).map((path) => `(deny file-read* file-write* (subpath ${JSON.stringify(path)}))`)];
531
+ return { command: "/usr/bin/sandbox-exec", args: ["-p", rules.join(" "), "/bin/sh", "-lc", command] };
532
+ }
533
+ if (process.platform === "linux") {
534
+ const bwrap = ["/usr/bin/bwrap", "/bin/bwrap"].find(existsSync);
535
+ if (bwrap) {
536
+ const canonicalRoot = canonicalPath(root);
537
+ if (["/usr", "/bin", "/sbin", "/lib", "/lib64", "/etc"].some((path) => canonicalRoot === path || canonicalRoot.startsWith(`${path}${sep}`)))
538
+ return null;
539
+ return { command: bwrap, args: linuxSandboxArgs(command, canonicalRoot, protectedPaths, sandboxTemp) };
540
+ }
541
+ }
542
+ return null;
543
+ }
544
+ function linuxSandboxArgs(command, root, protectedPaths, sandboxTemp) {
545
+ const canonicalRoot = canonicalPath(root);
546
+ const workspacePaths = sandboxWorkspacePaths(canonicalRoot, protectedPaths.map(canonicalPath));
547
+ const systemPaths = ["/usr", "/bin", "/sbin", "/lib", "/lib64", "/etc"].filter(existsSync).flatMap((path) => ["--ro-bind", path, path]);
548
+ const mounted = ["/tmp", "/usr", "/bin", "/sbin", "/lib", "/lib64", "/etc"];
549
+ const toolchains = toolchainReadPaths(canonicalRoot).filter((path) => !mounted.some((base) => path === base || path.startsWith(`${base}${sep}`)) && path !== canonicalRoot && !path.startsWith(`${canonicalRoot}${sep}`));
550
+ const destinations = [canonicalRoot, ...toolchains].flatMap((path) => pathAncestors(path).slice(1)).filter((path) => !mounted.some((base) => path === base || path.startsWith(`${base}${sep}`)));
551
+ const directories = [...new Set(destinations)].sort((left, right) => left.length - right.length).flatMap((path) => ["--dir", path]);
552
+ return ["--die-with-parent", "--unshare-all", "--share-net", ...systemPaths, "--dev", "/dev", "--proc", "/proc", "--tmpfs", "/tmp", ...sandboxTemp ? ["--dir", canonicalPath(sandboxTemp)] : [], ...directories, ...toolchains.flatMap((path) => ["--ro-bind", path, path]), ...workspacePaths.flatMap((path) => ["--bind", path, path]), "--chdir", canonicalRoot, "/bin/sh", "-lc", command];
553
+ }
554
+ function toolchainReadPaths(root) {
555
+ const executable = canonicalPath(process.execPath);
556
+ const pathEntries = (process.env.PATH ?? "").split(delimiter).filter(Boolean).map((path) => resolve(path));
557
+ const prefixes = ["/opt/homebrew", "/usr/local"].filter((prefix) => executable.startsWith(`${prefix}${sep}`) || pathEntries.some((path) => path.startsWith(`${prefix}${sep}`)));
558
+ const home = canonicalPath(homedir());
559
+ const managedHomeRuntime = [join(home, ".nvm", "versions", "node"), join(home, ".asdf", "installs", "node"), join(home, ".volta", "tools", "image", "node")].find((prefix) => executable.startsWith(`${prefix}${sep}`));
560
+ const runtimeRoot = prefixes.length ? [] : managedHomeRuntime ? [executable.slice(0, executable.indexOf(`${sep}bin${sep}`, managedHomeRuntime.length))] : [dirname(executable)];
561
+ return [.../* @__PURE__ */ new Set([...prefixes, ...runtimeRoot])].filter((path) => path !== root && !path.startsWith(`${root}${sep}`));
562
+ }
563
+ function sandboxWorkspacePaths(root, protectedPaths) {
564
+ if (!protectedPaths.some((path) => path === root || path.startsWith(`${root}${sep}`)))
565
+ return [root];
566
+ return [...new Set(readdirSync(root).flatMap((name) => {
567
+ try {
568
+ return [canonicalPath(join(root, name))];
569
+ } catch {
570
+ return [];
571
+ }
572
+ }))].filter((candidate) => candidate !== root && candidate.startsWith(`${root}${sep}`)).filter((candidate) => !protectedPaths.some((path) => path === candidate || path.startsWith(`${candidate}${sep}`) || candidate.startsWith(`${path}${sep}`)));
573
+ }
574
+ function canonicalPath(path) {
575
+ let current = resolve(path);
576
+ const suffix = [];
577
+ while (!existsSync(current)) {
578
+ const parent = dirname(current);
579
+ if (parent === current)
580
+ break;
581
+ suffix.unshift(current.slice(parent.length + 1));
582
+ current = parent;
583
+ }
584
+ return resolve(realpathSync(current), ...suffix);
585
+ }
586
+ function pathAncestors(path) {
587
+ const values = [];
588
+ let current = resolve(path);
589
+ while (true) {
590
+ values.unshift(current);
591
+ const parent = dirname(current);
592
+ if (parent === current)
593
+ return values;
594
+ current = parent;
595
+ }
596
+ }
597
+ function toolEnvironment(sandboxTemp = null) {
598
+ const env = {};
599
+ for (const name of ["PATH", "HOME", "TMPDIR", "TMP", "TEMP", "LANG", "LC_ALL", "SHELL", "TERM", "USER"])
600
+ if (process.env[name] !== void 0)
601
+ env[name] = process.env[name];
602
+ if (sandboxTemp) {
603
+ env.TMPDIR = sandboxTemp;
604
+ env.TMP = sandboxTemp;
605
+ env.TEMP = sandboxTemp;
606
+ }
607
+ if (process.platform === "darwin") {
608
+ const developer = ["/Library/Developer/CommandLineTools", "/Applications/Xcode.app/Contents/Developer"].find(existsSync);
609
+ if (developer)
610
+ env.DEVELOPER_DIR = developer;
611
+ }
612
+ Object.assign(env, gitIdentityEnvironment());
613
+ return env;
614
+ }
615
+ function gitIdentityEnvironment() {
616
+ try {
617
+ const source = readFileSync(join(homedir(), ".gitconfig"), "utf8");
618
+ const user = source.match(/^\[user\]\s*\n((?:[ \t].*(?:\n|$))*)/m)?.[1] ?? "";
619
+ const name = user.match(/^\s*name\s*=\s*(.+)$/m)?.[1]?.trim();
620
+ const email = user.match(/^\s*email\s*=\s*(.+)$/m)?.[1]?.trim();
621
+ return { ...name ? { GIT_AUTHOR_NAME: name, GIT_COMMITTER_NAME: name } : {}, ...email ? { GIT_AUTHOR_EMAIL: email, GIT_COMMITTER_EMAIL: email } : {}, GIT_CONFIG_GLOBAL: "/dev/null" };
622
+ } catch {
623
+ return { GIT_CONFIG_GLOBAL: "/dev/null" };
624
+ }
625
+ }
626
+ function estimateMessages(messages) {
627
+ return Math.ceil(JSON.stringify(messages).length / 4);
628
+ }
629
+ function integerSetting(value, fallback) {
630
+ if (value === void 0)
631
+ return fallback;
632
+ const parsed = Number(value);
633
+ if (!Number.isInteger(parsed) || parsed <= 0)
634
+ throw new Error("Pi token settings must be positive integers");
635
+ return parsed;
636
+ }
637
+ function messageText(message) {
638
+ const value = message;
639
+ if (value.role === "user")
640
+ return typeof value.content === "string" ? value.content : value.content.map((item) => item.type === "text" ? item.text : "[image]").join(" ");
641
+ if (value.role === "assistant")
642
+ return value.content.map((item) => item.type === "text" ? item.text : item.type === "thinking" ? item.thinking : `[tool:${item.name}]`).join(" ");
643
+ return value.content.map((item) => item.type === "text" ? item.text : "[image]").join(" ");
644
+ }
645
+ function assistantResponseText(message) {
646
+ const value = message;
647
+ if (value.role !== "assistant")
648
+ return messageText(message);
649
+ return value.content.filter((item) => item.type === "text").map((item) => normalizeAssistantText(item.text)).filter(Boolean).join("\n");
650
+ }
651
+ function sameHandoff(left, right) {
652
+ return left.outcome === right.outcome && left.evidence.length === right.evidence.length && left.evidence.every((value, index) => value === right.evidence[index]);
653
+ }
654
+ function hasAgentToolCall(message, name) {
655
+ return message.role === "assistant" && message.content.some((item) => item.type === "toolCall" && item.name === name);
656
+ }
657
+ if (process.argv[1] && resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url)))
658
+ await runPiWorker();
659
+ export {
660
+ assistantResponseText,
661
+ bashTimeoutMs,
662
+ compactMessages,
663
+ compactMessagesToTokenBudget,
664
+ linuxSandboxArgs,
665
+ resolveContextPolicy,
666
+ runBashCommand,
667
+ runPiWorker,
668
+ sandboxWorkspacePaths,
669
+ scopedRunnerPath,
670
+ snapshotModelConfig
671
+ };