@sinm/kai 1.10.2 → 1.10.3

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 (133) hide show
  1. package/dist-cli/kai-cli.js +1608 -1010
  2. package/dist-electron/renderer/assets/{_baseUniq-DXQms1uJ.js → _baseUniq-Dt9qXP29.js} +1 -1
  3. package/dist-electron/renderer/assets/_baseUniq-Dt9qXP29.js.gz +0 -0
  4. package/dist-electron/renderer/assets/{arc-BzUtcsT6.js → arc-RsiBQoWi.js} +1 -1
  5. package/dist-electron/renderer/assets/arc-RsiBQoWi.js.gz +0 -0
  6. package/dist-electron/renderer/assets/{architectureDiagram-Q4EWVU46-DWhLXXBB.js → architectureDiagram-Q4EWVU46-JhFDZdkM.js} +5 -5
  7. package/dist-electron/renderer/assets/architectureDiagram-Q4EWVU46-JhFDZdkM.js.gz +0 -0
  8. package/dist-electron/renderer/assets/{blockDiagram-DXYQGD6D-4chZr0B3.js → blockDiagram-DXYQGD6D-B86rt-OM.js} +6 -6
  9. package/dist-electron/renderer/assets/blockDiagram-DXYQGD6D-B86rt-OM.js.gz +0 -0
  10. package/dist-electron/renderer/assets/{c4Diagram-AHTNJAMY-B57DWDB5.js → c4Diagram-AHTNJAMY-BQCHj6of.js} +2 -2
  11. package/dist-electron/renderer/assets/c4Diagram-AHTNJAMY-BQCHj6of.js.gz +0 -0
  12. package/dist-electron/renderer/assets/{channel-CK8jbeS3.js → channel-CC4z4GJI.js} +1 -1
  13. package/dist-electron/renderer/assets/{chunk-4BX2VUAB-DJhRXS5K.js → chunk-4BX2VUAB-BVP9T2Dh.js} +1 -1
  14. package/dist-electron/renderer/assets/{chunk-4TB4RGXK-BaFYK52i.js → chunk-4TB4RGXK-CiPR4mxA.js} +5 -5
  15. package/dist-electron/renderer/assets/chunk-4TB4RGXK-CiPR4mxA.js.gz +0 -0
  16. package/dist-electron/renderer/assets/{chunk-55IACEB6-DjaH1FL_.js → chunk-55IACEB6-DFn516zY.js} +1 -1
  17. package/dist-electron/renderer/assets/{chunk-EDXVE4YY-K-LdDCd1.js → chunk-EDXVE4YY-CGRKmQT3.js} +1 -1
  18. package/dist-electron/renderer/assets/chunk-EDXVE4YY-CGRKmQT3.js.gz +0 -0
  19. package/dist-electron/renderer/assets/{chunk-FMBD7UC4-DzGM7STk.js → chunk-FMBD7UC4-BmRxbPzV.js} +1 -1
  20. package/dist-electron/renderer/assets/{chunk-OYMX7WX6-CLJ8M1Y6.js → chunk-OYMX7WX6-Dk-Q7zf7.js} +3 -3
  21. package/dist-electron/renderer/assets/chunk-OYMX7WX6-Dk-Q7zf7.js.gz +0 -0
  22. package/dist-electron/renderer/assets/{chunk-QZHKN3VN-CbcXgYrp.js → chunk-QZHKN3VN-CZqi7zia.js} +1 -1
  23. package/dist-electron/renderer/assets/{chunk-YZCP3GAM-DG6A2gPT.js → chunk-YZCP3GAM-BTonv1NP.js} +1 -1
  24. package/dist-electron/renderer/assets/chunk-YZCP3GAM-BTonv1NP.js.gz +0 -0
  25. package/dist-electron/renderer/assets/{classDiagram-6PBFFD2Q-C516x-2x.js → classDiagram-6PBFFD2Q-CLrLTGbu.js} +6 -6
  26. package/dist-electron/renderer/assets/{classDiagram-v2-HSJHXN6E-C516x-2x.js → classDiagram-v2-HSJHXN6E-CLrLTGbu.js} +6 -6
  27. package/dist-electron/renderer/assets/{clone-BZsfBfGE.js → clone-_36aVKDg.js} +1 -1
  28. package/dist-electron/renderer/assets/{cose-bilkent-S5V4N54A-Wa-FYjHx.js → cose-bilkent-S5V4N54A-C3iQr7P0.js} +1 -1
  29. package/dist-electron/renderer/assets/cose-bilkent-S5V4N54A-C3iQr7P0.js.gz +0 -0
  30. package/dist-electron/renderer/assets/{dagre-KV5264BT-Df-HS0DT.js → dagre-KV5264BT-C5t353zi.js} +6 -6
  31. package/dist-electron/renderer/assets/dagre-KV5264BT-C5t353zi.js.gz +0 -0
  32. package/dist-electron/renderer/assets/{diagram-5BDNPKRD-CaZsWnM2.js → diagram-5BDNPKRD-BeuTiBNY.js} +6 -6
  33. package/dist-electron/renderer/assets/diagram-5BDNPKRD-BeuTiBNY.js.gz +0 -0
  34. package/dist-electron/renderer/assets/{diagram-G4DWMVQ6-0B-U8e4R.js → diagram-G4DWMVQ6-BNAzh5ef.js} +6 -6
  35. package/dist-electron/renderer/assets/diagram-G4DWMVQ6-BNAzh5ef.js.gz +0 -0
  36. package/dist-electron/renderer/assets/{diagram-MMDJMWI5-Byvl-KNj.js → diagram-MMDJMWI5-ByaaDyoH.js} +5 -5
  37. package/dist-electron/renderer/assets/diagram-MMDJMWI5-ByaaDyoH.js.gz +0 -0
  38. package/dist-electron/renderer/assets/{diagram-TYMM5635-Dgy-yPsr.js → diagram-TYMM5635-DAsU-q28.js} +5 -5
  39. package/dist-electron/renderer/assets/diagram-TYMM5635-DAsU-q28.js.gz +0 -0
  40. package/dist-electron/renderer/assets/{erDiagram-SMLLAGMA-CkzvnQaU.js → erDiagram-SMLLAGMA-D0srSDPs.js} +4 -4
  41. package/dist-electron/renderer/assets/erDiagram-SMLLAGMA-D0srSDPs.js.gz +0 -0
  42. package/dist-electron/renderer/assets/{flowDiagram-DWJPFMVM-B5k0WctR.js → flowDiagram-DWJPFMVM-Br3VuPsd.js} +6 -6
  43. package/dist-electron/renderer/assets/flowDiagram-DWJPFMVM-Br3VuPsd.js.gz +0 -0
  44. package/dist-electron/renderer/assets/{ganttDiagram-T4ZO3ILL-C2pFdr_b.js → ganttDiagram-T4ZO3ILL-D09E8Ld2.js} +2 -2
  45. package/dist-electron/renderer/assets/ganttDiagram-T4ZO3ILL-D09E8Ld2.js.gz +0 -0
  46. package/dist-electron/renderer/assets/{gitGraphDiagram-UUTBAWPF-CJdXKPsy.js → gitGraphDiagram-UUTBAWPF-CKplsNll.js} +6 -6
  47. package/dist-electron/renderer/assets/gitGraphDiagram-UUTBAWPF-CKplsNll.js.gz +0 -0
  48. package/dist-electron/renderer/assets/{graph-_80OeAYU.js → graph-BTPzdQjH.js} +2 -2
  49. package/dist-electron/renderer/assets/graph-BTPzdQjH.js.gz +0 -0
  50. package/dist-electron/renderer/assets/{index-DCzIql_d.css → index-B2vb2ykm.css} +244 -207
  51. package/dist-electron/renderer/assets/index-B2vb2ykm.css.gz +0 -0
  52. package/dist-electron/renderer/assets/{index-Cs0m4pX4.js → index-D4EitlLm.js} +920 -388
  53. package/dist-electron/renderer/assets/index-D4EitlLm.js.gz +0 -0
  54. package/dist-electron/renderer/assets/{infoDiagram-42DDH7IO-CUBNnXNy.js → infoDiagram-42DDH7IO-VNZjK26Z.js} +4 -4
  55. package/dist-electron/renderer/assets/{ishikawaDiagram-UXIWVN3A-Blfv83uV.js → ishikawaDiagram-UXIWVN3A-DNQZ_EJr.js} +1 -1
  56. package/dist-electron/renderer/assets/ishikawaDiagram-UXIWVN3A-DNQZ_EJr.js.gz +0 -0
  57. package/dist-electron/renderer/assets/{journeyDiagram-VCZTEJTY-CTytCzzg.js → journeyDiagram-VCZTEJTY-4mieWisO.js} +4 -4
  58. package/dist-electron/renderer/assets/journeyDiagram-VCZTEJTY-4mieWisO.js.gz +0 -0
  59. package/dist-electron/renderer/assets/{kanban-definition-6JOO6SKY-CJ9BZQW-.js → kanban-definition-6JOO6SKY-Cm91R9mn.js} +2 -2
  60. package/dist-electron/renderer/assets/kanban-definition-6JOO6SKY-Cm91R9mn.js.gz +0 -0
  61. package/dist-electron/renderer/assets/{layout-sSswHT98.js → layout-sDMER76e.js} +4 -4
  62. package/dist-electron/renderer/assets/layout-sDMER76e.js.gz +0 -0
  63. package/dist-electron/renderer/assets/{linear-BglvYbbf.js → linear-BJZxaeHe.js} +1 -1
  64. package/dist-electron/renderer/assets/linear-BJZxaeHe.js.gz +0 -0
  65. package/dist-electron/renderer/assets/{min-Bzyu3TW9.js → min-CihovUOT.js} +2 -2
  66. package/dist-electron/renderer/assets/min-CihovUOT.js.gz +0 -0
  67. package/dist-electron/renderer/assets/{mindmap-definition-QFDTVHPH-Dvudei3d.js → mindmap-definition-QFDTVHPH-BWSrGBRN.js} +3 -3
  68. package/dist-electron/renderer/assets/mindmap-definition-QFDTVHPH-BWSrGBRN.js.gz +0 -0
  69. package/dist-electron/renderer/assets/{pieDiagram-DEJITSTG-LipgyJMA.js → pieDiagram-DEJITSTG-5w5tVLFj.js} +6 -6
  70. package/dist-electron/renderer/assets/pieDiagram-DEJITSTG-5w5tVLFj.js.gz +0 -0
  71. package/dist-electron/renderer/assets/{quadrantDiagram-34T5L4WZ-BsvYEtIZ.js → quadrantDiagram-34T5L4WZ-B5GobzTO.js} +2 -2
  72. package/dist-electron/renderer/assets/quadrantDiagram-34T5L4WZ-B5GobzTO.js.gz +0 -0
  73. package/dist-electron/renderer/assets/{requirementDiagram-MS252O5E-BnabpcqK.js → requirementDiagram-MS252O5E-EEt0fiRz.js} +3 -3
  74. package/dist-electron/renderer/assets/requirementDiagram-MS252O5E-EEt0fiRz.js.gz +0 -0
  75. package/dist-electron/renderer/assets/{sankeyDiagram-XADWPNL6-BuCgq17Q.js → sankeyDiagram-XADWPNL6-Osa6Eix6.js} +1 -1
  76. package/dist-electron/renderer/assets/sankeyDiagram-XADWPNL6-Osa6Eix6.js.gz +0 -0
  77. package/dist-electron/renderer/assets/{sequenceDiagram-FGHM5R23-CtGBoKet.js → sequenceDiagram-FGHM5R23-0i-4BqN-.js} +3 -3
  78. package/dist-electron/renderer/assets/sequenceDiagram-FGHM5R23-0i-4BqN-.js.gz +0 -0
  79. package/dist-electron/renderer/assets/{stateDiagram-FHFEXIEX-DYwbJ7V6.js → stateDiagram-FHFEXIEX-DX08_hh3.js} +8 -8
  80. package/dist-electron/renderer/assets/stateDiagram-FHFEXIEX-DX08_hh3.js.gz +0 -0
  81. package/dist-electron/renderer/assets/{stateDiagram-v2-QKLJ7IA2-CtQIhDqi.js → stateDiagram-v2-QKLJ7IA2-CP3UU-ar.js} +4 -4
  82. package/dist-electron/renderer/assets/{timeline-definition-GMOUNBTQ-Dg1mahK3.js → timeline-definition-GMOUNBTQ-Bn7U0euE.js} +2 -2
  83. package/dist-electron/renderer/assets/timeline-definition-GMOUNBTQ-Bn7U0euE.js.gz +0 -0
  84. package/dist-electron/renderer/assets/{vennDiagram-DHZGUBPP-CdFh8oWQ.js → vennDiagram-DHZGUBPP-ChvNdQSo.js} +1 -1
  85. package/dist-electron/renderer/assets/vennDiagram-DHZGUBPP-ChvNdQSo.js.gz +0 -0
  86. package/dist-electron/renderer/assets/{wardley-RL74JXVD-CQzndBZX.js → wardley-RL74JXVD-BF3DE4pq.js} +3 -3
  87. package/dist-electron/renderer/assets/wardley-RL74JXVD-BF3DE4pq.js.gz +0 -0
  88. package/dist-electron/renderer/assets/{wardleyDiagram-NUSXRM2D-BUhyPKXM.js → wardleyDiagram-NUSXRM2D-BoIeDdfp.js} +5 -5
  89. package/dist-electron/renderer/assets/wardleyDiagram-NUSXRM2D-BoIeDdfp.js.gz +0 -0
  90. package/dist-electron/renderer/assets/{xychartDiagram-5P7HB3ND-CwTHSfES.js → xychartDiagram-5P7HB3ND-D5C0kytw.js} +2 -2
  91. package/dist-electron/renderer/assets/xychartDiagram-5P7HB3ND-D5C0kytw.js.gz +0 -0
  92. package/dist-electron/renderer/index.html +2 -2
  93. package/package.json +3 -3
  94. package/dist-electron/renderer/assets/_baseUniq-DXQms1uJ.js.gz +0 -0
  95. package/dist-electron/renderer/assets/arc-BzUtcsT6.js.gz +0 -0
  96. package/dist-electron/renderer/assets/architectureDiagram-Q4EWVU46-DWhLXXBB.js.gz +0 -0
  97. package/dist-electron/renderer/assets/blockDiagram-DXYQGD6D-4chZr0B3.js.gz +0 -0
  98. package/dist-electron/renderer/assets/c4Diagram-AHTNJAMY-B57DWDB5.js.gz +0 -0
  99. package/dist-electron/renderer/assets/chunk-4TB4RGXK-BaFYK52i.js.gz +0 -0
  100. package/dist-electron/renderer/assets/chunk-EDXVE4YY-K-LdDCd1.js.gz +0 -0
  101. package/dist-electron/renderer/assets/chunk-OYMX7WX6-CLJ8M1Y6.js.gz +0 -0
  102. package/dist-electron/renderer/assets/chunk-YZCP3GAM-DG6A2gPT.js.gz +0 -0
  103. package/dist-electron/renderer/assets/cose-bilkent-S5V4N54A-Wa-FYjHx.js.gz +0 -0
  104. package/dist-electron/renderer/assets/dagre-KV5264BT-Df-HS0DT.js.gz +0 -0
  105. package/dist-electron/renderer/assets/diagram-5BDNPKRD-CaZsWnM2.js.gz +0 -0
  106. package/dist-electron/renderer/assets/diagram-G4DWMVQ6-0B-U8e4R.js.gz +0 -0
  107. package/dist-electron/renderer/assets/diagram-MMDJMWI5-Byvl-KNj.js.gz +0 -0
  108. package/dist-electron/renderer/assets/diagram-TYMM5635-Dgy-yPsr.js.gz +0 -0
  109. package/dist-electron/renderer/assets/erDiagram-SMLLAGMA-CkzvnQaU.js.gz +0 -0
  110. package/dist-electron/renderer/assets/flowDiagram-DWJPFMVM-B5k0WctR.js.gz +0 -0
  111. package/dist-electron/renderer/assets/ganttDiagram-T4ZO3ILL-C2pFdr_b.js.gz +0 -0
  112. package/dist-electron/renderer/assets/gitGraphDiagram-UUTBAWPF-CJdXKPsy.js.gz +0 -0
  113. package/dist-electron/renderer/assets/graph-_80OeAYU.js.gz +0 -0
  114. package/dist-electron/renderer/assets/index-Cs0m4pX4.js.gz +0 -0
  115. package/dist-electron/renderer/assets/index-DCzIql_d.css.gz +0 -0
  116. package/dist-electron/renderer/assets/ishikawaDiagram-UXIWVN3A-Blfv83uV.js.gz +0 -0
  117. package/dist-electron/renderer/assets/journeyDiagram-VCZTEJTY-CTytCzzg.js.gz +0 -0
  118. package/dist-electron/renderer/assets/kanban-definition-6JOO6SKY-CJ9BZQW-.js.gz +0 -0
  119. package/dist-electron/renderer/assets/layout-sSswHT98.js.gz +0 -0
  120. package/dist-electron/renderer/assets/linear-BglvYbbf.js.gz +0 -0
  121. package/dist-electron/renderer/assets/min-Bzyu3TW9.js.gz +0 -0
  122. package/dist-electron/renderer/assets/mindmap-definition-QFDTVHPH-Dvudei3d.js.gz +0 -0
  123. package/dist-electron/renderer/assets/pieDiagram-DEJITSTG-LipgyJMA.js.gz +0 -0
  124. package/dist-electron/renderer/assets/quadrantDiagram-34T5L4WZ-BsvYEtIZ.js.gz +0 -0
  125. package/dist-electron/renderer/assets/requirementDiagram-MS252O5E-BnabpcqK.js.gz +0 -0
  126. package/dist-electron/renderer/assets/sankeyDiagram-XADWPNL6-BuCgq17Q.js.gz +0 -0
  127. package/dist-electron/renderer/assets/sequenceDiagram-FGHM5R23-CtGBoKet.js.gz +0 -0
  128. package/dist-electron/renderer/assets/stateDiagram-FHFEXIEX-DYwbJ7V6.js.gz +0 -0
  129. package/dist-electron/renderer/assets/timeline-definition-GMOUNBTQ-Dg1mahK3.js.gz +0 -0
  130. package/dist-electron/renderer/assets/vennDiagram-DHZGUBPP-CdFh8oWQ.js.gz +0 -0
  131. package/dist-electron/renderer/assets/wardley-RL74JXVD-CQzndBZX.js.gz +0 -0
  132. package/dist-electron/renderer/assets/wardleyDiagram-NUSXRM2D-BUhyPKXM.js.gz +0 -0
  133. package/dist-electron/renderer/assets/xychartDiagram-5P7HB3ND-CwTHSfES.js.gz +0 -0
@@ -84387,6 +84387,10 @@ function initMessageModel(sequelize) {
84387
84387
  setJsonField(this, "error", value);
84388
84388
  }
84389
84389
  },
