@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,17 +1,40 @@
1
1
  import {
2
2
  CODEMODE_TOOL_NAME,
3
+ DEFAULT_MAX_BYTES,
4
+ DEFAULT_MAX_LINES,
5
+ GREP_MAX_LINE_LENGTH,
6
+ SETTINGS_DEFAULTS,
3
7
  TOOL_SEARCH_TOOL_NAME,
8
+ VisualLinePreview,
4
9
  addUsageToTotals,
5
10
  combineUsage,
6
11
  createCodemodeToolDefinition,
12
+ createOutputFileStream,
7
13
  createToolDefinitionFromAgentTool,
8
14
  createToolSearchToolDefinition,
9
15
  createUsageTotals,
16
+ formatSize,
17
+ formatToolCallWithArgs,
18
+ getTextOutput,
10
19
  getUsageCostBreakdown,
11
- isCodemodeTool,
12
- isToolSearchTool,
13
- wrapToolDefinition
14
- } from "./cli-s9y81s7j.js";
20
+ invalidArgText,
21
+ normalizeDisplayText,
22
+ renderToolPath,
23
+ replaceTabs,
24
+ shortenPath,
25
+ splitIncompleteAnsiSuffix,
26
+ startToolTimer,
27
+ str,
28
+ stripAnsi,
29
+ toolTimerText,
30
+ truncateHead,
31
+ truncateLine,
32
+ truncateMiddle,
33
+ truncateTail,
34
+ truncateToVisualLines,
35
+ wrapToolDefinition,
36
+ writeOutputFile
37
+ } from "./cli-bt8k5h3s.js";
15
38
  import {
16
39
  ProjectTrustStore,
17
40
  addMcpServerConfig,
@@ -20,7 +43,7 @@ import {
20
43
  loadMcpConfig,
21
44
  openBrowser,
22
45
  updateMcpServerConfig
23
- } from "./cli-13xwcqvj.js";
46
+ } from "./cli-c5km5znr.js";
24
47
  import {
25
48
  AuthStorage,
26
49
  FileAuthStorageBackend,
@@ -29,10 +52,6 @@ import {
29
52
  McpServerRegistry,
30
53
  READ_MCP_RESOURCE_TOOL,
31
54
  ReadOnlyAuthStorage,
32
- createMcpResourceToolDefinitions,
33
- createMcpToolDefinition,
34
- createMcpToolName,
35
- createMcpToolRenderers,
36
55
  createToolNameMatcher,
37
56
  getConfigValueEnvVarNames,
38
57
  getMcpToolExposure,
@@ -46,51 +65,27 @@ import {
46
65
  require_proper_lockfile,
47
66
  resolveConfigValueOrThrow,
48
67
  resolveHeadersOrThrow,
68
+ toLlmContent,
49
69
  validateMcpServerConfig
50
- } from "./cli-xezn9nkh.js";
70
+ } from "./cli-r44t9wqc.js";
51
71
  import {
52
- DEFAULT_MAX_BYTES,
53
- DEFAULT_MAX_LINES,
54
- GREP_MAX_LINE_LENGTH,
55
- VisualLinePreview,
56
- createOutputFileStream,
57
- formatSize,
58
- formatToolCallWithArgs,
59
72
  getPowerShellConfig,
60
73
  getShellConfig,
61
74
  getShellEnv,
62
- getTextOutput,
63
- invalidArgText,
64
75
  killProcessTree,
65
76
  killTrackedDetachedChildren,
66
- normalizeDisplayText,
67
- renderToolPath,
68
- replaceTabs,
69
77
  sanitizeBinaryOutput,
70
- shortenPath,
71
- splitIncompleteAnsiSuffix,
72
- str,
73
- stripAnsi,
74
78
  trackDetachedChildPid,
75
- truncateHead,
76
- truncateLine,
77
- truncateTail,
78
- truncateToVisualLines,
79
79
  untrackDetachedChildPid
80
- } from "./cli-rhy7z1rp.js";
80
+ } from "./cli-ev91t6xp.js";
81
81
  import {
82
82
  ArminComponent
83
- } from "./cli-y195hv1a.js";
83
+ } from "./cli-pxeeyc53.js";
84
84
  import {
85
- APP_NAME,
86
- APP_TITLE,
87
85
  Box,
88
- CONFIG_DIR_NAME,
89
86
  CancellableLoader,
90
87
  CombinedAutocompleteProvider,
91
88
  Container,
92
- ENV_AGENT_DIR,
93
- ENV_SESSION_DIR,
94
89
  Editor,
95
90
  FS_WATCH_RETRY_DELAY_MS,
96
91
  Image,
@@ -100,63 +95,39 @@ import {
100
95
  Loader,
101
96
  Markdown,
102
97
  MouseRegion,
103
- PACKAGE_NAME,
104
98
  ProcessTerminal,
105
99
  SYSTEM_THEME_NAME,
106
100
  ScrollView,
107
101
  SelectList,
108
102
  SettingsList,
109
103
  Spacer,
104
+ THEME_TOKENS,
110
105
  TUI_KEYBINDINGS,
111
106
  Text,
112
107
  Theme,
113
108
  TruncatedText,
114
109
  TuiAltScreen,
115
110
  TuiMainScreen,
116
- VERSION,
117
111
  VStack,
118
112
  Z,
119
113
  backgroundAnsi,
120
- canonicalizePath,
121
114
  closeWatcher,
122
115
  detectCapabilities,
123
- detectInstallChange,
124
- detectInstallMethod,
125
- expandTildePath,
126
116
  foregroundAnsi,
127
117
  formatKeyText,
128
- formatPathRelativeToCwdOrAbsolute,
129
118
  fuzzyFilter,
130
119
  fuzzyMatch,
131
- getAgentDir,
132
- getAuthPath,
133
120
  getAvailableThemes,
134
121
  getAvailableThemesWithPaths,
135
- getBinDir,
136
- getBundledInteractiveAssetPath,
137
122
  getCapabilities,
138
- getChangelogPath,
139
- getCwdRelativePath,
140
- getDebugLogPath,
141
- getDocsPath,
142
123
  getEditorTheme,
143
- getExamplesPath,
144
- getExportTemplateDir,
145
- getFileRevision,
146
124
  getKeybindings,
147
125
  getLanguageFromPath,
148
126
  getMarkdownTheme,
149
127
  getNativeClipboard,
150
- getPackageDir,
151
- getReadmePath,
152
128
  getResolvedThemeColors,
153
129
  getSelectListTheme,
154
- getSelfUpdateCommand,
155
- getSelfUpdateUnavailableInstruction,
156
- getSessionsDir,
157
130
  getSettingsListTheme,
158
- getSettingsPath,
159
- getShareViewerUrl,
160
131
  getTerminalColorMode,
161
132
  getTerminalTheme,
162
133
  getThemeByName,
@@ -165,25 +136,19 @@ import {
165
136
  hyperlink,
166
137
  initTheme,
167
138
  isAppleTerminalSession,
168
- isBunBinary,
169
- isBundledNode,
170
- isLocalPath,
171
139
  isViewportTUI,
172
140
  keyDisplayText,
173
141
  keyHint,
174
142
  keyText,
175
143
  loadAllHighlightLanguages,
176
144
  loadThemeFromPath,
177
- markPathIgnoredByCloudSync,
178
145
  markTerminalColorsPending,
179
146
  matchesKey,
180
147
  mixColors,
181
- normalizePath,
182
148
  onThemeChange,
183
149
  parseAutoThemeSetting,
184
150
  parseColor,
185
151
  rawKeyHint,
186
- resolvePath,
187
152
  resolveThemeSetting,
188
153
  rgbColor,
189
154
  setCapabilityOverrides,
@@ -196,25 +161,64 @@ import {
196
161
  setThemeInstance,
197
162
  setThemeJsonValidator,
198
163
  sliceByColumn,
199
- source_default,
200
- spawnProcess,
201
- spawnProcessSync,
202
- splitBom,
203
164
  stopThemeWatcher,
204
- stripBom,
205
165
  theme,
206
166
  truncateToWidth,
207
167
  visibleWidth,
208
- waitForChildProcess,
209
168
  watchWithErrorHandler,
210
169
  wrapTextWithAnsi
211
- } from "./cli-5t5my0h8.js";
170
+ } from "./cli-qybkr9n3.js";
171
+ import {
172
+ source_default
173
+ } from "./cli-vb8g5x02.js";
174
+ import {
175
+ APP_NAME,
176
+ APP_TITLE,
177
+ CONFIG_DIR_NAME,
178
+ ENV_AGENT_DIR,
179
+ ENV_SESSION_DIR,
180
+ PACKAGE_NAME,
181
+ VERSION,
182
+ canonicalizePath,
183
+ detectInstallChange,
184
+ detectInstallMethod,
185
+ expandTildePath,
186
+ formatPathRelativeToCwdOrAbsolute,
187
+ getAgentDir,
188
+ getAuthPath,
189
+ getBinDir,
190
+ getBundledInteractiveAssetPath,
191
+ getChangelogPath,
192
+ getCwdRelativePath,
193
+ getDebugLogPath,
194
+ getDocsPath,
195
+ getExamplesPath,
196
+ getExportTemplateDir,
197
+ getFileRevision,
198
+ getPackageDir,
199
+ getReadmePath,
200
+ getSelfUpdateCommand,
201
+ getSelfUpdateUnavailableInstruction,
202
+ getSessionsDir,
203
+ getSettingsPath,
204
+ getShareViewerUrl,
205
+ isBunBinary,
206
+ isBundledNode,
207
+ isLocalPath,
208
+ markPathIgnoredByCloudSync,
209
+ normalizePath,
210
+ resolvePath,
211
+ spawnProcess,
212
+ spawnProcessSync,
213
+ splitBom,
214
+ stripBom,
215
+ waitForChildProcess
216
+ } from "./cli-hd27d2md.js";
212
217
  import {
213
218
  require_dist
214
219
  } from "./cli-7nxes1hs.js";
215
220
  import {
216
221
  Compile,
217
- DEFAULT_MAX_AGENT_RETRY_DELAY_MS,
218
222
  DEFAULT_RADIUS_GATEWAY,
219
223
  builtinProviders,
220
224
  completeSimple,
@@ -222,20 +226,21 @@ import {
222
226
  getBuiltinModelDataGeneratedAt,
223
227
  isContextOverflow,
224
228
  isRecoverableLength,
225
- isRetryableAssistantError,
226
229
  normalizeRadiusGatewayUrl,
230
+ personalizeOpenRouterCatalog,
227
231
  radiusProvider,
228
232
  resetApiProviders,
229
- retryAssistantCall,
230
- retryDelayMs,
231
233
  stream,
232
234
  streamSimple,
233
235
  typesafeSystemOneApi,
234
236
  validateToolArguments
235
- } from "./cli-5y67yrt6.js";
237
+ } from "./cli-cceskcvt.js";
236
238
  import {
237
- exports_typebox
238
- } from "./cli-rb9m6rpe.js";
239
+ exports_typebox,
240
+ isRetryableAssistantError,
241
+ retryAssistantCall,
242
+ retryDelayMs
243
+ } from "./cli-h6vtvt5c.js";
239
244
  import {
240
245
  cleanupSessionResources,
241
246
  uuidv7
@@ -274,7 +279,7 @@ import {
274
279
  modelsAreEqual,
275
280
  normalizeContext,
276
281
  toToolDeclaration
277
- } from "./cli-g7k7zbcz.js";
282
+ } from "./cli-p7z6q2m6.js";
278
283
  import {
279
284
  EventStream,
280
285
  createAssistantMessageEventStream
@@ -26906,11 +26911,11 @@ function configureHttpDispatcher(timeoutMs = DEFAULT_HTTP_IDLE_TIMEOUT_MS) {
26906
26911
  }
26907
26912
 
26908
26913
  // node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js
26914
+ var CACHE_WARMING_MODES = ["off", "streaming", "idle"];
26909
26915
  var DEFAULT_COMPACTION_TOKEN_SETTINGS = {
26910
- reserveTokens: 16384,
26911
- keepRecentTokens: 20000
26916
+ reserveTokens: SETTINGS_DEFAULTS.compaction.reserveTokens,
26917
+ keepRecentTokens: SETTINGS_DEFAULTS.compaction.keepRecentTokens
26912
26918
  };
26913
- var CACHE_WARMING_MODES = ["off", "streaming", "idle"];
26914
26919
  function isMergeableObject(value) {
26915
26920
  return typeof value === "object" && value !== null && !Array.isArray(value);
26916
26921
  }
@@ -27385,7 +27390,7 @@ class SettingsManager {
27385
27390
  this.save();
27386
27391
  }
27387
27392
  getSteeringMode() {
27388
- return this.settings.steeringMode || "one-at-a-time";
27393
+ return this.settings.steeringMode || SETTINGS_DEFAULTS.steeringMode;
27389
27394
  }
27390
27395
  setSteeringMode(mode) {
27391
27396
  this.globalSettings.steeringMode = mode;
@@ -27393,7 +27398,7 @@ class SettingsManager {
27393
27398
  this.save();
27394
27399
  }
27395
27400
  getFollowUpMode() {
27396
- return this.settings.followUpMode || "one-at-a-time";
27401
+ return this.settings.followUpMode || SETTINGS_DEFAULTS.followUpMode;
27397
27402
  }
27398
27403
  setFollowUpMode(mode) {
27399
27404
  this.globalSettings.followUpMode = mode;
@@ -27448,7 +27453,7 @@ class SettingsManager {
27448
27453
  this.save();
27449
27454
  }
27450
27455
  getTransport() {
27451
- return this.settings.transport ?? "auto";
27456
+ return this.settings.transport ?? SETTINGS_DEFAULTS.transport;
27452
27457
  }
27453
27458
  setTransport(transport) {
27454
27459
  this.globalSettings.transport = transport;
@@ -27456,7 +27461,7 @@ class SettingsManager {
27456
27461
  this.save();
27457
27462
  }
27458
27463
  getCompactionEnabled() {
27459
- return this.settings.compaction?.enabled ?? true;
27464
+ return this.settings.compaction?.enabled ?? SETTINGS_DEFAULTS.compaction.enabled;
27460
27465
  }
27461
27466
  setCompactionEnabled(enabled) {
27462
27467
  if (!this.globalSettings.compaction) {
@@ -27498,15 +27503,15 @@ class SettingsManager {
27498
27503
  }
27499
27504
  getBranchSummarySettings() {
27500
27505
  return {
27501
- reserveTokens: this.settings.branchSummary?.reserveTokens ?? 16384,
27502
- skipPrompt: this.settings.branchSummary?.skipPrompt ?? false
27506
+ reserveTokens: this.settings.branchSummary?.reserveTokens ?? SETTINGS_DEFAULTS.branchSummary.reserveTokens,
27507
+ skipPrompt: this.settings.branchSummary?.skipPrompt ?? SETTINGS_DEFAULTS.branchSummary.skipPrompt
27503
27508
  };
27504
27509
  }
27505
27510
  getBranchSummarySkipPrompt() {
27506
- return this.settings.branchSummary?.skipPrompt ?? false;
27511
+ return this.settings.branchSummary?.skipPrompt ?? SETTINGS_DEFAULTS.branchSummary.skipPrompt;
27507
27512
  }
27508
27513
  getRetryEnabled() {
27509
- return this.settings.retry?.enabled ?? true;
27514
+ return this.settings.retry?.enabled ?? SETTINGS_DEFAULTS.retry.enabled;
27510
27515
  }
27511
27516
  setRetryEnabled(enabled) {
27512
27517
  if (!this.globalSettings.retry) {
@@ -27519,9 +27524,9 @@ class SettingsManager {
27519
27524
  getRetrySettings() {
27520
27525
  return {
27521
27526
  enabled: this.getRetryEnabled(),
27522
- maxRetries: this.settings.retry?.maxRetries ?? 3,
27523
- baseDelayMs: this.settings.retry?.baseDelayMs ?? 2000,
27524
- maxAgentDelayMs: this.settings.retry?.maxAgentDelayMs ?? DEFAULT_MAX_AGENT_RETRY_DELAY_MS
27527
+ maxRetries: this.settings.retry?.maxRetries ?? SETTINGS_DEFAULTS.retry.maxRetries,
27528
+ baseDelayMs: this.settings.retry?.baseDelayMs ?? SETTINGS_DEFAULTS.retry.baseDelayMs,
27529
+ maxAgentDelayMs: this.settings.retry?.maxAgentDelayMs ?? SETTINGS_DEFAULTS.retry.maxAgentDelayMs
27525
27530
  };
27526
27531
  }
27527
27532
  getHttpIdleTimeoutMs() {
@@ -27537,7 +27542,7 @@ class SettingsManager {
27537
27542
  }
27538
27543
  getCacheWarmingMode() {
27539
27544
  const mode = this.globalSettings.cacheWarming;
27540
- return mode !== undefined && CACHE_WARMING_MODES.includes(mode) ? mode : "streaming";
27545
+ return mode !== undefined && CACHE_WARMING_MODES.includes(mode) ? mode : SETTINGS_DEFAULTS.cacheWarming;
27541
27546
  }
27542
27547
  setCacheWarmingMode(mode) {
27543
27548
  this.globalSettings.cacheWarming = mode;
@@ -27548,17 +27553,17 @@ class SettingsManager {
27548
27553
  return {
27549
27554
  timeoutMs: this.settings.retry?.provider?.timeoutMs,
27550
27555
  maxRetries: this.settings.retry?.provider?.maxRetries,
27551
- maxRetryDelayMs: this.settings.retry?.provider?.maxRetryDelayMs ?? 60000
27556
+ maxRetryDelayMs: this.settings.retry?.provider?.maxRetryDelayMs ?? SETTINGS_DEFAULTS.retry.provider.maxRetryDelayMs
27552
27557
  };
27553
27558
  }
27554
27559
  getWebSocketConnectTimeoutMs() {
27555
27560
  return parseTimeoutSetting(this.settings.websocketConnectTimeoutMs, "websocketConnectTimeoutMs");
27556
27561
  }
27557
27562
  getHideThinkingBlock() {
27558
- return this.settings.hideThinkingBlock ?? false;
27563
+ return this.settings.hideThinkingBlock ?? SETTINGS_DEFAULTS.hideThinkingBlock;
27559
27564
  }
27560
27565
  getShowCacheMissNotices() {
27561
- return this.settings.showCacheMissNotices ?? false;
27566
+ return this.settings.showCacheMissNotices ?? SETTINGS_DEFAULTS.showCacheMissNotices;
27562
27567
  }
27563
27568
  getExternalEditorCommand() {
27564
27569
  const configuredEditor = this.settings.externalEditor;
@@ -27592,7 +27597,7 @@ class SettingsManager {
27592
27597
  }
27593
27598
  getQuietStartup() {
27594
27599
  const value = this.settings.quietStartup;
27595
- return value === true || value === "header" ? value : false;
27600
+ return value === true || value === "header" ? value : SETTINGS_DEFAULTS.quietStartup;
27596
27601
  }
27597
27602
  setQuietStartup(quiet) {
27598
27603
  this.globalSettings.quietStartup = quiet;
@@ -27601,7 +27606,7 @@ class SettingsManager {
27601
27606
  }
27602
27607
  getDefaultProjectTrust() {
27603
27608
  const value = this.globalSettings.defaultProjectTrust;
27604
- return value === "always" || value === "never" ? value : "ask";
27609
+ return value === "always" || value === "never" ? value : SETTINGS_DEFAULTS.defaultProjectTrust;
27605
27610
  }
27606
27611
  setDefaultProjectTrust(defaultProjectTrust) {
27607
27612
  this.globalSettings.defaultProjectTrust = defaultProjectTrust;
@@ -27625,7 +27630,7 @@ class SettingsManager {
27625
27630
  this.save();
27626
27631
  }
27627
27632
  getCollapseChangelog() {
27628
- return this.settings.collapseChangelog ?? false;
27633
+ return this.settings.collapseChangelog ?? SETTINGS_DEFAULTS.collapseChangelog;
27629
27634
  }
27630
27635
  setCollapseChangelog(collapse) {
27631
27636
  this.globalSettings.collapseChangelog = collapse;
@@ -27633,7 +27638,7 @@ class SettingsManager {
27633
27638
  this.save();
27634
27639
  }
27635
27640
  getEnableInstallTelemetry() {
27636
- return this.settings.enableInstallTelemetry ?? true;
27641
+ return this.settings.enableInstallTelemetry ?? SETTINGS_DEFAULTS.enableInstallTelemetry;
27637
27642
  }
27638
27643
  setEnableInstallTelemetry(enabled) {
27639
27644
  this.globalSettings.enableInstallTelemetry = enabled;
@@ -27641,7 +27646,7 @@ class SettingsManager {
27641
27646
  this.save();
27642
27647
  }
27643
27648
  getEnableAnalytics() {
27644
- return this.settings.enableAnalytics ?? false;
27649
+ return this.settings.enableAnalytics ?? SETTINGS_DEFAULTS.enableAnalytics;
27645
27650
  }
27646
27651
  getTrackingId() {
27647
27652
  return this.settings.trackingId;
@@ -27729,7 +27734,7 @@ class SettingsManager {
27729
27734
  });
27730
27735
  }
27731
27736
  getEnableSkillCommands() {
27732
- return this.settings.enableSkillCommands ?? true;
27737
+ return this.settings.enableSkillCommands ?? SETTINGS_DEFAULTS.enableSkillCommands;
27733
27738
  }
27734
27739
  setEnableSkillCommands(enabled) {
27735
27740
  this.globalSettings.enableSkillCommands = enabled;
@@ -27749,7 +27754,7 @@ class SettingsManager {
27749
27754
  };
27750
27755
  }
27751
27756
  getShowImages() {
27752
- return this.settings.terminal?.showImages ?? true;
27757
+ return this.settings.terminal?.showImages ?? SETTINGS_DEFAULTS.terminal.showImages;
27753
27758
  }
27754
27759
  setShowImages(show) {
27755
27760
  if (!this.globalSettings.terminal) {
@@ -27762,7 +27767,7 @@ class SettingsManager {
27762
27767
  getImageWidthCells() {
27763
27768
  const width = this.settings.terminal?.imageWidthCells;
27764
27769
  if (typeof width !== "number" || !Number.isFinite(width)) {
27765
- return 60;
27770
+ return SETTINGS_DEFAULTS.terminal.imageWidthCells;
27766
27771
  }
27767
27772
  return Math.max(1, Math.floor(width));
27768
27773
  }
@@ -27778,7 +27783,9 @@ class SettingsManager {
27778
27783
  if (this.settings.terminal?.clearOnShrink !== undefined) {
27779
27784
  return this.settings.terminal.clearOnShrink;
27780
27785
  }
27781
- return process.env.PI_CLEAR_ON_SHRINK === "1";
27786
+ if (process.env.PI_CLEAR_ON_SHRINK === "1")
27787
+ return true;
27788
+ return SETTINGS_DEFAULTS.terminal.clearOnShrink;
27782
27789
  }
27783
27790
  setClearOnShrink(enabled) {
27784
27791
  if (!this.globalSettings.terminal) {
@@ -27789,7 +27796,7 @@ class SettingsManager {
27789
27796
  this.save();
27790
27797
  }
27791
27798
  getShowTerminalProgress() {
27792
- return this.settings.terminal?.showTerminalProgress ?? false;
27799
+ return this.settings.terminal?.showTerminalProgress ?? SETTINGS_DEFAULTS.terminal.showTerminalProgress;
27793
27800
  }
27794
27801
  setShowTerminalProgress(enabled) {
27795
27802
  if (!this.globalSettings.terminal) {
@@ -27800,7 +27807,7 @@ class SettingsManager {
27800
27807
  this.save();
27801
27808
  }
27802
27809
  getTuiMode() {
27803
- return this.settings.tuiMode === "regular" ? "regular" : "fullscreen";
27810
+ return this.settings.tuiMode === "regular" ? "regular" : SETTINGS_DEFAULTS.tuiMode;
27804
27811
  }
27805
27812
  setTuiMode(mode) {
27806
27813
  this.globalSettings.tuiMode = mode;
@@ -27808,7 +27815,7 @@ class SettingsManager {
27808
27815
  this.save();
27809
27816
  }
27810
27817
  getFullscreenExitOutput() {
27811
- return this.settings.fullscreenExitOutput === "resume-hint" ? "resume-hint" : "transcript";
27818
+ return this.settings.fullscreenExitOutput === "resume-hint" ? "resume-hint" : SETTINGS_DEFAULTS.fullscreenExitOutput;
27812
27819
  }
27813
27820
  setFullscreenExitOutput(output) {
27814
27821
  this.globalSettings.fullscreenExitOutput = output;
@@ -27817,7 +27824,7 @@ class SettingsManager {
27817
27824
  }
27818
27825
  getFullscreenScrollbar() {
27819
27826
  const mode = this.settings.fullscreenScrollbar;
27820
- return mode === "always" || mode === "hidden" ? mode : "auto";
27827
+ return mode === "always" || mode === "hidden" ? mode : SETTINGS_DEFAULTS.fullscreenScrollbar;
27821
27828
  }
27822
27829
  setFullscreenScrollbar(mode) {
27823
27830
  this.globalSettings.fullscreenScrollbar = mode;
@@ -27825,7 +27832,7 @@ class SettingsManager {
27825
27832
  this.save();
27826
27833
  }
27827
27834
  getFullscreenCopyOnSelect() {
27828
- return this.settings.fullscreenCopyOnSelect ?? true;
27835
+ return this.settings.fullscreenCopyOnSelect ?? SETTINGS_DEFAULTS.fullscreenCopyOnSelect;
27829
27836
  }
27830
27837
  setFullscreenCopyOnSelect(enabled) {
27831
27838
  this.globalSettings.fullscreenCopyOnSelect = enabled;
@@ -27834,7 +27841,7 @@ class SettingsManager {
27834
27841
  }
27835
27842
  getFullscreenWheelScrollLines() {
27836
27843
  const lines = this.settings.fullscreenWheelScrollLines;
27837
- return typeof lines === "number" && Number.isFinite(lines) ? Math.max(1, Math.min(100, Math.floor(lines))) : "auto";
27844
+ return typeof lines === "number" && Number.isFinite(lines) ? Math.max(1, Math.min(100, Math.floor(lines))) : SETTINGS_DEFAULTS.fullscreenWheelScrollLines;
27838
27845
  }
27839
27846
  setFullscreenWheelScrollLines(lines) {
27840
27847
  this.globalSettings.fullscreenWheelScrollLines = lines === "auto" ? lines : Math.max(1, Math.min(100, Math.floor(lines)));
@@ -27842,7 +27849,7 @@ class SettingsManager {
27842
27849
  this.save();
27843
27850
  }
27844
27851
  getImageAutoResize() {
27845
- return this.settings.images?.autoResize ?? true;
27852
+ return this.settings.images?.autoResize ?? SETTINGS_DEFAULTS.images.autoResize;
27846
27853
  }
27847
27854
  setImageAutoResize(enabled) {
27848
27855
  if (!this.globalSettings.images) {
@@ -27853,7 +27860,7 @@ class SettingsManager {
27853
27860
  this.save();
27854
27861
  }
27855
27862
  getBlockImages() {
27856
- return this.settings.images?.blockImages ?? false;
27863
+ return this.settings.images?.blockImages ?? SETTINGS_DEFAULTS.images.blockImages;
27857
27864
  }
27858
27865
  setBlockImages(blocked) {
27859
27866
  if (!this.globalSettings.images) {
@@ -27878,7 +27885,7 @@ class SettingsManager {
27878
27885
  this.save();
27879
27886
  }
27880
27887
  getDoubleEscapeAction() {
27881
- return this.settings.doubleEscapeAction ?? "tree";
27888
+ return this.settings.doubleEscapeAction ?? SETTINGS_DEFAULTS.doubleEscapeAction;
27882
27889
  }
27883
27890
  setDoubleEscapeAction(action) {
27884
27891
  this.globalSettings.doubleEscapeAction = action;
@@ -27888,7 +27895,7 @@ class SettingsManager {
27888
27895
  getTreeFilterMode() {
27889
27896
  const mode = this.settings.treeFilterMode;
27890
27897
  const valid = ["default", "no-tools", "user-only", "labeled-only", "all"];
27891
- return mode && valid.includes(mode) ? mode : "default";
27898
+ return mode && valid.includes(mode) ? mode : SETTINGS_DEFAULTS.treeFilterMode;
27892
27899
  }
27893
27900
  setTreeFilterMode(mode) {
27894
27901
  this.globalSettings.treeFilterMode = mode;
@@ -27904,7 +27911,7 @@ class SettingsManager {
27904
27911
  this.save();
27905
27912
  }
27906
27913
  getEditorPaddingX() {
27907
- return this.settings.editorPaddingX ?? 0;
27914
+ return this.settings.editorPaddingX ?? SETTINGS_DEFAULTS.editorPaddingX;
27908
27915
  }
27909
27916
  setEditorPaddingX(padding) {
27910
27917
  this.globalSettings.editorPaddingX = Math.max(0, Math.min(3, Math.floor(padding)));
@@ -27912,7 +27919,7 @@ class SettingsManager {
27912
27919
  this.save();
27913
27920
  }
27914
27921
  getOutputPad() {
27915
- return this.settings.outputPad === 0 ? 0 : 1;
27922
+ return this.settings.outputPad === 0 ? 0 : SETTINGS_DEFAULTS.outputPad;
27916
27923
  }
27917
27924
  setOutputPad(padding) {
27918
27925
  this.globalSettings.outputPad = padding;
@@ -27920,7 +27927,7 @@ class SettingsManager {
27920
27927
  this.save();
27921
27928
  }
27922
27929
  getAutocompleteMaxVisible() {
27923
- return this.settings.autocompleteMaxVisible ?? 5;
27930
+ return this.settings.autocompleteMaxVisible ?? SETTINGS_DEFAULTS.autocompleteMaxVisible;
27924
27931
  }
27925
27932
  setAutocompleteMaxVisible(maxVisible) {
27926
27933
  this.globalSettings.autocompleteMaxVisible = Math.max(3, Math.min(20, Math.floor(maxVisible)));
@@ -27928,11 +27935,11 @@ class SettingsManager {
27928
27935
  this.save();
27929
27936
  }
27930
27937
  getCodeBlockIndent() {
27931
- return this.settings.markdown?.codeBlockIndent ?? " ";
27938
+ return this.settings.markdown?.codeBlockIndent ?? SETTINGS_DEFAULTS.markdown.codeBlockIndent;
27932
27939
  }
27933
27940
  getMermaidRenderingMode() {
27934
27941
  const mode = this.settings.markdown?.mermaid;
27935
- return mode === "off" || mode === "final" ? mode : "streaming";
27942
+ return mode === "off" || mode === "final" ? mode : SETTINGS_DEFAULTS.markdown.mermaid;
27936
27943
  }
27937
27944
  setMermaidRenderingMode(mode) {
27938
27945
  this.globalSettings.markdown ??= {};
@@ -30540,172 +30547,447 @@ import { dirname as dirname2, join as join4 } from "node:path";
30540
30547
  // node_modules/@earendil-works/pi-coding-agent/dist/core/model-config.js
30541
30548
  import { readFile } from "node:fs/promises";
30542
30549
 
30543
- // node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js
30544
- function stripJsonComments(input) {
30545
- return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => m[0] === '"' ? m : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === '"' ? m : ""));
30546
- }
30550
+ // node_modules/@earendil-works/pi-ai/dist/providers/model-schema.js
30551
+ var THINKING_LEVELS = ["minimal", "low", "medium", "high", "xhigh", "max"];
30552
+ var MODEL_THINKING_LEVELS = ["off", ...THINKING_LEVELS];
30553
+ var MODEL_INPUT_MODALITIES = ["text", "image"];
30554
+ var CACHE_RETENTIONS = ["none", "short", "long"];
30555
+ var MODEL_PROMPT_CACHE_RETENTIONS = ["short", "long"];
30556
+ var ThinkingLevelSchema = exports_typebox.Enum(THINKING_LEVELS);
30557
+ var ModelThinkingLevelSchema = exports_typebox.Enum(MODEL_THINKING_LEVELS);
30558
+ var ModelInputModalitySchema = exports_typebox.Enum(MODEL_INPUT_MODALITIES);
30559
+ var CacheRetentionSchema = exports_typebox.Enum(CACHE_RETENTIONS);
30560
+ var ThinkingLevelMapValueSchema = exports_typebox.Union([exports_typebox.String(), exports_typebox.Null()]);
30561
+ var ThinkingLevelMapSchema = exports_typebox.Partial(exports_typebox.Record(ModelThinkingLevelSchema, ThinkingLevelMapValueSchema));
30562
+ var ModelPromptCacheSchema = exports_typebox.Partial(exports_typebox.Record(exports_typebox.Enum(MODEL_PROMPT_CACHE_RETENTIONS), exports_typebox.Number({ exclusiveMinimum: 0 })), {
30563
+ description: "Best-effort prompt cache lifetime in seconds for each retention tier. A missing tier means the lifetime is unknown, so Pi does not warm it."
30564
+ });
30565
+ var ModelCostRatesProperties = {
30566
+ input: exports_typebox.Number({ description: "Input cost in USD per million tokens." }),
30567
+ output: exports_typebox.Number({ description: "Output cost in USD per million tokens." }),
30568
+ cacheRead: exports_typebox.Number({ description: "Cache-read cost in USD per million tokens." }),
30569
+ cacheWrite: exports_typebox.Number({ description: "Cache-write cost in USD per million tokens." })
30570
+ };
30571
+ var ModelCostRatesSchema = exports_typebox.Object(ModelCostRatesProperties);
30572
+ var ModelCostTierSchema = exports_typebox.Object({
30573
+ inputTokensAbove: exports_typebox.Number({
30574
+ description: "Use this tier when total request input exceeds this token count."
30575
+ }),
30576
+ ...ModelCostRatesProperties
30577
+ });
30578
+ var ModelCostSchema = exports_typebox.Object({
30579
+ ...ModelCostRatesProperties,
30580
+ tiers: exports_typebox.Optional(exports_typebox.Array(ModelCostTierSchema, {
30581
+ description: "Request-wide pricing tiers. The highest matching input threshold applies to the full request."
30582
+ }))
30583
+ });
30584
+ function modelImageResizeOptions(options) {
30585
+ return exports_typebox.Object({
30586
+ maxWidth: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30587
+ maxHeight: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30588
+ maxBytes: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, description: "Maximum base64-encoded payload size in bytes." })),
30589
+ jpegQuality: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, maximum: 100 }))
30590
+ }, options);
30591
+ }
30592
+ var ModelImageResizeOptionsSchema = modelImageResizeOptions();
30593
+ var ModelImageInputLimitsSchema = exports_typebox.Object({
30594
+ resize: exports_typebox.Optional(modelImageResizeOptions({
30595
+ description: "Cache-safe resize profile applied before a new image enters conversation history."
30596
+ })),
30597
+ maxPerMessage: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, description: "Maximum images accepted in one provider message." })),
30598
+ maxPerRequest: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, description: "Maximum images accepted across one provider request." }))
30599
+ });
30600
+ var ModelInputLimitsSchema = exports_typebox.Object({
30601
+ maxRequestBytes: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, description: "Maximum serialized provider request size in bytes." })),
30602
+ images: exports_typebox.Optional(ModelImageInputLimitsSchema)
30603
+ });
30547
30604
 
30548
- // node_modules/@earendil-works/pi-coding-agent/dist/core/model-config.js
30549
- var PercentileCutoffsSchema = exports_typebox.Object({
30550
- p50: exports_typebox.Optional(exports_typebox.Number()),
30551
- p75: exports_typebox.Optional(exports_typebox.Number()),
30552
- p90: exports_typebox.Optional(exports_typebox.Number()),
30553
- p99: exports_typebox.Optional(exports_typebox.Number())
30605
+ // node_modules/@earendil-works/pi-ai/dist/providers/compat-schema.js
30606
+ function sessionAffinityFormat(options) {
30607
+ return exports_typebox.Union([exports_typebox.Literal("openai"), exports_typebox.Literal("openai-nosession"), exports_typebox.Literal("openrouter")], options);
30608
+ }
30609
+ var SessionAffinityFormatSchema = sessionAffinityFormat({
30610
+ description: "Session-affinity header format used to route related requests consistently."
30611
+ });
30612
+ function thinkingTokenBudgetField(options) {
30613
+ return exports_typebox.Union([exports_typebox.Literal("thinking_token_budget"), exports_typebox.Literal("thinking_budget"), exports_typebox.Literal("thinking_budget_tokens")], options);
30614
+ }
30615
+ var ThinkingTokenBudgetFieldSchema = thinkingTokenBudgetField({
30616
+ description: 'Top-level request field name used by OpenAI-compatible endpoints to cap reasoning tokens. "thinking_token_budget" is used by vLLM, "thinking_budget" by Qwen, DashScope, or SGLang, and "thinking_budget_tokens" by llama.cpp.'
30554
30617
  });
30618
+ var ChatTemplateKwargValueSchema = exports_typebox.Union([
30619
+ exports_typebox.String(),
30620
+ exports_typebox.Number(),
30621
+ exports_typebox.Boolean(),
30622
+ exports_typebox.Null(),
30623
+ exports_typebox.Object({
30624
+ $var: exports_typebox.Union([
30625
+ exports_typebox.Literal("thinking.enabled"),
30626
+ exports_typebox.Literal("thinking.effort"),
30627
+ exports_typebox.Literal("thinking.budget")
30628
+ ]),
30629
+ omitWhenOff: exports_typebox.Optional(exports_typebox.Boolean())
30630
+ })
30631
+ ]);
30632
+ function percentileCutoffs(metric) {
30633
+ return exports_typebox.Object({
30634
+ p50: exports_typebox.Optional(exports_typebox.Number({ description: `${metric} at the 50th percentile.` })),
30635
+ p75: exports_typebox.Optional(exports_typebox.Number({ description: `${metric} at the 75th percentile.` })),
30636
+ p90: exports_typebox.Optional(exports_typebox.Number({ description: `${metric} at the 90th percentile.` })),
30637
+ p99: exports_typebox.Optional(exports_typebox.Number({ description: `${metric} at the 99th percentile.` }))
30638
+ });
30639
+ }
30555
30640
  var OpenRouterRoutingSchema = exports_typebox.Object({
30556
- allow_fallbacks: exports_typebox.Optional(exports_typebox.Boolean()),
30557
- require_parameters: exports_typebox.Optional(exports_typebox.Boolean()),
30558
- data_collection: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("deny"), exports_typebox.Literal("allow")])),
30559
- zdr: exports_typebox.Optional(exports_typebox.Boolean()),
30560
- enforce_distillable_text: exports_typebox.Optional(exports_typebox.Boolean()),
30561
- order: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String())),
30562
- only: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String())),
30563
- ignore: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String())),
30564
- quantizations: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String())),
30641
+ allow_fallbacks: exports_typebox.Optional(exports_typebox.Boolean({ description: "Whether to allow backup providers to serve requests.", default: true })),
30642
+ require_parameters: exports_typebox.Optional(exports_typebox.Boolean({
30643
+ description: "Whether to filter providers to only those that support all parameters in the request.",
30644
+ default: false
30645
+ })),
30646
+ data_collection: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("deny"), exports_typebox.Literal("allow")], {
30647
+ description: 'Data collection setting. "allow": allow providers that may store or train on data. "deny": only use providers that do not collect user data.',
30648
+ default: "allow"
30649
+ })),
30650
+ zdr: exports_typebox.Optional(exports_typebox.Boolean({ description: "Whether to restrict routing to only ZDR (Zero Data Retention) endpoints." })),
30651
+ enforce_distillable_text: exports_typebox.Optional(exports_typebox.Boolean({ description: "Whether to restrict routing to only models that allow text distillation." })),
30652
+ order: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), {
30653
+ description: "An ordered list of provider names or slugs to try in sequence, falling back to the next if unavailable."
30654
+ })),
30655
+ only: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), {
30656
+ description: "List of provider names or slugs to exclusively allow for this request."
30657
+ })),
30658
+ ignore: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), { description: "List of provider names or slugs to skip for this request." })),
30659
+ quantizations: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), {
30660
+ description: 'A list of quantization levels to filter providers by, for example ["fp16", "bf16", "fp8", "fp6", "int8", "int4", "fp4", "fp32"].'
30661
+ })),
30565
30662
  sort: exports_typebox.Optional(exports_typebox.Union([
30566
30663
  exports_typebox.String(),
30567
30664
  exports_typebox.Object({
30568
- by: exports_typebox.Optional(exports_typebox.String()),
30569
- partition: exports_typebox.Optional(exports_typebox.Union([exports_typebox.String(), exports_typebox.Null()]))
30665
+ by: exports_typebox.Optional(exports_typebox.String({ description: 'The sorting metric, such as "price", "throughput", or "latency".' })),
30666
+ partition: exports_typebox.Optional(exports_typebox.Union([exports_typebox.String(), exports_typebox.Null()], {
30667
+ description: 'Partitioning strategy: "model" or "none".',
30668
+ default: "model"
30669
+ }))
30570
30670
  })
30571
- ])),
30671
+ ], {
30672
+ description: 'Sorting strategy. Can be a string such as "price", "throughput", or "latency", or an object.'
30673
+ })),
30572
30674
  max_price: exports_typebox.Optional(exports_typebox.Object({
30573
- prompt: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()])),
30574
- completion: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()])),
30575
- image: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()])),
30576
- audio: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()])),
30577
- request: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()]))
30675
+ prompt: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()], { description: "Price per million prompt tokens." })),
30676
+ completion: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()], { description: "Price per million completion tokens." })),
30677
+ image: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()], { description: "Price per image." })),
30678
+ audio: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()], { description: "Price per audio unit." })),
30679
+ request: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), exports_typebox.String()], { description: "Price per request." }))
30680
+ }, { description: "Maximum price per million tokens in USD." })),
30681
+ preferred_min_throughput: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), percentileCutoffs("Minimum tokens per second")], {
30682
+ description: "Preferred minimum throughput in tokens per second. A number applies to p50."
30578
30683
  })),
