@pentoshi/clai 3.9.7 → 3.11.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 (211) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +81 -9
  3. package/dist/agent/context-manager.d.ts +2 -1
  4. package/dist/agent/context-manager.js +16 -2
  5. package/dist/agent/context-manager.js.map +1 -1
  6. package/dist/agent/loop-guard.d.ts +18 -0
  7. package/dist/agent/loop-guard.js +50 -2
  8. package/dist/agent/loop-guard.js.map +1 -1
  9. package/dist/agent/must-continue.js +4 -8
  10. package/dist/agent/must-continue.js.map +1 -1
  11. package/dist/agent/prompt-composer.js +8 -8
  12. package/dist/agent/prompt-composer.js.map +1 -1
  13. package/dist/agent/runner.d.ts +1 -0
  14. package/dist/agent/runner.js +238 -74
  15. package/dist/agent/runner.js.map +1 -1
  16. package/dist/agent/session-policy.d.ts +1 -2
  17. package/dist/agent/session-policy.js +3 -2
  18. package/dist/agent/session-policy.js.map +1 -1
  19. package/dist/agent/tool-call-parser.js +6 -6
  20. package/dist/agent/tool-call-parser.js.map +1 -1
  21. package/dist/app/adapters/current-agent-adapter.js +1 -0
  22. package/dist/app/adapters/current-agent-adapter.js.map +1 -1
  23. package/dist/app/controllers/session-controller.js +2 -0
  24. package/dist/app/controllers/session-controller.js.map +1 -1
  25. package/dist/app/controllers/session-turn-request.d.ts +1 -0
  26. package/dist/app/controllers/session-turn-request.js +4 -1
  27. package/dist/app/controllers/session-turn-request.js.map +1 -1
  28. package/dist/app/ports/agent-port.d.ts +1 -0
  29. package/dist/attachments/clipboard-image.js +5 -4
  30. package/dist/attachments/clipboard-image.js.map +1 -1
  31. package/dist/attachments/image-content.d.ts +20 -2
  32. package/dist/attachments/image-content.js +201 -1
  33. package/dist/attachments/image-content.js.map +1 -1
  34. package/dist/attachments/image-prepare.d.ts +25 -0
  35. package/dist/attachments/image-prepare.js +390 -0
  36. package/dist/attachments/image-prepare.js.map +1 -0
  37. package/dist/attachments/service.d.ts +4 -2
  38. package/dist/attachments/service.js +51 -21
  39. package/dist/attachments/service.js.map +1 -1
  40. package/dist/commands/providers.d.ts +5 -2
  41. package/dist/commands/providers.js +121 -7
  42. package/dist/commands/providers.js.map +1 -1
  43. package/dist/index.js +12 -4
  44. package/dist/index.js.map +1 -1
  45. package/dist/llm/agentrouter.js +2 -2
  46. package/dist/llm/agentrouter.js.map +1 -1
  47. package/dist/llm/anthropic.d.ts +5 -4
  48. package/dist/llm/anthropic.js +28 -25
  49. package/dist/llm/anthropic.js.map +1 -1
  50. package/dist/llm/aws-mantle.js +19 -20
  51. package/dist/llm/aws-mantle.js.map +1 -1
  52. package/dist/llm/bynara.js +2 -2
  53. package/dist/llm/bynara.js.map +1 -1
  54. package/dist/llm/capabilities.d.ts +19 -0
  55. package/dist/llm/capabilities.js +273 -16
  56. package/dist/llm/capabilities.js.map +1 -1
  57. package/dist/llm/gemini.js +16 -8
  58. package/dist/llm/gemini.js.map +1 -1
  59. package/dist/llm/groq.js +2 -2
  60. package/dist/llm/groq.js.map +1 -1
  61. package/dist/llm/http.d.ts +7 -1
  62. package/dist/llm/http.js +210 -8
  63. package/dist/llm/http.js.map +1 -1
  64. package/dist/llm/kimchi.js +2 -2
  65. package/dist/llm/kimchi.js.map +1 -1
  66. package/dist/llm/lightning.d.ts +11 -0
  67. package/dist/llm/lightning.js +108 -0
  68. package/dist/llm/lightning.js.map +1 -0
  69. package/dist/llm/modal.d.ts +16 -0
  70. package/dist/llm/modal.js +182 -0
  71. package/dist/llm/modal.js.map +1 -0
  72. package/dist/llm/nvidia.js +2 -2
  73. package/dist/llm/nvidia.js.map +1 -1
  74. package/dist/llm/ollama.js +3 -3
  75. package/dist/llm/ollama.js.map +1 -1
  76. package/dist/llm/openai.js +2 -2
  77. package/dist/llm/openai.js.map +1 -1
  78. package/dist/llm/openrouter.js +2 -2
  79. package/dist/llm/openrouter.js.map +1 -1
  80. package/dist/llm/provider.d.ts +11 -0
  81. package/dist/llm/provider.js +316 -1
  82. package/dist/llm/provider.js.map +1 -1
  83. package/dist/llm/qwen-cloud.js +2 -5
  84. package/dist/llm/qwen-cloud.js.map +1 -1
  85. package/dist/llm/router.js +127 -7
  86. package/dist/llm/router.js.map +1 -1
  87. package/dist/llm/system-messages.d.ts +5 -0
  88. package/dist/llm/system-messages.js +14 -0
  89. package/dist/llm/system-messages.js.map +1 -1
  90. package/dist/llm/token-usage.d.ts +13 -0
  91. package/dist/llm/token-usage.js +31 -0
  92. package/dist/llm/token-usage.js.map +1 -1
  93. package/dist/llm/tokenrouter.d.ts +15 -0
  94. package/dist/llm/tokenrouter.js +106 -0
  95. package/dist/llm/tokenrouter.js.map +1 -0
  96. package/dist/modes/agent.d.ts +1 -0
  97. package/dist/modes/agent.js.map +1 -1
  98. package/dist/modes/ask.js +15 -4
  99. package/dist/modes/ask.js.map +1 -1
  100. package/dist/prompts/embedded.js +2 -2
  101. package/dist/prompts/embedded.js.map +1 -1
  102. package/dist/prompts/index.d.ts +6 -0
  103. package/dist/prompts/index.js +39 -21
  104. package/dist/prompts/index.js.map +1 -1
  105. package/dist/prompts/system.agent.md +15 -27
  106. package/dist/prompts/system.ask.md +1 -1
  107. package/dist/repl/slash-commands.js +53 -0
  108. package/dist/repl/slash-commands.js.map +1 -1
  109. package/dist/repl.js +16 -9
  110. package/dist/repl.js.map +1 -1
  111. package/dist/store/config.d.ts +55 -0
  112. package/dist/store/config.js +127 -0
  113. package/dist/store/config.js.map +1 -1
  114. package/dist/store/history.d.ts +2 -1
  115. package/dist/store/history.js +15 -16
  116. package/dist/store/history.js.map +1 -1
  117. package/dist/store/keys.js +41 -2
  118. package/dist/store/keys.js.map +1 -1
  119. package/dist/tools/definitions.js +31 -6
  120. package/dist/tools/definitions.js.map +1 -1
  121. package/dist/tools/image.d.ts +0 -7
  122. package/dist/tools/image.js +76 -22
  123. package/dist/tools/image.js.map +1 -1
  124. package/dist/tools/jobs.d.ts +11 -1
  125. package/dist/tools/jobs.js +67 -0
  126. package/dist/tools/jobs.js.map +1 -1
  127. package/dist/tools/ocr.d.ts +28 -0
  128. package/dist/tools/ocr.js +316 -0
  129. package/dist/tools/ocr.js.map +1 -0
  130. package/dist/tools/pdf.d.ts +0 -12
  131. package/dist/tools/pdf.js +436 -150
  132. package/dist/tools/pdf.js.map +1 -1
  133. package/dist/tools/registry.js +5 -0
  134. package/dist/tools/registry.js.map +1 -1
  135. package/dist/tui/format-keys.js +10 -0
  136. package/dist/tui/format-keys.js.map +1 -1
  137. package/dist/tui-v2/actions/action-id.d.ts +1 -1
  138. package/dist/tui-v2/actions/action-id.js +3 -0
  139. package/dist/tui-v2/actions/action-id.js.map +1 -1
  140. package/dist/tui-v2/actions/format-shortcuts.js +4 -1
  141. package/dist/tui-v2/actions/format-shortcuts.js.map +1 -1
  142. package/dist/tui-v2/actions/keymap.js +6 -1
  143. package/dist/tui-v2/actions/keymap.js.map +1 -1
  144. package/dist/tui-v2/app/App.js +3 -1
  145. package/dist/tui-v2/app/App.js.map +1 -1
  146. package/dist/tui-v2/app/commands/key-commands.js +117 -15
  147. package/dist/tui-v2/app/commands/key-commands.js.map +1 -1
  148. package/dist/tui-v2/app/commands/picker-commands.js +80 -11
  149. package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
  150. package/dist/tui-v2/bootstrap/console-guard.d.ts +20 -0
  151. package/dist/tui-v2/bootstrap/console-guard.js +73 -0
  152. package/dist/tui-v2/bootstrap/console-guard.js.map +1 -0
  153. package/dist/tui-v2/bootstrap/start-tui-v2.js +14 -0
  154. package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
  155. package/dist/tui-v2/components/composer/composer-input-box.js +5 -1
  156. package/dist/tui-v2/components/composer/composer-input-box.js.map +1 -1
  157. package/dist/tui-v2/components/jobs/jobs-panel.js +25 -1
  158. package/dist/tui-v2/components/jobs/jobs-panel.js.map +1 -1
  159. package/dist/tui-v2/components/modal/keys-modal.js +15 -8
  160. package/dist/tui-v2/components/modal/keys-modal.js.map +1 -1
  161. package/dist/tui-v2/components/modal/secret-modal.js +13 -4
  162. package/dist/tui-v2/components/modal/secret-modal.js.map +1 -1
  163. package/dist/tui-v2/components/pager/pager.js +103 -12
  164. package/dist/tui-v2/components/pager/pager.js.map +1 -1
  165. package/dist/tui-v2/components/status/status-line.d.ts +8 -2
  166. package/dist/tui-v2/components/status/status-line.js +12 -8
  167. package/dist/tui-v2/components/status/status-line.js.map +1 -1
  168. package/dist/tui-v2/components/transcript/thinking-block.d.ts +14 -4
  169. package/dist/tui-v2/components/transcript/thinking-block.js +53 -8
  170. package/dist/tui-v2/components/transcript/thinking-block.js.map +1 -1
  171. package/dist/tui-v2/components/transcript/transcript-row.d.ts +2 -0
  172. package/dist/tui-v2/components/transcript/transcript-row.js +2 -2
  173. package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
  174. package/dist/tui-v2/components/transcript/transcript-view.js +8 -1
  175. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  176. package/dist/tui-v2/composer/composer-action-port.d.ts +15 -3
  177. package/dist/tui-v2/composer/composer-action-port.js +49 -6
  178. package/dist/tui-v2/composer/composer-action-port.js.map +1 -1
  179. package/dist/tui-v2/composer/composer-editor.js +37 -44
  180. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  181. package/dist/tui-v2/composer/draft-actions.d.ts +31 -0
  182. package/dist/tui-v2/composer/draft-actions.js +45 -0
  183. package/dist/tui-v2/composer/draft-actions.js.map +1 -0
  184. package/dist/tui-v2/composer/textarea-keybindings.d.ts +1 -1
  185. package/dist/tui-v2/composer/textarea-keybindings.js +33 -0
  186. package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -1
  187. package/dist/tui-v2/composer/use-draft-actions.d.ts +32 -0
  188. package/dist/tui-v2/composer/use-draft-actions.js +59 -0
  189. package/dist/tui-v2/composer/use-draft-actions.js.map +1 -0
  190. package/dist/tui-v2/controllers/overlay-controller.d.ts +13 -0
  191. package/dist/tui-v2/controllers/overlay-controller.js +5 -2
  192. package/dist/tui-v2/controllers/overlay-controller.js.map +1 -1
  193. package/dist/tui-v2/rendering/artifact-pager-source.d.ts +10 -0
  194. package/dist/tui-v2/rendering/artifact-pager-source.js +6 -0
  195. package/dist/tui-v2/rendering/artifact-pager-source.js.map +1 -1
  196. package/dist/tui-v2/rendering/job-tail-source.d.ts +21 -0
  197. package/dist/tui-v2/rendering/job-tail-source.js +87 -0
  198. package/dist/tui-v2/rendering/job-tail-source.js.map +1 -0
  199. package/dist/tui-v2/state/use-has-draft.d.ts +6 -0
  200. package/dist/tui-v2/state/use-has-draft.js +13 -0
  201. package/dist/tui-v2/state/use-has-draft.js.map +1 -0
  202. package/dist/types.d.ts +7 -1
  203. package/dist/types.js +3 -0
  204. package/dist/types.js.map +1 -1
  205. package/dist/ui/mentions.d.ts +7 -2
  206. package/dist/ui/mentions.js +52 -117
  207. package/dist/ui/mentions.js.map +1 -1
  208. package/dist/version.generated.d.ts +2 -2
  209. package/dist/version.generated.js +2 -2
  210. package/dist/version.generated.js.map +1 -1
  211. package/package.json +1 -1