84390
+ status: {
84391
+ type: DataTypes.TEXT,
84392
+ allowNull: true
84393
+ },
84390
84394
  isContextMarker: {
84391
84395
  type: DataTypes.BOOLEAN,
84392
84396
  defaultValue: false,
@@ -85045,6 +85049,7 @@ async function rebuildMessagesTable(sequelize, sourceSessionColumn) {
85045
85049
  timestamp INTEGER NOT NULL,
85046
85050
  updated_at INTEGER,
85047
85051
  error TEXT,
85052
+ status TEXT,
85048
85053
  is_context_marker BOOLEAN DEFAULT 0,
85049
85054
  compression_metadata TEXT,
85050
85055
  usage TEXT,
@@ -85094,12 +85099,6 @@ async function ensureRequiredMessageColumns(sequelize) {
85094
85099
  (column) => !columns.has(column.name)
85095
85100
  );
85096
85101
  if (missingRequiredColumns.length === 0) return;
85097
- const hasSessionIdColumn = columns.has("session_id");
85098
- const hasLegacyConversationIdColumn = columns.has("conversation_id");
85099
- if (hasSessionIdColumn && !hasLegacyConversationIdColumn) {
85100
- logger4.debug("Deferring missing message columns until session_id migration");
85101
- return;
85102
- }
85103
85102
  for (const column of missingRequiredColumns) {
85104
85103
  await sequelize.query(`ALTER TABLE messages ADD COLUMN ${column.name} ${column.definition}`);
85105
85104
  }
@@ -85238,6 +85237,7 @@ var init_sequelize = __esm({
85238
85237
  REQUIRED_MESSAGE_COLUMNS = [
85239
85238
  { name: "updated_at", definition: "INTEGER" },
85240
85239
  { name: "error", definition: "TEXT" },
85240
+ { name: "status", definition: "TEXT" },
85241
85241
  { name: "is_context_marker", definition: "BOOLEAN DEFAULT 0" },
85242
85242
  { name: "compression_metadata", definition: "TEXT" },
85243
85243
  { name: "usage", definition: "TEXT" },
@@ -85256,6 +85256,7 @@ var init_sequelize = __esm({
85256
85256
  "timestamp",
85257
85257
  "updated_at",
85258
85258
  "error",
85259
+ "status",
85259
85260
  "is_context_marker",
85260
85261
  "compression_metadata",
85261
85262
  "usage",
@@ -85267,6 +85268,7 @@ var init_sequelize = __esm({
85267
85268
  MESSAGE_COPY_DEFAULTS = {
85268
85269
  updated_at: "timestamp",
85269
85270
  error: "NULL",
85271
+ status: "NULL",
85270
85272
  is_context_marker: "0",
85271
85273
  compression_metadata: "NULL",
85272
85274
  usage: "NULL",
@@ -85556,6 +85558,7 @@ function normalizeFallbackEntries(entries) {
85556
85558
  }));
85557
85559
  }
85558
85560
  function normalizeReasoningEffort(enableThinking, reasoningEffort) {
85561
+ if (reasoningEffort === "off" && enableThinking === true) return "medium";
85559
85562
  if (reasoningEffort) return reasoningEffort;
85560
85563
  return enableThinking === true ? "medium" : DEFAULT_REASONING_EFFORT;
85561
85564
  }
@@ -110877,789 +110880,6 @@ var init_execution_deps = __esm({
110877
110880
  }
110878
110881
  });
110879
110882
 
110880
- // src/core/agent/execution/model/ModelCapability.ts
110881
- var logger15, MODEL_RULES, DEFAULT_CONTEXT_WINDOW, MAX_LEARNED_MODELS, ModelCapability, modelCapability;
110882
- var init_ModelCapability = __esm({
110883
- "src/core/agent/execution/model/ModelCapability.ts"() {
110884
- "use strict";
110885
- init_logger();
110886
- logger15 = createLogger("ModelCapability");
110887
- MODEL_RULES = [
110888
- // OpenAI
110889
- { pattern: "gpt-4o-mini", contextWindow: 128e3, vision: true, verified: false },
110890
- { pattern: "gpt-4o", contextWindow: 128e3, vision: true, verified: false },
110891
- { pattern: "gpt-4.1", contextWindow: 1e6, vision: true, verified: false },
110892
- { pattern: "gpt-4-turbo", contextWindow: 128e3, vision: true, verified: false },
110893
- { pattern: "gpt-4-vision", contextWindow: 128e3, vision: true, verified: false },
110894
- { pattern: "gpt-4.5", contextWindow: 128e3, verified: false },
110895
- { pattern: "gpt-5.5", contextWindow: 512e3, vision: true, verified: false },
110896
- { pattern: "gpt-5.4", contextWindow: 4e5, vision: true, verified: false },
110897
- { pattern: "gpt-5", contextWindow: 128e3, vision: true, verified: false },
110898
- { pattern: "gpt-6", contextWindow: 128e3, vision: true, verified: false },
110899
- { pattern: "o4-mini", contextWindow: 2e5, vision: true, verified: false },
110900
- { pattern: "o3-mini", contextWindow: 2e5, verified: false },
110901
- { pattern: "o3", contextWindow: 2e5, vision: true, verified: false },
110902
- { pattern: "o1-mini", contextWindow: 128e3, verified: false },
110903
- { pattern: "o1", contextWindow: 2e5, vision: true, verified: false },
110904
- { pattern: "gpt-3.5-turbo", contextWindow: 16385, verified: false },
110905
- { pattern: "gpt-3.5", contextWindow: 16385, verified: false },
110906
- // Anthropic Claude
110907
- { pattern: "claude-opus-4", contextWindow: 2e5, vision: true, verified: false },
110908
- { pattern: "claude-sonnet-4", contextWindow: 2e5, vision: true, verified: false },
110909
- { pattern: "claude-3.7-sonnet", contextWindow: 2e5, vision: true, verified: false },
110910
- { pattern: "claude-3.5-sonnet", contextWindow: 2e5, vision: true, verified: false },
110911
- { pattern: "claude-3.5-haiku", contextWindow: 2e5, vision: true, verified: false },
110912
- { pattern: "claude-3-opus", contextWindow: 2e5, vision: true, verified: false },
110913
- { pattern: "claude-3-sonnet", contextWindow: 2e5, vision: true, verified: false },
110914
- { pattern: "claude-3-haiku", contextWindow: 2e5, vision: true, verified: false },
110915
- { pattern: "claude-opus", contextWindow: 2e5, verified: false },
110916
- { pattern: "claude-sonnet", contextWindow: 2e5, verified: false },
110917
- { pattern: "claude-haiku", contextWindow: 2e5, verified: false },
110918
- // Google Gemini
110919
- { pattern: "gemini-2.5-pro", contextWindow: 1e6, vision: true, verified: false },
110920
- { pattern: "gemini-2.5-flash", contextWindow: 1e6, vision: true, verified: false },
110921
- { pattern: "gemini-2.0-flash", contextWindow: 1e6, vision: true, verified: false },
110922
- { pattern: "gemini-1.5-pro", contextWindow: 1e6, vision: true, verified: false },
110923
- { pattern: "gemini-1.5-flash", contextWindow: 1e6, vision: true, verified: false },
110924
- { pattern: "gemini-pro-vision", contextWindow: 32e3, vision: true, verified: false },
110925
- { pattern: "gemini-pro", contextWindow: 32e3, verified: false },
110926
- { pattern: "gemini-2.0", contextWindow: 1e6, vision: true, verified: false },
110927
- // DeepSeek(官方已核验)
110928
- {
110929
- pattern: "deepseek-reasoner",
110930
- contextWindow: 128e3,
110931
- verified: true,
110932
- source: "https://api-docs.deepseek.com/quick_start/pricing"
110933
- },
110934
- {
110935
- pattern: "deepseek-chat",
110936
- contextWindow: 128e3,
110937
- verified: true,
110938
- source: "https://api-docs.deepseek.com/quick_start/pricing"
110939
- },
110940
- {
110941
- pattern: "deepseek-v3",
110942
- contextWindow: 128e3,
110943
- verified: true,
110944
- source: "https://api-docs.deepseek.com/quick_start/pricing"
110945
- },
110946
- {
110947
- pattern: "deepseek-r1",
110948
- contextWindow: 128e3,
110949
- verified: true,
110950
- source: "https://api-docs.deepseek.com/quick_start/pricing"
110951
- },
110952
- { pattern: "deepseek-vl", vision: true, verified: false },
110953
- { pattern: "deepseek-coder", contextWindow: 16e3, verified: false },
110954
- // Qwen / 通义千问(优先使用当前可核验的商业模型 ID)
110955
- // DashScope 兼容接口 max_tokens 上限为 65536
110956
- {
110957
- pattern: "qwen3-coder-plus",
110958
- contextWindow: 262144,
110959
- maxOutputTokens: 65536,
110960
- verified: false
110961
- },
110962
- {
110963
- pattern: "qwen3.6-plus",
110964
- contextWindow: 1e6,
110965
- maxOutputTokens: 65536,
110966
- vision: true,
110967
- verified: true,
110968
- source: "https://help.aliyun.com/zh/model-studio/models"
110969
- },
110970
- {
110971
- pattern: "qwen3.5-plus",
110972
- contextWindow: 1e6,
110973
- maxOutputTokens: 65536,
110974
- vision: true,
110975
- verified: true,
110976
- source: "https://help.aliyun.com/zh/model-studio/models"
110977
- },
110978
- {
110979
- pattern: "qwen3-max",
110980
- contextWindow: 262144,
110981
- maxOutputTokens: 65536,
110982
- verified: true,
110983
- source: "https://help.aliyun.com/zh/model-studio/models"
110984
- },
110985
- {
110986
- pattern: "qwen3.6-flash",
110987
- contextWindow: 1e6,
110988
- maxOutputTokens: 65536,
110989
- verified: true,
110990
- source: "https://help.aliyun.com/zh/model-studio/models"
110991
- },
110992
- {
110993
- pattern: "qwen3.5-flash",
110994
- contextWindow: 1e6,
110995
- maxOutputTokens: 65536,
110996
- verified: true,
110997
- source: "https://help.aliyun.com/zh/model-studio/models"
110998
- },
110999
- {
111000
- pattern: "qwen3.5-omni-plus",
111001
- contextWindow: 262144,
111002
- maxOutputTokens: 65536,
111003
- vision: true,
111004
- verified: true,
111005
- source: "https://help.aliyun.com/zh/model-studio/models"
111006
- },
111007
- {
111008
- pattern: "qwen3.5-omni-flash",
111009
- contextWindow: 262144,
111010
- maxOutputTokens: 65536,
111011
- vision: true,
111012
- verified: true,
111013
- source: "https://help.aliyun.com/zh/model-studio/models"
111014
- },
111015
- { pattern: "qwen3", maxOutputTokens: 65536, verified: false },
111016
- { pattern: "qwen2.5-vl", contextWindow: 128e3, maxOutputTokens: 65536, vision: true, verified: false },
111017
- { pattern: "qwen2-vl", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
111018
- { pattern: "qwen-vl-max", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
111019
- { pattern: "qwen-vl-plus", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
111020
- {
111021
- pattern: "qvq-max",
111022
- contextWindow: 131072,
111023
- maxOutputTokens: 65536,
111024
- vision: true,
111025
- verified: true,
111026
- source: "https://help.aliyun.com/zh/model-studio/models"
111027
- },
111028
- {
111029
- pattern: "qvq-plus",
111030
- contextWindow: 131072,
111031
- maxOutputTokens: 65536,
111032
- vision: true,
111033
- verified: true,
111034
- source: "https://help.aliyun.com/zh/model-studio/models"
111035
- },
111036
- {
111037
- pattern: "qvq",
111038
- contextWindow: 131072,
111039
- maxOutputTokens: 65536,
111040
- vision: true,
111041
- verified: true,
111042
- source: "https://help.aliyun.com/zh/model-studio/models"
111043
- },
111044
- { pattern: "qwen-max", contextWindow: 131072, maxOutputTokens: 65536, verified: false },
111045
- {
111046
- pattern: "qwen-plus",
111047
- contextWindow: 1e6,
111048
- maxOutputTokens: 65536,
111049
- verified: true,
111050
- source: "https://help.aliyun.com/zh/model-studio/models"
111051
- },
111052
- {
111053
- pattern: "qwen-flash",
111054
- contextWindow: 1e6,
111055
- maxOutputTokens: 65536,
111056
- verified: true,
111057
- source: "https://help.aliyun.com/zh/model-studio/models"
111058
- },
111059
- {
111060
- pattern: "qwen-turbo",
111061
- contextWindow: 1e6,
111062
- maxOutputTokens: 65536,
111063
- verified: true,
111064
- source: "https://help.aliyun.com/zh/model-studio/models"
111065
- },
111066
- { pattern: "qwen", maxOutputTokens: 65536, verified: false },
111067
- // Moonshot / Kimi(官方已核验)
111068
- {
111069
- pattern: "kimi-k2.5",
111070
- contextWindow: 256e3,
111071
- vision: true,
111072
- verified: true,
111073
- source: "https://platform.kimi.ai/docs/models"
111074
- },
111075
- {
111076
- pattern: "kimi-k2-0905-preview",
111077
- contextWindow: 256e3,
111078
- verified: true,
111079
- source: "https://platform.kimi.ai/docs/models"
111080
- },
111081
- {
111082
- pattern: "kimi-k2-turbo-preview",
111083
- contextWindow: 256e3,
111084
- verified: true,
111085
- source: "https://platform.kimi.ai/docs/models"
111086
- },
111087
- {
111088
- pattern: "kimi-k2-thinking-turbo",
111089
- contextWindow: 256e3,
111090
- verified: true,
111091
- source: "https://platform.kimi.ai/docs/models"
111092
- },
111093
- {
111094
- pattern: "kimi-k2-thinking",
111095
- contextWindow: 256e3,
111096
- verified: true,
111097
- source: "https://platform.kimi.ai/docs/models"
111098
- },
111099
- {
111100
- pattern: "kimi-k2-0711-preview",
111101
- contextWindow: 128e3,
111102
- verified: true,
111103
- source: "https://platform.kimi.ai/docs/models"
111104
- },
111105
- { pattern: "kimi-k2", contextWindow: 128e3, verified: false },
111106
- {
111107
- pattern: "moonshot-v1-128k-vision-preview",
111108
- contextWindow: 128e3,
111109
- vision: true,
111110
- verified: true,
111111
- source: "https://platform.kimi.ai/docs/models"
111112
- },
111113
- {
111114
- pattern: "moonshot-v1-32k-vision-preview",
111115
- contextWindow: 32e3,
111116
- vision: true,
111117
- verified: true,
111118
- source: "https://platform.kimi.ai/docs/models"
111119
- },
111120
- {
111121
- pattern: "moonshot-v1-8k-vision-preview",
111122
- contextWindow: 8192,
111123
- vision: true,
111124
- verified: true,
111125
- source: "https://platform.kimi.ai/docs/models"
111126
- },
111127
- {
111128
- pattern: "moonshot-v1-128k",
111129
- contextWindow: 128e3,
111130
- verified: true,
111131
- source: "https://platform.kimi.ai/docs/models"
111132
- },
111133
- {
111134
- pattern: "moonshot-v1-32k",
111135
- contextWindow: 32e3,
111136
- verified: true,
111137
- source: "https://platform.kimi.ai/docs/models"
111138
- },
111139
- {
111140
- pattern: "moonshot-v1-8k",
111141
- contextWindow: 8192,
111142
- verified: true,
111143
- source: "https://platform.kimi.ai/docs/models"
111144
- },
111145
- { pattern: "kimi", contextWindow: 128e3, verified: false },
111146
- { pattern: "moonshot", contextWindow: 128e3, verified: false },
111147
- // MiniMax(本轮未核到精确 context,使用保守 fallback,避免伪精确)
111148
- { pattern: "minimax-vl-01", contextWindow: 128e3, vision: true, verified: false },
111149
- { pattern: "minimax-text-01", contextWindow: 128e3, verified: false },
111150
- { pattern: "abab6.5", contextWindow: 2e5, verified: false },
111151
- { pattern: "abab6.5s", contextWindow: 2e5, verified: false },
111152
- { pattern: "abab", contextWindow: 2e5, verified: false },
111153
- { pattern: "minimax-vl", contextWindow: 128e3, vision: true, verified: false },
111154
- { pattern: "minimax", contextWindow: 128e3, verified: false },
111155
- // GLM / 智谱(官方已核验)
111156
- {
111157
- pattern: "glm-4.5v",
111158
- contextWindow: 64e3,
111159
- vision: true,
111160
- verified: true,
111161
- source: "https://docs.bigmodel.cn/cn/guide/models/vlm/glm-4.5v"
111162
- },
111163
- { pattern: "glm-4v", contextWindow: 128e3, vision: true, verified: false },
111164
- {
111165
- pattern: "glm-4.5-air",
111166
- contextWindow: 128e3,
111167
- verified: true,
111168
- source: "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5"
111169
- },
111170
- {
111171
- pattern: "glm-4.5",
111172
- contextWindow: 128e3,
111173
- verified: true,
111174
- source: "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5"
111175
- },
111176
- { pattern: "glm-4-plus", contextWindow: 128e3, verified: false },
111177
- { pattern: "glm-4", contextWindow: 128e3, verified: false },
111178
- // Meta Llama / 其他常见开源视觉模型
111179
- { pattern: "llama-3.2", contextWindow: 128e3, verified: false },
111180
- { pattern: "llama-3.1", contextWindow: 128e3, verified: false },
111181
- { pattern: "llama-3", contextWindow: 128e3, verified: false },
111182
- { pattern: "llama-2", contextWindow: 4096, verified: false },
111183
- { pattern: "llava", contextWindow: 32768, vision: true, verified: false },
111184
- { pattern: "internvl", contextWindow: 32768, vision: true, verified: false },
111185
- { pattern: "minicpm-v", contextWindow: 32768, vision: true, verified: false },
111186
- { pattern: "pixtral", contextWindow: 128e3, vision: true, verified: false },
111187
- // 通用兜底关键词(放最后,避免过度误判)
111188
- { pattern: "vision", vision: true, verified: false },
111189
- { pattern: "vl", vision: true, verified: false },
111190
- { pattern: "omni", vision: true, verified: false }
111191
- ].sort((a, b) => b.pattern.length - a.pattern.length);
111192
- DEFAULT_CONTEXT_WINDOW = 128e3;
111193
- MAX_LEARNED_MODELS = 100;
111194
- ModelCapability = class {
111195
- learnedWindows = /* @__PURE__ */ new Map();
111196
- learnedMaxOutputTokens = /* @__PURE__ */ new Map();
111197
- learnedUpdatedAt = /* @__PURE__ */ new Map();
111198
- onLearned;
111199
- setOnLearned(callback) {
111200
- this.onLearned = callback;
111201
- }
111202
- hydrate(snapshot) {
111203
- this.learnedWindows.clear();
111204
- this.learnedMaxOutputTokens.clear();
111205
- this.learnedUpdatedAt.clear();
111206
- for (const [model, record2] of Object.entries(snapshot.models)) {
111207
- const normalized = this.normalizeModel(model);
111208
- if (typeof record2.contextWindow === "number") {
111209
- this.learnedWindows.set(normalized, record2.contextWindow);
111210
- }
111211
- if (typeof record2.maxOutputTokens === "number") {
111212
- this.learnedMaxOutputTokens.set(normalized, record2.maxOutputTokens);
111213
- }
111214
- if (typeof record2.updatedAt === "number") {
111215
- this.learnedUpdatedAt.set(normalized, record2.updatedAt);
111216
- }
111217
- }
111218
- }
111219
- snapshot() {
111220
- const models = {};
111221
- for (const model of /* @__PURE__ */ new Set([
111222
- ...this.learnedWindows.keys(),
111223
- ...this.learnedMaxOutputTokens.keys()
111224
- ])) {
111225
- const contextWindow = this.learnedWindows.get(model);
111226
- const maxOutputTokens = this.learnedMaxOutputTokens.get(model);
111227
- models[model] = {
111228
- updatedAt: this.learnedUpdatedAt.get(model) ?? Date.now(),
111229
- ...contextWindow !== void 0 ? { contextWindow } : {},
111230
- ...maxOutputTokens !== void 0 ? { maxOutputTokens } : {}
111231
- };
111232
- }
111233
- return { models };
111234
- }
111235
- normalizeModel(model) {
111236
- return model.toLowerCase();
111237
- }
111238
- markLearned(model) {
111239
- this.learnedUpdatedAt.set(model, Date.now());
111240
- this.cleanup();
111241
- this.onLearned?.();
111242
- }
111243
- findRule(model) {
111244
- const normalized = this.normalizeModel(model);
111245
- return MODEL_RULES.find((rule) => normalized.includes(rule.pattern));
111246
- }
111247
- /**
111248
- * 获取模型的上下文窗口大小
111249
- */
111250
- getContextWindow(model) {
111251
- const normalized = this.normalizeModel(model);
111252
- if (this.learnedWindows.has(normalized)) {
111253
- return this.learnedWindows.get(normalized);
111254
- }
111255
- const rule = this.findRule(model);
111256
- if (rule?.contextWindow) {
111257
- return rule.contextWindow;
111258
- }
111259
- return DEFAULT_CONTEXT_WINDOW;
111260
- }
111261
- /**
111262
- * 从错误信息中学习上下文窗口大小
111263
- */
111264
- learnContextWindow(model, errorMessage) {
111265
- const patterns = [
111266
- /maximum input length[:\s]*\(?(\d+)\)?/i,
111267
- /range of input length should be\s*\[\s*1\s*,\s*(\d+)\s*\]/i,
111268
- /does not support max tokens\s*>\s*(\d+)/i,
111269
- /context length is\s*(\d+)/i,
111270
- /maximum context length[:\s]*(\d+)/i
111271
- ];
111272
- for (const pattern of patterns) {
111273
- const match = errorMessage.match(pattern);
111274
- if (match?.[1]) {
111275
- const contextWindow = parseInt(match[1], 10);
111276
- this.saveContextWindow(model, contextWindow);
111277
- return contextWindow;
111278
- }
111279
- }
111280
- return void 0;
111281
- }
111282
- learnFromError(model, errorMessage) {
111283
- const learned = {};
111284
- const contextWindow = this.learnContextWindow(model, errorMessage);
111285
- const maxOutputTokens = this.learnMaxOutputTokens(model, errorMessage);
111286
- if (contextWindow !== void 0) learned.contextWindow = contextWindow;
111287
- if (maxOutputTokens !== void 0) learned.maxOutputTokens = maxOutputTokens;
111288
- return Object.keys(learned).length ? learned : void 0;
111289
- }
111290
- /**
111291
- * 获取模型允许的最大输出 token 数(用于 clamp maxOutputTokens)
111292
- */
111293
- getMaxOutputTokens(model) {
111294
- const normalized = this.normalizeModel(model);
111295
- if (this.learnedMaxOutputTokens.has(normalized)) {
111296
- return this.learnedMaxOutputTokens.get(normalized);
111297
- }
111298
- return this.findRule(model)?.maxOutputTokens;
111299
- }
111300
- /**
111301
- * 从错误信息中学习 maxOutputTokens 上限
111302
- */
111303
- learnMaxOutputTokens(model, errorMessage) {
111304
- const patterns = [
111305
- /Range of max_tokens should be \[1, (\d+)\]/i,
111306
- /max_tokens.*should be.*?(\d+)/i
111307
- ];
111308
- for (const pattern of patterns) {
111309
- const match = errorMessage.match(pattern);
111310
- if (match?.[1]) {
111311
- const maxOutput = parseInt(match[1], 10);
111312
- const normalized = this.normalizeModel(model);
111313
- this.learnedMaxOutputTokens.set(normalized, maxOutput);
111314
- this.markLearned(normalized);
111315
- logger15.debug(`Learned maxOutputTokens for ${model}: ${maxOutput}`);
111316
- return maxOutput;
111317
- }
111318
- }
111319
- return void 0;
111320
- }
111321
- learnMaxOutputTokensFromError(model, errorMessage) {
111322
- return this.learnMaxOutputTokens(model, errorMessage) ?? null;
111323
- }
111324
- /**
111325
- * 保存学习到的上下文窗口大小
111326
- */
111327
- saveContextWindow(model, contextWindow) {
111328
- const normalized = this.normalizeModel(model);
111329
- this.learnedWindows.set(normalized, contextWindow);
111330
- this.markLearned(normalized);
111331
- logger15.debug(`Learned context window for ${model}: ${contextWindow} tokens`);
111332
- }
111333
- /**
111334
- * 检测模型是否支持视觉功能
111335
- */
111336
- supportsVision(model) {
111337
- return this.findRule(model)?.vision === true;
111338
- }
111339
- /**
111340
- * 检测是否为图片 MIME 类型
111341
- */
111342
- isImageMimeType(mimeType) {
111343
- return mimeType.startsWith("image/");
111344
- }
111345
- /**
111346
- * 检测所有附件是否都是图片
111347
- */
111348
- allAttachmentsAreImages(attachments) {
111349
- return attachments.length > 0 && attachments.every((a) => this.isImageMimeType(a.mimeType));
111350
- }
111351
- /**
111352
- * 清理过旧的学习记录
111353
- */
111354
- cleanup() {
111355
- while (this.learnedUpdatedAt.size > MAX_LEARNED_MODELS) {
111356
- const oldest = [...this.learnedUpdatedAt.entries()].sort((a, b) => a[1] - b[1])[0]?.[0];
111357
- if (!oldest) break;
111358
- this.learnedWindows.delete(oldest);
111359
- this.learnedMaxOutputTokens.delete(oldest);
111360
- this.learnedUpdatedAt.delete(oldest);
111361
- }
111362
- }
111363
- };
111364
- modelCapability = new ModelCapability();
111365
- }
111366
- });
111367
-
111368
- // src/core/agent/execution/kernel/multimodal.ts
111369
- var logger16, RECENT_USER_MESSAGE_COUNT, MultimodalTransformer, multimodalTransformer;
111370
- var init_multimodal = __esm({
111371
- "src/core/agent/execution/kernel/multimodal.ts"() {
111372
- "use strict";
111373
- init_ModelCapability();
111374
- init_execution_deps();
111375
- init_logger();
111376
- logger16 = createLogger("MultimodalTransformer");
111377
- RECENT_USER_MESSAGE_COUNT = 2;
111378
- MultimodalTransformer = class {
111379
- /** data URL 缓存(简单 Map,不做 LRU) */
111380
- cache = /* @__PURE__ */ new Map();
111381
- /**
111382
- * 核心入口:转换 messages 中的图片附件为多模态格式
111383
- *
111384
- * - 只转换最近 N 条 role='user' 的 message
111385
- * - 识别 <attachment mime="image/..."> 占位文本
111386
- * - 读取文件 → 缩放 → 转为 ImagePart
111387
- * - 不支持 vision 的模型 → 原样透传
111388
- * - 非图片附件 → 保留文本标记
111389
- */
111390
- async transform(messages, model) {
111391
- if (!modelCapability.supportsVision(model)) {
111392
- return messages;
111393
- }
111394
- const userIndices = [];
111395
- for (let i = messages.length - 1; i >= 0; i--) {
111396
- if (messages[i].role === "user") {
111397
- userIndices.unshift(i);
111398
- if (userIndices.length >= RECENT_USER_MESSAGE_COUNT) break;
111399
- }
111400
- }
111401
- if (userIndices.length === 0) return messages;
111402
- const result = [...messages];
111403
- for (const idx of userIndices) {
111404
- const msg = result[idx];
111405
- if (msg.role !== "user") continue;
111406
- if (typeof msg.content === "string") {
111407
- const transformed = await this.transformStringContent(msg.content);
111408
- if (transformed !== msg.content) {
111409
- result[idx] = { ...msg, content: transformed };
111410
- }
111411
- continue;
111412
- }
111413
- if (Array.isArray(msg.content)) {
111414
- const transformed = await this.transformPartsContent(msg.content);
111415
- if (transformed !== msg.content) {
111416
- result[idx] = { ...msg, content: transformed };
111417
- }
111418
- }
111419
- }
111420
- return result;
111421
- }
111422
- /**
111423
- * 处理 string content — 可能包含 <attachment> 标记或 legacy DSL 块
111424
- */
111425
- async transformStringContent(content) {
111426
- const attachmentRegex = /<attachment\s+mime="([^"]+)"\s+name="([^"]+)">([^<]+)<\/attachment>/g;
111427
- const matches = [];
111428
- let hasImage = false;
111429
- let m;
111430
- while ((m = attachmentRegex.exec(content)) !== null) {
111431
- if (m[1].startsWith("image/")) hasImage = true;
111432
- matches.push({ mime: m[1], name: m[2], path: m[3], index: m.index, fullMatch: m[0] });
111433
- }
111434
- if (matches.length > 0) {
111435
- if (!hasImage) return content;
111436
- const parts = [];
111437
- let lastEnd = 0;
111438
- for (const match of matches) {
111439
- if (match.index > lastEnd) {
111440
- parts.push({ type: "text", text: content.slice(lastEnd, match.index) });
111441
- }
111442
- if (match.mime.startsWith("image/")) {
111443
- const image = await this.loadImageDataUrl(match.path);
111444
- if (image) {
111445
- parts.push({ type: "image", image });
111446
- } else {
111447
- parts.push({ type: "text", text: `[\u56FE\u7247: ${match.name}]` });
111448
- }
111449
- } else {
111450
- parts.push({ type: "text", text: match.fullMatch });
111451
- }
111452
- lastEnd = match.index + match.fullMatch.length;
111453
- }
111454
- if (lastEnd < content.length) {
111455
- parts.push({ type: "text", text: content.slice(lastEnd) });
111456
- }
111457
- return parts.some((p) => p.type === "image") ? parts : content;
111458
- }
111459
- return this.transformLegacyDsl(content);
111460
- }
111461
- /**
111462
- * 兼容 legacy DSL 格式:```attachments\n<file ...>path</file>\n```
111463
- */
111464
- async transformLegacyDsl(content) {
111465
- const blockRegex = /```attachments\n([\s\S]*?)```/g;
111466
- if (!blockRegex.test(content)) return content;
111467
- const regex2 = /```attachments\n([\s\S]*?)```/g;
111468
- const parts = [];
111469
- let lastEnd = 0;
111470
- let hasImage = false;
111471
- let blockMatch;
111472
- while ((blockMatch = regex2.exec(content)) !== null) {
111473
- if (blockMatch.index > lastEnd) {
111474
- parts.push({ type: "text", text: content.slice(lastEnd, blockMatch.index) });
111475
- }
111476
- const blockContent = blockMatch[1];
111477
- const fileRegex = /<file(?:\s+mime="([^"]*)"\s+name="([^"]*)")?>([^<]+)<\/file>/g;
111478
- let fileMatch;
111479
- while ((fileMatch = fileRegex.exec(blockContent)) !== null) {
111480
- const mime = fileMatch[1] || void 0;
111481
- const name21 = fileMatch[2] || void 0;
111482
- const path11 = fileMatch[3];
111483
- const isImage = mime ? mime.startsWith("image/") : /\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(path11);
111484
- if (isImage) {
111485
- const image = await this.loadImageDataUrl(path11);
111486
- if (image) {
111487
- hasImage = true;
111488
- parts.push({ type: "image", image });
111489
- } else {
111490
- parts.push({ type: "text", text: `[\u56FE\u7247: ${name21 || path11}]` });
111491
- }
111492
- } else {
111493
- parts.push({ type: "text", text: fileMatch[0] });
111494
- }
111495
- }
111496
- lastEnd = blockMatch.index + blockMatch[0].length;
111497
- }
111498
- if (lastEnd < content.length) {
111499
- parts.push({ type: "text", text: content.slice(lastEnd) });
111500
- }
111501
- return hasImage ? parts : content;
111502
- }
111503
- /**
111504
- * 处理 Array<TextPart> content — 逐 part 检查 <attachment> 标记
111505
- */
111506
- async transformPartsContent(content) {
111507
- let hasTransformed = false;
111508
- const result = [];
111509
- for (const part of content) {
111510
- if (part.type === "text" && "text" in part && typeof part.text === "string") {
111511
- const text4 = part.text;
111512
- const attachment = this.parseInlineAttachment(text4);
111513
- if (attachment) {
111514
- if (attachment.isImage) {
111515
- const image = await this.loadImageDataUrl(attachment.path);
111516
- if (image) {
111517
- hasTransformed = true;
111518
- result.push({ type: "image", image });
111519
- } else {
111520
- result.push({ type: "text", text: `[\u56FE\u7247: ${attachment.name}]` });
111521
- }
111522
- } else {
111523
- result.push(part);
111524
- }
111525
- continue;
111526
- }
111527
- result.push(part);
111528
- } else if (part.type === "image") {
111529
- result.push(part);
111530
- } else if (part.type === "file") {
111531
- result.push({ type: "text", text: JSON.stringify(part) });
111532
- }
111533
- }
111534
- return hasTransformed ? result : content;
111535
- }
111536
- /**
111537
- * 解析单行 <attachment mime="..." name="...">path</attachment> 标记
111538
- */
111539
- parseInlineAttachment(text4) {
111540
- const m = text4.match(/^<attachment\s+mime="([^"]+)"\s+name="([^"]+)">([^<]+)<\/attachment>$/);
111541
- if (!m) return null;
111542
- return {
111543
- path: m[3],
111544
- name: m[2],
111545
- isImage: m[1].startsWith("image/")
111546
- };
111547
- }
111548
- /**
111549
- * 读取图片附件 → data URL
111550
- * 带缓存和超时保护
111551
- */
111552
- async loadImageDataUrl(relativePath) {
111553
- const cached2 = this.cache.get(relativePath);
111554
- if (cached2) return cached2;
111555
- try {
111556
- const resolver = resolveAgentExecutionDeps().multimodalAssetResolver;
111557
- if (!resolver) return null;
111558
- const image = await resolver.loadImageDataUrl(relativePath);
111559
- if (image) {
111560
- this.cache.set(relativePath, image);
111561
- }
111562
- return image;
111563
- } catch (err) {
111564
- logger16.warn(`Failed to load image asset: ${relativePath}`, err);
111565
- return null;
111566
- }
111567
- }
111568
- };
111569
- multimodalTransformer = new MultimodalTransformer();
111570
- }
111571
- });
111572
-
111573
- // src/core/agent/execution/kernel/request-projection.ts
111574
- function projectRequestMessagesForProvider(messages, modelSettings) {
111575
- return stripUnsupportedReasoningMetadataForModel(
111576
- projectOpenAIImageGenerationForForeignProvider(messages, modelSettings.apiType),
111577
- modelSettings
111578
- );
111579
- }
111580
- function projectOpenAIImageGenerationForForeignProvider(messages, apiType) {
111581
- if (supportsOpenAIProviderExecutedHistory(apiType)) return messages;
111582
- let changed = false;
111583
- const projected = messages.flatMap((message) => {
111584
- if (message.role !== "assistant" || !Array.isArray(message.content)) return [message];
111585
- const content = message.content;
111586
- const generatedImageCount = countOpenAIImageGenerationResults(content);
111587
- const nextContent = content.filter((part) => {
111588
- if (isOpenAIImageGenerationToolPart(part)) {
111589
- changed = true;
111590
- return false;
111591
- }
111592
- return true;
111593
- });
111594
- if (generatedImageCount > 0) {
111595
- changed = true;
111596
- nextContent.push({
111597
- type: "text",
111598
- text: generatedImageCount === 1 ? "\u4E4B\u524D\u5DF2\u751F\u6210\u4E00\u5F20\u56FE\u7247\uFF0C\u5DF2\u4FDD\u5B58\u4E3A\u9644\u4EF6\u3002" : `\u4E4B\u524D\u5DF2\u751F\u6210 ${generatedImageCount} \u5F20\u56FE\u7247\uFF0C\u5DF2\u4FDD\u5B58\u4E3A\u9644\u4EF6\u3002`
111599
- });
111600
- }
111601
- if (nextContent.length === 0) {
111602
- changed = true;
111603
- return [];
111604
- }
111605
- return [{ ...message, content: nextContent }];
111606
- });
111607
- return changed ? projected : messages;
111608
- }
111609
- function stripUnsupportedReasoningMetadataForModel(messages, modelSettings) {
111610
- if (!isGlm51Thinking(modelSettings)) return messages;
111611
- let changed = false;
111612
- const sanitized = messages.map((message) => {
111613
- if (!Array.isArray(message.content)) return message;
111614
- let contentChanged = false;
111615
- const content = message.content.map((part) => {
111616
- if (part.type !== "reasoning") return part;
111617
- if (!("providerOptions" in part) && !("providerMetadata" in part) && !("experimental_providerMetadata" in part)) {
111618
- return part;
111619
- }
111620
- const {
111621
- providerOptions: _providerOptions,
111622
- providerMetadata: _providerMetadata,
111623
- experimental_providerMetadata: _experimentalProviderMetadata,
111624
- ...rest
111625
- } = part;
111626
- contentChanged = true;
111627
- changed = true;
111628
- return rest;
111629
- });
111630
- return contentChanged ? { ...message, content } : message;
111631
- });
111632
- return changed ? sanitized : messages;
111633
- }
111634
- function supportsOpenAIProviderExecutedHistory(apiType) {
111635
- return apiType?.toLowerCase() === "openai";
111636
- }
111637
- function isGlm51Thinking(modelSettings) {
111638
- return modelSettings.model.toLowerCase().includes("glm-5.1") && Boolean(modelSettings.reasoningEffort && modelSettings.reasoningEffort !== "off");
111639
- }
111640
- function countOpenAIImageGenerationResults(content) {
111641
- return content.filter((part) => {
111642
- if (part.type !== "tool-result" || part.toolName !== "image_generation") return false;
111643
- const output = part.output;
111644
- return Boolean(output && typeof output === "object" && "result" in output);
111645
- }).length;
111646
- }
111647
- function isOpenAIImageGenerationToolPart(part) {
111648
- if (part.type !== "tool-call" && part.type !== "tool-result") return false;
111649
- if (part.toolName !== "image_generation") return false;
111650
- if (part.type === "tool-call") {
111651
- return part.providerExecuted === true;
111652
- }
111653
- const providerOptions = part.providerOptions;
111654
- const openaiOptions = providerOptions && typeof providerOptions === "object" ? providerOptions.openai : void 0;
111655
- return Boolean(openaiOptions && typeof openaiOptions === "object");
111656
- }
111657
- var init_request_projection = __esm({
111658
- "src/core/agent/execution/kernel/request-projection.ts"() {
111659
- "use strict";
111660
- }
111661
- });
111662
-
111663
110883
  // src/core/agent/orchestration/swarm/factory/PromptBuilder.ts
111664
110884
  function buildSystemInfo(agentId) {
111665
110885
  const sysInfoLines = [
@@ -112183,7 +111403,7 @@ function shouldFallback(error48) {
112183
111403
  return error48.type === "model_error" && isFallbackFailureReason(error48.failureReason);
112184
111404
  }
112185
111405
  function isFallbackFailureReason(reason) {
112186
- return reason !== "context_overflow";
111406
+ return reason !== "context_overflow" && reason !== "empty_response";
112187
111407
  }
112188
111408
  var DefaultAgentLoop;
112189
111409
  var init_DefaultAgentLoop = __esm({
@@ -112260,7 +111480,13 @@ var init_DefaultAgentLoop = __esm({
112260
111480
  continue;
112261
111481
  }
112262
111482
  }
112263
- return this.buildResult(messages, steps, blocks, "error", this.buildKernelLoopError(stepError, hasFallbackPolicy));
111483
+ return this.buildResult(
111484
+ messages,
111485
+ steps,
111486
+ blocks,
111487
+ "error",
111488
+ this.buildKernelLoopError(stepError, hasFallbackPolicy)
111489
+ );
112264
111490
  }
112265
111491
  consumedSteps += 1;
112266
111492
  if (input.stopWhen?.({ steps, messages })) {
@@ -115504,7 +114730,7 @@ Run 'npx vercel link' to link your project, then 'vc env pull' to fetch the toke
115504
114730
  */
115505
114731
  perplexitySearch
115506
114732
  };
115507
- VERSION2 = true ? "3.0.116" : "0.0.0-test";
114733
+ VERSION2 = true ? "3.0.118" : "0.0.0-test";
115508
114734
  AI_GATEWAY_PROTOCOL_VERSION = "0.0.1";
115509
114735
  gateway = createGatewayProvider();
115510
114736
  }
@@ -124927,7 +124153,7 @@ var init_dist6 = __esm({
124927
124153
  const id3Size = (bytes[6] & 127) << 21 | (bytes[7] & 127) << 14 | (bytes[8] & 127) << 7 | bytes[9] & 127;
124928
124154
  return bytes.slice(id3Size + 10);
124929
124155
  };
124930
- VERSION4 = true ? "6.0.185" : "0.0.0-test";
124156
+ VERSION4 = true ? "6.0.188" : "0.0.0-test";
124931
124157
  download = async ({
124932
124158
  url: url2,
124933
124159
  maxBytes,
@@ -127552,11 +126778,22 @@ var init_dist6 = __esm({
127552
126778
  _b17,
127553
126779
  baseCallArgs
127554
126780
  ))) != null ? _d : baseCallArgs;
127555
- const { instructions, messages, prompt, ...callArgs } = preparedCallArgs;
126781
+ const {
126782
+ instructions,
126783
+ allowSystemInMessages,
126784
+ messages,
126785
+ prompt,
126786
+ ...callArgs
126787
+ } = preparedCallArgs;
127556
126788
  return {
127557
126789
  ...callArgs,
127558
126790
  // restore prompt types
127559
- ...{ system: instructions, messages, prompt }
126791
+ ...{
126792
+ system: instructions,
126793
+ allowSystemInMessages,
126794
+ messages,
126795
+ prompt
126796
+ }
127560
126797
  };
127561
126798
  }
127562
126799
  mergeOnStepFinishCallbacks(methodCallback) {
@@ -129585,12 +128822,17 @@ function buildKernelProviderOptions(modelSettings, explicitOptions) {
129585
128822
  const options2 = explicitOptions ? cloneProviderOptions(explicitOptions) : {};
129586
128823
  const reasoningEffort = modelSettings.reasoningEffort;
129587
128824
  if (reasoningEffort && reasoningEffort !== "off") {
129588
- mergeReasoningEffort(options2, modelSettings.apiType, reasoningEffort);
128825
+ mergeReasoningEffort(options2, getEffectiveApiType(modelSettings), reasoningEffort);
129589
128826
  }
129590
128827
  return Object.keys(options2).length ? options2 : void 0;
129591
128828
  }
129592
128829
  function shouldOmitSamplingForThinking(modelSettings) {
129593
- return modelSettings.model.toLowerCase().includes("glm-5.1") && Boolean(modelSettings.reasoningEffort && modelSettings.reasoningEffort !== "off");
128830
+ if (!modelSettings.reasoningEffort || modelSettings.reasoningEffort === "off") return false;
128831
+ return getEffectiveApiType(modelSettings) === "openai" || modelSettings.model.toLowerCase().includes("glm-5.1");
128832
+ }
128833
+ function getEffectiveApiType(modelSettings) {
128834
+ const apiType = modelSettings.effectiveApiType ?? modelSettings.apiType;
128835
+ return apiType === "openai" || apiType === "anthropic" || apiType === "google" || apiType === "openai-compatible" ? apiType : "openai-compatible";
129594
128836
  }
129595
128837
  function mergeReasoningEffort(options2, apiType, reasoningEffort) {
129596
128838
  switch (apiType) {
@@ -129608,7 +128850,10 @@ function mergeReasoningEffort(options2, apiType, reasoningEffort) {
129608
128850
  });
129609
128851
  break;
129610
128852
  case "openai":
129611
- mergeProviderOptions(options2, "openai", { reasoningEffort });
128853
+ mergeProviderOptions(options2, "openai", {
128854
+ reasoningEffort,
128855
+ reasoningSummary: "auto"
128856
+ });
129612
128857
  break;
129613
128858
  case "openai-compatible":
129614
128859
  default:
@@ -129761,12 +129006,12 @@ function withOpenAIItemReference(part, toolCallId) {
129761
129006
  }
129762
129007
  };
129763
129008
  }
129764
- var logger17, ImageGenerationResultProcessor;
129009
+ var logger15, ImageGenerationResultProcessor;
129765
129010
  var init_image_generation = __esm({
129766
129011
  "src/core/agent/execution/kernel/image-generation.ts"() {
129767
129012
  "use strict";
129768
129013
  init_logger();
129769
- logger17 = createLogger("ImageGenerationResultProcessor");
129014
+ logger15 = createLogger("ImageGenerationResultProcessor");
129770
129015
  ImageGenerationResultProcessor = class {
129771
129016
  constructor(deps) {
129772
129017
  this.deps = deps;
@@ -129837,7 +129082,7 @@ var init_image_generation = __esm({
129837
129082
  `gpt-image-${Date.now()}.png`,
129838
129083
  "image/png"
129839
129084
  );
129840
- logger17.debug(`image_generation: saved ${metadata.path} (${buffer.length} bytes)`);
129085
+ logger15.debug(`image_generation: saved ${metadata.path} (${buffer.length} bytes)`);
129841
129086
  const absolutePath = await this.deps.attachmentPort.getAttachmentPath(metadata.path);
129842
129087
  this.paths.set(toolCallId, absolutePath);
129843
129088
  return {
@@ -129848,7 +129093,7 @@ var init_image_generation = __esm({
129848
129093
  size: metadata.size
129849
129094
  };
129850
129095
  } catch (error48) {
129851
- logger17.debug("image_generation: failed to save attachment", error48);
129096
+ logger15.debug("image_generation: failed to save attachment", error48);
129852
129097
  return null;
129853
129098
  }
129854
129099
  }
@@ -129859,7 +129104,7 @@ var init_image_generation = __esm({
129859
129104
  this.paths.set(toolCallId, parsed.imagePath);
129860
129105
  return parsed.attachment;
129861
129106
  } catch (error48) {
129862
- logger17.error("generateImage: failed to process result", error48);
129107
+ logger15.error("generateImage: failed to process result", error48);
129863
129108
  return null;
129864
129109
  }
129865
129110
  }
@@ -130155,6 +129400,38 @@ function assertNoSystemMessages(messages) {
130155
129400
  function shouldDelayRetryOnce(error48) {
130156
129401
  return error48?.cause instanceof EmptyResponseMessagesError || isTerminatedError(error48?.cause);
130157
129402
  }
129403
+ function toRetryExhaustedError(error48) {
129404
+ if (error48.cause instanceof EmptyResponseMessagesError) {
129405
+ const cause = new EmptyResponseRetryExhaustedError();
129406
+ if (error48.type === "model_error") {
129407
+ return {
129408
+ ...error48,
129409
+ failureReason: "empty_response",
129410
+ message: cause.message,
129411
+ cause
129412
+ };
129413
+ }
129414
+ return {
129415
+ ...error48,
129416
+ message: cause.message,
129417
+ cause
129418
+ };
129419
+ }
129420
+ return error48;
129421
+ }
129422
+ function hasMeaningfulBlocks(blocks) {
129423
+ return blocks.some((block) => {
129424
+ switch (block.type) {
129425
+ case "text":
129426
+ case "reasoning":
129427
+ return block.text.trim().length > 0;
129428
+ case "attachments":
129429
+ return block.attachments.length > 0;
129430
+ default:
129431
+ return true;
129432
+ }
129433
+ });
129434
+ }
130158
129435
  function toKernelError(error48, abortSignal) {
130159
129436
  const type = classifyKernelError(error48, abortSignal);
130160
129437
  const message = getErrorMessage3(error48);
@@ -130192,6 +129469,7 @@ function isRetryableKernelError(error48, type) {
130192
129469
  }
130193
129470
  function getFailureReason(error48) {
130194
129471
  if (RetryError.isInstance(error48)) return getFailureReason(error48.lastError);
129472
+ if (isContextOverflowError(error48)) return "context_overflow";
130195
129473
  if (isWrappedProviderError(error48)) {
130196
129474
  const reason = classifyProviderFailureReason(error48);
130197
129475
  return reason === "quota" ? "rate_limit" : reason;
@@ -130199,9 +129477,15 @@ function getFailureReason(error48) {
130199
129477
  if (!APICallError.isInstance(error48)) return "unknown";
130200
129478
  if (error48.statusCode === 429) return "rate_limit";
130201
129479
  if (error48.statusCode === 408 || /\btimeout\b|timed out/i.test(error48.message)) return "timeout";
130202
- if (/context(?: window| length)?|maximum context|too many tokens/i.test(error48.message)) return "context_overflow";
130203
129480
  return "api_error";
130204
129481
  }
129482
+ function isContextOverflowError(error48) {
129483
+ if (!error48 || typeof error48 !== "object") return false;
129484
+ const err = error48;
129485
+ if (typeof err.code === "string" && /context.*exceed|max.*context|context.*length/i.test(err.code)) return true;
129486
+ const message = getErrorMessage3(error48);
129487
+ return CONTEXT_OVERFLOW_PATTERN.test(message);
129488
+ }
130205
129489
  function isWrappedProviderError(error48) {
130206
129490
  if (!TypeValidationError.isInstance(error48)) return false;
130207
129491
  const nested = getNestedErrorPayload(error48);
@@ -130272,7 +129556,7 @@ function withAnthropicCacheControl(providerOptions) {
130272
129556
  }
130273
129557
  };
130274
129558
  }
130275
- var EmptyResponseMessagesError, ANTHROPIC_PROMPT_CACHE_CONTROL, AgentKernel;
129559
+ var EmptyResponseMessagesError, EmptyResponseRetryExhaustedError, ANTHROPIC_PROMPT_CACHE_CONTROL, CONTEXT_OVERFLOW_PATTERN, AgentKernel;
130276
129560
  var init_AgentKernel = __esm({
130277
129561
  "src/core/agent/execution/kernel/AgentKernel.ts"() {
130278
129562
  "use strict";
@@ -130288,11 +129572,18 @@ var init_AgentKernel = __esm({
130288
129572
  init_image_generation();
130289
129573
  EmptyResponseMessagesError = class extends Error {
130290
129574
  constructor() {
130291
- super("model returned empty response.messages");
129575
+ super("\u6A21\u578B\u8FD4\u56DE\u7A7A\u5185\u5BB9");
130292
129576
  this.name = "EmptyResponseMessagesError";
130293
129577
  }
130294
129578
  };
129579
+ EmptyResponseRetryExhaustedError = class extends Error {
129580
+ constructor() {
129581
+ super("\u6A21\u578B\u8FDE\u7EED\u8FD4\u56DE\u7A7A\u5185\u5BB9\u3002\u8BF7\u5148\u538B\u7F29\u4E0A\u4E0B\u6587\u540E\u518D\u8BD5\u3002");
129582
+ this.name = "EmptyResponseRetryExhaustedError";
129583
+ }
129584
+ };
130295
129585
  ANTHROPIC_PROMPT_CACHE_CONTROL = { type: "ephemeral" };
129586
+ CONTEXT_OVERFLOW_PATTERN = /context(?:_length| window| length)?|maximum context|too many tokens/i;
130296
129587
  AgentKernel = class {
130297
129588
  constructor(deps) {
130298
129589
  this.deps = deps;
@@ -130313,10 +129604,17 @@ var init_AgentKernel = __esm({
130313
129604
  currentInput = toClampedMaxTokensInput(currentInput, learnedMaxOutputTokens);
130314
129605
  continue;
130315
129606
  }
130316
- if (shouldDelayRetryOnce(result.error) && delayedRetryCount < 1) {
130317
- delayedRetryCount += 1;
130318
- await sleep(5e3);
130319
- continue;
129607
+ const delayedRetryError = result.error;
129608
+ if (shouldDelayRetryOnce(delayedRetryError)) {
129609
+ if (delayedRetryCount < 1) {
129610
+ delayedRetryCount += 1;
129611
+ await sleep(5e3);
129612
+ continue;
129613
+ }
129614
+ return {
129615
+ ...result,
129616
+ error: toRetryExhaustedError(delayedRetryError)
129617
+ };
130320
129618
  }
130321
129619
  if (!this.shouldRetry(result, currentInput, retryCount)) return result;
130322
129620
  retryCount += 1;
@@ -130364,12 +129662,15 @@ var init_AgentKernel = __esm({
130364
129662
  if (input.requestMessages) assertNoSystemMessages(input.requestMessages);
130365
129663
  const model = this.deps.createModel(input);
130366
129664
  const streamId = genId(ID_TYPE.MSG);
129665
+ const effectiveApiType = input.modelSettings.effectiveApiType ?? input.modelSettings.apiType;
130367
129666
  const omitSampling = shouldOmitSamplingForThinking(input.modelSettings);
130368
129667
  const breadcrumbBase = {
130369
129668
  streamId,
130370
129669
  agentId: input.agent.id,
130371
129670
  channelId: input.modelSettings.channelId,
130372
- provider: input.modelSettings.apiType,
129671
+ provider: effectiveApiType,
129672
+ configuredApiType: input.modelSettings.configuredApiType ?? input.modelSettings.apiType,
129673
+ effectiveApiType: input.modelSettings.effectiveApiType,
130373
129674
  model: input.modelSettings.model
130374
129675
  };
130375
129676
  recordAppCrashBreadcrumb("llm.stream.start", {
@@ -130384,9 +129685,9 @@ var init_AgentKernel = __esm({
130384
129685
  });
130385
129686
  const result = streamText({
130386
129687
  model,
130387
- system: toCachedSystem(input.system, input.modelSettings.apiType),
130388
- messages: toCachedMessages(input.requestMessages ?? input.messages, input.modelSettings.apiType),
130389
- tools: toCachedTools(input.tools, input.modelSettings.apiType),
129688
+ system: toCachedSystem(input.system, effectiveApiType),
129689
+ messages: toCachedMessages(input.requestMessages ?? input.messages, effectiveApiType),
129690
+ tools: toCachedTools(input.tools, effectiveApiType),
130390
129691
  abortSignal: input.abortSignal,
130391
129692
  temperature: omitSampling ? void 0 : input.modelSettings.temperature,
130392
129693
  topP: omitSampling ? void 0 : input.modelSettings.topP,
@@ -130409,8 +129710,9 @@ var init_AgentKernel = __esm({
130409
129710
  const steps = await result.steps;
130410
129711
  const response = await result.response;
130411
129712
  const usage = await result.totalUsage;
129713
+ const modelStep = steps.at(-1);
130412
129714
  const sanitizedMessages = imageGeneration2?.sanitizeMessages(response.messages) ?? response.messages;
130413
- if (sanitizedMessages.length === 0 && blocks.length === 0) {
129715
+ if (sanitizedMessages.length === 0 && !hasMeaningfulBlocks(blocks)) {
130414
129716
  throw new EmptyResponseMessagesError();
130415
129717
  }
130416
129718
  const responseMessages = this.tagAssistantMessages(sanitizedMessages, input.agent.id, input.agent.name);
@@ -130424,7 +129726,7 @@ var init_AgentKernel = __esm({
130424
129726
  });
130425
129727
  return {
130426
129728
  deltaMessages: responseMessages,
130427
- modelStep: steps.at(-1),
129729
+ modelStep,
130428
129730
  blocks,
130429
129731
  usage: toUsage(usage),
130430
129732
  model: input.modelSettings.model,
@@ -130437,7 +129739,9 @@ var init_AgentKernel = __esm({
130437
129739
  recordAppCrashBreadcrumb("llm.stream.error", {
130438
129740
  agentId: input.agent.id,
130439
129741
  channelId: input.modelSettings.channelId,
130440
- provider: input.modelSettings.apiType,
129742
+ provider: input.modelSettings.effectiveApiType ?? input.modelSettings.apiType,
129743
+ configuredApiType: input.modelSettings.configuredApiType ?? input.modelSettings.apiType,
129744
+ effectiveApiType: input.modelSettings.effectiveApiType,
130441
129745
  model: input.modelSettings.model,
130442
129746
  error: error48
130443
129747
  }, "error");
@@ -130530,6 +129834,790 @@ var init_AgentKernel = __esm({
130530
129834
  }
130531
129835
  });
130532
129836
 
129837
+ // src/core/agent/execution/model/ModelCapability.ts
129838
+ var logger16, MODEL_RULES, DEFAULT_CONTEXT_WINDOW, MAX_LEARNED_MODELS, ModelCapability, modelCapability;
129839
+ var init_ModelCapability = __esm({
129840
+ "src/core/agent/execution/model/ModelCapability.ts"() {
129841
+ "use strict";
129842
+ init_logger();
129843
+ logger16 = createLogger("ModelCapability");
129844
+ MODEL_RULES = [
129845
+ // OpenAI
129846
+ { pattern: "gpt-4o-mini", contextWindow: 128e3, vision: true, verified: false },
129847
+ { pattern: "gpt-4o", contextWindow: 128e3, vision: true, verified: false },
129848
+ { pattern: "gpt-4.1", contextWindow: 1e6, vision: true, verified: false },
129849
+ { pattern: "gpt-4-turbo", contextWindow: 128e3, vision: true, verified: false },
129850
+ { pattern: "gpt-4-vision", contextWindow: 128e3, vision: true, verified: false },
129851
+ { pattern: "gpt-4.5", contextWindow: 128e3, verified: false },
129852
+ { pattern: "gpt-5.5", contextWindow: 32e4, vision: true, verified: false },
129853
+ { pattern: "gpt-5.4", contextWindow: 32e4, vision: true, verified: false },
129854
+ { pattern: "gpt-5", contextWindow: 128e3, vision: true, verified: false },
129855
+ { pattern: "gpt-6", contextWindow: 128e3, vision: true, verified: false },
129856
+ { pattern: "o4-mini", contextWindow: 2e5, vision: true, verified: false },
129857
+ { pattern: "o3-mini", contextWindow: 2e5, verified: false },
129858
+ { pattern: "o3", contextWindow: 2e5, vision: true, verified: false },
129859
+ { pattern: "o1-mini", contextWindow: 128e3, verified: false },
129860
+ { pattern: "o1", contextWindow: 2e5, vision: true, verified: false },
129861
+ { pattern: "gpt-3.5-turbo", contextWindow: 16385, verified: false },
129862
+ { pattern: "gpt-3.5", contextWindow: 16385, verified: false },
129863
+ // Anthropic Claude
129864
+ { pattern: "claude-opus-4", contextWindow: 2e5, vision: true, verified: false },
129865
+ { pattern: "claude-sonnet-4", contextWindow: 2e5, vision: true, verified: false },
129866
+ { pattern: "claude-3.7-sonnet", contextWindow: 2e5, vision: true, verified: false },
129867
+ { pattern: "claude-3.5-sonnet", contextWindow: 2e5, vision: true, verified: false },
129868
+ { pattern: "claude-3.5-haiku", contextWindow: 2e5, vision: true, verified: false },
129869
+ { pattern: "claude-3-opus", contextWindow: 2e5, vision: true, verified: false },
129870
+ { pattern: "claude-3-sonnet", contextWindow: 2e5, vision: true, verified: false },
129871
+ { pattern: "claude-3-haiku", contextWindow: 2e5, vision: true, verified: false },
129872
+ { pattern: "claude-opus", contextWindow: 2e5, verified: false },
129873
+ { pattern: "claude-sonnet", contextWindow: 2e5, verified: false },
129874
+ { pattern: "claude-haiku", contextWindow: 2e5, verified: false },
129875
+ // Google Gemini
129876
+ { pattern: "gemini-2.5-pro", contextWindow: 1e6, vision: true, verified: false },
129877
+ { pattern: "gemini-2.5-flash", contextWindow: 1e6, vision: true, verified: false },
129878
+ { pattern: "gemini-2.0-flash", contextWindow: 1e6, vision: true, verified: false },
129879
+ { pattern: "gemini-1.5-pro", contextWindow: 1e6, vision: true, verified: false },
129880
+ { pattern: "gemini-1.5-flash", contextWindow: 1e6, vision: true, verified: false },
129881
+ { pattern: "gemini-pro-vision", contextWindow: 32e3, vision: true, verified: false },
129882
+ { pattern: "gemini-pro", contextWindow: 32e3, verified: false },
129883
+ { pattern: "gemini-2.0", contextWindow: 1e6, vision: true, verified: false },
129884
+ { pattern: "deepseek-v4", contextWindow: 1e6, vision: false, verified: false },
129885
+ // DeepSeek(官方已核验)
129886
+ {
129887
+ pattern: "deepseek-reasoner",
129888
+ contextWindow: 128e3,
129889
+ verified: true,
129890
+ source: "https://api-docs.deepseek.com/quick_start/pricing"
129891
+ },
129892
+ {
129893
+ pattern: "deepseek-chat",
129894
+ contextWindow: 128e3,
129895
+ verified: true,
129896
+ source: "https://api-docs.deepseek.com/quick_start/pricing"
129897
+ },
129898
+ {
129899
+ pattern: "deepseek-v3",
129900
+ contextWindow: 128e3,
129901
+ verified: true,
129902
+ source: "https://api-docs.deepseek.com/quick_start/pricing"
129903
+ },
129904
+ {
129905
+ pattern: "deepseek-r1",
129906
+ contextWindow: 128e3,
129907
+ verified: true,
129908
+ source: "https://api-docs.deepseek.com/quick_start/pricing"
129909
+ },
129910
+ { pattern: "deepseek-vl", vision: true, verified: false },
129911
+ { pattern: "deepseek-coder", contextWindow: 16e3, verified: false },
129912
+ // Qwen / 通义千问(优先使用当前可核验的商业模型 ID)
129913
+ // DashScope 兼容接口 max_tokens 上限为 65536
129914
+ {
129915
+ pattern: "qwen3-coder-plus",
129916
+ contextWindow: 262144,
129917
+ maxOutputTokens: 65536,
129918
+ verified: false
129919
+ },
129920
+ {
129921
+ pattern: "qwen3.6-plus",
129922
+ contextWindow: 1e6,
129923
+ maxOutputTokens: 65536,
129924
+ vision: true,
129925
+ verified: true,
129926
+ source: "https://help.aliyun.com/zh/model-studio/models"
129927
+ },
129928
+ {
129929
+ pattern: "qwen3.5-plus",
129930
+ contextWindow: 1e6,
129931
+ maxOutputTokens: 65536,
129932
+ vision: true,
129933
+ verified: true,
129934
+ source: "https://help.aliyun.com/zh/model-studio/models"
129935
+ },
129936
+ {
129937
+ pattern: "qwen3-max",
129938
+ contextWindow: 262144,
129939
+ maxOutputTokens: 65536,
129940
+ verified: true,
129941
+ source: "https://help.aliyun.com/zh/model-studio/models"
129942
+ },
129943
+ {
129944
+ pattern: "qwen3.6-flash",
129945
+ contextWindow: 1e6,
129946
+ maxOutputTokens: 65536,
129947
+ verified: true,
129948
+ source: "https://help.aliyun.com/zh/model-studio/models"
129949
+ },
129950
+ {
129951
+ pattern: "qwen3.5-flash",
129952
+ contextWindow: 1e6,
129953
+ maxOutputTokens: 65536,
129954
+ verified: true,
129955
+ source: "https://help.aliyun.com/zh/model-studio/models"
129956
+ },
129957
+ {
129958
+ pattern: "qwen3.5-omni-plus",
129959
+ contextWindow: 262144,
129960
+ maxOutputTokens: 65536,
129961
+ vision: true,
129962
+ verified: true,
129963
+ source: "https://help.aliyun.com/zh/model-studio/models"
129964
+ },
129965
+ {
129966
+ pattern: "qwen3.5-omni-flash",
129967
+ contextWindow: 262144,
129968
+ maxOutputTokens: 65536,
129969
+ vision: true,
129970
+ verified: true,
129971
+ source: "https://help.aliyun.com/zh/model-studio/models"
129972
+ },
129973
+ { pattern: "qwen3", maxOutputTokens: 65536, verified: false },
129974
+ { pattern: "qwen2.5-vl", contextWindow: 128e3, maxOutputTokens: 65536, vision: true, verified: false },
129975
+ { pattern: "qwen2-vl", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
129976
+ { pattern: "qwen-vl-max", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
129977
+ { pattern: "qwen-vl-plus", contextWindow: 32768, maxOutputTokens: 65536, vision: true, verified: false },
129978
+ {
129979
+ pattern: "qvq-max",
129980
+ contextWindow: 131072,
129981
+ maxOutputTokens: 65536,
129982
+ vision: true,
129983
+ verified: true,
129984
+ source: "https://help.aliyun.com/zh/model-studio/models"
129985
+ },
129986
+ {
129987
+ pattern: "qvq-plus",
129988
+ contextWindow: 131072,
129989
+ maxOutputTokens: 65536,
129990
+ vision: true,
129991
+ verified: true,
129992
+ source: "https://help.aliyun.com/zh/model-studio/models"
129993
+ },
129994
+ {
129995
+ pattern: "qvq",
129996
+ contextWindow: 131072,
129997
+ maxOutputTokens: 65536,
129998
+ vision: true,
129999
+ verified: true,
130000
+ source: "https://help.aliyun.com/zh/model-studio/models"
130001
+ },
130002
+ { pattern: "qwen-max", contextWindow: 131072, maxOutputTokens: 65536, verified: false },
130003
+ {
130004
+ pattern: "qwen-plus",
130005
+ contextWindow: 1e6,
130006
+ maxOutputTokens: 65536,
130007
+ verified: true,
130008
+ source: "https://help.aliyun.com/zh/model-studio/models"
130009
+ },
130010
+ {
130011
+ pattern: "qwen-flash",
130012
+ contextWindow: 1e6,
130013
+ maxOutputTokens: 65536,
130014
+ verified: true,
130015
+ source: "https://help.aliyun.com/zh/model-studio/models"
130016
+ },
130017
+ {
130018
+ pattern: "qwen-turbo",
130019
+ contextWindow: 1e6,
130020
+ maxOutputTokens: 65536,
130021
+ verified: true,
130022
+ source: "https://help.aliyun.com/zh/model-studio/models"
130023
+ },
130024
+ { pattern: "qwen", maxOutputTokens: 65536, verified: false },
130025
+ // Moonshot / Kimi(官方已核验)
130026
+ {
130027
+ pattern: "kimi-k2.5",
130028
+ contextWindow: 256e3,
130029
+ vision: true,
130030
+ verified: true,
130031
+ source: "https://platform.kimi.ai/docs/models"
130032
+ },
130033
+ {
130034
+ pattern: "kimi-k2-0905-preview",
130035
+ contextWindow: 256e3,
130036
+ verified: true,
130037
+ source: "https://platform.kimi.ai/docs/models"
130038
+ },
130039
+ {
130040
+ pattern: "kimi-k2-turbo-preview",
130041
+ contextWindow: 256e3,
130042
+ verified: true,
130043
+ source: "https://platform.kimi.ai/docs/models"
130044
+ },
130045
+ {
130046
+ pattern: "kimi-k2-thinking-turbo",
130047
+ contextWindow: 256e3,
130048
+ verified: true,
130049
+ source: "https://platform.kimi.ai/docs/models"
130050
+ },
130051
+ {
130052
+ pattern: "kimi-k2-thinking",
130053
+ contextWindow: 256e3,
130054
+ verified: true,
130055
+ source: "https://platform.kimi.ai/docs/models"
130056
+ },
130057
+ {
130058
+ pattern: "kimi-k2-0711-preview",
130059
+ contextWindow: 128e3,
130060
+ verified: true,
130061
+ source: "https://platform.kimi.ai/docs/models"
130062
+ },
130063
+ { pattern: "kimi-k2", contextWindow: 128e3, verified: false },
130064
+ {
130065
+ pattern: "moonshot-v1-128k-vision-preview",
130066
+ contextWindow: 128e3,
130067
+ vision: true,
130068
+ verified: true,
130069
+ source: "https://platform.kimi.ai/docs/models"
130070
+ },
130071
+ {
130072
+ pattern: "moonshot-v1-32k-vision-preview",
130073
+ contextWindow: 32e3,
130074
+ vision: true,
130075
+ verified: true,
130076
+ source: "https://platform.kimi.ai/docs/models"
130077
+ },
130078
+ {
130079
+ pattern: "moonshot-v1-8k-vision-preview",
130080
+ contextWindow: 8192,
130081
+ vision: true,
130082
+ verified: true,
130083
+ source: "https://platform.kimi.ai/docs/models"
130084
+ },
130085
+ {
130086
+ pattern: "moonshot-v1-128k",
130087
+ contextWindow: 128e3,
130088
+ verified: true,
130089
+ source: "https://platform.kimi.ai/docs/models"
130090
+ },
130091
+ {
130092
+ pattern: "moonshot-v1-32k",
130093
+ contextWindow: 32e3,
130094
+ verified: true,
130095
+ source: "https://platform.kimi.ai/docs/models"
130096
+ },
130097
+ {
130098
+ pattern: "moonshot-v1-8k",
130099
+ contextWindow: 8192,
130100
+ verified: true,
130101
+ source: "https://platform.kimi.ai/docs/models"
130102
+ },
130103
+ { pattern: "kimi", contextWindow: 128e3, verified: false },
130104
+ { pattern: "moonshot", contextWindow: 128e3, verified: false },
130105
+ // MiniMax(本轮未核到精确 context,使用保守 fallback,避免伪精确)
130106
+ { pattern: "minimax-vl-01", contextWindow: 128e3, vision: true, verified: false },
130107
+ { pattern: "minimax-text-01", contextWindow: 128e3, verified: false },
130108
+ { pattern: "abab6.5", contextWindow: 2e5, verified: false },
130109
+ { pattern: "abab6.5s", contextWindow: 2e5, verified: false },
130110
+ { pattern: "abab", contextWindow: 2e5, verified: false },
130111
+ { pattern: "minimax-vl", contextWindow: 128e3, vision: true, verified: false },
130112
+ { pattern: "minimax", contextWindow: 128e3, verified: false },
130113
+ // GLM / 智谱(官方已核验)
130114
+ {
130115
+ pattern: "glm-4.5v",
130116
+ contextWindow: 64e3,
130117
+ vision: true,
130118
+ verified: true,
130119
+ source: "https://docs.bigmodel.cn/cn/guide/models/vlm/glm-4.5v"
130120
+ },
130121
+ { pattern: "glm-4v", contextWindow: 128e3, vision: true, verified: false },
130122
+ {
130123
+ pattern: "glm-4.5-air",
130124
+ contextWindow: 128e3,
130125
+ verified: true,
130126
+ source: "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5"
130127
+ },
130128
+ {
130129
+ pattern: "glm-4.5",
130130
+ contextWindow: 128e3,
130131
+ verified: true,
130132
+ source: "https://docs.bigmodel.cn/cn/guide/models/text/glm-4.5"
130133
+ },
130134
+ { pattern: "glm-4-plus", contextWindow: 128e3, verified: false },
130135
+ { pattern: "glm-4", contextWindow: 128e3, verified: false },
130136
+ // Meta Llama / 其他常见开源视觉模型
130137
+ { pattern: "llama-3.2", contextWindow: 128e3, verified: false },
130138
+ { pattern: "llama-3.1", contextWindow: 128e3, verified: false },
130139
+ { pattern: "llama-3", contextWindow: 128e3, verified: false },
130140
+ { pattern: "llama-2", contextWindow: 4096, verified: false },
130141
+ { pattern: "llava", contextWindow: 32768, vision: true, verified: false },
130142
+ { pattern: "internvl", contextWindow: 32768, vision: true, verified: false },
130143
+ { pattern: "minicpm-v", contextWindow: 32768, vision: true, verified: false },
130144
+ { pattern: "pixtral", contextWindow: 128e3, vision: true, verified: false },
130145
+ // 通用兜底关键词(放最后,避免过度误判)
130146
+ { pattern: "vision", vision: true, verified: false },
130147
+ { pattern: "vl", vision: true, verified: false },
130148
+ { pattern: "omni", vision: true, verified: false }
130149
+ ].sort((a, b) => b.pattern.length - a.pattern.length);
130150
+ DEFAULT_CONTEXT_WINDOW = 128e3;
130151
+ MAX_LEARNED_MODELS = 100;
130152
+ ModelCapability = class {
130153
+ learnedWindows = /* @__PURE__ */ new Map();
130154
+ learnedMaxOutputTokens = /* @__PURE__ */ new Map();
130155
+ learnedUpdatedAt = /* @__PURE__ */ new Map();
130156
+ onLearned;
130157
+ setOnLearned(callback) {
130158
+ this.onLearned = callback;
130159
+ }
130160
+ hydrate(snapshot) {
130161
+ this.learnedWindows.clear();
130162
+ this.learnedMaxOutputTokens.clear();
130163
+ this.learnedUpdatedAt.clear();
130164
+ for (const [model, record2] of Object.entries(snapshot.models)) {
130165
+ const normalized = this.normalizeModel(model);
130166
+ if (typeof record2.contextWindow === "number") {
130167
+ this.learnedWindows.set(normalized, record2.contextWindow);
130168
+ }
130169
+ if (typeof record2.maxOutputTokens === "number") {
130170
+ this.learnedMaxOutputTokens.set(normalized, record2.maxOutputTokens);
130171
+ }
130172
+ if (typeof record2.updatedAt === "number") {
130173
+ this.learnedUpdatedAt.set(normalized, record2.updatedAt);
130174
+ }
130175
+ }
130176
+ }
130177
+ snapshot() {
130178
+ const models = {};
130179
+ for (const model of /* @__PURE__ */ new Set([
130180
+ ...this.learnedWindows.keys(),
130181
+ ...this.learnedMaxOutputTokens.keys()
130182
+ ])) {
130183
+ const contextWindow = this.learnedWindows.get(model);
130184
+ const maxOutputTokens = this.learnedMaxOutputTokens.get(model);
130185
+ models[model] = {
130186
+ updatedAt: this.learnedUpdatedAt.get(model) ?? Date.now(),
130187
+ ...contextWindow !== void 0 ? { contextWindow } : {},
130188
+ ...maxOutputTokens !== void 0 ? { maxOutputTokens } : {}
130189
+ };
130190
+ }
130191
+ return { models };
130192
+ }
130193
+ normalizeModel(model) {
130194
+ return model.toLowerCase();
130195
+ }
130196
+ markLearned(model) {
130197
+ this.learnedUpdatedAt.set(model, Date.now());
130198
+ this.cleanup();
130199
+ this.onLearned?.();
130200
+ }
130201
+ findRule(model) {
130202
+ const normalized = this.normalizeModel(model);
130203
+ return MODEL_RULES.find((rule) => normalized.includes(rule.pattern));
130204
+ }
130205
+ /**
130206
+ * 获取模型的上下文窗口大小
130207
+ */
130208
+ getContextWindow(model) {
130209
+ const normalized = this.normalizeModel(model);
130210
+ if (this.learnedWindows.has(normalized)) {
130211
+ return this.learnedWindows.get(normalized);
130212
+ }
130213
+ const rule = this.findRule(model);
130214
+ if (rule?.contextWindow) {
130215
+ return rule.contextWindow;
130216
+ }
130217
+ return DEFAULT_CONTEXT_WINDOW;
130218
+ }
130219
+ /**
130220
+ * 从错误信息中学习上下文窗口大小
130221
+ */
130222
+ learnContextWindow(model, errorMessage) {
130223
+ const patterns = [
130224
+ /maximum input length[:\s]*\(?(\d+)\)?/i,
130225
+ /range of input length should be\s*\[\s*1\s*,\s*(\d+)\s*\]/i,
130226
+ /does not support max tokens\s*>\s*(\d+)/i,
130227
+ /context length is\s*(\d+)/i,
130228
+ /maximum context length[:\s]*(\d+)/i
130229
+ ];
130230
+ for (const pattern of patterns) {
130231
+ const match = errorMessage.match(pattern);
130232
+ if (match?.[1]) {
130233
+ const contextWindow = parseInt(match[1], 10);
130234
+ this.saveContextWindow(model, contextWindow);
130235
+ return contextWindow;
130236
+ }
130237
+ }
130238
+ return void 0;
130239
+ }
130240
+ learnFromError(model, errorMessage) {
130241
+ const learned = {};
130242
+ const contextWindow = this.learnContextWindow(model, errorMessage);
130243
+ const maxOutputTokens = this.learnMaxOutputTokens(model, errorMessage);
130244
+ if (contextWindow !== void 0) learned.contextWindow = contextWindow;
130245
+ if (maxOutputTokens !== void 0) learned.maxOutputTokens = maxOutputTokens;
130246
+ return Object.keys(learned).length ? learned : void 0;
130247
+ }
130248
+ /**
130249
+ * 获取模型允许的最大输出 token 数(用于 clamp maxOutputTokens)
130250
+ */
130251
+ getMaxOutputTokens(model) {
130252
+ const normalized = this.normalizeModel(model);
130253
+ if (this.learnedMaxOutputTokens.has(normalized)) {
130254
+ return this.learnedMaxOutputTokens.get(normalized);
130255
+ }
130256
+ return this.findRule(model)?.maxOutputTokens;
130257
+ }
130258
+ /**
130259
+ * 从错误信息中学习 maxOutputTokens 上限
130260
+ */
130261
+ learnMaxOutputTokens(model, errorMessage) {
130262
+ const patterns = [
130263
+ /Range of max_tokens should be \[1, (\d+)\]/i,
130264
+ /max_tokens.*should be.*?(\d+)/i
130265
+ ];
130266
+ for (const pattern of patterns) {
130267
+ const match = errorMessage.match(pattern);
130268
+ if (match?.[1]) {
130269
+ const maxOutput = parseInt(match[1], 10);
130270
+ const normalized = this.normalizeModel(model);
130271
+ this.learnedMaxOutputTokens.set(normalized, maxOutput);
130272
+ this.markLearned(normalized);
130273
+ logger16.debug(`Learned maxOutputTokens for ${model}: ${maxOutput}`);
130274
+ return maxOutput;
130275
+ }
130276
+ }
130277
+ return void 0;
130278
+ }
130279
+ learnMaxOutputTokensFromError(model, errorMessage) {
130280
+ return this.learnMaxOutputTokens(model, errorMessage) ?? null;
130281
+ }
130282
+ /**
130283
+ * 保存学习到的上下文窗口大小
130284
+ */
130285
+ saveContextWindow(model, contextWindow) {
130286
+ const normalized = this.normalizeModel(model);
130287
+ this.learnedWindows.set(normalized, contextWindow);
130288
+ this.markLearned(normalized);
130289
+ logger16.debug(`Learned context window for ${model}: ${contextWindow} tokens`);
130290
+ }
130291
+ /**
130292
+ * 检测模型是否支持视觉功能
130293
+ */
130294
+ supportsVision(model) {
130295
+ return this.findRule(model)?.vision === true;
130296
+ }
130297
+ /**
130298
+ * 检测是否为图片 MIME 类型
130299
+ */
130300
+ isImageMimeType(mimeType) {
130301
+ return mimeType.startsWith("image/");
130302
+ }
130303
+ /**
130304
+ * 检测所有附件是否都是图片
130305
+ */
130306
+ allAttachmentsAreImages(attachments) {
130307
+ return attachments.length > 0 && attachments.every((a) => this.isImageMimeType(a.mimeType));
130308
+ }
130309
+ /**
130310
+ * 清理过旧的学习记录
130311
+ */
130312
+ cleanup() {
130313
+ while (this.learnedUpdatedAt.size > MAX_LEARNED_MODELS) {
130314
+ const oldest = [...this.learnedUpdatedAt.entries()].sort((a, b) => a[1] - b[1])[0]?.[0];
130315
+ if (!oldest) break;
130316
+ this.learnedWindows.delete(oldest);
130317
+ this.learnedMaxOutputTokens.delete(oldest);
130318
+ this.learnedUpdatedAt.delete(oldest);
130319
+ }
130320
+ }
130321
+ };
130322
+ modelCapability = new ModelCapability();
130323
+ }
130324
+ });
130325
+
130326
+ // src/core/agent/execution/kernel/multimodal.ts
130327
+ var logger17, RECENT_USER_MESSAGE_COUNT, MultimodalTransformer, multimodalTransformer;
130328
+ var init_multimodal = __esm({
130329
+ "src/core/agent/execution/kernel/multimodal.ts"() {
130330
+ "use strict";
130331
+ init_ModelCapability();
130332
+ init_execution_deps();
130333
+ init_logger();
130334
+ logger17 = createLogger("MultimodalTransformer");
130335
+ RECENT_USER_MESSAGE_COUNT = 2;
130336
+ MultimodalTransformer = class {
130337
+ /** data URL 缓存(简单 Map,不做 LRU) */
130338
+ cache = /* @__PURE__ */ new Map();
130339
+ /**
130340
+ * 核心入口:转换 messages 中的图片附件为多模态格式
130341
+ *
130342
+ * - 只转换最近 N 条 role='user' 的 message
130343
+ * - 识别 <attachment mime="image/..."> 占位文本
130344
+ * - 读取文件 → 缩放 → 转为 ImagePart
130345
+ * - 不支持 vision 的模型 → 原样透传
130346
+ * - 非图片附件 → 保留文本标记
130347
+ */
130348
+ async transform(messages, model) {
130349
+ if (!modelCapability.supportsVision(model)) {
130350
+ return messages;
130351
+ }
130352
+ const userIndices = [];
130353
+ for (let i = messages.length - 1; i >= 0; i--) {
130354
+ if (messages[i].role === "user") {
130355
+ userIndices.unshift(i);
130356
+ if (userIndices.length >= RECENT_USER_MESSAGE_COUNT) break;
130357
+ }
130358
+ }
130359
+ if (userIndices.length === 0) return messages;
130360
+ const result = [...messages];
130361
+ for (const idx of userIndices) {
130362
+ const msg = result[idx];
130363
+ if (msg.role !== "user") continue;
130364
+ if (typeof msg.content === "string") {
130365
+ const transformed = await this.transformStringContent(msg.content);
130366
+ if (transformed !== msg.content) {
130367
+ result[idx] = { ...msg, content: transformed };
130368
+ }
130369
+ continue;
130370
+ }
130371
+ if (Array.isArray(msg.content)) {
130372
+ const transformed = await this.transformPartsContent(msg.content);
130373
+ if (transformed !== msg.content) {
130374
+ result[idx] = { ...msg, content: transformed };
130375
+ }
130376
+ }
130377
+ }
130378
+ return result;
130379
+ }
130380
+ /**
130381
+ * 处理 string content — 可能包含 <attachment> 标记或 legacy DSL 块
130382
+ */
130383
+ async transformStringContent(content) {
130384
+ const attachmentRegex = /<attachment\s+mime="([^"]+)"\s+name="([^"]+)">([^<]+)<\/attachment>/g;
130385
+ const matches = [];
130386
+ let hasImage = false;
130387
+ let m;
130388
+ while ((m = attachmentRegex.exec(content)) !== null) {
130389
+ if (m[1].startsWith("image/")) hasImage = true;
130390
+ matches.push({ mime: m[1], name: m[2], path: m[3], index: m.index, fullMatch: m[0] });
130391
+ }
130392
+ if (matches.length > 0) {
130393
+ if (!hasImage) return content;
130394
+ const parts = [];
130395
+ let lastEnd = 0;
130396
+ for (const match of matches) {
130397
+ if (match.index > lastEnd) {
130398
+ parts.push({ type: "text", text: content.slice(lastEnd, match.index) });
130399
+ }
130400
+ if (match.mime.startsWith("image/")) {
130401
+ const image = await this.loadImageDataUrl(match.path);
130402
+ if (image) {
130403
+ parts.push({ type: "image", image });
130404
+ } else {
130405
+ parts.push({ type: "text", text: `[\u56FE\u7247: ${match.name}]` });
130406
+ }
130407
+ } else {
130408
+ parts.push({ type: "text", text: match.fullMatch });
130409
+ }
130410
+ lastEnd = match.index + match.fullMatch.length;
130411
+ }
130412
+ if (lastEnd < content.length) {
130413
+ parts.push({ type: "text", text: content.slice(lastEnd) });
130414
+ }
130415
+ return parts.some((p) => p.type === "image") ? parts : content;
130416
+ }
130417
+ return this.transformLegacyDsl(content);
130418
+ }
130419
+ /**
130420
+ * 兼容 legacy DSL 格式:```attachments\n<file ...>path</file>\n```
130421
+ */
130422
+ async transformLegacyDsl(content) {
130423
+ const blockRegex = /```attachments\n([\s\S]*?)```/g;
130424
+ if (!blockRegex.test(content)) return content;
130425
+ const regex2 = /```attachments\n([\s\S]*?)```/g;
130426
+ const parts = [];
130427
+ let lastEnd = 0;
130428
+ let hasImage = false;
130429
+ let blockMatch;
130430
+ while ((blockMatch = regex2.exec(content)) !== null) {
130431
+ if (blockMatch.index > lastEnd) {
130432
+ parts.push({ type: "text", text: content.slice(lastEnd, blockMatch.index) });
130433
+ }
130434
+ const blockContent = blockMatch[1];
130435
+ const fileRegex = /<file(?:\s+mime="([^"]*)"\s+name="([^"]*)")?>([^<]+)<\/file>/g;
130436
+ let fileMatch;
130437
+ while ((fileMatch = fileRegex.exec(blockContent)) !== null) {
130438
+ const mime = fileMatch[1] || void 0;
130439
+ const name21 = fileMatch[2] || void 0;
130440
+ const path11 = fileMatch[3];
130441
+ const isImage = mime ? mime.startsWith("image/") : /\.(png|jpe?g|gif|webp|bmp|svg)$/i.test(path11);
130442
+ if (isImage) {
130443
+ const image = await this.loadImageDataUrl(path11);
130444
+ if (image) {
130445
+ hasImage = true;
130446
+ parts.push({ type: "image", image });
130447
+ } else {
130448
+ parts.push({ type: "text", text: `[\u56FE\u7247: ${name21 || path11}]` });
130449
+ }
130450
+ } else {
130451
+ parts.push({ type: "text", text: fileMatch[0] });
130452
+ }
130453
+ }
130454
+ lastEnd = blockMatch.index + blockMatch[0].length;
130455
+ }
130456
+ if (lastEnd < content.length) {
130457
+ parts.push({ type: "text", text: content.slice(lastEnd) });
130458
+ }
130459
+ return hasImage ? parts : content;
130460
+ }
130461
+ /**
130462
+ * 处理 Array<TextPart> content — 逐 part 检查 <attachment> 标记
130463
+ */
130464
+ async transformPartsContent(content) {
130465
+ let hasTransformed = false;
130466
+ const result = [];
130467
+ for (const part of content) {
130468
+ if (part.type === "text" && "text" in part && typeof part.text === "string") {
130469
+ const text4 = part.text;
130470
+ const attachment = this.parseInlineAttachment(text4);
130471
+ if (attachment) {
130472
+ if (attachment.isImage) {
130473
+ const image = await this.loadImageDataUrl(attachment.path);
130474
+ if (image) {
130475
+ hasTransformed = true;
130476
+ result.push({ type: "image", image });
130477
+ } else {
130478
+ result.push({ type: "text", text: `[\u56FE\u7247: ${attachment.name}]` });
130479
+ }
130480
+ } else {
130481
+ result.push(part);
130482
+ }
130483
+ continue;
130484
+ }
130485
+ result.push(part);
130486
+ } else if (part.type === "image") {
130487
+ result.push(part);
130488
+ } else if (part.type === "file") {
130489
+ result.push({ type: "text", text: JSON.stringify(part) });
130490
+ }
130491
+ }
130492
+ return hasTransformed ? result : content;
130493
+ }
130494
+ /**
130495
+ * 解析单行 <attachment mime="..." name="...">path</attachment> 标记
130496
+ */
130497
+ parseInlineAttachment(text4) {
130498
+ const m = text4.match(/^<attachment\s+mime="([^"]+)"\s+name="([^"]+)">([^<]+)<\/attachment>$/);
130499
+ if (!m) return null;
130500
+ return {
130501
+ path: m[3],
130502
+ name: m[2],
130503
+ isImage: m[1].startsWith("image/")
130504
+ };
130505
+ }
130506
+ /**
130507
+ * 读取图片附件 → data URL
130508
+ * 带缓存和超时保护
130509
+ */
130510
+ async loadImageDataUrl(relativePath) {
130511
+ const cached2 = this.cache.get(relativePath);
130512
+ if (cached2) return cached2;
130513
+ try {
130514
+ const resolver = resolveAgentExecutionDeps().multimodalAssetResolver;
130515
+ if (!resolver) return null;
130516
+ const image = await resolver.loadImageDataUrl(relativePath);
130517
+ if (image) {
130518
+ this.cache.set(relativePath, image);
130519
+ }
130520
+ return image;
130521
+ } catch (err) {
130522
+ logger17.warn(`Failed to load image asset: ${relativePath}`, err);
130523
+ return null;
130524
+ }
130525
+ }
130526
+ };
130527
+ multimodalTransformer = new MultimodalTransformer();
130528
+ }
130529
+ });
130530
+
130531
+ // src/core/agent/execution/kernel/request-projection.ts
130532
+ function projectRequestMessagesForProvider(messages, modelSettings) {
130533
+ return stripUnsupportedReasoningMetadataForModel(
130534
+ projectOpenAIImageGenerationForForeignProvider(messages, modelSettings.apiType),
130535
+ modelSettings
130536
+ );
130537
+ }
130538
+ function projectOpenAIImageGenerationForForeignProvider(messages, apiType) {
130539
+ if (supportsOpenAIProviderExecutedHistory(apiType)) return messages;
130540
+ let changed = false;
130541
+ const projected = messages.flatMap((message) => {
130542
+ if (message.role !== "assistant" || !Array.isArray(message.content)) return [message];
130543
+ const content = message.content;
130544
+ const generatedImageCount = countOpenAIImageGenerationResults(content);
130545
+ const nextContent = content.filter((part) => {
130546
+ if (isOpenAIImageGenerationToolPart(part)) {
130547
+ changed = true;
130548
+ return false;
130549
+ }
130550
+ return true;
130551
+ });
130552
+ if (generatedImageCount > 0) {
130553
+ changed = true;
130554
+ nextContent.push({
130555
+ type: "text",
130556
+ text: generatedImageCount === 1 ? "\u4E4B\u524D\u5DF2\u751F\u6210\u4E00\u5F20\u56FE\u7247\uFF0C\u5DF2\u4FDD\u5B58\u4E3A\u9644\u4EF6\u3002" : `\u4E4B\u524D\u5DF2\u751F\u6210 ${generatedImageCount} \u5F20\u56FE\u7247\uFF0C\u5DF2\u4FDD\u5B58\u4E3A\u9644\u4EF6\u3002`
130557
+ });
130558
+ }
130559
+ if (nextContent.length === 0) {
130560
+ changed = true;
130561
+ return [];
130562
+ }
130563
+ return [{ ...message, content: nextContent }];
130564
+ });
130565
+ return changed ? projected : messages;
130566
+ }
130567
+ function stripUnsupportedReasoningMetadataForModel(messages, modelSettings) {
130568
+ if (!isGlm51Thinking(modelSettings)) return messages;
130569
+ let changed = false;
130570
+ const sanitized = messages.map((message) => {
130571
+ if (!Array.isArray(message.content)) return message;
130572
+ let contentChanged = false;
130573
+ const content = message.content.map((part) => {
130574
+ if (part.type !== "reasoning") return part;
130575
+ if (!("providerOptions" in part) && !("providerMetadata" in part) && !("experimental_providerMetadata" in part)) {
130576
+ return part;
130577
+ }
130578
+ const {
130579
+ providerOptions: _providerOptions,
130580
+ providerMetadata: _providerMetadata,
130581
+ experimental_providerMetadata: _experimentalProviderMetadata,
130582
+ ...rest
130583
+ } = part;
130584
+ contentChanged = true;
130585
+ changed = true;
130586
+ return rest;
130587
+ });
130588
+ return contentChanged ? { ...message, content } : message;
130589
+ });
130590
+ return changed ? sanitized : messages;
130591
+ }
130592
+ function supportsOpenAIProviderExecutedHistory(apiType) {
130593
+ return apiType?.toLowerCase() === "openai";
130594
+ }
130595
+ function isGlm51Thinking(modelSettings) {
130596
+ return modelSettings.model.toLowerCase().includes("glm-5.1") && Boolean(modelSettings.reasoningEffort && modelSettings.reasoningEffort !== "off");
130597
+ }
130598
+ function countOpenAIImageGenerationResults(content) {
130599
+ return content.filter((part) => {
130600
+ if (part.type !== "tool-result" || part.toolName !== "image_generation") return false;
130601
+ const output = part.output;
130602
+ return Boolean(output && typeof output === "object" && "result" in output);
130603
+ }).length;
130604
+ }
130605
+ function isOpenAIImageGenerationToolPart(part) {
130606
+ if (part.type !== "tool-call" && part.type !== "tool-result") return false;
130607
+ if (part.toolName !== "image_generation") return false;
130608
+ if (part.type === "tool-call") {
130609
+ return part.providerExecuted === true;
130610
+ }
130611
+ const providerOptions = part.providerOptions;
130612
+ const openaiOptions = providerOptions && typeof providerOptions === "object" ? providerOptions.openai : void 0;
130613
+ return Boolean(openaiOptions && typeof openaiOptions === "object");
130614
+ }
130615
+ var init_request_projection = __esm({
130616
+ "src/core/agent/execution/kernel/request-projection.ts"() {
130617
+ "use strict";
130618
+ }
130619
+ });
130620
+
130533
130621
  // src/core/agent/runtime/environmentMessages.ts
130534
130622
  function buildEnvironmentSystem(environment, request) {
130535
130623
  const sessionOwner = environment.session?.owner;
@@ -130657,11 +130745,19 @@ function toDurableMessages(prepared, loopMessages) {
130657
130745
  ...loopMessages.slice(prefixLength + prepared.durableMessageOffset)
130658
130746
  ];
130659
130747
  }
130748
+ function sameWorkerMessages(a, b) {
130749
+ if (a.length !== b.length) return false;
130750
+ for (let i = 0; i < a.length; i += 1) {
130751
+ if (a[i]?.role !== b[i]?.role) return false;
130752
+ if (JSON.stringify(a[i]?.content) !== JSON.stringify(b[i]?.content)) return false;
130753
+ }
130754
+ return true;
130755
+ }
130660
130756
  function joinSystemBlocks(...blocks) {
130661
130757
  const content = blocks.map((block) => block?.trim()).filter((block) => Boolean(block));
130662
130758
  return content.length ? content.join("\n\n") : void 0;
130663
130759
  }
130664
- var compactionLogger, DefaultWorkerContextManager, DefaultWorkerRuntime;
130760
+ var CompactionInputOverflowError, compactionLogger, DefaultWorkerContextManager, DefaultWorkerRuntime;
130665
130761
  var init_WorkerRuntime = __esm({
130666
130762
  "src/core/agent/runtime/WorkerRuntime.ts"() {
130667
130763
  "use strict";
@@ -130669,6 +130765,16 @@ var init_WorkerRuntime = __esm({
130669
130765
  init_types5();
130670
130766
  init_environmentMessages();
130671
130767
  init_runtimeOnlyMessages();
130768
+ CompactionInputOverflowError = class extends Error {
130769
+ constructor(overheadTokens, inputTokenLimit) {
130770
+ super(`Current request overhead exceeds input token limit (${overheadTokens}/${inputTokenLimit})`);
130771
+ this.overheadTokens = overheadTokens;
130772
+ this.inputTokenLimit = inputTokenLimit;
130773
+ this.name = "CompactionInputOverflowError";
130774
+ }
130775
+ overheadTokens;
130776
+ inputTokenLimit;
130777
+ };
130672
130778
  compactionLogger = createStructuredLogger({ scope: "worker-runtime.compaction" });
130673
130779
  DefaultWorkerContextManager = class {
130674
130780
  async prepare(input) {
@@ -130727,34 +130833,64 @@ var init_WorkerRuntime = __esm({
130727
130833
  const replayInput = this.toReplayInput(input);
130728
130834
  const repaired = await this.repairStepBoundaryBudget(prepared, replayInput, loopResult);
130729
130835
  if (!repaired.ok) return repaired.result;
130730
- const repairedLoopResult = await this.deps.loop.run(this.toLoopInput(
130731
- replayInput,
130732
- repaired.prepared.worker,
130733
- repaired.prepared.messages,
130734
- { enableStepBoundaryCheckpoint: false }
130735
- ));
130836
+ const repairedLoopResult = await this.deps.loop.run(
130837
+ this.toLoopInput(replayInput, repaired.prepared.worker, repaired.prepared.messages, { enableStepBoundaryCheckpoint: false })
130838
+ );
130736
130839
  await this.observeTokenUsage(replayInput, repaired.prepared.messages, repairedLoopResult.usage);
130737
130840
  const repairedResult = this.mergeCheckpointRunResult(
130738
130841
  this.toRunResult(repaired.prepared.worker, repairedLoopResult),
130739
130842
  loopResult,
130740
130843
  repairedLoopResult
130741
130844
  );
130742
- if (repairedResult.error?.type === "context_overflow") return repairedResult;
130743
- return this.saveLoopResult(repaired.prepared, repairedLoopResult, repairedResult);
130845
+ if (repairedResult.error?.type === "context_overflow") {
130846
+ const reactiveRepair = await this.repairContextOverflow(
130847
+ repaired.prepared.worker,
130848
+ replayInput,
130849
+ repairedLoopResult.errorDetail
130850
+ );
130851
+ if (!reactiveRepair) return repairedResult;
130852
+ if (!reactiveRepair.ok) return reactiveRepair.result;
130853
+ const reactiveLoopResult = await this.deps.loop.run(
130854
+ this.toLoopInput(replayInput, reactiveRepair.prepared.worker, reactiveRepair.prepared.messages, { enableStepBoundaryCheckpoint: false })
130855
+ );
130856
+ await this.observeTokenUsage(replayInput, reactiveRepair.prepared.messages, reactiveLoopResult.usage);
130857
+ const reactiveResult = this.mergeCheckpointRunResult(
130858
+ this.toRunResult(reactiveRepair.prepared.worker, reactiveLoopResult),
130859
+ loopResult,
130860
+ reactiveLoopResult
130861
+ );
130862
+ if (reactiveResult.error?.type === "context_overflow") return reactiveResult;
130863
+ return this.saveLoopResult(
130864
+ this.withPreparedWorker(reactiveRepair.prepared, reactiveRepair.prepared.worker),
130865
+ reactiveLoopResult,
130866
+ reactiveResult
130867
+ );
130868
+ }
130869
+ return this.saveLoopResult(
130870
+ this.withPreparedWorker(repaired.prepared, repaired.prepared.worker),
130871
+ repairedLoopResult,
130872
+ repairedResult
130873
+ );
130744
130874
  }
130745
130875
  const result = this.toRunResult(prepared.worker, loopResult);
130746
130876
  if (result.error?.type === "context_overflow") {
130747
- if (prepared.compacted) return result;
130877
+ if (prepared.compactionReason === "reactive_context_overflow") return result;
130748
130878
  const repaired = await this.repairContextOverflow(prepared.worker, input, loopResult.errorDetail);
130749
130879
  if (!repaired) return result;
130750
130880
  if (!repaired.ok) return repaired.result;
130751
- const repairedLoopResult = await this.deps.loop.run(this.toLoopInput(input, repaired.prepared.worker, repaired.prepared.messages));
130881
+ const repairedLoopResult = await this.deps.loop.run(
130882
+ this.toLoopInput(input, repaired.prepared.worker, repaired.prepared.messages)
130883
+ );
130752
130884
  await this.observeTokenUsage(input, repaired.prepared.messages, repairedLoopResult.usage);
130753
130885
  const repairedResult = this.toRunResult(repaired.prepared.worker, repairedLoopResult);
130754
130886
  if (repairedResult.error?.type === "context_overflow") return repairedResult;
130755
- return this.saveLoopResult(repaired.prepared, repairedLoopResult, repairedResult);
130887
+ return this.saveLoopResult(
130888
+ this.withPreparedWorker(repaired.prepared, repaired.prepared.worker),
130889
+ repairedLoopResult,
130890
+ repairedResult
130891
+ );
130756
130892
  }
130757
- return this.saveLoopResult(prepared, loopResult, result);
130893
+ return this.saveLoopResult(this.withPreparedWorker(prepared, prepared.worker), loopResult, result);
130758
130894
  }
130759
130895
  async prepareWithProactiveCompaction(worker, input) {
130760
130896
  const prepared = this.sanitizePreparedResult(await this.contextManager.prepare({
@@ -130769,13 +130905,15 @@ var init_WorkerRuntime = __esm({
130769
130905
  if (!this.shouldCompactForBudget(estimatedPreparedTokens)) {
130770
130906
  return { ok: true, prepared };
130771
130907
  }
130772
- const compactedWorker = await this.compactWorker(
130773
- worker,
130908
+ const compaction = await this.compactWorkerSafely(
130909
+ prepared.worker,
130774
130910
  input,
130775
130911
  "proactive_budget",
130776
130912
  void 0,
130777
130913
  estimatedPreparedTokens
130778
130914
  );
130915
+ if (!compaction.ok) return { ok: false, result: compaction.result };
130916
+ const compactedWorker = compaction.value.worker;
130779
130917
  const saveError = await this.saveWorker(compactedWorker);
130780
130918
  if (saveError) return { ok: false, result: saveError };
130781
130919
  const compactedPrepared = this.sanitizePreparedResult(await this.contextManager.prepare({
@@ -130787,23 +130925,35 @@ var init_WorkerRuntime = __esm({
130787
130925
  this.toBudgetMessages(input, compactedPrepared.messages)
130788
130926
  );
130789
130927
  this.emitContextStatus(compactedWorker, compactedPreparedTokens);
130928
+ if (this.exceedsHardInputLimit(compactedPreparedTokens)) {
130929
+ return {
130930
+ ok: false,
130931
+ result: this.toContextOverflowResult(
130932
+ compactedWorker,
130933
+ `Context remains over the input token limit after proactive compaction (${compactedPreparedTokens}/${this.deps.tokenBudget?.inputTokenLimit}).`
130934
+ )
130935
+ };
130936
+ }
130790
130937
  return {
130791
130938
  ok: true,
130792
130939
  prepared: {
130793
130940
  ...compactedPrepared,
130794
- compacted: true
130941
+ compacted: true,
130942
+ compactionReason: "proactive_budget"
130795
130943
  }
130796
130944
  };
130797
130945
  }
130798
130946
  async repairContextOverflow(worker, input, loopError) {
130799
130947
  if (!this.canReactivelyCompact()) return void 0;
130800
130948
  const targetTokenLimit = this.learnReactiveTargetTokenLimit(input.modelSettings, loopError) ?? this.getDefaultCompactionTargetTokenLimit();
130801
- const compactedWorker = await this.compactWorker(
130949
+ const compaction = await this.compactWorkerSafely(
130802
130950
  worker,
130803
130951
  input,
130804
130952
  "reactive_context_overflow",
130805
130953
  targetTokenLimit
130806
130954
  );
130955
+ if (!compaction.ok) return { ok: false, result: compaction.result };
130956
+ const compactedWorker = compaction.value.worker;
130807
130957
  const saveError = await this.saveWorker(compactedWorker);
130808
130958
  if (saveError) return { ok: false, result: saveError };
130809
130959
  const prepared = this.sanitizePreparedResult(await this.contextManager.prepare({
@@ -130815,7 +130965,8 @@ var init_WorkerRuntime = __esm({
130815
130965
  ok: true,
130816
130966
  prepared: {
130817
130967
  ...prepared,
130818
- compacted: true
130968
+ compacted: true,
130969
+ compactionReason: "reactive_context_overflow"
130819
130970
  }
130820
130971
  };
130821
130972
  }
@@ -130827,13 +130978,15 @@ var init_WorkerRuntime = __esm({
130827
130978
  const triggerTokens = await this.estimateCompactionTokensSafely(
130828
130979
  this.toBudgetMessages(replayInput, loopResult.messages)
130829
130980
  );
130830
- const compactedWorker = await this.compactWorker(
130981
+ const compaction = await this.compactWorkerSafely(
130831
130982
  checkpointWorker,
130832
130983
  replayInput,
130833
130984
  "step_boundary_budget",
130834
130985
  void 0,
130835
130986
  triggerTokens
130836
130987
  );
130988
+ if (!compaction.ok) return { ok: false, result: compaction.result };
130989
+ const compactedWorker = compaction.value.worker;
130837
130990
  const saveError = await this.saveWorker(compactedWorker);
130838
130991
  if (saveError) return { ok: false, result: saveError };
130839
130992
  const preparedAfterCompaction = this.sanitizePreparedResult(await this.contextManager.prepare({
@@ -130849,7 +131002,8 @@ var init_WorkerRuntime = __esm({
130849
131002
  ok: true,
130850
131003
  prepared: {
130851
131004
  ...preparedAfterCompaction,
130852
- compacted: true
131005
+ compacted: true,
131006
+ compactionReason: "step_boundary_budget"
130853
131007
  }
130854
131008
  };
130855
131009
  }
@@ -130902,13 +131056,54 @@ var init_WorkerRuntime = __esm({
130902
131056
  });
130903
131057
  }
130904
131058
  }
131059
+ async compactWorkerSafely(worker, input, reason, targetTokenLimitOverride, triggerTokens) {
131060
+ try {
131061
+ return {
131062
+ ok: true,
131063
+ value: await this.compactWorker(worker, input, reason, targetTokenLimitOverride, triggerTokens)
131064
+ };
131065
+ } catch (error48) {
131066
+ if (this.isAbortError(error48) || input.abortSignal?.aborted) {
131067
+ return {
131068
+ ok: false,
131069
+ result: this.toCancelledResult(worker)
131070
+ };
131071
+ }
131072
+ if (error48 instanceof CompactionInputOverflowError) {
131073
+ return {
131074
+ ok: false,
131075
+ result: this.toContextOverflowResult(worker, error48.message)
131076
+ };
131077
+ }
131078
+ return {
131079
+ ok: false,
131080
+ result: this.toCompactionErrorResult(worker, error48)
131081
+ };
131082
+ }
131083
+ }
130905
131084
  async compactWorker(worker, input, reason, targetTokenLimitOverride, triggerTokens) {
130906
131085
  const budget = this.deps.tokenBudget;
130907
131086
  const compactor = this.deps.compactor;
130908
- if (!budget || !compactor) return worker;
131087
+ if (!budget || !compactor) {
131088
+ return {
131089
+ worker,
131090
+ changed: false,
131091
+ skipped: true,
131092
+ targetTokenLimit: targetTokenLimitOverride ?? 0,
131093
+ messageTargetTokenLimit: targetTokenLimitOverride ?? 0
131094
+ };
131095
+ }
130909
131096
  const targetTokenLimit = targetTokenLimitOverride ?? budget.inputTokenLimit * budget.targetRatioAfterCompaction;
130910
131097
  const sanitizedWorker = this.sanitizeWorker(worker);
130911
131098
  const beforeTokens = await this.estimateCompactionTokensSafely(sanitizedWorker.messages);
131099
+ const targetResolution = await this.resolveCompactionMessageTargetTokenLimit(
131100
+ input,
131101
+ targetTokenLimit
131102
+ );
131103
+ if (!targetResolution.ok) {
131104
+ throw new CompactionInputOverflowError(targetResolution.overheadTokens, budget.inputTokenLimit);
131105
+ }
131106
+ const messageTargetTokenLimit = targetResolution.messageTargetTokenLimit;
130912
131107
  const isNoopCompaction = sanitizedWorker.messages.length === 0;
130913
131108
  if (reason === "proactive_budget" && isNoopCompaction) {
130914
131109
  const logger48 = compactionLogger.child({
@@ -130923,7 +131118,16 @@ var init_WorkerRuntime = __esm({
130923
131118
  beforeMessageCount: sanitizedWorker.messages.length,
130924
131119
  ...beforeTokens !== void 0 ? { durableBeforeTokens: beforeTokens } : {}
130925
131120
  });
130926
- return worker;
131121
+ return {
131122
+ worker,
131123
+ changed: false,
131124
+ skipped: true,
131125
+ targetTokenLimit,
131126
+ messageTargetTokenLimit,
131127
+ ...targetResolution.overheadTokens !== void 0 ? { overheadTokens: targetResolution.overheadTokens } : {},
131128
+ ...targetResolution.overheadExceedsTarget !== void 0 ? { overheadExceedsTarget: targetResolution.overheadExceedsTarget } : {},
131129
+ ...beforeTokens !== void 0 ? { beforeTokens } : {}
131130
+ };
130927
131131
  }
130928
131132
  const startedAt = Date.now();
130929
131133
  this.emitCompactionEvent({
@@ -130942,11 +131146,12 @@ var init_WorkerRuntime = __esm({
130942
131146
  worker: sanitizedWorker,
130943
131147
  environment: input.environment,
130944
131148
  request: input.request,
130945
- targetTokenLimit,
131149
+ targetTokenLimit: messageTargetTokenLimit,
130946
131150
  reason
130947
131151
  });
130948
131152
  const compactedWorker = this.sanitizeWorker(result.worker);
130949
131153
  const afterTokens = await this.estimateCompactionTokensSafely(compactedWorker.messages);
131154
+ const changed = !sameWorkerMessages(sanitizedWorker.messages, compactedWorker.messages);
130950
131155
  this.emitCompactionEvent({
130951
131156
  phase: "completed",
130952
131157
  reason,
@@ -130961,7 +131166,16 @@ var init_WorkerRuntime = __esm({
130961
131166
  ...afterTokens !== void 0 ? { durableAfterTokens: afterTokens } : {},
130962
131167
  durationMs: Date.now() - startedAt
130963
131168
  });
130964
- return compactedWorker;
131169
+ return {
131170
+ worker: compactedWorker,
131171
+ changed,
131172
+ targetTokenLimit,
131173
+ messageTargetTokenLimit,
131174
+ ...targetResolution.overheadTokens !== void 0 ? { overheadTokens: targetResolution.overheadTokens } : {},
131175
+ ...targetResolution.overheadExceedsTarget !== void 0 ? { overheadExceedsTarget: targetResolution.overheadExceedsTarget } : {},
131176
+ ...beforeTokens !== void 0 ? { beforeTokens } : {},
131177
+ ...afterTokens !== void 0 ? { afterTokens } : {}
131178
+ };
130965
131179
  } catch (error48) {
130966
131180
  this.emitCompactionEvent({
130967
131181
  phase: "failed",
@@ -130979,6 +131193,25 @@ var init_WorkerRuntime = __esm({
130979
131193
  throw error48;
130980
131194
  }
130981
131195
  }
131196
+ async resolveCompactionMessageTargetTokenLimit(input, preparedTargetTokenLimit) {
131197
+ const overheadTokens = await this.estimateCompactionTokensSafely(
131198
+ this.toBudgetMessages(input, stripRuntimeOnlyMessages(input.request.inputMessages))
131199
+ );
131200
+ if (overheadTokens === void 0) {
131201
+ return { ok: true, messageTargetTokenLimit: preparedTargetTokenLimit };
131202
+ }
131203
+ const budget = this.deps.tokenBudget;
131204
+ if (budget && overheadTokens >= budget.inputTokenLimit) {
131205
+ return { ok: false, reason: "overhead_exceeds_input_limit", overheadTokens };
131206
+ }
131207
+ const overheadExceedsTarget = overheadTokens >= preparedTargetTokenLimit;
131208
+ return {
131209
+ ok: true,
131210
+ messageTargetTokenLimit: Math.max(1, Math.floor(preparedTargetTokenLimit - overheadTokens)),
131211
+ overheadTokens,
131212
+ overheadExceedsTarget
131213
+ };
131214
+ }
130982
131215
  getDefaultCompactionTargetTokenLimit() {
130983
131216
  const budget = this.deps.tokenBudget;
130984
131217
  if (!budget) return void 0;
@@ -130990,7 +131223,17 @@ var init_WorkerRuntime = __esm({
130990
131223
  const errorMessage = loopError.message ?? loopError.kernelError.message;
130991
131224
  const learned = modelCapability2.learnFromError(modelSettings.model, errorMessage);
130992
131225
  if (!learned?.contextWindow) return void 0;
130993
- return Math.floor(learned.contextWindow * 0.5);
131226
+ const maxOutputTokens = modelSettings.maxTokens ?? 0;
131227
+ const learnedInputLimit = Math.max(1, learned.contextWindow - maxOutputTokens);
131228
+ return Math.floor(learnedInputLimit * (this.deps.tokenBudget?.targetRatioAfterCompaction ?? 0.5));
131229
+ }
131230
+ exceedsHardInputLimit(tokens) {
131231
+ const budget = this.deps.tokenBudget;
131232
+ if (!budget || tokens === void 0) return false;
131233
+ return tokens > budget.inputTokenLimit;
131234
+ }
131235
+ isAbortError(error48) {
131236
+ return error48 instanceof Error && error48.name === "AbortError";
130994
131237
  }
130995
131238
  canProactivelyCompact() {
130996
131239
  return Boolean(this.deps.tokenBudget && this.deps.tokenEstimator && this.deps.compactor);
@@ -131089,10 +131332,11 @@ var init_WorkerRuntime = __esm({
131089
131332
  }
131090
131333
  toLoopInput(input, worker, messages, options2 = {}) {
131091
131334
  const enableStepBoundaryCheckpoint = options2.enableStepBoundaryCheckpoint ?? true;
131335
+ const system = this.buildLoopSystem(input);
131092
131336
  return {
131093
131337
  agent: input.agent,
131094
131338
  tools: input.tools,
131095
- system: this.buildLoopSystem(input),
131339
+ system,
131096
131340
  messages: stripRuntimeOnlyMessages(messages),
131097
131341
  modelSettings: input.modelSettings,
131098
131342
  fallbackModelSettings: input.fallbackModelSettings,
@@ -131167,6 +131411,9 @@ var init_WorkerRuntime = __esm({
131167
131411
  messages: stripRuntimeOnlyMessages(worker.messages)
131168
131412
  };
131169
131413
  }
131414
+ withPreparedWorker(prepared, worker) {
131415
+ return { ...prepared, worker };
131416
+ }
131170
131417
  toRunResult(worker, loopResult) {
131171
131418
  return {
131172
131419
  workerId: worker.id,
@@ -131192,6 +131439,51 @@ var init_WorkerRuntime = __esm({
131192
131439
  }
131193
131440
  };
131194
131441
  }
131442
+ toCompactionErrorResult(worker, error48) {
131443
+ return {
131444
+ workerId: worker.id,
131445
+ sessionId: worker.sessionId,
131446
+ messages: worker.messages,
131447
+ steps: [],
131448
+ stopReason: "error",
131449
+ error: {
131450
+ type: "compaction_error",
131451
+ message: error48 instanceof Error ? error48.message : String(error48),
131452
+ cause: error48
131453
+ }
131454
+ };
131455
+ }
131456
+ toCancelledResult(worker) {
131457
+ return {
131458
+ workerId: worker.id,
131459
+ sessionId: worker.sessionId,
131460
+ messages: worker.messages,
131461
+ steps: [],
131462
+ stopReason: "cancelled"
131463
+ };
131464
+ }
131465
+ toContextOverflowResult(worker, message) {
131466
+ return {
131467
+ workerId: worker.id,
131468
+ sessionId: worker.sessionId,
131469
+ messages: worker.messages,
131470
+ steps: [],
131471
+ stopReason: "context_overflow",
131472
+ error: {
131473
+ type: "context_overflow",
131474
+ message,
131475
+ loopError: {
131476
+ type: "context_overflow",
131477
+ message,
131478
+ kernelError: {
131479
+ type: "model_error",
131480
+ failureReason: "context_overflow",
131481
+ message
131482
+ }
131483
+ }
131484
+ }
131485
+ };
131486
+ }
131195
131487
  };
131196
131488
  }
131197
131489
  });
@@ -131219,10 +131511,13 @@ function createWorkerRuntime(deps, options2 = {}) {
131219
131511
  const baseKernel = options2.kernel ?? defaultKernel;
131220
131512
  const kernel = {
131221
131513
  executeStep: async (input) => {
131222
- const requestMessages = await (options2.requestMessageProjector ?? defaultRequestMessageProjector).project(input.messages, input.modelSettings);
131514
+ const projected = await multimodalTransformer.transform(
131515
+ projectRequestMessagesForProvider(input.messages, input.modelSettings),
131516
+ input.modelSettings.model
131517
+ );
131223
131518
  const result = await baseKernel.executeStep({
131224
131519
  ...input,
131225
- requestMessages
131520
+ messages: projected
131226
131521
  });
131227
131522
  recordChannelHealth(deps, input, result);
131228
131523
  return result;
@@ -131252,17 +131547,14 @@ function recordChannelHealth(deps, input, result) {
131252
131547
  }
131253
131548
  deps.channelHealth.recordSuccess(channelId, input.modelSettings.model, result.timeToFirstChunkMs);
131254
131549
  }
131255
- var defaultRequestMessageProjector;
131256
131550
  var init_createWorkerRuntime = __esm({
131257
131551
  "src/core/agent/runtime/createWorkerRuntime.ts"() {
131258
131552
  "use strict";
131259
131553
  init_DefaultAgentLoop();
131260
131554
  init_AgentKernel();
131555
+ init_multimodal();
131556
+ init_request_projection();
131261
131557
  init_WorkerRuntime();
131262
- defaultRequestMessageProjector = {
131263
- // Core runtime defaults to durable messages. Orchestration may inject provider-only projections.
131264
- project: async (messages) => messages
131265
- };
131266
131558
  }
131267
131559
  });
131268
131560
 
@@ -132117,7 +132409,7 @@ var init_MessageCompactor = __esm({
132117
132409
  logger21.debug(
132118
132410
  `model=${model}, contextWindow=${contextWindow}, currentTokens=${currentTokens}, targetTokens=${targetTokens}`
132119
132411
  );
132120
- if (currentTokens <= targetTokens) {
132412
+ if (!this.config.force && currentTokens <= targetTokens) {
132121
132413
  logger21.debug("No compression needed");
132122
132414
  const sanitizedNonSystemMessages = this.sanitizeToolCallPairs(nonSystemMessages);
132123
132415
  return systemMessages.concat(sanitizedNonSystemMessages);
@@ -132311,6 +132603,12 @@ var init_MessageCompactor = __esm({
132311
132603
  }
132312
132604
  calculateTargetTokens(systemMessages, contextWindow) {
132313
132605
  const systemTokens = estimateMessagesTokens(systemMessages);
132606
+ if (this.config.absoluteMessageTargetTokens !== void 0) {
132607
+ const absoluteMessageTarget = Math.floor(this.config.absoluteMessageTargetTokens);
132608
+ if (Number.isFinite(absoluteMessageTarget)) {
132609
+ return Math.max(1, absoluteMessageTarget - systemTokens);
132610
+ }
132611
+ }
132314
132612
  const baseTarget = Math.floor(contextWindow * this.config.targetTokenRatio);
132315
132613
  const dynamicMinTarget = Math.min(32e3, Math.floor(contextWindow * 0.5));
132316
132614
  const toolsReserved = COMPRESSION_CONFIG.TOOLS_RESERVED_TOKENS;
@@ -132519,12 +132817,14 @@ var init_context_compaction = __esm({
132519
132817
  async compact(input) {
132520
132818
  const compactor = new MessageCompactor(
132521
132819
  this.agentId,
132522
- (model) => this.getEffectiveContextWindow(model, input.targetTokenLimit),
132820
+ (model) => this.getContextWindow(model),
132523
132821
  this.createSummaryLanguageModel(),
132524
132822
  {
132525
132823
  targetTokenRatio: 1,
132824
+ absoluteMessageTargetTokens: input.targetTokenLimit,
132526
132825
  ...this.compactorConfig?.keepRecentCount !== void 0 ? { keepRecentCount: this.compactorConfig.keepRecentCount } : {},
132527
- ...this.compactorConfig?.summaryTips ? { summaryTips: this.compactorConfig.summaryTips } : {}
132826
+ ...this.compactorConfig?.summaryTips ? { summaryTips: this.compactorConfig.summaryTips } : {},
132827
+ ...this.compactorConfig?.force !== void 0 ? { force: this.compactorConfig.force } : {}
132528
132828
  }
132529
132829
  );
132530
132830
  const messages = await compactor.compact(
@@ -132553,10 +132853,6 @@ var init_context_compaction = __esm({
132553
132853
  getContextWindow(model) {
132554
132854
  return this.modelCapability?.getContextWindow(model) ?? DEFAULT_CONTEXT_WINDOW2;
132555
132855
  }
132556
- getEffectiveContextWindow(model, targetTokenLimit) {
132557
- const providerWindow = this.getContextWindow(model);
132558
- return Math.max(1, Math.min(providerWindow, Math.floor(targetTokenLimit)));
132559
- }
132560
132856
  };
132561
132857
  }
132562
132858
  });
@@ -132587,6 +132883,29 @@ var init_default_worker_compaction_options = __esm({
132587
132883
  }
132588
132884
  });
132589
132885
 
132886
+ // src/shared/llm-api-type.ts
132887
+ function resolveForcedApiType(model) {
132888
+ const modelId = model.split("/").pop() ?? model;
132889
+ if (/^claude-/i.test(modelId)) return "anthropic";
132890
+ if (/^gemini-/i.test(modelId)) return "google";
132891
+ if (/^gpt-[5-9]/i.test(modelId)) return "openai";
132892
+ return void 0;
132893
+ }
132894
+ function resolveEffectiveApiType(input) {
132895
+ const forced = resolveForcedApiType(input.model);
132896
+ if (forced) return forced;
132897
+ if (!input.configuredApiType || input.configuredApiType === "auto") {
132898
+ return resolveApiType(input.model);
132899
+ }
132900
+ return input.configuredApiType;
132901
+ }
132902
+ var init_llm_api_type = __esm({
132903
+ "src/shared/llm-api-type.ts"() {
132904
+ "use strict";
132905
+ init_types4();
132906
+ }
132907
+ });
132908
+
132590
132909
  // src/core/agent/runtime/agent-model-settings-resolver.ts
132591
132910
  function resolveAgentModelSettings(input) {
132592
132911
  const configView = AgentConfig.from(input.agentConfig);
@@ -132654,10 +132973,17 @@ function selectFallbackEntries(input, triedKey, allowUnhealthy) {
132654
132973
  }
132655
132974
  function toModelSettings(input) {
132656
132975
  const requestDefaults = input.config.models.requestDefaults;
132976
+ const configuredApiType = input.channel?.apiType;
132977
+ const effectiveApiType = resolveEffectiveApiType({
132978
+ model: input.model,
132979
+ configuredApiType
132980
+ });
132657
132981
  return {
132658
132982
  channelId: input.channel?.id,
132659
132983
  model: input.model,
132660
- apiType: input.channel?.apiType,
132984
+ configuredApiType,
132985
+ effectiveApiType,
132986
+ apiType: configuredApiType,
132661
132987
  baseUrl: input.channel?.baseUrl,
132662
132988
  apiKey: input.channel?.apiKey,
132663
132989
  temperature: requestDefaults.temperature,
@@ -132675,6 +133001,7 @@ var init_agent_model_settings_resolver = __esm({
132675
133001
  "use strict";
132676
133002
  init_AgentConfigModel();
132677
133003
  init_agentConfigUtils();
133004
+ init_llm_api_type();
132678
133005
  }
132679
133006
  });
132680
133007
 
@@ -132696,7 +133023,7 @@ var init_conversation_event_bus = __esm({
132696
133023
  this.subscribers.delete(handler);
132697
133024
  };
132698
133025
  }
132699
- emitSnapshot(sessionId, conversation, memberAgentIds, messages, hasMore, queue) {
133026
+ emitSnapshot(sessionId, conversation, memberAgentIds, messages, hasMore, queue, runtime) {
132700
133027
  this.dispatch({
132701
133028
  type: "snapshot",
132702
133029
  sessionId,
@@ -132705,7 +133032,8 @@ var init_conversation_event_bus = __esm({
132705
133032
  memberAgentIds,
132706
133033
  messages,
132707
133034
  hasMore,
132708
- queue
133035
+ queue,
133036
+ runtime
132709
133037
  });
132710
133038
  }
132711
133039
  emit(event) {
@@ -132844,7 +133172,6 @@ function createAgentWorkerRuntimeRunner(deps, options2 = {}) {
132844
133172
  modelCapability: resolvedDeps.modelCapability,
132845
133173
  onBlock: options2.onBlock,
132846
133174
  toolRepairPolicy: options2.toolRepairPolicy,
132847
- requestMessageProjector: options2.requestMessageProjector ?? agentWorkerRequestMessageProjector,
132848
133175
  ...createDefaultWorkerCompactionOptions({
132849
133176
  agentId: agent.id,
132850
133177
  modelSettings: resolvedModels.modelSettings,
@@ -132978,7 +133305,6 @@ function createSystemPromptSnapshotSink(deps, scope) {
132978
133305
  sessionId: scope.session.sessionId
132979
133306
  });
132980
133307
  }
132981
- var agentWorkerRequestMessageProjector;
132982
133308
  var init_agent_worker_runtime_runner = __esm({
132983
133309
  "src/core/agent/orchestration/agent-worker-runtime-runner.ts"() {
132984
133310
  "use strict";
@@ -132987,8 +133313,6 @@ var init_agent_worker_runtime_runner = __esm({
132987
133313
  init_SkillListingInjector();
132988
133314
  init_execution();
132989
133315
  init_execution_deps();
132990
- init_multimodal();
132991
- init_request_projection();
132992
133316
  init_prompts();
132993
133317
  init_createWorkerRuntime();
132994
133318
  init_default_worker_compaction_options();
@@ -132997,12 +133321,6 @@ var init_agent_worker_runtime_runner = __esm({
132997
133321
  init_runtimeOnlyMessages();
132998
133322
  init_conversation_event_compaction_observer();
132999
133323
  init_runtime2();
133000
- agentWorkerRequestMessageProjector = {
133001
- project: (messages, modelSettings) => multimodalTransformer.transform(
133002
- projectRequestMessagesForProvider(messages, modelSettings),
133003
- modelSettings.model
133004
- )
133005
- };
133006
133324
  }
133007
133325
  });
133008
133326
 
@@ -133071,7 +133389,7 @@ function toReplyError(error48) {
133071
133389
  return replyError;
133072
133390
  }
133073
133391
  function getWorkerRunErrorCause(error48) {
133074
- return error48.type === "persistence_error" ? error48.cause : void 0;
133392
+ return error48.type === "persistence_error" || error48.type === "compaction_error" ? error48.cause : void 0;
133075
133393
  }
133076
133394
  function extractKernelError(error48) {
133077
133395
  if (error48.type !== "loop_error" && error48.type !== "context_overflow") return void 0;
@@ -135175,8 +135493,6 @@ var init_SwarmWorkerRuntimeRunner = __esm({
135175
135493
  init_default_worker_compaction_options();
135176
135494
  init_conversation_event_compaction_observer();
135177
135495
  init_agent_model_settings_resolver();
135178
- init_multimodal();
135179
- init_request_projection();
135180
135496
  init_execute_step_mapper();
135181
135497
  SwarmWorkerRuntimeRunner = class {
135182
135498
  constructor(deps) {
@@ -135199,12 +135515,6 @@ var init_SwarmWorkerRuntimeRunner = __esm({
135199
135515
  contextStatusObserver: conversationEventCompactionObserver
135200
135516
  }
135201
135517
  }),
135202
- requestMessageProjector: {
135203
- project: async (messages, modelSettings) => multimodalTransformer.transform(
135204
- projectRequestMessagesForProvider(messages, modelSettings),
135205
- modelSettings.model
135206
- )
135207
- },
135208
135518
  systemPromptSnapshotSink: this.deps.agentDeps.createSystemPromptSnapshotSink?.({
135209
135519
  type: "group",
135210
135520
  groupId: this.deps.groupId,
@@ -135503,7 +135813,7 @@ var init_SwarmExecutor = __esm({
135503
135813
  currentMessageCount: current.length,
135504
135814
  durableMessageCount: durable.length
135505
135815
  });
135506
- return current;
135816
+ return current.slice(durable.length);
135507
135817
  }
135508
135818
  }
135509
135819
  return current.slice(durable.length);
@@ -135636,12 +135946,16 @@ var init_SwarmExecutor = __esm({
135636
135946
  createSwarmWorkerId() {
135637
135947
  return `${this.toWorkerIdSegment(this.session.sessionId)}__swarm`;
135638
135948
  }
135949
+ getSwarmWorkerStateKey(workerId, agentId) {
135950
+ return `${workerId}::${agentId}`;
135951
+ }
135639
135952
  toWorkerIdSegment(value) {
135640
135953
  return value.replace(/[^a-zA-Z0-9._-]/g, "_");
135641
135954
  }
135642
135955
  createGroupSessionWorkerStore(agentId) {
135643
135956
  const workerId = this.createSwarmWorkerId();
135644
135957
  const sessionId = this.session.sessionId;
135958
+ const workerStateKey = this.getSwarmWorkerStateKey(workerId, agentId);
135645
135959
  return {
135646
135960
  load: async (id) => {
135647
135961
  if (id !== workerId) return void 0;
@@ -137597,7 +137911,8 @@ var init_MessageProcessor = __esm({
137597
137911
  sessionId,
137598
137912
  senderId: agentId,
137599
137913
  senderRole: "agent",
137600
- blocks
137914
+ blocks,
137915
+ status: "streaming"
137601
137916
  },
137602
137917
  { id: aiMessageId, createdAt, updatedAt: Date.now() }
137603
137918
  );
@@ -137611,6 +137926,11 @@ var init_MessageProcessor = __esm({
137611
137926
  isGroupSession
137612
137927
  };
137613
137928
  this.messageQueue?.registerRunId(ctx.runId, sessionId);
137929
+ this.messageQueue?.registerActiveRunSnapshot(sessionId, {
137930
+ runId: ctx.runId,
137931
+ messageId: aiMessageId,
137932
+ startedAt: startTime
137933
+ });
137614
137934
  log16.noise(`runId=${ctx.runId}, agentId=${agentId}, isGroupSession=${isGroupSession}`);
137615
137935
  try {
137616
137936
  return await this.executeAgent(ctx);
@@ -137681,6 +138001,11 @@ var init_MessageProcessor = __esm({
137681
138001
  ctx.model = info.model;
137682
138002
  ctx.fallback = info.fallback;
137683
138003
  ctx.fallbackTransition = info.fallbackTransition;
138004
+ this.messageQueue?.updateActiveRunSnapshot(sessionId, {
138005
+ model: info.model,
138006
+ fallback: info.fallback,
138007
+ fallbackTransition: info.fallbackTransition
138008
+ });
137684
138009
  eventBus.emit({
137685
138010
  type: "run.progress",
137686
138011
  sessionId,
@@ -137693,6 +138018,9 @@ var init_MessageProcessor = __esm({
137693
138018
  });
137694
138019
  chat.onUsageUpdate((usage2) => {
137695
138020
  ctx.streamingUsage = usage2;
138021
+ this.messageQueue?.updateActiveRunSnapshot(sessionId, {
138022
+ usage: normalizeUsage(usage2)
138023
+ });
137696
138024
  });
137697
138025
  const PROGRESS_INTERVAL_MS = 3e3;
137698
138026
  ctx.progressTimer = setInterval(() => {
@@ -137728,6 +138056,7 @@ var init_MessageProcessor = __esm({
137728
138056
  durationMs,
137729
138057
  model,
137730
138058
  fallback,
138059
+ status: "completed",
137731
138060
  metadata: metadata?.intent ? { intent: metadata.intent } : void 0,
137732
138061
  updatedAt: Date.now()
137733
138062
  });
@@ -137742,6 +138071,7 @@ var init_MessageProcessor = __esm({
137742
138071
  durationMs,
137743
138072
  model,
137744
138073
  fallback,
138074
+ status: "completed",
137745
138075
  metadata: metadata?.intent ? { intent: metadata.intent } : void 0
137746
138076
  },
137747
138077
  { id: aiMessageId, createdAt, updatedAt: Date.now() }
@@ -137785,7 +138115,7 @@ var init_MessageProcessor = __esm({
137785
138115
  if (err instanceof DOMException ? err.name === "AbortError" : err instanceof Error && err.name === "AbortError") {
137786
138116
  if (streamingBlocks.length > 0) {
137787
138117
  ctx.streamingBlocks = settlePendingBlocks(streamingBlocks);
137788
- await this.persistErrorMessage(ctx);
138118
+ await this.persistTerminalMessage(ctx, "cancelled");
137789
138119
  }
137790
138120
  eventBus.emit({
137791
138121
  type: "run.stopped",
@@ -137818,7 +138148,7 @@ var init_MessageProcessor = __esm({
137818
138148
  };
137819
138149
  }
137820
138150
  const chatError = buildChatError(err, retryCount, MAX_RETRIES);
137821
- await this.persistErrorMessage(ctx, chatError);
138151
+ await this.persistTerminalMessage(ctx, "failed", chatError);
137822
138152
  const durationMs = Date.now() - startTime;
137823
138153
  eventBus.emit({
137824
138154
  type: "run.failed",
@@ -137834,9 +138164,11 @@ var init_MessageProcessor = __esm({
137834
138164
  }
137835
138165
  }
137836
138166
  /**
137837
- * 持久化错误消息到数据库
138167
+ * 持久化明确 Run terminal 分支上的消息状态。
138168
+ *
138169
+ * 这里只携带 Run lifecycle 已经确定的 status,不从 blocks/error/content 推导 status。
137838
138170
  */
137839
- async persistErrorMessage(ctx, error48) {
138171
+ async persistTerminalMessage(ctx, status, error48) {
137840
138172
  const { sessionId, aiMessageId, createdAt, startTime, streamingBlocks, agentId, model, fallback, metadata, streamingUsage } = ctx;
137841
138173
  const durationMs = Date.now() - startTime;
137842
138174
  const { messageRepository: messageRepository2 } = resolveMessageDeps();
@@ -137846,6 +138178,7 @@ var init_MessageProcessor = __esm({
137846
138178
  if (ctx.persistScheduler.hasPersistedSkeleton) {
137847
138179
  await messageRepository2.update(aiMessageId, {
137848
138180
  blocks: streamingBlocks,
138181
+ status,
137849
138182
  ...error48 ? { error: error48 } : {},
137850
138183
  durationMs,
137851
138184
  model,
@@ -137861,6 +138194,7 @@ var init_MessageProcessor = __esm({
137861
138194
  senderId: agentId,
137862
138195
  senderRole: "agent",
137863
138196
  blocks: streamingBlocks,
138197
+ status,
137864
138198
  ...error48 ? { error: error48 } : {},
137865
138199
  durationMs,
137866
138200
  model,
@@ -138000,6 +138334,8 @@ var init_MessageQueue = __esm({
138000
138334
  // runId → sessionId
138001
138335
  sessionRunIdMap = /* @__PURE__ */ new Map();
138002
138336
  // sessionId → runId
138337
+ activeRunSnapshotMap = /* @__PURE__ */ new Map();
138338
+ // sessionId → active run runtime snapshot
138003
138339
  timers = /* @__PURE__ */ new Map();
138004
138340
  isDestroyed = false;
138005
138341
  processingSet = /* @__PURE__ */ new Set();
@@ -138055,14 +138391,29 @@ var init_MessageQueue = __esm({
138055
138391
  this.runIdMap.set(runId, sessionId);
138056
138392
  this.sessionRunIdMap.set(sessionId, runId);
138057
138393
  }
138394
+ registerActiveRunSnapshot(sessionId, snapshot) {
138395
+ this.activeRunSnapshotMap.set(sessionId, snapshot);
138396
+ }
138397
+ updateActiveRunSnapshot(sessionId, patch) {
138398
+ const current = this.activeRunSnapshotMap.get(sessionId);
138399
+ if (!current) return;
138400
+ this.activeRunSnapshotMap.set(sessionId, { ...current, ...patch });
138401
+ }
138058
138402
  unregisterRunId(runId) {
138059
138403
  const sessionId = this.runIdMap.get(runId);
138060
- if (sessionId) this.sessionRunIdMap.delete(sessionId);
138404
+ if (sessionId) {
138405
+ this.sessionRunIdMap.delete(sessionId);
138406
+ const activeRun = this.activeRunSnapshotMap.get(sessionId);
138407
+ if (activeRun?.runId === runId) this.activeRunSnapshotMap.delete(sessionId);
138408
+ }
138061
138409
  this.runIdMap.delete(runId);
138062
138410
  }
138063
138411
  getActiveRunIdBySessionId(sessionId) {
138064
138412
  return this.sessionRunIdMap.get(sessionId);
138065
138413
  }
138414
+ getActiveRunSnapshot(sessionId) {
138415
+ return this.activeRunSnapshotMap.get(sessionId);
138416
+ }
138066
138417
  emitQueueUpdated(sessionId) {
138067
138418
  const pending = this.queueMap.get(sessionId)?.length || 0;
138068
138419
  const running = this.processingSet.has(sessionId);
@@ -138072,7 +138423,7 @@ var init_MessageQueue = __esm({
138072
138423
  eventBus.emit({
138073
138424
  type: "queue.updated",
138074
138425
  sessionId,
138075
- queue: { pending, running }
138426
+ queue: { pending, running, activeRunId: this.sessionRunIdMap.get(sessionId) }
138076
138427
  });
138077
138428
  }
138078
138429
  startConsume(sessionId, retryCount = 0) {
@@ -138299,6 +138650,7 @@ var init_MessagePublisher = __esm({
138299
138650
  senderId: "user",
138300
138651
  senderRole: "user",
138301
138652
  blocks,
138653
+ status: "completed",
138302
138654
  metadata: options2.metadata
138303
138655
  });
138304
138656
  this.emitAccepted(message, options2.clientRequestId);
@@ -138338,6 +138690,7 @@ var init_MessagePublisher = __esm({
138338
138690
  senderId: "system",
138339
138691
  senderRole: "agent",
138340
138692
  blocks: [],
138693
+ status: "completed",
138341
138694
  isContextMarker: true
138342
138695
  }, transaction);
138343
138696
  this.emitAccepted(message);
@@ -138366,7 +138719,8 @@ var init_MessagePublisher = __esm({
138366
138719
  sessionId,
138367
138720
  senderId,
138368
138721
  senderRole: "user",
138369
- blocks
138722
+ blocks,
138723
+ status: "completed"
138370
138724
  });
138371
138725
  this.emitAccepted(message, options2.clientRequestId);
138372
138726
  if (options2.targetAgentId) {
@@ -138394,7 +138748,8 @@ var init_MessagePublisher = __esm({
138394
138748
  sessionId,
138395
138749
  senderId: "system",
138396
138750
  senderRole: "system",
138397
- blocks
138751
+ blocks,
138752
+ status: "completed"
138398
138753
  });
138399
138754
  this.emitAccepted(message, options2.clientRequestId);
138400
138755
  log19.noise(`published local system message, id=${message.id}, sessionId=${sessionId}`);
@@ -139944,37 +140299,69 @@ var init_scheduler = __esm({
139944
140299
  }
139945
140300
  });
139946
140301
 
139947
- // src/adapters/scheduler/ConversationExecutor.ts
139948
- async function resolveGroupTarget(groupId, sessionId, taskAgentId) {
139949
- if (sessionId) {
139950
- const session = await sessionFileStore.findById(sessionId);
139951
- if (!session) return null;
140302
+ // src/adapters/scheduler/scheduled-task-target.ts
140303
+ async function resolveScheduledTaskTarget(task) {
140304
+ if (task.type === "agent") {
140305
+ if (task.sessionId) {
140306
+ const session = await directSessionFileStore.findById(task.sessionId);
140307
+ if (!session || session.owner.agentId !== task.agentId) return null;
140308
+ return {
140309
+ kind: "agent-session",
140310
+ agentId: task.agentId,
140311
+ sessionId: session.id,
140312
+ targetAgentId: task.agentId,
140313
+ source: "explicit"
140314
+ };
140315
+ }
139952
140316
  return {
139953
- targetSessionId: session.id,
139954
- targetAgentId: taskAgentId || session.speakerId
140317
+ kind: "agent-session",
140318
+ agentId: task.agentId,
140319
+ sessionId: await resolveDirectSessionId(task.agentId),
140320
+ targetAgentId: task.agentId,
140321
+ source: "legacy-default"
139955
140322
  };
139956
140323
  }
139957
- const defaultSession = await sessionFileStore.findDefaultByGroupId(groupId);
139958
- if (!defaultSession) return null;
139959
- return {
139960
- targetSessionId: defaultSession.id,
139961
- targetAgentId: taskAgentId || defaultSession.speakerId
139962
- };
139963
- }
139964
- async function resolveAgentTarget(agentId) {
139965
- const targetSessionId = await resolveDirectSessionId(agentId);
139966
- return {
139967
- targetSessionId,
139968
- targetAgentId: agentId
139969
- };
140324
+ if (task.type === "group") {
140325
+ if (task.sessionId) {
140326
+ const session = await sessionFileStore.findById(task.sessionId);
140327
+ if (!session || getGroupOwnerId(session) !== task.groupId) return null;
140328
+ return {
140329
+ kind: "group-session",
140330
+ groupId: task.groupId,
140331
+ sessionId: session.id,
140332
+ targetAgentId: session.speakerId,
140333
+ source: "explicit"
140334
+ };
140335
+ }
140336
+ const defaultSession = await sessionFileStore.findDefaultByGroupId(task.groupId);
140337
+ if (!defaultSession) return null;
140338
+ return {
140339
+ kind: "group-session",
140340
+ groupId: task.groupId,
140341
+ sessionId: defaultSession.id,
140342
+ targetAgentId: defaultSession.speakerId,
140343
+ source: "legacy-default"
140344
+ };
140345
+ }
140346
+ return null;
139970
140347
  }
140348
+ var init_scheduled_task_target = __esm({
140349
+ "src/adapters/scheduler/scheduled-task-target.ts"() {
140350
+ "use strict";
140351
+ init_types4();
140352
+ init_agent_file_store();
140353
+ init_direct_session_file_store();
140354
+ init_session_file_store();
140355
+ }
140356
+ });
140357
+
140358
+ // src/adapters/scheduler/ConversationExecutor.ts
139971
140359
  var ConversationExecutor;
139972
140360
  var init_ConversationExecutor = __esm({
139973
140361
  "src/adapters/scheduler/ConversationExecutor.ts"() {
139974
140362
  "use strict";
139975
140363
  init_MessagePublisher();
139976
- init_session_file_store();
139977
- init_agent_file_store();
140364
+ init_scheduled_task_target();
139978
140365
  ConversationExecutor = class {
139979
140366
  type = "agent";
139980
140367
  // registered for both 'agent' and 'group'
@@ -139984,14 +140371,9 @@ var init_ConversationExecutor = __esm({
139984
140371
  }
139985
140372
  const message = task.message?.trim();
139986
140373
  if (!message) return { success: false, error: "message required" };
139987
- let target = null;
139988
- if (task.type === "agent") {
139989
- target = await resolveAgentTarget(task.agentId);
139990
- } else if (task.type === "group") {
139991
- target = await resolveGroupTarget(task.groupId, task.sessionId);
139992
- }
140374
+ const target = await resolveScheduledTaskTarget(task);
139993
140375
  if (!target) {
139994
- const desc = task.type === "agent" ? `agent: ${task.agentId}` : `group: ${task.groupId}, session: ${task.sessionId || "default"}`;
140376
+ const desc = task.type === "agent" ? `agent: ${task.agentId}, session: ${task.sessionId || "legacy-default"}` : `group: ${task.groupId}, session: ${task.sessionId || "default"}`;
139995
140377
  return {
139996
140378
  success: false,
139997
140379
  error: `Cannot resolve target for ${desc}`
@@ -139999,14 +140381,14 @@ var init_ConversationExecutor = __esm({
139999
140381
  }
140000
140382
  const blocks = [{ type: "text", text: message }];
140001
140383
  await messagePublisher.publishUserMessage(
140002
- target.targetSessionId,
140384
+ target.sessionId,
140003
140385
  blocks,
140004
140386
  { targetAgentId: target.targetAgentId }
140005
140387
  );
140006
140388
  ctx.logger.log(
140007
- `[ConversationExecutor] task=${task.id} type=${task.type} target=${target.targetSessionId} agent=${target.targetAgentId ?? "none"}`
140389
+ `[ConversationExecutor] task=${task.id} type=${task.type} target=${target.sessionId} agent=${target.targetAgentId ?? "none"} source=${target.source}`
140008
140390
  );
140009
- return { success: true, output: `Sent to ${target.targetSessionId}` };
140391
+ return { success: true, output: `Sent to ${target.sessionId}` };
140010
140392
  }
140011
140393
  };
140012
140394
  }
@@ -194241,6 +194623,22 @@ init_sequelize();
194241
194623
  init_lib();
194242
194624
  init_id2();
194243
194625
  init_models();
194626
+
194627
+ // src/shared/message-status.ts
194628
+ var MESSAGE_STATUS_VALUES = /* @__PURE__ */ new Set([
194629
+ "streaming",
194630
+ "completed",
194631
+ "failed",
194632
+ "cancelled"
194633
+ ]);
194634
+ function isMessageStatus(value) {
194635
+ return typeof value === "string" && MESSAGE_STATUS_VALUES.has(value);
194636
+ }
194637
+ function parseMessageStatus(value) {
194638
+ return isMessageStatus(value) ? value : void 0;
194639
+ }
194640
+
194641
+ // src/adapters/db/repositories/MessageRepository.ts
194244
194642
  init_sequelize();
194245
194643
  var MessageRepositoryImpl = class {
194246
194644
  async insertWithId(message, options2) {
@@ -194257,6 +194655,7 @@ var MessageRepositoryImpl = class {
194257
194655
  timestamp,
194258
194656
  updatedAt: options2?.updatedAt ?? timestamp,
194259
194657
  error: message.error,
194658
+ status: message.status,
194260
194659
  isContextMarker: message.isContextMarker ?? false,
194261
194660
  compressionMetadata: message.compressionMetadata,
194262
194661
  usage: message.usage,
@@ -194383,6 +194782,7 @@ var MessageRepositoryImpl = class {
194383
194782
  timestamp,
194384
194783
  updatedAt: timestamp,
194385
194784
  error: message.error,
194785
+ status: message.status,
194386
194786
  isContextMarker: message.isContextMarker ?? false,
194387
194787
  compressionMetadata: message.compressionMetadata,
194388
194788
  usage: message.usage,
@@ -194409,6 +194809,7 @@ var MessageRepositoryImpl = class {
194409
194809
  createdAt: timestamp,
194410
194810
  updatedAt: timestamp,
194411
194811
  error: message.error,
194812
+ status: message.status,
194412
194813
  isContextMarker: message.isContextMarker,
194413
194814
  compressionMetadata: message.compressionMetadata,
194414
194815
  usage: message.usage,
@@ -194465,6 +194866,7 @@ var MessageRepositoryImpl = class {
194465
194866
  createdAt: msg.timestamp.getTime(),
194466
194867
  updatedAt: msg.updatedAt?.getTime() ?? msg.timestamp.getTime(),
194467
194868
  error: msg.error ?? void 0,
194869
+ status: parseMessageStatus(msg.status),
194468
194870
  isContextMarker: msg.isContextMarker ?? void 0,
194469
194871
  compressionMetadata: msg.compressionMetadata ?? void 0,
194470
194872
  usage: msg.usage ?? void 0,
@@ -195391,9 +195793,25 @@ var SessionStorage = class {
195391
195793
  bytes
195392
195794
  });
195393
195795
  }
195796
+ getAgentWorkerStatePath(sessionId, agentId) {
195797
+ const contextPath = this.getAgentContextPath(sessionId, agentId);
195798
+ return import_path13.default.join(import_path13.default.dirname(contextPath), "worker-state.json");
195799
+ }
195800
+ async getWorkerState(workerId) {
195801
+ const parsed = this.parseDirectWorkerStateId(workerId);
195802
+ if (!parsed) return void 0;
195803
+ return { agentId: parsed.agentId, sessionId: parsed.sessionId };
195804
+ }
195805
+ async saveWorkerState(_worker) {
195806
+ }
195394
195807
  isLegacyDirectSessionId(sessionId) {
195395
195808
  return !sessionId.startsWith("sess_");
195396
195809
  }
195810
+ parseDirectWorkerStateId(workerId) {
195811
+ const [kind, agentId, sessionId] = workerId.split(":");
195812
+ if (kind !== "direct" || !agentId) return void 0;
195813
+ return { agentId, sessionId: sessionId ?? agentId };
195814
+ }
195397
195815
  // ---------------------------------------------------------------------------
195398
195816
  // 群聊:groups/{groupId}/sessions/{sessionId}/context.json
195399
195817
  // ---------------------------------------------------------------------------
@@ -195480,11 +195898,12 @@ var DirectAgentWorkerStore = class {
195480
195898
  const directWorker = parseDirectWorkerId(workerId);
195481
195899
  if (!directWorker) return void 0;
195482
195900
  const sessionId = await this.resolveCanonicalSessionId(directWorker);
195901
+ const messages = await this.contextStore.getAgentContext(sessionId, directWorker.agentId);
195483
195902
  return {
195484
195903
  id: workerId,
195485
195904
  agentId: directWorker.agentId,
195486
195905
  sessionId,
195487
- messages: await this.contextStore.getAgentContext(sessionId, directWorker.agentId)
195906
+ messages
195488
195907
  };
195489
195908
  }
195490
195909
  async save(worker) {
@@ -197740,6 +198159,7 @@ var ChannelManager = class {
197740
198159
  }
197741
198160
  const failures = [];
197742
198161
  let total = 0;
198162
+ const sentPaths = /* @__PURE__ */ new Set();
197743
198163
  log20.info(
197744
198164
  `sendFilesFromBlocks: scanning ${blocks.length} blocks, channelType=${pending.channelType}`
197745
198165
  );
@@ -197754,8 +198174,14 @@ var ChannelManager = class {
197754
198174
  if (!filePath) continue;
197755
198175
  total++;
197756
198176
  try {
197757
- await this.assertSendableFilePath(filePath);
198177
+ const resolvedPath = await (0, import_promises16.realpath)(filePath);
198178
+ if (sentPaths.has(resolvedPath)) {
198179
+ log20.info(`channel file skipped (duplicate): ${resolvedPath}`);
198180
+ continue;
198181
+ }
198182
+ await this.assertSendableFilePath(resolvedPath);
197758
198183
  await adapter2.sendFile(pending.chatId, filePath, pending.chatType);
198184
+ sentPaths.add(resolvedPath);
197759
198185
  log20.info(`channel file sent: ${pending.channelType} -> ${filePath}`);
197760
198186
  } catch (err) {
197761
198187
  const msg = err instanceof Error ? err.message : String(err);
@@ -197771,8 +198197,14 @@ var ChannelManager = class {
197771
198197
  total++;
197772
198198
  try {
197773
198199
  const absolutePath = await attachmentStorage.getAttachmentPath(att.path);
198200
+ const resolvedPath = await (0, import_promises16.realpath)(absolutePath);
198201
+ if (sentPaths.has(resolvedPath)) {
198202
+ log20.info(`channel image skipped (duplicate): ${resolvedPath}`);
198203
+ continue;
198204
+ }
197774
198205
  await this.assertSendableFilePath(absolutePath);
197775
198206
  await adapter2.sendFile(pending.chatId, absolutePath, pending.chatType);
198207
+ sentPaths.add(resolvedPath);
197776
198208
  log20.info(`channel image sent: ${pending.channelType} -> ${absolutePath}`);
197777
198209
  } catch (err) {
197778
198210
  const msg = err instanceof Error ? err.message : String(err);
@@ -198386,7 +198818,7 @@ var ManualContextCompactionUseCase = class {
198386
198818
  modelSettings,
198387
198819
  languageModelFactory,
198388
198820
  modelCapability,
198389
- { keepRecentCount: MANUAL_KEEP_RECENT_COUNT, summaryTips: cleanTips }
198821
+ { keepRecentCount: MANUAL_KEEP_RECENT_COUNT, summaryTips: cleanTips, force: true }
198390
198822
  );
198391
198823
  const compactedWorker = (await compactor.compact({
198392
198824
  worker,
@@ -198950,13 +199382,15 @@ async function emitConversationSnapshot(sessionId) {
198950
199382
  const pending = messageQueue.getQueuedMessages(sessionId).length;
198951
199383
  const running = messageQueue.isRunning(sessionId);
198952
199384
  const activeRunId = running ? messageQueue.getActiveRunIdBySessionId(sessionId) : void 0;
199385
+ const activeRun = running ? messageQueue.getActiveRunSnapshot(sessionId) : void 0;
198953
199386
  eventBus.emitSnapshot(
198954
199387
  sessionId,
198955
199388
  conversation,
198956
199389
  memberAgentIds,
198957
199390
  filterVisibleMessages(messages),
198958
199391
  hasMore,
198959
- { pending, running, activeRunId }
199392
+ { pending, running, activeRunId },
199393
+ activeRun ? { activeRun } : void 0
198960
199394
  );
198961
199395
  } catch (error48) {
198962
199396
  logger28.error("Failed to emit snapshot", { sessionId, error: error48 });
@@ -199288,7 +199722,7 @@ init_ipc_events();
199288
199722
  init_config();
199289
199723
 
199290
199724
  // src/adapters/llm/create-language-model.ts
199291
- init_types4();
199725
+ init_llm_api_type();
199292
199726
 
199293
199727
  // node_modules/@ai-sdk/openai-compatible/dist/index.mjs
199294
199728
  init_dist2();
@@ -213419,7 +213853,7 @@ init_v4();
213419
213853
  init_dist4();
213420
213854
  init_dist4();
213421
213855
  init_dist4();
213422
- var VERSION8 = true ? "3.0.75" : "0.0.0-test";
213856
+ var VERSION8 = true ? "3.0.78" : "0.0.0-test";
213423
213857
  var googleErrorDataSchema = lazySchema(
213424
213858
  () => zodSchema(
213425
213859
  external_exports3.object({
@@ -214207,17 +214641,32 @@ var googleLanguageModelOptions = lazySchema(
214207
214641
  */
214208
214642
  streamFunctionCallArguments: external_exports3.boolean().optional(),
214209
214643
  /**
214210
- * Optional. The service tier to use for the request.
214644
+ * Optional. The service tier to use for the request. Sent as the
214645
+ * `serviceTier` body field. Gemini API only.
214211
214646
  */
214212
- serviceTier: external_exports3.enum(["standard", "flex", "priority"]).optional()
214647
+ serviceTier: external_exports3.enum(["standard", "flex", "priority"]).optional(),
214648
+ /**
214649
+ * Optional. Vertex AI only. Sent as the
214650
+ * `X-Vertex-AI-LLM-Shared-Request-Type` request header to select a
214651
+ * shared (PayGo) tier. With Provisioned Throughput allocated and
214652
+ * `requestType` unset, the request falls back to this tier only if
214653
+ * PT capacity is exhausted.
214654
+ *
214655
+ * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/priority-paygo
214656
+ * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/flex-paygo
214657
+ */
214658
+ sharedRequestType: external_exports3.enum(["priority", "flex", "standard"]).optional(),
214659
+ /**
214660
+ * Optional. Vertex AI only. Sent as the `X-Vertex-AI-LLM-Request-Type`
214661
+ * request header. Set to `'shared'` together with `sharedRequestType`
214662
+ * to bypass Provisioned Throughput entirely.
214663
+ *
214664
+ * https://docs.cloud.google.com/vertex-ai/generative-ai/docs/priority-paygo
214665
+ */
214666
+ requestType: external_exports3.enum(["shared"]).optional()
214213
214667
  })
214214
214668
  )
214215
214669
  );
214216
- var VertexServiceTierMap = {
214217
- standard: "SERVICE_TIER_STANDARD",
214218
- flex: "SERVICE_TIER_FLEX",
214219
- priority: "SERVICE_TIER_PRIORITY"
214220
- };
214221
214670
  function prepareTools3({
214222
214671
  tools,
214223
214672
  toolChoice,
@@ -214765,10 +215214,27 @@ var GoogleGenerativeAILanguageModel = class {
214765
215214
  message: `'streamFunctionCallArguments' is only supported on the Vertex AI API and will be ignored with the current Google provider (${this.config.provider}). See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling#streaming-fc`
214766
215215
  });
214767
215216
  }
214768
- let sanitizedServiceTier = googleOptions == null ? void 0 : googleOptions.serviceTier;
214769
215217
  if ((googleOptions == null ? void 0 : googleOptions.serviceTier) && isVertexProvider) {
214770
- sanitizedServiceTier = VertexServiceTierMap[googleOptions.serviceTier];
215218
+ warnings.push({
215219
+ type: "other",
215220
+ message: "'serviceTier' is a Gemini API option and is not supported on Vertex AI. Use 'sharedRequestType' (and optionally 'requestType') instead. See https://docs.cloud.google.com/vertex-ai/generative-ai/docs/priority-paygo"
215221
+ });
215222
+ }
215223
+ if (((googleOptions == null ? void 0 : googleOptions.sharedRequestType) || (googleOptions == null ? void 0 : googleOptions.requestType)) && !isVertexProvider) {
215224
+ warnings.push({
215225
+ type: "other",
215226
+ message: `'sharedRequestType' and 'requestType' are Vertex AI options and are ignored with the current Google provider (${this.config.provider}).`
215227
+ });
214771
215228
  }
215229
+ const vertexPaygoHeaders = isVertexProvider && ((googleOptions == null ? void 0 : googleOptions.sharedRequestType) || (googleOptions == null ? void 0 : googleOptions.requestType)) ? {
215230
+ ...googleOptions.sharedRequestType && {
215231
+ "X-Vertex-AI-LLM-Shared-Request-Type": googleOptions.sharedRequestType
215232
+ },
215233
+ ...googleOptions.requestType && {
215234
+ "X-Vertex-AI-LLM-Request-Type": googleOptions.requestType
215235
+ }
215236
+ } : void 0;
215237
+ const bodyServiceTier = isVertexProvider ? void 0 : googleOptions == null ? void 0 : googleOptions.serviceTier;
214772
215238
  const isGemmaModel = this.modelId.toLowerCase().startsWith("gemma-");
214773
215239
  const supportsFunctionResponseParts = this.modelId.startsWith("gemini-3");
214774
215240
  const { contents: contents2, systemInstruction } = convertToGoogleGenerativeAIMessages(
@@ -214840,18 +215306,20 @@ var GoogleGenerativeAILanguageModel = class {
214840
215306
  toolConfig,
214841
215307
  cachedContent: googleOptions == null ? void 0 : googleOptions.cachedContent,
214842
215308
  labels: googleOptions == null ? void 0 : googleOptions.labels,
214843
- serviceTier: sanitizedServiceTier
215309
+ serviceTier: bodyServiceTier
214844
215310
  },
214845
215311
  warnings: [...warnings, ...toolWarnings],
214846
- providerOptionsName
215312
+ providerOptionsName,
215313
+ extraHeaders: vertexPaygoHeaders
214847
215314
  };
214848
215315
  }
214849
215316
  async doGenerate(options2) {
214850
215317
  var _a28, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
214851
- const { args: args2, warnings, providerOptionsName } = await this.getArgs(options2);
215318
+ const { args: args2, warnings, providerOptionsName, extraHeaders } = await this.getArgs(options2);
214852
215319
  const mergedHeaders = combineHeaders(
214853
215320
  await resolve(this.config.headers),
214854
- options2.headers
215321
+ options2.headers,
215322
+ extraHeaders
214855
215323
  );
214856
215324
  const {
214857
215325
  responseHeaders,
@@ -215016,7 +215484,7 @@ var GoogleGenerativeAILanguageModel = class {
215016
215484
  safetyRatings: (_p = candidate.safetyRatings) != null ? _p : null,
215017
215485
  usageMetadata: usageMetadata != null ? usageMetadata : null,
215018
215486
  finishMessage: (_q = candidate.finishMessage) != null ? _q : null,
215019
- serviceTier: (_r = response.serviceTier) != null ? _r : null
215487
+ serviceTier: (_r = usageMetadata == null ? void 0 : usageMetadata.serviceTier) != null ? _r : null
215020
215488
  }
215021
215489
  },
215022
215490
  request: { body: args2 },
@@ -215028,13 +215496,11 @@ var GoogleGenerativeAILanguageModel = class {
215028
215496
  };
215029
215497
  }
215030
215498
  async doStream(options2) {
215031
- const { args: args2, warnings, providerOptionsName } = await this.getArgs(
215032
- options2,
215033
- { isStreaming: true }
215034
- );
215499
+ const { args: args2, warnings, providerOptionsName, extraHeaders } = await this.getArgs(options2, { isStreaming: true });
215035
215500
  const headers = combineHeaders(
215036
215501
  await resolve(this.config.headers),
215037
- options2.headers
215502
+ options2.headers,
215503
+ extraHeaders
215038
215504
  );
215039
215505
  const { responseHeaders, value: response } = await postJsonToApi({
215040
215506
  url: `${this.config.baseURL}/${getModelPath(
@@ -215055,7 +215521,6 @@ var GoogleGenerativeAILanguageModel = class {
215055
215521
  let providerMetadata = void 0;
215056
215522
  let lastGroundingMetadata = null;
215057
215523
  let lastUrlContextMetadata = null;
215058
- let serviceTier = null;
215059
215524
  const generateId3 = this.config.generateId;
215060
215525
  let hasToolCalls = false;
215061
215526
  let currentTextBlockId = null;
@@ -215065,6 +215530,34 @@ var GoogleGenerativeAILanguageModel = class {
215065
215530
  let lastCodeExecutionToolCallId;
215066
215531
  let lastServerToolCallId;
215067
215532
  const activeStreamingToolCalls = [];
215533
+ const finishActiveStreamingToolCall = (controller) => {
215534
+ const active = activeStreamingToolCalls.pop();
215535
+ if (active == null) {
215536
+ return;
215537
+ }
215538
+ const { finalJSON, closingDelta } = active.accumulator.finalize();
215539
+ if (closingDelta.length > 0) {
215540
+ controller.enqueue({
215541
+ type: "tool-input-delta",
215542
+ id: active.toolCallId,
215543
+ delta: closingDelta,
215544
+ providerMetadata: active.providerMetadata
215545
+ });
215546
+ }
215547
+ controller.enqueue({
215548
+ type: "tool-input-end",
215549
+ id: active.toolCallId,
215550
+ providerMetadata: active.providerMetadata
215551
+ });
215552
+ controller.enqueue({
215553
+ type: "tool-call",
215554
+ toolCallId: active.toolCallId,
215555
+ toolName: active.toolName,
215556
+ input: finalJSON,
215557
+ providerMetadata: active.providerMetadata
215558
+ });
215559
+ hasToolCalls = true;
215560
+ };
215068
215561
  return {
215069
215562
  stream: response.pipeThrough(
215070
215563
  new TransformStream({
@@ -215072,7 +215565,7 @@ var GoogleGenerativeAILanguageModel = class {
215072
215565
  controller.enqueue({ type: "stream-start", warnings });
215073
215566
  },
215074
215567
  transform(chunk, controller) {
215075
- var _a28, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
215568
+ var _a28, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
215076
215569
  if (options2.includeRawChunks) {
215077
215570
  controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
215078
215571
  }
@@ -215085,9 +215578,6 @@ var GoogleGenerativeAILanguageModel = class {
215085
215578
  if (usageMetadata != null) {
215086
215579
  usage = usageMetadata;
215087
215580
  }
215088
- if (value.serviceTier != null) {
215089
- serviceTier = value.serviceTier;
215090
- }
215091
215581
  const candidate = (_a28 = value.candidates) == null ? void 0 : _a28[0];
215092
215582
  if (candidate == null) {
215093
215583
  return;
@@ -215277,7 +215767,7 @@ var GoogleGenerativeAILanguageModel = class {
215277
215767
  const isCompleteCall = part.functionCall.name != null && part.functionCall.args != null && part.functionCall.partialArgs == null;
215278
215768
  const isNoArgsCompleteCall = part.functionCall.name != null && part.functionCall.args == null && part.functionCall.partialArgs == null && part.functionCall.willContinue !== true;
215279
215769
  if (isStreamingChunk) {
215280
- if (part.functionCall.name != null && part.functionCall.willContinue === true) {
215770
+ if (part.functionCall.name != null) {
215281
215771
  const toolCallId = (_i = part.functionCall.id) != null ? _i : generateId3();
215282
215772
  const accumulator = new GoogleJSONAccumulator();
215283
215773
  activeStreamingToolCalls.push({
@@ -215293,9 +215783,8 @@ var GoogleGenerativeAILanguageModel = class {
215293
215783
  providerMetadata: providerMeta
215294
215784
  });
215295
215785
  if (part.functionCall.partialArgs != null) {
215296
- const { textDelta } = accumulator.processPartialArgs(
215297
- part.functionCall.partialArgs
215298
- );
215786
+ const partialArgs = part.functionCall.partialArgs;
215787
+ const { textDelta } = accumulator.processPartialArgs(partialArgs);
215299
215788
  if (textDelta.length > 0) {
215300
215789
  controller.enqueue({
215301
215790
  type: "tool-input-delta",
@@ -215304,12 +215793,14 @@ var GoogleGenerativeAILanguageModel = class {
215304
215793
  providerMetadata: providerMeta
215305
215794
  });
215306
215795
  }
215796
+ if (part.functionCall.willContinue !== true && partialArgs.every((arg) => arg.willContinue !== true)) {
215797
+ finishActiveStreamingToolCall(controller);
215798
+ }
215307
215799
  }
215308
215800
  } else if (part.functionCall.partialArgs != null && activeStreamingToolCalls.length > 0) {
215309
215801
  const active = activeStreamingToolCalls[activeStreamingToolCalls.length - 1];
215310
- const { textDelta } = active.accumulator.processPartialArgs(
215311
- part.functionCall.partialArgs
215312
- );
215802
+ const partialArgs = part.functionCall.partialArgs;
215803
+ const { textDelta } = active.accumulator.processPartialArgs(partialArgs);
215313
215804
  if (textDelta.length > 0) {
215314
215805
  controller.enqueue({
215315
215806
  type: "tool-input-delta",
@@ -215318,31 +215809,12 @@ var GoogleGenerativeAILanguageModel = class {
215318
215809
  providerMetadata: providerMeta
215319
215810
  });
215320
215811
  }
215812
+ if (part.functionCall.willContinue !== true && partialArgs.every((arg) => arg.willContinue !== true)) {
215813
+ finishActiveStreamingToolCall(controller);
215814
+ }
215321
215815
  }
215322
215816
  } else if (isTerminalChunk && activeStreamingToolCalls.length > 0) {
215323
- const active = activeStreamingToolCalls.pop();
215324
- const { finalJSON, closingDelta } = active.accumulator.finalize();
215325
- if (closingDelta.length > 0) {
215326
- controller.enqueue({
215327
- type: "tool-input-delta",
215328
- id: active.toolCallId,
215329
- delta: closingDelta,
215330
- providerMetadata: active.providerMetadata
215331
- });
215332
- }
215333
- controller.enqueue({
215334
- type: "tool-input-end",
215335
- id: active.toolCallId,
215336
- providerMetadata: active.providerMetadata
215337
- });
215338
- controller.enqueue({
215339
- type: "tool-call",
215340
- toolCallId: active.toolCallId,
215341
- toolName: active.toolName,
215342
- input: finalJSON,
215343
- providerMetadata: active.providerMetadata
215344
- });
215345
- hasToolCalls = true;
215817
+ finishActiveStreamingToolCall(controller);
215346
215818
  } else if (isCompleteCall) {
215347
215819
  const toolCallId = (_j = part.functionCall.id) != null ? _j : generateId3();
215348
215820
  const toolName = part.functionCall.name;
@@ -215413,7 +215885,7 @@ var GoogleGenerativeAILanguageModel = class {
215413
215885
  safetyRatings: (_n = candidate.safetyRatings) != null ? _n : null,
215414
215886
  usageMetadata: usageMetadata != null ? usageMetadata : null,
215415
215887
  finishMessage: (_o = candidate.finishMessage) != null ? _o : null,
215416
- serviceTier
215888
+ serviceTier: (_p = usage == null ? void 0 : usage.serviceTier) != null ? _p : null
215417
215889
  }
215418
215890
  };
215419
215891
  }
@@ -215672,6 +216144,7 @@ var usageSchema2 = external_exports3.object({
215672
216144
  totalTokenCount: external_exports3.number().nullish(),
215673
216145
  // https://cloud.google.com/vertex-ai/generative-ai/docs/reference/rest/v1/GenerateContentResponse#TrafficType
215674
216146
  trafficType: external_exports3.string().nullish(),
216147
+ serviceTier: external_exports3.string().nullish(),
215675
216148
  // https://ai.google.dev/api/generate-content#Modality
215676
216149
  promptTokensDetails: tokenDetailsSchema,
215677
216150
  candidatesTokensDetails: tokenDetailsSchema
@@ -215701,8 +216174,7 @@ var responseSchema = lazySchema(
215701
216174
  promptFeedback: external_exports3.object({
215702
216175
  blockReason: external_exports3.string().nullish(),
215703
216176
  safetyRatings: external_exports3.array(getSafetyRatingSchema()).nullish()
215704
- }).nullish(),
215705
- serviceTier: external_exports3.string().nullish()
216177
+ }).nullish()
215706
216178
  })
215707
216179
  )
215708
216180
  );
@@ -215723,8 +216195,7 @@ var chunkSchema = lazySchema(
215723
216195
  promptFeedback: external_exports3.object({
215724
216196
  blockReason: external_exports3.string().nullish(),
215725
216197
  safetyRatings: external_exports3.array(getSafetyRatingSchema()).nullish()
215726
- }).nullish(),
215727
- serviceTier: external_exports3.string().nullish()
216198
+ }).nullish()
215728
216199
  })
215729
216200
  )
215730
216201
  );
@@ -217879,7 +218350,61 @@ var googleInteractionsLanguageModelOptions = lazySchema(
217879
218350
  * call) before giving up. Defaults to 30 minutes. Long-running agents
217880
218351
  * such as deep research can take tens of minutes — increase if needed.
217881
218352
  */
217882
- pollingTimeoutMs: external_exports3.number().int().positive().nullish()
218353
+ pollingTimeoutMs: external_exports3.number().int().positive().nullish(),
218354
+ /**
218355
+ * Run the interaction in the background. Required for agents whose
218356
+ * server-side workflow cannot complete within a single request/response.
218357
+ * When `true`, the POST returns with a non-terminal status and the SDK
218358
+ * polls `GET /interactions/{id}` until the work completes. Some agents
218359
+ * reject `true`; see the agent's documentation for which mode it
218360
+ * requires.
218361
+ */
218362
+ background: external_exports3.boolean().nullish(),
218363
+ /**
218364
+ * Environment configuration for the agent sandbox. Only applies to agent
218365
+ * calls (`google.interactions({ agent })`); ignored on model-id calls.
218366
+ *
218367
+ * - `"remote"`: provision a fresh sandbox for this call.
218368
+ * - any other string: an existing `environment_id` to reuse.
218369
+ * - object: provision a fresh sandbox and optionally preload `sources`
218370
+ * and/or constrain outbound traffic via `network`.
218371
+ */
218372
+ environment: external_exports3.union([
218373
+ external_exports3.string(),
218374
+ external_exports3.object({
218375
+ type: external_exports3.literal("remote"),
218376
+ sources: external_exports3.array(
218377
+ external_exports3.union([
218378
+ external_exports3.object({
218379
+ type: external_exports3.literal("gcs"),
218380
+ source: external_exports3.string(),
218381
+ target: external_exports3.string().nullish()
218382
+ }),
218383
+ external_exports3.object({
218384
+ type: external_exports3.literal("repository"),
218385
+ source: external_exports3.string(),
218386
+ target: external_exports3.string().nullish()
218387
+ }),
218388
+ external_exports3.object({
218389
+ type: external_exports3.literal("inline"),
218390
+ content: external_exports3.string(),
218391
+ target: external_exports3.string()
218392
+ })
218393
+ ])
218394
+ ).nullish(),
218395
+ network: external_exports3.union([
218396
+ external_exports3.literal("disabled"),
218397
+ external_exports3.object({
218398
+ allowlist: external_exports3.array(
218399
+ external_exports3.object({
218400
+ domain: external_exports3.string(),
218401
+ transform: external_exports3.array(external_exports3.record(external_exports3.string(), external_exports3.string())).nullish()
218402
+ })
218403
+ )
218404
+ })
218405
+ ]).nullish()
218406
+ })
218407
+ ]).nullish()
217883
218408
  })
217884
218409
  )
217885
218410
  );
@@ -218588,6 +219113,9 @@ var GoogleInteractionsLanguageModel = class {
218588
219113
  if (typeof modelOrAgent === "string") {
218589
219114
  this.modelId = modelOrAgent;
218590
219115
  this.agent = void 0;
219116
+ } else if ("managedAgent" in modelOrAgent) {
219117
+ this.modelId = modelOrAgent.managedAgent;
219118
+ this.agent = modelOrAgent.managedAgent;
218591
219119
  } else {
218592
219120
  this.modelId = modelOrAgent.agent;
218593
219121
  this.agent = modelOrAgent.agent;
@@ -218613,7 +219141,7 @@ var GoogleInteractionsLanguageModel = class {
218613
219141
  };
218614
219142
  }
218615
219143
  async getArgs(options2) {
218616
- var _a28, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
219144
+ var _a28, _b17, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
218617
219145
  const warnings = [];
218618
219146
  const opts = await parseProviderOptions({
218619
219147
  provider: "google",
@@ -218770,6 +219298,55 @@ var GoogleInteractionsLanguageModel = class {
218770
219298
  agentConfig = { type: "dynamic" };
218771
219299
  }
218772
219300
  }
219301
+ let environment;
219302
+ if ((opts == null ? void 0 : opts.environment) != null) {
219303
+ if (!isAgent) {
219304
+ warnings.push({
219305
+ type: "other",
219306
+ message: "google.interactions: environment is only supported when an agent is set; environment will be omitted from the request body."
219307
+ });
219308
+ } else if (typeof opts.environment === "string") {
219309
+ environment = opts.environment;
219310
+ } else {
219311
+ const env2 = opts.environment;
219312
+ const sources = (_u = env2.sources) == null ? void 0 : _u.map((s) => {
219313
+ var _a29;
219314
+ if (s.type === "inline") {
219315
+ return {
219316
+ type: "inline",
219317
+ content: s.content,
219318
+ target: s.target
219319
+ };
219320
+ }
219321
+ return pruneUndefined({
219322
+ type: s.type,
219323
+ source: s.source,
219324
+ target: (_a29 = s.target) != null ? _a29 : void 0
219325
+ });
219326
+ });
219327
+ let network;
219328
+ if (env2.network === "disabled") {
219329
+ network = "disabled";
219330
+ } else if (env2.network != null) {
219331
+ network = {
219332
+ allowlist: env2.network.allowlist.map(
219333
+ (entry) => {
219334
+ var _a29;
219335
+ return pruneUndefined({
219336
+ domain: entry.domain,
219337
+ transform: (_a29 = entry.transform) != null ? _a29 : void 0
219338
+ });
219339
+ }
219340
+ )
219341
+ };
219342
+ }
219343
+ environment = pruneUndefined({
219344
+ type: "remote",
219345
+ sources: sources != null && sources.length > 0 ? sources : void 0,
219346
+ network
219347
+ });
219348
+ }
219349
+ }
218773
219350
  const args2 = pruneUndefined({
218774
219351
  ...isAgent ? { agent: this.agent } : { model: this.modelId },
218775
219352
  input,
@@ -218777,18 +219354,20 @@ var GoogleInteractionsLanguageModel = class {
218777
219354
  tools: toolsForBody,
218778
219355
  response_format: responseFormatEntries.length > 0 ? responseFormatEntries : void 0,
218779
219356
  response_modalities: (opts == null ? void 0 : opts.responseModalities) != null ? opts.responseModalities : void 0,
218780
- previous_interaction_id: (_u = opts == null ? void 0 : opts.previousInteractionId) != null ? _u : void 0,
218781
- service_tier: (_v = opts == null ? void 0 : opts.serviceTier) != null ? _v : void 0,
218782
- store: (_w = opts == null ? void 0 : opts.store) != null ? _w : void 0,
219357
+ previous_interaction_id: (_v = opts == null ? void 0 : opts.previousInteractionId) != null ? _v : void 0,
219358
+ service_tier: (_w = opts == null ? void 0 : opts.serviceTier) != null ? _w : void 0,
219359
+ store: (_x = opts == null ? void 0 : opts.store) != null ? _x : void 0,
218783
219360
  generation_config: generationConfig != null && Object.keys(generationConfig).length > 0 ? generationConfig : void 0,
218784
219361
  agent_config: agentConfig,
218785
- ...isAgent ? { background: true } : {}
219362
+ environment,
219363
+ background: (_y = opts == null ? void 0 : opts.background) != null ? _y : void 0
218786
219364
  });
218787
219365
  return {
218788
219366
  args: args2,
218789
219367
  warnings,
218790
219368
  isAgent,
218791
- pollingTimeoutMs: (_x = opts == null ? void 0 : opts.pollingTimeoutMs) != null ? _x : void 0
219369
+ isBackground: (opts == null ? void 0 : opts.background) === true,
219370
+ pollingTimeoutMs: (_z = opts == null ? void 0 : opts.pollingTimeoutMs) != null ? _z : void 0
218792
219371
  };
218793
219372
  }
218794
219373
  async doGenerate(options2) {
@@ -218874,14 +219453,14 @@ var GoogleInteractionsLanguageModel = class {
218874
219453
  }
218875
219454
  async doStream(options2) {
218876
219455
  var _a28;
218877
- const { args: args2, warnings, isAgent, pollingTimeoutMs } = await this.getArgs(options2);
219456
+ const { args: args2, warnings, isBackground, pollingTimeoutMs } = await this.getArgs(options2);
218878
219457
  const url2 = `${this.config.baseURL}/interactions`;
218879
219458
  const mergedHeaders = combineHeaders(
218880
219459
  INTERACTIONS_API_REVISION_HEADER,
218881
219460
  this.config.headers ? await resolve(this.config.headers) : void 0,
218882
219461
  options2.headers
218883
219462
  );
218884
- if (isAgent) {
219463
+ if (isBackground) {
218885
219464
  return this.doStreamBackground({
218886
219465
  args: args2,
218887
219466
  warnings,
@@ -219976,17 +220555,11 @@ function createImageModel(config3, options2) {
219976
220555
  operation: "image_generation"
219977
220556
  });
219978
220557
  }
219979
- function resolveForcedApiType(model) {
219980
- if (/^claude-/i.test(model)) return "anthropic";
219981
- if (/^gemini-/i.test(model)) return "google";
219982
- if (/^gpt-[5-9]/i.test(model)) return "openai";
219983
- return void 0;
219984
- }
219985
220558
  function resolveConfiguredApiType(config3) {
219986
- const forced = resolveForcedApiType(config3.model);
219987
- if (forced) return forced;
219988
- if (config3.apiType === "auto") return resolveApiType(config3.model);
219989
- return config3.apiType || "openai-compatible";
220559
+ return resolveEffectiveApiType({
220560
+ model: config3.model,
220561
+ configuredApiType: config3.apiType
220562
+ });
219990
220563
  }
219991
220564
 
219992
220565
  // src/electron/main/handlers/agent-handlers.ts
@@ -221111,12 +221684,13 @@ init_cron_file_store();
221111
221684
  init_scheduler2();
221112
221685
  init_ipc_events();
221113
221686
  init_logger();
221687
+ init_scheduled_task_target();
221114
221688
  var logger34 = createLogger("TaskHandlers");
221115
221689
  function isDuplicateScheduledTask(task, existing) {
221116
221690
  if (task.type !== existing.type) return false;
221117
221691
  if (task.cronExpression !== existing.cronExpression) return false;
221118
221692
  if (task.type === "agent" && existing.type === "agent") {
221119
- return task.agentId === existing.agentId && task.message === existing.message;
221693
+ return task.agentId === existing.agentId && task.sessionId === existing.sessionId && task.message === existing.message;
221120
221694
  }
221121
221695
  if (task.type === "group" && existing.type === "group") {
221122
221696
  return task.groupId === existing.groupId && task.sessionId === existing.sessionId && task.message === existing.message;
@@ -221131,6 +221705,7 @@ function isDuplicateScheduledTask(task, existing) {
221131
221705
  }
221132
221706
  async function handleCreateScheduledTask(task) {
221133
221707
  logger34.debug("\u521B\u5EFA\u4EFB\u52A1:", task.name);
221708
+ await assertValidScheduledTaskTarget(task);
221134
221709
  const existingTasks = await cronFileStore.findAllTasks();
221135
221710
  const duplicate = existingTasks.find((existing) => isDuplicateScheduledTask(task, existing));
221136
221711
  if (duplicate) {
@@ -221147,6 +221722,10 @@ async function handleListScheduledTasks() {
221147
221722
  return cronFileStore.findAllTasks();
221148
221723
  }
221149
221724
  async function handleUpdateScheduledTask(id, updates) {
221725
+ const current = await cronFileStore.findTaskById(id);
221726
+ if (current) {
221727
+ await assertValidScheduledTaskTarget({ ...current, ...updates });
221728
+ }
221150
221729
  await cronFileStore.updateTask(id, updates);
221151
221730
  const task = await cronFileStore.findTaskById(id);
221152
221731
  if (task) {
@@ -221154,6 +221733,14 @@ async function handleUpdateScheduledTask(id, updates) {
221154
221733
  if (task.enabled) getScheduler().schedule(task);
221155
221734
  }
221156
221735
  }
221736
+ async function assertValidScheduledTaskTarget(task) {
221737
+ if (task.type !== "agent" && task.type !== "group") return;
221738
+ if (!task.sessionId) return;
221739
+ const resolved = await resolveScheduledTaskTarget(task);
221740
+ if (!resolved || resolved.source !== "explicit") {
221741
+ throw new Error("\u5B9A\u65F6\u4EFB\u52A1\u76EE\u6807 Session \u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u6240\u9009\u6267\u884C\u4F4D\u7F6E");
221742
+ }
221743
+ }
221157
221744
  async function handleDeleteScheduledTask(id) {
221158
221745
  getScheduler().unschedule(id);
221159
221746
  await cronFileStore.deleteTask(id);
@@ -240372,16 +240959,22 @@ init_scheduler2();
240372
240959
  function belongsToScope(task, scope) {
240373
240960
  if (task.type === "memory-update") return false;
240374
240961
  if (scope.kind === "agent") {
240375
- return task.type === "agent" && task.agentId === scope.agentId;
240962
+ if (task.type !== "agent" || task.agentId !== scope.agentId) return false;
240963
+ if (scope.sessionId) return task.sessionId === scope.sessionId || !task.sessionId;
240964
+ return true;
240376
240965
  }
240377
240966
  if (task.type !== "group") return false;
240378
240967
  if (task.groupId !== scope.groupId) return false;
240379
- if (scope.sessionId) return task.sessionId === scope.sessionId;
240968
+ if (scope.sessionId) return task.sessionId === scope.sessionId || !task.sessionId;
240380
240969
  return true;
240381
240970
  }
240382
240971
  function resolveSchedulerToolScope(scope) {
240383
240972
  if (scope.toolAccess.type === "agentWorkspace") {
240384
- return { kind: "agent", agentId: scope.toolAccess.agentId };
240973
+ return {
240974
+ kind: "agent",
240975
+ agentId: scope.toolAccess.agentId,
240976
+ sessionId: scope.session?.type === "direct" ? scope.session.sessionId : void 0
240977
+ };
240385
240978
  }
240386
240979
  if (scope.toolAccess.type === "groupWorkspace") {
240387
240980
  return {
@@ -240391,7 +240984,11 @@ function resolveSchedulerToolScope(scope) {
240391
240984
  speakerId: scope.toolAccess.speakerAgentId
240392
240985
  };
240393
240986
  }
240394
- return { kind: "agent", agentId: scope.worker.agentId };
240987
+ return {
240988
+ kind: "agent",
240989
+ agentId: scope.worker.agentId,
240990
+ sessionId: scope.session?.type === "direct" ? scope.session.sessionId : void 0
240991
+ };
240395
240992
  }
240396
240993
 
240397
240994
  // src/adapters/tools/scheduler.ts
@@ -240401,6 +240998,7 @@ function createTaskInput(scope, params) {
240401
240998
  name: params.name,
240402
240999
  type: "agent",
240403
241000
  agentId: scope.agentId,
241001
+ sessionId: scope.sessionId,
240404
241002
  cronExpression: params.cronExpression,
240405
241003
  message: params.message,
240406
241004
  enabled: true