@desplega.ai/agent-swarm 1.171.0 → 1.172.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/dist/{acp-adapter-1z9p3fvx.js → acp-adapter-fpecx1g1.js} +23 -5
  2. package/dist/{actions-rc2yjk8a.js → actions-pw87a1a8.js} +24 -25
  3. package/dist/{amp-adapter-ypyf5s1x.js → amp-adapter-8jem2bc0.js} +1 -1
  4. package/dist/{anthropic-messages-etkbxhhy.js → anthropic-messages-8ee2f22q.js} +55 -22
  5. package/dist/{app-04ab2s0z.js → app-wmf0m843.js} +7 -8
  6. package/dist/{assistant-vhmjd8wf.js → assistant-emp1e108.js} +26 -27
  7. package/dist/{azure-openai-responses-xap57x4b.js → azure-openai-responses-ap1gwxgr.js} +3 -3
  8. package/dist/{boot-reembed-3p0m259x.js → boot-reembed-1de4f4aj.js} +6 -7
  9. package/dist/{boot-reembed-wew3gwk8.js → boot-reembed-4ymn9atn.js} +6 -7
  10. package/dist/{boot-scrub-sweep-5ytwtq24.js → boot-scrub-sweep-adhk1s8c.js} +7 -8
  11. package/dist/{boot-seeds-s8p2xry8.js → boot-seeds-8q637aew.js} +9 -10
  12. package/dist/{claude-adapter-akrzg6jh.js → claude-adapter-t26cv8a4.js} +16 -17
  13. package/dist/{claude-managed-adapter-kqqqhp2q.js → claude-managed-adapter-xgxhqrt2.js} +2 -2
  14. package/dist/{claude-sdk-session-exq1jadx.js → claude-sdk-session-gsfsh662.js} +16 -17
  15. package/dist/{cli-n8ybnv1k.js → cli-04emfe2q.js} +1 -1
  16. package/dist/{cli-w0bwte75.js → cli-104zsxba.js} +2 -1
  17. package/dist/{cli-x6z90nq9.js → cli-19njxg5g.js} +2 -4
  18. package/dist/{cli-8mr695sb.js → cli-1hgat6pa.js} +5 -5
  19. package/dist/{cli-1qtgd1h1.js → cli-1m2xxxe2.js} +2 -2
  20. package/dist/{cli-231av4y6.js → cli-1x7da0de.js} +2 -4
  21. package/dist/{cli-x3fy2tgp.js → cli-388egyf6.js} +1 -1
  22. package/dist/{cli-j0w59p15.js → cli-4fnb6884.js} +4 -4
  23. package/dist/{cli-y1j1ggbf.js → cli-4nz8p1p5.js} +1372 -588
  24. package/dist/{cli-s88my3br.js → cli-5rv1j9ga.js} +6 -6
  25. package/dist/{cli-mn8qkd8v.js → cli-61625k3x.js} +1 -1
  26. package/dist/{cli-mzj3aqac.js → cli-6jb2rf77.js} +3 -3
  27. package/dist/{cli-ec7hrgqp.js → cli-8hzfb6xz.js} +8 -8
  28. package/dist/{cli-n805bb98.js → cli-8vs9trd4.js} +1 -1
  29. package/dist/{cli-xf713zz0.js → cli-9fxpr83v.js} +1 -1
  30. package/dist/{cli-q1vnz8wv.js → cli-9s17naqf.js} +1 -1
  31. package/dist/{cli-nkjwe4z7.js → cli-9xsmdpdt.js} +59 -54
  32. package/dist/{cli-6xxxb8qt.js → cli-aspcaef3.js} +5 -5
  33. package/dist/cli-bf7485pm.js +514 -0
  34. package/dist/{cli-s9y81s7j.js → cli-bt8k5h3s.js} +625 -150
  35. package/dist/{cli-jxsgrnmq.js → cli-c2pq2rjb.js} +2 -2
  36. package/dist/{cli-13xwcqvj.js → cli-c5km5znr.js} +2 -2
  37. package/dist/{cli-5y67yrt6.js → cli-cceskcvt.js} +112 -176
  38. package/dist/{cli-ph3145b7.js → cli-cf69s3ew.js} +4 -4
  39. package/dist/{cli-k2v5x13t.js → cli-d603qf86.js} +1 -1
  40. package/dist/{cli-r455yd58.js → cli-e0a9sk00.js} +1 -1
  41. package/dist/{cli-cgj4hc12.js → cli-eh1ytktb.js} +1872 -190
  42. package/dist/{cli-erbp6b4g.js → cli-esnpehf5.js} +7 -8
  43. package/dist/cli-ev91t6xp.js +148 -0
  44. package/dist/{cli-e2prcx5m.js → cli-fdvbjtbw.js} +235 -5
  45. package/dist/{cli-62bwwc2q.js → cli-g4f5pj26.js} +3 -3
  46. package/dist/{cli-tg8q0b5y.js → cli-g6t9texm.js} +5 -5
  47. package/dist/{cli-p2pjfq1r.js → cli-gj81e47t.js} +1 -1
  48. package/dist/{cli-srmej5tp.js → cli-gp1rtyvk.js} +2 -2
  49. package/dist/{cli-rb9m6rpe.js → cli-h6vtvt5c.js} +139 -1
  50. package/dist/cli-hd27d2md.js +1057 -0
  51. package/dist/{cli-hsk5gd15.js → cli-hwwvy36w.js} +3 -3
  52. package/dist/{cli-2rbt7at8.js → cli-hz99wfxp.js} +1 -1
  53. package/dist/cli-j1pmc07z.js +706 -0
  54. package/dist/{cli-01qndrvw.js → cli-j6kpj9az.js} +14 -8
  55. package/dist/{cli-2qbs2tvf.js → cli-k46r9hmk.js} +6 -6
  56. package/dist/{cli-wfvedq5w.js → cli-kb4ehzx5.js} +5 -5
  57. package/dist/{cli-agamgm0p.js → cli-mvzyxwg3.js} +1 -1
  58. package/dist/{cli-280gnz4v.js → cli-nv4zd0b9.js} +1 -1
  59. package/dist/{cli-rrbctenq.js → cli-nyhb1r6x.js} +3 -5
  60. package/dist/{cli-g7k7zbcz.js → cli-p7z6q2m6.js} +2 -1
  61. package/dist/{cli-yn0a417a.js → cli-phre6gz0.js} +22 -4
  62. package/dist/{cli-m4csbs67.js → cli-pj6x9qce.js} +1 -1
  63. package/dist/{cli-w0zx9ya1.js → cli-prrt9fa0.js} +4 -4
  64. package/dist/{cli-ctret352.js → cli-pstq9888.js} +33 -33
  65. package/dist/{cli-y195hv1a.js → cli-pxeeyc53.js} +1 -1
  66. package/dist/{cli-4bm25xtw.js → cli-qsztpfry.js} +1 -1
  67. package/dist/{cli-5t5my0h8.js → cli-qybkr9n3.js} +278 -1267
  68. package/dist/{cli-xezn9nkh.js → cli-r44t9wqc.js} +29 -472
  69. package/dist/{cli-x207g4w1.js → cli-r8smj8b8.js} +1 -1
  70. package/dist/{cli-bxqez1p0.js → cli-rcp5aqdw.js} +9 -39
  71. package/dist/{cli-vr5avem2.js → cli-smcrrmhy.js} +14 -18
  72. package/dist/{cli-0d2rqhvq.js → cli-tgpfnm6r.js} +15 -17
  73. package/dist/cli-vb8g5x02.js +549 -0
  74. package/dist/{cli-gt4hxb8p.js → cli-vv0qtfpx.js} +1 -2
  75. package/dist/{cli-95zs84qw.js → cli-wd0hz6ah.js} +671 -388
  76. package/dist/{cli-nkqjj42q.js → cli-x4m6feqt.js} +1 -1
  77. package/dist/{cli-x61srfpp.js → cli-xczpdp9e.js} +2 -2
  78. package/dist/cli-z1kd834t.js +36 -0
  79. package/dist/{cli-p8f7dqgt.js → cli-ztrv9y21.js} +48 -33
  80. package/dist/cli.js +24 -25
  81. package/dist/{cloudflare-workers-ai-system-one-sta45jf9.js → cloudflare-workers-ai-system-one-vnpyfr7e.js} +3 -3
  82. package/dist/{codex-adapter-9ag75whm.js → codex-adapter-m4tgdysy.js} +12 -12
  83. package/dist/{codex-hook-7ba15hjd.js → codex-hook-xch6z5wt.js} +2 -3
  84. package/dist/{codex-session-runner-9fp7y4cf.js → codex-session-runner-ymwzm6ea.js} +12 -12
  85. package/dist/{commands-d7eah0y9.js → commands-n0hshcvs.js} +6 -7
  86. package/dist/{controllers-connect-8t0k65x2.js → controllers-connect-y07cqcvy.js} +24 -25
  87. package/dist/{cursor-adapter-t4pr1m3c.js → cursor-adapter-q8pgv5qa.js} +2 -3
  88. package/dist/{db-sp39qv72.js → db-4w7tmt1g.js} +6 -7
  89. package/dist/{db-2rmd23wq.js → db-hkqvrdcb.js} +7 -8
  90. package/dist/{dispatcher-g7fsybsd.js → dispatcher-5sd69y14.js} +23 -24
  91. package/dist/{easter-egg-3d-66zxervv.js → easter-egg-3d-m8rvz40s.js} +4 -3
  92. package/dist/execute-107xtsp1.js +3745 -0
  93. package/dist/{google-generative-ai-pvhm0dq1.js → google-generative-ai-7pavrbv7.js} +3 -3
  94. package/dist/{google-vertex-tek9sqe2.js → google-vertex-3f1jk41f.js} +3 -3
  95. package/dist/{grok-adapter-1err1me7.js → grok-adapter-8m9yqzbq.js} +24 -6
  96. package/dist/{handlers-c7yggm37.js → handlers-s20xr10r.js} +26 -27
  97. package/dist/{heartbeat-dkm924fk.js → heartbeat-3k31q4g2.js} +25 -26
  98. package/dist/{hook-wgx4exw6.js → hook-gdn6a2fn.js} +13 -14
  99. package/dist/{hook-g8e7sfnf.js → hook-ygwerrdh.js} +14 -15
  100. package/dist/{http-1d23k928.js → http-jdteeg81.js} +53 -55
  101. package/dist/{index-y5vvczrs.js → index-6ksewd5y.js} +20 -18
  102. package/dist/{index-kkeftv5h.js → index-82rk11v7.js} +4 -4
  103. package/dist/{index-gm10tmye.js → index-e0snym4t.js} +23 -24
  104. package/dist/{index-vertaxs1.js → index-ffqzqgwb.js} +6 -7
  105. package/dist/{index-q7cj9bn2.js → index-tsszt7g9.js} +25 -26
  106. package/dist/{index-w097eg0x.js → index-vccv018g.js} +1 -1
  107. package/dist/{index-va4zbvzp.js → index-vm3bm9t7.js} +24 -25
  108. package/dist/{keepalive-1jc5e7ct.js → keepalive-jekc896t.js} +8 -9
  109. package/dist/{lead-yxw2f1sg.js → lead-4k9s9szx.js} +40 -41
  110. package/dist/{maintenance-h7w2m10y.js → maintenance-shazch4n.js} +6 -7
  111. package/dist/{mistral-conversations-rjxa9s1j.js → mistral-conversations-vjc1ggpd.js} +29 -15
  112. package/dist/{oauth-refresh-sweep-wh9ypd1b.js → oauth-refresh-sweep-5gb36kn8.js} +7 -8
  113. package/dist/{onboard-dfr9j762.js → onboard-ydrbnvww.js} +2 -2
  114. package/dist/{openai-codex-responses-pgvtddvv.js → openai-codex-responses-33qhkkdy.js} +7 -39
  115. package/dist/{openai-completions-44gb0zsk.js → openai-completions-s88xm3ns.js} +2 -2
  116. package/dist/{openai-decisions-vj9nkpf8.js → openai-decisions-fctnj8xd.js} +2 -2
  117. package/dist/{openai-responses-9dyzwzkr.js → openai-responses-7xd2f2e2.js} +3 -3
  118. package/dist/opencode-adapter-5zh0he20.js +55 -0
  119. package/dist/{otel-impl-and31m5s.js → otel-impl-6pf5cv86.js} +1 -1
  120. package/dist/{pi-mono-adapter-fx6k5wwh.js → pi-mono-adapter-ef9wwx9m.js} +25 -500
  121. package/dist/{pricing-refresh-23zr6j3w.js → pricing-refresh-s52nsa5q.js} +8 -9
  122. package/dist/{rbac-roles-wnx35x4x.js → rbac-roles-aq3msh4e.js} +6 -7
  123. package/dist/{rbac-roles-nc7k9d0t.js → rbac-roles-q5gb5e8v.js} +7 -8
  124. package/dist/{render-v2-81cg1y52.js → render-v2-pd1rg54q.js} +7 -8
  125. package/dist/{resume-d4b6j2n2.js → resume-gw4a2c6v.js} +14 -15
  126. package/dist/{runtime-h9ha1mq6.js → runtime-qfry88v2.js} +4 -7
  127. package/dist/{setup-g68r1w28.js → setup-jda1ksdh.js} +2 -2
  128. package/dist/{typesafe-system-one-e988vty7.js → typesafe-system-one-zzzcx4s3.js} +3 -3
  129. package/dist/{virtual-modules-rdjmcg7q.js → virtual-modules-b3ga2m65.js} +13 -12
  130. package/dist/{work-objects-0zzdnbt9.js → work-objects-tb7ycye8.js} +26 -27
  131. package/dist/{worker-p1g8qm6h.js → worker-njjccz5d.js} +40 -41
  132. package/openapi.json +1 -1
  133. package/package.json +7 -8
  134. package/src/be/scripts/extract-schema.ts +4 -0
  135. package/src/github/handlers.ts +61 -18
  136. package/src/github/types.ts +2 -1
  137. package/src/prompts/goal-reminder.ts +30 -0
  138. package/src/prompts/session-templates.ts +22 -0
  139. package/src/providers/acp-targets.ts +3 -4
  140. package/src/providers/amp-adapter.ts +1 -1
  141. package/src/providers/harness-version.ts +0 -1
  142. package/src/providers/opencode-adapter.ts +442 -723
  143. package/src/providers/opencode-swarm-plugin.ts +88 -0
  144. package/src/providers/pi-mono-extension.ts +58 -37
  145. package/src/scripts-runtime/executors/native.ts +6 -5
  146. package/src/scripts-runtime/executors/quickjs-bundle.ts +18 -11
  147. package/src/scripts-runtime/extract-args-schema.ts +22 -4
  148. package/src/scripts-runtime/import-allowlist.ts +1 -1
  149. package/src/scripts-runtime/zod-mini-bundle.ts +5 -0
  150. package/src/slack/render-v2.ts +2 -2
  151. package/src/tests/entrypoint-acp-target-binary.test.ts +19 -1
  152. package/src/tests/github-handlers-inline-comments.test.ts +131 -2
  153. package/src/tests/github-handlers-reactions.test.ts +9 -0
  154. package/src/tests/harness-version.test.ts +0 -20
  155. package/src/tests/opencode-adapter.test.ts +536 -1389
  156. package/src/tests/opencode-mcp-admission-sdk.test.ts +106 -0
  157. package/src/tests/opencode-swarm-plugin.test.ts +130 -0
  158. package/src/tests/pi-mono-extension.test.ts +59 -0
  159. package/src/tests/prompt-template-session.test.ts +4 -3
  160. package/src/tests/provider-registration.test.ts +3 -0
  161. package/src/tests/script-executor-quickjs.test.ts +17 -12
  162. package/src/tests/scripts-http.test.ts +24 -16
  163. package/src/tests/scripts-import-allowlist.test.ts +1 -1
  164. package/src/tests/scripts-runtime.test.ts +78 -40
  165. package/src/tests/seed-scripts.test.ts +13 -0
  166. package/src/tests/slack-render-v2.test.ts +4 -2
  167. package/src/tests/ui-logs-parser.test.ts +28 -0
  168. package/src/tools/script-upsert.ts +1 -1
  169. package/src/utils/memory-raters.ts +7 -3
  170. package/src/utils/openrouter-base-url.ts +0 -2
  171. package/templates/schedules/weekly-harness-upgrade-check/content.md +4 -6
  172. package/templates/skills/heartbeat-runbook/content.md +2 -0
  173. package/templates/skills/swarm-scripts/SKILL.md +1 -0
  174. package/templates/skills/swarm-scripts/content.md +1 -0
  175. package/dist/cli-5bfdm1ah.js +0 -462
  176. package/dist/cli-5c2j5yvx.js +0 -222
  177. package/dist/cli-rhy7z1rp.js +0 -532
  178. package/dist/cli-ywh2a87k.js +0 -2359
  179. package/dist/execute-h4jgevyw.js +0 -1387
  180. package/dist/opencode-adapter-f1zby94p.js +0 -34
  181. package/plugin/opencode-plugins/lib/memory-raters.ts +0 -7
  182. package/src/tests/opencode-plugin.test.ts +0 -580
  183. package/src/tests/providers/opencode-cost.test.ts +0 -74