30579
- preferred_min_throughput: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), PercentileCutoffsSchema])),
30580
- preferred_max_latency: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), PercentileCutoffsSchema]))
30684
+ preferred_max_latency: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Number(), percentileCutoffs("Maximum latency in seconds")], {
30685
+ description: "Preferred maximum latency in seconds. A number applies to p50."
30686
+ }))
30687
+ }, {
30688
+ description: "OpenRouter provider routing preferences. Controls which upstream providers OpenRouter routes requests to. Sent as the provider field in the OpenRouter API request body. See https://openrouter.ai/docs/guides/routing/provider-selection."
30581
30689
  });
30582
30690
  var VercelGatewayRoutingSchema = exports_typebox.Object({
30583
- only: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String())),
30584
- order: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String()))
30585
- });
30586
- var ThinkingLevelMapValueSchema = exports_typebox.Union([exports_typebox.String(), exports_typebox.Null()]);
30587
- var ThinkingLevelMapSchema = exports_typebox.Object({
30588
- off: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30589
- minimal: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30590
- low: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30591
- medium: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30592
- high: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30593
- xhigh: exports_typebox.Optional(ThinkingLevelMapValueSchema),
30594
- max: exports_typebox.Optional(ThinkingLevelMapValueSchema)
30595
- });
30596
- var SamplingParamsSchema = exports_typebox.Record(exports_typebox.String(), exports_typebox.Unknown());
30597
- var SamplingParamsByThinkingLevelSchema = exports_typebox.Object({
30598
- off: exports_typebox.Optional(SamplingParamsSchema),
30599
- minimal: exports_typebox.Optional(SamplingParamsSchema),
30600
- low: exports_typebox.Optional(SamplingParamsSchema),
30601
- medium: exports_typebox.Optional(SamplingParamsSchema),
30602
- high: exports_typebox.Optional(SamplingParamsSchema),
30603
- xhigh: exports_typebox.Optional(SamplingParamsSchema),
30604
- max: exports_typebox.Optional(SamplingParamsSchema)
30605
- });
30606
- var ChatTemplateKwargScalarSchema = exports_typebox.Union([exports_typebox.String(), exports_typebox.Number(), exports_typebox.Boolean(), exports_typebox.Null()]);
30607
- var ChatTemplateKwargVariableSchema = exports_typebox.Object({
30608
- $var: exports_typebox.Union([exports_typebox.Literal("thinking.enabled"), exports_typebox.Literal("thinking.effort")]),
30609
- omitWhenOff: exports_typebox.Optional(exports_typebox.Boolean())
30691
+ only: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), {
30692
+ description: 'List of provider slugs to exclusively use for this request, for example ["bedrock", "anthropic"].'
30693
+ })),
30694
+ order: exports_typebox.Optional(exports_typebox.Array(exports_typebox.String(), {
30695
+ description: 'List of provider slugs to try in order, for example ["anthropic", "openai"].'
30696
+ }))
30697
+ }, {
30698
+ description: "Vercel AI Gateway routing preferences. Controls which upstream providers the gateway routes requests to. See https://vercel.com/docs/ai-gateway/models-and-providers/provider-options."
30610
30699
  });
