dominds 1.22.0 → 1.22.1

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 (125) hide show
  1. package/dist/dialog-instance-registry.js +3 -4
  2. package/dist/dialog.d.ts +2 -2
  3. package/dist/dialog.js +3 -3
  4. package/dist/docs/diligence-push.md +19 -12
  5. package/dist/docs/diligence-push.zh.md +11 -9
  6. package/dist/docs/dominds-terminology.md +3 -3
  7. package/dist/docs/llm-provider-isolation.md +1 -1
  8. package/dist/docs/llm-provider-isolation.zh.md +1 -1
  9. package/dist/docs/team_mgmt-toolset.md +1 -1
  10. package/dist/docs/team_mgmt-toolset.zh.md +1 -1
  11. package/dist/docs/volcengine-coding-plan-openai-compatible.zh.md +11 -10
  12. package/dist/llm/api-quirks.d.ts +0 -2
  13. package/dist/llm/api-quirks.js +1 -3
  14. package/dist/llm/client.d.ts +1 -0
  15. package/dist/llm/defaults.yaml +2 -6
  16. package/dist/llm/gen/anthropic.d.ts +0 -6
  17. package/dist/llm/gen/anthropic.js +21 -468
  18. package/dist/llm/gen/openai-compatible.d.ts +11 -1
  19. package/dist/llm/gen/openai-compatible.js +188 -8
  20. package/dist/llm/gen.d.ts +4 -2
  21. package/dist/llm/kernel-driver/drive.js +164 -114
  22. package/dist/llm/kernel-driver/runtime.js +36 -11
  23. package/dist/llm/kernel-driver/tellask-special.js +12 -9
  24. package/dist/persistence.d.ts +2 -3
  25. package/dist/persistence.js +53 -76
  26. package/dist/problems.js +2 -1
  27. package/dist/server/websocket-handler.js +17 -3
  28. package/dist/tools/team_mgmt-manual.js +4 -4
  29. package/dist/tools/team_mgmt.js +13 -3
  30. package/package.json +3 -3
  31. package/webapp/dist/assets/{_basePickBy-BYnYcdaa.js → _basePickBy-DUbW5G8a.js} +3 -3
  32. package/webapp/dist/assets/{_basePickBy-BYnYcdaa.js.map → _basePickBy-DUbW5G8a.js.map} +1 -1
  33. package/webapp/dist/assets/{_baseUniq-CHLBB955.js → _baseUniq-vou1IeXB.js} +2 -2
  34. package/webapp/dist/assets/{_baseUniq-CHLBB955.js.map → _baseUniq-vou1IeXB.js.map} +1 -1
  35. package/webapp/dist/assets/{arc-DQXtgZdO.js → arc-D_O9oO0B.js} +2 -2
  36. package/webapp/dist/assets/{arc-DQXtgZdO.js.map → arc-D_O9oO0B.js.map} +1 -1
  37. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CzP5Yf9x.js → architectureDiagram-2XIMDMQ5-B7k9SWSL.js} +7 -7
  38. package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CzP5Yf9x.js.map → architectureDiagram-2XIMDMQ5-B7k9SWSL.js.map} +1 -1
  39. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-sOx5Byq8.js → blockDiagram-WCTKOSBZ-e3xTmffi.js} +7 -7
  40. package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-sOx5Byq8.js.map → blockDiagram-WCTKOSBZ-e3xTmffi.js.map} +1 -1
  41. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D8-GiS6c.js → c4Diagram-IC4MRINW-DVvi-N2o.js} +3 -3
  42. package/webapp/dist/assets/{c4Diagram-IC4MRINW-D8-GiS6c.js.map → c4Diagram-IC4MRINW-DVvi-N2o.js.map} +1 -1
  43. package/webapp/dist/assets/{channel-Bvke0iMP.js → channel-CH387UD2.js} +2 -2
  44. package/webapp/dist/assets/{channel-Bvke0iMP.js.map → channel-CH387UD2.js.map} +1 -1
  45. package/webapp/dist/assets/{chunk-4BX2VUAB-C9pln2M7.js → chunk-4BX2VUAB-BOo0Xj3m.js} +2 -2
  46. package/webapp/dist/assets/{chunk-4BX2VUAB-C9pln2M7.js.map → chunk-4BX2VUAB-BOo0Xj3m.js.map} +1 -1
  47. package/webapp/dist/assets/{chunk-55IACEB6-BLDXNtAM.js → chunk-55IACEB6-CI4uRAx_.js} +2 -2
  48. package/webapp/dist/assets/{chunk-55IACEB6-BLDXNtAM.js.map → chunk-55IACEB6-CI4uRAx_.js.map} +1 -1
  49. package/webapp/dist/assets/{chunk-FMBD7UC4-dYd3QdHa.js → chunk-FMBD7UC4-C4N1ovxD.js} +2 -2
  50. package/webapp/dist/assets/{chunk-FMBD7UC4-dYd3QdHa.js.map → chunk-FMBD7UC4-C4N1ovxD.js.map} +1 -1
  51. package/webapp/dist/assets/{chunk-JSJVCQXG-SqHEmHHd.js → chunk-JSJVCQXG-5U4Hu7pC.js} +2 -2
  52. package/webapp/dist/assets/{chunk-JSJVCQXG-SqHEmHHd.js.map → chunk-JSJVCQXG-5U4Hu7pC.js.map} +1 -1
  53. package/webapp/dist/assets/{chunk-KX2RTZJC-CRXgzI2d.js → chunk-KX2RTZJC-BXPDNuct.js} +2 -2
  54. package/webapp/dist/assets/{chunk-KX2RTZJC-CRXgzI2d.js.map → chunk-KX2RTZJC-BXPDNuct.js.map} +1 -1
  55. package/webapp/dist/assets/{chunk-NQ4KR5QH-IMA2JZhH.js → chunk-NQ4KR5QH-oVsExnnn.js} +4 -4
  56. package/webapp/dist/assets/{chunk-NQ4KR5QH-IMA2JZhH.js.map → chunk-NQ4KR5QH-oVsExnnn.js.map} +1 -1
  57. package/webapp/dist/assets/{chunk-QZHKN3VN-DBaGWjY3.js → chunk-QZHKN3VN-C6FzEv2C.js} +2 -2
  58. package/webapp/dist/assets/{chunk-QZHKN3VN-DBaGWjY3.js.map → chunk-QZHKN3VN-C6FzEv2C.js.map} +1 -1
  59. package/webapp/dist/assets/{chunk-WL4C6EOR-QLmsLbcS.js → chunk-WL4C6EOR-Ir7e_B7t.js} +6 -6
  60. package/webapp/dist/assets/{chunk-WL4C6EOR-QLmsLbcS.js.map → chunk-WL4C6EOR-Ir7e_B7t.js.map} +1 -1
  61. package/webapp/dist/assets/{classDiagram-VBA2DB6C-jN4lhUtx.js → classDiagram-VBA2DB6C-CPYs_LAr.js} +7 -7
  62. package/webapp/dist/assets/{classDiagram-VBA2DB6C-jN4lhUtx.js.map → classDiagram-VBA2DB6C-CPYs_LAr.js.map} +1 -1
  63. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-jN4lhUtx.js → classDiagram-v2-RAHNMMFH-CPYs_LAr.js} +7 -7
  64. package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-jN4lhUtx.js.map → classDiagram-v2-RAHNMMFH-CPYs_LAr.js.map} +1 -1
  65. package/webapp/dist/assets/{clone-DPC4Vt09.js → clone-CToca8rS.js} +2 -2
  66. package/webapp/dist/assets/{clone-DPC4Vt09.js.map → clone-CToca8rS.js.map} +1 -1
  67. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BtVgObsc.js → cose-bilkent-S5V4N54A-DLNtqY7a.js} +2 -2
  68. package/webapp/dist/assets/{cose-bilkent-S5V4N54A-BtVgObsc.js.map → cose-bilkent-S5V4N54A-DLNtqY7a.js.map} +1 -1
  69. package/webapp/dist/assets/{dagre-KLK3FWXG-Bv6mn-UV.js → dagre-KLK3FWXG-Bkt-O9uW.js} +7 -7
  70. package/webapp/dist/assets/{dagre-KLK3FWXG-Bv6mn-UV.js.map → dagre-KLK3FWXG-Bkt-O9uW.js.map} +1 -1
  71. package/webapp/dist/assets/{diagram-E7M64L7V-D2OPgDkq.js → diagram-E7M64L7V-B4JR_u4V.js} +8 -8
  72. package/webapp/dist/assets/{diagram-E7M64L7V-D2OPgDkq.js.map → diagram-E7M64L7V-B4JR_u4V.js.map} +1 -1
  73. package/webapp/dist/assets/{diagram-IFDJBPK2-CZpDu-e5.js → diagram-IFDJBPK2-D9zRh8b7.js} +7 -7
  74. package/webapp/dist/assets/{diagram-IFDJBPK2-CZpDu-e5.js.map → diagram-IFDJBPK2-D9zRh8b7.js.map} +1 -1
  75. package/webapp/dist/assets/{diagram-P4PSJMXO-BkMbbW0p.js → diagram-P4PSJMXO-CAaXVWnX.js} +7 -7
  76. package/webapp/dist/assets/{diagram-P4PSJMXO-BkMbbW0p.js.map → diagram-P4PSJMXO-CAaXVWnX.js.map} +1 -1
  77. package/webapp/dist/assets/{erDiagram-INFDFZHY-Kf17ek1z.js → erDiagram-INFDFZHY-DDeoaSkJ.js} +5 -5
  78. package/webapp/dist/assets/{erDiagram-INFDFZHY-Kf17ek1z.js.map → erDiagram-INFDFZHY-DDeoaSkJ.js.map} +1 -1
  79. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-Cort4hNL.js → flowDiagram-PKNHOUZH-DEYqzSEJ.js} +7 -7
  80. package/webapp/dist/assets/{flowDiagram-PKNHOUZH-Cort4hNL.js.map → flowDiagram-PKNHOUZH-DEYqzSEJ.js.map} +1 -1
  81. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DcXFKB1Y.js → ganttDiagram-A5KZAMGK-BuLOSh0d.js} +3 -3
  82. package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-DcXFKB1Y.js.map → ganttDiagram-A5KZAMGK-BuLOSh0d.js.map} +1 -1
  83. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-BORnqZ0-.js → gitGraphDiagram-K3NZZRJ6-CBrwZvBf.js} +8 -8
  84. package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-BORnqZ0-.js.map → gitGraphDiagram-K3NZZRJ6-CBrwZvBf.js.map} +1 -1
  85. package/webapp/dist/assets/{graph-D4Uth-MK.js → graph-fX6cvjwR.js} +3 -3
  86. package/webapp/dist/assets/{graph-D4Uth-MK.js.map → graph-fX6cvjwR.js.map} +1 -1
  87. package/webapp/dist/assets/{index-YBIJr7jH.js → index-B3WzTLcD.js} +67 -40
  88. package/webapp/dist/assets/{index-YBIJr7jH.js.map → index-B3WzTLcD.js.map} +1 -1
  89. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-DDjsEPg3.js → infoDiagram-LFFYTUFH-Ci3XYvve.js} +6 -6
  90. package/webapp/dist/assets/{infoDiagram-LFFYTUFH-DDjsEPg3.js.map → infoDiagram-LFFYTUFH-Ci3XYvve.js.map} +1 -1
  91. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bb2sPnCX.js → ishikawaDiagram-PHBUUO56-DOH5ua9R.js} +2 -2
  92. package/webapp/dist/assets/{ishikawaDiagram-PHBUUO56-Bb2sPnCX.js.map → ishikawaDiagram-PHBUUO56-DOH5ua9R.js.map} +1 -1
  93. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BtRY6eBa.js → journeyDiagram-4ABVD52K-DM_fiZlj.js} +5 -5
  94. package/webapp/dist/assets/{journeyDiagram-4ABVD52K-BtRY6eBa.js.map → journeyDiagram-4ABVD52K-DM_fiZlj.js.map} +1 -1
  95. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-aGmxT2H9.js → kanban-definition-K7BYSVSG-CSh2hqc2.js} +3 -3
  96. package/webapp/dist/assets/{kanban-definition-K7BYSVSG-aGmxT2H9.js.map → kanban-definition-K7BYSVSG-CSh2hqc2.js.map} +1 -1
  97. package/webapp/dist/assets/{layout-BuLicmwh.js → layout-yZEK1LgL.js} +5 -5
  98. package/webapp/dist/assets/{layout-BuLicmwh.js.map → layout-yZEK1LgL.js.map} +1 -1
  99. package/webapp/dist/assets/{linear-DIPh96mp.js → linear-m76SmdtZ.js} +2 -2
  100. package/webapp/dist/assets/{linear-DIPh96mp.js.map → linear-m76SmdtZ.js.map} +1 -1
  101. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-ofWsysn9.js → mindmap-definition-YRQLILUH-NiwP-SLH.js} +4 -4
  102. package/webapp/dist/assets/{mindmap-definition-YRQLILUH-ofWsysn9.js.map → mindmap-definition-YRQLILUH-NiwP-SLH.js.map} +1 -1
  103. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DQqCTITO.js → pieDiagram-SKSYHLDU-CSCapDSD.js} +8 -8
  104. package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DQqCTITO.js.map → pieDiagram-SKSYHLDU-CSCapDSD.js.map} +1 -1
  105. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DxWc0avu.js → quadrantDiagram-337W2JSQ-CbDGQH91.js} +3 -3
  106. package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-DxWc0avu.js.map → quadrantDiagram-337W2JSQ-CbDGQH91.js.map} +1 -1
  107. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DHgYfzwt.js → requirementDiagram-Z7DCOOCP-CeG2yodp.js} +4 -4
  108. package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DHgYfzwt.js.map → requirementDiagram-Z7DCOOCP-CeG2yodp.js.map} +1 -1
  109. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-Cuhwe80W.js → sankeyDiagram-WA2Y5GQK-B_l8tKqa.js} +2 -2
  110. package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-Cuhwe80W.js.map → sankeyDiagram-WA2Y5GQK-B_l8tKqa.js.map} +1 -1
  111. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DqSNoro8.js → sequenceDiagram-2WXFIKYE-Dc5gBIi5.js} +4 -4
  112. package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DqSNoro8.js.map → sequenceDiagram-2WXFIKYE-Dc5gBIi5.js.map} +1 -1
  113. package/webapp/dist/assets/{stateDiagram-RAJIS63D-D1mvuJi6.js → stateDiagram-RAJIS63D-DMYeNS1r.js} +9 -9
  114. package/webapp/dist/assets/{stateDiagram-RAJIS63D-D1mvuJi6.js.map → stateDiagram-RAJIS63D-DMYeNS1r.js.map} +1 -1
  115. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BCYX5Gy-.js → stateDiagram-v2-FVOUBMTO-MfUJuUEe.js} +5 -5
  116. package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-BCYX5Gy-.js.map → stateDiagram-v2-FVOUBMTO-MfUJuUEe.js.map} +1 -1
  117. package/webapp/dist/assets/{timeline-definition-YZTLITO2-DDLYGao7.js → timeline-definition-YZTLITO2-Ci2CZEky.js} +3 -3
  118. package/webapp/dist/assets/{timeline-definition-YZTLITO2-DDLYGao7.js.map → timeline-definition-YZTLITO2-Ci2CZEky.js.map} +1 -1
  119. package/webapp/dist/assets/{treemap-KZPCXAKY-DXkv1e6y.js → treemap-KZPCXAKY-CNgzp4sT.js} +5 -5
  120. package/webapp/dist/assets/{treemap-KZPCXAKY-DXkv1e6y.js.map → treemap-KZPCXAKY-CNgzp4sT.js.map} +1 -1
  121. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DMxsg9P0.js → vennDiagram-LZ73GAT5-BYxtNx2s.js} +2 -2
  122. package/webapp/dist/assets/{vennDiagram-LZ73GAT5-DMxsg9P0.js.map → vennDiagram-LZ73GAT5-BYxtNx2s.js.map} +1 -1
  123. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-BJ2qipzT.js → xychartDiagram-JWTSCODW-BUS3bn9p.js} +3 -3
  124. package/webapp/dist/assets/{xychartDiagram-JWTSCODW-BJ2qipzT.js.map → xychartDiagram-JWTSCODW-BUS3bn9p.js.map} +1 -1
  125. package/webapp/dist/index.html +1 -1