@@ -1,24 +1,248 @@
1
1
  import {
2
- VisualLinePreview,
3
- getTextOutput,
4
- replaceTabs,
5
- str
6
- } from "./cli-rhy7z1rp.js";
2
+ sanitizeBinaryOutput
3
+ } from "./cli-ev91t6xp.js";
7
4
  import {
8
5
  Container,
9
6
  Spacer,
10
7
  Text,
11
- getDocsPath,
8
+ getCapabilities,
9
+ getImageDimensions,
12
10
  highlightCode,
13
- keyHint
14
- } from "./cli-5t5my0h8.js";
11
+ hyperlink,
12
+ imageFallback,
13
+ keyHint,
14
+ truncateToWidth
15
+ } from "./cli-qybkr9n3.js";
16
+ import {
17
+ getDocsPath,
18
+ resolvePath
19
+ } from "./cli-hd27d2md.js";
15
20
  import {
21
+ DEFAULT_MAX_AGENT_RETRY_DELAY_MS,
16
22
  exports_typebox
17
- } from "./cli-rb9m6rpe.js";
23
+ } from "./cli-h6vtvt5c.js";
18
24
  import {
19
25
  __require
20
26
  } from "./cli-bc05qbss.js";
21
27
 
28
+ // node_modules/@earendil-works/pi-coding-agent/dist/utils/output-files.js
29
+ import { randomBytes } from "node:crypto";
30
+ import { createWriteStream } from "node:fs";
31
+ import { writeFile } from "node:fs/promises";
32
+ import { tmpdir } from "node:os";
33
+ import { join } from "node:path";
34
+ var OUTPUT_FILE_MODE = 384;
35
+ function createOutputFilePath(prefix, extension) {
36
+ return join(tmpdir(), `${prefix}-${randomBytes(8).toString("hex")}${extension}`);
37
+ }
38
+ async function writeOutputFile(prefix, extension, data) {
39
+ const path = createOutputFilePath(prefix, extension);
40
+ await writeFile(path, data, { mode: OUTPUT_FILE_MODE, flag: "wx" });
41
+ return path;
42
+ }
43
+ function createOutputFileStream(prefix, extension) {
44
+ const path = createOutputFilePath(prefix, extension);
45
+ return { path, stream: createWriteStream(path, { mode: OUTPUT_FILE_MODE, flags: "wx" }) };
46
+ }
47
+
48
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/truncate.js
49
+ var DEFAULT_MAX_LINES = 2000;
50
+ var DEFAULT_MAX_BYTES = 50 * 1024;
51
+ var GREP_MAX_LINE_LENGTH = 500;
52
+ function splitLinesForCounting(content) {
53
+ if (content.length === 0) {
54
+ return [];
55
+ }
56
+ const lines = content.split(`
57
+ `);
58
+ if (content.endsWith(`
59
+ `)) {
60
+ lines.pop();
61
+ }
62
+ return lines;
63
+ }
64
+ function formatSize(bytes) {
65
+ if (bytes < 1024) {
66
+ return `${bytes}B`;
67
+ } else if (bytes < 1024 * 1024) {
68
+ return `${(bytes / 1024).toFixed(1)}KB`;
69
+ } else {
70
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
71
+ }
72
+ }
73
+ function truncateHead(content, options = {}) {
74
+ const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
75
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
76
+ const totalBytes = Buffer.byteLength(content, "utf-8");
77
+ const lines = splitLinesForCounting(content);
78
+ const totalLines = lines.length;
79
+ if (totalLines <= maxLines && totalBytes <= maxBytes) {
80
+ return {
81
+ content,
82
+ truncated: false,
83
+ truncatedBy: null,
84
+ totalLines,
85
+ totalBytes,
86
+ outputLines: totalLines,
87
+ outputBytes: totalBytes,
88
+ lastLinePartial: false,
89
+ firstLineExceedsLimit: false,
90
+ maxLines,
91
+ maxBytes
92
+ };
93
+ }
94
+ const firstLineBytes = Buffer.byteLength(lines[0], "utf-8");
95
+ if (firstLineBytes > maxBytes) {
96
+ return {
97
+ content: "",
98
+ truncated: true,
99
+ truncatedBy: "bytes",
100
+ totalLines,
101
+ totalBytes,
102
+ outputLines: 0,
103
+ outputBytes: 0,
104
+ lastLinePartial: false,
105
+ firstLineExceedsLimit: true,
106
+ maxLines,
107
+ maxBytes
108
+ };
109
+ }
110
+ const outputLinesArr = [];
111
+ let outputBytesCount = 0;
112
+ let truncatedBy = "lines";
113
+ for (let i = 0;i < lines.length && i < maxLines; i++) {
114
+ const line = lines[i];
115
+ const lineBytes = Buffer.byteLength(line, "utf-8") + (i > 0 ? 1 : 0);
116
+ if (outputBytesCount + lineBytes > maxBytes) {
117
+ truncatedBy = "bytes";
118
+ break;
119
+ }
120
+ outputLinesArr.push(line);
121
+ outputBytesCount += lineBytes;
122
+ }
123
+ if (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {
124
+ truncatedBy = "lines";
125
+ }
126
+ const outputContent = outputLinesArr.join(`
127
+ `);
128
+ const finalOutputBytes = Buffer.byteLength(outputContent, "utf-8");
129
+ return {
130
+ content: outputContent,
131
+ truncated: true,
132
+ truncatedBy,
133
+ totalLines,
134
+ totalBytes,
135
+ outputLines: outputLinesArr.length,
136
+ outputBytes: finalOutputBytes,
137
+ lastLinePartial: false,
138
+ firstLineExceedsLimit: false,
139
+ maxLines,
140
+ maxBytes
141
+ };
142
+ }
143
+ function truncateTail(content, options = {}) {
144
+ const maxLines = options.maxLines ?? DEFAULT_MAX_LINES;
145
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
146
+ const totalBytes = Buffer.byteLength(content, "utf-8");
147
+ const lines = splitLinesForCounting(content);
148
+ const totalLines = lines.length;
149
+ if (totalLines <= maxLines && totalBytes <= maxBytes) {
150
+ return {
151
+ content,
152
+ truncated: false,
153
+ truncatedBy: null,
154
+ totalLines,
155
+ totalBytes,
156
+ outputLines: totalLines,
157
+ outputBytes: totalBytes,
158
+ lastLinePartial: false,
159
+ firstLineExceedsLimit: false,
160
+ maxLines,
161
+ maxBytes
162
+ };
163
+ }
164
+ const outputLinesArr = [];
165
+ let outputBytesCount = 0;
166
+ let truncatedBy = "lines";
167
+ let lastLinePartial = false;
168
+ for (let i = lines.length - 1;i >= 0 && outputLinesArr.length < maxLines; i--) {
169
+ const line = lines[i];
170
+ const lineBytes = Buffer.byteLength(line, "utf-8") + (outputLinesArr.length > 0 ? 1 : 0);
171
+ if (outputBytesCount + lineBytes > maxBytes) {
172
+ truncatedBy = "bytes";
173
+ if (outputLinesArr.length === 0) {
174
+ const truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);
175
+ outputLinesArr.unshift(truncatedLine);
176
+ outputBytesCount = Buffer.byteLength(truncatedLine, "utf-8");
177
+ lastLinePartial = true;
178
+ }
179
+ break;
180
+ }
181
+ outputLinesArr.unshift(line);
182
+ outputBytesCount += lineBytes;
183
+ }
184
+ if (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {
185
+ truncatedBy = "lines";
186
+ }
187
+ const outputContent = outputLinesArr.join(`
188
+ `);
189
+ const finalOutputBytes = Buffer.byteLength(outputContent, "utf-8");
190
+ return {
191
+ content: outputContent,
192
+ truncated: true,
193
+ truncatedBy,
194
+ totalLines,
195
+ totalBytes,
196
+ outputLines: outputLinesArr.length,
197
+ outputBytes: finalOutputBytes,
198
+ lastLinePartial,
199
+ firstLineExceedsLimit: false,
200
+ maxLines,
201
+ maxBytes
202
+ };
203
+ }
204
+ function truncateStringToBytesFromEnd(str, maxBytes) {
205
+ const buf = Buffer.from(str, "utf-8");
206
+ if (buf.length <= maxBytes) {
207
+ return str;
208
+ }
209
+ let start = buf.length - maxBytes;
210
+ while (start < buf.length && (buf[start] & 192) === 128) {
211
+ start++;
212
+ }
213
+ return buf.slice(start).toString("utf-8");
214
+ }
215
+ function truncateLine(line, maxChars = GREP_MAX_LINE_LENGTH) {
216
+ if (line.length <= maxChars) {
217
+ return { text: line, wasTruncated: false };
218
+ }
219
+ return { text: `${line.slice(0, maxChars)}... [truncated]`, wasTruncated: true };
220
+ }
221
+ function truncateMiddle(content, maxBytes) {
222
+ const buf = Buffer.from(content, "utf-8");
223
+ const totalLines = splitLinesForCounting(content).length;
224
+ if (buf.length <= maxBytes) {
225
+ return { content, truncated: false, removedChars: 0, totalBytes: buf.length, totalLines };
226
+ }
227
+ const isBoundary = (index) => index >= buf.length || (buf[index] & 192) !== 128;
228
+ let headEnd = Math.floor(maxBytes / 2);
229
+ while (headEnd > 0 && !isBoundary(headEnd))
230
+ headEnd--;
231
+ let tailStart = buf.length - (maxBytes - Math.floor(maxBytes / 2));
232
+ while (tailStart < buf.length && !isBoundary(tailStart))
233
+ tailStart++;
234
+ const head = buf.subarray(0, headEnd).toString("utf-8");
235
+ const tail = buf.subarray(tailStart).toString("utf-8");
236
+ const removedChars = Array.from(buf.subarray(headEnd, tailStart).toString("utf-8")).length;
237
+ return {
238
+ content: `${head}…${removedChars} chars truncated…${tail}`,
239
+ truncated: true,
240
+ removedChars,
241
+ totalBytes: buf.length,
242
+ totalLines
243
+ };
244
+ }
245
+
22
246
  // node_modules/@earendil-works/pi-coding-agent/dist/core/usage-totals.js
23
247
  function createUsageTotals() {
24
248
  return {
@@ -103,82 +327,23 @@ var IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
103
327
  var INDENT = " ";
104
328
  var DEFAULT_INPUT_SCHEMA_MAX_CHARS = 16000;
105
329
  var MAX_REF_EXPANSIONS = 32;
106
- var MCP_TYPESCRIPT_PREAMBLE = `type Role = "user" | "assistant";
107
- type MetaObject = Record<string, unknown>;
108
- type Annotations = {
109
- audience?: Role[];
110
- priority?: number;
111
- lastModified?: string;
112
- };
113
- type Icon = {
114
- src: string;
115
- mimeType?: string;
116
- sizes?: string[];
117
- theme?: "light" | "dark";
118
- };
119
- type TextResourceContents = {
120
- uri: string;
121
- mimeType?: string;
122
- _meta?: MetaObject;
123
- text: string;
124
- };
125
- type BlobResourceContents = {
126
- uri: string;
127
- mimeType?: string;
128
- _meta?: MetaObject;
129
- blob: string;
130
- };
131
- type TextContent = {
132
- type: "text";
133
- text: string;
134
- annotations?: Annotations;
135
- _meta?: MetaObject;
136
- };
137
- type ImageContent = {
138
- type: "image";
139
- data: string;
140
- mimeType: string;
141
- annotations?: Annotations;
142
- _meta?: MetaObject;
143
- };
144
- type AudioContent = {
145
- type: "audio";
146
- data: string;
147
- mimeType: string;
148
- annotations?: Annotations;
149
- _meta?: MetaObject;
150
- };
151
- type ResourceLink = {
152
- icons?: Icon[];
153
- name: string;
154
- title?: string;
155
- uri: string;
156
- description?: string;
157
- mimeType?: string;
158
- annotations?: Annotations;
159
- size?: number;
160
- _meta?: MetaObject;
161
- type: "resource_link";
162
- };
163
- type EmbeddedResource = {
164
- type: "resource";
165
- resource: TextResourceContents | BlobResourceContents;
166
- annotations?: Annotations;
167
- _meta?: MetaObject;
168
- };
169
- type ContentBlock =
170
- | TextContent
171
- | ImageContent
172
- | AudioContent
173
- | ResourceLink
174
- | EmbeddedResource;
175
- type CallToolResult<TStructured = { [key: string]: unknown }> = {
176
- _meta?: MetaObject;
177
- content: ContentBlock[];
178
- isError?: boolean;
179
- structuredContent?: TStructured;
180
- [key: string]: unknown;
181
- };`;
330
+ var TAG_KEYWORDS = [
331
+ "minimum",
332
+ "exclusiveMinimum",
333
+ "maximum",
334
+ "exclusiveMaximum",
335
+ "multipleOf",
336
+ "minLength",
337
+ "maxLength",
338
+ "pattern",
339
+ "format",
340
+ "minItems",
341
+ "maxItems"
342
+ ];
343
+ var LOWER_BOUNDS = new Set(["minimum", "exclusiveMinimum", "minLength", "minItems"]);
344
+ var UPPER_BOUNDS = new Set(["maximum", "exclusiveMaximum", "maxLength", "maxItems"]);
345
+ var MAX_TAG_CHARS = 80;
346
+ var LINE_TERMINATORS = /[\r\n\u2028\u2029]/g;
182
347
  function renderToolSignature(tool, options = {}) {
183
348
  const input = tool.inputSchema === undefined ? "unknown" : schemaToType(tool.inputSchema, { maxChars: options.inputMaxChars ?? DEFAULT_INPUT_SCHEMA_MAX_CHARS });
184
349
  return `${toCodemodeIdentifier(tool.name)}(args: ${input}): Promise<${renderToolOutputType(tool.outputSchema)}>;`;
@@ -192,31 +357,12 @@ codemode tool declaration:
192
357
  ${declaration}
193
358
  \`\`\``;
194
359
  }
195
- function mcpStructuredContentSchema(schema) {
196
- if (!isObject(schema) || !isObject(schema.properties))
197
- return;
198
- const { content, isError, _meta, structuredContent } = schema.properties;
199
- if (!isObject(content) || content.type !== "array" || !isObject(content.items) || content.items.type !== "object") {
200
- return;
201
- }
202
- if (!isObject(isError) || isError.type !== "boolean" || !isObject(_meta) || _meta.type !== "object")
203
- return;
204
- return isObject(structuredContent) || typeof structuredContent === "boolean" ? structuredContent : true;
205
- }
206
360
  function renderToolOutputType(schema) {
207
- const structured = mcpStructuredContentSchema(schema);
208
- if (structured !== undefined) {
209
- const type = schemaToType(structured);
210
- return type === "unknown" ? "CallToolResult" : `CallToolResult<${type}>`;
211
- }
212
361
  return schema === undefined ? "unknown" : schemaToType(schema);
213
362
  }
214
363
  function propertyKey(name) {
215
364
  return IDENTIFIER.test(name) ? name : JSON.stringify(name);
216
365
  }
217
- function isObject(value) {
218
- return typeof value === "object" && value !== null && !Array.isArray(value);
219
- }
220
366
  function union(types) {
221
367
  const unique = [...new Set(types)];
222
368
  if (unique.includes("unknown"))
@@ -224,8 +370,12 @@ function union(types) {
224
370
  return unique.length === 0 ? "never" : unique.join(" | ");
225
371
  }
226
372
  function schemaToType(schema, options = {}) {
227
- const type = toType(schema, { root: schema, resolving: new Set, expansions: 0 });
228
- return options.maxChars !== undefined && type.length > options.maxChars ? "unknown" : type;
373
+ const render = (tags) => toType(schema, { root: schema, resolving: new Set, expansions: 0, tags });
374
+ const type = render(true);
375
+ if (options.maxChars === undefined || type.length <= options.maxChars)
376
+ return type;
377
+ const untagged = render(false);
378
+ return untagged.length <= options.maxChars ? untagged : "unknown";
229
379
  }
230
380
  function resolveRef(ref, root) {
231
381
  if (ref !== "#" && !ref.startsWith("#/"))
@@ -233,18 +383,21 @@ function resolveRef(ref, root) {
233
383
  let current = root;
234
384
  for (const segment of ref.slice(2).split("/").filter(Boolean)) {
235
385
  const key = decodeURIComponent(segment).replaceAll("~1", "/").replaceAll("~0", "~");
236
- if (!isObject(current) || !(key in current))
386
+ if (typeof current !== "object" || current === null || Array.isArray(current) || !(key in current)) {
237
387
  return;
388
+ }
238
389
  current = current[key];
239
390
  }
240
- return typeof current === "boolean" || isObject(current) ? current : undefined;
391
+ if (typeof current === "boolean")
392
+ return current;
393
+ return typeof current === "object" && current !== null && !Array.isArray(current) ? current : undefined;
241
394
  }
242
395
  function toType(schema, context) {
243
396
  if (schema === true)
244
397
  return "unknown";
245
398
  if (schema === false)
246
399
  return "never";
247
- if (!isObject(schema))
400
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
248
401
  return "unknown";
249
402
  if (typeof schema.$ref === "string") {
250
403
  const ref = schema.$ref;
@@ -310,10 +463,51 @@ function arrayType(schema, context) {
310
463
  return "unknown[]";
311
464
  }
312
465
  function descriptionOf(property) {
313
- return isObject(property) && typeof property.description === "string" ? property.description.trim() : "";
466
+ const description = property?.description;
467
+ return typeof description === "string" ? description.trim() : "";
468
+ }
469
+ function constraintTags(schema) {
470
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema))
471
+ return "";
472
+ const property = schema;
473
+ const variants = Array.isArray(property.anyOf) ? property.anyOf : property.oneOf;
474
+ const nonNull = Array.isArray(variants) ? variants.filter((variant) => variant?.type !== "null") : [];
475
+ const branch = nonNull.length === 1 ? nonNull[0] : undefined;
476
+ const branches = typeof branch === "object" && branch !== null && !Array.isArray(branch) ? [property, branch] : [property];
477
+ const schemas = branches.map((schema2) => ({
478
+ ...schema2,
479
+ ...schema2.exclusiveMinimum === true ? { minimum: undefined, exclusiveMinimum: schema2.minimum } : {},
480
+ ...schema2.exclusiveMaximum === true ? { maximum: undefined, exclusiveMaximum: schema2.maximum } : {}
481
+ }));
482
+ const tags = [];
483
+ const isInteger = (type) => type === "integer" || Array.isArray(type) && type.includes("integer");
484
+ if (schemas.some((schema2) => isInteger(schema2.type)))
485
+ tags.push("@integer");
486
+ for (const keyword of TAG_KEYWORDS) {
487
+ const values = schemas.map((schema2) => schema2[keyword]);
488
+ if (LOWER_BOUNDS.has(keyword) || UPPER_BOUNDS.has(keyword)) {
489
+ const numbers = values.filter((value) => typeof value === "number");
490
+ if (numbers.length === 0)
491
+ continue;
492
+ tags.push(`@${keyword} ${LOWER_BOUNDS.has(keyword) ? Math.max(...numbers) : Math.min(...numbers)}`);
493
+ continue;
494
+ }
495
+ for (const value of new Set(values)) {
496
+ if (typeof value === "number" || typeof value === "string")
497
+ tags.push(`@${keyword} ${value}`);
498
+ }
499
+ }
500
+ if (schemas.some((schema2) => schema2.uniqueItems === true))
501
+ tags.push("@uniqueItems");
502
+ if (property.default !== undefined && property.default !== null) {
503
+ tags.push(`@default ${JSON.stringify(property.default)}`);
504
+ }
505
+ if (property.deprecated === true)
506
+ tags.push("@deprecated");
507
+ 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(" ");
314
508
  }
315
509
  function objectType(schema, context) {
316
- const properties = isObject(schema.properties) ? schema.properties : {};
510
+ const properties = typeof schema.properties === "object" && schema.properties !== null && !Array.isArray(schema.properties) ? schema.properties : {};
317
511
  const required = new Set(Array.isArray(schema.required) ? schema.required : []);
318
512
  const names = Object.keys(properties).sort();
319
513
  const members = names.map((name) => {
@@ -329,14 +523,17 @@ function objectType(schema, context) {
329
523
  }
330
524
  if (members.length === 0)
331
525
  return "{}";
332
- if (!names.some((name) => descriptionOf(properties[name])))
526
+ const comments = names.map((name) => {
527
+ const lines2 = descriptionOf(properties[name]).split(LINE_TERMINATORS).map((line) => line.trim()).filter(Boolean);
528
+ const tags = context.tags ? constraintTags(properties[name]) : "";
529
+ return tags ? [...lines2, tags] : lines2;
530
+ });
531
+ if (!comments.some((comment) => comment.length > 0))
333
532
  return `{ ${members.join(" ")} }`;
334
533
  const lines = ["{"];
335
- names.forEach((name, index) => {
336
- for (const line of descriptionOf(properties[name]).split(/\r?\n/)) {
337
- if (line.trim())
338
- lines.push(`${INDENT}// ${line.trim()}`);
339
- }
534
+ comments.forEach((comment, index) => {
535
+ for (const line of comment)
536
+ lines.push(`${INDENT}// ${line}`);
340
537
  lines.push(`${INDENT}${members[index].replaceAll(`
341
538
  `, `
342
539
  ${INDENT}`)}`);
@@ -411,9 +608,15 @@ function parseCodemodeSource(input) {
411
608
  if (input.trim() === "") {
412
609
  throw new CodemodeSourceError('Expected JavaScript source text (non-empty). Provide JS only, optionally with a first line `// @options: {"max_output_tokens": 1000}`.');
413
610
  }
611
+ const lines = input.split(`
612
+ `);
613
+ const misplaced = lines.findIndex((line, index) => index > 0 && line.trimStart().startsWith(CODEMODE_OPTIONS_PREFIX));
614
+ if (misplaced !== -1) {
615
+ throw new CodemodeSourceError(`The ${CODEMODE_OPTIONS_PREFIX} line must be the first line of the input; found one on line ${misplaced + 1}`);
616
+ }
414
617
  const newline = input.indexOf(`
415
618
  `);
416
- const firstLine = (newline === -1 ? input : input.slice(0, newline)).replace(/\r$/, "");
619
+ const firstLine = lines[0].replace(/\r$/, "");
417
620
  const trimmed = firstLine.trimStart();
418
621
  if (!trimmed.startsWith(CODEMODE_OPTIONS_PREFIX))
419
622
  return { code: input, options: {} };
@@ -462,15 +665,15 @@ function stem(term) {
462
665
  function tokenize(text) {
463
666
  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);
464
667
  }
465
- function isObject2(value) {
668
+ function isObject(value) {
466
669
  return typeof value === "object" && value !== null && !Array.isArray(value);
467
670
  }
468
671
  function schemaText(schema, parts) {
469
- if (!isObject2(schema))
672
+ if (!isObject(schema))
470
673
  return;
471
674
  if (typeof schema.description === "string")
472
675
  parts.push(schema.description);
473
- if (isObject2(schema.properties)) {
676
+ if (isObject(schema.properties)) {
474
677
  for (const [name, property] of Object.entries(schema.properties)) {
475
678
  parts.push(name);
476
679
  schemaText(property, parts);
@@ -535,9 +738,6 @@ var toolSearchSchema = exports_typebox.Object({
535
738
  query: exports_typebox.String({ description: "Search query for deferred tools." }),
536
739
  limit: exports_typebox.Optional(exports_typebox.Number({ description: `Maximum number of tools to return. Defaults to ${DEFAULT_TOOL_SEARCH_LIMIT}.` }))
537
740
  });
538
- function isToolSearchTool(tool) {
539
- return tool.name === TOOL_SEARCH_TOOL_NAME && tool.parameters === toolSearchSchema;
540
- }
541
741
  function isSearchable(exposure) {
542
742
  return exposure === "codemode" || exposure === "deferred";
543
743
  }
@@ -566,6 +766,7 @@ function createToolSearchToolDefinition(options = {}) {
566
766
  promptSnippet: "Search for tools that are not loaded yet and load the matches",
567
767
  parameters: toolSearchSchema,
568
768
  exposure: "model-only",
769
+ reachesTools: () => "all",
569
770
  async execute(_toolCallId, { query, limit }) {
570
771
  if (query.trim() === "")
571
772
  throw new Error("query must not be empty");
@@ -582,7 +783,72 @@ ${tools.map((tool) => `- ${tool.name}: ${tool.description.trim().split(/\r?\n/)[
582
783
  }
583
784
 
584
785
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/tool.js
585
- import { join } from "node:path";
786
+ import { join as join2 } from "node:path";
787
+
788
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/settings-defaults.js
789
+ var SETTINGS_DEFAULTS = {
790
+ transport: "auto",
791
+ steeringMode: "one-at-a-time",
792
+ followUpMode: "one-at-a-time",
793
+ compaction: {
794
+ enabled: true,
795
+ reserveTokens: 16384,
796
+ keepRecentTokens: 20000
797
+ },
798
+ branchSummary: {
799
+ reserveTokens: 16384,
800
+ skipPrompt: false
801
+ },
802
+ retry: {
803
+ enabled: true,
804
+ maxRetries: 3,
805
+ baseDelayMs: 2000,
806
+ maxAgentDelayMs: DEFAULT_MAX_AGENT_RETRY_DELAY_MS,
807
+ provider: {
808
+ maxRetryDelayMs: 60000
809
+ }
810
+ },
811
+ hideThinkingBlock: false,
812
+ showCacheMissNotices: false,
813
+ quietStartup: false,
814
+ defaultProjectTrust: "ask",
815
+ collapseChangelog: false,
816
+ enableInstallTelemetry: true,
817
+ enableAnalytics: false,
818
+ enableSkillCommands: true,
819
+ terminal: {
820
+ showImages: true,
821
+ imageWidthCells: 60,
822
+ clearOnShrink: false,
823
+ showTerminalProgress: false
824
+ },
825
+ images: {
826
+ autoResize: true,
827
+ blockImages: false
828
+ },
829
+ doubleEscapeAction: "tree",
830
+ treeFilterMode: "default",
831
+ editorPaddingX: 0,
832
+ outputPad: 1,
833
+ autocompleteMaxVisible: 5,
834
+ markdown: {
835
+ codeBlockIndent: " ",
836
+ mermaid: "streaming"
837
+ },
838
+ warnings: {
839
+ anthropicExtraUsage: true
840
+ },
841
+ codemode: {
842
+ mode: "on",
843
+ inlineBudget: 3000
844
+ },
845
+ cacheWarming: "streaming",
846
+ tuiMode: "fullscreen",
847
+ fullscreenExitOutput: "transcript",
848
+ fullscreenScrollbar: "auto",
849
+ fullscreenCopyOnSelect: true,
850
+ fullscreenWheelScrollLines: "auto"
851
+ };
586
852
 
587
853
  // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/tool-definition-wrapper.js
588
854
  function wrapToolDefinition(definition, ctxFactory) {
@@ -613,13 +879,211 @@ function createToolDefinitionFromAgentTool(tool) {
613
879
  }
614
880
 
615
881
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/execute.lazy.js
616
- var loadCodemodeExecutor = () => import("./execute-h4jgevyw.js");
882
+ var loadCodemodeExecutor = () => import("./execute-107xtsp1.js");
883
+
884
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js
885
+ import * as os from "node:os";
886
+ import { pathToFileURL } from "node:url";
887
+
888
+ // node_modules/@earendil-works/pi-coding-agent/dist/utils/ansi.js
889
+ var ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
890
+ var OSC_START = "\\u001B\\]";
891
+ var CSI_START = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?";
892
+ var CSI_FINAL = "[\\dA-PR-TZcf-nq-uy=><~]";
893
+ var ansiRegex = new RegExp(`(?:${OSC_START}[\\s\\S]*?${ST})|${CSI_START}${CSI_FINAL}`, "g");
894
+ var unfinishedAnsiAtEndRegex = new RegExp(`(?:${OSC_START}(?:[^\\u0007\\u009C\\u001B]|\\u001B(?!\\\\))*|${CSI_START})$`);
895
+ var MAX_PENDING_ANSI_LENGTH = 256;
896
+ function splitIncompleteAnsiSuffix(value) {
897
+ if (!value.includes("\x1B") && !value.includes("›")) {
898
+ return { complete: value, pending: "" };
899
+ }
900
+ const windowStart = Math.max(0, value.length - MAX_PENDING_ANSI_LENGTH);
901
+ const match = unfinishedAnsiAtEndRegex.exec(value.slice(windowStart));
902
+ if (!match) {
903
+ return { complete: value, pending: "" };
904
+ }
905
+ const splitAt = windowStart + match.index;
906
+ return { complete: value.slice(0, splitAt), pending: value.slice(splitAt) };
907
+ }
908
+ function stripAnsi(value) {
909
+ if (typeof value !== "string") {
910
+ throw new TypeError(`Expected a \`string\`, got \`${typeof value}\``);
911
+ }
912
+ if (!value.includes("\x1B") && !value.includes("›")) {
913
+ return value;
914
+ }
915
+ return value.replace(ansiRegex, "");
916
+ }
917
+
918
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js
919
+ function shortenPath(path) {
920
+ if (typeof path !== "string")
921
+ return "";
922
+ const home = os.homedir();
923
+ if (path.startsWith(home)) {
924
+ return `~${path.slice(home.length)}`;
925
+ }
926
+ return path;
927
+ }
928
+ function linkPath(styledText, rawPath, cwd) {
929
+ if (!getCapabilities().hyperlinks)
930
+ return styledText;
931
+ const absolutePath = resolvePath(rawPath, cwd);
932
+ return hyperlink(styledText, pathToFileURL(absolutePath).href);
933
+ }
934
+ function str(value) {
935
+ if (typeof value === "string")
936
+ return value;
937
+ if (value == null)
938
+ return "";
939
+ return null;
940
+ }
941
+ function replaceTabs(text) {
942
+ return text.replace(/\t/g, " ");
943
+ }
944
+ function normalizeDisplayText(text) {
945
+ return text.replace(/\r/g, "");
946
+ }
947
+ function getTextOutput(result, showImages) {
948
+ if (!result)
949
+ return "";
950
+ const textBlocks = result.content.filter((c) => c.type === "text");
951
+ const imageBlocks = result.content.filter((c) => c.type === "image");
952
+ let output = textBlocks.map((c) => sanitizeBinaryOutput(stripAnsi(c.text || "")).replace(/\r/g, "")).join(`
953
+ `);
954
+ const caps = getCapabilities();
955
+ if (imageBlocks.length > 0 && (!caps.images || !showImages)) {
956
+ const imageIndicators = imageBlocks.map((img) => {
957
+ const mimeType = img.mimeType ?? "image/unknown";
958
+ const dims = img.data && img.mimeType ? getImageDimensions(img.data, img.mimeType) ?? undefined : undefined;
959
+ return imageFallback(mimeType, dims);
960
+ }).join(`
961
+ `);
962
+ output = output ? `${output}
963
+ ${imageIndicators}` : imageIndicators;
964
+ }
965
+ return output;
966
+ }
967
+ var COLLAPSED_ARGS_CHARS = 100;
968
+ function formatToolCallWithArgs(title, args, theme, expanded) {
969
+ const header = theme.fg("toolTitle", theme.bold(title));
970
+ if (args == null)
971
+ return header;
972
+ const entries = typeof args === "object" && !Array.isArray(args) ? Object.entries(args) : [["args", args]];
973
+ if (entries.length === 0)
974
+ return header;
975
+ if (expanded) {
976
+ const lines = entries.map(([key, value]) => {
977
+ const text = typeof value === "string" ? value : JSON.stringify(value, null, 2) ?? String(value);
978
+ return ` ${key}: ${replaceTabs(text).replace(/\r/g, "").split(`
979
+ `).join(`
980
+ `)}`;
981
+ });
982
+ return `${header}
983
+ ${theme.fg("muted", lines.join(`
984
+ `))}`;
985
+ }
986
+ const pairs = entries.map(([key, value]) => `${key}=${JSON.stringify(value) ?? String(value)}`).join(" ");
987
+ const preview = pairs.length > COLLAPSED_ARGS_CHARS ? `${pairs.slice(0, COLLAPSED_ARGS_CHARS - 3)}...` : pairs;
988
+ return `${header} ${theme.fg("muted", preview)}`;
989
+ }
990
+ function formatToolDuration(ms) {
991
+ const seconds = ms / 1000;
992
+ if (seconds < 60)
993
+ return `${seconds.toFixed(1)}s`;
994
+ const totalSeconds = Math.floor(seconds);
995
+ const minutes = Math.floor(totalSeconds / 60);
996
+ const remainder = totalSeconds % 60;
997
+ if (minutes < 60)
998
+ return `${minutes}m ${remainder}s`;
999
+ return `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;
1000
+ }
1001
+ function startToolTimer(context) {
1002
+ const state = context.state;
1003
+ if (context.executionStarted && state.startedAt === undefined) {
1004
+ state.startedAt = Date.now();
1005
+ state.endedAt = undefined;
1006
+ }
1007
+ }
1008
+ function toolTimerText(context, isPartial) {
1009
+ const state = context.state;
1010
+ if (state.startedAt !== undefined && isPartial && !state.interval) {
1011
+ state.interval = setInterval(() => context.invalidate(), 1000);
1012
+ }
1013
+ if (!isPartial || context.isError) {
1014
+ state.endedAt ??= Date.now();
1015
+ if (state.interval) {
1016
+ clearInterval(state.interval);
1017
+ state.interval = undefined;
1018
+ }
1019
+ }
1020
+ if (!isPartial && context.durationMs !== undefined)
1021
+ return `Took ${formatToolDuration(context.durationMs)}`;
1022
+ if (state.startedAt === undefined)
1023
+ return;
1024
+ const endTime = state.endedAt ?? Date.now();
1025
+ return `${isPartial ? "Elapsed" : "Took"} ${formatToolDuration(endTime - state.startedAt)}`;
1026
+ }
1027
+ function invalidArgText(theme) {
1028
+ return theme.fg("error", "[invalid arg]");
1029
+ }
1030
+ function renderToolPath(rawPath, theme, cwd, options) {
1031
+ if (rawPath === null)
1032
+ return invalidArgText(theme);
1033
+ const value = rawPath || options?.emptyFallback;
1034
+ if (!value)
1035
+ return theme.fg("toolOutput", "...");
1036
+ return linkPath(theme.fg("accent", shortenPath(value)), value, cwd);
1037
+ }
1038
+
1039
+ // node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/visual-truncate.js
1040
+ function truncateToVisualLines(text, maxVisualLines, width, paddingX = 0, keep = "end") {
1041
+ if (!text) {
1042
+ return { visualLines: [], skippedCount: 0 };
1043
+ }
1044
+ const tempText = new Text(text, paddingX, 0);
1045
+ const allVisualLines = tempText.render(width);
1046
+ if (allVisualLines.length <= maxVisualLines) {
1047
+ return { visualLines: allVisualLines, skippedCount: 0 };
1048
+ }
1049
+ const truncatedLines = keep === "start" ? allVisualLines.slice(0, maxVisualLines) : allVisualLines.slice(-maxVisualLines);
1050
+ const skippedCount = allVisualLines.length - maxVisualLines;
1051
+ return { visualLines: truncatedLines, skippedCount };
1052
+ }
1053
+
1054
+ class VisualLinePreview {
1055
+ options;
1056
+ cachedWidth;
1057
+ cachedLines;
1058
+ constructor(options) {
1059
+ this.options = options;
1060
+ }
1061
+ render(width) {
1062
+ if (this.cachedLines === undefined || this.cachedWidth !== width) {
1063
+ const { text, maxVisualLines, keep, formatHint } = this.options;
1064
+ const preview = truncateToVisualLines(text, maxVisualLines, width, 0, keep);
1065
+ const lines = preview.visualLines;
1066
+ if (preview.skippedCount > 0) {
1067
+ const hint = truncateToWidth(formatHint(preview.skippedCount), width, "...");
1068
+ this.cachedLines = keep === "start" ? [...lines, hint] : [hint, ...lines];
1069
+ } else {
1070
+ this.cachedLines = lines;
1071
+ }
1072
+ this.cachedWidth = width;
1073
+ }
1074
+ return this.cachedLines;
1075
+ }
1076
+ invalidate() {
1077
+ this.cachedWidth = undefined;
1078
+ this.cachedLines = undefined;
1079
+ }
1080
+ }
617
1081
 
618
1082
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/renderer.js
619
1083
  var CODE_PREVIEW_LINES = 10;
620
1084
  var CALL_PREVIEW_COUNT = 8;
621
1085
  var OUTPUT_PREVIEW_LINES = 5;
622
- var COLLAPSED_ARGS_CHARS = 80;
1086
+ var COLLAPSED_ARGS_CHARS2 = 80;
623
1087
  var SCRIPT_HEADER = /^Script (completed|failed)\nWall time [\d.]+ seconds\nOutput:\n$/;
624
1088
  function expandHint(theme, hidden, noun) {
625
1089
  return `${theme.fg("muted", `... (${hidden} more ${noun},`)} ${keyHint("app.tools.expand", "to expand")}${theme.fg("muted", ")")}`;
@@ -645,7 +1109,7 @@ function statusIcon(call, theme) {
645
1109
  }
646
1110
  }
647
1111
  function formatCall(call, theme, expanded) {
648
- const args = !expanded && call.args.length > COLLAPSED_ARGS_CHARS ? `${call.args.slice(0, COLLAPSED_ARGS_CHARS - 3)}...` : call.args;
1112
+ const args = !expanded && call.args.length > COLLAPSED_ARGS_CHARS2 ? `${call.args.slice(0, COLLAPSED_ARGS_CHARS2 - 3)}...` : call.args;
649
1113
  const duration = formatDuration(call.durationMs);
650
1114
  let line = `${statusIcon(call, theme)} ${theme.fg("toolTitle", call.name)}`;
651
1115
  if (args)
@@ -663,6 +1127,7 @@ function formatCall(call, theme, expanded) {
663
1127
  }
664
1128
  var codemodeRenderers = {
665
1129
  renderCall(args, theme, context) {
1130
+ startToolTimer(context);
666
1131
  const code = str(args?.code);
667
1132
  const title = theme.fg("toolTitle", theme.bold("codemode"));
668
1133
  const component = context.lastComponent ?? new Container;
@@ -685,6 +1150,7 @@ var codemodeRenderers = {
685
1150
  return component;
686
1151
  },
687
1152
  renderResult(result, options, theme, context) {
1153
+ const timerText = toolTimerText(context, options.isPartial);
688
1154
  const component = context.lastComponent ?? new Container;
689
1155
  component.clear();
690
1156
  const calls = result.details?.calls ?? [];
@@ -726,6 +1192,10 @@ var codemodeRenderers = {
726
1192
  component.addChild(new Text(theme.fg("muted", `Full output: ${fullOutputPath}`), 0, 0));
727
1193
  }
728
1194
  }
1195
+ if (timerText) {
1196
+ component.addChild(new Spacer(1));
1197
+ component.addChild(new Text(theme.fg("muted", timerText), 0, 0));
1198
+ }
729
1199
  return component;
730
1200
  }
731
1201
  };
@@ -739,18 +1209,15 @@ var codemodeSchema = exports_typebox.Object({
739
1209
  description: "Raw JavaScript source."
740
1210
  })
741
1211
  });
742
- function isCodemodeTool(tool) {
743
- return tool.name === CODEMODE_TOOL_NAME && tool.parameters === codemodeSchema;
744
- }
745
1212
  var codemodeToolSystemPromptContribution = {
746
1213
  snippet: "Run JavaScript that calls other tools",
747
1214
  guidelines: [
748
1215
  "Use codemode to batch independent tool calls (Promise.allSettled), chain them, or filter large output, instead of many separate calls."
749
1216
  ]
750
1217
  };
751
- var CODEMODE_DOCS_PATH = join(getDocsPath(), "codemode.md");
1218
+ var CODEMODE_DOCS_PATH = join2(getDocsPath(), "codemode.md");
752
1219
  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.
753
- - \`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. Calls still running when the script ends are cancelled.
1220
+ - \`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.
754
1221
  - Optional first line: \`// @options: {"max_output_tokens": 10000, "timeout_ms": 60000}\``;
755
1222
  function describeGlobals(models) {
756
1223
  const lines = [
@@ -765,7 +1232,7 @@ function describeGlobals(models) {
765
1232
  return lines.join(`
766
1233
  `);
767
1234
  }
768
- var DEFAULT_CODEMODE_INLINE_BUDGET = 3000;
1235
+ var DEFAULT_CODEMODE_INLINE_BUDGET = SETTINGS_DEFAULTS.codemode.inlineBudget;
769
1236
  var CHARS_PER_TOKEN = 4;
770
1237
  function toCodemodeDeclaration(tool, guidelines = []) {
771
1238
  const bullets = guidelines.flatMap((guideline) => guideline.trim() ? [`- ${guideline.trim()}`] : []);
@@ -822,12 +1289,6 @@ function createCodemodeDescription(tools, options = {}) {
822
1289
  const ordered = [...groups.values()].sort((a, b) => a.namespace === undefined ? -1 : b.namespace === undefined ? 1 : a.namespace.name.localeCompare(b.namespace.name));
823
1290
  const shown = selectCatalog(ordered, options.inlineBudget);
824
1291
  const sections = [DESCRIPTION_INTRO, describeGlobals(options.models === true)];
825
- if (declarations.some((declaration) => shown.has(declaration.name) && mcpStructuredContentSchema(declaration.outputSchema) !== undefined)) {
826
- sections.push(`Shared MCP Types:
827
- \`\`\`ts
828
- ${MCP_TYPESCRIPT_PREAMBLE}
829
- \`\`\``);
830
- }
831
1292
  if (declarations.length === 0)
832
1293
  return sections.join(`
833
1294
 
@@ -851,18 +1312,25 @@ ${description}` : ""}`);
851
1312
 
852
1313
  `);
853
1314
  }
1315
+ function describeFields(schema, depth) {
1316
+ if (typeof schema !== "object" || schema === null)
1317
+ return;
1318
+ const { type, properties, required } = schema;
1319
+ if (type !== "object" || typeof properties !== "object" || properties === null)
1320
+ return;
1321
+ const requiredNames = new Set(Array.isArray(required) ? required : []);
1322
+ const fields = Object.entries(properties).map(([name, field]) => {
1323
+ const nested = depth > 0 ? describeFields(field, depth - 1) : undefined;
1324
+ return `${name}${requiredNames.has(name) ? "" : "?"}${nested ? `: ${nested}` : ""}`;
1325
+ });
1326
+ return `{ ${fields.join(", ")} }`;
1327
+ }
854
1328
  function describeOutput(schema) {
855
1329
  const type = renderToolOutputType(schema);
856
1330
  if (type === "string")
857
1331
  return "a string";
858
- const object = typeof schema === "object" ? schema : undefined;
859
- const properties = object?.properties;
860
- if (object?.type === "object" && typeof properties === "object" && properties !== null && mcpStructuredContentSchema(schema) === undefined) {
861
- const required = new Set(Array.isArray(object.required) ? object.required : []);
862
- const fields = Object.keys(properties).map((name) => required.has(name) ? name : `${name}?`);
863
- return `\`{ ${fields.join(", ")} }\``;
864
- }
865
- return `\`${type.replace(/\s+/g, " ")}\``;
1332
+ const fields = describeFields(schema, 1);
1333
+ return `\`${fields ?? type.replace(/\s+/g, " ")}\``;
866
1334
  }
867
1335
  function describeScriptCall(tool) {
868
1336
  return `${tool.description.trim()}
@@ -870,7 +1338,7 @@ function describeScriptCall(tool) {
870
1338
  Codemode: \`tools.${toCodemodeIdentifier(tool.name)}(args)\` resolves to ${describeOutput(toCodemodeDeclaration(tool).outputSchema)}.`;
871
1339
  }
872
1340
  function prepareCodemodeLoadout(loadout, options) {
873
- const mode = options.getMode?.() ?? "on";
1341
+ const mode = options.getMode?.() ?? SETTINGS_DEFAULTS.codemode.mode;
874
1342
  const isDirect = (tool) => loadout.getExposure(tool.name) === "direct";
875
1343
  const callable = getCodemodeCallableTools(loadout.callable);
876
1344
  const callableNames = new Set(callable.map((tool) => tool.name));
@@ -900,6 +1368,12 @@ function prepareCodemodeLoadout(loadout, options) {
900
1368
  hiddenDeclarations: mode === "only" ? callable.filter((tool) => isDirect(tool) && declaredNames.has(tool.name)).map((tool) => tool.name) : []
901
1369
  };
902
1370
  }
1371
+ var DISCOVERY_GLOBALS = /\b(searchTools|describeNamespace|describeTool|ALL_TOOLS)\b/;
1372
+ function getScriptReach(code) {
1373
+ if (typeof code !== "string")
1374
+ return [];
1375
+ return DISCOVERY_GLOBALS.test(code) ? "all" : code.match(/\w+/g) ?? [];
1376
+ }
903
1377
  function createCodemodeToolDefinition(options = {}) {
904
1378
  return {
905
1379
  name: CODEMODE_TOOL_NAME,
@@ -910,10 +1384,11 @@ function createCodemodeToolDefinition(options = {}) {
910
1384
  parameters: codemodeSchema,
911
1385
  exposure: "model-only",
912
1386
  prepareLoadout: (loadout) => prepareCodemodeLoadout(loadout, options),
1387
+ reachesTools: (input) => getScriptReach(input.code),
913
1388
  constrainedSampling: { type: "grammar", variants: { openai_lark: CODEMODE_SOURCE_GRAMMAR } },
914
1389
  execute: async (toolCallId, params, signal, onUpdate, ctx) => (await loadCodemodeExecutor()).executeCodemode(toolCallId, params, signal, onUpdate, ctx, options),
915
1390
  ...codemodeRenderers
916
1391
  };
917
1392
  }
918
1393
 
919
- export { createUsageTotals, addUsageToTotals, combineUsage, getUsageCostBreakdown, wrapToolDefinition, createToolDefinitionFromAgentTool, toCodemodeIdentifier, renderToolSample, parseCodemodeSource, TOOL_SEARCH_TOOL_NAME, DEFAULT_TOOL_SEARCH_LIMIT, createToolSearchDocument, Bm25Ranker, isToolSearchTool, createToolSearchToolDefinition, CODEMODE_TOOL_NAME, CODEMODE_STORE_ENTRY_TYPE, isCodemodeTool, CODEMODE_DOCS_PATH, toCodemodeDeclaration, getCodemodeCallableTools, createCodemodeToolDefinition };
1394
+ export { SETTINGS_DEFAULTS, splitIncompleteAnsiSuffix, stripAnsi, writeOutputFile, createOutputFileStream, DEFAULT_MAX_LINES, DEFAULT_MAX_BYTES, GREP_MAX_LINE_LENGTH, formatSize, truncateHead, truncateTail, truncateLine, truncateMiddle, createUsageTotals, addUsageToTotals, combineUsage, getUsageCostBreakdown, wrapToolDefinition, createToolDefinitionFromAgentTool, truncateToVisualLines, VisualLinePreview, shortenPath, str, replaceTabs, normalizeDisplayText, getTextOutput, formatToolCallWithArgs, startToolTimer, toolTimerText, invalidArgText, renderToolPath, toCodemodeIdentifier, renderToolSample, parseCodemodeSource, TOOL_SEARCH_TOOL_NAME, DEFAULT_TOOL_SEARCH_LIMIT, createToolSearchDocument, Bm25Ranker, createToolSearchToolDefinition, CODEMODE_TOOL_NAME, CODEMODE_STORE_ENTRY_TYPE, CODEMODE_DOCS_PATH, toCodemodeDeclaration, getCodemodeCallableTools, createCodemodeToolDefinition };