30611
- var ChatTemplateKwargSchema = exports_typebox.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);
30700
+ var AnthropicAllowedFallbackModelSchema = exports_typebox.Object({
30701
+ provider: exports_typebox.String({ minLength: 1 }),
30702
+ model: exports_typebox.String({ minLength: 1 }),
30703
+ cost: ModelCostSchema
30704
+ }, { description: "An Anthropic server-side refusal fallback model with local pricing metadata." });
30705
+ function optionalCompatBoolean(options) {
30706
+ return exports_typebox.Optional(exports_typebox.Boolean(options));
30707
+ }
30708
+ function optionalSessionAffinityFormat(options) {
30709
+ return exports_typebox.Optional(sessionAffinityFormat(options));
30710
+ }
30612
30711
  var OpenAICompletionsCompatSchema = exports_typebox.Object({
30613
- supportsStore: exports_typebox.Optional(exports_typebox.Boolean()),
30614
- supportsDeveloperRole: exports_typebox.Optional(exports_typebox.Boolean()),
30615
- supportsReasoningEffort: exports_typebox.Optional(exports_typebox.Boolean()),
30616
- supportsUsageInStreaming: exports_typebox.Optional(exports_typebox.Boolean()),
30617
- supportsFinishReason: exports_typebox.Optional(exports_typebox.Boolean()),
30618
- maxTokensField: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("max_completion_tokens"), exports_typebox.Literal("max_tokens")])),
30619
- requiresToolResultName: exports_typebox.Optional(exports_typebox.Boolean()),
30620
- requiresAssistantAfterToolResult: exports_typebox.Optional(exports_typebox.Boolean()),
30621
- requiresThinkingAsText: exports_typebox.Optional(exports_typebox.Boolean()),
30622
- requiresReasoningContentOnAssistantMessages: exports_typebox.Optional(exports_typebox.Boolean()),
30712
+ supportsStore: exports_typebox.Optional(exports_typebox.Boolean({
30713
+ description: "Whether the provider supports the store field. Default: auto-detected from URL."
30714
+ })),
30715
+ supportsDeveloperRole: optionalCompatBoolean({
30716
+ description: "Whether the provider supports the developer role instead of system. Default: auto-detected from URL."
30717
+ }),
30718
+ supportsReasoningEffort: exports_typebox.Optional(exports_typebox.Boolean({
30719
+ description: "Whether the provider supports reasoning_effort. Default: auto-detected from URL."
30720
+ })),
30721
+ supportsUsageInStreaming: exports_typebox.Optional(exports_typebox.Boolean({
30722
+ description: "Whether the provider supports stream_options.include_usage for token usage in streaming responses.",
30723
+ default: true
30724
+ })),
30725
+ supportsFinishReason: exports_typebox.Optional(exports_typebox.Boolean({
30726
+ description: "Whether streamed responses include finish_reason. When false, pi infers stop or toolUse when the stream ends.",
30727
+ default: true
30728
+ })),
30729
+ maxTokensField: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("max_completion_tokens"), exports_typebox.Literal("max_tokens")], {
30730
+ description: "Which field to use for max tokens. Default: auto-detected from URL."
30731
+ })),
30732
+ requiresToolResultName: exports_typebox.Optional(exports_typebox.Boolean({ description: "Whether tool results require the name field. Default: auto-detected from URL." })),
30733
+ requiresAssistantAfterToolResult: exports_typebox.Optional(exports_typebox.Boolean({
30734
+ description: "Whether a user message after tool results requires an assistant message in between. Default: auto-detected from URL."
30735
+ })),
30736
+ requiresThinkingAsText: exports_typebox.Optional(exports_typebox.Boolean({
30737
+ description: "Whether thinking blocks must be converted to text blocks with <thinking> delimiters. Default: auto-detected from URL."
30738
+ })),
30739
+ requiresReasoningContentOnAssistantMessages: exports_typebox.Optional(exports_typebox.Boolean({
30740
+ description: "Whether all replayed assistant messages must include an empty reasoning_content field when reasoning is enabled. Default: auto-detected from URL."
30741
+ })),
30623
30742
  thinkingFormat: exports_typebox.Optional(exports_typebox.Union([
30624
30743
  exports_typebox.Literal("openai"),
30625
30744
  exports_typebox.Literal("openrouter"),
30745
+ exports_typebox.Literal("deepseek"),
30626
30746
  exports_typebox.Literal("together"),
30627
30747
  exports_typebox.Literal("baseten"),
30628
- exports_typebox.Literal("deepseek"),
30629
30748
  exports_typebox.Literal("zai"),
30630
30749
  exports_typebox.Literal("qwen"),
30631
30750
  exports_typebox.Literal("chat-template"),
30632
30751
  exports_typebox.Literal("qwen-chat-template"),
30633
30752
  exports_typebox.Literal("string-thinking"),
30634
30753
  exports_typebox.Literal("ant-ling")
30635
- ])),
30636
- chatTemplateKwargs: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ChatTemplateKwargSchema)),
30637
- chatTemplateArgs: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ChatTemplateKwargSchema)),
30638
- cacheControlFormat: exports_typebox.Optional(exports_typebox.Literal("anthropic")),
30754
+ ], {
30755
+ description: 'Format for reasoning or thinking parameters. When omitted, Pi auto-detects the format from the provider URL. "openai" uses reasoning_effort, "openrouter" uses reasoning.effort, "deepseek" uses thinking.type plus reasoning_effort when supported, "together" uses reasoning.enabled plus reasoning_effort when supported, "baseten" uses configurable chat_template_args plus reasoning_effort when supported, "zai" uses thinking.type, "qwen" uses top-level enable_thinking, "qwen-chat-template" uses chat_template_kwargs.enable_thinking and preserve_thinking, "chat-template" uses configurable chat_template_kwargs, "string-thinking" uses top-level thinking, and "ant-ling" uses reasoning.effort only when the mapped effort is non-null.'
30756
+ })),
30757
+ chatTemplateKwargs: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ChatTemplateKwargValueSchema, {
30758
+ description: 'Kwargs sent as chat_template_kwargs when thinkingFormat is "chat-template". Use $var with "thinking.enabled", "thinking.effort", or "thinking.budget" for pi-controlled values.'
30759
+ })),
30760
+ chatTemplateArgs: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ChatTemplateKwargValueSchema, {
30761
+ description: 'Arguments sent as chat_template_args when thinkingFormat is "baseten". Use $var with "thinking.enabled", "thinking.effort", or "thinking.budget" for pi-controlled values.'
30762
+ })),
30639
30763
  openRouterRouting: exports_typebox.Optional(OpenRouterRoutingSchema),
30640
30764
  vercelGatewayRouting: exports_typebox.Optional(VercelGatewayRoutingSchema),
30641
- supportsOpenAIGrammarTools: exports_typebox.Optional(exports_typebox.Boolean()),
30642
- supportsStrictMode: exports_typebox.Optional(exports_typebox.Boolean()),
30643
- sendSessionAffinityHeaders: exports_typebox.Optional(exports_typebox.Boolean()),
30644
- sessionAffinityFormat: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("openai"), exports_typebox.Literal("openai-nosession"), exports_typebox.Literal("openrouter")])),
30645
- supportsLongCacheRetention: exports_typebox.Optional(exports_typebox.Boolean()),
30646
- vllmPriority: exports_typebox.Optional(exports_typebox.Number())
30765
+ zaiToolStream: exports_typebox.Optional(exports_typebox.Boolean({
30766
+ description: "Whether z.ai supports top-level tool_stream for streaming tool call deltas.",
30767
+ default: false
30768
+ })),
30769
+ thinkingTokenBudgetField: exports_typebox.Optional(thinkingTokenBudgetField({
30770
+ description: 'Top-level request field used to cap reasoning tokens from thinkingBudgets. Reasoning and the answer share max_tokens on these endpoints. "thinking_token_budget" is vLLM, "thinking_budget" is Qwen, DashScope, or SGLang, and "thinking_budget_tokens" is llama.cpp. Off by default and not set on the generated catalog.'
30771
+ })),
30772
+ supportsThinkingTokenBudget: exports_typebox.Optional(exports_typebox.Boolean({
30773
+ description: 'Alias for thinkingTokenBudgetField: "thinking_token_budget" (vLLM). Prefer thinkingTokenBudgetField.',
30774
+ default: false
30775
+ })),
30776
+ supportsOpenAIGrammarTools: optionalCompatBoolean({
30777
+ description: "Whether the provider supports OpenAI custom tools with Lark or regex grammar formats. When false, grammar-constrained tools fall back to normal function tools. The generated catalog enables this for capable models.",
30778
+ default: false
30779
+ }),
30780
+ supportsMidConvoSystemMessages: optionalCompatBoolean({
30781
+ description: "Whether the exact model accepts system or developer messages after the conversation has started. When false, later system messages are folded into the leading system message. The generated catalog enables this for verified models.",
30782
+ default: false
30783
+ }),
30784
+ supportsMidConvoToolAdditions: exports_typebox.Optional(exports_typebox.Boolean({
30785
+ description: "Whether system messages can introduce additional tools mid-conversation. Requires supportsMidConvoSystemMessages. The generated catalog enables this for capable models.",
30786
+ default: false
30787
+ })),
30788
+ supportsStrictMode: optionalCompatBoolean({
30789
+ description: "Whether the provider supports the strict field in tool definitions. Generated capable models enable it explicitly.",
30790
+ default: false
30791
+ }),
30792
+ cacheControlFormat: exports_typebox.Optional(exports_typebox.Literal("anthropic", {
30793
+ description: "Cache control convention for prompt caching. Anthropic applies cache_control markers to the system prompt, last tool definition, and last user, assistant, or tool-result text content."
30794
+ })),
30795
+ sendSessionAffinityHeaders: optionalCompatBoolean({
30796
+ description: "Whether to send session-affinity data from options.sessionId. Default: true for OpenRouter endpoints, false otherwise."
30797
+ }),
30798
+ sessionAffinityFormat: optionalSessionAffinityFormat({
30799
+ description: "Session-affinity header format. openai sends session_id, x-client-request-id, and x-session-affinity; openai-nosession sends x-client-request-id and x-session-affinity; openrouter sends x-session-id. Does not affect prompt_cache_key. Default: auto-detected."
30800
+ }),
30801
+ supportsLongCacheRetention: optionalCompatBoolean({
30802
+ description: 'Whether the provider supports long prompt cache retention (prompt_cache_retention: "24h" or Anthropic-style cache_control.ttl: "1h", depending on format). Default: auto-detected from provider and URL.'
30803
+ }),
30804
+ vllmPriority: exports_typebox.Optional(exports_typebox.Number({
30805
+ description: "vLLM scheduler priority sent as the top-level priority request field. Lower values are handled earlier and the server default is 0. Only meaningful with --scheduling-policy priority. Off by default and not set on the generated catalog."
30806
+ }))
30807
+ }, {
30808
+ description: "Compatibility settings for OpenAI-compatible completions APIs. Use this to override URL-based auto-detection for custom providers.",
30809
+ additionalProperties: true
30647
30810
  });
30648
30811
  var OpenAIResponsesCompatSchema = exports_typebox.Object({
30649
- supportsDeveloperRole: exports_typebox.Optional(exports_typebox.Boolean()),
30650
- sessionAffinityFormat: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("openai"), exports_typebox.Literal("openai-nosession"), exports_typebox.Literal("openrouter")])),
30651
- supportsLongCacheRetention: exports_typebox.Optional(exports_typebox.Boolean()),
30652
- supportsStrictMode: exports_typebox.Optional(exports_typebox.Boolean()),
30653
- supportsOpenAIGrammarTools: exports_typebox.Optional(exports_typebox.Boolean()),
30654
- supportsMaxOutputTokens: exports_typebox.Optional(exports_typebox.Boolean())
30655
- });
30656
- var ModelCostRatesSchema = {
30657
- input: exports_typebox.Number(),
30658
- output: exports_typebox.Number(),
30659
- cacheRead: exports_typebox.Number(),
30660
- cacheWrite: exports_typebox.Number()
30661
- };
30662
- var ModelCostTierSchema = exports_typebox.Object({
30663
- inputTokensAbove: exports_typebox.Number(),
30664
- ...ModelCostRatesSchema
30665
- });
30666
- var ModelCostSchema = exports_typebox.Object({
30667
- ...ModelCostRatesSchema,
30668
- tiers: exports_typebox.Optional(exports_typebox.Array(ModelCostTierSchema))
30669
- });
30670
- var ModelPromptCacheSchema = exports_typebox.Object({
30671
- short: exports_typebox.Optional(exports_typebox.Number({ exclusiveMinimum: 0 })),
30672
- long: exports_typebox.Optional(exports_typebox.Number({ exclusiveMinimum: 0 }))
30673
- });
30674
- var ImageResizeSchema = exports_typebox.Object({
30675
- maxWidth: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30676
- maxHeight: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30677
- maxBytes: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30678
- jpegQuality: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1, maximum: 100 }))
30679
- });
30680
- var ModelInputLimitsSchema = exports_typebox.Object({
30681
- maxRequestBytes: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30682
- images: exports_typebox.Optional(exports_typebox.Object({
30683
- resize: exports_typebox.Optional(ImageResizeSchema),
30684
- maxPerMessage: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 })),
30685
- maxPerRequest: exports_typebox.Optional(exports_typebox.Integer({ minimum: 1 }))
30812
+ supportsDeveloperRole: optionalCompatBoolean({
30813
+ description: "Whether the provider supports the developer role instead of system.",
30814
+ default: true
30815
+ }),
30816
+ supportsMidConvoSystemMessages: optionalCompatBoolean({
30817
+ description: "Whether the exact model accepts developer or system messages after the conversation has started. When false, later system messages are folded into the leading system message. The generated catalog enables this for verified models.",
30818
+ default: false
30819
+ }),
30820
+ sessionAffinityFormat: optionalSessionAffinityFormat({
30821
+ description: "Session-affinity header format. openai sends session_id and x-client-request-id; openai-nosession sends x-client-request-id; openrouter sends x-session-id. Does not affect prompt_cache_key. Default: auto-detected."
30822
+ }),
30823
+ supportsLongCacheRetention: optionalCompatBoolean({
30824
+ description: 'Whether the provider supports long prompt cache retention. This uses prompt_cache_options.ttl: "30m" on GPT-5.6+ and prompt_cache_retention: "24h" on earlier models.',
30825
+ default: true
30826
+ }),
30827
+ supportsStrictMode: optionalCompatBoolean({
30828
+ description: "Whether the provider supports strict JSON-schema function tools. Defaults are API-specific; generated OpenAI models enable it explicitly."
30829
+ }),
30830
+ supportsOpenAIGrammarTools: optionalCompatBoolean({
30831
+ description: "Whether to emit OpenAI custom tools with Lark or regex grammar formats. When false, grammar-constrained tools fall back to normal function tools. The generated catalog enables this for capable models.",
30832
+ default: false
30833
+ }),
30834
+ supportsAdditionalTools: exports_typebox.Optional(exports_typebox.Boolean({
30835
+ description: "Whether the model supports message-anchored additional_tools input items.",
30836
+ default: false
30837
+ })),
30838
+ supportsToolSearch: exports_typebox.Optional(exports_typebox.Boolean({
30839
+ description: "Whether the model supports client-executed tool search for transcript-anchored additions.",
30840
+ default: false
30841
+ })),
30842
+ supportsExplicitPromptCacheMode: exports_typebox.Optional(exports_typebox.Boolean({
30843
+ description: "Whether the model accepts prompt_cache_options. Older OpenAI models reject the parameter.",
30844
+ default: false
30845
+ })),
30846
+ supportsMaxOutputTokens: exports_typebox.Optional(exports_typebox.Boolean({
30847
+ description: "Whether the provider accepts max_output_tokens. Some Codex-protocol gateways reject it.",
30848
+ default: true
30686
30849
  }))
30687
- });
30850
+ }, { description: "Compatibility settings for OpenAI Responses APIs.", additionalProperties: true });
30688
30851
  var AnthropicMessagesCompatSchema = exports_typebox.Object({
30689
- supportsEagerToolInputStreaming: exports_typebox.Optional(exports_typebox.Boolean()),
30690
- supportsLongCacheRetention: exports_typebox.Optional(exports_typebox.Boolean()),
30691
- sendSessionAffinityHeaders: exports_typebox.Optional(exports_typebox.Boolean()),
30692
- supportsCacheControlOnTools: exports_typebox.Optional(exports_typebox.Boolean()),
30693
- supportsTemperature: exports_typebox.Optional(exports_typebox.Boolean()),
30694
- forceAdaptiveThinking: exports_typebox.Optional(exports_typebox.Boolean()),
30695
- allowEmptySignature: exports_typebox.Optional(exports_typebox.Boolean()),
30696
- supportsStrictTools: exports_typebox.Optional(exports_typebox.Boolean()),
30697
- supportsMidConvoEffort: exports_typebox.Optional(exports_typebox.Boolean()),
30698
- allowedFallbackModels: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Object({
30699
- provider: exports_typebox.String({ minLength: 1 }),
30700
- model: exports_typebox.String({ minLength: 1 }),
30701
- cost: ModelCostSchema
30702
- }), { maxItems: 3 }))
30852
+ supportsEagerToolInputStreaming: exports_typebox.Optional(exports_typebox.Boolean({
30853
+ description: "Whether the provider accepts per-tool eager_input_streaming. When false, the Anthropic provider omits tools[].eager_input_streaming and sends the legacy fine-grained-tool-streaming-2025-05-14 beta header for tool-enabled requests.",
30854
+ default: true
30855
+ })),
30856
+ supportsLongCacheRetention: optionalCompatBoolean({
30857
+ description: "Whether the provider supports Anthropic long cache retention through cache_control.ttl.",
30858
+ default: true
30859
+ }),
30860
+ sendSessionAffinityHeaders: optionalCompatBoolean({
30861
+ description: "Whether to send x-session-affinity from options.sessionId when caching is enabled. Required for providers like Fireworks that use session affinity for prompt cache routing; requests to the same replica maximize cache hits. Default: true for OpenRouter endpoints, false otherwise."
30862
+ }),
30863
+ sessionAffinityFormat: exports_typebox.Optional(exports_typebox.Literal("openrouter", {
30864
+ description: "Session-affinity format. openrouter sends x-session-id; when unset, sends x-session-affinity."
30865
+ })),
30866
+ supportsCacheControlOnTools: exports_typebox.Optional(exports_typebox.Boolean({
30867
+ description: "Whether the provider supports Anthropic-style cache_control markers on tool definitions. When false, cache_control is omitted from tool parameters. Some Anthropic-compatible providers, such as Fireworks, do not support this field on tools and may reject or ignore it.",
30868
+ default: true
30869
+ })),
30870
+ supportsTemperature: exports_typebox.Optional(exports_typebox.Boolean({
30871
+ description: "Whether the model accepts the Anthropic temperature request field. Claude Opus 4.7+ rejects non-default values.",
30872
+ default: true
30873
+ })),
30874
+ forceAdaptiveThinking: exports_typebox.Optional(exports_typebox.Boolean({
30875
+ description: "Whether to force adaptive thinking (thinking.type: adaptive plus output_config.effort) regardless of model ID. Built-in models that require adaptive thinking set this in generated metadata. Custom Anthropic-compatible providers can set this to true for any model whose upstream requires the adaptive format. Set false to opt out on overridden built-in models.",
30876
+ default: false
30877
+ })),
30878
+ allowEmptySignature: exports_typebox.Optional(exports_typebox.Boolean({
30879
+ description: "Whether to replay empty thinking signatures instead of converting thinking to text.",
30880
+ default: false
30881
+ })),
30882
+ supportsStrictTools: exports_typebox.Optional(exports_typebox.Boolean({
30883
+ description: "Whether the provider supports Anthropic strict tool schemas. Generated Anthropic models enable it explicitly.",
30884
+ default: false
30885
+ })),
30886
+ supportsMidConvoEffort: exports_typebox.Optional(exports_typebox.Boolean({
30887
+ description: "Whether the exact model transport supports effort-only system messages and thinking binding controls.",
30888
+ default: false
30889
+ })),
30890
+ supportsMidConvoSystemMessages: optionalCompatBoolean({
30891
+ description: "Whether the exact model accepts system-role messages inside the conversation. When false, later system messages are folded into the top-level system prompt.",
30892
+ default: false
30893
+ }),
30894
+ supportsMidConvoToolChanges: exports_typebox.Optional(exports_typebox.Boolean({
30895
+ description: "Whether the exact model accepts mid-conversation tool_addition and tool_removal blocks. Requires supportsMidConvoSystemMessages.",
30896
+ default: false
30897
+ })),
30898
+ allowedFallbackModels: exports_typebox.Optional(exports_typebox.Array(AnthropicAllowedFallbackModelSchema, {
30899
+ maxItems: 3,
30900
+ description: "Models Anthropic accepts for server-side refusal fallback, with local pricing metadata for returned fallback responses. When absent or empty, callers must omit fallbacks; Anthropic rejects the field for models with no permitted fallback targets."
30901
+ }))
30902
+ }, { description: "Compatibility settings for Anthropic Messages-compatible APIs.", additionalProperties: true });
30903
+ var BedrockCompatSchema = exports_typebox.Object({
30904
+ supportsStrictMode: optionalCompatBoolean({
30905
+ description: "Whether the model supports Bedrock strict tool schemas.",
30906
+ default: false
30907
+ })
30908
+ }, { description: "Compatibility settings for Amazon Bedrock models.", additionalProperties: true });
30909
+ var MistralConversationsCompatSchema = exports_typebox.Object({
30910
+ supportsMidConvoSystemMessages: optionalCompatBoolean({
30911
+ description: "Whether the exact model accepts system messages after the conversation has started. When false, later system messages are folded into the leading system message.",
30912
+ default: false
30913
+ })
30914
+ }, { description: "Compatibility settings for the Mistral chat API.", additionalProperties: true });
30915
+ var ProviderCompatPropertyOverrides = {
30916
+ supportsDeveloperRole: optionalCompatBoolean({
30917
+ description: "Whether the provider supports the developer role instead of system. Defaults are API-specific."
30918
+ }),
30919
+ supportsMidConvoSystemMessages: optionalCompatBoolean({
30920
+ description: "Whether the exact model accepts system or developer messages after the conversation has started. When false, later system messages are folded into the leading system message.",
30921
+ default: false
30922
+ }),
30923
+ sessionAffinityFormat: optionalSessionAffinityFormat({
30924
+ description: "Session-affinity header format. Defaults are API-specific or auto-detected."
30925
+ }),
30926
+ supportsLongCacheRetention: optionalCompatBoolean({
30927
+ description: "Whether the provider supports long prompt cache retention. Defaults are API-specific or auto-detected."
30928
+ }),
30929
+ supportsStrictMode: optionalCompatBoolean({
30930
+ description: "Whether the provider supports strict tool schemas. Defaults are API-specific."
30931
+ }),
30932
+ supportsOpenAIGrammarTools: optionalCompatBoolean({
30933
+ description: "Whether the provider supports OpenAI custom tools with Lark or regex grammar formats. When false, grammar-constrained tools fall back to normal function tools.",
30934
+ default: false
30935
+ }),
30936
+ sendSessionAffinityHeaders: optionalCompatBoolean({
30937
+ description: "Whether to send session-affinity data from options.sessionId. Defaults are API-specific."
30938
+ })
30939
+ };
30940
+ function mergeCompatProperties(propertyGroups, overrides) {
30941
+ const merged = {};
30942
+ const duplicateNames = new Set;
30943
+ for (const properties of propertyGroups) {
30944
+ for (const [name, schema] of Object.entries(properties)) {
30945
+ if (merged[name] !== undefined) {
30946
+ duplicateNames.add(name);
30947
+ if (!(name in overrides)) {
30948
+ throw new Error(`Duplicate compatibility schema property requires an override: ${name}`);
30949
+ }
30950
+ }
30951
+ merged[name] = schema;
30952
+ }
30953
+ }
30954
+ for (const name of Object.keys(overrides)) {
30955
+ if (!duplicateNames.has(name)) {
30956
+ throw new Error(`Compatibility schema override does not resolve a duplicate property: ${name}`);
30957
+ }
30958
+ }
30959
+ return { ...merged, ...overrides };
30960
+ }
30961
+ var CompatSchemasByApi = {
30962
+ "openai-completions": OpenAICompletionsCompatSchema,
30963
+ "openai-responses": OpenAIResponsesCompatSchema,
30964
+ "anthropic-messages": AnthropicMessagesCompatSchema,
30965
+ "bedrock-converse-stream": BedrockCompatSchema,
30966
+ "mistral-conversations": MistralConversationsCompatSchema
30967
+ };
30968
+ var ProviderCompatProperties = mergeCompatProperties(Object.values(CompatSchemasByApi).map((schema) => schema.properties), ProviderCompatPropertyOverrides);
30969
+ var ProviderCompatSchema = exports_typebox.Object(ProviderCompatProperties, {
30970
+ description: "Provider and model compatibility overrides.",
30971
+ additionalProperties: true
30703
30972
  });
