privateer-agent 0.15.4 → 0.15.6

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 (229) hide show
  1. package/README.md +11 -0
  2. package/bin/boot-bundle.d.mts +2 -0
  3. package/bin/boot-bundle.mjs +44 -0
  4. package/bin/fresh-supervisor.d.mts +5 -1
  5. package/bin/fresh-supervisor.mjs +47 -10
  6. package/bin/privateer-launch.mjs +27 -3
  7. package/bin/privateer-subagent.mjs +5 -2
  8. package/bin/privateer-verify.mjs +12 -0
  9. package/bin/session-recovery.d.mts +53 -0
  10. package/bin/session-recovery.mjs +240 -0
  11. package/bin/session-seal-preload.mjs +17 -0
  12. package/bin/session-seal.d.mts +25 -0
  13. package/bin/session-seal.mjs +242 -0
  14. package/dist-boot/boot.mjs +3 -0
  15. package/dist-boot/c-27JKSMWL.mjs +1460 -0
  16. package/dist-boot/c-2BMRFV24.mjs +269 -0
  17. package/dist-boot/c-2CTF6JA3.mjs +166 -0
  18. package/dist-boot/c-2G3BBHRJ.mjs +84 -0
  19. package/dist-boot/c-2IDLKXX6.mjs +250 -0
  20. package/dist-boot/c-2NJD5VYM.mjs +8 -0
  21. package/dist-boot/c-2S5EEQPW.mjs +1602 -0
  22. package/dist-boot/c-2WRDCUVI.mjs +25 -0
  23. package/dist-boot/c-2YN3M256.mjs +14 -0
  24. package/dist-boot/c-37GM3GMU.mjs +187 -0
  25. package/dist-boot/c-3STKRSVO.mjs +2480 -0
  26. package/dist-boot/c-3TPV6TQQ.mjs +2320 -0
  27. package/dist-boot/c-3UVHLQDJ.mjs +225 -0
  28. package/dist-boot/c-42PUUZYC.mjs +697 -0
  29. package/dist-boot/c-4D5UMWVW.mjs +683 -0
  30. package/dist-boot/c-4ETZRMTA.mjs +46 -0
  31. package/dist-boot/c-4QT25BD5.mjs +1482 -0
  32. package/dist-boot/c-4WVR32AP.mjs +2579 -0
  33. package/dist-boot/c-5EMM567G.mjs +152 -0
  34. package/dist-boot/c-5FA4CV63.mjs +145 -0
  35. package/dist-boot/c-5GV3X3RB.mjs +14 -0
  36. package/dist-boot/c-5JCEPRIY.mjs +52 -0
  37. package/dist-boot/c-5NDKIIWT.mjs +16 -0
  38. package/dist-boot/c-5QL3AR26.mjs +4665 -0
  39. package/dist-boot/c-5XY6MFKN.mjs +5142 -0
  40. package/dist-boot/c-65UZIZC7.mjs +2897 -0
  41. package/dist-boot/c-6FUXKHOK.mjs +1969 -0
  42. package/dist-boot/c-6JHWQE4V.mjs +18242 -0
  43. package/dist-boot/c-6LOBR4I6.mjs +5280 -0
  44. package/dist-boot/c-6QHOZXKQ.mjs +14394 -0
  45. package/dist-boot/c-6ZO2SADQ.mjs +178 -0
  46. package/dist-boot/c-6ZORVVZP.mjs +1449 -0
  47. package/dist-boot/c-76QH4UCP.mjs +2441 -0
  48. package/dist-boot/c-77GO5L5Y.mjs +20982 -0
  49. package/dist-boot/c-7M23XFTN.mjs +5052 -0
  50. package/dist-boot/c-7TC367E2.mjs +32 -0
  51. package/dist-boot/c-7UOG7POX.mjs +1524 -0
  52. package/dist-boot/c-7VHP3FLN.mjs +376 -0
  53. package/dist-boot/c-A73JHZP2.mjs +13207 -0
  54. package/dist-boot/c-ABXULAFL.mjs +71 -0
  55. package/dist-boot/c-ANDD2AQO.mjs +74 -0
  56. package/dist-boot/c-AOY77AZL.mjs +1430 -0
  57. package/dist-boot/c-AXEPZ22I.mjs +108 -0
  58. package/dist-boot/c-B2Y7VNHU.mjs +427 -0
  59. package/dist-boot/c-B7VJUH73.mjs +77 -0
  60. package/dist-boot/c-BFW6CDVL.mjs +24 -0
  61. package/dist-boot/c-BHNIF2AR.mjs +188 -0
  62. package/dist-boot/c-BKF2O6BL.mjs +23 -0
  63. package/dist-boot/c-BOZXFTZN.mjs +8 -0
  64. package/dist-boot/c-BRNYJWZL.mjs +28 -0
  65. package/dist-boot/c-C3N4Z2HO.mjs +93 -0
  66. package/dist-boot/c-C4IV7ZFG.mjs +717 -0
  67. package/dist-boot/c-C5NK6UYV.mjs +793 -0
  68. package/dist-boot/c-C67644MB.mjs +1659 -0
  69. package/dist-boot/c-C6S2YB53.mjs +620 -0
  70. package/dist-boot/c-CDBEJSBF.mjs +37 -0
  71. package/dist-boot/c-CG47HBKU.mjs +435 -0
  72. package/dist-boot/c-CKCTWCT5.mjs +51 -0
  73. package/dist-boot/c-CN77DCGF.mjs +60 -0
  74. package/dist-boot/c-CRBXNKFO.mjs +1795 -0
  75. package/dist-boot/c-CRIHASQ6.mjs +973 -0
  76. package/dist-boot/c-CU4NGAUO.mjs +3786 -0
  77. package/dist-boot/c-CWRFLGQU.mjs +1883 -0
  78. package/dist-boot/c-CYQB2USO.mjs +32 -0
  79. package/dist-boot/c-DEE67DJO.mjs +379 -0
  80. package/dist-boot/c-DIFDBYOP.mjs +1258 -0
  81. package/dist-boot/c-DOSGVXDZ.mjs +34879 -0
  82. package/dist-boot/c-DR7XQI32.mjs +381 -0
  83. package/dist-boot/c-DTGPSB46.mjs +14666 -0
  84. package/dist-boot/c-DTHDNA4P.mjs +320 -0
  85. package/dist-boot/c-E4Z3Y5B5.mjs +3864 -0
  86. package/dist-boot/c-E66Z2TI7.mjs +203 -0
  87. package/dist-boot/c-EBU6RLRV.mjs +1527 -0
  88. package/dist-boot/c-EBZZNGSF.mjs +432 -0
  89. package/dist-boot/c-EC3LJ2KF.mjs +1032 -0
  90. package/dist-boot/c-EQBKXWNX.mjs +15829 -0
  91. package/dist-boot/c-EUEPIW4S.mjs +574 -0
  92. package/dist-boot/c-EX4YVWAT.mjs +378 -0
  93. package/dist-boot/c-EYZGSAJU.mjs +98 -0
  94. package/dist-boot/c-F75VRKY4.mjs +172 -0
  95. package/dist-boot/c-FH4NXKHV.mjs +177 -0
  96. package/dist-boot/c-FHNUCTEM.mjs +140 -0
  97. package/dist-boot/c-FJ5T42DS.mjs +5349 -0
  98. package/dist-boot/c-FPCNRL7G.mjs +1728 -0
  99. package/dist-boot/c-G4DLN7Q4.mjs +8 -0
  100. package/dist-boot/c-G56GYQFZ.mjs +2507 -0
  101. package/dist-boot/c-GLIOERDQ.mjs +1200 -0
  102. package/dist-boot/c-GMJ5HUBM.mjs +14 -0
  103. package/dist-boot/c-H3HSGMAQ.mjs +461 -0
  104. package/dist-boot/c-HIKTO6P7.mjs +275 -0
  105. package/dist-boot/c-I2MCJ34O.mjs +464 -0
  106. package/dist-boot/c-I3C6LBW4.mjs +765 -0
  107. package/dist-boot/c-I54OKQHW.mjs +387 -0
  108. package/dist-boot/c-IFSP3R4D.mjs +80 -0
  109. package/dist-boot/c-IZK77VB7.mjs +171 -0
  110. package/dist-boot/c-J3Y25UGE.mjs +54 -0
  111. package/dist-boot/c-J5IESS7W.mjs +27750 -0
  112. package/dist-boot/c-JJWZBY7L.mjs +254 -0
  113. package/dist-boot/c-JKTFXTGF.mjs +463 -0
  114. package/dist-boot/c-JN57AXQ4.mjs +77 -0
  115. package/dist-boot/c-KFIO6LUW.mjs +1096 -0
  116. package/dist-boot/c-KIEMEFWW.mjs +478 -0
  117. package/dist-boot/c-KIVXWBYD.mjs +28 -0
  118. package/dist-boot/c-KP6CRIP4.mjs +580 -0
  119. package/dist-boot/c-L26VOJX4.mjs +11558 -0
  120. package/dist-boot/c-L5GHWG5G.mjs +5988 -0
  121. package/dist-boot/c-M7NSQAKK.mjs +353 -0
  122. package/dist-boot/c-MCEWOPBW.mjs +56 -0
  123. package/dist-boot/c-MGPIEG7I.mjs +20 -0
  124. package/dist-boot/c-NREXJV3M.mjs +393 -0
  125. package/dist-boot/c-O5PP6CTX.mjs +162 -0
  126. package/dist-boot/c-OBQDHSXM.mjs +1774 -0
  127. package/dist-boot/c-OLQHHDD4.mjs +21 -0
  128. package/dist-boot/c-OXW4JQQH.mjs +319 -0
  129. package/dist-boot/c-P3D7ZUWN.mjs +1288 -0
  130. package/dist-boot/c-P4PQZVV5.mjs +948 -0
  131. package/dist-boot/c-P63T3XL2.mjs +26373 -0
  132. package/dist-boot/c-P6N5DQGZ.mjs +194 -0
  133. package/dist-boot/c-P7MLKQFC.mjs +58 -0
  134. package/dist-boot/c-PB3PZJL5.mjs +1276 -0
  135. package/dist-boot/c-PTN4S6G2.mjs +1259 -0
  136. package/dist-boot/c-PYCE5J7U.mjs +1083 -0
  137. package/dist-boot/c-Q4HYCRLB.mjs +19410 -0
  138. package/dist-boot/c-QUXMETGG.mjs +68 -0
  139. package/dist-boot/c-RDMJZCOX.mjs +356 -0
  140. package/dist-boot/c-ROGJK76M.mjs +17 -0
  141. package/dist-boot/c-RQJJ26T4.mjs +708 -0
  142. package/dist-boot/c-RSKCUPJF.mjs +7559 -0
  143. package/dist-boot/c-RVJU4O6P.mjs +37 -0
  144. package/dist-boot/c-S2RVHR3M.mjs +165 -0
  145. package/dist-boot/c-SKMK3PEE.mjs +91120 -0
  146. package/dist-boot/c-TI7SM4EG.mjs +20 -0
  147. package/dist-boot/c-TILJ6GXD.mjs +1235 -0
  148. package/dist-boot/c-TT6BCUJD.mjs +114 -0
  149. package/dist-boot/c-U4ITOXAN.mjs +2107 -0
  150. package/dist-boot/c-UGERXVO2.mjs +7120 -0
  151. package/dist-boot/c-UPBH5AXY.mjs +1363 -0
  152. package/dist-boot/c-US2PUNZL.mjs +597 -0
  153. package/dist-boot/c-UU4WZPPE.mjs +20 -0
  154. package/dist-boot/c-UWVIYPQS.mjs +39 -0
  155. package/dist-boot/c-V4RHQBPQ.mjs +17683 -0
  156. package/dist-boot/c-V5MRVK47.mjs +351 -0
  157. package/dist-boot/c-V6CL266R.mjs +1755 -0
  158. package/dist-boot/c-VJTMFKYE.mjs +14975 -0
  159. package/dist-boot/c-VJTRUKIB.mjs +773 -0
  160. package/dist-boot/c-W4IFSHPW.mjs +43 -0
  161. package/dist-boot/c-WETGB2CF.mjs +113 -0
  162. package/dist-boot/c-WO3QSZUU.mjs +1337 -0
  163. package/dist-boot/c-WQLH73TY.mjs +242 -0
  164. package/dist-boot/c-XL735JW5.mjs +500 -0
  165. package/dist-boot/c-Y7HADL5B.mjs +1107 -0
  166. package/dist-boot/c-YGQHSVSK.mjs +41 -0
  167. package/dist-boot/c-YMP2AMEB.mjs +10350 -0
  168. package/dist-boot/c-YRDO2WEF.mjs +12012 -0
  169. package/dist-boot/c-YUSTRATJ.mjs +8 -0
  170. package/dist-boot/c-Z2262R22.mjs +2697 -0
  171. package/dist-boot/c-Z4ALQMJC.mjs +709 -0
  172. package/dist-boot/c-Z5ZUQVUY.mjs +62 -0
  173. package/dist-boot/c-ZDZUKXF7.mjs +874 -0
  174. package/dist-boot/c-ZJYLGIC3.mjs +32 -0
  175. package/dist-boot/c-ZNA5CDMI.mjs +77 -0
  176. package/dist-boot/c-ZSO6DI3M.mjs +204 -0
  177. package/dist-boot/c-ZWUVHKMK.mjs +100 -0
  178. package/dist-boot/c-ZY4MESEW.mjs +832 -0
  179. package/dist-boot/c-ZZ5REI4L.mjs +329 -0
  180. package/dist-boot/cli.mjs +51 -0
  181. package/dist-boot/ext-anthropic-attribution.mjs +207 -0
  182. package/dist-boot/ext-pi-background-tasks.mjs +7234 -0
  183. package/dist-boot/ext-pi-subagents.mjs +37 -0
  184. package/dist-boot/ext-privateer-account.mjs +4426 -0
  185. package/dist-boot/ext-privateer-brand.mjs +5274 -0
  186. package/dist-boot/ext-privateer-codemode.mjs +37 -0
  187. package/dist-boot/ext-privateer-computer.mjs +626 -0
  188. package/dist-boot/ext-privateer-connect.mjs +1862 -0
  189. package/dist-boot/ext-privateer-context.mjs +323 -0
  190. package/dist-boot/ext-privateer-desktop.mjs +92 -0
  191. package/dist-boot/ext-privateer-final-audit.mjs +48 -0
  192. package/dist-boot/ext-privateer-fresh.mjs +81 -0
  193. package/dist-boot/ext-privateer-gate.mjs +5959 -0
  194. package/dist-boot/ext-privateer-hints.mjs +236 -0
  195. package/dist-boot/ext-privateer-media.mjs +2626 -0
  196. package/dist-boot/ext-privateer-models.mjs +3397 -0
  197. package/dist-boot/ext-privateer-posture.mjs +3006 -0
  198. package/dist-boot/ext-privateer-privacy.mjs +4578 -0
  199. package/dist-boot/ext-privateer-recovery.mjs +287 -0
  200. package/dist-boot/ext-privateer-speak.mjs +4754 -0
  201. package/dist-boot/ext-privateer-terminals.mjs +725 -0
  202. package/dist-boot/ext-privateer-tools.mjs +528 -0
  203. package/dist-boot/ext-privateer-truncation.mjs +74 -0
  204. package/dist-boot/ext-privateer-update.mjs +210 -0
  205. package/dist-boot/ext-privateer-vision.mjs +148 -0
  206. package/dist-boot/ext-privateer-web.mjs +543 -0
  207. package/dist-boot/ext-rpiv-ask-user-question.mjs +710 -0
  208. package/dist-boot/manifest.json +9 -0
  209. package/extensions/privateer-brand.ts +3 -1
  210. package/extensions/privateer-context.ts +4 -2
  211. package/extensions/privateer-final-audit.ts +17 -0
  212. package/extensions/privateer-gate.ts +55 -9
  213. package/extensions/privateer-recovery.ts +175 -0
  214. package/extensions/privateer-web.ts +4 -4
  215. package/package.json +3 -1
  216. package/patches/@earendil-works+pi-coding-agent+1.3.0.patch +199 -2
  217. package/patches/pi-background-tasks+2.6.10.patch +91 -7
  218. package/src/cli/chat.ts +7 -1
  219. package/src/config/moatManifest.json +2 -0
  220. package/src/config/whatsNew.json +4 -4
  221. package/src/context.ts +33 -5
  222. package/src/engine/finalAudit.ts +38 -0
  223. package/src/engine/stallWatchdog.ts +8 -1
  224. package/src/providers/account.ts +34 -3
  225. package/src/remote/attentionPush.ts +40 -0
  226. package/src/remote/liveTaskSession.ts +7 -1
  227. package/src/remote/relayClient.ts +38 -4
  228. package/src/remote/remoteBridge.ts +17 -0
  229. package/src/remote/transcriptSnapshot.ts +104 -0