@@ -16,7 +16,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.OpenAiCompatibleGen = void 0;
19
+ exports.resolveOpenAiCompatibleToolChoice = resolveOpenAiCompatibleToolChoice;
19
20
  exports.buildOpenAiCompatibleExtraParamsForTest = buildOpenAiCompatibleExtraParamsForTest;
21
+ exports.wrapOpenAiCompatibleRejectedRequestErrorForTest = wrapOpenAiCompatibleRejectedRequestErrorForTest;
20
22
  exports.buildOpenAiCompatibleRequestMessagesWrapper = buildOpenAiCompatibleRequestMessagesWrapper;
21
23
  exports.consumeOpenAiCompatibleChatCompletionStreamForTest = consumeOpenAiCompatibleChatCompletionStreamForTest;
22
24
  exports.chatCompletionToChatMessagesForTest = chatCompletionToChatMessagesForTest;
@@ -38,15 +40,19 @@ const tool_result_image_ingest_1 = require("./tool-result-image-ingest");
38
40
  const log = (0, log_1.createLogger)('llm/openai-compatible');
39
41
  const OPENAI_COMPAT_CAPTURE_SSE_ENV = 'DOMINDS_OPENAI_COMPAT_CAPTURE_SSE';
40
42
  const OPENAI_COMPAT_CAPTURE_DIR_ENV = 'DOMINDS_OPENAI_COMPAT_CAPTURE_DIR';