30704
- var ProviderCompatSchema = exports_typebox.Union([
30705
- OpenAICompletionsCompatSchema,
30706
- OpenAIResponsesCompatSchema,
30707
- AnthropicMessagesCompatSchema
30708
- ]);
30973
+
30974
+ // node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js
30975
+ function stripJsonComments(input) {
30976
+ return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => m[0] === '"' ? m : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === '"' ? m : ""));
30977
+ }
30978
+
30979
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/model-config.js
30980
+ var SamplingParamsSchema = exports_typebox.Record(exports_typebox.String(), exports_typebox.Unknown());
30981
+ var SamplingParamsByThinkingLevelSchema = exports_typebox.Object({
30982
+ off: exports_typebox.Optional(SamplingParamsSchema),
30983
+ minimal: exports_typebox.Optional(SamplingParamsSchema),
30984
+ low: exports_typebox.Optional(SamplingParamsSchema),
30985
+ medium: exports_typebox.Optional(SamplingParamsSchema),
30986
+ high: exports_typebox.Optional(SamplingParamsSchema),
30987
+ xhigh: exports_typebox.Optional(SamplingParamsSchema),
30988
+ max: exports_typebox.Optional(SamplingParamsSchema)
30989
+ });
30990
+ var PositiveTokenCountSchema = exports_typebox.Number({ exclusiveMinimum: 0 });
30709
30991
  var ModelDefinitionSchema = exports_typebox.Object({
30710
30992
  id: exports_typebox.String({ minLength: 1 }),
30711
30993
  name: exports_typebox.Optional(exports_typebox.String({ minLength: 1 })),
@@ -30713,12 +30995,12 @@ var ModelDefinitionSchema = exports_typebox.Object({
30713
30995
  baseUrl: exports_typebox.Optional(exports_typebox.String({ minLength: 1 })),
30714
30996
  reasoning: exports_typebox.Optional(exports_typebox.Boolean()),
30715
30997
  thinkingLevelMap: exports_typebox.Optional(ThinkingLevelMapSchema),
30716
- input: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Union([exports_typebox.Literal("text"), exports_typebox.Literal("image")]))),
30998
+ input: exports_typebox.Optional(exports_typebox.Array(ModelInputModalitySchema)),
30717
30999
  inputLimits: exports_typebox.Optional(ModelInputLimitsSchema),
30718
31000
  cost: exports_typebox.Optional(ModelCostSchema),
30719
31001
  promptCache: exports_typebox.Optional(ModelPromptCacheSchema),
30720
- contextWindow: exports_typebox.Optional(exports_typebox.Number()),
30721
- maxTokens: exports_typebox.Optional(exports_typebox.Number()),
31002
+ contextWindow: exports_typebox.Optional(PositiveTokenCountSchema),
31003
+ maxTokens: exports_typebox.Optional(PositiveTokenCountSchema),
30722
31004
  samplingParams: exports_typebox.Optional(SamplingParamsSchema),
30723
31005
  samplingParamsByThinkingLevel: exports_typebox.Optional(SamplingParamsByThinkingLevelSchema),
30724
31006
  headers: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), exports_typebox.String())),
@@ -30728,18 +31010,12 @@ var ModelOverrideSchema = exports_typebox.Object({
30728
31010
  name: exports_typebox.Optional(exports_typebox.String({ minLength: 1 })),
30729
31011
  reasoning: exports_typebox.Optional(exports_typebox.Boolean()),
30730
31012
  thinkingLevelMap: exports_typebox.Optional(ThinkingLevelMapSchema),
30731
- input: exports_typebox.Optional(exports_typebox.Array(exports_typebox.Union([exports_typebox.Literal("text"), exports_typebox.Literal("image")]))),
31013
+ input: exports_typebox.Optional(exports_typebox.Array(ModelInputModalitySchema)),
30732
31014
  inputLimits: exports_typebox.Optional(ModelInputLimitsSchema),
30733
- cost: exports_typebox.Optional(exports_typebox.Object({
30734
- input: exports_typebox.Optional(exports_typebox.Number()),
30735
- output: exports_typebox.Optional(exports_typebox.Number()),
30736
- cacheRead: exports_typebox.Optional(exports_typebox.Number()),
30737
- cacheWrite: exports_typebox.Optional(exports_typebox.Number()),
30738
- tiers: exports_typebox.Optional(exports_typebox.Array(ModelCostTierSchema))
30739
- })),
31015
+ cost: exports_typebox.Optional(exports_typebox.Partial(ModelCostSchema)),
30740
31016
  promptCache: exports_typebox.Optional(ModelPromptCacheSchema),
30741
- contextWindow: exports_typebox.Optional(exports_typebox.Number()),
30742
- maxTokens: exports_typebox.Optional(exports_typebox.Number()),
31017
+ contextWindow: exports_typebox.Optional(PositiveTokenCountSchema),
31018
+ maxTokens: exports_typebox.Optional(PositiveTokenCountSchema),
30743
31019
  samplingParams: exports_typebox.Optional(SamplingParamsSchema),
30744
31020
  samplingParamsByThinkingLevel: exports_typebox.Optional(SamplingParamsByThinkingLevelSchema),
30745
31021
  headers: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), exports_typebox.String())),
@@ -30757,8 +31033,12 @@ var ProviderConfigSchema = exports_typebox.Object({
30757
31033
  models: exports_typebox.Optional(exports_typebox.Array(ModelDefinitionSchema)),
30758
31034
  modelOverrides: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ModelOverrideSchema))
30759
31035
  });
30760
- var ModelsConfigSchema = exports_typebox.Object({
31036
+ var ModelsConfigProperties = {
30761
31037
  providers: exports_typebox.Record(exports_typebox.String(), ProviderConfigSchema)
31038
+ };
31039
+ var ModelsConfigSchema = exports_typebox.Object({
31040
+ $schema: exports_typebox.Optional(exports_typebox.String()),
31041
+ ...ModelsConfigProperties
30762
31042
  });
30763
31043
  var validateModelsConfig = Compile(ModelsConfigSchema);
30764
31044
  function formatValidationPath(error) {
@@ -30818,9 +31098,8 @@ ${errors2}
30818
31098
 
30819
31099
  File: ${path}`);
30820
31100
  }
30821
- const config = parsed;
30822
31101
  const providers = new Map;
30823
- for (const [providerId, provider] of Object.entries(config.providers)) {
31102
+ for (const [providerId, provider] of Object.entries(parsed.providers)) {
30824
31103
  providers.set(providerId, deepFreeze(structuredClone(provider)));
30825
31104
  }
30826
31105
  return new ModelConfig(providers);
@@ -31428,13 +31707,31 @@ function parseCatalog(providerId, value) {
31428
31707
  throw new Error(`Invalid model catalog for provider "${providerId}"`);
31429
31708
  return entries.filter((entry) => typeof entry === "object" && entry !== null && ("id" in entry)).filter(isSupportedModelType).map((model) => ({ ...model, provider: providerId }));
31430
31709
  }
31710
+ async function readCatalog(providerId, response) {
31711
+ const lastModified = Date.parse(response.headers.get("last-modified") ?? "");
31712
+ return {
31713
+ models: parseCatalog(providerId, await response.json()),
31714
+ lastModified: Number.isNaN(lastModified) ? 0 : lastModified,
31715
+ etag: response.headers.get("etag") ?? undefined
31716
+ };
31717
+ }
31718
+ function isNewer(lastModified, localGeneratedAt) {
31719
+ return localGeneratedAt === undefined || lastModified !== undefined && lastModified > localGeneratedAt;
31720
+ }
31431
31721
  function remoteModels(entry, localGeneratedAt) {
31432
- if (!entry)
31433
- return [];
31434
- if (localGeneratedAt !== undefined && (entry.lastModified === undefined || entry.lastModified <= localGeneratedAt)) {
31435
- return [];
31436
- }
31437
- return entry.models;
31722
+ return entry && isNewer(entry.lastModified, localGeneratedAt) ? entry.models : [];
31723
+ }
31724
+ function requestCatalog(providerId, catalogBaseUrl, signal, validator) {
31725
+ const url = new URL(`/api/models/providers/${encodeURIComponent(providerId)}`, catalogBaseUrl);
31726
+ url.searchParams.set("types", REMOTE_CATALOG_MODEL_TYPES.join(","));
31727
+ return fetchWithRetry(url, {
31728
+ headers: {
31729
+ accept: "application/json",
31730
+ "User-Agent": getPiUserAgent(VERSION),
31731
+ ...validator ? { "if-none-match": validator } : {}
31732
+ },
31733
+ signal
31734
+ }, { attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS });
31438
31735
  }
31439
31736
  function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL, localGeneratedAt) {
31440
31737
  let dynamicModels = [];
@@ -31458,16 +31755,7 @@ function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL,
31458
31755
  return;
31459
31756
  }
31460
31757
  const validator = stored && stored.models.length > 0 ? stored.etag : undefined;
31461
- const url = new URL(`/api/models/providers/${encodeURIComponent(provider.id)}`, catalogBaseUrl);
31462
- url.searchParams.set("types", REMOTE_CATALOG_MODEL_TYPES.join(","));
31463
- const response = await fetchWithRetry(url, {
31464
- headers: {
31465
- accept: "application/json",
31466
- "User-Agent": getPiUserAgent(VERSION),
31467
- ...validator ? { "if-none-match": validator } : {}
31468
- },
31469
- signal: context.signal
31470
- }, { attemptTimeoutMs: REMOTE_CATALOG_ATTEMPT_TIMEOUT_MS });
31758
+ const response = await requestCatalog(provider.id, catalogBaseUrl, context.signal, validator);
31471
31759
  if (context.signal.aborted)
31472
31760
  return;
31473
31761
  const checkedAt = Date.now();
@@ -31490,16 +31778,10 @@ function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL,
31490
31778
  await context.publish({ persist: { ...stored ?? { models: [] }, checkedAt } });
31491
31779
  throw new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);
31492
31780
  }
31493
- const refreshed = parseCatalog(provider.id, await response.json());
31494
- const lastModified = Date.parse(response.headers.get("last-modified") ?? "");
31781
+ const catalog = await readCatalog(provider.id, response);
31495
31782
  if (context.signal.aborted)
31496
31783
  return;
31497
- const entry = {
31498
- models: refreshed,
31499
- checkedAt,
31500
- lastModified: Number.isNaN(lastModified) ? 0 : lastModified,
31501
- etag: response.headers.get("etag") ?? undefined
31502
- };
31784
+ const entry = { ...catalog, checkedAt };
31503
31785
  const published = remoteModels(entry, localGeneratedAt);
31504
31786
  await context.publish({
31505
31787
  persist: entry,
@@ -31510,6 +31792,48 @@ function withRemoteCatalog(provider, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL,
31510
31792
  }
31511
31793
  };
31512
31794
  }
31795
+ function withPersonalizedCatalog(provider, personalize, catalogBaseUrl = DEFAULT_CATALOG_BASE_URL, localGeneratedAt) {
31796
+ let personalModels = [];
31797
+ const builtinModels = () => provider.getAllModels?.() ?? provider.getModels();
31798
+ const getAllModels = () => personalModels.length > 0 ? personalModels : builtinModels();
31799
+ return {
31800
+ ...provider,
31801
+ getModels: () => getAllModels().filter((model) => isModelType(model, "chat")),
31802
+ getAllModels,
31803
+ refreshModels: async (context) => {
31804
+ const restored = (context.stored?.models ?? []).filter((model) => model.provider === provider.id);
31805
+ if (!await context.publish({
31806
+ update: () => {
31807
+ personalModels = restored;
31808
+ }
31809
+ })) {
31810
+ return;
31811
+ }
31812
+ if (!context.allowNetwork || context.signal.aborted)
31813
+ return;
31814
+ const response = await requestCatalog(provider.id, catalogBaseUrl, context.signal);
31815
+ if (context.signal.aborted)
31816
+ return;
31817
+ let remote = [];
31818
+ if (response.status !== 404 && response.status !== 501) {
31819
+ if (!response.ok)
31820
+ throw new Error(`Model catalog request failed for ${provider.id}: ${response.status}`);
31821
+ const catalog = await readCatalog(provider.id, response);
31822
+ if (isNewer(catalog.lastModified, localGeneratedAt))
31823
+ remote = catalog.models;
31824
+ }
31825
+ const personalized = await personalize(mergeModels(builtinModels(), remote), context);
31826
+ if (context.signal.aborted)
31827
+ return;
31828
+ await context.publish({
31829
+ persist: { models: personalized, checkedAt: Date.now() },
31830
+ update: () => {
31831
+ personalModels = personalized;
31832
+ }
31833
+ });
31834
+ }
31835
+ };
31836
+ }
31513
31837
 
31514
31838
  // node_modules/@earendil-works/pi-coding-agent/dist/core/runtime-credentials.js
31515
31839
  class RuntimeCredentials {
@@ -31553,7 +31877,7 @@ class RuntimeCredentials {
31553
31877
  // node_modules/@earendil-works/pi-coding-agent/dist/core/virtual-models.js
31554
31878
  var VIRTUAL_MODEL_API = "pi-virtual";
31555
31879
  var VIRTUAL_MODEL_STATE_ENTRY = "pi.virtual-model-state";
31556
- var THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
31880
+ var THINKING_LEVELS2 = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
31557
31881
  function isVirtualModel(model) {
31558
31882
  return model.api === VIRTUAL_MODEL_API;
31559
31883
  }
@@ -31603,7 +31927,7 @@ function getVirtualModelState(branch, provider, modelId) {
31603
31927
  function createVirtualModel(definition) {
31604
31928
  const levels = definition.thinkingLevels ?? ["off"];
31605
31929
  const thinkingLevelMap = {};
31606
- for (const level of THINKING_LEVELS)
31930
+ for (const level of THINKING_LEVELS2)
31607
31931
  thinkingLevelMap[level] = levels.includes(level) ? level : null;
31608
31932
  return {
31609
31933
  id: definition.id,
@@ -31722,7 +32046,14 @@ class ModelRuntime {
31722
32046
  const config = await ModelConfig.load(modelsPath);
31723
32047
  const modelsStore = options.modelsStore ?? (modelsPath ? new FileModelsStore(options.modelsStorePath ?? join4(dirname2(modelsPath), "models-store.json")) : new InMemoryCodingAgentModelsStore);
31724
32048
  const builtinModelDataGeneratedAt = getBuiltinModelDataGeneratedAt();
31725
- const providers = builtinProviders().map((provider) => provider.id === "radius" ? provider : withRemoteCatalog(provider, options.catalogBaseUrl, builtinModelDataGeneratedAt));
32049
+ const providers = builtinProviders().map((provider) => {
32050
+ if (provider.id === "radius")
32051
+ return provider;
32052
+ if (provider.id === "openrouter") {
32053
+ return withPersonalizedCatalog(provider, personalizeOpenRouterCatalog, options.catalogBaseUrl, builtinModelDataGeneratedAt);
32054
+ }
32055
+ return withRemoteCatalog(provider, options.catalogBaseUrl, builtinModelDataGeneratedAt);
32056
+ });
31726
32057
  const runtime = new ModelRuntime(credentials, config, modelsPath, modelsStore, providers, process.env.PI_OFFLINE === undefined);
31727
32058
  runtime.configureRadiusProviders();
31728
32059
  runtime.rebuildProviders();
@@ -32533,7 +32864,7 @@ function getCreateJiti() {
32533
32864
  }
32534
32865
  var virtualModulesPromise;
32535
32866
  function getVirtualModules() {
32536
- virtualModulesPromise ??= import("./virtual-modules-rdjmcg7q.js").then((module) => module.VIRTUAL_MODULES);
32867
+ virtualModulesPromise ??= import("./virtual-modules-b3ga2m65.js").then((module) => module.VIRTUAL_MODULES);
32537
32868
  return virtualModulesPromise;
32538
32869
  }
32539
32870
  var _aliases = null;
@@ -35860,7 +36191,7 @@ function matchesAnyPattern(filePath, patterns, baseDir) {
35860
36191
  const parentName = isSkillFile ? basename2(parentDir) : undefined;
35861
36192
  const parentDirPosix = isSkillFile ? toPosixPath(parentDir) : undefined;
35862
36193
  return patterns.some((pattern) => {
35863
- const normalizedPattern = toPosixPath(pattern);
36194
+ const normalizedPattern = toPosixPath(normalizePath(pattern));
35864
36195
  if (minimatch(rel, normalizedPattern) || minimatch(name, normalizedPattern) || minimatch(filePathPosix, normalizedPattern)) {
35865
36196
  return true;
35866
36197
  }
@@ -35871,7 +36202,7 @@ function matchesAnyPattern(filePath, patterns, baseDir) {
35871
36202
  }
35872
36203
  function normalizeExactPattern(pattern) {
35873
36204
  const normalized = pattern.startsWith("./") || pattern.startsWith(".\\") ? pattern.slice(2) : pattern;
35874
- return toPosixPath(normalized);
36205
+ return toPosixPath(normalizePath(normalized));
35875
36206
  }
35876
36207
  function matchesAnyExactPattern(filePath, patterns, baseDir) {
35877
36208
  if (patterns.length === 0)
@@ -38212,7 +38543,7 @@ function loadProjectContextFiles(options) {
38212
38543
  let currentDir = resolvedCwd;
38213
38544
  while (true) {
38214
38545
  const contextFile = loadContextFileFromDir(currentDir);
38215
- const isShadowed = shadowedContextFile !== undefined && canonicalizePath(contextFile?.path ?? "") === shadowedContextFile;
38546
+ const isShadowed = shadowedContextFile !== undefined && contextFile !== null && join10(canonicalizePath(currentDir), basename5(contextFile.path)) === shadowedContextFile;
38216
38547
  if (contextFile && !isShadowed && !seenPaths.has(contextFile.path)) {
38217
38548
  ancestorContextFiles.unshift(contextFile);
38218
38549
  seenPaths.add(contextFile.path);
@@ -39853,21 +40184,14 @@ function serializeConversation(messages) {
39853
40184
  if (content)
39854
40185
  parts.push(`[User]: ${content}`);
39855
40186
  } else if (msg.role === "assistant") {
39856
- const thinkingParts = [];
39857
40187
  const toolCalls = [];
39858
40188
  for (const block of msg.content) {
39859
- if (block.type === "thinking") {
39860
- thinkingParts.push(block.thinking);
39861
- } else if (block.type === "toolCall") {
40189
+ if (block.type === "toolCall") {
39862
40190
  const args = block.arguments;
39863
40191
  const argsStr = Object.entries(args).map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(", ");
39864
40192
  toolCalls.push(`${block.name}(${argsStr})`);
39865
40193
  }
39866
40194
  }
39867
- if (thinkingParts.length > 0) {
39868
- parts.push(`[Assistant thinking]: ${thinkingParts.join(`
39869
- `)}`);
39870
- }
39871
40195
  if (msg.content.some((block) => block.type === "text")) {
39872
40196
  parts.push(`[Assistant]: ${contentText(msg.content)}`);
39873
40197
  }
@@ -42585,7 +42909,7 @@ class ExtensionRunner {
42585
42909
  }
42586
42910
  return headers;
42587
42911
  }
42588
- async emitBeforeAgentStart(prompt, images, systemPromptOptions) {
42912
+ async emitBeforeAgentStart(trigger, systemPromptOptions) {
42589
42913
  const currentOptions = normalizeBuildSystemPromptOptions(systemPromptOptions);
42590
42914
  const renderCurrentSystemPrompt = () => buildSystemPrompt(currentOptions);
42591
42915
  const ctx = Object.defineProperties({}, Object.getOwnPropertyDescriptors(this.createContext()));
@@ -42598,9 +42922,8 @@ class ExtensionRunner {
42598
42922
  for (const handler of handlers) {
42599
42923
  try {
42600
42924
  const event = {
42925
+ ...trigger,
42601
42926
  type: "before_agent_start",
42602
- prompt,
42603
- images,
42604
42927
  get systemPrompt() {
42605
42928
  return renderCurrentSystemPrompt();
42606
42929
  },
@@ -43251,17 +43574,6 @@ ${tailText}`, truncated: true };
43251
43574
  // node_modules/@earendil-works/pi-coding-agent/dist/core/tools/renderers/bash.js
43252
43575
  var BASH_PREVIEW_LINES = 5;
43253
43576
  var BASH_UPDATE_THROTTLE_MS = 100;
43254
- function formatDuration(ms) {
43255
- const seconds = ms / 1000;
43256
- if (seconds < 60)
43257
- return `${seconds.toFixed(1)}s`;
43258
- const totalSeconds = Math.floor(seconds);
43259
- const minutes = Math.floor(totalSeconds / 60);
43260
- const remainder = totalSeconds % 60;
43261
- if (minutes < 60)
43262
- return `${minutes}m ${remainder}s`;
43263
- return `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;
43264
- }
43265
43577
  function formatShellCall(args, prompt) {
43266
43578
  const command = str(args?.command);
43267
43579
  const timeout = args?.timeout;
@@ -43269,7 +43581,7 @@ function formatShellCall(args, prompt) {
43269
43581
  const commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg("toolOutput", "...");
43270
43582
  return theme.fg("toolTitle", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;
43271
43583
  }
43272
- function rebuildBashResultRenderComponent(component, result, options, showImages, startedAt, endedAt, durationMs) {
43584
+ function rebuildBashResultRenderComponent(component, result, options, showImages, timerText) {
43273
43585
  component.clear();
43274
43586
  let output = getTextOutput(result, showImages).trim();
43275
43587
  const truncation = result.details?.truncation;
@@ -43314,42 +43626,22 @@ ${styledOutput}`, 0, 0));
43314
43626
  component.addChild(new Text(`
43315
43627
  ${theme.fg("warning", `[${warnings.join(". ")}]`)}`, 0, 0));
43316
43628
  }
