dominds 1.17.7 → 1.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/dialog-fork.js +11 -5
  2. package/dist/dialog-instance-registry.js +1 -18
  3. package/dist/dialog.d.ts +21 -31
  4. package/dist/dialog.js +207 -56
  5. package/dist/docs/dialog-system.md +3 -2
  6. package/dist/docs/dialog-system.zh.md +3 -2
  7. package/dist/docs/tellask-collab.md +2 -1
  8. package/dist/docs/tellask-collab.zh.md +2 -1
  9. package/dist/llm/defaults.yaml +43 -0
  10. package/dist/llm/gen/anthropic.js +153 -12
  11. package/dist/llm/gen/codex.js +160 -10
  12. package/dist/llm/gen/openai-compatible.js +141 -81
  13. package/dist/llm/gen/openai.js +178 -12
  14. package/dist/llm/gen/tool-result-image-ingest.d.ts +17 -8
  15. package/dist/llm/gen/tool-result-image-ingest.js +127 -27
  16. package/dist/llm/gen.d.ts +13 -0
  17. package/dist/llm/kernel-driver/drive.js +79 -15
  18. package/dist/llm/kernel-driver/flow.js +158 -41
  19. package/dist/llm/kernel-driver/reply-guidance.d.ts +6 -6
  20. package/dist/llm/kernel-driver/reply-guidance.js +169 -2
  21. package/dist/llm/kernel-driver/runtime.d.ts +2 -2
  22. package/dist/llm/kernel-driver/subdialog.js +4 -0
  23. package/dist/llm/kernel-driver/tellask-special.d.ts +2 -0
  24. package/dist/llm/kernel-driver/tellask-special.js +11 -6
  25. package/dist/llm/kernel-driver/types.d.ts +14 -24
  26. package/dist/minds/system-prompt.js +8 -8
  27. package/dist/persistence.d.ts +6 -5
  28. package/dist/persistence.js +198 -39
  29. package/dist/priming.js +98 -3
  30. package/dist/runtime/driver-messages.d.ts +1 -0
  31. package/dist/runtime/driver-messages.js +32 -10
  32. package/dist/runtime/reply-prompt-copy.js +4 -4
  33. package/dist/server/api-routes.js +11 -43
  34. package/dist/server/websocket-handler.js +155 -10
  35. package/dist/tools/builtins.js +10 -4
  36. package/dist/tools/cmd-runner.js +110 -49
  37. package/dist/tools/picture.d.ts +3 -0
  38. package/dist/tools/picture.js +344 -0
  39. package/dist/tools/prompts/control/en/principles.md +4 -2
  40. package/dist/tools/prompts/control/en/scenarios.md +2 -1
  41. package/dist/tools/prompts/control/en/tools.md +6 -6
  42. package/dist/tools/prompts/control/zh/principles.md +4 -2
  43. package/dist/tools/prompts/control/zh/scenarios.md +2 -1
  44. package/dist/tools/prompts/control/zh/tools.md +1 -1
  45. package/dist/tools/prompts/ws_mod.en.md +1 -0
  46. package/dist/tools/prompts/ws_mod.zh.md +1 -0
  47. package/dist/tools/prompts/ws_read/en/tools.md +25 -5
  48. package/dist/tools/prompts/ws_read/zh/tools.md +25 -5
  49. package/package.json +4 -4
  50. package/webapp/dist/assets/{_basePickBy-u7tNFRWr.js → _basePickBy-BPJaiZdW.js} +3 -3
  51. package/webapp/dist/assets/{_basePickBy-u7tNFRWr.js.map → _basePickBy-BPJaiZdW.js.map} +1 -1
  52. package/webapp/dist/assets/{_baseUniq-CH9LRkiH.js → _baseUniq-BEetT15i.js} +2 -2
  53. package/webapp/dist/assets/{_baseUniq-CH9LRkiH.js.map → _baseUniq-BEetT15i.js.map} +1 -1
  54. package/webapp/dist/assets/{arc-Bo0Lw3ZP.js → arc-Dm7Zf36f.js} +2 -2
  55. package/webapp/dist/assets/{arc-Bo0Lw3ZP.js.map → arc-Dm7Zf36f.js.map} +1 -1
  56. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ckyr89Iw.js → architectureDiagram-VXUJARFQ-BpTPtkuo.js} +7 -7
  57. package/webapp/dist/assets/{architectureDiagram-VXUJARFQ-Ckyr89Iw.js.map → architectureDiagram-VXUJARFQ-BpTPtkuo.js.map} +1 -1
  58. package/webapp/dist/assets/{blockDiagram-VD42YOAC-BSXoLLq_.js → blockDiagram-VD42YOAC-C8fLN0iu.js} +7 -7
  59. package/webapp/dist/assets/{blockDiagram-VD42YOAC-BSXoLLq_.js.map → blockDiagram-VD42YOAC-C8fLN0iu.js.map} +1 -1
  60. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CgCG1cP0.js → c4Diagram-YG6GDRKO-BpPr62CH.js} +3 -3
  61. package/webapp/dist/assets/{c4Diagram-YG6GDRKO-CgCG1cP0.js.map → c4Diagram-YG6GDRKO-BpPr62CH.js.map} +1 -1
  62. package/webapp/dist/assets/{channel-Crbz0zgt.js → channel-EMYoPjW3.js} +2 -2
  63. package/webapp/dist/assets/{channel-Crbz0zgt.js.map → channel-EMYoPjW3.js.map} +1 -1
  64. package/webapp/dist/assets/{chunk-4BX2VUAB-BIIEb_5S.js → chunk-4BX2VUAB-CefNtjWG.js} +2 -2
  65. package/webapp/dist/assets/{chunk-4BX2VUAB-BIIEb_5S.js.map → chunk-4BX2VUAB-CefNtjWG.js.map} +1 -1
  66. package/webapp/dist/assets/{chunk-55IACEB6-CaJzGgc9.js → chunk-55IACEB6-C_X7T43V.js} +2 -2
  67. package/webapp/dist/assets/{chunk-55IACEB6-CaJzGgc9.js.map → chunk-55IACEB6-C_X7T43V.js.map} +1 -1
  68. package/webapp/dist/assets/{chunk-B4BG7PRW-DHQwhO9F.js → chunk-B4BG7PRW-BRe3_2oA.js} +5 -5
  69. package/webapp/dist/assets/{chunk-B4BG7PRW-DHQwhO9F.js.map → chunk-B4BG7PRW-BRe3_2oA.js.map} +1 -1
  70. package/webapp/dist/assets/{chunk-DI55MBZ5-CG1lO0R8.js → chunk-DI55MBZ5-CbvrsI_w.js} +4 -4
  71. package/webapp/dist/assets/{chunk-DI55MBZ5-CG1lO0R8.js.map → chunk-DI55MBZ5-CbvrsI_w.js.map} +1 -1
  72. package/webapp/dist/assets/{chunk-FMBD7UC4-DAUsTLPS.js → chunk-FMBD7UC4-ORmtkrtS.js} +2 -2
  73. package/webapp/dist/assets/{chunk-FMBD7UC4-DAUsTLPS.js.map → chunk-FMBD7UC4-ORmtkrtS.js.map} +1 -1
  74. package/webapp/dist/assets/{chunk-QN33PNHL-BfQs-QHE.js → chunk-QN33PNHL-LTAOVhWu.js} +2 -2
  75. package/webapp/dist/assets/{chunk-QN33PNHL-BfQs-QHE.js.map → chunk-QN33PNHL-LTAOVhWu.js.map} +1 -1
  76. package/webapp/dist/assets/{chunk-QZHKN3VN-C5iKQ6mQ.js → chunk-QZHKN3VN-ZoUM_4u5.js} +2 -2
  77. package/webapp/dist/assets/{chunk-QZHKN3VN-C5iKQ6mQ.js.map → chunk-QZHKN3VN-ZoUM_4u5.js.map} +1 -1
  78. package/webapp/dist/assets/{chunk-TZMSLE5B-CBShDwy2.js → chunk-TZMSLE5B-Gao4qrq7.js} +2 -2
  79. package/webapp/dist/assets/{chunk-TZMSLE5B-CBShDwy2.js.map → chunk-TZMSLE5B-Gao4qrq7.js.map} +1 -1
  80. package/webapp/dist/assets/{classDiagram-2ON5EDUG-DrfJDzYO.js → classDiagram-2ON5EDUG-uha1vIGN.js} +6 -6
  81. package/webapp/dist/assets/{classDiagram-2ON5EDUG-DrfJDzYO.js.map → classDiagram-2ON5EDUG-uha1vIGN.js.map} +1 -1
  82. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-DrfJDzYO.js → classDiagram-v2-WZHVMYZB-uha1vIGN.js} +6 -6
  83. package/webapp/dist/assets/{classDiagram-v2-WZHVMYZB-DrfJDzYO.js.map → classDiagram-v2-WZHVMYZB-uha1vIGN.js.map} +1 -1
  84. package/webapp/dist/assets/{clone-Cd-48URG.js → clone-_9Ayb1Gp.js} +2 -2
  85. package/webapp/dist/assets/{clone-Cd-48URG.js.map → clone-_9Ayb1Gp.js.map} +1 -1
  86. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCji0YN3.js → cose-bilkent-S5V4N54A-C8wDw3NY.js} +2 -2
  87. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-CCji0YN3.js.map → cose-bilkent-S5V4N54A-C8wDw3NY.js.map} +1 -1
  88. package/webapp/dist/assets/{dagre-6UL2VRFP-B94p-Dpl.js → dagre-6UL2VRFP-BUSeNot0.js} +7 -7
  89. package/webapp/dist/assets/{dagre-6UL2VRFP-B94p-Dpl.js.map → dagre-6UL2VRFP-BUSeNot0.js.map} +1 -1
  90. package/webapp/dist/assets/{diagram-PSM6KHXK-DP-zGmAS.js → diagram-PSM6KHXK-CMZAksVC.js} +8 -8
  91. package/webapp/dist/assets/{diagram-PSM6KHXK-DP-zGmAS.js.map → diagram-PSM6KHXK-CMZAksVC.js.map} +1 -1
  92. package/webapp/dist/assets/{diagram-QEK2KX5R-DquJirs4.js → diagram-QEK2KX5R-BQKoRtwy.js} +7 -7
  93. package/webapp/dist/assets/{diagram-QEK2KX5R-DquJirs4.js.map → diagram-QEK2KX5R-BQKoRtwy.js.map} +1 -1
  94. package/webapp/dist/assets/{diagram-S2PKOQOG-Dt5W2t6V.js → diagram-S2PKOQOG-DjMG97kd.js} +7 -7
  95. package/webapp/dist/assets/{diagram-S2PKOQOG-Dt5W2t6V.js.map → diagram-S2PKOQOG-DjMG97kd.js.map} +1 -1
  96. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Bs0-2Rfj.js → erDiagram-Q2GNP2WA-BujwA137.js} +5 -5
  97. package/webapp/dist/assets/{erDiagram-Q2GNP2WA-Bs0-2Rfj.js.map → erDiagram-Q2GNP2WA-BujwA137.js.map} +1 -1
  98. package/webapp/dist/assets/{flowDiagram-NV44I4VS-cJjXWAlK.js → flowDiagram-NV44I4VS-DgwPjg4y.js} +6 -6
  99. package/webapp/dist/assets/{flowDiagram-NV44I4VS-cJjXWAlK.js.map → flowDiagram-NV44I4VS-DgwPjg4y.js.map} +1 -1
  100. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Du1AUaKm.js → ganttDiagram-JELNMOA3-Db2ykf3E.js} +3 -3
  101. package/webapp/dist/assets/{ganttDiagram-JELNMOA3-Du1AUaKm.js.map → ganttDiagram-JELNMOA3-Db2ykf3E.js.map} +1 -1
  102. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-D_jVOYOK.js → gitGraphDiagram-V2S2FVAM-D_gSifkv.js} +8 -8
  103. package/webapp/dist/assets/{gitGraphDiagram-V2S2FVAM-D_jVOYOK.js.map → gitGraphDiagram-V2S2FVAM-D_gSifkv.js.map} +1 -1
  104. package/webapp/dist/assets/{graph-CuF_sq4r.js → graph-BHjCU5xP.js} +3 -3
  105. package/webapp/dist/assets/{graph-CuF_sq4r.js.map → graph-BHjCU5xP.js.map} +1 -1
  106. package/webapp/dist/assets/{index-DAShQcjb.js → index-DLajsIDJ.js} +1363 -248
  107. package/webapp/dist/assets/{index-DAShQcjb.js.map → index-DLajsIDJ.js.map} +1 -1
  108. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-CEFlo_Hl.js → infoDiagram-HS3SLOUP-BDba5pKs.js} +6 -6
  109. package/webapp/dist/assets/{infoDiagram-HS3SLOUP-CEFlo_Hl.js.map → infoDiagram-HS3SLOUP-BDba5pKs.js.map} +1 -1
  110. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-zc2Q4Se9.js → journeyDiagram-XKPGCS4Q-CmJAbmlm.js} +5 -5
  111. package/webapp/dist/assets/{journeyDiagram-XKPGCS4Q-zc2Q4Se9.js.map → journeyDiagram-XKPGCS4Q-CmJAbmlm.js.map} +1 -1
  112. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-oT42RM2a.js → kanban-definition-3W4ZIXB7-DxQeBTDk.js} +3 -3
  113. package/webapp/dist/assets/{kanban-definition-3W4ZIXB7-oT42RM2a.js.map → kanban-definition-3W4ZIXB7-DxQeBTDk.js.map} +1 -1
  114. package/webapp/dist/assets/{layout-BvaOu3k2.js → layout-DteV_yE8.js} +5 -5
  115. package/webapp/dist/assets/{layout-BvaOu3k2.js.map → layout-DteV_yE8.js.map} +1 -1
  116. package/webapp/dist/assets/{linear-Cg-CjocS.js → linear-zItbPrND.js} +2 -2
  117. package/webapp/dist/assets/{linear-Cg-CjocS.js.map → linear-zItbPrND.js.map} +1 -1
  118. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-CVFVrU22.js → mindmap-definition-VGOIOE7T-BJXI7UqO.js} +4 -4
  119. package/webapp/dist/assets/{mindmap-definition-VGOIOE7T-CVFVrU22.js.map → mindmap-definition-VGOIOE7T-BJXI7UqO.js.map} +1 -1
  120. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-Bai5CMos.js → pieDiagram-ADFJNKIX-BpM-aH2p.js} +8 -8
  121. package/webapp/dist/assets/{pieDiagram-ADFJNKIX-Bai5CMos.js.map → pieDiagram-ADFJNKIX-BpM-aH2p.js.map} +1 -1
  122. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BPXDO_2E.js → quadrantDiagram-AYHSOK5B-NXdIpA15.js} +3 -3
  123. package/webapp/dist/assets/{quadrantDiagram-AYHSOK5B-BPXDO_2E.js.map → quadrantDiagram-AYHSOK5B-NXdIpA15.js.map} +1 -1
  124. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-Dgj9X9cE.js → requirementDiagram-UZGBJVZJ-D1AICAA0.js} +4 -4
  125. package/webapp/dist/assets/{requirementDiagram-UZGBJVZJ-Dgj9X9cE.js.map → requirementDiagram-UZGBJVZJ-D1AICAA0.js.map} +1 -1
  126. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Dc0mO4OD.js → sankeyDiagram-TZEHDZUN-WiReDPfo.js} +2 -2
  127. package/webapp/dist/assets/{sankeyDiagram-TZEHDZUN-Dc0mO4OD.js.map → sankeyDiagram-TZEHDZUN-WiReDPfo.js.map} +1 -1
  128. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-DZJTga0d.js → sequenceDiagram-WL72ISMW-Cw76oP8t.js} +4 -4
  129. package/webapp/dist/assets/{sequenceDiagram-WL72ISMW-DZJTga0d.js.map → sequenceDiagram-WL72ISMW-Cw76oP8t.js.map} +1 -1
  130. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-RNxYatKM.js → stateDiagram-FKZM4ZOC-QjCeRczs.js} +9 -9
  131. package/webapp/dist/assets/{stateDiagram-FKZM4ZOC-RNxYatKM.js.map → stateDiagram-FKZM4ZOC-QjCeRczs.js.map} +1 -1
  132. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-ADxYqWzo.js → stateDiagram-v2-4FDKWEC3-IClqxQ4s.js} +5 -5
  133. package/webapp/dist/assets/{stateDiagram-v2-4FDKWEC3-ADxYqWzo.js.map → stateDiagram-v2-4FDKWEC3-IClqxQ4s.js.map} +1 -1
  134. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-Qx_h1e-i.js → timeline-definition-IT6M3QCI-BfyfTY7m.js} +3 -3
  135. package/webapp/dist/assets/{timeline-definition-IT6M3QCI-Qx_h1e-i.js.map → timeline-definition-IT6M3QCI-BfyfTY7m.js.map} +1 -1
  136. package/webapp/dist/assets/{treemap-GDKQZRPO-BHzYvXGn.js → treemap-GDKQZRPO-C5MiL6--.js} +5 -5
  137. package/webapp/dist/assets/{treemap-GDKQZRPO-BHzYvXGn.js.map → treemap-GDKQZRPO-C5MiL6--.js.map} +1 -1
  138. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-DGdjkYQQ.js → xychartDiagram-PRI3JC2R-ybaJrSry.js} +3 -3
  139. package/webapp/dist/assets/{xychartDiagram-PRI3JC2R-DGdjkYQQ.js.map → xychartDiagram-PRI3JC2R-ybaJrSry.js.map} +1 -1
  140. package/webapp/dist/index.html +1 -1