@@ -0,0 +1,1524 @@
1
+ import{createRequire as __pvCR}from"node:module";import{fileURLToPath as __pvF}from"node:url";import{dirname as __pvD}from"node:path";const require=__pvCR(import.meta.url);const __pvUrl=(r)=>new URL(r,import.meta.url).href;const __pvFile=(r)=>__pvF(new URL(r,import.meta.url));
2
+ import {
3
+ sanitizeBinaryOutput
4
+ } from "./c-6ZO2SADQ.mjs";
5
+ import {
6
+ highlightCode,
7
+ keyHint
8
+ } from "./c-CRBXNKFO.mjs";
9
+ import {
10
+ getDocsPath,
11
+ resolvePath
12
+ } from "./c-PTN4S6G2.mjs";
13
+ import {
14
+ DEFAULT_MAX_AGENT_RETRY_DELAY_MS
15
+ } from "./c-BHNIF2AR.mjs";
16
+ import {
17
+ Container,
18
+ Spacer,
19
+ Text,
20
+ getCapabilities,
21
+ getImageDimensions,
22
+ hyperlink,
23
+ imageFallback,
24
+ truncateToWidth
25
+ } from "./c-EQBKXWNX.mjs";
26
+ import {
27
+ typebox_exports
28
+ } from "./c-RQJJ26T4.mjs";
29
+ import {
30
+ __name
31
+ } from "./c-CN77DCGF.mjs";
32
+
33
+ // node_modules/@earendil-works/pi-coding-agent/dist/utils/output-files.js
34
+ import { randomBytes } from "node:crypto";
35
+ import { createWriteStream } from "node:fs";
36
+ import { writeFile } from "node:fs/promises";
37
+ import { tmpdir } from "node:os";
38
+ import { join } from "node:path";
39
+ var OUTPUT_FILE_MODE = 384;
40
+ function createOutputFilePath(prefix, extension) {
41
+ return join(tmpdir(), `${prefix}-${randomBytes(8).toString("hex")}${extension}`);
42
+ }
43
+ __name(createOutputFilePath, "createOutputFilePath");
44
+ async function writeOutputFile(prefix, extension, data) {
45
+ const path = createOutputFilePath(prefix, extension);
46
+ await writeFile(path, data, { mode: OUTPUT_FILE_MODE, flag: "wx" });
47
+ return path;
48
+ }
49
+ __name(writeOutputFile, "writeOutputFile");
50
+ function createOutputFileStream(prefix, extension) {
51
+ const path = createOutputFilePath(prefix, extension);
52
+ return { path, stream: createWriteStream(path, { mode: OUTPUT_FILE_MODE, flags: "wx" }) };
53
+ }
54
+ __name(createOutputFileStream, "createOutputFileStream");
55
+
56
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/truncate.js
57
+ var DEFAULT_MAX_LINES = 2e3;
58
+ var DEFAULT_MAX_BYTES = 50 * 1024;
59
+ var GREP_MAX_LINE_LENGTH = 500;
60
+ function splitLinesForCounting(content) {
61
+ if (content.length === 0) {
62
+ return [];
63
+ }
64
+ const lines = content.split("\n");
65
+ if (content.endsWith("\n")) {
66
+ lines.pop();
67
+ }
68
+ return lines;
69
+ }
70
+ __name(splitLinesForCounting, "splitLinesForCounting");
71
+ function formatSize(bytes) {
72
+ if (bytes < 1024) {
73
+ return `${bytes}B`;
74
+ } else if (bytes < 1024 * 1024) {
75
+ return `${(bytes / 1024).toFixed(1)}KB`;
76
+ } else {
77
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
78
+ }
79
+ }
80
+ __name(formatSize, "formatSize");
81
+ function truncateHead(content, options = {}) {
82
+ const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
83
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
84
+ const totalBytes = Buffer.byteLength(content, "utf-8");
85
+ const lines = splitLinesForCounting(content);
86
+ const totalLines = lines.length;
87
+ if (totalLines <= maxLines && totalBytes <= maxBytes) {
88
+ return {
89
+ content,
90
+ truncated: false,
91
+ truncatedBy: null,
92
+ totalLines,
93
+ totalBytes,
94
+ outputLines: totalLines,
95
+ outputBytes: totalBytes,
96
+ lastLinePartial: false,
97
+ firstLineExceedsLimit: false,
98
+ maxLines,
99
+ maxBytes
100
+ };
101
+ }
102
+ const firstLineBytes = Buffer.byteLength(lines[0], "utf-8");
103
+ if (firstLineBytes > maxBytes) {
104
+ return {
105
+ content: "",
106
+ truncated: true,
107
+ truncatedBy: "bytes",
108
+ totalLines,
109
+ totalBytes,
110
+ outputLines: 0,
111
+ outputBytes: 0,
112
+ lastLinePartial: false,
113
+ firstLineExceedsLimit: true,
114
+ maxLines,
115
+ maxBytes
116
+ };
117
+ }
118
+ const outputLinesArr = [];
119
+ let outputBytesCount = 0;
120
+ let truncatedBy = "lines";
121
+ for (let i = 0; i < lines.length && i < maxLines; i++) {
122
+ const line = lines[i];
123
+ const lineBytes = Buffer.byteLength(line, "utf-8") + (i > 0 ? 1 : 0);
124
+ if (outputBytesCount + lineBytes > maxBytes) {
125
+ truncatedBy = "bytes";
126
+ break;
127
+ }
128
+ outputLinesArr.push(line);
129
+ outputBytesCount += lineBytes;
130
+ }
131
+ if (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {
132
+ truncatedBy = "lines";
133
+ }
134
+ const outputContent = outputLinesArr.join("\n");
135
+ const finalOutputBytes = Buffer.byteLength(outputContent, "utf-8");
136
+ return {
137
+ content: outputContent,
138
+ truncated: true,
139
+ truncatedBy,
140
+ totalLines,
141
+ totalBytes,
142
+ outputLines: outputLinesArr.length,
143
+ outputBytes: finalOutputBytes,
144
+ lastLinePartial: false,
145
+ firstLineExceedsLimit: false,
146
+ maxLines,
147
+ maxBytes
148
+ };
149
+ }
150
+ __name(truncateHead, "truncateHead");
151
+ function truncateTail(content, options = {}) {
152
+ const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
153
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
154
+ const totalBytes = Buffer.byteLength(content, "utf-8");
155
+ const lines = splitLinesForCounting(content);
156
+ const totalLines = lines.length;
157
+ if (totalLines <= maxLines && totalBytes <= maxBytes) {
158
+ return {
159
+ content,
160
+ truncated: false,
161
+ truncatedBy: null,
162
+ totalLines,
163
+ totalBytes,
164
+ outputLines: totalLines,
165
+ outputBytes: totalBytes,
166
+ lastLinePartial: false,
167
+ firstLineExceedsLimit: false,
168
+ maxLines,
169
+ maxBytes
170
+ };
171
+ }
172
+ const outputLinesArr = [];
173
+ let outputBytesCount = 0;
174
+ let truncatedBy = "lines";
175
+ let lastLinePartial = false;
176
+ for (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {
177
+ const line = lines[i];
178
+ const lineBytes = Buffer.byteLength(line, "utf-8") + (outputLinesArr.length > 0 ? 1 : 0);
179
+ if (outputBytesCount + lineBytes > maxBytes) {
180
+ truncatedBy = "bytes";
181
+ if (outputLinesArr.length === 0) {
182
+ const truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);
183
+ outputLinesArr.unshift(truncatedLine);
184
+ outputBytesCount = Buffer.byteLength(truncatedLine, "utf-8");
185
+ lastLinePartial = true;
186
+ }
187
+ break;
188
+ }
189
+ outputLinesArr.unshift(line);
190
+ outputBytesCount += lineBytes;
191
+ }
192
+ if (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {
193
+ truncatedBy = "lines";
194
+ }
195
+ const outputContent = outputLinesArr.join("\n");
196
+ const finalOutputBytes = Buffer.byteLength(outputContent, "utf-8");
197
+ return {
198
+ content: outputContent,
199
+ truncated: true,
200
+ truncatedBy,
201
+ totalLines,
202
+ totalBytes,
203
+ outputLines: outputLinesArr.length,
204
+ outputBytes: finalOutputBytes,
205
+ lastLinePartial,
206
+ firstLineExceedsLimit: false,
207
+ maxLines,
208
+ maxBytes
209
+ };
210
+ }
211
+ __name(truncateTail, "truncateTail");
212
+ function truncateStringToBytesFromEnd(str2, maxBytes) {
213
+ const buf = Buffer.from(str2, "utf-8");
214
+ if (buf.length <= maxBytes) {
215
+ return str2;
216
+ }
217
+ let start = buf.length - maxBytes;
218
+ while (start < buf.length && (buf[start] & 192) === 128) {
219
+ start++;
220
+ }
221
+ return buf.slice(start).toString("utf-8");
222
+ }
223
+ __name(truncateStringToBytesFromEnd, "truncateStringToBytesFromEnd");
224
+ function truncateLine(line, maxChars = GREP_MAX_LINE_LENGTH) {
225
+ if (line.length <= maxChars) {
226
+ return { text: line, wasTruncated: false };
227
+ }
228
+ return { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };
229
+ }
230
+ __name(truncateLine, "truncateLine");
231
+ function truncateMiddle(content, maxBytes) {
232
+ const buf = Buffer.from(content, "utf-8");
233
+ const totalLines = splitLinesForCounting(content).length;
234
+ if (buf.length <= maxBytes) {
235
+ return { content, truncated: false, removedChars: 0, totalBytes: buf.length, totalLines };
236
+ }
237
+ const isBoundary = /* @__PURE__ */ __name((index) => index >= buf.length || (buf[index] & 192) !== 128, "isBoundary");
238
+ let headEnd = Math.floor(maxBytes / 2);
239
+ while (headEnd > 0 && !isBoundary(headEnd))
240
+ headEnd--;
241
+ let tailStart = buf.length - (maxBytes - Math.floor(maxBytes / 2));
242
+ while (tailStart < buf.length && !isBoundary(tailStart))
243
+ tailStart++;
244
+ const head = buf.subarray(0, headEnd).toString("utf-8");
245
+ const tail = buf.subarray(tailStart).toString("utf-8");
246
+ const removedChars = Array.from(buf.subarray(headEnd, tailStart).toString("utf-8")).length;
247
+ return {
248
+ content: `${head}\u2026${removedChars} chars truncated\u2026${tail}`,
249
+ truncated: true,
250
+ removedChars,
251
+ totalBytes: buf.length,
252
+ totalLines
253
+ };
254
+ }
255
+ __name(truncateMiddle, "truncateMiddle");
256
+
257
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/usage-totals.js
258
+ function createUsageTotals() {
259
+ return {
260
+ input: 0,
261
+ output: 0,
262
+ cacheRead: 0,
263
+ cacheWrite: 0,
264
+ cost: 0
265
+ };
266
+ }
267
+ __name(createUsageTotals, "createUsageTotals");
268
+ function addUsageToTotals(totals, usage) {
269
+ totals.input += usage.input;
270
+ totals.output += usage.output;
271
+ totals.cacheRead += usage.cacheRead;
272
+ totals.cacheWrite += usage.cacheWrite;
273
+ totals.cost += usage.cost.total;
274
+ }
275
+ __name(addUsageToTotals, "addUsageToTotals");
276
+ function combineUsage(first, second) {
277
+ return {
278
+ input: first.input + second.input,
279
+ output: first.output + second.output,
280
+ cacheRead: first.cacheRead + second.cacheRead,
281
+ cacheWrite: first.cacheWrite + second.cacheWrite,
282
+ ...first.cacheWrite1h !== void 0 || second.cacheWrite1h !== void 0 ? { cacheWrite1h: (first.cacheWrite1h ?? 0) + (second.cacheWrite1h ?? 0) } : {},
283
+ ...first.reasoning !== void 0 || second.reasoning !== void 0 ? { reasoning: (first.reasoning ?? 0) + (second.reasoning ?? 0) } : {},
284
+ totalTokens: first.totalTokens + second.totalTokens,
285
+ cost: {
286
+ input: first.cost.input + second.cost.input,
287
+ output: first.cost.output + second.cost.output,
288
+ cacheRead: first.cost.cacheRead + second.cost.cacheRead,
289
+ cacheWrite: first.cost.cacheWrite + second.cost.cacheWrite,
290
+ total: first.cost.total + second.cost.total
291
+ }
292
+ };
293
+ }
294
+ __name(combineUsage, "combineUsage");
295
+ function getUsageCostBreakdown(entries) {
296
+ const totalsByKey = /* @__PURE__ */ new Map();
297
+ for (const entry of entries) {
298
+ let key;
299
+ let usage;
300
+ if (entry.type === "message" && entry.message.role === "assistant") {
301
+ key = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;
302
+ usage = entry.message.usage;
303
+ } else if (entry.type === "usage") {
304
+ key = `${entry.provider}/${entry.model}`;
305
+ usage = entry.usage;
306
+ } else if (entry.type === "message" && entry.message.role === "toolResult" && entry.message.usage) {
307
+ key = "Tools/summaries";
308
+ usage = entry.message.usage;
309
+ } else if ((entry.type === "branch_summary" || entry.type === "compaction") && entry.usage) {
310
+ key = "Tools/summaries";
311
+ usage = entry.usage;
312
+ }
313
+ if (!key || !usage)
314
+ continue;
315
+ let totals = totalsByKey.get(key);
316
+ if (!totals) {
317
+ totals = createUsageTotals();
318
+ totalsByKey.set(key, totals);
319
+ }
320
+ addUsageToTotals(totals, usage);
321
+ }
322
+ return Array.from(totalsByKey, ([key, totals]) => ({
323
+ key,
324
+ cost: totals.cost,
325
+ tokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite
326
+ })).filter((entry) => entry.cost > 0 || entry.tokens > 0).sort((a, b) => b.cost - a.cost);
327
+ }
328
+ __name(getUsageCostBreakdown, "getUsageCostBreakdown");
329
+
330
+ // node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/visual-truncate.js
331
+ function truncateToVisualLines(text, maxVisualLines, width, paddingX = 0, keep = "end") {
332
+ if (!text) {
333
+ return { visualLines: [], skippedCount: 0 };
334
+ }
335
+ const tempText = new Text(text, paddingX, 0);
336
+ const allVisualLines = tempText.render(width);
337
+ if (allVisualLines.length <= maxVisualLines) {
338
+ return { visualLines: allVisualLines, skippedCount: 0 };
339
+ }
340
+ const truncatedLines = keep === "start" ? allVisualLines.slice(0, maxVisualLines) : allVisualLines.slice(-maxVisualLines);
341
+ const skippedCount = allVisualLines.length - maxVisualLines;
342
+ return { visualLines: truncatedLines, skippedCount };
343
+ }
344
+ __name(truncateToVisualLines, "truncateToVisualLines");
345
+ var VisualLinePreview = class {
346
+ static {
347
+ __name(this, "VisualLinePreview");
348
+ }
349
+ options;
350
+ cachedWidth;
351
+ cachedLines;
352
+ constructor(options) {
353
+ this.options = options;
354
+ }
355
+ render(width) {
356
+ if (this.cachedLines === void 0 || this.cachedWidth !== width) {
357
+ const { text, maxVisualLines, keep, formatHint } = this.options;
358
+ const preview = truncateToVisualLines(text, maxVisualLines, width, 0, keep);
359
+ const lines = preview.visualLines;
360
+ if (preview.skippedCount > 0) {
361
+ const hint = truncateToWidth(formatHint(preview.skippedCount), width, "...");
362
+ this.cachedLines = keep === "start" ? [...lines, hint] : [hint, ...lines];
363
+ } else {
364
+ this.cachedLines = lines;
365
+ }
366
+ this.cachedWidth = width;
367
+ }
368
+ return this.cachedLines;
369
+ }
370
+ invalidate() {
371
+ this.cachedWidth = void 0;
372
+ this.cachedLines = void 0;
373
+ }
374
+ };
375
+
376
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js
377
+ import * as os from "node:os";
378
+ import { pathToFileURL } from "node:url";
379
+
380
+ // node_modules/@earendil-works/pi-coding-agent/dist/utils/ansi.js
381
+ var ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
382
+ var OSC_START = "\\u001B\\]";
383
+ var CSI_START = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?";
384
+ var CSI_FINAL = "[\\dA-PR-TZcf-nq-uy=><~]";
385
+ var ansiRegex = new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`, "g");
386
+ var unfinishedAnsiAtEndRegex = new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`);
387
+ var MAX_PENDING_ANSI_LENGTH = 256;
388
+ function splitIncompleteAnsiSuffix(value) {
389
+ if (!value.includes("\x1B") && !value.includes("\x9B")) {
390
+ return { complete: value, pending: "" };
391
+ }
392
+ const windowStart = Math.max(0, value.length - MAX_PENDING_ANSI_LENGTH);
393
+ const match = unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));
394
+ if (!match) {
395
+ return { complete: value, pending: "" };
396
+ }
397
+ const splitAt = windowStart + match.index;
398
+ return { complete: value.slice(0, splitAt), pending: value.slice(splitAt) };
399
+ }
400
+ __name(splitIncompleteAnsiSuffix, "splitIncompleteAnsiSuffix");
401
+ function stripAnsi(value) {
402
+ if (typeof value !== "string") {
403
+ throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);
404
+ }
405
+ if (!value.includes("\x1B") && !value.includes("\x9B")) {
406
+ return value;
407
+ }
408
+ return value.replace(ansiRegex, "");
409
+ }
410
+ __name(stripAnsi, "stripAnsi");
411
+
412
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js
413
+ function shortenPath(path) {
414
+ if (typeof path !== "string")
415
+ return "";
416
+ const home = os.homedir();
417
+ if (path.startsWith(home)) {
418
+ return `~${path.slice(home.length)}`;
419
+ }
420
+ return path;
421
+ }
422
+ __name(shortenPath, "shortenPath");
423
+ function linkPath(styledText, rawPath, cwd) {
424
+ if (!getCapabilities().hyperlinks)
425
+ return styledText;
426
+ const absolutePath = resolvePath(rawPath, cwd);
427
+ return hyperlink(styledText, pathToFileURL(absolutePath).href);
428
+ }
429
+ __name(linkPath, "linkPath");
430
+ function str(value) {
431
+ if (typeof value === "string")
432
+ return value;
433
+ if (value == null)
434
+ return "";
435
+ return null;
436
+ }
437
+ __name(str, "str");
438
+ function parseLineNumber(value) {
439
+ if (typeof value === "string" && value.trim() !== "")
440
+ value = Number(value);
441
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
442
+ }
443
+ __name(parseLineNumber, "parseLineNumber");
444
+ function formatReadLineRange(offset, limit) {
445
+ if (offset == null && limit == null)
446
+ return "";
447
+ const start = offset == null ? 1 : parseLineNumber(offset);
448
+ if (start === void 0)
449
+ return "";
450
+ if (limit == null)
451
+ return `:${start}`;
452
+ const count = parseLineNumber(limit);
453
+ if (count === void 0)
454
+ return "";
455
+ const end = start + count - 1;
456
+ return `:${start}${end ? `-${end}` : ""}`;
457
+ }
458
+ __name(formatReadLineRange, "formatReadLineRange");
459
+ function replaceTabs(text) {
460
+ return text.replace(/\t/g, " ");
461
+ }
462
+ __name(replaceTabs, "replaceTabs");
463
+ function normalizeDisplayText(text) {
464
+ return text.replace(/\r/g, "");
465
+ }
466
+ __name(normalizeDisplayText, "normalizeDisplayText");
467
+ function getTextOutput(result, showImages) {
468
+ if (!result)
469
+ return "";
470
+ const textBlocks = result.content.filter((c) => c.type === "text");
471
+ const imageBlocks = result.content.filter((c) => c.type === "image");
472
+ let output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || "")).replace(/\r/g, "")).join("\n");
473
+ const caps = getCapabilities();
474
+ if (imageBlocks.length > 0 && (!caps.images || !showImages)) {
475
+ const imageIndicators = imageBlocks.map((img) => {
476
+ const mimeType = img.mimeType ?? "image/unknown";
477
+ const dims = img.data && img.mimeType ? getImageDimensions(img.data, img.mimeType) ?? void 0 : void 0;
478
+ return imageFallback(mimeType, dims);
479
+ }).join("\n");
480
+ output = output ? `${output}
481
+ ${imageIndicators}` : imageIndicators;
482
+ }
483
+ return output;
484
+ }
485
+ __name(getTextOutput, "getTextOutput");
486
+ var COLLAPSED_ARGS_CHARS = 100;
487
+ function formatToolCallWithArgs(title, args, theme, expanded) {
488
+ const header = theme.fg("toolTitle", theme.bold(title));
489
+ if (args == null)
490
+ return header;
491
+ const entries = typeof args === "object" && !Array.isArray(args) ? Object.entries(args) : [["args", args]];
492
+ if (entries.length === 0)
493
+ return header;
494
+ if (expanded) {
495
+ const lines = entries.map(([key, value]) => {
496
+ const text = typeof value === "string" ? value : JSON.stringify(value, null, 2) ?? String(value);
497
+ return ` ${key}: ${replaceTabs(text).replace(/\r/g, "").split("\n").join("\n ")}`;
498
+ });
499
+ return `${header}
500
+ ${theme.fg("muted", lines.join("\n"))}`;
501
+ }
502
+ const pairs = entries.map(([key, value]) => `${key}=${JSON.stringify(value) ?? String(value)}`).join(" ");
503
+ const preview = pairs.length > COLLAPSED_ARGS_CHARS ? `${pairs.slice(0, COLLAPSED_ARGS_CHARS - 3)}...` : pairs;
504
+ return `${header} ${theme.fg("muted", preview)}`;
505
+ }
506
+ __name(formatToolCallWithArgs, "formatToolCallWithArgs");
507
+ function formatToolDuration(ms) {
508
+ const seconds = ms / 1e3;
509
+ if (seconds < 60)
510
+ return `${seconds.toFixed(1)}s`;
511
+ const totalSeconds = Math.floor(seconds);
512
+ const minutes = Math.floor(totalSeconds / 60);
513
+ const remainder = totalSeconds % 60;
514
+ if (minutes < 60)
515
+ return `${minutes}m ${remainder}s`;
516
+ return `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;
517
+ }
518
+ __name(formatToolDuration, "formatToolDuration");
519
+ function startToolTimer(context) {
520
+ const state = context.state;
521
+ if (context.executionStarted && state.startedAt === void 0) {
522
+ state.startedAt = Date.now();
523
+ state.endedAt = void 0;
524
+ }
525
+ }
526
+ __name(startToolTimer, "startToolTimer");
527
+ function toolTimerText(context, isPartial) {
528
+ const state = context.state;
529
+ if (state.startedAt !== void 0 && isPartial && !state.interval) {
530
+ state.interval = setInterval(() => context.invalidate(), 1e3);
531
+ }
532
+ if (!isPartial || context.isError) {
533
+ state.endedAt ??= Date.now();
534
+ if (state.interval) {
535
+ clearInterval(state.interval);
536
+ state.interval = void 0;
537
+ }
538
+ }
539
+ if (!isPartial && context.durationMs !== void 0)
540
+ return `Took ${formatToolDuration(context.durationMs)}`;
541
+ if (state.startedAt === void 0)
542
+ return void 0;
543
+ const endTime = state.endedAt ?? Date.now();
544
+ return `${isPartial ? "Elapsed" : "Took"} ${formatToolDuration(endTime - state.startedAt)}`;
545
+ }
546
+ __name(toolTimerText, "toolTimerText");
547
+ function invalidArgText(theme) {
548
+ return theme.fg("error", "[invalid arg]");
549
+ }
550
+ __name(invalidArgText, "invalidArgText");
551
+ function renderToolPath(rawPath, theme, cwd, options) {
552
+ if (rawPath === null)
553
+ return invalidArgText(theme);
554
+ const value = rawPath || options?.emptyFallback;
555
+ if (!value)
556
+ return theme.fg("toolOutput", "...");
557
+ return linkPath(theme.fg("accent", shortenPath(value)), value, cwd);
558
+ }
559
+ __name(renderToolPath, "renderToolPath");
560
+
561
+ // node_modules/@earendil-works/pi-codemode/dist/identifier.js
562
+ function toCodemodeIdentifier(name) {
563
+ let identifier = "";
564
+ for (const char of name) {
565
+ const valid = identifier === "" ? /^[A-Za-z_$]$/.test(char) : /^[A-Za-z0-9_$]$/.test(char);
566
+ identifier += valid ? char : "_";
567
+ }
568
+ return identifier === "" ? "_" : identifier;
569
+ }
570
+ __name(toCodemodeIdentifier, "toCodemodeIdentifier");
571
+
572
+ // node_modules/@earendil-works/pi-codemode/dist/declarations.js
573
+ var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
574
+ var INDENT = " ";
575
+ var DEFAULT_INPUT_SCHEMA_MAX_CHARS = 16e3;
576
+ var MAX_REF_EXPANSIONS = 32;
577
+ var TAG_KEYWORDS = [
578
+ "minimum",
579
+ "exclusiveMinimum",
580
+ "maximum",
581
+ "exclusiveMaximum",
582
+ "multipleOf",
583
+ "minLength",
584
+ "maxLength",
585
+ "pattern",
586
+ "format",
587
+ "minItems",
588
+ "maxItems"
589
+ ];
590
+ var LOWER_BOUNDS = /* @__PURE__ */ new Set(["minimum", "exclusiveMinimum", "minLength", "minItems"]);
591
+ var UPPER_BOUNDS = /* @__PURE__ */ new Set(["maximum", "exclusiveMaximum", "maxLength", "maxItems"]);
592
+ var MAX_TAG_CHARS = 80;
593
+ var LINE_TERMINATORS = /[\r\n\u2028\u2029]/g;
594
+ function renderToolSignature(tool, options = {}) {
595
+ const input = tool.inputSchema === void 0 ? "unknown" : schemaToType(tool.inputSchema, { maxChars: options.inputMaxChars ?? DEFAULT_INPUT_SCHEMA_MAX_CHARS });
596
+ return `${toCodemodeIdentifier(tool.name)}(args: ${input}): Promise<${renderToolOutputType(tool.outputSchema)}>;`;
597
+ }
598
+ __name(renderToolSignature, "renderToolSignature");
599
+ function renderToolSample(tool, options = {}) {
600
+ const declaration = `declare const tools: { ${renderToolSignature(tool, options)} };`;
601
+ return `${tool.description?.trim() ?? ""}
602
+
603
+ codemode tool declaration:
604
+ \`\`\`ts
605
+ ${declaration}
606
+ \`\`\``;
607
+ }
608
+ __name(renderToolSample, "renderToolSample");
609
+ function renderToolOutputType(schema) {
610
+ return schema === void 0 ? "unknown" : schemaToType(schema);
611
+ }
612
+ __name(renderToolOutputType, "renderToolOutputType");
613
+ function propertyKey(name) {
614
+ return IDENTIFIER.test(name) ? name : JSON.stringify(name);
615
+ }
616
+ __name(propertyKey, "propertyKey");
617
+ function union(types) {
618
+ const unique = [...new Set(types)];
619
+ if (unique.includes("unknown"))
620
+ return "unknown";
621
+ return unique.length === 0 ? "never" : unique.join(" | ");
622
+ }
623
+ __name(union, "union");
624
+ function schemaToType(schema, options = {}) {
625
+ const render = /* @__PURE__ */ __name((tags) => toType(schema, { root: schema, resolving: /* @__PURE__ */ new Set(), expansions: 0, tags }), "render");
626
+ const type = render(true);
627
+ if (options.maxChars === void 0 || type.length <= options.maxChars)
628
+ return type;
629
+ const untagged = render(false);
630
+ return untagged.length <= options.maxChars ? untagged : "unknown";
631
+ }
632
+ __name(schemaToType, "schemaToType");
633
+ function resolveRef(ref, root) {
634
+ if (ref !== "#" && !ref.startsWith("#/"))
635
+ return void 0;
636
+ let current = root;
637
+ for (const segment of ref.slice(2).split("/").filter(Boolean)) {
638
+ const key = decodeURIComponent(segment).replaceAll("~1", "/").replaceAll("~0", "~");
639
+ if (typeof current !== "object" || current === null || Array.isArray(current) || !(key in current)) {
640
+ return void 0;
641
+ }
642
+ current = current[key];
643
+ }
644
+ if (typeof current === "boolean")
645
+ return current;
646
+ return typeof current === "object" && current !== null && !Array.isArray(current) ? current : void 0;
647
+ }
648
+ __name(resolveRef, "resolveRef");
649
+ function toType(schema, context) {
650
+ if (schema === true)
651
+ return "unknown";
652
+ if (schema === false)
653
+ return "never";
654
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
655
+ return "unknown";
656
+ if (typeof schema.$ref === "string") {
657
+ const ref = schema.$ref;
658
+ if (context.resolving.has(ref) || context.expansions >= MAX_REF_EXPANSIONS)
659
+ return "unknown";
660
+ const target = resolveRef(ref, context.root);
661
+ if (target === void 0)
662
+ return "unknown";
663
+ context.expansions++;
664
+ context.resolving.add(ref);
665
+ try {
666
+ return toType(target, context);
667
+ } finally {
668
+ context.resolving.delete(ref);
669
+ }
670
+ }
671
+ if ("const" in schema)
672
+ return JSON.stringify(schema.const) ?? "unknown";
673
+ if (Array.isArray(schema.enum))
674
+ return union(schema.enum.map((value) => JSON.stringify(value) ?? "unknown"));
675
+ const variants = Array.isArray(schema.anyOf) ? schema.anyOf : Array.isArray(schema.oneOf) ? schema.oneOf : void 0;
676
+ if (variants)
677
+ return union(variants.map((variant) => toType(variant, context)));
678
+ if (Array.isArray(schema.allOf)) {
679
+ const parts = schema.allOf.map((part) => toType(part, context)).filter((part) => part !== "unknown");
680
+ return parts.length === 0 ? "unknown" : parts.map((part) => part.includes(" | ") ? `(${part})` : part).join(" & ");
681
+ }
682
+ const type = schema.type;
683
+ if (Array.isArray(type))
684
+ return union(type.map((entry) => toType({ ...schema, type: entry }, context)));
685
+ switch (type) {
686
+ case "string":
687
+ return "string";
688
+ case "number":
689
+ case "integer":
690
+ return "number";
691
+ case "boolean":
692
+ return "boolean";
693
+ case "null":
694
+ return "null";
695
+ case "array":
696
+ return arrayType(schema, context);
697
+ case "object":
698
+ return objectType(schema, context);
699
+ case void 0:
700
+ if ("properties" in schema || "additionalProperties" in schema || "required" in schema) {
701
+ return objectType(schema, context);
702
+ }
703
+ if ("items" in schema || "prefixItems" in schema)
704
+ return arrayType(schema, context);
705
+ return "unknown";
706
+ default:
707
+ return "unknown";
708
+ }
709
+ }
710
+ __name(toType, "toType");
711
+ function arrayType(schema, context) {
712
+ if (schema.items !== void 0 && !Array.isArray(schema.items)) {
713
+ return `Array<${toType(schema.items, context)}>`;
714
+ }
715
+ const tuple = Array.isArray(schema.prefixItems) ? schema.prefixItems : Array.isArray(schema.items) ? schema.items : [];
716
+ if (tuple.length > 0)
717
+ return `[${tuple.map((item) => toType(item, context)).join(", ")}]`;
718
+ return "unknown[]";
719
+ }
720
+ __name(arrayType, "arrayType");
721
+ function descriptionOf(property) {
722
+ const description = property?.description;
723
+ return typeof description === "string" ? description.trim() : "";
724
+ }
725
+ __name(descriptionOf, "descriptionOf");
726
+ function constraintTags(schema) {
727
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
728
+ return "";
729
+ const property = schema;
730
+ const variants = Array.isArray(property.anyOf) ? property.anyOf : property.oneOf;
731
+ const nonNull = Array.isArray(variants) ? variants.filter((variant) => variant?.type !== "null") : [];
732
+ const branch = nonNull.length === 1 ? nonNull[0] : void 0;
733
+ const branches = typeof branch === "object" && branch !== null && !Array.isArray(branch) ? [property, branch] : [property];
734
+ const schemas = branches.map((schema2) => ({
735
+ ...schema2,
736
+ ...schema2.exclusiveMinimum === true ? { minimum: void 0, exclusiveMinimum: schema2.minimum } : {},
737
+ ...schema2.exclusiveMaximum === true ? { maximum: void 0, exclusiveMaximum: schema2.maximum } : {}
738
+ }));
739
+ const tags = [];
740
+ const isInteger = /* @__PURE__ */ __name((type) => type === "integer" || Array.isArray(type) && type.includes("integer"), "isInteger");
741
+ if (schemas.some((schema2) => isInteger(schema2.type)))
742
+ tags.push("@integer");
743
+ for (const keyword of TAG_KEYWORDS) {
744
+ const values = schemas.map((schema2) => schema2[keyword]);
745
+ if (LOWER_BOUNDS.has(keyword) || UPPER_BOUNDS.has(keyword)) {
746
+ const numbers = values.filter((value) => typeof value === "number");
747
+ if (numbers.length === 0)
748
+ continue;
749
+ tags.push(`@${keyword} ${LOWER_BOUNDS.has(keyword) ? Math.max(...numbers) : Math.min(...numbers)}`);
750
+ continue;
751
+ }
752
+ for (const value of new Set(values)) {
753
+ if (typeof value === "number" || typeof value === "string")
754
+ tags.push(`@${keyword} ${value}`);
755
+ }
756
+ }
757
+ if (schemas.some((schema2) => schema2.uniqueItems === true))
758
+ tags.push("@uniqueItems");
759
+ if (property.default !== void 0 && property.default !== null) {
760
+ tags.push(`@default ${JSON.stringify(property.default)}`);
761
+ }
762
+ if (property.deprecated === true)
763
+ tags.push("@deprecated");
764
+ return tags.filter((tag) => tag.length <= MAX_TAG_CHARS).map((tag) => tag.replace(LINE_TERMINATORS, (char) => `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`)).join(" ");
765
+ }
766
+ __name(constraintTags, "constraintTags");
767
+ function objectType(schema, context) {
768
+ const properties = typeof schema.properties === "object" && schema.properties !== null && !Array.isArray(schema.properties) ? schema.properties : {};
769
+ const required = new Set(Array.isArray(schema.required) ? schema.required : []);
770
+ const names = Object.keys(properties).sort();
771
+ const members = names.map((name) => {
772
+ const optional = required.has(name) ? "" : "?";
773
+ return `${propertyKey(name)}${optional}: ${toType(properties[name], context)};`;
774
+ });
775
+ const additional = schema.additionalProperties;
776
+ if (additional !== void 0 && additional !== false) {
777
+ const type = additional === true ? "unknown" : toType(additional, context);
778
+ members.push(`[key: string]: ${type};`);
779
+ } else if (additional === void 0 && names.length === 0) {
780
+ members.push("[key: string]: unknown;");
781
+ }
782
+ if (members.length === 0)
783
+ return "{}";
784
+ const comments = names.map((name) => {
785
+ const lines2 = descriptionOf(properties[name]).split(LINE_TERMINATORS).map((line) => line.trim()).filter(Boolean);
786
+ const tags = context.tags ? constraintTags(properties[name]) : "";
787
+ return tags ? [...lines2, tags] : lines2;
788
+ });
789
+ if (!comments.some((comment) => comment.length > 0))
790
+ return `{ ${members.join(" ")} }`;
791
+ const lines = ["{"];
792
+ comments.forEach((comment, index) => {
793
+ for (const line of comment)
794
+ lines.push(`${INDENT}// ${line}`);
795
+ lines.push(`${INDENT}${members[index].replaceAll("\n", `
796
+ ${INDENT}`)}`);
797
+ });
798
+ for (const member of members.slice(names.length))
799
+ lines.push(`${INDENT}${member}`);
800
+ lines.push("}");
801
+ return lines.join("\n");
802
+ }
803
+ __name(objectType, "objectType");
804
+
805
+ // node_modules/@earendil-works/pi-codemode/dist/source.js
806
+ var CODEMODE_OPTIONS_PREFIX = "// @options:";
807
+ var SUPPORTED_FIELDS = ["max_output_tokens", "timeout_ms"];
808
+ var SUPPORTED_FIELDS_TEXT = "`max_output_tokens` and `timeout_ms`";
809
+ var MAX_TIMEOUT_MS = 2147483647;
810
+ var CODEMODE_SOURCE_GRAMMAR = String.raw`
811
+ start: options_source | plain_source
812
+ options_source: OPTIONS_LINE NEWLINE SOURCE
813
+ plain_source: SOURCE
814
+
815
+ OPTIONS_LINE: /[ \t]*\/\/ @options:[^\r\n]*/
816
+ NEWLINE: /\r?\n/
817
+ SOURCE: /[\s\S]+/
818
+ `;
819
+ var CodemodeSourceError = class extends Error {
820
+ static {
821
+ __name(this, "CodemodeSourceError");
822
+ }
823
+ constructor(message) {
824
+ super(message);
825
+ this.name = "CodemodeSourceError";
826
+ }
827
+ };
828
+ function isSafeInteger(value) {
829
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
830
+ }
831
+ __name(isSafeInteger, "isSafeInteger");
832
+ function parseOptions(directive) {
833
+ if (directive === "") {
834
+ throw new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);
835
+ }
836
+ let value;
837
+ try {
838
+ value = JSON.parse(directive);
839
+ } catch (error) {
840
+ throw new CodemodeSourceError(`@options must be valid JSON with supported fields ${SUPPORTED_FIELDS_TEXT}: ${error instanceof Error ? error.message : String(error)}`);
841
+ }
842
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
843
+ throw new CodemodeSourceError(`@options must be a JSON object with supported fields ${SUPPORTED_FIELDS_TEXT}`);
844
+ }
845
+ const fields = value;
846
+ for (const key of Object.keys(fields)) {
847
+ if (!SUPPORTED_FIELDS.includes(key)) {
848
+ throw new CodemodeSourceError(`@options only supports ${SUPPORTED_FIELDS_TEXT}; got \`${key}\``);
849
+ }
850
+ }
851
+ const options = {};
852
+ const { max_output_tokens, timeout_ms } = fields;
853
+ if (max_output_tokens !== void 0) {
854
+ if (!isSafeInteger(max_output_tokens)) {
855
+ throw new CodemodeSourceError("@options field `max_output_tokens` must be a non-negative safe integer");
856
+ }
857
+ options.maxOutputTokens = max_output_tokens;
858
+ }
859
+ if (timeout_ms !== void 0) {
860
+ if (!isSafeInteger(timeout_ms) || timeout_ms === 0 || timeout_ms > MAX_TIMEOUT_MS) {
861
+ throw new CodemodeSourceError(`@options field \`timeout_ms\` must be a positive integer up to ${MAX_TIMEOUT_MS}`);
862
+ }
863
+ options.timeoutMs = timeout_ms;
864
+ }
865
+ return options;
866
+ }
867
+ __name(parseOptions, "parseOptions");
868
+ function parseCodemodeSource(input) {
869
+ if (input.trim() === "") {
870
+ throw new CodemodeSourceError('Expected JavaScript source text (non-empty). Provide JS only, optionally with a first line `// @options: {"max_output_tokens": 1000}`.');
871
+ }
872
+ const lines = input.split("\n");
873
+ const misplaced = lines.findIndex((line, index) => index > 0 && line.trimStart().startsWith(CODEMODE_OPTIONS_PREFIX));
874
+ if (misplaced !== -1) {
875
+ throw new CodemodeSourceError(`The ${CODEMODE_OPTIONS_PREFIX} line must be the first line of the input; found one on line ${misplaced + 1}`);
876
+ }
877
+ const newline = input.indexOf("\n");
878
+ const firstLine = lines[0].replace(/\r$/, "");
879
+ const trimmed = firstLine.trimStart();
880
+ if (!trimmed.startsWith(CODEMODE_OPTIONS_PREFIX))
881
+ return { code: input, options: {} };
882
+ const code = newline === -1 ? "" : input.slice(newline);
883
+ if (code.trim() === "") {
884
+ throw new CodemodeSourceError("The @options line must be followed by JavaScript source on subsequent lines");
885
+ }
886
+ return { code, options: parseOptions(trimmed.slice(CODEMODE_OPTIONS_PREFIX.length).trim()) };
887
+ }
888
+ __name(parseCodemodeSource, "parseCodemodeSource");
889
+
890
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/tool-search/tool.js
891
+ var TOOL_SEARCH_TOOL_NAME = "tool_search";
892
+ var DEFAULT_TOOL_SEARCH_LIMIT = 8;
893
+ var STOP_WORDS = /* @__PURE__ */ new Set([
894
+ "a",
895
+ "an",
896
+ "and",
897
+ "are",
898
+ "as",
899
+ "at",
900
+ "be",
901
+ "by",
902
+ "for",
903
+ "from",
904
+ "in",
905
+ "is",
906
+ "it",
907
+ "of",
908
+ "on",
909
+ "or",
910
+ "that",
911
+ "the",
912
+ "this",
913
+ "to",
914
+ "with"
915
+ ]);
916
+ function stem(term) {
917
+ if (term.length > 4 && term.endsWith("ies"))
918
+ return `${term.slice(0, -3)}y`;
919
+ if (term.length > 4 && /(ches|shes|sses|xes|zes)$/.test(term))
920
+ return term.slice(0, -2);
921
+ if (term.length > 3 && term.endsWith("s") && !term.endsWith("ss"))
922
+ return term.slice(0, -1);
923
+ return term;
924
+ }
925
+ __name(stem, "stem");
926
+ function tokenize(text) {
927
+ return text.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter((term) => term.length > 0 && !STOP_WORDS.has(term)).map(stem);
928
+ }
929
+ __name(tokenize, "tokenize");
930
+ function isObject(value) {
931
+ return typeof value === "object" && value !== null && !Array.isArray(value);
932
+ }
933
+ __name(isObject, "isObject");
934
+ function schemaText(schema, parts) {
935
+ if (!isObject(schema))
936
+ return;
937
+ if (typeof schema.description === "string")
938
+ parts.push(schema.description);
939
+ if (isObject(schema.properties)) {
940
+ for (const [name, property] of Object.entries(schema.properties)) {
941
+ parts.push(name);
942
+ schemaText(property, parts);
943
+ }
944
+ }
945
+ schemaText(schema.items, parts);
946
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
947
+ const variants = schema[key];
948
+ if (Array.isArray(variants))
949
+ for (const variant of variants)
950
+ schemaText(variant, parts);
951
+ }
952
+ }
953
+ __name(schemaText, "schemaText");
954
+ function createToolSearchDocument(tool, namespace) {
955
+ const parts = [tool.name, tool.name.replaceAll("_", " "), tool.description];
956
+ schemaText(tool.parameters, parts);
957
+ if (namespace)
958
+ parts.push(namespace.name, namespace.description ?? "", namespace.instructions ?? "");
959
+ return { name: tool.name, text: parts.filter((part) => part.trim()).join(" ") };
960
+ }
961
+ __name(createToolSearchDocument, "createToolSearchDocument");
962
+ var Bm25Ranker = class {
963
+ static {
964
+ __name(this, "Bm25Ranker");
965
+ }
966
+ k1;
967
+ b;
968
+ constructor(options = {}) {
969
+ this.k1 = options.k1 ?? 1.2;
970
+ this.b = options.b ?? 0.75;
971
+ }
972
+ rank(query, documents, limit) {
973
+ const queryTerms = [...new Set(tokenize(query))];
974
+ if (queryTerms.length === 0 || documents.length === 0 || limit <= 0)
975
+ return [];
976
+ const termCounts = documents.map((document) => {
977
+ const counts = /* @__PURE__ */ new Map();
978
+ for (const term of tokenize(document.text))
979
+ counts.set(term, (counts.get(term) ?? 0) + 1);
980
+ return counts;
981
+ });
982
+ const lengths = termCounts.map((counts) => [...counts.values()].reduce((sum, count) => sum + count, 0));
983
+ const averageLength = lengths.reduce((sum, length) => sum + length, 0) / documents.length || 1;
984
+ const idf = new Map(queryTerms.map((term) => {
985
+ const frequency = termCounts.filter((counts) => counts.has(term)).length;
986
+ return [term, Math.log(1 + (documents.length - frequency + 0.5) / (frequency + 0.5))];
987
+ }));
988
+ const matches = [];
989
+ documents.forEach((document, index) => {
990
+ let score = 0;
991
+ for (const term of queryTerms) {
992
+ const count = termCounts[index].get(term);
993
+ if (!count)
994
+ continue;
995
+ const norm = this.k1 * (1 - this.b + this.b * lengths[index] / averageLength);
996
+ score += (idf.get(term) ?? 0) * (count * (this.k1 + 1) / (count + norm));
997
+ }
998
+ if (score > 0)
999
+ matches.push({ name: document.name, score });
1000
+ });
1001
+ return matches.sort((a, b) => b.score - a.score).slice(0, limit);
1002
+ }
1003
+ };
1004
+ var toolSearchSchema = typebox_exports.Object({
1005
+ query: typebox_exports.String({ description: "Search query for deferred tools." }),
1006
+ limit: typebox_exports.Optional(typebox_exports.Number({ description: `Maximum number of tools to return. Defaults to ${DEFAULT_TOOL_SEARCH_LIMIT}.` }))
1007
+ });
1008
+ function isSearchable(exposure) {
1009
+ return exposure === "codemode" || exposure === "deferred";
1010
+ }
1011
+ __name(isSearchable, "isSearchable");
1012
+ function searchAndLoad(tools, query, limit) {
1013
+ const active = tools.getActiveTools();
1014
+ const candidates = tools.getAllTools().filter((tool) => isSearchable(tool.exposure) && !active.includes(tool.name));
1015
+ const documents = candidates.map((tool) => createToolSearchDocument(tool, tool.namespace));
1016
+ const matches = new Bm25Ranker().rank(query, documents, limit);
1017
+ if (matches.length > 0)
1018
+ tools.setActiveTools([...active, ...matches.map((match) => match.name)]);
1019
+ return matches.map((match) => ({
1020
+ name: match.name,
1021
+ description: candidates.find((tool) => tool.name === match.name)?.description ?? ""
1022
+ }));
1023
+ }
1024
+ __name(searchAndLoad, "searchAndLoad");
1025
+ var TOOL_SEARCH_DESCRIPTION = `# Tool discovery
1026
+
1027
+ Searches over deferred tool metadata with BM25 and exposes matching tools for the next model call.
1028
+
1029
+ Some of the tools, such as tools of MCP servers, may not have been provided to you upfront, and you should use this tool (\`${TOOL_SEARCH_TOOL_NAME}\`) to search for the required tools. For MCP tool discovery, always use \`${TOOL_SEARCH_TOOL_NAME}\`.`;
1030
+ function createToolSearchToolDefinition(options = {}) {
1031
+ return {
1032
+ name: TOOL_SEARCH_TOOL_NAME,
1033
+ label: TOOL_SEARCH_TOOL_NAME,
1034
+ description: TOOL_SEARCH_DESCRIPTION,
1035
+ promptSnippet: "Search for tools that are not loaded yet and load the matches",
1036
+ parameters: toolSearchSchema,
1037
+ // Searching is not something scripts need; it changes what the model sees.
1038
+ exposure: "model-only",
1039
+ // A query can match any tool that is not declared yet.
1040
+ reachesTools: /* @__PURE__ */ __name(() => "all", "reachesTools"),
1041
+ async execute(_toolCallId, { query, limit }) {
1042
+ if (query.trim() === "")
1043
+ throw new Error("query must not be empty");
1044
+ const max = limit ?? DEFAULT_TOOL_SEARCH_LIMIT;
1045
+ if (!Number.isInteger(max) || max <= 0)
1046
+ throw new Error("limit must be a positive integer");
1047
+ const tools = options.tools ? searchAndLoad(options.tools, query, max) : [];
1048
+ const text = tools.length === 0 ? "No matching tools found." : `Loaded ${tools.length} tool${tools.length === 1 ? "" : "s"}. They are available from your next call:
1049
+ ${tools.map((tool) => `- ${tool.name}: ${tool.description.trim().split(/\r?\n/)[0]}`).join("\n")}`;
1050
+ return { content: [{ type: "text", text }], details: { loaded: tools.map((tool) => tool.name) } };
1051
+ }
1052
+ };
1053
+ }
1054
+ __name(createToolSearchToolDefinition, "createToolSearchToolDefinition");
1055
+
1056
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/tool.js
1057
+ import { join as join2 } from "node:path";
1058
+
1059
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/settings-defaults.js
1060
+ var SETTINGS_DEFAULTS = {
1061
+ transport: "auto",
1062
+ sessionShareDestination: "auto",
1063
+ steeringMode: "one-at-a-time",
1064
+ followUpMode: "one-at-a-time",
1065
+ compaction: {
1066
+ enabled: true,
1067
+ reserveTokens: 16384,
1068
+ keepRecentTokens: 2e4
1069
+ },
1070
+ branchSummary: {
1071
+ reserveTokens: 16384,
1072
+ skipPrompt: false
1073
+ },
1074
+ retry: {
1075
+ enabled: true,
1076
+ maxRetries: 3,
1077
+ baseDelayMs: 2e3,
1078
+ maxAgentDelayMs: DEFAULT_MAX_AGENT_RETRY_DELAY_MS,
1079
+ provider: {
1080
+ maxRetryDelayMs: 6e4
1081
+ }
1082
+ },
1083
+ hideThinkingBlock: false,
1084
+ showCacheMissNotices: false,
1085
+ quietStartup: false,
1086
+ defaultProjectTrust: "ask",
1087
+ collapseChangelog: false,
1088
+ enableInstallTelemetry: true,
1089
+ enableAnalytics: false,
1090
+ enableSkillCommands: true,
1091
+ terminal: {
1092
+ showImages: true,
1093
+ imageWidthCells: 60,
1094
+ clearOnShrink: false,
1095
+ showTerminalProgress: false
1096
+ },
1097
+ images: {
1098
+ autoResize: true,
1099
+ blockImages: false
1100
+ },
1101
+ doubleEscapeAction: "tree",
1102
+ treeFilterMode: "default",
1103
+ editorPaddingX: 0,
1104
+ outputPad: 1,
1105
+ autocompleteMaxVisible: 5,
1106
+ markdown: {
1107
+ codeBlockIndent: " ",
1108
+ mermaid: "streaming"
1109
+ },
1110
+ warnings: {
1111
+ anthropicExtraUsage: true
1112
+ },
1113
+ codemode: {
1114
+ mode: "on",
1115
+ inlineBudget: 3e3
1116
+ },
1117
+ cacheWarming: "streaming",
1118
+ tuiMode: "fullscreen",
1119
+ fullscreenExitOutput: "transcript",
1120
+ fullscreenScrollbar: "auto",
1121
+ fullscreenCopyOnSelect: true,
1122
+ fullscreenWheelScrollLines: "auto"
1123
+ };
1124
+
1125
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/tool-definition-wrapper.js
1126
+ function wrapToolDefinition(definition, ctxFactory) {
1127
+ return {
1128
+ name: definition.name,
1129
+ label: definition.label,
1130
+ description: definition.description,
1131
+ parameters: definition.parameters,
1132
+ outputSchema: definition.outputSchema,
1133
+ constrainedSampling: definition.constrainedSampling,
1134
+ prepareArguments: definition.prepareArguments,
1135
+ executionMode: definition.executionMode,
1136
+ execute: /* @__PURE__ */ __name((toolCallId, params, signal, onUpdate, ctx) => definition.execute(toolCallId, params, signal, onUpdate, ctx ?? ctxFactory?.(toolCallId, signal)), "execute")
1137
+ };
1138
+ }
1139
+ __name(wrapToolDefinition, "wrapToolDefinition");
1140
+ function createToolDefinitionFromAgentTool(tool) {
1141
+ return {
1142
+ name: tool.name,
1143
+ label: tool.label,
1144
+ description: tool.description,
1145
+ parameters: tool.parameters,
1146
+ outputSchema: tool.outputSchema,
1147
+ constrainedSampling: tool.constrainedSampling,
1148
+ prepareArguments: tool.prepareArguments,
1149
+ executionMode: tool.executionMode,
1150
+ execute: /* @__PURE__ */ __name(async (toolCallId, params, signal, onUpdate) => tool.execute(toolCallId, params, signal, onUpdate), "execute")
1151
+ };
1152
+ }
1153
+ __name(createToolDefinitionFromAgentTool, "createToolDefinitionFromAgentTool");
1154
+
1155
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/execute.lazy.js
1156
+ var loadCodemodeExecutor = /* @__PURE__ */ __name(() => import("./c-FPCNRL7G.mjs"), "loadCodemodeExecutor");
1157
+
1158
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/renderer.js
1159
+ var CODE_PREVIEW_LINES = 10;
1160
+ var CALL_PREVIEW_COUNT = 8;
1161
+ var OUTPUT_PREVIEW_LINES = 5;
1162
+ var COLLAPSED_ARGS_CHARS2 = 80;
1163
+ var SCRIPT_HEADER = /^Script (completed|failed)\nWall time [\d.]+ seconds\nOutput:\n$/;
1164
+ function expandHint(theme, hidden, noun) {
1165
+ return `${theme.fg("muted", `... (${hidden} more ${noun},`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
1166
+ }
1167
+ __name(expandHint, "expandHint");
1168
+ function formatDuration(ms) {
1169
+ if (ms === void 0)
1170
+ return "";
1171
+ return ms < 1e3 ? `${Math.round(ms)}ms` : `${(ms / 1e3).toFixed(1)}s`;
1172
+ }
1173
+ __name(formatDuration, "formatDuration");
1174
+ function formatCost(cost) {
1175
+ return `$${cost >= 0.01 ? cost.toFixed(2) : cost.toPrecision(2)}`;
1176
+ }
1177
+ __name(formatCost, "formatCost");
1178
+ function statusIcon(call, theme) {
1179
+ switch (call.status) {
1180
+ case "running":
1181
+ return theme.fg("warning", "\u2026");
1182
+ case "ok":
1183
+ return theme.fg("success", "\u2713");
1184
+ case "error":
1185
+ return theme.fg("error", "\u2717");
1186
+ case "cancelled":
1187
+ return theme.fg("muted", "\u2298");
1188
+ }
1189
+ }
1190
+ __name(statusIcon, "statusIcon");
1191
+ function formatCall(call, theme, expanded) {
1192
+ const args = !expanded && call.args.length > COLLAPSED_ARGS_CHARS2 ? `${call.args.slice(0, COLLAPSED_ARGS_CHARS2 - 3)}...` : call.args;
1193
+ const duration = formatDuration(call.durationMs);
1194
+ let line = `${statusIcon(call, theme)} ${theme.fg("toolTitle", call.name)}`;
1195
+ if (args)
1196
+ line += ` ${theme.fg("muted", args)}`;
1197
+ if (duration)
1198
+ line += ` ${theme.fg("dim", duration)}`;
1199
+ if (call.cost)
1200
+ line += ` ${theme.fg("dim", formatCost(call.cost))}`;
1201
+ if (expanded && call.error)
1202
+ line += `
1203
+ ${theme.fg("error", call.error.split("\n").join("\n "))}`;
1204
+ return line;
1205
+ }
1206
+ __name(formatCall, "formatCall");
1207
+ var codemodeRenderers = {
1208
+ renderCall(args, theme, context) {
1209
+ startToolTimer(context);
1210
+ const code = str(args?.code);
1211
+ const title = theme.fg("toolTitle", theme.bold("codemode"));
1212
+ const component = context.lastComponent ?? new Container();
1213
+ component.clear();
1214
+ if (code === null) {
1215
+ component.addChild(new Text(`${title} ${theme.fg("error", "[invalid arg]")}`, 0, 0));
1216
+ return component;
1217
+ }
1218
+ component.addChild(new Text(title, 0, 0));
1219
+ if (code) {
1220
+ const highlighted = highlightCode(replaceTabs(code.replace(/\r/g, "").trimEnd()), "javascript").join("\n");
1221
+ component.addChild(context.expanded ? new Text(highlighted, 0, 0) : new VisualLinePreview({
1222
+ text: highlighted,
1223
+ maxVisualLines: CODE_PREVIEW_LINES,
1224
+ keep: "start",
1225
+ formatHint: /* @__PURE__ */ __name((hidden) => expandHint(theme, hidden, "lines"), "formatHint")
1226
+ }));
1227
+ }
1228
+ return component;
1229
+ },
1230
+ renderResult(result, options, theme, context) {
1231
+ const timerText = toolTimerText(context, options.isPartial);
1232
+ const component = context.lastComponent ?? new Container();
1233
+ component.clear();
1234
+ const calls = result.details?.calls ?? [];
1235
+ if (calls.length > 0) {
1236
+ const shown = options.expanded ? calls : calls.slice(-CALL_PREVIEW_COUNT);
1237
+ const lines = shown.map((call) => formatCall(call, theme, options.expanded));
1238
+ if (shown.length < calls.length) {
1239
+ lines.unshift(`${theme.fg("muted", `... (${calls.length - shown.length} earlier calls,`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`);
1240
+ }
1241
+ const priced = calls.filter((call) => call.cost);
1242
+ if (priced.length > 1) {
1243
+ const total = priced.reduce((sum, call) => sum + (call.cost ?? 0), 0);
1244
+ lines.push(theme.fg("muted", `Model calls: ${formatCost(total)}`));
1245
+ }
1246
+ component.addChild(new Spacer(1));
1247
+ component.addChild(new Text(lines.join("\n"), 0, 0));
1248
+ }
1249
+ const [first, ...rest] = result.content;
1250
+ const hasHeader = first?.type === "text" && SCRIPT_HEADER.test(first.text);
1251
+ const output = options.isPartial ? "" : getTextOutput({ ...result, content: hasHeader ? rest : result.content }, context.showImages).trim();
1252
+ if (output) {
1253
+ const color = context.isError ? "error" : "toolOutput";
1254
+ const styled = replaceTabs(output).split("\n").map((line) => theme.fg(color, line)).join("\n");
1255
+ component.addChild(new Spacer(1));
1256
+ if (options.expanded) {
1257
+ component.addChild(new Text(styled, 0, 0));
1258
+ } else {
1259
+ component.addChild(new VisualLinePreview({
1260
+ text: styled,
1261
+ maxVisualLines: OUTPUT_PREVIEW_LINES,
1262
+ keep: "start",
1263
+ formatHint: /* @__PURE__ */ __name((hidden) => expandHint(theme, hidden, "lines"), "formatHint")
1264
+ }));
1265
+ const fullOutputPath = result.details?.fullOutputPath;
1266
+ if (fullOutputPath)
1267
+ component.addChild(new Text(theme.fg("muted", `Full output: ${fullOutputPath}`), 0, 0));
1268
+ }
1269
+ }
1270
+ if (timerText) {
1271
+ component.addChild(new Spacer(1));
1272
+ component.addChild(new Text(theme.fg("muted", timerText), 0, 0));
1273
+ }
1274
+ return component;
1275
+ }
1276
+ };
1277
+
1278
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/tool.js
1279
+ var CODEMODE_TOOL_NAME = "codemode";
1280
+ var CODEMODE_STORE_ENTRY_TYPE = "codemode-store";
1281
+ var TEXT_OUTPUT_SCHEMA = { type: "string" };
1282
+ var codemodeSchema = typebox_exports.Object({
1283
+ code: typebox_exports.String({
1284
+ description: "Raw JavaScript source."
1285
+ })
1286
+ });
1287
+ var codemodeToolSystemPromptContribution = {
1288
+ snippet: "Run JavaScript that calls other tools",
1289
+ guidelines: [
1290
+ "Use codemode to batch independent tool calls (Promise.allSettled), chain them, or filter large output, instead of many separate calls."
1291
+ ]
1292
+ };
1293
+ var CODEMODE_DOCS_PATH = join2(getDocsPath(), "codemode.md");
1294
+ var DESCRIPTION_INTRO = `Run JavaScript that calls other tools. The input is raw JavaScript (not JSON, no code fence), run as an async function body in a QuickJS sandbox: top-level \`await\` and \`return\` work. No Node, file system, network, or timers.
1295
+ - \`await tools.<name>({ ...args })\` resolves to a string, or an object if the tool's declaration says so, and rejects with an Error on failure. A tool whose declaration returns an object resolves on failure too when it returned that object; check its fields. Calls still running when the script ends are cancelled.
1296
+ - Optional first line: \`// @options: {"max_output_tokens": 10000, "timeout_ms": 60000}\``;
1297
+ function describeGlobals(models) {
1298
+ const lines = [
1299
+ "Globals:",
1300
+ "- `text(value)`, `image(dataUrlOrImageBlock)`, `console.log(...)`, and top-level `return` add output; `exit()` ends the script. With several text items, each starts with a `==> text N/M <==` line, and `console` lines follow the other output in one `<console_output>` block. `image()` also saves the image to a temp file and the result names its path.",
1301
+ "- `store(key, value)` and `load(key)` keep JSON values across codemode calls.",
1302
+ "- `ALL_TOOLS`, `await searchTools(query, { limit?, namespace? })`, `await describeTool(name)`, `await describeNamespace(name)`: find unlisted tools, such as MCP tools."
1303
+ ];
1304
+ if (models) {
1305
+ lines.push(`- \`models\`: classifiers and image generation. Read ${CODEMODE_DOCS_PATH} first.`);
1306
+ }
1307
+ return lines.join("\n");
1308
+ }
1309
+ __name(describeGlobals, "describeGlobals");
1310
+ var DEFAULT_CODEMODE_INLINE_BUDGET = SETTINGS_DEFAULTS.codemode.inlineBudget;
1311
+ var CHARS_PER_TOKEN = 4;
1312
+ function toCodemodeDeclaration(tool, guidelines = []) {
1313
+ const bullets = guidelines.flatMap((guideline) => guideline.trim() ? [`- ${guideline.trim()}`] : []);
1314
+ return {
1315
+ name: tool.name,
1316
+ description: bullets.length > 0 ? `${tool.description.trim()}
1317
+
1318
+ ${bullets.join("\n")}` : tool.description,
1319
+ inputSchema: tool.parameters,
1320
+ outputSchema: tool.outputSchema ?? TEXT_OUTPUT_SCHEMA
1321
+ };
1322
+ }
1323
+ __name(toCodemodeDeclaration, "toCodemodeDeclaration");
1324
+ function getCodemodeCallableTools(tools) {
1325
+ return tools.filter((tool) => tool.name !== CODEMODE_TOOL_NAME);
1326
+ }
1327
+ __name(getCodemodeCallableTools, "getCodemodeCallableTools");
1328
+ function renderToolSection(declaration) {
1329
+ const id = toCodemodeIdentifier(declaration.name);
1330
+ const heading = id === declaration.name ? `### \`${id}\`` : `### \`${id}\` (\`${declaration.name}\`)`;
1331
+ return `${heading}
1332
+ ${renderToolSample(declaration).trim()}`;
1333
+ }
1334
+ __name(renderToolSection, "renderToolSection");
1335
+ function selectCatalog(groups, budget) {
1336
+ if (budget === void 0)
1337
+ return new Set(groups.flatMap((group) => group.entries.map((entry) => entry.name)));
1338
+ const queues = groups.map((group) => [...group.entries].sort((a, b) => a.cost - b.cost));
1339
+ const shown = /* @__PURE__ */ new Set();
1340
+ let remaining = budget;
1341
+ let active = queues.filter((queue) => queue.length > 0);
1342
+ while (active.length > 0) {
1343
+ active = active.filter((queue) => {
1344
+ const next = queue[0];
1345
+ if (next.cost > remaining)
1346
+ return false;
1347
+ remaining -= next.cost;
1348
+ shown.add(next.name);
1349
+ queue.shift();
1350
+ return queue.length > 0;
1351
+ });
1352
+ }
1353
+ return shown;
1354
+ }
1355
+ __name(selectCatalog, "selectCatalog");
1356
+ function createCodemodeDescription(tools, options = {}) {
1357
+ const declarations = getCodemodeCallableTools(tools).filter((tool) => !options.deferred?.has(tool.name)).map((tool) => toCodemodeDeclaration(tool, options.guidelines?.get(tool.name)));
1358
+ const groups = /* @__PURE__ */ new Map([["", { namespace: void 0, entries: [] }]]);
1359
+ for (const declaration of declarations) {
1360
+ const namespace = options.namespaces?.get(declaration.name);
1361
+ const key = namespace ? `ns:${namespace.name}` : "";
1362
+ const group = groups.get(key) ?? { namespace, entries: [] };
1363
+ groups.set(key, group);
1364
+ const section = renderToolSection(declaration);
1365
+ group.entries.push({ name: declaration.name, section, cost: Math.ceil(section.length / CHARS_PER_TOKEN) });
1366
+ }
1367
+ const ordered = [...groups.values()].sort((a, b) => a.namespace === void 0 ? -1 : b.namespace === void 0 ? 1 : a.namespace.name.localeCompare(b.namespace.name));
1368
+ const shown = selectCatalog(ordered, options.inlineBudget);
1369
+ const sections = [DESCRIPTION_INTRO, describeGlobals(options.models === true)];
1370
+ if (declarations.length === 0)
1371
+ return sections.join("\n\n");
1372
+ const toolSections = ["Nested tools:"];
1373
+ for (const { namespace, entries } of ordered) {
1374
+ const visible = entries.filter((entry) => shown.has(entry.name));
1375
+ if (namespace) {
1376
+ const listing = visible.length === entries.length ? "" : visible.length === 0 ? " (tools not listed)" : " (some tools not listed)";
1377
+ const description = namespace.description?.trim();
1378
+ toolSections.push(`## ${namespace.name}${listing}${description ? `
1379
+ ${description}` : ""}`);
1380
+ }
1381
+ for (const entry of visible)
1382
+ toolSections.push(entry.section);
1383
+ }
1384
+ sections.push(toolSections.join("\n\n"));
1385
+ return sections.join("\n\n");
1386
+ }
1387
+ __name(createCodemodeDescription, "createCodemodeDescription");
1388
+ function describeFields(schema, depth) {
1389
+ if (typeof schema !== "object" || schema === null)
1390
+ return void 0;
1391
+ const { type, properties, required } = schema;
1392
+ if (type !== "object" || typeof properties !== "object" || properties === null)
1393
+ return void 0;
1394
+ const requiredNames = new Set(Array.isArray(required) ? required : []);
1395
+ const fields = Object.entries(properties).map(([name, field]) => {
1396
+ const nested = depth > 0 ? describeFields(field, depth - 1) : void 0;
1397
+ return `${name}${requiredNames.has(name) ? "" : "?"}${nested ? `: ${nested}` : ""}`;
1398
+ });
1399
+ return `{ ${fields.join(", ")} }`;
1400
+ }
1401
+ __name(describeFields, "describeFields");
1402
+ function describeOutput(schema) {
1403
+ const type = renderToolOutputType(schema);
1404
+ if (type === "string")
1405
+ return "a string";
1406
+ const fields = describeFields(schema, 1);
1407
+ return `\`${fields ?? type.replace(/\s+/g, " ")}\``;
1408
+ }
1409
+ __name(describeOutput, "describeOutput");
1410
+ function describeScriptCall(tool) {
1411
+ return `${tool.description.trim()}
1412
+
1413
+ Codemode: \`tools.${toCodemodeIdentifier(tool.name)}(args)\` resolves to ${describeOutput(toCodemodeDeclaration(tool).outputSchema)}.`;
1414
+ }
1415
+ __name(describeScriptCall, "describeScriptCall");
1416
+ function prepareCodemodeLoadout(loadout, options) {
1417
+ const mode = options.getMode?.() ?? SETTINGS_DEFAULTS.codemode.mode;
1418
+ const isDirect = /* @__PURE__ */ __name((tool) => loadout.getExposure(tool.name) === "direct", "isDirect");
1419
+ const callable = getCodemodeCallableTools(loadout.callable);
1420
+ const callableNames = new Set(callable.map((tool) => tool.name));
1421
+ const descriptions = {};
1422
+ if (mode === "on") {
1423
+ for (const tool of loadout.declared) {
1424
+ if (callableNames.has(tool.name))
1425
+ descriptions[tool.name] = describeScriptCall(tool);
1426
+ }
1427
+ }
1428
+ const listed = mode === "only" ? callable : callable.filter((tool) => !isDirect(tool));
1429
+ const namespaces = new Map(listed.flatMap((tool) => {
1430
+ const namespace = loadout.getNamespace(tool.name);
1431
+ return namespace ? [[tool.name, namespace]] : [];
1432
+ }));
1433
+ const guidelines = new Map(listed.map((tool) => [tool.name, loadout.getPromptGuidelines(tool.name)]));
1434
+ descriptions[CODEMODE_TOOL_NAME] = createCodemodeDescription(listed, {
1435
+ models: options.models === true,
1436
+ namespaces,
1437
+ guidelines,
1438
+ deferred: new Set(listed.filter((tool) => loadout.getExposure(tool.name) === "deferred").map((tool) => tool.name)),
1439
+ inlineBudget: options.getInlineBudget?.() ?? DEFAULT_CODEMODE_INLINE_BUDGET
1440
+ });
1441
+ const declaredNames = new Set(loadout.declared.map((tool) => tool.name));
1442
+ return {
1443
+ descriptions,
1444
+ hiddenDeclarations: mode === "only" ? callable.filter((tool) => isDirect(tool) && declaredNames.has(tool.name)).map((tool) => tool.name) : []
1445
+ };
1446
+ }
1447
+ __name(prepareCodemodeLoadout, "prepareCodemodeLoadout");
1448
+ var DISCOVERY_GLOBALS = /\b(searchTools|describeNamespace|describeTool|ALL_TOOLS)\b/;
1449
+ function getScriptReach(code) {
1450
+ if (typeof code !== "string")
1451
+ return [];
1452
+ return DISCOVERY_GLOBALS.test(code) ? "all" : code.match(/\w+/g) ?? [];
1453
+ }
1454
+ __name(getScriptReach, "getScriptReach");
1455
+ function createCodemodeToolDefinition(options = {}) {
1456
+ return {
1457
+ name: CODEMODE_TOOL_NAME,
1458
+ label: CODEMODE_TOOL_NAME,
1459
+ // Replaced with the declarations of the callable tools when the tool is activated.
1460
+ description: createCodemodeDescription([], { models: options.models === true }),
1461
+ promptSnippet: codemodeToolSystemPromptContribution.snippet,
1462
+ promptGuidelines: [...codemodeToolSystemPromptContribution.guidelines],
1463
+ parameters: codemodeSchema,
1464
+ // Scripts must not start other scripts.
1465
+ exposure: "model-only",
1466
+ prepareLoadout: /* @__PURE__ */ __name((loadout) => prepareCodemodeLoadout(loadout, options), "prepareLoadout"),
1467
+ reachesTools: /* @__PURE__ */ __name((input) => getScriptReach(input.code), "reachesTools"),
1468
+ // Capable models write the script as raw text instead of a JSON-escaped string.
1469
+ constrainedSampling: { type: "grammar", variants: { openai_lark: CODEMODE_SOURCE_GRAMMAR } },
1470
+ // The sandbox (worker, QuickJS wasm) loads on the first call, not at startup.
1471
+ execute: /* @__PURE__ */ __name(async (toolCallId, params, signal, onUpdate, ctx) => (await loadCodemodeExecutor()).executeCodemode(toolCallId, params, signal, onUpdate, ctx, options), "execute"),
1472
+ ...codemodeRenderers
1473
+ };
1474
+ }
1475
+ __name(createCodemodeToolDefinition, "createCodemodeToolDefinition");
1476
+
1477
+ export {
1478
+ SETTINGS_DEFAULTS,
1479
+ splitIncompleteAnsiSuffix,
1480
+ stripAnsi,
1481
+ writeOutputFile,
1482
+ createOutputFileStream,
1483
+ DEFAULT_MAX_LINES,
1484
+ DEFAULT_MAX_BYTES,
1485
+ GREP_MAX_LINE_LENGTH,
1486
+ formatSize,
1487
+ truncateHead,
1488
+ truncateTail,
1489
+ truncateLine,
1490
+ truncateMiddle,
1491
+ createUsageTotals,
1492
+ addUsageToTotals,
1493
+ combineUsage,
1494
+ getUsageCostBreakdown,
1495
+ wrapToolDefinition,
1496
+ createToolDefinitionFromAgentTool,
1497
+ truncateToVisualLines,
1498
+ VisualLinePreview,
1499
+ shortenPath,
1500
+ str,
1501
+ formatReadLineRange,
1502
+ replaceTabs,
1503
+ normalizeDisplayText,
1504
+ getTextOutput,
1505
+ formatToolCallWithArgs,
1506
+ startToolTimer,
1507
+ toolTimerText,
1508
+ invalidArgText,
1509
+ renderToolPath,
1510
+ toCodemodeIdentifier,
1511
+ renderToolSample,
1512
+ parseCodemodeSource,
1513
+ TOOL_SEARCH_TOOL_NAME,
1514
+ DEFAULT_TOOL_SEARCH_LIMIT,
1515
+ createToolSearchDocument,
1516
+ Bm25Ranker,
1517
+ createToolSearchToolDefinition,
1518
+ CODEMODE_TOOL_NAME,
1519
+ CODEMODE_STORE_ENTRY_TYPE,
1520
+ CODEMODE_DOCS_PATH,
1521
+ toCodemodeDeclaration,
1522
+ getCodemodeCallableTools,
1523
+ createCodemodeToolDefinition
1524
+ };