43317
- if (!options.isPartial && durationMs !== undefined) {
43318
- component.addChild(new Text(`
43319
- ${theme.fg("muted", `Took ${formatDuration(durationMs)}`)}`, 0, 0));
43320
- } else if (startedAt !== undefined) {
43321
- const label = options.isPartial ? "Elapsed" : "Took";
43322
- const endTime = endedAt ?? Date.now();
43629
+ if (timerText)
43323
43630
  component.addChild(new Text(`
43324
- ${theme.fg("muted", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));
43325
- }
43631
+ ${theme.fg("muted", timerText)}`, 0, 0));
43326
43632
  }
43327
43633
  function createShellRenderers(prompt) {
43328
43634
  return {
43329
43635
  renderCall(args, _theme, context) {
43330
- const state = context.state;
43331
- if (context.executionStarted && state.startedAt === undefined) {
43332
- state.startedAt = Date.now();
43333
- state.endedAt = undefined;
43334
- }
43636
+ startToolTimer(context);
43335
43637
  const text = context.lastComponent ?? new Text("", 0, 0);
43336
43638
  text.setText(formatShellCall(args, prompt));
43337
43639
  return text;
43338
43640
  },
43339
43641
  renderResult(result, options, _theme, context) {
43340
- const state = context.state;
43341
- if (state.startedAt !== undefined && options.isPartial && !state.interval) {
43342
- state.interval = setInterval(() => context.invalidate(), 1000);
43343
- }
43344
- if (!options.isPartial || context.isError) {
43345
- state.endedAt ??= Date.now();
43346
- if (state.interval) {
43347
- clearInterval(state.interval);
43348
- state.interval = undefined;
43349
- }
43350
- }
43642
+ const timerText = toolTimerText(context, options.isPartial);
43351
43643
  const component = context.lastComponent ?? new Container;
43352
- rebuildBashResultRenderComponent(component, result, options, context.showImages, state.startedAt, state.endedAt, context.durationMs);
43644
+ rebuildBashResultRenderComponent(component, result, options, context.showImages, timerText);
43353
43645
  component.invalidate();
43354
43646
  return component;
43355
43647
  }
@@ -47621,6 +47913,8 @@ class AgentSession {
47621
47913
  this._resolveIdleWaitIfIdle();
47622
47914
  }
47623
47915
  _handleAgentEvent = async (event) => {
47916
+ if (event.type === "agent_start" && this._agentRunAbortRequested)
47917
+ this.agent.abort();
47624
47918
  if (this._nestedToolCalls) {
47625
47919
  if (event.type === "message_start" && event.message.role === "toolResult") {
47626
47920
  const message = event.message;
@@ -47914,6 +48208,7 @@ class AgentSession {
47914
48208
  exposure: this._getToolExposure(definition.name),
47915
48209
  ...definition.namespace ? { namespace: definition.namespace } : {},
47916
48210
  ...definition.annotations ? { annotations: { ...definition.annotations } } : {},
48211
+ ...definition.reachesTools ? { reachesTools: definition.reachesTools } : {},
47917
48212
  sourceInfo
47918
48213
  }));
47919
48214
  }
@@ -48130,12 +48425,25 @@ class AgentSession {
48130
48425
  this._pendingToolNames = new Set(names.filter((name) => this._isAllowedTool(name)));
48131
48426
  this._setActiveTools(names);
48132
48427
  }
48133
- async _runAgentPrompt(messages) {
48428
+ async _startRun(trigger, onStarted) {
48429
+ this._isAgentRunActive = true;
48134
48430
  this._agentRunAbortRequested = false;
48431
+ let messages;
48432
+ try {
48433
+ messages = await this._prepareRun(trigger);
48434
+ } catch (error) {
48435
+ this._isAgentRunActive = false;
48436
+ this._flushPendingBashMessages();
48437
+ this._flushPendingCustomMessages();
48438
+ this._resolveIdleWaitIfIdle();
48439
+ throw error;
48440
+ }
48441
+ this._flushPendingBashMessages();
48442
+ this._flushPendingCustomMessages();
48443
+ onStarted?.();
48135
48444
  this._failedResponse = undefined;
48136
48445
  this._recordSelection();
48137
48446
  this._pendingToolNames.clear();
48138
- this._isAgentRunActive = true;
48139
48447
  try {
48140
48448
  await this.agent.prompt(messages);
48141
48449
  while (!this._agentRunAbortRequested) {
@@ -48161,6 +48469,49 @@ class AgentSession {
48161
48469
  await this._emitAgentSettled();
48162
48470
  }
48163
48471
  }
48472
+ async _prepareRun(trigger) {
48473
+ const lastAssistant = this._findLastAssistantMessage();
48474
+ if (lastAssistant) {
48475
+ await this._checkCompaction(lastAssistant, false);
48476
+ }
48477
+ const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
48478
+ const result = await this._extensionRunner.emitBeforeAgentStart(trigger, this._baseSystemPromptOptions);
48479
+ const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length || result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
48480
+ if (!handlerEditedTools)
48481
+ result.systemPromptOptions.selectedTools = this.getActiveToolNames();
48482
+ const messages = [];
48483
+ if (trigger.messageType === "custom") {
48484
+ messages.push(trigger.message);
48485
+ } else {
48486
+ const normalized = await this._normalizePromptImages(trigger.images);
48487
+ const text = normalized.hints.length > 0 ? `${trigger.prompt}
48488
+
48489
+ ${normalized.hints.join(`
48490
+ `)}` : trigger.prompt;
48491
+ messages.push({
48492
+ role: "user",
48493
+ content: [{ type: "text", text }, ...normalized.images],
48494
+ timestamp: Date.now()
48495
+ });
48496
+ }
48497
+ messages.push(...this._pendingNextTurnMessages);
48498
+ this._pendingNextTurnMessages = [];
48499
+ for (const msg of result.messages) {
48500
+ messages.push({
48501
+ role: "custom",
48502
+ customType: msg.customType,
48503
+ content: msg.content ?? [],
48504
+ display: msg.display,
48505
+ details: msg.details,
48506
+ timestamp: Date.now()
48507
+ });
48508
+ }
48509
+ const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
48510
+ this._runSystemPromptOptions = result.systemPromptOptions;
48511
+ if (updateMessage)
48512
+ messages.unshift(updateMessage);
48513
+ return messages;
48514
+ }
48164
48515
  async _handlePostAgentRun() {
48165
48516
  const message = this._lastAssistantMessage;
48166
48517
  const toolResults = this._lastAssistantToolResults;
@@ -48291,8 +48642,6 @@ class AgentSession {
48291
48642
  preflightResult?.("queued");
48292
48643
  return;
48293
48644
  }
48294
- this._flushPendingBashMessages();
48295
- this._flushPendingCustomMessages();
48296
48645
  if (!this.model) {
48297
48646
  throw new Error(formatNoModelSelectedMessage());
48298
48647
  }
@@ -48304,48 +48653,7 @@ class AgentSession {
48304
48653
  }
48305
48654
  throw new Error(formatNoApiKeyFoundMessage(this.model.provider));
48306
48655
  }
48307
- const lastAssistant = this._findLastAssistantMessage();
48308
- if (lastAssistant) {
48309
- await this._checkCompaction(lastAssistant, false);
48310
- }
48311
- const selectedToolsBefore = this._baseSystemPromptOptions.selectedTools;
48312
- const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPromptOptions);
48313
- const handlerEditedTools = result.systemPromptOptions.selectedTools.length !== selectedToolsBefore.length || result.systemPromptOptions.selectedTools.some((name, index) => name !== selectedToolsBefore[index]);
48314
- if (!handlerEditedTools)
48315
- result.systemPromptOptions.selectedTools = this.getActiveToolNames();
48316
- const normalized = await this._normalizePromptImages(currentImages);
48317
- const userText = normalized.hints.length > 0 ? `${expandedText}
48318
-
48319
- ${normalized.hints.join(`
48320
- `)}` : expandedText;
48321
- const messages = [];
48322
- const userContent = [{ type: "text", text: userText }];
48323
- userContent.push(...normalized.images);
48324
- messages.push({
48325
- role: "user",
48326
- content: userContent,
48327
- timestamp: Date.now()
48328
- });
48329
- for (const msg of this._pendingNextTurnMessages) {
48330
- messages.push(msg);
48331
- }
48332
- this._pendingNextTurnMessages = [];
48333
- for (const msg of result.messages) {
48334
- messages.push({
48335
- role: "custom",
48336
- customType: msg.customType,
48337
- content: msg.content ?? [],
48338
- display: msg.display,
48339
- details: msg.details,
48340
- timestamp: Date.now()
48341
- });
48342
- }
48343
- const updateMessage = this._preparePromptAndToolLoadout(result.systemPromptOptions);
48344
- this._runSystemPromptOptions = result.systemPromptOptions;
48345
- if (updateMessage)
48346
- messages.unshift(updateMessage);
48347
- preflightResult?.("started");
48348
- await this._runAgentPrompt(messages);
48656
+ await this._startRun({ messageType: "user", prompt: expandedText, images: currentImages }, () => preflightResult?.("started"));
48349
48657
  }
48350
48658
  async _tryExecuteExtensionCommand(text) {
48351
48659
  const spaceIndex = text.indexOf(" ");
@@ -48467,10 +48775,10 @@ ${args}` : skillBlock;
48467
48775
  }
48468
48776
  } else if (options?.triggerTurn) {
48469
48777
  if (this._isEmittingAgentSettled) {
48470
- this._deferredSettledActions.push(async () => await this._runAgentPrompt(appMessage));
48778
+ this._deferredSettledActions.push(async () => await this.sendCustomMessage(message, options));
48471
48779
  return;
48472
48780
  }
48473
- await this._runAgentPrompt(appMessage);
48781
+ await this._startRun({ messageType: "custom", message: appMessage });
48474
48782
  } else if (this.isStreaming) {
48475
48783
  this._pendingCustomMessages.push(appMessage);
48476
48784
  } else {
@@ -51690,7 +51998,7 @@ async function createAgentSession(options = {}) {
51690
51998
 
51691
51999
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/codemode/index.js
51692
52000
  function readMode(pi) {
51693
- return pi.getSettings().codemode?.mode === "only" ? "only" : "on";
52001
+ return pi.getSettings().codemode?.mode === "only" ? "only" : SETTINGS_DEFAULTS.codemode.mode;
51694
52002
  }
51695
52003
  function readInlineBudget(pi) {
51696
52004
  const budget = pi.getSettings().codemode?.inlineBudget;
@@ -51716,8 +52024,485 @@ var codemode_default = createCodemodeExtension();
51716
52024
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/mcp/index.js
51717
52025
  import { join as join19, resolve as resolve10 } from "node:path";
51718
52026
 
52027
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/mcp/tools.js
52028
+ import { createHash as createHash2 } from "node:crypto";
52029
+ function toToolExposure(exposure) {
52030
+ return exposure === "codemode" ? "deferred" : exposure;
52031
+ }
52032
+ var MAX_TOOL_NAME_LENGTH = 64;
52033
+ var MCP_OUTPUT_MAX_BYTES = 20 * 1024;
52034
+ var OUTPUT_PREVIEW_LINES = 5;
52035
+ function saveToTempFile(data, extension) {
52036
+ return writeOutputFile("pi-mcp", extension, data);
52037
+ }
52038
+ function createMcpToolName(server, tool, isTaken = () => false) {
52039
+ const name = `mcp__${server}__${tool}`.replace(/[^A-Za-z0-9_]/g, "_");
52040
+ if (name.length <= MAX_TOOL_NAME_LENGTH && !isTaken(name))
52041
+ return name;
52042
+ const hash = createHash2("sha256").update(`${server}\x00${tool}`).digest("hex").slice(0, 8);
52043
+ return `${name.slice(0, MAX_TOOL_NAME_LENGTH - hash.length - 1)}_${hash}`;
52044
+ }
52045
+ function textOf2(content) {
52046
+ return content.filter((block) => block.type === "text").map((block) => block.text).join(`
52047
+ `);
52048
+ }
52049
+ var CONTENT_BLOCK_SCHEMA = {
52050
+ type: "object",
52051
+ properties: {
52052
+ type: { enum: ["text", "image", "audio", "resource_link", "resource"] },
52053
+ text: { type: "string" },
52054
+ data: { type: "string" },
52055
+ mimeType: { type: "string" }
52056
+ },
52057
+ required: ["type"],
52058
+ additionalProperties: true
52059
+ };
52060
+ var SCHEMA_DATA_KEYWORDS = new Set(["const", "enum", "default", "examples"]);
52061
+ var SCHEMA_MAP_KEYWORDS = new Set([
52062
+ "properties",
52063
+ "patternProperties",
52064
+ "dependentSchemas",
52065
+ "dependencies",
52066
+ "$defs",
52067
+ "definitions"
52068
+ ]);
52069
+ function relocateSchema(schema, pointer) {
52070
+ if (Array.isArray(schema))
52071
+ return schema.map((item) => relocateSchema(item, pointer));
52072
+ if (typeof schema !== "object" || schema === null)
52073
+ return schema;
52074
+ const relocated = {};
52075
+ for (const [key, value] of Object.entries(schema)) {
52076
+ if (key === "$ref" && typeof value === "string" && (value === "#" || value.startsWith("#/"))) {
52077
+ relocated[key] = `${pointer}${value.slice(1)}`;
52078
+ } else if (SCHEMA_DATA_KEYWORDS.has(key)) {
52079
+ relocated[key] = value;
52080
+ } else if (SCHEMA_MAP_KEYWORDS.has(key) && typeof value === "object" && value !== null && !Array.isArray(value)) {
52081
+ relocated[key] = Object.fromEntries(Object.entries(value).map(([name, subschema]) => [name, relocateSchema(subschema, pointer)]));
52082
+ } else {
52083
+ relocated[key] = relocateSchema(value, pointer);
52084
+ }
52085
+ }
52086
+ return relocated;
52087
+ }
52088
+ function createMcpResultSchema(structuredContentSchema) {
52089
+ return {
52090
+ type: "object",
52091
+ properties: {
52092
+ content: { type: "array", items: CONTENT_BLOCK_SCHEMA },
52093
+ structuredContent: structuredContentSchema ? relocateSchema(structuredContentSchema, "#/properties/structuredContent") : {},
52094
+ isError: { type: "boolean" }
52095
+ },
52096
+ required: ["content"],
52097
+ additionalProperties: true
52098
+ };
52099
+ }
52100
+ async function limitMcpContent(content, saveOutput = saveToTempFile) {
52101
+ const combined = textOf2(content);
52102
+ const truncation = truncateMiddle(combined, MCP_OUTPUT_MAX_BYTES);
52103
+ if (!truncation.truncated)
52104
+ return { content };
52105
+ let fullOutputPath;
52106
+ let where;
52107
+ try {
52108
+ fullOutputPath = await saveOutput(combined, ".txt");
52109
+ where = `[Full output: ${fullOutputPath} (read it with offset/limit)]`;
52110
+ } catch (error) {
52111
+ where = `[Could not save the full output: ${error instanceof Error ? error.message : String(error)}]`;
52112
+ }
52113
+ const tokens = Math.ceil(truncation.totalBytes / 4);
52114
+ const text = `Warning: truncated output (original token count: ${tokens})
52115
+ Total output lines: ${truncation.totalLines}
52116
+
52117
+ ${truncation.content}
52118
+
52119
+ ${where}`;
52120
+ return {
52121
+ content: [{ type: "text", text }, ...content.filter((block) => block.type === "image")],
52122
+ ...fullOutputPath ? { fullOutputPath } : {}
52123
+ };
52124
+ }
52125
+ function extensionOf(uri) {
52126
+ const path6 = URL.canParse(uri) ? new URL(uri).pathname : uri;
52127
+ return /\.[A-Za-z0-9]{1,8}$/.exec(path6)?.[0] ?? ".bin";
52128
+ }
52129
+ function isTextMimeType(mimeType) {
52130
+ if (!mimeType)
52131
+ return false;
52132
+ const type = mimeType.split(";", 1)[0].trim().toLowerCase();
52133
+ return type.startsWith("text/") || type === "application/json" || type.endsWith("+json") || type.endsWith("+xml");
52134
+ }
52135
+ async function blockToContent(server, block, options) {
52136
+ if (block.type === "resource_link") {
52137
+ const details = [block.mimeType, block.size === undefined ? undefined : formatSize(block.size)].filter(Boolean);
52138
+ const read = options.readableResources ? `. Read it with ${READ_MCP_RESOURCE_TOOL} (server "${server}")` : "";
52139
+ const description = block.description ? `: ${block.description}` : "";
52140
+ return [
52141
+ {
52142
+ type: "text",
52143
+ text: `[Resource ${block.uri} "${block.title ?? block.name}"${details.length > 0 ? ` (${details.join(", ")})` : ""}${description}${read}]`
52144
+ }
52145
+ ];
52146
+ }
52147
+ if (block.type === "resource" && "blob" in block.resource && !block.resource.mimeType?.startsWith("image/")) {
52148
+ const { uri, mimeType, blob } = block.resource;
52149
+ const data = Buffer.from(blob, "base64");
52150
+ if (isTextMimeType(mimeType))
52151
+ return [{ type: "text", text: data.toString("utf8") }];
52152
+ const kind = `${mimeType ?? "unknown type"}, ${formatSize(data.length)}`;
52153
+ try {
52154
+ const path6 = await (options.saveOutput ?? saveToTempFile)(data, extensionOf(uri));
52155
+ return [{ type: "text", text: `[Binary resource ${uri} (${kind}) saved to ${path6}]` }];
52156
+ } catch (error) {
52157
+ const reason = error instanceof Error ? error.message : String(error);
52158
+ return [{ type: "text", text: `[Binary resource ${uri} (${kind}) could not be saved: ${reason}]` }];
52159
+ }
52160
+ }
52161
+ return toLlmContent({ content: [block] });
52162
+ }
52163
+ async function toModelContent(server, blocks, options = {}) {
52164
+ return (await Promise.all(blocks.map((block) => blockToContent(server, block, options)))).flat();
52165
+ }
52166
+ async function convertMcpResult(server, tool, result, options = {}) {
52167
+ const converted = result.content.length > 0 ? await toModelContent(server, result.content, options) : toLlmContent(result);
52168
+ if (result.isError && textOf2(converted) === "") {
52169
+ converted.push({ type: "text", text: `MCP tool ${server}/${tool} returned an error` });
52170
+ }
52171
+ const { content, fullOutputPath } = await limitMcpContent(converted, options.saveOutput);
52172
+ const { _meta: _ignored, ...scriptResult } = result;
52173
+ return {
52174
+ content,
52175
+ details: { server, tool, ...fullOutputPath ? { fullOutputPath } : {} },
52176
+ structuredContent: scriptResult,
52177
+ ...result.isError ? { isError: true } : {}
52178
+ };
52179
+ }
52180
+ function toParameters(schema) {
52181
+ return {
52182
+ ...schema,
52183
+ type: schema.type ?? "object",
52184
+ ...schema.properties === undefined ? { properties: {} } : {}
52185
+ };
52186
+ }
52187
+ var ANNOTATION_HINTS = ["readOnlyHint", "destructiveHint", "idempotentHint", "openWorldHint"];
52188
+ function toToolAnnotations(tool) {
52189
+ const annotations = {};
52190
+ for (const hint of ANNOTATION_HINTS) {
52191
+ const value = tool.annotations?.[hint];
52192
+ if (typeof value === "boolean")
52193
+ annotations[hint] = value;
52194
+ }
52195
+ return Object.keys(annotations).length > 0 ? annotations : undefined;
52196
+ }
52197
+ function createMcpToolDefinition(options) {
52198
+ const { server, tool } = options;
52199
+ const title = tool.title ?? tool.annotations?.title;
52200
+ const annotations = toToolAnnotations(tool);
52201
+ const label = `${server}/${tool.name}`;
52202
+ return {
52203
+ name: options.name,
52204
+ label,
52205
+ description: tool.description?.trim() || title || `MCP tool ${tool.name} from server ${server}`,
52206
+ parameters: toParameters(tool.inputSchema),
52207
+ outputSchema: createMcpResultSchema(tool.outputSchema),
52208
+ exposure: toToolExposure(options.exposure),
52209
+ namespace: options.namespace,
52210
+ ...annotations ? { annotations } : {},
52211
+ ...createMcpToolRenderers(label),
52212
+ async execute(_toolCallId, params, signal, onUpdate) {
52213
+ const client = await options.getClient();
52214
+ const result = await client.callTool(tool.name, params ?? {}, {
52215
+ signal,
52216
+ timeoutMs: options.timeoutMs,
52217
+ onProgress: (progress) => {
52218
+ const total = progress.total === undefined ? "" : `/${progress.total}`;
52219
+ const text = progress.message ?? `Progress ${progress.progress}${total}`;
52220
+ onUpdate?.({ content: [{ type: "text", text }], details: { server, tool: tool.name } });
52221
+ }
52222
+ });
52223
+ return convertMcpResult(server, tool.name, result, { readableResources: options.readableResources?.() });
52224
+ }
52225
+ };
52226
+ }
52227
+ function createMcpToolRenderers(label) {
52228
+ return {
52229
+ renderCall(args, theme2, context) {
52230
+ const component = context.lastComponent ?? new Text("", 0, 0);
52231
+ component.setText(formatToolCallWithArgs(label, args, theme2, context.expanded));
52232
+ return component;
52233
+ },
52234
+ renderResult(result, options, theme2, context) {
52235
+ const component = context.lastComponent ?? new Container;
52236
+ component.clear();
52237
+ const output = getTextOutput(result, context.showImages).trim();
52238
+ if (!output)
52239
+ return component;
52240
+ const color = context.isError ? "error" : "toolOutput";
52241
+ const styled = replaceTabs(output).split(`
52242
+ `).map((line) => theme2.fg(color, line)).join(`
52243
+ `);
52244
+ component.addChild(new Spacer(1));
52245
+ if (options.expanded) {
52246
+ component.addChild(new Text(styled, 0, 0));
52247
+ } else {
52248
+ component.addChild(new VisualLinePreview({
52249
+ text: styled,
52250
+ maxVisualLines: OUTPUT_PREVIEW_LINES,
52251
+ keep: "start",
52252
+ formatHint: (hidden) => `${theme2.fg("muted", `... (${hidden} more lines,`)} ${keyHint("app.tools.expand", "to expand")}${theme2.fg("muted", ")")}`
52253
+ }));
52254
+ const fullOutputPath = result.details?.fullOutputPath;
52255
+ if (fullOutputPath)
52256
+ component.addChild(new Text(theme2.fg("muted", `Full output: ${fullOutputPath}`), 0, 0));
52257
+ }
52258
+ return component;
52259
+ }
52260
+ };
52261
+ }
52262
+
52263
+ // node_modules/@earendil-works/pi-coding-agent/dist/extensions/mcp/resources.js
52264
+ function isMcpAppResource(item) {
52265
+ const uri = item.uri ?? item.uriTemplate ?? "";
52266
+ return uri.startsWith("ui://") || /;\s*profile\s*=\s*"?mcp-app"?/i.test(item.mimeType ?? "");
52267
+ }
52268
+ function listed(server, item) {
52269
+ const { _meta, icons: _icons, ...rest } = item;
52270
+ return { server, ...rest };
52271
+ }
52272
+ var stringProperty = (description) => ({ type: "string", description });
52273
+ var SERVER_FILTER = stringProperty("MCP server name. Omit to list every server with resources.");
52274
+ var CURSOR = stringProperty("Opaque cursor from a previous call with the same server; omit for the first page.");
52275
+ var LIST_PARAMETERS = {
52276
+ type: "object",
52277
+ properties: { server: SERVER_FILTER, cursor: CURSOR },
52278
+ additionalProperties: false
52279
+ };
52280
+ var READ_PARAMETERS = {
52281
+ type: "object",
52282
+ properties: {
52283
+ server: stringProperty("MCP server name exactly as configured. Must match the 'server' field returned by list_mcp_resources."),
52284
+ uri: stringProperty("Resource URI to read. Must be one of the URIs returned by list_mcp_resources.")
52285
+ },
52286
+ required: ["server", "uri"],
52287
+ additionalProperties: false
52288
+ };
52289
+ var optionalString = { type: "string" };
52290
+ var LISTING_ERRORS = {
52291
+ type: "array",
52292
+ description: "Servers that could not be listed",
52293
+ items: {
52294
+ type: "object",
52295
+ properties: { server: { type: "string" }, error: { type: "string" } },
52296
+ required: ["server", "error"]
52297
+ }
52298
+ };
52299
+ var LIST_OUTPUT_SCHEMA = {
52300
+ type: "object",
52301
+ properties: {
52302
+ server: optionalString,
52303
+ resources: {
52304
+ type: "array",
52305
+ items: {
52306
+ type: "object",
52307
+ properties: {
52308
+ server: { type: "string" },
52309
+ uri: { type: "string" },
52310
+ name: { type: "string" },
52311
+ title: optionalString,
52312
+ description: optionalString,
52313
+ mimeType: optionalString,
52314
+ size: { type: "number" }
52315
+ },
52316
+ required: ["server", "uri", "name"]
52317
+ }
52318
+ },
52319
+ nextCursor: optionalString,
52320
+ errors: LISTING_ERRORS
52321
+ },
52322
+ required: ["resources"]
52323
+ };
52324
+ var LIST_TEMPLATES_OUTPUT_SCHEMA = {
52325
+ type: "object",
52326
+ properties: {
52327
+ server: optionalString,
52328
+ resourceTemplates: {
52329
+ type: "array",
52330
+ items: {
52331
+ type: "object",
52332
+ properties: {
52333
+ server: { type: "string" },
52334
+ uriTemplate: { type: "string", description: "RFC 6570 URI template" },
52335
+ name: { type: "string" },
52336
+ title: optionalString,
52337
+ description: optionalString,
52338
+ mimeType: optionalString
52339
+ },
52340
+ required: ["server", "uriTemplate", "name"]
52341
+ }
52342
+ },
52343
+ nextCursor: optionalString,
52344
+ errors: LISTING_ERRORS
52345
+ },
52346
+ required: ["resourceTemplates"]
52347
+ };
52348
+ var READ_OUTPUT_SCHEMA = {
52349
+ type: "object",
52350
+ properties: {
52351
+ server: { type: "string" },
52352
+ uri: { type: "string" },
52353
+ contents: {
52354
+ type: "array",
52355
+ items: {
52356
+ anyOf: [
52357
+ {
52358
+ type: "object",
52359
+ properties: { uri: { type: "string" }, mimeType: optionalString, text: { type: "string" } },
52360
+ required: ["uri", "text"]
52361
+ },
52362
+ {
52363
+ type: "object",
52364
+ properties: {
52365
+ uri: { type: "string" },
52366
+ mimeType: optionalString,
52367
+ blob: { type: "string", description: "base64" }
52368
+ },
52369
+ required: ["uri", "blob"]
52370
+ }
52371
+ ]
52372
+ }
52373
+ }
52374
+ },
52375
+ required: ["server", "uri", "contents"]
52376
+ };
52377
+ function stringArgument(params, key) {
52378
+ const value = params?.[key];
52379
+ if (value === undefined || value === null)
52380
+ return;
52381
+ if (typeof value !== "string")
52382
+ throw new Error(`${key} must be a string`);
52383
+ return value.trim() || undefined;
52384
+ }
52385
+ function errorMessage(error) {
52386
+ return error instanceof Error ? error.message : String(error);
52387
+ }
52388
+ async function jsonResult(tool, server, payload) {
52389
+ const { content, fullOutputPath } = await limitMcpContent([{ type: "text", text: JSON.stringify(payload) }]);
52390
+ return {
52391
+ content,
52392
+ details: { server: server ?? "", tool, ...fullOutputPath ? { fullOutputPath } : {} },
52393
+ structuredContent: payload
52394
+ };
52395
+ }
52396
+ function createMcpResourceToolDefinitions(options) {
52397
+ const readOnly = { readOnlyHint: true };
52398
+ const findServer = (name) => {
52399
+ const servers = options.servers();
52400
+ const server = servers.find((candidate) => candidate.name === name);
52401
+ if (server)
52402
+ return server;
52403
+ const available = servers.map((candidate) => candidate.name).join(", ");
52404
+ throw new Error(`MCP server "${name}" has no resources${available ? `. Servers with resources: ${available}` : ""}`);
52405
+ };
52406
+ const list = async (params, signal, key, page, all) => {
52407
+ const serverName = stringArgument(params, "server");
52408
+ const cursor = stringArgument(params, "cursor");
52409
+ const visible = (item) => !isMcpAppResource(item);
52410
+ if (serverName) {
52411
+ const server = findServer(serverName);
52412
+ const result = await page(server, cursor, { signal, timeoutMs: server.timeoutMs });
52413
+ return {
52414
+ server: server.name,
52415
+ [key]: result.items.filter(visible).map((item) => listed(server.name, item)),
52416
+ ...result.nextCursor === undefined ? {} : { nextCursor: result.nextCursor }
52417
+ };
52418
+ }
52419
+ if (cursor)
52420
+ throw new Error("cursor can only be used when a server is specified");
52421
+ const servers = [...options.servers()].sort((a, b) => a.name.localeCompare(b.name));
52422
+ const results = await Promise.allSettled(servers.map((server) => all(server, { signal, timeoutMs: server.timeoutMs })));
52423
+ const items = [];
52424
+ const errors2 = [];
52425
+ results.forEach((result, index) => {
52426
+ const server = servers[index].name;
52427
+ if (result.status === "fulfilled")
52428
+ items.push(...result.value.filter(visible).map((item) => listed(server, item)));
52429
+ else
52430
+ errors2.push({ server, error: errorMessage(result.reason) });
52431
+ });
52432
+ return { [key]: items, ...errors2.length > 0 ? { errors: errors2 } : {} };
52433
+ };
52434
+ const listResources = {
52435
+ name: LIST_MCP_RESOURCES_TOOL,
52436
+ label: LIST_MCP_RESOURCES_TOOL,
52437
+ description: "Lists resources provided by MCP servers. Resources allow servers to share data that provides context to language models, such as files, database schemas, or application-specific information. Prefer resources over web search when possible.",
52438
+ parameters: LIST_PARAMETERS,
52439
+ outputSchema: LIST_OUTPUT_SCHEMA,
52440
+ exposure: toToolExposure(options.exposure),
52441
+ annotations: readOnly,
52442
+ async execute(_toolCallId, params, signal) {
52443
+ const payload = await list(params, signal, "resources", async (server, cursor, requestOptions) => {
52444
+ const result = await server.resourcesPage(cursor, requestOptions);
52445
+ return { items: result.resources, nextCursor: result.nextCursor };
52446
+ }, (server, requestOptions) => server.allResources(requestOptions));
52447
+ return jsonResult(LIST_MCP_RESOURCES_TOOL, stringArgument(params, "server"), payload);
52448
+ }
52449
+ };
52450
+ const listTemplates = {
52451
+ name: LIST_MCP_RESOURCE_TEMPLATES_TOOL,
52452
+ label: LIST_MCP_RESOURCE_TEMPLATES_TOOL,
52453
+ description: "Lists resource templates provided by MCP servers. Parameterized resource templates allow servers to share data that takes parameters and provides context to language models, such as files, database schemas, or application-specific information. Prefer resource templates over web search when possible.",
52454
+ parameters: LIST_PARAMETERS,
52455
+ outputSchema: LIST_TEMPLATES_OUTPUT_SCHEMA,
52456
+ exposure: toToolExposure(options.exposure),
52457
+ annotations: readOnly,
52458
+ async execute(_toolCallId, params, signal) {
52459
+ const payload = await list(params, signal, "resourceTemplates", async (server, cursor, requestOptions) => {
52460
+ const result = await server.resourceTemplatesPage(cursor, requestOptions);
52461
+ return { items: result.resourceTemplates, nextCursor: result.nextCursor };
52462
+ }, (server, requestOptions) => server.allResourceTemplates(requestOptions));
52463
+ return jsonResult(LIST_MCP_RESOURCE_TEMPLATES_TOOL, stringArgument(params, "server"), payload);
52464
+ }
52465
+ };
52466
+ const readResource = {
52467
+ name: READ_MCP_RESOURCE_TOOL,
52468
+ label: READ_MCP_RESOURCE_TOOL,
52469
+ description: "Read a specific resource from an MCP server given the server name and resource URI.",
52470
+ parameters: READ_PARAMETERS,
52471
+ outputSchema: READ_OUTPUT_SCHEMA,
52472
+ exposure: toToolExposure(options.exposure),
52473
+ annotations: readOnly,
52474
+ async execute(_toolCallId, params, signal) {
52475
+ const serverName = stringArgument(params, "server");
52476
+ const uri = stringArgument(params, "uri");
52477
+ if (!serverName)
52478
+ throw new Error("server must be provided");
52479
+ if (!uri)
52480
+ throw new Error("uri must be provided");
52481
+ const server = findServer(serverName);
52482
+ const result = await server.readResource(uri, { signal, timeoutMs: server.timeoutMs });
52483
+ const blocks = result.contents.flatMap((contents2) => [
52484
+ ...result.contents.length > 1 ? [{ type: "text", text: `${contents2.uri}:` }] : [],
52485
+ { type: "resource", resource: contents2 }
52486
+ ]);
52487
+ const converted = await toModelContent(server.name, blocks);
52488
+ const { content, fullOutputPath } = await limitMcpContent(converted.length > 0 ? converted : [{ type: "text", text: `Resource ${uri} is empty.` }]);
52489
+ const contents = result.contents.map(({ _meta: _ignored, ...rest }) => rest);
52490
+ return {
52491
+ content,
52492
+ details: {
52493
+ server: server.name,
52494
+ tool: READ_MCP_RESOURCE_TOOL,
52495
+ ...fullOutputPath ? { fullOutputPath } : {}
52496
+ },
52497
+ structuredContent: { server: server.name, uri, contents }
52498
+ };
52499
+ }
52500
+ };
52501
+ return [listResources, listTemplates, readResource];
52502
+ }
52503
+
51719
52504
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/mcp/runtime.lazy.js
51720
- var loadMcpRuntime = () => import("./runtime-h9ha1mq6.js");
52505
+ var loadMcpRuntime = () => import("./runtime-qfry88v2.js");
51721
52506
 
51722
52507
  // node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard.js
51723
52508
  import { randomUUID as randomUUID3 } from "node:crypto";
@@ -51786,7 +52571,7 @@ function isWSL(env = process.env) {
51786
52571
  // node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard.js
51787
52572
  var MAX_OSC52_ENCODED_LENGTH = 1e5;
51788
52573
  function isRemoteSession(env) {
51789
- return Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);
52574
+ return Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION || env.PI_CLIPBOARD_OSC52 === "1");
51790
52575
  }
51791
52576
  function emitOsc52(text) {
51792
52577
  const encoded = Buffer.from(text).toString("base64");
@@ -52138,7 +52923,7 @@ var EXPOSURE_DESCRIPTIONS = {
52138
52923
  deferred: "not declared until tool_search loads them, then called directly; no codemode needed",
52139
52924
  direct: "declared to the model like built-in tools"
52140
52925
  };
52141
- function errorMessage(error) {
52926
+ function errorMessage2(error) {
52142
52927
  return error instanceof Error ? error.message : String(error);
52143
52928
  }
52144
52929
  function firstLine(text) {
@@ -52183,30 +52968,31 @@ function serverSummary(server) {
52183
52968
  `, 1)[0] ?? "").trim();
52184
52969
  }
52185
52970
  function renderServersSection(servers) {
52186
- const listed = servers.filter((server) => isEnabled(server) && hasIndirectTools(server.entry)).sort((a, b) => a.entry.name.localeCompare(b.entry.name));
52187
- if (listed.length === 0)
52971
+ const listed2 = servers.filter((server) => isEnabled(server) && hasIndirectTools(server.entry)).sort((a, b) => a.entry.name.localeCompare(b.entry.name));
52972
+ if (listed2.length === 0)
52188
52973
  return;
52189
- const reaches = listed.map((server) => configuredExposures(server.entry).has("codemode") ? "codemode" : "tool_search");
52974
+ const reaches = listed2.map((server) => configuredExposures(server.entry).has("codemode") ? "codemode" : "tool_search");
52190
52975
  const intro = serversSectionIntro(new Set(reaches));
52191
- const heads = listed.map((server, index) => `- ${mcpNamespace(server.entry.name)} (${reaches[index]})`);
52976
+ const heads = listed2.map((server, index) => `- ${mcpNamespace(server.entry.name)} (${reaches[index]})`);
52192
52977
  const omitted = (count) => count > 0 ? [`- … ${count} more server${count === 1 ? "" : "s"}; find their tools with searchTools()`] : [];
52193
- const size = (kept2) => [intro, ...heads.slice(0, kept2), ...omitted(listed.length - kept2)].join(`
52978
+ const size = (kept2) => [intro, ...heads.slice(0, kept2), ...omitted(listed2.length - kept2)].join(`
52194
52979
  `).length;
52195
- let kept = listed.length;
52980
+ let kept = listed2.length;
52196
52981
  while (kept > 0 && size(kept) > MAX_SERVERS_SECTION_CHARS)
52197
52982
  kept--;
52198
52983
  const perServer = kept === 0 ? 0 : Math.min(MAX_SERVER_DESCRIPTION_CHARS, Math.floor((MAX_SERVERS_SECTION_CHARS - size(kept)) / kept) - 2);
52199
- const lines = listed.slice(0, kept).map((server, index) => {
52984
+ const lines = listed2.slice(0, kept).map((server, index) => {
52200
52985
  const summary = perServer > 0 ? truncate(serverSummary(server), perServer) : "";
52201
52986
  return summary ? `${heads[index]}: ${summary}` : heads[index];
52202
52987
  });
52203
- return [intro, ...lines, ...omitted(listed.length - kept)].join(`
52988
+ return [intro, ...lines, ...omitted(listed2.length - kept)].join(`
52204
52989
  `);
52205
52990
  }
52206
- function scriptNeedsServer(code, server) {
52207
- if (/\b(searchTools|describeNamespace|describeTool|ALL_TOOLS)\b/.test(code))
52991
+ function reachesServer(reach, server) {
52992
+ if (reach === "all")
52208
52993
  return true;
52209
- return code.includes(mcpNamespace(server));
52994
+ const namespace = mcpNamespace(server);
52995
+ return reach.some((word) => word.includes(namespace));
52210
52996
  }
52211
52997
  function describeState(server, withError = true) {
52212
52998
  if (!isEnabled(server))
@@ -52220,10 +53006,8 @@ function describeState(server, withError = true) {
52220
53006
  case "failed":
52221
53007
  return withError ? `failed: ${firstLine(connection.error ?? "unknown error")}` : "failed";
52222
53008
  case "connected": {
52223
- const { tools, resources } = connection;
52224
- const count = resources.length;
52225
- const resourceCount = count > 0 ? ` · ${count} resource${count === 1 ? "" : "s"}` : "";
52226
- return `connected · ${tools.length} tool${tools.length === 1 ? "" : "s"}${resourceCount}`;
53009
+ const { tools, hasResources } = connection;
53010
+ return `connected · ${tools.length} tool${tools.length === 1 ? "" : "s"}${hasResources ? " · resources" : ""}`;
52227
53011
  }
52228
53012
  case "connecting":
52229
53013
  return "connecting…";
@@ -52337,6 +53121,7 @@ function createMcpExtension(options = {}) {
52337
53121
  const description = entry.config.description?.trim();
52338
53122
  const namespace = {
52339
53123
  name: mcpNamespace(server),
53124
+ aliases: [server],
52340
53125
  ...description ? { description } : {},
52341
53126
  ...connection.instructions ? { instructions: connection.instructions } : {}
52342
53127
  };
@@ -52425,8 +53210,9 @@ function createMcpExtension(options = {}) {
52425
53210
  if (!needsCodemode && !needsToolSearch)
52426
53211
  return;
52427
53212
  const tools = pi.getAllTools();
52428
- const hasCodemode = tools.some(isCodemodeTool);
52429
- const hasToolSearch = tools.some(isToolSearchTool);
53213
+ const hasReachingTool = (name) => tools.some((tool) => tool.name === name && tool.reachesTools);
53214
+ const hasCodemode = hasReachingTool(CODEMODE_TOOL_NAME);
53215
+ const hasToolSearch = hasReachingTool(TOOL_SEARCH_TOOL_NAME);
52430
53216
  const active = pi.getActiveTools();
52431
53217
  const activate = [];
52432
53218
  if (needsCodemode && hasCodemode && autoEnableCodemode && !active.includes(CODEMODE_TOOL_NAME)) {
@@ -52556,7 +53342,7 @@ Run /mcp to fix.`, "warning");
52556
53342
  try {
52557
53343
  updateConfig(entry, patch);
52558
53344
  } catch (error) {
52559
- return `Could not update ${entry.override ?? entry.source}: ${errorMessage(error)}`;
53345
+ return `Could not update ${entry.override ?? entry.source}: ${errorMessage2(error)}`;
52560
53346
  }
52561
53347
  }
52562
53348
  server.entry = { ...entry, config: { ...entry.config, ...patch } };
@@ -52581,13 +53367,13 @@ Run /mcp to fix.`, "warning");
52581
53367
  } catch (error) {
52582
53368
  if (error instanceof runtime.McpSignInCancelledError)
52583
53369
  return "Sign-in cancelled.";
52584
- return `Sign-in failed: ${errorMessage(error)}`;
53370
+ return `Sign-in failed: ${errorMessage2(error)}`;
52585
53371
  }
52586
53372
  connection.challenge = undefined;
52587
53373
  try {
52588
53374
  await connection.reconnect();
52589
53375
  } catch (error) {
52590
- return `Signed in, but ${errorMessage(error)}`;
53376
+ return `Signed in, but ${errorMessage2(error)}`;
52591
53377
  }
52592
53378
  return;
52593
53379
  };
@@ -52616,7 +53402,7 @@ Run /mcp to fix.`, "warning");
52616
53402
  await ready;
52617
53403
  return;
52618
53404
  } catch (error) {
52619
- return errorMessage(error);
53405
+ return errorMessage2(error);
52620
53406
  }
52621
53407
  };
52622
53408
  const setEnabled = async (server, enabled, inProject = false) => {
@@ -52803,7 +53589,7 @@ Some tools override it with toolExposure.` : ""}`,
52803
53589
  ensureDiscoveryActive(ctx);
52804
53590
  emitChange();
52805
53591
  };
52806
- track(ready.then(finish, (error) => finish(errorMessage(error))));
53592
+ track(ready.then(finish, (error) => finish(errorMessage2(error))));
52807
53593
  };
52808
53594
  const runAction = async (ui, ctx, server, action) => {
52809
53595
  const { signal } = session;
@@ -52968,7 +53754,7 @@ ${url.href}`, "info");
52968
53754
  reportProblems(ctx);
52969
53755
  }).catch((error) => {
52970
53756
  try {
52971
- ctx.ui.notify(`MCP failed to load: ${errorMessage(error)}`, "error");
53757
+ ctx.ui.notify(`MCP failed to load: ${errorMessage2(error)}`, "error");
52972
53758
  } catch {}
52973
53759
  });
52974
53760
  });