@@ -1,4 +1,3 @@
1
- export const MAX_IMAGE_BYTES = 3_750_000;
2
1
  const MODEL_IMAGE_MEDIA_TYPES = new Set([
3
2
  "image/png",
4
3
  "image/jpeg",
@@ -48,4 +47,205 @@ export function detectModelImageMediaType(bytes) {
48
47
  }
49
48
  return undefined;
50
49
  }
50
+ export function detectConvertibleImageFormat(bytes) {
51
+ const native = detectModelImageMediaType(bytes);
52
+ if (native)
53
+ return native;
54
+ if (bytes.length >= 2 && bytes[0] === 0x42 && bytes[1] === 0x4d) {
55
+ return "image/bmp";
56
+ }
57
+ if (bytes.length >= 4) {
58
+ const isLittleEndianTiff = bytes[0] === 0x49 && bytes[1] === 0x49 && bytes[2] === 0x2a && bytes[3] === 0x00;
59
+ const isBigEndianTiff = bytes[0] === 0x4d && bytes[1] === 0x4d && bytes[2] === 0x00 && bytes[3] === 0x2a;
60
+ if (isLittleEndianTiff || isBigEndianTiff)
61
+ return "image/tiff";
62
+ if (bytes[0] === 0x00 &&
63
+ bytes[1] === 0x00 &&
64
+ bytes[2] === 0x01 &&
65
+ bytes[3] === 0x00) {
66
+ return "image/x-icon";
67
+ }
68
+ }
69
+ if (bytes.length >= 12) {
70
+ const boxType = String.fromCharCode(bytes[4], bytes[5], bytes[6], bytes[7]);
71
+ if (boxType === "ftyp") {
72
+ const brand = String.fromCharCode(bytes[8], bytes[9], bytes[10], bytes[11]).toLowerCase();
73
+ if (brand.startsWith("av"))
74
+ return "image/avif";
75
+ return "image/heic";
76
+ }
77
+ }
78
+ return undefined;
79
+ }
80
+ function pngDimensions(bytes) {
81
+ if (bytes.length < 24)
82
+ return undefined;
83
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
84
+ const width = view.getUint32(16, false);
85
+ const height = view.getUint32(20, false);
86
+ return width > 0 && height > 0 ? { width, height } : undefined;
87
+ }
88
+ function gifDimensions(bytes) {
89
+ if (bytes.length < 10)
90
+ return undefined;
91
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
92
+ const width = view.getUint16(6, true);
93
+ const height = view.getUint16(8, true);
94
+ return width > 0 && height > 0 ? { width, height } : undefined;
95
+ }
96
+ function jpegDimensions(bytes) {
97
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
98
+ let offset = 2;
99
+ while (offset + 9 < bytes.length) {
100
+ if (bytes[offset] !== 0xff) {
101
+ offset += 1;
102
+ continue;
103
+ }
104
+ let marker = bytes[offset + 1];
105
+ while (marker === 0xff && offset + 2 < bytes.length) {
106
+ offset += 1;
107
+ marker = bytes[offset + 1];
108
+ }
109
+ if (marker === 0xd8 || marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) {
110
+ offset += 2;
111
+ continue;
112
+ }
113
+ if (marker === 0xd9 || marker === 0xda)
114
+ return undefined;
115
+ const length = view.getUint16(offset + 2, false);
116
+ if (length < 2)
117
+ return undefined;
118
+ const isStartOfFrame = marker >= 0xc0 &&
119
+ marker <= 0xcf &&
120
+ marker !== 0xc4 &&
121
+ marker !== 0xc8 &&
122
+ marker !== 0xcc;
123
+ if (isStartOfFrame) {
124
+ if (offset + 9 >= bytes.length)
125
+ return undefined;
126
+ const height = view.getUint16(offset + 5, false);
127
+ const width = view.getUint16(offset + 7, false);
128
+ return width > 0 && height > 0 ? { width, height } : undefined;
129
+ }
130
+ offset += 2 + length;
131
+ }
132
+ return undefined;
133
+ }
134
+ function webpDimensions(bytes) {
135
+ if (bytes.length < 30)
136
+ return undefined;
137
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
138
+ const chunk = String.fromCharCode(bytes[12], bytes[13], bytes[14], bytes[15]);
139
+ if (chunk === "VP8X") {
140
+ const width = 1 + (bytes[24] | (bytes[25] << 8) | (bytes[26] << 16));
141
+ const height = 1 + (bytes[27] | (bytes[28] << 8) | (bytes[29] << 16));
142
+ return width > 1 && height > 1 ? { width, height } : undefined;
143
+ }
144
+ if (chunk === "VP8 ") {
145
+ if (bytes.length < 30)
146
+ return undefined;
147
+ if (bytes[23] !== 0x9d || bytes[24] !== 0x01 || bytes[25] !== 0x2a) {
148
+ return undefined;
149
+ }
150
+ const width = view.getUint16(26, true) & 0x3fff;
151
+ const height = view.getUint16(28, true) & 0x3fff;
152
+ return width > 0 && height > 0 ? { width, height } : undefined;
153
+ }
154
+ if (chunk === "VP8L") {
155
+ if (bytes.length < 25 || bytes[20] !== 0x2f)
156
+ return undefined;
157
+ const packed = bytes[21] |
158
+ (bytes[22] << 8) |
159
+ (bytes[23] << 16) |
160
+ (bytes[24] << 24);
161
+ const width = (packed & 0x3fff) + 1;
162
+ const height = ((packed >>> 14) & 0x3fff) + 1;
163
+ return width > 0 && height > 0 ? { width, height } : undefined;
164
+ }
165
+ return undefined;
166
+ }
167
+ export function readImageDimensions(bytes) {
168
+ switch (detectModelImageMediaType(bytes)) {
169
+ case "image/png":
170
+ return pngDimensions(bytes);
171
+ case "image/gif":
172
+ return gifDimensions(bytes);
173
+ case "image/jpeg":
174
+ return jpegDimensions(bytes);
175
+ case "image/webp":
176
+ return webpDimensions(bytes);
177
+ default:
178
+ return undefined;
179
+ }
180
+ }
181
+ const ANTHROPIC_BUDGET = {
182
+ maxBytes: 3_600_000,
183
+ hardMaxBytes: 3_900_000,
184
+ maxDimension: 1568,
185
+ maxCount: 20,
186
+ maxTotalBytes: 12_000_000,
187
+ label: "Anthropic",
188
+ };
189
+ const OPENAI_BUDGET = {
190
+ maxBytes: 4_500_000,
191
+ hardMaxBytes: 18_000_000,
192
+ maxDimension: 2048,
193
+ maxCount: 10,
194
+ maxTotalBytes: 15_000_000,
195
+ label: "OpenAI",
196
+ };
197
+ const GEMINI_BUDGET = {
198
+ maxBytes: 4_500_000,
199
+ hardMaxBytes: 14_000_000,
200
+ maxDimension: 3072,
201
+ maxCount: 12,
202
+ maxTotalBytes: 15_000_000,
203
+ label: "Gemini",
204
+ };
205
+ const LOCAL_BUDGET = {
206
+ maxBytes: 6_000_000,
207
+ hardMaxBytes: 40_000_000,
208
+ maxDimension: 2048,
209
+ maxCount: 8,
210
+ maxTotalBytes: 24_000_000,
211
+ label: "Ollama",
212
+ };
213
+ const GATEWAY_BUDGET = {
214
+ maxBytes: 3_600_000,
215
+ hardMaxBytes: 5_000_000,
216
+ maxDimension: 2048,
217
+ maxCount: 8,
218
+ maxTotalBytes: 10_000_000,
219
+ label: "gateway",
220
+ };
221
+ function budgetForModelFamily(model) {
222
+ if (/claude|anthropic/i.test(model))
223
+ return ANTHROPIC_BUDGET;
224
+ if (/gemini|gemma/i.test(model))
225
+ return GEMINI_BUDGET;
226
+ if (/gpt-|^o[134]|openai/i.test(model))
227
+ return OPENAI_BUDGET;
228
+ return undefined;
229
+ }
230
+ export function imageBudgetFor(provider, model = "") {
231
+ switch (provider) {
232
+ case "anthropic":
233
+ return ANTHROPIC_BUDGET;
234
+ case "openai":
235
+ return OPENAI_BUDGET;
236
+ case "gemini":
237
+ return GEMINI_BUDGET;
238
+ case "ollama":
239
+ return LOCAL_BUDGET;
240
+ default:
241
+ return budgetForModelFamily(model) ?? GATEWAY_BUDGET;
242
+ }
243
+ }
244
+ export function formatByteSize(bytes) {
245
+ if (bytes < 1024)
246
+ return `${bytes} B`;
247
+ if (bytes < 1024 * 1024)
248
+ return `${(bytes / 1024).toFixed(0)} KB`;
249
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
250
+ }
51
251
  //# sourceMappingURL=image-content.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"image-content.js","sourceRoot":"","sources":["../../src/attachments/image-content.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC;AAEzC,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC;IACtC,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;CACb,CAAC,CAAC;AAEH,MAAM,UAAU,qBAAqB,CAAC,SAAiB;IACrD,OAAO,uBAAuB,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,yBAAyB,CACvC,KAAiB;IAEjB,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EACjB,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EACjB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;QACxC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EACjB,CAAC;QACD,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IACE,KAAK,CAAC,MAAM,IAAI,EAAE;QAClB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI;QACjB,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI;QAClB,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,EAClB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"image-content.js","sourceRoot":"","sources":["../../src/attachments/image-content.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { imageBudgetFor, type ImageBudget, type ImageDimensions, type ModelImageMediaType } from "./image-content.js";
2
+ export { imageBudgetFor };
3
+ export type { ImageBudget };
4
+ export interface PreparedImage {
5
+ readonly ok: true;
6
+ readonly path: string;
7
+ readonly sourcePath: string;
8
+ readonly mediaType: ModelImageMediaType;
9
+ readonly byteLength: number;
10
+ readonly dimensions?: ImageDimensions | undefined;
11
+ readonly transcoded: boolean;
12
+ readonly resized?: boolean | undefined;
13
+ }
14
+ export interface RejectedImage {
15
+ readonly ok: false;
16
+ readonly sourcePath: string;
17
+ readonly reason: string;
18
+ readonly recoverable: boolean;
19
+ }
20
+ export type ImagePreparation = PreparedImage | RejectedImage;
21
+ export declare function hasImageTranscoder(): boolean;
22
+ export declare function imageTranscoderHint(): string;
23
+ export declare function clearImagePreparationCache(): void;
24
+ export declare function prepareImageForModel(sourcePath: string, budget: ImageBudget, baseDir?: string): ImagePreparation;
25
+ export declare function describePreparedImage(prepared: PreparedImage): string;
@@ -0,0 +1,390 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { closeSync, existsSync, mkdirSync, openSync, readSync, rmSync, statSync, } from "node:fs";
3
+ import { platform } from "node:os";
4
+ import { basename, extname, join } from "node:path";
5
+ import { createHash } from "node:crypto";
6
+ import { findExecutableSync } from "../os/command.js";
7
+ import { safeCwd } from "../os/cwd.js";
8
+ import { scratchDirFor } from "../prompts/index.js";
9
+ import { detectConvertibleImageFormat, detectModelImageMediaType, formatByteSize, imageBudgetFor, readImageDimensions, } from "./image-content.js";
10
+ export { imageBudgetFor };
11
+ const HEADER_PROBE_BYTES = 262_144;
12
+ const ABSOLUTE_MAX_SOURCE_BYTES = 268_435_456;
13
+ const MIN_TARGET_DIMENSION = 320;
14
+ const TRANSCODE_TIMEOUT_MS = 30_000;
15
+ function readHead(path, length) {
16
+ const handle = openSync(path, "r");
17
+ try {
18
+ const buffer = Buffer.alloc(length);
19
+ const read = readSync(handle, buffer, 0, length, 0);
20
+ return buffer.subarray(0, read);
21
+ }
22
+ finally {
23
+ closeSync(handle);
24
+ }
25
+ }
26
+ function probeImage(path, byteLength) {
27
+ const head = readHead(path, Math.min(byteLength, HEADER_PROBE_BYTES));
28
+ return {
29
+ byteLength,
30
+ mediaType: detectModelImageMediaType(head),
31
+ format: detectConvertibleImageFormat(head),
32
+ dimensions: readImageDimensions(head),
33
+ };
34
+ }
35
+ function resolveBinary(command) {
36
+ return findExecutableSync(command);
37
+ }
38
+ function hasBinary(command) {
39
+ return resolveBinary(command) !== undefined;
40
+ }
41
+ function runQuiet(command, argv) {
42
+ const executable = resolveBinary(command);
43
+ if (!executable)
44
+ return false;
45
+ const result = spawnSync(executable, argv, {
46
+ stdio: "ignore",
47
+ timeout: TRANSCODE_TIMEOUT_MS,
48
+ });
49
+ return result.status === 0 && !result.error;
50
+ }
51
+ const transcoders = [
52
+ {
53
+ id: "magick",
54
+ available: () => hasBinary("magick"),
55
+ run: (source, destination, target) => runQuiet("magick", magickArgv(source, destination, target)),
56
+ },
57
+ {
58
+ id: "convert",
59
+ available: () => platform() !== "win32" && hasBinary("convert"),
60
+ run: (source, destination, target) => runQuiet("convert", magickArgv(source, destination, target)),
61
+ },
62
+ {
63
+ id: "sips",
64
+ available: () => platform() === "darwin" && hasBinary("sips"),
65
+ run: (source, destination, target) => {
66
+ const argv = ["-s", "format", target.format === "png" ? "png" : "jpeg"];
67
+ if (target.format === "jpeg") {
68
+ argv.push("-s", "formatOptions", String(target.quality));
69
+ }
70
+ if (target.shrinks)
71
+ argv.push("-Z", String(target.maxDimension));
72
+ argv.push(source, "--out", destination);
73
+ return runQuiet("sips", argv);
74
+ },
75
+ },
76
+ {
77
+ id: "ffmpeg",
78
+ available: () => hasBinary("ffmpeg"),
79
+ run: (source, destination, target) => {
80
+ if (target.format !== "png")
81
+ return false;
82
+ return runQuiet("ffmpeg", [
83
+ "-y",
84
+ "-loglevel",
85
+ "error",
86
+ "-i",
87
+ source,
88
+ "-vf",
89
+ `scale=w=min(iw\\,${target.maxDimension}):h=min(ih\\,${target.maxDimension}):force_original_aspect_ratio=decrease`,
90
+ "-frames:v",
91
+ "1",
92
+ destination,
93
+ ]);
94
+ },
95
+ },
96
+ ];
97
+ function magickArgv(source, destination, target) {
98
+ const argv = [`${source}[0]`, "-auto-orient", "-strip"];
99
+ if (target.shrinks) {
100
+ argv.push("-resize", `${target.maxDimension}x${target.maxDimension}>`);
101
+ }
102
+ if (target.format === "jpeg") {
103
+ argv.push("-background", "white", "-alpha", "remove", "-alpha", "off");
104
+ argv.push("-quality", String(target.quality));
105
+ }
106
+ else {
107
+ argv.push("-define", "png:compression-level=9");
108
+ }
109
+ argv.push(destination);
110
+ return argv;
111
+ }
112
+ function externalDimensions(path) {
113
+ const parse = (stdout) => {
114
+ const width = /pixelWidth:\s*(\d+)/.exec(stdout)?.[1];
115
+ const height = /pixelHeight:\s*(\d+)/.exec(stdout)?.[1];
116
+ if (width && height) {
117
+ return { width: Number(width), height: Number(height) };
118
+ }
119
+ const pair = /^(\d+)\s+(\d+)/.exec(stdout.trim());
120
+ return pair ? { width: Number(pair[1]), height: Number(pair[2]) } : undefined;
121
+ };
122
+ const attempts = [];
123
+ if (hasBinary("magick")) {
124
+ attempts.push(["magick", ["identify", "-format", "%w %h", `${path}[0]`]]);
125
+ }
126
+ if (platform() !== "win32" && hasBinary("identify")) {
127
+ attempts.push(["identify", ["-format", "%w %h", `${path}[0]`]]);
128
+ }
129
+ if (platform() === "darwin" && hasBinary("sips")) {
130
+ attempts.push(["sips", ["-g", "pixelWidth", "-g", "pixelHeight", path]]);
131
+ }
132
+ for (const [command, argv] of attempts) {
133
+ const executable = resolveBinary(command);
134
+ if (!executable)
135
+ continue;
136
+ const result = spawnSync(executable, argv, {
137
+ encoding: "utf8",
138
+ timeout: 10_000,
139
+ stdio: ["ignore", "pipe", "ignore"],
140
+ });
141
+ if (result.status !== 0 || typeof result.stdout !== "string")
142
+ continue;
143
+ const dimensions = parse(result.stdout);
144
+ if (dimensions && dimensions.width > 0 && dimensions.height > 0) {
145
+ return dimensions;
146
+ }
147
+ }
148
+ return undefined;
149
+ }
150
+ function availableTranscoders() {
151
+ return transcoders.filter((transcoder) => transcoder.available());
152
+ }
153
+ export function hasImageTranscoder() {
154
+ return availableTranscoders().length > 0;
155
+ }
156
+ export function imageTranscoderHint() {
157
+ return platform() === "darwin"
158
+ ? "install ImageMagick (brew install imagemagick) or resize it with sips"
159
+ : platform() === "win32"
160
+ ? "install ImageMagick (scoop install imagemagick) and retry"
161
+ : "install ImageMagick (apt install imagemagick / dnf install ImageMagick) and retry";
162
+ }
163
+ function scale(dimension, factor) {
164
+ return Math.max(MIN_TARGET_DIMENSION, Math.round(dimension * factor));
165
+ }
166
+ function ladderFor(budget, probe) {
167
+ const longestEdge = probe.dimensions
168
+ ? Math.max(probe.dimensions.width, probe.dimensions.height)
169
+ : undefined;
170
+ const base = longestEdge === undefined
171
+ ? budget.maxDimension
172
+ : Math.max(MIN_TARGET_DIMENSION, Math.min(budget.maxDimension, longestEdge));
173
+ const photographic = probe.format === "image/jpeg" ||
174
+ probe.format === "image/heic" ||
175
+ probe.format === "image/avif";
176
+ const dimensions = photographic
177
+ ? [base, scale(base, 0.75), scale(base, 0.5), 1280, 1024, 800]
178
+ : [base, base, base, scale(base, 0.75), scale(base, 0.75), 1280, 1024, 800];
179
+ const plan = photographic
180
+ ? [
181
+ ["jpeg", dimensions[0], 88],
182
+ ["jpeg", dimensions[1], 84],
183
+ ["jpeg", dimensions[2], 78],
184
+ ]
185
+ : [
186
+ ["png", dimensions[0], 100],
187
+ ["jpeg", dimensions[1], 92],
188
+ ["jpeg", dimensions[2], 80],
189
+ ["png", dimensions[3], 100],
190
+ ["jpeg", dimensions[4], 85],
191
+ ];
192
+ plan.push(["jpeg", Math.min(base, 1280), 78], ["jpeg", Math.min(base, 1024), 70], ["jpeg", Math.min(base, 800), 58]);
193
+ const seen = new Set();
194
+ const targets = [];
195
+ for (const [format, maxDimension, quality] of plan) {
196
+ const key = `${format}:${maxDimension}:${quality}`;
197
+ if (seen.has(key))
198
+ continue;
199
+ seen.add(key);
200
+ targets.push({
201
+ format,
202
+ maxDimension,
203
+ quality,
204
+ shrinks: longestEdge === undefined || longestEdge > maxDimension,
205
+ });
206
+ }
207
+ return targets;
208
+ }
209
+ function fittedDirectory(baseDir) {
210
+ const directory = join(scratchDirFor(baseDir), "attachments", "fitted");
211
+ mkdirSync(directory, { recursive: true });
212
+ return directory;
213
+ }
214
+ function stemFor(path) {
215
+ const extension = extname(path);
216
+ const stem = basename(path, extension)
217
+ .replace(/[^\w.-]+/g, "_")
218
+ .replace(/_+/g, "_")
219
+ .slice(0, 60);
220
+ return stem || "image";
221
+ }
222
+ function transcodeToBudget(source, probe, budget, baseDir) {
223
+ const tools = availableTranscoders();
224
+ if (tools.length === 0)
225
+ return undefined;
226
+ const directory = fittedDirectory(baseDir);
227
+ const fingerprint = createHash("sha1")
228
+ .update(`${source}|${probe.byteLength}|${budget.maxBytes}|${budget.maxDimension}`)
229
+ .digest("hex")
230
+ .slice(0, 12);
231
+ const stem = stemFor(source);
232
+ let best;
233
+ for (const target of ladderFor(budget, probe)) {
234
+ const extension = target.format === "png" ? "png" : "jpg";
235
+ const destination = join(directory, `${fingerprint}-${target.maxDimension}q${target.quality}-${stem}.${extension}`);
236
+ for (const tool of tools) {
237
+ rmSync(destination, { force: true });
238
+ if (!tool.run(source, destination, target))
239
+ continue;
240
+ let byteLength = 0;
241
+ try {
242
+ byteLength = statSync(destination).size;
243
+ }
244
+ catch {
245
+ continue;
246
+ }
247
+ if (byteLength === 0) {
248
+ rmSync(destination, { force: true });
249
+ continue;
250
+ }
251
+ const head = readHead(destination, Math.min(byteLength, HEADER_PROBE_BYTES));
252
+ const mediaType = detectModelImageMediaType(head);
253
+ if (!mediaType) {
254
+ rmSync(destination, { force: true });
255
+ continue;
256
+ }
257
+ const dimensions = readImageDimensions(head);
258
+ const sourceEdge = probe.dimensions
259
+ ? Math.max(probe.dimensions.width, probe.dimensions.height)
260
+ : undefined;
261
+ const outputEdge = dimensions
262
+ ? Math.max(dimensions.width, dimensions.height)
263
+ : undefined;
264
+ const candidate = {
265
+ ok: true,
266
+ path: destination,
267
+ sourcePath: source,
268
+ mediaType,
269
+ byteLength,
270
+ dimensions,
271
+ transcoded: true,
272
+ resized: sourceEdge === undefined ||
273
+ outputEdge === undefined ||
274
+ outputEdge < sourceEdge,
275
+ };
276
+ if (byteLength <= budget.maxBytes)
277
+ return candidate;
278
+ if (!best || byteLength < best.byteLength)
279
+ best = candidate;
280
+ break;
281
+ }
282
+ }
283
+ if (best && best.byteLength <= budget.hardMaxBytes)
284
+ return best;
285
+ return undefined;
286
+ }
287
+ const preparationCache = new Map();
288
+ function cacheKey(path, mtimeMs, size, budget) {
289
+ return `${path}|${Math.round(mtimeMs)}|${size}|${budget.maxBytes}|${budget.hardMaxBytes}|${budget.maxDimension}`;
290
+ }
291
+ export function clearImagePreparationCache() {
292
+ preparationCache.clear();
293
+ }
294
+ function reject(sourcePath, reason, recoverable = false) {
295
+ return { ok: false, sourcePath, reason, recoverable };
296
+ }
297
+ export function prepareImageForModel(sourcePath, budget, baseDir = safeCwd()) {
298
+ let info;
299
+ try {
300
+ info = statSync(sourcePath);
301
+ }
302
+ catch (error) {
303
+ return reject(sourcePath, `could not be read (${error instanceof Error ? error.message : String(error)})`);
304
+ }
305
+ if (!info.isFile())
306
+ return reject(sourcePath, "is not a regular file");
307
+ if (info.size === 0)
308
+ return reject(sourcePath, "is empty (0 bytes)");
309
+ if (info.size > ABSOLUTE_MAX_SOURCE_BYTES) {
310
+ return reject(sourcePath, `is ${formatByteSize(info.size)}, far beyond any model image limit`);
311
+ }
312
+ const key = cacheKey(sourcePath, info.mtimeMs, info.size, budget);
313
+ const cached = preparationCache.get(key);
314
+ if (cached && (!cached.ok || existsSync(cached.path)))
315
+ return cached;
316
+ const outcome = prepare(sourcePath, info.size, budget, baseDir);
317
+ preparationCache.set(key, outcome);
318
+ return outcome;
319
+ }
320
+ function prepare(sourcePath, size, budget, baseDir) {
321
+ let probe;
322
+ try {
323
+ probe = probeImage(sourcePath, size);
324
+ }
325
+ catch (error) {
326
+ return reject(sourcePath, `could not be read (${error instanceof Error ? error.message : String(error)})`);
327
+ }
328
+ const format = probe.format;
329
+ if (!format) {
330
+ return reject(sourcePath, "its bytes are not a supported image (expected PNG, JPEG, GIF, WebP, BMP, TIFF, HEIC or AVIF)");
331
+ }
332
+ if (!probe.dimensions &&
333
+ (probe.mediaType === undefined || size > budget.maxBytes)) {
334
+ const external = externalDimensions(sourcePath);
335
+ if (external)
336
+ probe = { ...probe, dimensions: external };
337
+ }
338
+ const oversizedDimensions = probe.dimensions
339
+ ? Math.max(probe.dimensions.width, probe.dimensions.height) >
340
+ budget.maxDimension
341
+ : false;
342
+ const nativeAndFitting = probe.mediaType !== undefined &&
343
+ size <= budget.maxBytes &&
344
+ !oversizedDimensions;
345
+ if (nativeAndFitting) {
346
+ return {
347
+ ok: true,
348
+ path: sourcePath,
349
+ sourcePath,
350
+ mediaType: probe.mediaType,
351
+ byteLength: size,
352
+ dimensions: probe.dimensions,
353
+ transcoded: false,
354
+ };
355
+ }
356
+ const fitted = transcodeToBudget(sourcePath, probe, budget, baseDir);
357
+ if (fitted)
358
+ return fitted;
359
+ if (probe.mediaType && size <= budget.hardMaxBytes) {
360
+ return {
361
+ ok: true,
362
+ path: sourcePath,
363
+ sourcePath,
364
+ mediaType: probe.mediaType,
365
+ byteLength: size,
366
+ dimensions: probe.dimensions,
367
+ transcoded: false,
368
+ };
369
+ }
370
+ if (!probe.mediaType) {
371
+ return reject(sourcePath, `is ${format.replace("image/", "").toUpperCase()}, which models cannot read, and no converter is installed — ${imageTranscoderHint()}`, true);
372
+ }
373
+ return reject(sourcePath, `is ${formatByteSize(size)}, above the ${formatByteSize(budget.hardMaxBytes)} per-image limit for ${budget.label} models` +
374
+ (hasImageTranscoder()
375
+ ? " and could not be downscaled far enough"
376
+ : ` and no downscaler is installed — ${imageTranscoderHint()}`), true);
377
+ }
378
+ export function describePreparedImage(prepared) {
379
+ const size = formatByteSize(prepared.byteLength);
380
+ const dimensions = prepared.dimensions
381
+ ? `${prepared.dimensions.width}x${prepared.dimensions.height}`
382
+ : "unknown size";
383
+ const format = prepared.mediaType.replace("image/", "").toUpperCase();
384
+ if (!prepared.transcoded)
385
+ return `${dimensions} ${format} (${size})`;
386
+ return prepared.resized
387
+ ? `resized to ${dimensions} ${format} (${size}) to fit the model input limit`
388
+ : `converted to ${dimensions} ${format} (${size}) so the model can read it`;
389
+ }
390
+ //# sourceMappingURL=image-prepare.js.map