@@ -309,18 +309,157 @@ function chatMessageToCodexItems(msg) {
309
309
  }
310
310
  }
311
311
  }
312
- async function buildCodexFunctionCallOutput(msg, limitChars, requestContext, allowedImageKeys, onToolResultImageIngest) {
312
+ async function userLikeMessageToCodexItemsWithImages(msg, requestContext, providerConfig, allowedImageKeys, onUserImageIngest) {
313
+ const items = msg.contentItems;
314
+ if (!Array.isArray(items) || items.length === 0) {
315
+ return chatMessageToCodexItems(msg);
316
+ }
317
+ const content = [{ type: 'input_text', text: msg.content }];
318
+ const supportsImageInput = (0, tool_result_image_ingest_1.resolveModelImageInputSupport)(requestContext.modelKey === undefined
319
+ ? undefined
320
+ : providerConfig?.models[requestContext.modelKey], true);
321
+ for (const [itemIndex, item] of items.entries()) {
322
+ if (item.type === 'input_text') {
323
+ content.push({ type: 'input_text', text: item.text });
324
+ continue;
325
+ }
326
+ if (item.type === 'input_image') {
327
+ if (!supportsImageInput) {
328
+ if (onUserImageIngest) {
329
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
330
+ requestContext,
331
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
332
+ artifact: item.artifact,
333
+ disposition: 'filtered_model_unsupported',
334
+ providerPathLabel: 'Codex Responses path',
335
+ }));
336
+ }
337
+ content.push({
338
+ type: 'input_text',
339
+ text: `[image not sent: current model does not support image input]`,
340
+ });
341
+ continue;
342
+ }
343
+ if (!(0, artifacts_1.isVisionImageMimeType)(item.mimeType)) {
344
+ if (onUserImageIngest) {
345
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
346
+ requestContext,
347
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
348
+ artifact: item.artifact,
349
+ disposition: 'filtered_mime_unsupported',
350
+ mimeType: item.mimeType,
351
+ providerPathLabel: 'Codex Responses path',
352
+ }));
353
+ }
354
+ content.push({
355
+ type: 'input_text',
356
+ text: `[image not sent: unsupported mimeType=${item.mimeType}]`,
357
+ });
358
+ continue;
359
+ }
360
+ if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildImageBudgetKeyForContentItem)({ msg, itemIndex, artifact: item.artifact }))) {
361
+ if (onUserImageIngest) {
362
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
363
+ requestContext,
364
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
365
+ artifact: item.artifact,
366
+ disposition: 'filtered_size_limit',
367
+ detail: (0, tool_result_image_ingest_1.buildImageBudgetLimitDetail)({
368
+ byteLength: item.byteLength,
369
+ budgetBytes: tool_result_image_ingest_1.CODEX_TOOL_RESULT_IMAGE_BUDGET_BYTES,
370
+ }),
371
+ providerPathLabel: 'Codex Responses path',
372
+ }));
373
+ }
374
+ content.push({
375
+ type: 'input_text',
376
+ text: `[image not sent: request image budget exceeded bytes=${String(item.byteLength)} budget=${String(tool_result_image_ingest_1.CODEX_TOOL_RESULT_IMAGE_BUDGET_BYTES)}]`,
377
+ });
378
+ continue;
379
+ }
380
+ const bytesResult = await (0, tool_result_image_ingest_1.readToolResultImageBytesSafe)(item.artifact);
381
+ if (bytesResult.kind === 'missing') {
382
+ if (onUserImageIngest) {
383
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
384
+ requestContext,
385
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
386
+ artifact: item.artifact,
387
+ disposition: 'filtered_missing',
388
+ providerPathLabel: 'Codex Responses path',
389
+ }));
390
+ }
391
+ content.push({ type: 'input_text', text: `[image missing: ${item.artifact.relPath}]` });
392
+ continue;
393
+ }
394
+ if (bytesResult.kind === 'read_failed') {
395
+ if (onUserImageIngest) {
396
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
397
+ requestContext,
398
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
399
+ artifact: item.artifact,
400
+ disposition: 'filtered_read_failed',
401
+ detail: bytesResult.detail,
402
+ providerPathLabel: 'Codex Responses path',
403
+ }));
404
+ }
405
+ content.push({ type: 'input_text', text: `[image unreadable: ${item.artifact.relPath}]` });
406
+ continue;
407
+ }
408
+ if (onUserImageIngest) {
409
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
410
+ requestContext,
411
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
412
+ artifact: item.artifact,
413
+ disposition: 'fed_native',
414
+ providerPathLabel: 'Codex Responses path',
415
+ }));
416
+ }
417
+ content.push({
418
+ type: 'input_image',
419
+ image_url: (0, artifacts_1.bytesToDataUrl)({ mimeType: item.mimeType, bytes: bytesResult.bytes }),
420
+ });
421
+ continue;
422
+ }
423
+ const _exhaustive = item;
424
+ throw new Error(`Unsupported user content item: ${String(_exhaustive)}`);
425
+ }
426
+ return [
427
+ {
428
+ type: 'message',
429
+ role: 'user',
430
+ content,
431
+ },
432
+ ];
433
+ }
434
+ async function buildCodexFunctionCallOutput(msg, limitChars, requestContext, allowedImageKeys, supportsImageInput, onToolResultImageIngest) {
313
435
  const items = msg.contentItems;
314
436
  if (!Array.isArray(items) || items.length === 0) {
315
437
  return limitCodexToolOutputText(msg.content, msg, limitChars);
316
438
  }
317
439
  const out = [];
318
- for (const item of items) {
440
+ for (const [itemIndex, item] of items.entries()) {
319
441
  if (item.type === 'input_text') {
320
442
  out.push({ type: 'input_text', text: item.text });
321
443
  continue;
322
444
  }
323
445
  if (item.type === 'input_image') {
446
+ if (!supportsImageInput) {
447
+ if (onToolResultImageIngest) {
448
+ await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
449
+ requestContext,
450
+ toolCallId: msg.id,
451
+ toolName: msg.name,
452
+ artifact: item.artifact,
453
+ disposition: 'filtered_model_unsupported',
454
+ providerPathLabel: 'Codex path',
455
+ }));
456
+ }
457
+ out.push({
458
+ type: 'input_text',
459
+ text: `[image not sent: current model does not support image input]`,
460
+ });
461
+ continue;
462
+ }
324
463
  if (!(0, artifacts_1.isVisionImageMimeType)(item.mimeType)) {
325
464
  if (onToolResultImageIngest) {
326
465
  await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
@@ -339,7 +478,7 @@ async function buildCodexFunctionCallOutput(msg, limitChars, requestContext, all
339
478
  });
340
479
  continue;
341
480
  }
342
- if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildToolResultImageBudgetKeyForMsg)(msg, item.artifact))) {
481
+ if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildImageBudgetKeyForContentItem)({ msg, itemIndex, artifact: item.artifact }))) {
343
482
  if (onToolResultImageIngest) {
344
483
  await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
345
484
  requestContext,
@@ -347,7 +486,7 @@ async function buildCodexFunctionCallOutput(msg, limitChars, requestContext, all
347
486
  toolName: msg.name,
348
487
  artifact: item.artifact,
349
488
  disposition: 'filtered_size_limit',
350
- detail: (0, tool_result_image_ingest_1.buildToolResultImageBudgetLimitDetail)({
489
+ detail: (0, tool_result_image_ingest_1.buildImageBudgetLimitDetail)({
351
490
  byteLength: item.byteLength,
352
491
  budgetBytes: tool_result_image_ingest_1.CODEX_TOOL_RESULT_IMAGE_BUDGET_BYTES,
353
492
  }),
@@ -414,7 +553,7 @@ async function buildCodexFunctionCallOutput(msg, limitChars, requestContext, all
414
553
  ? limitCodexToolOutputItems(out, msg, limitChars)
415
554
  : limitCodexToolOutputText(msg.content, msg, limitChars);
416
555
  }
417
- async function buildCodexInput(context, requestContext, providerConfig, onToolResultImageIngest) {
556
+ async function buildCodexInput(context, requestContext, providerConfig, onToolResultImageIngest, onUserImageIngest) {
418
557
  const normalized = (0, tool_call_context_1.normalizeToolCallPairs)(context);
419
558
  const violation = (0, tool_call_context_1.findFirstToolCallAdjacencyViolation)(normalized);
420
559
  if (violation) {
@@ -429,8 +568,19 @@ async function buildCodexInput(context, requestContext, providerConfig, onToolRe
429
568
  }
430
569
  const input = [];
431
570
  const toolResultMaxChars = (0, tool_output_limit_1.resolveProviderToolResultMaxChars)(providerConfig);
432
- const allowedImageKeys = (0, tool_result_image_ingest_1.selectLatestToolResultImagesWithinBudget)(normalized, tool_result_image_ingest_1.CODEX_TOOL_RESULT_IMAGE_BUDGET_BYTES);
571
+ const allowedImageKeys = (0, tool_result_image_ingest_1.selectLatestImagesWithinBudget)(normalized, tool_result_image_ingest_1.CODEX_TOOL_RESULT_IMAGE_BUDGET_BYTES);
572
+ const supportsImageInput = (0, tool_result_image_ingest_1.resolveModelImageInputSupport)(requestContext.modelKey === undefined
573
+ ? undefined
574
+ : providerConfig?.models[requestContext.modelKey], true);
433
575
  for (const msg of normalized) {
576
+ if ((msg.type === 'prompting_msg' ||
577
+ msg.type === 'tellask_result_msg' ||
578
+ msg.type === 'tellask_carryover_msg') &&
579
+ Array.isArray(msg.contentItems) &&
580
+ msg.contentItems.length > 0) {
581
+ input.push(...(await userLikeMessageToCodexItemsWithImages(msg, requestContext, providerConfig, allowedImageKeys, onUserImageIngest)));
582
+ continue;
583
+ }
434
584
  if (msg.type === 'func_call_msg') {
435
585
  input.push({
436
586
  type: 'function_call',
@@ -444,7 +594,7 @@ async function buildCodexInput(context, requestContext, providerConfig, onToolRe
444
594
  input.push({
445
595
  type: 'function_call_output',
446
596
  call_id: msg.id,
447
- output: await buildCodexFunctionCallOutput(msg, toolResultMaxChars, requestContext, allowedImageKeys, onToolResultImageIngest),
597
+ output: await buildCodexFunctionCallOutput(msg, toolResultMaxChars, requestContext, allowedImageKeys, supportsImageInput, onToolResultImageIngest),
448
598
  });
449
599
  continue;
450
600
  }
@@ -455,11 +605,11 @@ async function buildCodexInput(context, requestContext, providerConfig, onToolRe
455
605
  }
456
606
  return input;
457
607
  }
458
- async function buildCodexRequest(providerConfig, agent, instructions, funcTools, requestContext, context, onToolResultImageIngest) {
608
+ async function buildCodexRequest(providerConfig, agent, instructions, funcTools, requestContext, context, onToolResultImageIngest, onUserImageIngest) {
459
609
  if (!agent.model) {
460
610
  throw new Error(`Internal error: Model is undefined for agent '${agent.id}'`);
461
611
  }
462
- const input = await buildCodexInput(context, requestContext, providerConfig, onToolResultImageIngest);
612
+ const input = await buildCodexInput(context, requestContext, providerConfig, onToolResultImageIngest, onUserImageIngest);
463
613
  // Provider isolation rule: request construction must only read Codex-native params here.
464
614
  const codexParams = agent.model_params?.codex;
465
615
  const parallelToolCalls = codexParams?.parallel_tool_calls ?? true;
@@ -512,7 +662,7 @@ class CodexGen {
512
662
  throw new Error(`Internal error: Model is undefined for agent '${agent.id}'`);
513
663
  }
514
664
  const instructions = resolveCodexInstructions(systemPrompt);
515
- const payload = await buildCodexRequest(providerConfig, agent, instructions, funcTools, requestContext, context, receiver.toolResultImageIngest);
665
+ const payload = await buildCodexRequest(providerConfig, agent, instructions, funcTools, requestContext, context, receiver.toolResultImageIngest, receiver.userImageIngest);
516
666
  let sayingStarted = false;
517
667
  let thinkingStarted = false;
518
668
  let sawOutputText = false;
@@ -185,6 +185,125 @@ function chatMessageToChatCompletionMessage(msg) {
185
185
  }
186
186
  }
187
187
  }
188
+ async function userLikeMessageToChatCompletionMessageWithImages(msg, requestContext, providerConfig, allowedImageKeys, onUserImageIngest) {
189
+ const items = msg.contentItems;
190
+ if (!Array.isArray(items) || items.length === 0) {
191
+ return chatMessageToChatCompletionMessage(msg);
192
+ }
193
+ const content = [{ type: 'text', text: msg.content }];
194
+ const supportsImageInput = (0, tool_result_image_ingest_1.resolveModelImageInputSupport)(requestContext.modelKey === undefined
195
+ ? undefined
196
+ : providerConfig?.models[requestContext.modelKey], false);
197
+ for (const [itemIndex, item] of items.entries()) {
198
+ if (item.type === 'input_text') {
199
+ content.push({ type: 'text', text: item.text });
200
+ continue;
201
+ }
202
+ if (item.type === 'input_image') {
203
+ if (!supportsImageInput) {
204
+ if (onUserImageIngest) {
205
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
206
+ requestContext,
207
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
208
+ artifact: item.artifact,
209
+ disposition: 'filtered_model_unsupported',
210
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
211
+ }));
212
+ }
213
+ content.push({
214
+ type: 'text',
215
+ text: `[image not sent: current model does not support image input]`,
216
+ });
217
+ continue;
218
+ }
219
+ if (!(0, artifacts_1.isVisionImageMimeType)(item.mimeType)) {
220
+ if (onUserImageIngest) {
221
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
222
+ requestContext,
223
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
224
+ artifact: item.artifact,
225
+ disposition: 'filtered_mime_unsupported',
226
+ mimeType: item.mimeType,
227
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
228
+ }));
229
+ }
230
+ content.push({
231
+ type: 'text',
232
+ text: `[image not sent: unsupported mimeType=${item.mimeType}]`,
233
+ });
234
+ continue;
235
+ }
236
+ if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildImageBudgetKeyForContentItem)({ msg, itemIndex, artifact: item.artifact }))) {
237
+ if (onUserImageIngest) {
238
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
239
+ requestContext,
240
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
241
+ artifact: item.artifact,
242
+ disposition: 'filtered_size_limit',
243
+ detail: (0, tool_result_image_ingest_1.buildImageBudgetLimitDetail)({
244
+ byteLength: item.byteLength,
245
+ budgetBytes: tool_result_image_ingest_1.OPENAI_COMPATIBLE_TOOL_RESULT_IMAGE_BUDGET_BYTES,
246
+ }),
247
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
248
+ }));
249
+ }
250
+ content.push({
251
+ type: 'text',
252
+ text: `[image not sent: request image budget exceeded bytes=${String(item.byteLength)} budget=${String(tool_result_image_ingest_1.OPENAI_COMPATIBLE_TOOL_RESULT_IMAGE_BUDGET_BYTES)}]`,
253
+ });
254
+ continue;
255
+ }
256
+ const bytesResult = await (0, tool_result_image_ingest_1.readToolResultImageBytesSafe)(item.artifact);
257
+ if (bytesResult.kind === 'missing') {
258
+ if (onUserImageIngest) {
259
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
260
+ requestContext,
261
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
262
+ artifact: item.artifact,
263
+ disposition: 'filtered_missing',
264
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
265
+ }));
266
+ }
267
+ content.push({ type: 'text', text: `[image missing: ${item.artifact.relPath}]` });
268
+ continue;
269
+ }
270
+ if (bytesResult.kind === 'read_failed') {
271
+ if (onUserImageIngest) {
272
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
273
+ requestContext,
274
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
275
+ artifact: item.artifact,
276
+ disposition: 'filtered_read_failed',
277
+ detail: bytesResult.detail,
278
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
279
+ }));
280
+ }
281
+ content.push({ type: 'text', text: `[image unreadable: ${item.artifact.relPath}]` });
282
+ continue;
283
+ }
284
+ if (onUserImageIngest) {
285
+ await onUserImageIngest((0, tool_result_image_ingest_1.buildUserImageIngest)({
286
+ requestContext,
287
+ ...(msg.type === 'prompting_msg' ? { msgId: msg.msgId } : {}),
288
+ artifact: item.artifact,
289
+ disposition: 'fed_provider_transformed',
290
+ providerPathLabel: 'OpenAI-compatible Chat Completions path',
291
+ }));
292
+ }
293
+ content.push({
294
+ type: 'image_url',
295
+ image_url: {
296
+ url: (0, artifacts_1.bytesToDataUrl)({ mimeType: item.mimeType, bytes: bytesResult.bytes }),
297
+ detail: 'auto',
298
+ },
299
+ });
300
+ continue;
301
+ }
302
+ const _exhaustive = item;
303
+ throw new Error(`Unsupported user content item: ${String(_exhaustive)}`);
304
+ }
305
+ return { role: 'user', content };
306
+ }
188
307
  async function funcResultToChatCompletionMessages(msg, limitChars, requestContext, providerConfig, allowedImageKeys, onToolResultImageIngest) {
189
308
  const items = msg.contentItems;
190
309
  if (!Array.isArray(items) || items.length === 0) {
@@ -209,14 +328,13 @@ async function funcResultToChatCompletionMessages(msg, limitChars, requestContex
209
328
  type: 'text',
210
329
  text: `Tool output images (${msg.name}, call_id=${msg.id}):`,
211
330
  });
212
- const supportsImageInput = (() => {
213
- if (!providerConfig)
214
- return false;
215
- const modelKey = typeof requestContext.modelKey === 'string' ? requestContext.modelKey.trim() : '';
216
- const modelInfo = modelKey.length > 0 ? providerConfig.models[modelKey] : undefined;
217
- return isRecord(modelInfo) && modelInfo['supports_image_input'] === true;
218
- })();
219
- for (const item of items) {
331
+ const modelKey = typeof requestContext.modelKey === 'string' ? requestContext.modelKey.trim() : '';
332
+ const modelInfo = modelKey.length > 0 && providerConfig ? providerConfig.models[modelKey] : undefined;
333
+ const supportsImageInput = (0, tool_result_image_ingest_1.resolveModelImageInputSupport)(modelInfo, false);
334
+ const imageUnsupportedDisposition = modelInfo?.['supports_image_input'] === false
335
+ ? 'filtered_model_unsupported'
336
+ : 'filtered_provider_unsupported';
337
+ for (const [itemIndex, item] of items.entries()) {
220
338
  if (item.type === 'input_text')
221
339
  continue;
222
340
  if (item.type === 'input_image') {
@@ -228,7 +346,7 @@ async function funcResultToChatCompletionMessages(msg, limitChars, requestContex
228
346
  toolCallId: msg.id,
229
347
  toolName: msg.name,
230
348
  artifact: item.artifact,
231
- disposition: 'filtered_provider_unsupported',
349
+ disposition: imageUnsupportedDisposition,
232
350
  providerPathLabel: 'OpenAI-compatible path',
233
351
  }));
234
352
  }
@@ -256,7 +374,7 @@ async function funcResultToChatCompletionMessages(msg, limitChars, requestContex
256
374
  });