@@ -53008,11 +53794,10 @@ ${url.href}`, "info");
53008
53794
  if (readyServers.length === 0)
53009
53795
  return;
53010
53796
  let waiting = [];
53011
- if (isCodemodeTool(tool)) {
53012
- const { code } = event.input;
53013
- const source = typeof code === "string" ? code : "";
53014
- waiting = readyServers.filter((server) => scriptNeedsServer(source, server.entry.name));
53015
- } else if (isToolSearchTool(tool) || RESOURCE_TOOL_NAMES.has(tool.name)) {
53797
+ const reach = tool.reachesTools?.(event.input);
53798
+ if (reach !== undefined) {
53799
+ waiting = readyServers.filter((server) => reachesServer(reach, server.entry.name));
53800
+ } else if (RESOURCE_TOOL_NAMES.has(tool.name)) {
53016
53801
  waiting = readyServers;
53017
53802
  } else {
53018
53803
  const owner = toolOwners.get(event.toolName)?.split("\x00", 1)[0];
@@ -53050,7 +53835,7 @@ ${url.href}`, "info");
53050
53835
  return;
53051
53836
  }
53052
53837
  } catch (error) {
53053
- ctx.ui.notify(`MCP failed to load: ${errorMessage(error)}`, "error");
53838
+ ctx.ui.notify(`MCP failed to load: ${errorMessage2(error)}`, "error");
53054
53839
  return;
53055
53840
  }