43
+ const OPENAI_COMPAT_REJECTED_DIR_ENV = 'DOMINDS_OPENAI_COMPAT_REJECTED_DIR';
41
44
  const OPENAI_COMPATIBLE_MALFORMED_BATCH_TOOL_CALL_ERROR_CODE = 'OPENAI_COMPATIBLE_MALFORMED_BATCH_TOOL_CALL';
42
- function resolveOpenAiCompatibleToolChoice(funcTools, requestContext) {
45
+ const OPENAI_COMPATIBLE_REJECTED_REQUEST_ERROR_CODE = 'OPENAI_COMPATIBLE_REJECTED_REQUEST';
46
+ function resolveOpenAiCompatibleToolChoice(funcTools, requestContext, modelInfo) {
43
47
  const requirement = requestContext.toolUseRequirement ?? 'auto';
44
48
  if (funcTools.length === 0) {
45
49
  if (requirement === 'required') {
46
50
  throw new Error(`OpenAI-compatible request invariant violation: toolUseRequirement=required but no tools are available (dialog=${requestContext.dialogSelfId})`);
47
51
  }
48
- return 'none';
52
+ return modelInfo?.supports_tool_choice === false ? undefined : 'none';
49
53
  }
54
+ if (modelInfo?.supports_tool_choice === false)
55
+ return undefined;
50
56
  if (requirement === 'none')
51
57
  return 'none';
52
58
  if (requirement === 'required')
@@ -56,6 +62,15 @@ function resolveOpenAiCompatibleToolChoice(funcTools, requestContext) {
56
62
  function resolveOpenAiCompatibleRequestTools(funcTools, requestContext) {
57
63
  return (requestContext.toolUseRequirement ?? 'auto') === 'none' ? [] : [...funcTools];
58
64
  }
65
+ function resolveOpenAiCompatibleRequestModelInfo(providerConfig, agent, requestContext) {
66
+ const requestModelKey = requestContext.modelKey;
67
+ const modelKey = typeof requestModelKey === 'string' && requestModelKey.trim() !== ''
68
+ ? requestModelKey
69
+ : agent.model;
70
+ if (typeof modelKey !== 'string' || modelKey.trim() === '')
71
+ return undefined;
72
+ return providerConfig.models[modelKey];
73
+ }
59
74
  function isOpenAiCompatibleSseCaptureEnabled() {
60
75
  const configured = process.env[OPENAI_COMPAT_CAPTURE_SSE_ENV]?.trim().toLowerCase();
61
76
  return configured === '1' || configured === 'true' || configured === 'yes' || configured === 'on';
@@ -66,12 +81,25 @@ function resolveOpenAiCompatibleCaptureDir() {
66
81
  return path_1.default.resolve(configured);
67
82
  return path_1.default.resolve(process.cwd(), '.dialogs', 'debug', 'openai-compatible-sse');
68
83
  }
84
+ function resolveOpenAiCompatibleRejectedDir() {
85
+ const configured = process.env[OPENAI_COMPAT_REJECTED_DIR_ENV]?.trim();
86
+ if (configured && configured.length > 0)
87
+ return path_1.default.resolve(configured);
88
+ return path_1.default.resolve(process.cwd(), '.dialogs', 'debug', 'openai-compatible-rejected');
89
+ }
69
90
  function sanitizeCapturePathPart(value) {
70
91
  const sanitized = value.replace(/[^a-zA-Z0-9_.-]+/g, '_').replace(/^_+|_+$/g, '');
71
92
  if (sanitized.length === 0)
72
93
  return 'unknown';
73
94
  return sanitized.slice(0, 96);
74
95
  }
96
+ function formatRejectedCaptureFailureDetail(error) {
97
+ const raw = error instanceof Error ? error.message : String(error);
98
+ const compact = raw.replace(/\s+/g, ' ').trim();
99
+ if (compact.length === 0)
100
+ return 'unknown debug capture failure';
101
+ return compact.slice(0, 500);
102
+ }
75
103
  function buildOpenAiCompatibleCaptureId(context) {
76
104
  const now = new Date().toISOString().replace(/[:.]/g, '-');
77
105
  const suffix = Math.random().toString(36).slice(2, 10);
@@ -84,6 +112,19 @@ function buildOpenAiCompatibleCaptureId(context) {
84
112
  suffix,
85
113
  ].join('__');
86
114
  }
115
+ function buildOpenAiCompatibleRejectedCaptureId(context) {
116
+ const now = new Date().toISOString().replace(/[:.]/g, '-');
117
+ const suffix = Math.random().toString(36).slice(2, 10);
118
+ return [
119
+ now,
120
+ sanitizeCapturePathPart(context.providerKey ?? context.providerName),
121
+ sanitizeCapturePathPart(context.model),
122
+ sanitizeCapturePathPart(context.dialogSelfId),
123
+ `g${String(context.genseq)}`,
124
+ context.requestKind,
125
+ suffix,
126
+ ].join('__');
127
+ }
87
128
  function redactHttpHeader(name, value) {
88
129
  const normalized = name.toLowerCase();
89
130
  if (normalized === 'authorization' ||
@@ -206,6 +247,52 @@ async function startOpenAiCompatibleCapture(context, input, init) {
206
247
  });
207
248
  return record;
208
249
  }
250
+ async function writeOpenAiCompatibleRejectedCapture(args) {
251
+ const captureRoot = resolveOpenAiCompatibleRejectedDir();
252
+ const id = buildOpenAiCompatibleRejectedCaptureId(args.context);
253
+ const dir = path_1.default.join(captureRoot, id);
254
+ await promises_1.default.mkdir(dir, { recursive: true });
255
+ const record = {
256
+ id,
257
+ dir,
258
+ metaPath: path_1.default.join(dir, 'meta.json'),
259
+ requestPayloadPath: path_1.default.join(dir, 'request-payload.json'),
260
+ };
261
+ await writeCaptureJson(record.requestPayloadPath, args.payload);
262
+ await writeCaptureJson(record.metaPath, {
263
+ id,
264
+ capturedAt: new Date().toISOString(),
265
+ context: args.context,
266
+ request: {
267
+ payloadPath: record.requestPayloadPath,
268
+ },
269
+ error: {
270
+ name: args.error instanceof Error ? args.error.name : undefined,
271
+ message: args.context.upstreamMessage,
272
+ status: args.context.status,
273
+ code: args.context.code,
274
+ },
275
+ });
276
+ return record;
277
+ }
278
+ async function tryWriteOpenAiCompatibleRejectedCapture(args) {
279
+ try {
280
+ return { kind: 'captured', record: await writeOpenAiCompatibleRejectedCapture(args) };
281
+ }
282
+ catch (error) {
283
+ const detail = formatRejectedCaptureFailureDetail(error);
284
+ log.error('OPENAI-COMPATIBLE rejected request debug capture failed', error, {
285
+ providerKey: args.context.providerKey,
286
+ providerName: args.context.providerName,
287
+ model: args.context.model,
288
+ rootId: args.context.dialogRootId,
289
+ selfId: args.context.dialogSelfId,
290
+ genseq: args.context.genseq,
291
+ requestKind: args.context.requestKind,
292
+ });
293
+ return { kind: 'capture_failed', detail };
294
+ }
295
+ }
209
296
  function parseSseFrameData(frame) {
210
297
  const lines = frame.split(/\r?\n/);
211
298
  const eventLine = lines.find((line) => line.startsWith('event:'));
@@ -546,9 +633,68 @@ function buildOpenAiCompatibleExtraParams(args) {
546
633
  ...(reasoningEffort !== undefined ? { reasoning_effort: reasoningEffort } : {}),
547
634
  };
548
635
  }
636
+ async function wrapOpenAiCompatibleRejectedRequestError(args) {
637
+ const status = (0, failure_classifier_1.readErrorStatus)(args.error);
638
+ if (status !== 400)
639
+ return args.error;
640
+ const providerKey = args.requestContext.providerKey ?? args.providerConfig.name;
641
+ const modelKey = args.requestContext.modelKey ?? args.agent.model ?? 'unknown';
642
+ const code = (0, failure_classifier_1.readErrorCode)(args.error);
643
+ const upstreamMessage = args.error instanceof Error ? args.error.message : String(args.error);
644
+ const captureContext = {
645
+ providerKey,
646
+ providerName: args.providerConfig.name.trim().length > 0 ? args.providerConfig.name : providerKey,
647
+ model: modelKey,
648
+ dialogRootId: args.requestContext.dialogRootId,
649
+ dialogSelfId: args.requestContext.dialogSelfId,
650
+ requestKind: args.requestKind,
651
+ genseq: args.genseq,
652
+ status,
653
+ ...(code !== undefined && { code }),
654
+ upstreamMessage,
655
+ };
656
+ const capture = await tryWriteOpenAiCompatibleRejectedCapture({
657
+ context: captureContext,
658
+ payload: args.payload,
659
+ error: args.error,
660
+ });
661
+ const captureMessageLines = capture.kind === 'captured'
662
+ ? [
663
+ `debugPath=${capture.record.dir}`,
664
+ `requestPayloadPath=${capture.record.requestPayloadPath}`,
665
+ ]
666
+ : [`debugCaptureError=${capture.detail}`];
667
+ const message = [
668
+ `OPENAI-compatible provider rejected ${args.requestKind} request with HTTP 400.`,
669
+ `provider=${providerKey}`,
670
+ `model=${modelKey}`,
671
+ `rootId=${args.requestContext.dialogRootId}`,
672
+ `selfId=${args.requestContext.dialogSelfId}`,
673
+ `genseq=${String(args.genseq)}`,
674
+ `upstream=${upstreamMessage}`,
675
+ ...captureMessageLines,
676
+ ].join('\n');
677
+ const wrapped = new Error(message);
678
+ wrapped.name = 'OpenAiCompatibleRejectedRequestError';
679
+ wrapped.cause = args.error;
680
+ wrapped.status = status;
681
+ wrapped.statusCode = status;
682
+ wrapped.code = code ?? OPENAI_COMPATIBLE_REJECTED_REQUEST_ERROR_CODE;
683
+ if (capture.kind === 'captured') {
684
+ wrapped.debugPath = capture.record.dir;
685
+ wrapped.requestPayloadPath = capture.record.requestPayloadPath;
686
+ }
687
+ else {
688
+ wrapped.debugCaptureError = capture.detail;
689
+ }
690
+ return wrapped;
691
+ }
549
692
  function buildOpenAiCompatibleExtraParamsForTest(args) {
550
693
  return buildOpenAiCompatibleExtraParams(args);
551
694
  }
695
+ async function wrapOpenAiCompatibleRejectedRequestErrorForTest(args) {
696
+ return await wrapOpenAiCompatibleRejectedRequestError(args);
697
+ }
552
698
  function extractThinkingReasoningText(msg) {
553
699
  const fromSummary = msg.reasoning?.summary.map((part) => part.text).join('') ?? '';
554
700
  const fromContent = msg.reasoning?.content?.map((part) => part.text).join('') ?? '';
@@ -1363,6 +1509,8 @@ class OpenAiCompatibleGen {
1363
1509
  const parallelToolCalls = openAiParams.parallel_tool_calls ?? true;
1364
1510
  const responseFormat = buildChatCompletionResponseFormat(openAiParams);
1365
1511
  const requestTools = resolveOpenAiCompatibleRequestTools(funcTools, requestContext);
1512
+ const modelInfo = resolveOpenAiCompatibleRequestModelInfo(providerConfig, agent, requestContext);
1513
+ const toolChoice = resolveOpenAiCompatibleToolChoice(requestTools, requestContext, modelInfo);
1366
1514
  const openAiCompatibleExtraParams = buildOpenAiCompatibleExtraParams({
1367
1515
  agent,
1368
1516
  openAiParams,
@@ -1381,7 +1529,7 @@ class OpenAiCompatibleGen {
1381
1529
  ...openAiCompatibleExtraParams,
1382
1530
  ...(responseFormat !== undefined && { response_format: responseFormat }),
1383
1531
  ...(requestTools.length > 0 ? { tools: requestTools.map(funcToolToChatCompletionTool) } : {}),
1384
- tool_choice: resolveOpenAiCompatibleToolChoice(requestTools, requestContext),
1532
+ ...(toolChoice !== undefined && { tool_choice: toolChoice }),
1385
1533
  parallel_tool_calls: parallelToolCalls,
1386
1534
  };
1387
1535
  try {
@@ -1396,8 +1544,23 @@ class OpenAiCompatibleGen {
1396
1544
  });
1397
1545
  }
1398
1546
  catch (error) {
1399
- log.warn('OPENAI-COMPATIBLE streaming error', error);
1400
- throw error;
1547
+ const enrichedError = await wrapOpenAiCompatibleRejectedRequestError({
1548
+ error,
1549
+ providerConfig,
1550
+ agent,
1551
+ requestContext,
1552
+ genseq,
1553
+ requestKind: 'stream',
1554
+ payload,
1555
+ });
1556
+ log.warn('OPENAI-COMPATIBLE streaming error', enrichedError, {
1557
+ providerKey: requestContext.providerKey ?? providerConfig.name,
1558
+ model: requestContext.modelKey ?? agent.model,
1559
+ rootId: requestContext.dialogRootId,
1560
+ selfId: requestContext.dialogSelfId,
1561
+ genseq,
1562
+ });
1563
+ throw enrichedError;
1401
1564
  }
1402
1565
  }
1403
1566
  async genMoreMessages(providerConfig, agent, systemPrompt, funcTools, requestContext, context, genseq, abortSignal) {
@@ -1428,6 +1591,8 @@ class OpenAiCompatibleGen {
1428
1591
  const parallelToolCalls = openAiParams.parallel_tool_calls ?? true;
1429
1592
  const responseFormat = buildChatCompletionResponseFormat(openAiParams);
1430
1593
  const requestTools = resolveOpenAiCompatibleRequestTools(funcTools, requestContext);
1594
+ const modelInfo = resolveOpenAiCompatibleRequestModelInfo(providerConfig, agent, requestContext);
1595
+ const toolChoice = resolveOpenAiCompatibleToolChoice(requestTools, requestContext, modelInfo);
1431
1596
  const openAiCompatibleExtraParams = buildOpenAiCompatibleExtraParams({
1432
1597
  agent,
1433
1598
  openAiParams,
@@ -1444,7 +1609,7 @@ class OpenAiCompatibleGen {
1444
1609
  ...openAiCompatibleExtraParams,
1445
1610
  ...(responseFormat !== undefined && { response_format: responseFormat }),
1446
1611
  ...(requestTools.length > 0 && { tools: requestTools.map(funcToolToChatCompletionTool) }),
1447
- tool_choice: resolveOpenAiCompatibleToolChoice(requestTools, requestContext),
1612
+ ...(toolChoice !== undefined && { tool_choice: toolChoice }),
1448
1613
  parallel_tool_calls: parallelToolCalls,
1449
1614
  };
1450
1615
  try {
@@ -1466,8 +1631,23 @@ class OpenAiCompatibleGen {
1466
1631
  };
1467
1632
  }
1468
1633
  catch (error) {
1469
- log.warn('OPENAI-COMPATIBLE batch error', error);
1470
- throw error;
1634
+ const enrichedError = await wrapOpenAiCompatibleRejectedRequestError({
1635
+ error,
1636
+ providerConfig,
1637
+ agent,
1638
+ requestContext,
1639
+ genseq,
1640
+ requestKind: 'batch',
1641
+ payload,
1642
+ });
1643
+ log.warn('OPENAI-COMPATIBLE batch error', enrichedError, {
1644
+ providerKey: requestContext.providerKey ?? providerConfig.name,
1645
+ model: requestContext.modelKey ?? agent.model,
1646
+ rootId: requestContext.dialogRootId,
1647
+ selfId: requestContext.dialogSelfId,
1648
+ genseq,
1649
+ });
1650
+ throw enrichedError;
1471
1651
  }
1472
1652
  }
1473
1653
  }
package/dist/llm/gen.d.ts CHANGED
@@ -56,7 +56,6 @@ export interface LlmRequestContext {
56
56
  modelKey?: string;
57
57
  promptCacheKey?: string;
58
58
  toolUseRequirement?: 'none' | 'auto' | 'required';
59
- knownFunctionCallIds?: ReadonlySet<string>;
60
59
  }
61
60
  export type ToolResultImageIngest = {
62
61
  toolCallId: string;
@@ -146,7 +145,10 @@ export interface LlmStreamReceiver {
146
145
  sayingStart: () => Promise<void>;
147
146
  sayingChunk: (chunk: string) => Promise<void>;
148
147
  sayingFinish: () => Promise<void>;
149
- funcCall: (callId: string, name: string, args: string) => Promise<void>;
148
+ funcCall: (callId: string, name: string, args: string, ids?: {
149
+ rawCallId?: string;
150
+ effectiveCallId?: string;
151
+ }) => Promise<void>;
150
152
  webSearchCall?: (call: LlmWebSearchCall) => Promise<void>;
151
153
  nativeToolCall?: (call: OpenAiResponsesNativeToolCall) => Promise<void>;
152
154
  toolResultImageIngest?: (ingest: ToolResultImageIngest) => Promise<void>;