257
375
  continue;
258
376
  }
259
- if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildToolResultImageBudgetKeyForMsg)(msg, item.artifact))) {
377
+ if (!allowedImageKeys.has((0, tool_result_image_ingest_1.buildImageBudgetKeyForContentItem)({ msg, itemIndex, artifact: item.artifact }))) {
260
378
  if (onToolResultImageIngest) {
261
379
  await onToolResultImageIngest((0, tool_result_image_ingest_1.buildToolResultImageIngest)({
262
380
  requestContext,
@@ -264,7 +382,7 @@ async function funcResultToChatCompletionMessages(msg, limitChars, requestContex
264
382
  toolName: msg.name,
265
383
  artifact: item.artifact,
266
384
  disposition: 'filtered_size_limit',
267
- detail: (0, tool_result_image_ingest_1.buildToolResultImageBudgetLimitDetail)({
385
+ detail: (0, tool_result_image_ingest_1.buildImageBudgetLimitDetail)({
268
386
  byteLength: item.byteLength,
269
387
  budgetBytes: tool_result_image_ingest_1.OPENAI_COMPATIBLE_TOOL_RESULT_IMAGE_BUDGET_BYTES,
270
388
  }),
@@ -354,74 +472,6 @@ async function funcResultToChatCompletionMessages(msg, limitChars, requestContex
354
472
  }
355
473
  return out;
356
474
  }
357
- async function orphanedFuncResultToChatCompletionMessages(msg, limitChars) {
358
- const items = msg.contentItems;
359
- if (!Array.isArray(items) || items.length === 0) {
360
- return [
361
- {
362
- role: 'user',
363
- content: limitOpenAiCompatibleToolOutputText(`[orphaned_tool_output:${msg.name}:${msg.id}] ${msg.content}`, msg, limitChars),
364
- },
365
- ];
366
- }
367
- const parts = [
368
- {
369
- type: 'text',
370
- text: limitOpenAiCompatibleToolOutputText(`[orphaned_tool_output:${msg.name}:${msg.id}] ${msg.content}`, msg, limitChars),
371
- },
372
- ];
373
- let sawImageUrl = false;
374
- let sawAnyImage = false;
375
- for (const item of items) {
376
- if (item.type === 'input_text')
377
- continue;
378
- if (item.type === 'input_image') {
379
- sawAnyImage = true;
380
- if (!(0, artifacts_1.isVisionImageMimeType)(item.mimeType)) {
381
- parts.push({
382
- type: 'text',
383
- text: `[image omitted: unsupported mimeType=${item.mimeType}]`,
384
- });
385
- continue;
386
- }
387
- const bytes = await (0, artifacts_1.readDialogArtifactBytes)({
388
- rootId: item.artifact.rootId,
389
- selfId: item.artifact.selfId,
390
- status: item.artifact.status,
391
- relPath: item.artifact.relPath,
392
- });
393
- if (!bytes) {
394
- parts.push({
395
- type: 'text',
396
- text: `[image missing: ${item.artifact.relPath}]`,
397
- });
398
- continue;
399
- }
400
- parts.push({
401
- type: 'image_url',
402
- image_url: { url: (0, artifacts_1.bytesToDataUrl)({ mimeType: item.mimeType, bytes }), detail: 'auto' },
403
- });
404
- sawImageUrl = true;
405
- continue;
406
- }
407
- const _exhaustive = item;
408
- parts.push({ type: 'text', text: `[unknown content item: ${String(_exhaustive)}]` });
409
- }
410
- if (sawImageUrl) {
411
- return [{ role: 'user', content: parts }];
412
- }
413
- if (sawAnyImage) {
414
- const text = parts
415
- .filter((p) => p.type === 'text')
416
- .map((p) => p.text)
417
- .join('\n')
418
- .trim();
419
- return [{ role: 'user', content: text }];
420
- }
421
- return [
422
- { role: 'user', content: limitOpenAiCompatibleToolOutputText(msg.content, msg, limitChars) },
423
- ];
424
- }
425
475
  function mergeAdjacentMessages(input) {
426
476
  // Some proxies behave poorly with long runs of same-role messages (Dominds persists thinking/saying
427
477
  // as separate msgs). Merge adjacent user/assistant/system messages where safe.
@@ -472,7 +522,7 @@ async function buildChatCompletionMessages(systemPrompt, context, requestContext
472
522
  const input = [];
473
523
  const reasoningContentMode = options?.reasoningContentMode === true;
474
524
  const toolResultMaxChars = (0, tool_output_limit_1.resolveProviderToolResultMaxChars)(options?.providerConfig);
475
- const allowedImageKeys = (0, tool_result_image_ingest_1.selectLatestToolResultImagesWithinBudget)(normalized, tool_result_image_ingest_1.OPENAI_COMPATIBLE_TOOL_RESULT_IMAGE_BUDGET_BYTES);
525
+ const allowedImageKeys = (0, tool_result_image_ingest_1.selectLatestImagesWithinBudget)(normalized, tool_result_image_ingest_1.OPENAI_COMPATIBLE_TOOL_RESULT_IMAGE_BUDGET_BYTES);
476
526
  let pendingReasoningContent;
477
527
  const takePendingReasoningContent = () => {
478
528
  const current = pendingReasoningContent;
@@ -514,7 +564,13 @@ async function buildChatCompletionMessages(systemPrompt, context, requestContext
514
564
  input.push(...(await funcResultToChatCompletionMessages(msg, toolResultMaxChars, requestContext, options?.providerConfig, allowedImageKeys, options?.onToolResultImageIngest)));
515
565
  continue;
516
566
  }
517
- const mapped = chatMessageToChatCompletionMessage(msg);
567
+ const mapped = (msg.type === 'prompting_msg' ||
568
+ msg.type === 'tellask_result_msg' ||
569
+ msg.type === 'tellask_carryover_msg') &&
570
+ Array.isArray(msg.contentItems) &&
571
+ msg.contentItems.length > 0
572
+ ? await userLikeMessageToChatCompletionMessageWithImages(msg, requestContext, options?.providerConfig, allowedImageKeys, options?.onUserImageIngest)
573
+ : chatMessageToChatCompletionMessage(msg);
518
574
  input.push(attachReasoningContent(mapped, takePendingReasoningContent()));
519
575
  }
520
576
  flushPendingReasoningAsAssistantMessage();
@@ -630,6 +686,7 @@ class OpenAiCompatibleGen {
630
686
  reasoningContentMode,
631
687
  providerConfig,
632
688
  onToolResultImageIngest: receiver.toolResultImageIngest,
689
+ onUserImageIngest: receiver.userImageIngest,
633
690
  });
634
691
  const openAiParams = agent.model_params?.openai || {};
635
692
  const maxTokens = agent.model_params?.max_tokens;
@@ -834,6 +891,9 @@ class OpenAiCompatibleGen {
834
891
  onToolResultImageIngest: async (ingest) => {
835
892
  outputs.push({ kind: 'tool_result_image_ingest', ingest });
836
893
  },
894
+ onUserImageIngest: async (ingest) => {
895
+ outputs.push({ kind: 'user_image_ingest', ingest });
896
+ },
837
897
  });
838
898
  const openAiParams = agent.model_params?.openai || {};
839
899
  const maxTokens = agent.model_params?.max_tokens;