53056
53841
  if (signal.aborted)
@@ -53691,28 +54476,26 @@ function areExperimentalFeaturesEnabled() {
53691
54476
  // node_modules/@earendil-works/pi-coding-agent/dist/core/keybindings.js
53692
54477
  import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
53693
54478
  import { join as join20 } from "path";
54479
+
54480
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/key-id-schema.js
54481
+ var modifiers = ["ctrl", "shift", "alt", "super"];
54482
+ var baseKeyPattern = `(?:[a-z0-9]|${Object.values(Key).flatMap((value) => typeof value === "string" ? [value.replace(/[\\^$.*+?()[\]{}|]/g, "\\$&")] : []).join("|")})`;
54483
+ var duplicateModifierPattern = modifiers.map((modifier) => `${modifier}\\+.*${modifier}\\+`).join("|");
54484
+ var KeyIdSchema = exports_typebox.Unsafe(exports_typebox.String({
54485
+ pattern: `^(?!.*(?:${duplicateModifierPattern}))(?:(?:${modifiers.join("|")})\\+){0,4}${baseKeyPattern}$`,
54486
+ description: "Key identifier with optional ctrl, shift, alt, or super modifiers."
54487
+ }));
54488
+ function keybindingValueSchema(options) {
54489
+ return exports_typebox.Union([KeyIdSchema, exports_typebox.Array(KeyIdSchema)], options);
54490
+ }
54491
+ var KeybindingValueSchema = keybindingValueSchema();
54492
+
54493
+ // node_modules/@earendil-works/pi-coding-agent/dist/core/keybindings.js
53694
54494
  function useWindowsKeybindings(platform3 = process.platform, env = process.env) {
53695
54495
  return platform3 === "win32" || platform3 === "linux" && Boolean(env.WSL_DISTRO_NAME || env.WSL_INTEROP);
53696
54496
  }
53697
54497
  var windowsKeybindings = useWindowsKeybindings();
53698
- var KEYBINDINGS = {
53699
- ...TUI_KEYBINDINGS,
53700
- "tui.editor.undo": {
53701
- ...TUI_KEYBINDINGS["tui.editor.undo"],
53702
- defaultKeys: process.platform === "win32" ? "ctrl+z" : windowsKeybindings ? "alt+z" : "ctrl+-"
53703
- },
53704
- "tui.altScreen.previousPrompt": {
53705
- ...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],
53706
- defaultKeys: windowsKeybindings ? "ctrl+up" : ["ctrl+shift+up", "ctrl+up"]
53707
- },
53708
- "tui.altScreen.nextPrompt": {
53709
- ...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],
53710
- defaultKeys: windowsKeybindings ? "ctrl+down" : ["ctrl+shift+down", "ctrl+down"]
53711
- },
53712
- "tui.altScreen.search": {
53713
- ...TUI_KEYBINDINGS["tui.altScreen.search"],
53714
- defaultKeys: windowsKeybindings ? "ctrl+f" : "ctrl+shift+f"
53715
- },
54498
+ var APP_KEYBINDINGS = {
53716
54499
  "app.interrupt": { defaultKeys: "escape", description: "Cancel or abort" },
53717
54500
  "app.clear": { defaultKeys: "ctrl+c", description: "Clear editor" },
53718
54501
  "app.exit": { defaultKeys: "ctrl+d", description: "Exit when editor is empty" },
@@ -53859,6 +54642,26 @@ var KEYBINDINGS = {
53859
54642
  description: "Tree filter: cycle backward"
53860
54643
  }
53861
54644
  };
54645
+ var KEYBINDINGS = {
54646
+ ...TUI_KEYBINDINGS,
54647
+ "tui.editor.undo": {
54648
+ ...TUI_KEYBINDINGS["tui.editor.undo"],
54649
+ defaultKeys: process.platform === "win32" ? "ctrl+z" : windowsKeybindings ? "alt+z" : "ctrl+-"
54650
+ },
54651
+ "tui.altScreen.previousPrompt": {
54652
+ ...TUI_KEYBINDINGS["tui.altScreen.previousPrompt"],
54653
+ defaultKeys: windowsKeybindings ? "ctrl+up" : ["ctrl+shift+up", "ctrl+up"]
54654
+ },
54655
+ "tui.altScreen.nextPrompt": {
54656
+ ...TUI_KEYBINDINGS["tui.altScreen.nextPrompt"],
54657
+ defaultKeys: windowsKeybindings ? "ctrl+down" : ["ctrl+shift+down", "ctrl+down"]
54658
+ },
54659
+ "tui.altScreen.search": {
54660
+ ...TUI_KEYBINDINGS["tui.altScreen.search"],
54661
+ defaultKeys: windowsKeybindings ? "ctrl+f" : "ctrl+shift+f"
54662
+ },
54663
+ ...APP_KEYBINDINGS
54664
+ };
53862
54665
  var KEYBINDING_NAME_MIGRATIONS = {
53863
54666
  cursorUp: "tui.editor.cursorUp",
53864
54667
  cursorDown: "tui.editor.cursorDown",
@@ -53923,16 +54726,14 @@ var KEYBINDING_NAME_MIGRATIONS = {
53923
54726
  function isLegacyKeybindingName(key) {
53924
54727
  return key in KEYBINDING_NAME_MIGRATIONS;
53925
54728
  }
54729
+ var validateKeybindingValue = Compile(KeybindingValueSchema);
53926
54730
  function toKeybindingsConfig(value) {
53927
54731
  const config = {};
53928
54732
  for (const [key, binding] of Object.entries(value)) {
53929
- if (typeof binding === "string") {
53930
- config[key] = binding;
54733
+ if (key === "$schema")
53931
54734
  continue;
53932
- }
53933
- if (Array.isArray(binding) && binding.every((entry) => typeof entry === "string")) {
54735
+ if (validateKeybindingValue.Check(binding))
53934
54736
  config[key] = binding;
53935
- }
53936
54737
  }
53937
54738
  return config;
53938
54739
  }
@@ -55423,8 +56224,8 @@ class SessionSelectorComponent extends Container {
55423
56224
  this.header.setStatusMessage({ type: "info", message: msg }, 2000);
55424
56225
  await this.refreshSessionsAfterMutation();
55425
56226
  } else {
55426
- const errorMessage2 = result.error ?? "Unknown error";
55427
- this.header.setStatusMessage({ type: "error", message: `Failed to delete: ${errorMessage2}` }, 3000);
56227
+ const errorMessage3 = result.error ?? "Unknown error";
56228
+ this.header.setStatusMessage({ type: "error", message: `Failed to delete: ${errorMessage3}` }, 3000);
55428
56229
  }
55429
56230
  this.requestRender();
55430
56231
  };
@@ -55654,7 +56455,7 @@ async function resolveProjectTrusted(options) {
55654
56455
  if (decision !== null) {
55655
56456
  return decision;
55656
56457
  }
55657
- switch (options.defaultProjectTrust ?? "ask") {
56458
+ switch (options.defaultProjectTrust ?? SETTINGS_DEFAULTS.defaultProjectTrust) {
55658
56459
  case "always":
55659
56460
  return true;
55660
56461
  case "never":
@@ -55692,7 +56493,7 @@ function deduplicateDiagnostics(diagnostics) {
55692
56493
  }
55693
56494
 
55694
56495
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/llama/client.js
55695
- function errorMessage2(payload, fallback) {
56496
+ function errorMessage3(payload, fallback) {
55696
56497
  if (typeof payload !== "object" || payload === null)
55697
56498
  return fallback;
55698
56499
  const error = payload.error;
@@ -55829,7 +56630,7 @@ class LlamaClient {
55829
56630
  payload = undefined;
55830
56631
  }
55831
56632
  if (!response.ok)
55832
- throw new Error(errorMessage2(payload, `llama.cpp returned HTTP ${response.status}`));
56633
+ throw new Error(errorMessage3(payload, `llama.cpp returned HTTP ${response.status}`));
55833
56634
  return payload;
55834
56635
  }
55835
56636
  async list(options = {}) {
@@ -55963,7 +56764,7 @@ class LlamaClient {
55963
56764
  if (event.event === "download_finished")
55964
56765
  finished = true;
55965
56766
  if (event.event === "download_failed")
55966
- failure = errorMessage2(event.data, "Download failed");
56767
+ failure = errorMessage3(event.data, "Download failed");
55967
56768
  if (event.event === "download_progress") {
55968
56769
  sawDownloading = true;
55969
56770
  const progress = parseDownloadProgress(event.data);
@@ -56931,7 +57732,7 @@ ${details.id}`, options);
56931
57732
  if (!client)
56932
57733
  return;
56933
57734
  await showLlamaUi(ctx, async (ui) => {
56934
- const readCatalog = async () => {
57735
+ const readCatalog2 = async () => {
56935
57736
  while (true) {
56936
57737
  try {
56937
57738
  return await syncCatalog(ctx, client);
@@ -56942,7 +57743,7 @@ ${details.id}`, options);
56942
57743
  }
56943
57744
  }
56944
57745
  };
56945
- let catalog = await readCatalog();
57746
+ let catalog = await readCatalog2();
56946
57747
  if (!catalog)
56947
57748
  return;
56948
57749
  while (true) {
@@ -56962,7 +57763,7 @@ ${details.id}`, options);
56962
57763
  } catch (error) {
56963
57764
  actionError = error;
56964
57765
  }
56965
- const refreshed = await readCatalog();
57766
+ const refreshed = await readCatalog2();
56966
57767
  if (!refreshed)
56967
57768
  return;
56968
57769
  catalog = refreshed;
@@ -56984,7 +57785,7 @@ var builtInExtensions = [
56984
57785
  ];
56985
57786
 
56986
57787
  // node_modules/@earendil-works/pi-coding-agent/dist/extensions/mcp/cli.lazy.js
56987
- var loadMcpCommand = () => import("./cli-vr5avem2.js");
57788
+ var loadMcpCommand = () => import("./cli-smcrrmhy.js");
56988
57789
 
56989
57790
  // node_modules/@earendil-works/pi-coding-agent/dist/migrations.js
56990
57791
  import { existsSync as existsSync17, mkdirSync as mkdirSync7, readdirSync as readdirSync8, readFileSync as readFileSync12, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
@@ -58210,7 +59011,7 @@ async function reportBug(context, initialHint) {
58210
59011
  if (loader.signal.aborted)
58211
59012
  context.showStatus("Bug report cancelled");
58212
59013
  else
58213
- context.showError(`Failed to write bug report summary: ${errorMessage3(error)}`);
59014
+ context.showError(`Failed to write bug report summary: ${errorMessage4(error)}`);
58214
59015
  return;
58215
59016
  }
58216
59017
  restoreEditor2(context, loader);
@@ -58223,7 +59024,7 @@ async function reportBug(context, initialHint) {
58223
59024
  try {
58224
59025
  bundle = buildBundle(context.session, options, summary);
58225
59026
  } catch (error) {
58226
- context.showError(`Failed to build bug report: ${errorMessage3(error)}`);
59027
+ context.showError(`Failed to build bug report: ${errorMessage4(error)}`);
58227
59028
  return;
58228
59029
  }
58229
59030
  if (options.delivery === "upload") {
@@ -58312,7 +59113,7 @@ async function upload(context, bundle) {
58312
59113
  context.showStatus("Bug report cancelled");
58313
59114
  return;
58314
59115
  }
58315
- return errorMessage3(error);
59116
+ return errorMessage4(error);
58316
59117
  }
58317
59118
  }
58318
59119
  async function exportZip(context, bundle) {
@@ -58320,7 +59121,7 @@ async function exportZip(context, bundle) {
58320
59121
  try {
58321
59122
  await writeBugReportArchive(bundle, archivePath);
58322
59123
  } catch (error) {
58323
- context.showError(`Failed to write bug report: ${errorMessage3(error)}`);
59124
+ context.showError(`Failed to write bug report: ${errorMessage4(error)}`);
58324
59125
  return;
58325
59126
  }
58326
59127
  recordInSession(context.session, bundle, { delivery: "zip", path: archivePath });
@@ -58382,7 +59183,7 @@ function restoreEditor2(context, component) {
58382
59183
  context.ui.setFocus(context.editor);
58383
59184
  context.ui.requestRender();
58384
59185
  }
58385
- function errorMessage3(error) {
59186
+ function errorMessage4(error) {
58386
59187
  return error instanceof Error ? error.message : "Unknown error";
58387
59188
  }
58388
59189
 
@@ -59060,7 +59861,7 @@ function playEasterEgg3d(tui, egg) {
59060
59861
  if (tui.hasOverlay())
59061
59862
  return true;
59062
59863
  const screen = tui.getScreenLines();
59063
- import("./easter-egg-3d-66zxervv.js").then((module) => module.playEasterEgg3d(tui, screen, egg), () => {});
59864
+ import("./easter-egg-3d-m8rvz40s.js").then((module) => module.playEasterEgg3d(tui, screen, egg), () => {});
59064
59865
  return true;
59065
59866
  }
59066
59867
  function playPiLogo3d(tui, column, row) {
@@ -64185,7 +64986,7 @@ class WarningSettingsSubmenu extends Container {
64185
64986
  id: "anthropic-extra-usage",
64186
64987
  label: "Anthropic extra usage",
64187
64988
  description: "Warn when Anthropic subscription auth may use paid extra usage",
64188
- currentValue: this.state.anthropicExtraUsage ?? true ? "true" : "false",
64989
+ currentValue: this.state.anthropicExtraUsage ?? SETTINGS_DEFAULTS.warnings.anthropicExtraUsage ? "true" : "false",
64189
64990
  values: ["true", "false"]
64190
64991
  }
64191
64992
  ];
@@ -64709,7 +65510,7 @@ class SettingsSelectorComponent extends Container {
64709
65510
  items.splice(skillCommandsIndex + 1, 0, {
64710
65511
  id: "show-hardware-cursor",
64711
65512
  label: "Show hardware cursor",
64712
- description: "Show the terminal cursor while still positioning it for IME support",
65513
+ description: "Use the terminal cursor instead of Pi's drawn cursor",
64713
65514
  currentValue: config.showHardwareCursor ? "true" : "false",
64714
65515
  values: ["true", "false"]
64715
65516
  });
@@ -64961,10 +65762,10 @@ class RetryStatusIndicator extends StatusIndicator {
64961
65762
  }
64962
65763
 
64963
65764
  class CompactionStatusIndicator extends StatusIndicator {
64964
- constructor(ui, reason) {
65765
+ constructor(ui, reason, colorFn) {
64965
65766
  const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
64966
65767
  const label = reason === "manual" ? `Compacting context... ${cancelHint}` : `${reason === "overflow" ? "Context overflow detected, " : ""}Auto-compacting... ${cancelHint}`;
64967
- super("compaction", ui, (spinner) => theme.fg("accent", spinner), (text) => theme.fg("muted", text), label);
65768
+ super("compaction", ui, colorFn ?? ((spinner) => theme.fg("accent", spinner)), colorFn ?? ((text) => theme.fg("muted", text)), label);
64968
65769
  }
64969
65770
  }
64970
65771
 
@@ -66820,7 +67621,7 @@ function createInteractiveTuiReference(getTui) {
66820
67621
  }
66821
67622
 
66822
67623
  // node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js
66823
- function isWorkingStatusEditor(editor) {
67624
+ function isEmbeddedStatus(editor) {
66824
67625
  return "embedWorkingStatus" in editor && editor.embedWorkingStatus === true && "setWorkingStatusIndicator" in editor && typeof editor.setWorkingStatusIndicator === "function";
66825
67626
  }
66826
67627
  function isExpandable(obj) {
@@ -67523,8 +68324,8 @@ ${onboarding()}`, this.getStartupExpansionState(), 1, 0);
67523
68324
  try {
67524
68325
  await this.session.prompt(initialMessage, { images: initialImages });
67525
68326
  } catch (error) {
67526
- const errorMessage4 = error instanceof Error ? error.message : "Unknown error occurred";
67527
- this.showError(errorMessage4);
68327
+ const errorMessage5 = error instanceof Error ? error.message : "Unknown error occurred";
68328
+ this.showError(errorMessage5);
67528
68329
  }
67529
68330
  }
67530
68331
  if (initialMessages) {
@@ -67532,8 +68333,8 @@ ${onboarding()}`, this.getStartupExpansionState(), 1, 0);
67532
68333
  try {
67533
68334
  await this.session.prompt(message);
67534
68335
  } catch (error) {
67535
- const errorMessage4 = error instanceof Error ? error.message : "Unknown error occurred";
67536
- this.showError(errorMessage4);
68336
+ const errorMessage5 = error instanceof Error ? error.message : "Unknown error occurred";
68337
+ this.showError(errorMessage5);
67537
68338
  }
67538
68339
  }
67539
68340
  }
@@ -67542,8 +68343,8 @@ ${onboarding()}`, this.getStartupExpansionState(), 1, 0);
67542
68343
  try {
67543
68344
  await this.session.prompt(userInput);
67544
68345
  } catch (error) {
67545
- const errorMessage4 = error instanceof Error ? error.message : "Unknown error occurred";
67546
- this.showError(errorMessage4);
68346
+ const errorMessage5 = error instanceof Error ? error.message : "Unknown error occurred";
68347
+ this.showError(errorMessage5);
67547
68348
  }
67548
68349
  }
67549
68350
  }
@@ -68338,7 +69139,7 @@ ${warningLines()}`, 0, 0));
68338
69139
  }
68339
69140
  setEditorWorkingStatusIndicator(indicator) {
68340
69141
  this.defaultEditor.setWorkingStatusIndicator(undefined);
68341
- if (!isWorkingStatusEditor(this.editor))
69142
+ if (!isEmbeddedStatus(this.editor))
68342
69143
  return false;
68343
69144
  this.editor.setWorkingStatusIndicator(indicator);
68344
69145
  return true;
@@ -68371,7 +69172,7 @@ ${warningLines()}`, 0, 0));
68371
69172
  }
68372
69173
  }
68373
69174
  showWorkingStatusIndicator() {
68374
- const colorFn = isWorkingStatusEditor(this.editor) ? (text) => (this.editor.borderColor ?? theme.getThinkingBorderColor(this.session.thinkingLevel || "off"))(text) : undefined;
69175
+ const colorFn = isEmbeddedStatus(this.editor) ? (text) => (this.editor.borderColor ?? theme.getThinkingBorderColor(this.session.thinkingLevel || "off"))(text) : undefined;
68375
69176
  this.showStatusIndicator(new WorkingStatusIndicator(this.ui, this.workingMessage ?? this.defaultWorkingMessage, this.workingIndicatorOptions, colorFn));
68376
69177
  }
68377
69178
  setWorkingVisible(visible) {
@@ -69308,20 +70109,20 @@ ${message}`, ["Yes", "No"], opts, {
69308
70109
  break;
69309
70110
  if (this.streamingComponent && event.message.role === "assistant") {
69310
70111
  this.streamingMessage = event.message;
69311
- let errorMessage4;
70112
+ let errorMessage5;
69312
70113
  if (this.streamingMessage.stopReason === "aborted") {
69313
70114
  const retryAttempt = this.session.retryAttempt;
69314
- errorMessage4 = retryAttempt > 0 ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` : "Operation aborted";
69315
- this.streamingMessage.errorMessage = errorMessage4;
70115
+ errorMessage5 = retryAttempt > 0 ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` : "Operation aborted";
70116
+ this.streamingMessage.errorMessage = errorMessage5;
69316
70117
  }
69317
70118
  this.streamingComponent.updateContent(this.streamingMessage, false);
69318
70119
  if (this.streamingMessage.stopReason === "aborted" || this.streamingMessage.stopReason === "error") {
69319
- if (!errorMessage4) {
69320
- errorMessage4 = this.streamingMessage.errorMessage || "Error";
70120
+ if (!errorMessage5) {
70121
+ errorMessage5 = this.streamingMessage.errorMessage || "Error";
69321
70122
  }
69322
70123
  for (const [, component] of this.pendingTools.entries()) {
69323
70124
  component.updateResult({
69324
- content: [{ type: "text", text: errorMessage4 }],
70125
+ content: [{ type: "text", text: errorMessage5 }],
69325
70126
  isError: true
69326
70127
  });
69327
70128
  }
@@ -69403,7 +70204,8 @@ ${message}`, ["Yes", "No"], opts, {
69403
70204
  this.defaultEditor.onEscape = () => {
69404
70205
  this.session.abortCompaction();
69405
70206
  };
69406
- this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
70207
+ const colorFn = isEmbeddedStatus(this.editor) ? (text) => (this.editor.borderColor ?? theme.getThinkingBorderColor(this.session.thinkingLevel || "off"))(text) : undefined;
70208
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason, colorFn));
69407
70209
  this.ui.requestRender();
69408
70210
  break;
69409
70211
  }
@@ -69443,8 +70245,8 @@ ${message}`, ["Yes", "No"], opts, {
69443
70245
  this.showError(event.errorMessage);
69444
70246
  } else {
69445
70247
  this.chatContainer.addChild(new Spacer(1));
69446
- const errorMessage4 = event.errorMessage;
69447
- this.chatContainer.addChild(new ThemedText(() => theme.fg("error", errorMessage4), 1, 0));
70248
+ const errorMessage5 = event.errorMessage;
70249
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", errorMessage5), 1, 0));
69448
70250
  }
69449
70251
  }
69450
70252
  this.flushCompactionQueue({ willRetry: event.willRetry });
@@ -69483,7 +70285,8 @@ ${message}`, ["Yes", "No"], opts, {
69483
70285
  if (event.source === "branchSummary") {
69484
70286
  this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
69485
70287
  } else {
69486
- this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
70288
+ const colorFn = isEmbeddedStatus(this.editor) ? (text) => (this.editor.borderColor ?? theme.getThinkingBorderColor(this.session.thinkingLevel || "off"))(text) : undefined;
70289
+ this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason, colorFn));
69487
70290
  }
69488
70291
  this.ui.requestRender();
69489
70292
  break;
@@ -69660,14 +70463,14 @@ ${message}`, ["Yes", "No"], opts, {
69660
70463
  component.setExpanded(this.toolOutputExpanded);
69661
70464
  this.chatContainer.addChild(component);
69662
70465
  if (message.stopReason === "aborted" || message.stopReason === "error") {
69663
- let errorMessage4;
70466
+ let errorMessage5;
69664
70467
  if (message.stopReason === "aborted") {
69665
70468
  const retryAttempt = this.session.retryAttempt;
69666
- errorMessage4 = retryAttempt > 0 ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` : "Operation aborted";
70469
+ errorMessage5 = retryAttempt > 0 ? `Aborted after ${retryAttempt} retry attempt${retryAttempt > 1 ? "s" : ""}` : "Operation aborted";
69667
70470
  } else {
69668
- errorMessage4 = message.errorMessage || "Error";
70471
+ errorMessage5 = message.errorMessage || "Error";
69669
70472
  }
69670
- component.updateResult({ content: [{ type: "text", text: errorMessage4 }], isError: true });
70473
+ component.updateResult({ content: [{ type: "text", text: errorMessage5 }], isError: true });
69671
70474
  } else {
69672
70475
  renderedPendingTools.set(content.id, component);
69673
70476
  }
@@ -70075,9 +70878,9 @@ ${this.crashReportInstructions()}`);
70075
70878
  this.editor.setText("");
70076
70879
  this.ui.requestRender();
70077
70880
  }
70078
- showError(errorMessage4) {
70881
+ showError(errorMessage5) {
70079
70882
  this.chatContainer.addChild(new Spacer(1));
70080
- this.chatContainer.addChild(new ThemedText(() => theme.fg("error", `Error: ${errorMessage4}`), this.outputPad, 0));
70883
+ this.chatContainer.addChild(new ThemedText(() => theme.fg("error", `Error: ${errorMessage5}`), this.outputPad, 0));
70081
70884
  this.ui.requestRender();
70082
70885
  }
70083
70886
  showWarning(warningMessage) {
@@ -71246,8 +72049,8 @@ ${packageLines}`, 1, 0));
71246
72049
  await this.session.setModel(selectedModel, { persist: true });
71247
72050
  } catch (error) {
71248
72051
  selectedModel = undefined;
71249
- const errorMessage4 = error instanceof Error ? error.message : String(error);
71250
- selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage4}. Use /model to select a model.`;
72052
+ const errorMessage5 = error instanceof Error ? error.message : String(error);
72053
+ selectionError = `${actionLabel}, but selecting its default model failed: ${errorMessage5}. Use /model to select a model.`;
71251
72054
  }
71252
72055
  }
71253
72056
  }
@@ -72204,6 +73007,10 @@ async function runPrintMode(runtimeHost, options) {
72204
73007
  `);
72205
73008
  }
72206
73009
  }
73010
+ if (assistantMsg.stopReason === "length") {
73011
+ console.error("Response was truncated: the model reached its output token limit.");
73012
+ exitCode = 1;
73013
+ }
72207
73014
  }
72208
73015
  }
72209
73016
  }
@@ -73145,82 +73952,63 @@ async function runRpcMode(runtimeHost) {
73145
73952
  })();
73146
73953
  return new Promise(() => {});
73147
73954
  }
73148
- // node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme-json.js
73149
- var ColorValueSchema = exports_typebox.Union([
73150
- exports_typebox.String(),
73151
- exports_typebox.Integer({ minimum: 0, maximum: 255 })
73152
- ]);
73955
+ // node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme-schema.js
73956
+ function colorValue(description) {
73957
+ return exports_typebox.Union([
73958
+ exports_typebox.String({
73959
+ description: "Hex color (#RGB or #RRGGBB), OKLCH or OKHSL color, variable reference, or empty string for terminal default"
73960
+ }),
73961
+ exports_typebox.Integer({
73962
+ minimum: 0,
73963
+ maximum: 255,
73964
+ description: "256-color palette index (0-255)"
73965
+ })
73966
+ ], description ? { description } : {});
73967
+ }
73968
+ var ColorValueSchema = colorValue();
73969
+ function themeTokenProperties(tokens) {
73970
+ const properties = {};
73971
+ for (const [name, descriptor] of Object.entries(tokens)) {
73972
+ const schema = colorValue(descriptor.description);
73973
+ properties[name] = descriptor.fallback === undefined ? schema : exports_typebox.Optional(schema);
73974
+ }
73975
+ return properties;
73976
+ }
73977
+ var ThemeColorsSchema = exports_typebox.Unsafe(exports_typebox.Object(themeTokenProperties(THEME_TOKENS), {
73978
+ description: "Theme color definitions (scrollbar, thinkingMax, and search highlight colors are optional and use compatible fallbacks)",
73979
+ additionalProperties: false
73980
+ }));
73153
73981
  var ThemeJsonSchema = exports_typebox.Object({
73154
- $schema: exports_typebox.Optional(exports_typebox.String()),
73155
- name: exports_typebox.String(),
73156
- appearance: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("dark"), exports_typebox.Literal("light")])),
73157
- vars: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ColorValueSchema)),
73158
- colors: exports_typebox.Object({
73159
- accent: ColorValueSchema,
73160
- border: ColorValueSchema,
73161
- borderAccent: ColorValueSchema,
73162
- borderMuted: ColorValueSchema,
73163
- success: ColorValueSchema,
73164
- error: ColorValueSchema,
73165
- warning: ColorValueSchema,
73166
- muted: ColorValueSchema,
73167
- dim: ColorValueSchema,
73168
- text: ColorValueSchema,
73169
- thinkingText: ColorValueSchema,
73170
- scrollbarTrack: exports_typebox.Optional(ColorValueSchema),
73171
- scrollbarThumb: exports_typebox.Optional(ColorValueSchema),
73172
- selectedBg: ColorValueSchema,
73173
- searchMatchBg: exports_typebox.Optional(ColorValueSchema),
73174
- searchMatchText: exports_typebox.Optional(ColorValueSchema),
73175
- userMessageBg: ColorValueSchema,
73176
- userMessageText: ColorValueSchema,
73177
- customMessageBg: ColorValueSchema,
73178
- customMessageText: ColorValueSchema,
73179
- customMessageLabel: ColorValueSchema,
73180
- toolPendingBg: ColorValueSchema,
73181
- toolSuccessBg: ColorValueSchema,
73182
- toolErrorBg: ColorValueSchema,
73183
- toolTitle: ColorValueSchema,
73184
- toolOutput: ColorValueSchema,
73185
- mdHeading: ColorValueSchema,
73186
- mdLink: ColorValueSchema,
73187
- mdLinkUrl: ColorValueSchema,
73188
- mdCode: ColorValueSchema,
73189
- mdCodeBlock: ColorValueSchema,
73190
- mdCodeBlockBorder: ColorValueSchema,
73191
- mdQuote: ColorValueSchema,
73192
- mdQuoteBorder: ColorValueSchema,
73193
- mdHr: ColorValueSchema,
73194
- mdListBullet: ColorValueSchema,
73195
- toolDiffAdded: ColorValueSchema,
73196
- toolDiffRemoved: ColorValueSchema,
73197
- toolDiffContext: ColorValueSchema,
73198
- syntaxComment: ColorValueSchema,
73199
- syntaxKeyword: ColorValueSchema,
73200
- syntaxFunction: ColorValueSchema,
73201
- syntaxVariable: ColorValueSchema,
73202
- syntaxString: ColorValueSchema,
73203
- syntaxNumber: ColorValueSchema,
73204
- syntaxType: ColorValueSchema,
73205
- syntaxOperator: ColorValueSchema,
73206
- syntaxPunctuation: ColorValueSchema,
73207
- thinkingOff: ColorValueSchema,
73208
- thinkingMinimal: ColorValueSchema,
73209
- thinkingLow: ColorValueSchema,
73210
- thinkingMedium: ColorValueSchema,
73211
- thinkingHigh: ColorValueSchema,
73212
- thinkingXhigh: ColorValueSchema,
73213
- thinkingMax: exports_typebox.Optional(ColorValueSchema),
73214
- bashMode: ColorValueSchema
73982
+ $schema: exports_typebox.Optional(exports_typebox.String({ description: "JSON schema reference" })),
73983
+ name: exports_typebox.String({
73984
+ pattern: "^[^/]+$",
73985
+ description: "Theme name. Must not contain '/' because it is reserved for automatic light/dark theme settings."
73215
73986
  }),
73987
+ appearance: exports_typebox.Optional(exports_typebox.Union([exports_typebox.Literal("dark"), exports_typebox.Literal("light")], {
73988
+ description: "Background the theme is designed for. Detected from the theme colors when omitted."
73989
+ })),
73990
+ vars: exports_typebox.Optional(exports_typebox.Record(exports_typebox.String(), ColorValueSchema, {
73991
+ description: "Reusable color variables"
73992
+ })),
73993
+ colors: ThemeColorsSchema,
73216
73994
  export: exports_typebox.Optional(exports_typebox.Object({
73217
- pageBg: exports_typebox.Optional(ColorValueSchema),
73218
- cardBg: exports_typebox.Optional(ColorValueSchema),
73219
- infoBg: exports_typebox.Optional(ColorValueSchema)
73995
+ pageBg: exports_typebox.Optional(colorValue("Page background color")),
73996
+ cardBg: exports_typebox.Optional(colorValue("Card/container background color")),
73997
+ infoBg: exports_typebox.Optional(colorValue("Info sections background (system prompt, notices)"))
73998
+ }, {
73999
+ description: "Optional colors for HTML export (defaults derived from userMessageBg if not specified)",
74000
+ additionalProperties: false
73220
74001
  }))
74002
+ }, {
74003
+ title: "Pi Coding Agent Theme",
74004
+ description: "Theme schema for Pi coding agent",
74005
+ additionalProperties: false
73221
74006
  });
73222
74007
  var compiledThemeSchema = Compile(ThemeJsonSchema);
73223
74008
  function validateThemeJson(label, json) {
74009
+ if (typeof json === "object" && json !== null && "name" in json && typeof json.name === "string" && json.name.includes("/")) {
74010
+ throw new Error(`Invalid theme name "${json.name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`);
74011
+ }
73224
74012
  if (!compiledThemeSchema.Check(json)) {
73225
74013
  const errors2 = Array.from(compiledThemeSchema.Errors(json));
73226
74014
  const missingColors = new Set;
@@ -73236,34 +74024,30 @@ function validateThemeJson(label, json) {
73236
74024
  const path10 = error.instancePath || "/";
73237
74025
  otherErrors.push(` - ${path10}: ${error.message}`);
73238
74026
  }
73239
- let errorMessage4 = `Invalid theme "${label}":
74027
+ let errorMessage5 = `Invalid theme "${label}":
73240
74028
  `;
73241
74029
  if (missingColors.size > 0) {
73242
- errorMessage4 += `
74030
+ errorMessage5 += `
73243
74031
  Missing required color tokens:
73244
74032
  `;
73245
- errorMessage4 += Array.from(missingColors).sort().map((color) => ` - ${color}`).join(`
74033
+ errorMessage5 += Array.from(missingColors).sort().map((color) => ` - ${color}`).join(`
73246
74034
  `);
73247
- errorMessage4 += `
74035
+ errorMessage5 += `
73248
74036
 
73249
74037
  Please add these colors to your theme's "colors" object.`;
73250
- errorMessage4 += `
74038
+ errorMessage5 += `
73251
74039
  See the built-in themes (dark.json, light.json) for reference values.`;
73252
74040
  }
73253
74041
  if (otherErrors.length > 0) {
73254
- errorMessage4 += `
74042
+ errorMessage5 += `
73255
74043
 
73256
74044
  Other errors:
73257
74045
  ${otherErrors.join(`
73258
74046
  `)}`;
73259
74047
  }
73260
- throw new Error(errorMessage4);
73261
- }
73262
- const themeJson = json;
73263
- if (themeJson.name.includes("/")) {
73264
- throw new Error(`Invalid theme name "${themeJson.name}": theme names cannot contain "/" because it is reserved for automatic light/dark theme settings.`);
74048
+ throw new Error(errorMessage5);
73265
74049
  }
73266
- return themeJson;
74050
+ return json;
73267
74051
  }
73268
74052
 
73269
74053
  // node_modules/@earendil-works/pi-coding-agent/dist/package-manager-cli.js
@@ -75357,6 +76141,7 @@ async function promptForMissingSessionCwd(issue, settingsManager) {
75357
76141
  }
75358
76142
  async function main(args, options) {
75359
76143
  resetTimings();
76144
+ setThemeJsonValidator(validateThemeJson);
75360
76145
  const extensionFactories = [...builtInExtensions, ...options?.extensionFactories ?? []];
75361
76146
  const offlineMode = args.includes("--offline") || isTruthyEnvFlag2(process.env.PI_OFFLINE);
75362
76147
  if (offlineMode) {
@@ -75609,7 +76394,6 @@ async function main(args, options) {
75609
76394
  time("readPipedStdin");
75610
76395
  const { initialMessage, initialImages } = await prepareInitialMessage(parsed, stdinContent);
75611
76396
  time("prepareInitialMessage");
75612
- setThemeJsonValidator(validateThemeJson);
75613
76397
  initTheme(settingsManager.getTheme(), appMode === "interactive");
75614
76398
  time("initTheme");
75615
76399
  if (appMode === "interactive" && deprecationWarnings.length > 0) {