@straiffi/archon 1.8.11 → 1.8.13

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 (128) hide show
  1. package/dist/client/assets/{ActivityView-DZV4XUv5.js → ActivityView-DD1Fom-k.js} +1 -1
  2. package/dist/client/assets/{GitHubActionsDialog-DllnU-XT.js → GitHubActionsDialog-aDf_6y6m.js} +1 -1
  3. package/dist/client/assets/{RepositoryGraphDialog-CrQ6MxMs.js → RepositoryGraphDialog-B4Ij2xmA.js} +1 -1
  4. package/dist/client/assets/VerificationDialog-BBCRKTdr.js +4 -0
  5. package/dist/client/assets/{architectureDiagram-3BPJPVTR-N5146a3S.js → architectureDiagram-3BPJPVTR-DW3kiEe6.js} +1 -1
  6. package/dist/client/assets/{blockDiagram-GPEHLZMM-CTcYKML0.js → blockDiagram-GPEHLZMM-BVWrspTj.js} +1 -1
  7. package/dist/client/assets/{c4Diagram-AAUBKEIU-B6KtPTDy.js → c4Diagram-AAUBKEIU-CDqXjYR1.js} +1 -1
  8. package/dist/client/assets/channel-C14KP1Bm.js +1 -0
  9. package/dist/client/assets/{chunk-2J33WTMH-BQpseL_z.js → chunk-2J33WTMH-Db4bg8nj.js} +1 -1
  10. package/dist/client/assets/{chunk-3OPIFGDE-ODMBF3_2.js → chunk-3OPIFGDE-DqziKs5m.js} +1 -1
  11. package/dist/client/assets/{chunk-5ZQYHXKU-BQkjE9zf.js → chunk-5ZQYHXKU-wdN7gQNo.js} +1 -1
  12. package/dist/client/assets/{chunk-727SXJPM-i-cz4gzR.js → chunk-727SXJPM-Dj3aKc06.js} +1 -1
  13. package/dist/client/assets/{chunk-AQP2D5EJ-La2Fm8rX.js → chunk-AQP2D5EJ-CAlE_C_J.js} +1 -1
  14. package/dist/client/assets/{chunk-CSCIHK7Q-UilBsGGE.js → chunk-CSCIHK7Q-KstW8JRv.js} +1 -1
  15. package/dist/client/assets/{chunk-KSCS5N6A-CflYh1HZ.js → chunk-KSCS5N6A-DrY-9bi9.js} +1 -1
  16. package/dist/client/assets/{chunk-L5ZTLDWV-BJEWtfsH.js → chunk-L5ZTLDWV-C6fw_Dab.js} +1 -1
  17. package/dist/client/assets/{chunk-LZXEDZCA-C4d0AP9G.js → chunk-LZXEDZCA-DaZP5hZq.js} +2 -2
  18. package/dist/client/assets/{chunk-ND2GUHAM-C6MmukYU.js → chunk-ND2GUHAM-ChYXM7G3.js} +1 -1
  19. package/dist/client/assets/{chunk-NZK2D7GU--wEL0wvv.js → chunk-NZK2D7GU-JajrDJgw.js} +1 -1
  20. package/dist/client/assets/{chunk-O5CBEL6O-Cz9pgEVx.js → chunk-O5CBEL6O-C4HoCf_q.js} +1 -1
  21. package/dist/client/assets/{chunk-WU5MYG2G-B6fT5FbV.js → chunk-WU5MYG2G-BdjAiDOI.js} +1 -1
  22. package/dist/client/assets/classDiagram-4FO5ZUOK-CR20Gg9e.js +1 -0
  23. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B-N-i15d.js +1 -0
  24. package/dist/client/assets/{dagre-BM42HDAG-B0PyS1FL.js → dagre-BM42HDAG-CpXupRCy.js} +1 -1
  25. package/dist/client/assets/{diagram-2AECGRRQ-CvtQVi1p.js → diagram-2AECGRRQ-DyopuXBv.js} +1 -1
  26. package/dist/client/assets/{diagram-5GNKFQAL-UnDOww2D.js → diagram-5GNKFQAL-C8lS8Vro.js} +1 -1
  27. package/dist/client/assets/{diagram-KO2AKTUF-DKoH-jJ2.js → diagram-KO2AKTUF-CsyC_xgK.js} +1 -1
  28. package/dist/client/assets/{diagram-LMA3HP47-LZrMP400.js → diagram-LMA3HP47-DWsQdA71.js} +1 -1
  29. package/dist/client/assets/{diagram-OG6HWLK6-paUHgI0c.js → diagram-OG6HWLK6-YkNa_Tt6.js} +1 -1
  30. package/dist/client/assets/{erDiagram-TEJ5UH35-CP8NLTFn.js → erDiagram-TEJ5UH35-VmMz5G_L.js} +1 -1
  31. package/dist/client/assets/{flowDiagram-I6XJVG4X-avS4UFeu.js → flowDiagram-I6XJVG4X-DZAu6IJl.js} +1 -1
  32. package/dist/client/assets/{ganttDiagram-6RSMTGT7-Bvl128Wz.js → ganttDiagram-6RSMTGT7-CHJRz_2M.js} +1 -1
  33. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CJgbaHl7.js → gitGraphDiagram-PVQCEYII-BfA1qYTR.js} +1 -1
  34. package/dist/client/assets/index-B4x8ZZ8N.js +275 -0
  35. package/dist/client/assets/index-CCQwWUKF.css +2 -0
  36. package/dist/client/assets/{infoDiagram-5YYISTIA-BIFDf_rC.js → infoDiagram-5YYISTIA-CyqqEYvx.js} +1 -1
  37. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DoCriMKl.js → ishikawaDiagram-YF4QCWOH-DnXMvxPm.js} +1 -1
  38. package/dist/client/assets/{journeyDiagram-JHISSGLW-CdTptvEe.js → journeyDiagram-JHISSGLW-DBumlehf.js} +1 -1
  39. package/dist/client/assets/{kanban-definition-UN3LZRKU-BC1ZCmbd.js → kanban-definition-UN3LZRKU-D-QvfQhh.js} +1 -1
  40. package/dist/client/assets/{line-C_yPvd0q.js → line-BgwSCyaP.js} +1 -1
  41. package/dist/client/assets/{mermaid-parser.core-BxaoFpKE.js → mermaid-parser.core-qDA1puIK.js} +1 -1
  42. package/dist/client/assets/{mermaid.core-BQdOGFuG.js → mermaid.core-CFM-fuJi.js} +3 -3
  43. package/dist/client/assets/{mindmap-definition-RKZ34NQL-v_WYf2A1.js → mindmap-definition-RKZ34NQL-B93RAITk.js} +1 -1
  44. package/dist/client/assets/{pieDiagram-4H26LBE5-BRQ8es8D.js → pieDiagram-4H26LBE5-C9arDpCE.js} +1 -1
  45. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Dm3Zr3El.js → quadrantDiagram-W4KKPZXB-Tma_RsUu.js} +1 -1
  46. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BotklrXj.js → requirementDiagram-4Y6WPE33-C6GCxpqT.js} +1 -1
  47. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Bt86Y-ht.js → sankeyDiagram-5OEKKPKP-CY8ukFyG.js} +1 -1
  48. package/dist/client/assets/{sequenceDiagram-3UESZ5HK--2FukK6-.js → sequenceDiagram-3UESZ5HK-B6MbhJm7.js} +1 -1
  49. package/dist/client/assets/{stateDiagram-AJRCARHV-BkimDXmB.js → stateDiagram-AJRCARHV-Bjy1dBVk.js} +1 -1
  50. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-asf2fsPC.js +1 -0
  51. package/dist/client/assets/{timeline-definition-PNZ67QCA-sxDyme1L.js → timeline-definition-PNZ67QCA-KrbaHcGf.js} +1 -1
  52. package/dist/client/assets/{vennDiagram-CIIHVFJN-CuqwFpba.js → vennDiagram-CIIHVFJN-DQ-5gbga.js} +1 -1
  53. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-CNT6_pw9.js → wardleyDiagram-YWT4CUSO-Cwpu-hvf.js} +1 -1
  54. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BgW2O1VI.js → xychartDiagram-2RQKCTM6-DoP4HxQE.js} +1 -1
  55. package/dist/client/index.html +2 -2
  56. package/dist/server/db.js +78 -2
  57. package/dist/server/db.js.map +1 -1
  58. package/dist/server/index.js +85 -13
  59. package/dist/server/index.js.map +1 -1
  60. package/dist/server/lib/agent.js +53 -91
  61. package/dist/server/lib/agent.js.map +1 -1
  62. package/dist/server/lib/automationReconciliation.js +20 -0
  63. package/dist/server/lib/automationReconciliation.js.map +1 -1
  64. package/dist/server/lib/automationResumeDecision.js +2 -2
  65. package/dist/server/lib/automationResumeDecision.js.map +1 -1
  66. package/dist/server/lib/buildCompletionContinuation.js +1 -1
  67. package/dist/server/lib/buildCompletionContinuation.js.map +1 -1
  68. package/dist/server/lib/checkRepairDispatch.js +14 -4
  69. package/dist/server/lib/checkRepairDispatch.js.map +1 -1
  70. package/dist/server/lib/checkRuns.js +14 -0
  71. package/dist/server/lib/checkRuns.js.map +1 -1
  72. package/dist/server/lib/executionReconciliation.js +43 -4
  73. package/dist/server/lib/executionReconciliation.js.map +1 -1
  74. package/dist/server/lib/executionRetry.js +16 -9
  75. package/dist/server/lib/executionRetry.js.map +1 -1
  76. package/dist/server/lib/executionRetryPredicates.js +12 -3
  77. package/dist/server/lib/executionRetryPredicates.js.map +1 -1
  78. package/dist/server/lib/figmaResources.js +6 -2
  79. package/dist/server/lib/figmaResources.js.map +1 -1
  80. package/dist/server/lib/git.js +4 -4
  81. package/dist/server/lib/git.js.map +1 -1
  82. package/dist/server/lib/lightweightPrompt.js +12 -48
  83. package/dist/server/lib/lightweightPrompt.js.map +1 -1
  84. package/dist/server/lib/opencodeErrors.js +35 -0
  85. package/dist/server/lib/opencodeErrors.js.map +1 -0
  86. package/dist/server/lib/opencodePromptOutput.js +112 -0
  87. package/dist/server/lib/opencodePromptOutput.js.map +1 -0
  88. package/dist/server/lib/postBuildCheckRuns.js +16 -12
  89. package/dist/server/lib/postBuildCheckRuns.js.map +1 -1
  90. package/dist/server/lib/postBuildChecks.js +45 -43
  91. package/dist/server/lib/postBuildChecks.js.map +1 -1
  92. package/dist/server/lib/previewProxy.js +36 -4
  93. package/dist/server/lib/previewProxy.js.map +1 -1
  94. package/dist/server/lib/projectAutoConfig.js +18 -91
  95. package/dist/server/lib/projectAutoConfig.js.map +1 -1
  96. package/dist/server/lib/projects.js +34 -6
  97. package/dist/server/lib/projects.js.map +1 -1
  98. package/dist/server/lib/reviewContext.js +10 -5
  99. package/dist/server/lib/reviewContext.js.map +1 -1
  100. package/dist/server/lib/reviewFindings.js +186 -27
  101. package/dist/server/lib/reviewFindings.js.map +1 -1
  102. package/dist/server/lib/reviewerConfig.js +23 -0
  103. package/dist/server/lib/reviewerConfig.js.map +1 -0
  104. package/dist/server/lib/specReviewOperations.js +64 -9
  105. package/dist/server/lib/specReviewOperations.js.map +1 -1
  106. package/dist/server/lib/ticketFollowUpOperations.js +28 -0
  107. package/dist/server/lib/ticketFollowUpOperations.js.map +1 -1
  108. package/dist/server/lib/tickets.js +15 -0
  109. package/dist/server/lib/tickets.js.map +1 -1
  110. package/dist/server/lib/types.js.map +1 -1
  111. package/dist/server/workers/build.js +8 -1
  112. package/dist/server/workers/build.js.map +1 -1
  113. package/dist/server/workers/chat.js +5 -2
  114. package/dist/server/workers/chat.js.map +1 -1
  115. package/dist/server/workers/followUp.js +6 -1
  116. package/dist/server/workers/followUp.js.map +1 -1
  117. package/dist/server/workers/review.js +147 -60
  118. package/dist/server/workers/review.js.map +1 -1
  119. package/dist/server/workers/specReview.js +26 -11
  120. package/dist/server/workers/specReview.js.map +1 -1
  121. package/package.json +1 -1
  122. package/dist/client/assets/VerificationDialog-aKNCXSi7.js +0 -4
  123. package/dist/client/assets/channel-Dc3uo-0Q.js +0 -1
  124. package/dist/client/assets/classDiagram-4FO5ZUOK-CPqs9EFT.js +0 -1
  125. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-D95HVzC8.js +0 -1
  126. package/dist/client/assets/index-BdIJvP4n.js +0 -274
  127. package/dist/client/assets/index-BsjoiBxI.css +0 -2
  128. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B-x02NWy.js +0 -1
@@ -17,6 +17,8 @@ import { markTicketDescriptionVisibleInBundle } from './ticketMessages.js';
17
17
  import { getTicket } from './tickets.js';
18
18
  import { createTranscriptRunSnapshots } from './transcriptRuns.js';
19
19
  import { createWorkspaceProcessEnvironment } from './workspaceProcessEnvironment.js';
20
+ import { OpencodeModelResolutionError, parseOpencodeError, parseOpencodeStderrModelResolutionError, } from './opencodeErrors.js';
21
+ import { extractLeadingOpencodeJsonObjects } from './opencodePromptOutput.js';
20
22
  import { assertAgentSpawnPermit, AgentSpawnPermitRevokedError } from './agentSpawnPermits.js';
21
23
  const withTranscriptRuns = (value, transcriptRuns) => {
22
24
  return transcriptRuns ? { ...value, transcriptRuns } : value;
@@ -25,6 +27,8 @@ const createOpencodeRecoveryTracker = () => {
25
27
  let sawError = false;
26
28
  let latestEvent = null;
27
29
  let recoveredFinalAnswerFragments = [];
30
+ let latestError = null;
31
+ let modelResolutionError = null;
28
32
  return {
29
33
  consume: events => {
30
34
  let shouldResetResponse = false;
@@ -32,6 +36,10 @@ const createOpencodeRecoveryTracker = () => {
32
36
  latestEvent = event.type;
33
37
  if (event.type === 'error') {
34
38
  sawError = true;
39
+ latestError = event.error;
40
+ if (event.error?.isModelResolutionError) {
41
+ modelResolutionError = event.error;
42
+ }
35
43
  recoveredFinalAnswerFragments = [];
36
44
  shouldResetResponse = true;
37
45
  continue;
@@ -46,12 +54,21 @@ const createOpencodeRecoveryTracker = () => {
46
54
  && latestEvent === 'final_answer'
47
55
  && recoveredFinalAnswerFragments.length > 0),
48
56
  hasUnrecoveredError: () => latestEvent === 'error',
57
+ getModelResolutionError: () => modelResolutionError,
58
+ getUnrecoveredError: () => latestEvent === 'error' ? latestError : null,
49
59
  getRecoveredResponse: () => recoveredFinalAnswerFragments.join('\n\n'),
50
60
  };
51
61
  };
52
- const isSuccessfulOpencodeExit = (code, modelError, recoveryTracker) => (!modelError
62
+ const isSuccessfulOpencodeExit = (code, stderrModelError, recoveryTracker) => (!stderrModelError
63
+ && !recoveryTracker.getModelResolutionError()
53
64
  && !recoveryTracker.hasUnrecoveredError()
54
65
  && (code === 0 || recoveryTracker.hasRecoveredFinalAnswer()));
66
+ const createOpencodeExitError = (message, stderrModelError, recoveryTracker) => {
67
+ const structuredError = recoveryTracker.getModelResolutionError() ?? recoveryTracker.getUnrecoveredError();
68
+ return structuredError?.isModelResolutionError || stderrModelError
69
+ ? new OpencodeModelResolutionError(message)
70
+ : new Error(message);
71
+ };
55
72
  export class AgentContinuationRejectedError extends Error {
56
73
  constructor(message) {
57
74
  super(message);
@@ -284,7 +301,7 @@ export const mergeUsageFromJsonLine = (current, line) => {
284
301
  if (!trimmedLine.startsWith('{')) {
285
302
  return current;
286
303
  }
287
- const { jsonObjects } = extractLeadingJsonObjects(trimmedLine);
304
+ const { jsonObjects } = extractLeadingOpencodeJsonObjects(trimmedLine);
288
305
  let next = current;
289
306
  for (const jsonObject of jsonObjects) {
290
307
  try {
@@ -956,6 +973,7 @@ const emptyParsedStreamLine = () => ({
956
973
  responseFragment: null,
957
974
  subagentEvents: [],
958
975
  providerSessionId: null,
976
+ modelResolutionError: false,
959
977
  });
960
978
  const isExecutionCapableParsedStreamLine = (parsed) => (parsed.logFragment !== null
961
979
  || parsed.responseFragment !== null
@@ -1067,62 +1085,6 @@ const formatOpencodeStepTitle = (event) => {
1067
1085
  const title = event.part?.title?.trim();
1068
1086
  return title || null;
1069
1087
  };
1070
- const extractLeadingJsonObject = (line) => {
1071
- if (!line.startsWith('{')) {
1072
- return null;
1073
- }
1074
- let depth = 0;
1075
- let inString = false;
1076
- let escaping = false;
1077
- for (let index = 0; index < line.length; index += 1) {
1078
- const char = line[index];
1079
- if (inString) {
1080
- if (escaping) {
1081
- escaping = false;
1082
- continue;
1083
- }
1084
- if (char === '\\') {
1085
- escaping = true;
1086
- continue;
1087
- }
1088
- if (char === '"') {
1089
- inString = false;
1090
- }
1091
- continue;
1092
- }
1093
- if (char === '"') {
1094
- inString = true;
1095
- continue;
1096
- }
1097
- if (char === '{') {
1098
- depth += 1;
1099
- continue;
1100
- }
1101
- if (char === '}') {
1102
- depth -= 1;
1103
- if (depth === 0) {
1104
- return line.slice(0, index + 1);
1105
- }
1106
- }
1107
- }
1108
- return null;
1109
- };
1110
- const extractLeadingJsonObjects = (line) => {
1111
- const jsonObjects = [];
1112
- let remaining = line.trim();
1113
- while (remaining.startsWith('{')) {
1114
- const jsonObject = extractLeadingJsonObject(remaining);
1115
- if (!jsonObject) {
1116
- break;
1117
- }
1118
- jsonObjects.push(jsonObject);
1119
- remaining = remaining.slice(jsonObject.length).trim();
1120
- }
1121
- return {
1122
- jsonObjects,
1123
- remainder: remaining,
1124
- };
1125
- };
1126
1088
  const parseOpencodeJsonEvent = (event, cwd) => {
1127
1089
  const providerSessionId = event.sessionID?.trim()
1128
1090
  || event.sessionId?.trim()
@@ -1137,6 +1099,7 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1137
1099
  responseFragment: text && (!phase || phase === 'final_answer') ? text : null,
1138
1100
  subagentEvents: [],
1139
1101
  providerSessionId,
1102
+ modelResolutionError: false,
1140
1103
  recoveryEvents: text && phase === 'final_answer'
1141
1104
  ? [{ type: 'final_answer', text }]
1142
1105
  : [],
@@ -1149,6 +1112,7 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1149
1112
  responseFragment: null,
1150
1113
  subagentEvents: [],
1151
1114
  providerSessionId,
1115
+ modelResolutionError: false,
1152
1116
  };
1153
1117
  }
1154
1118
  if (event.type === 'tool' || event.type === 'tool_use' || event.type === 'tool_result') {
@@ -1188,6 +1152,7 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1188
1152
  : []),
1189
1153
  ],
1190
1154
  providerSessionId,
1155
+ modelResolutionError: false,
1191
1156
  };
1192
1157
  }
1193
1158
  if (!isToolInvocation) {
@@ -1199,6 +1164,7 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1199
1164
  responseFragment: null,
1200
1165
  subagentEvents: [],
1201
1166
  providerSessionId,
1167
+ modelResolutionError: false,
1202
1168
  };
1203
1169
  }
1204
1170
  if (event.type === 'step_start') {
@@ -1207,6 +1173,7 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1207
1173
  responseFragment: null,
1208
1174
  subagentEvents: [],
1209
1175
  providerSessionId,
1176
+ modelResolutionError: false,
1210
1177
  };
1211
1178
  }
1212
1179
  if (event.type === 'step_finish') {
@@ -1215,23 +1182,18 @@ const parseOpencodeJsonEvent = (event, cwd) => {
1215
1182
  responseFragment: null,
1216
1183
  subagentEvents: [],
1217
1184
  providerSessionId,
1185
+ modelResolutionError: false,
1218
1186
  };
1219
1187
  }
1220
1188
  if (event.type === 'error') {
1221
- const errorText = typeof event.error === 'string'
1222
- ? event.error.trim()
1223
- : event.error && typeof event.error === 'object'
1224
- ? (event.error.data?.message?.trim()
1225
- || event.error.message?.trim()
1226
- || JSON.stringify(event.error))
1227
- : '';
1228
- const text = event.part?.text?.trim() || errorText || '';
1189
+ const parsedError = parseOpencodeError(event.error, event.part?.text);
1190
+ const text = parsedError?.message ?? '';
1229
1191
  return {
1230
1192
  logFragment: text ? `**Error:** ${text}` : null,
1231
1193
  responseFragment: null,
1232
1194
  subagentEvents: [],
1233
1195
  providerSessionId,
1234
- recoveryEvents: [{ type: 'error' }],
1196
+ recoveryEvents: [{ type: 'error', error: parsedError }],
1235
1197
  };
1236
1198
  }
1237
1199
  return emptyParsedStreamLine();
@@ -1241,7 +1203,7 @@ const parseOpencodeJsonLine = (line, cwd) => {
1241
1203
  if (!trimmed) {
1242
1204
  return emptyParsedStreamLine();
1243
1205
  }
1244
- const { jsonObjects, remainder } = extractLeadingJsonObjects(trimmed);
1206
+ const { jsonObjects, remainder } = extractLeadingOpencodeJsonObjects(trimmed);
1245
1207
  if (jsonObjects.length === 0) {
1246
1208
  if (trimmed.startsWith('{')) {
1247
1209
  return emptyParsedStreamLine();
@@ -1259,13 +1221,14 @@ const parseOpencodeJsonLine = (line, cwd) => {
1259
1221
  }],
1260
1222
  };
1261
1223
  }
1262
- return { logFragment: trimmed, responseFragment: trimmed, subagentEvents: [], providerSessionId: null };
1224
+ return { logFragment: trimmed, responseFragment: trimmed, subagentEvents: [], providerSessionId: null, modelResolutionError: false };
1263
1225
  }
1264
1226
  const logFragments = [];
1265
1227
  const responseFragments = [];
1266
1228
  const subagentEvents = [];
1267
1229
  const recoveryEvents = [];
1268
1230
  let providerSessionId = null;
1231
+ let modelResolutionError = false;
1269
1232
  for (const jsonObject of jsonObjects) {
1270
1233
  let event;
1271
1234
  try {
@@ -1278,6 +1241,7 @@ const parseOpencodeJsonLine = (line, cwd) => {
1278
1241
  const { logFragment, responseFragment } = parsedEvent;
1279
1242
  subagentEvents.push(...parsedEvent.subagentEvents);
1280
1243
  recoveryEvents.push(...(parsedEvent.recoveryEvents ?? []));
1244
+ modelResolutionError ||= Boolean(parsedEvent.modelResolutionError);
1281
1245
  providerSessionId = providerSessionId ?? parsedEvent.providerSessionId;
1282
1246
  if (logFragment !== null) {
1283
1247
  logFragments.push(logFragment);
@@ -1308,6 +1272,7 @@ const parseOpencodeJsonLine = (line, cwd) => {
1308
1272
  responseFragment: responseFragments.length > 0 ? responseFragments.join('\n\n') : null,
1309
1273
  subagentEvents,
1310
1274
  providerSessionId,
1275
+ modelResolutionError,
1311
1276
  recoveryEvents,
1312
1277
  };
1313
1278
  }
@@ -1731,12 +1696,7 @@ const buildResponseTiming = ({ startTime, firstFinalAnswerTime, isStopped, }) =>
1731
1696
  const responseMs = Date.now() - firstFinalAnswerTime;
1732
1697
  return { totalMs, thinkingMs, responseMs };
1733
1698
  };
1734
- const isModelResolutionError = (message) => {
1735
- if (typeof message !== 'string') {
1736
- return false;
1737
- }
1738
- return /ProviderModelNotFoundError|Model not found/i.test(message);
1739
- };
1699
+ const isLegacyModelResolutionError = (message) => (typeof message === 'string' && /ProviderModelNotFoundError|Model not found/i.test(message));
1740
1700
  const isProcessAlive = (proc) => {
1741
1701
  if (!proc) {
1742
1702
  return false;
@@ -2221,7 +2181,7 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2221
2181
  const errOutput = Buffer.concat(stderrChunks).toString();
2222
2182
  const finalLog = logLines.join('\n\n') || errOutput;
2223
2183
  const finalResponse = responseLines.join('\n\n') || errOutput;
2224
- const modelError = isModelResolutionError(finalLog);
2184
+ const modelError = isLegacyModelResolutionError(errOutput);
2225
2185
  const timing = startTime ? { totalMs: Date.now() - startTime } : null;
2226
2186
  if (buildState?.stopRequested || reviewProcessState?.stopRequested) {
2227
2187
  const transcriptRuns = finalizeRun('stopped', finalLog, finalResponse);
@@ -2331,14 +2291,14 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2331
2291
  const finalResponse = recoveryTracker.hasRecoveredFinalAnswer()
2332
2292
  ? recoveredResponse
2333
2293
  : responseLines.join('\n\n') || stderrOutput;
2334
- const modelError = isModelResolutionError(log);
2294
+ const stderrModelError = parseOpencodeStderrModelResolutionError(stderrOutput);
2335
2295
  const timing = buildResponseTiming({ startTime, firstFinalAnswerTime, isStopped: Boolean(buildState?.stopRequested || reviewProcessState?.stopRequested) });
2336
2296
  if (buildState?.stopRequested || reviewProcessState?.stopRequested) {
2337
2297
  const transcriptRuns = finalizeRun('stopped', log, finalResponse);
2338
2298
  resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing }, transcriptRuns));
2339
2299
  return;
2340
2300
  }
2341
- if (isSuccessfulOpencodeExit(code, modelError, recoveryTracker)) {
2301
+ if (isSuccessfulOpencodeExit(code, stderrModelError, recoveryTracker)) {
2342
2302
  const transcriptRuns = finalizeRun('done', log, finalResponse, { emit: emitSuccessUpdate });
2343
2303
  resolveOnce(withTranscriptRuns({ response: finalResponse, responseTiming: timing }, transcriptRuns));
2344
2304
  return;
@@ -2346,7 +2306,7 @@ export const runAgent = ({ ticketId, tool, prompt, cwd, io, model, variant = nul
2346
2306
  const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
2347
2307
  const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2348
2308
  ? new AgentContinuationRejectedError(failureMessage)
2349
- : new Error(failureMessage);
2309
+ : createOpencodeExitError(failureMessage, stderrModelError, recoveryTracker);
2350
2310
  const transcriptRuns = finalizeRun('error', log, finalResponse);
2351
2311
  rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2352
2312
  });
@@ -2555,7 +2515,7 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2555
2515
  }, transcriptRuns));
2556
2516
  return;
2557
2517
  }
2558
- const modelError = isModelResolutionError(finalLog);
2518
+ const modelError = isLegacyModelResolutionError(errOutput);
2559
2519
  if (code === 0 && !modelError) {
2560
2520
  const finalOutput = getPreservedChatOutput({
2561
2521
  chatSessionId,
@@ -2709,8 +2669,8 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2709
2669
  }, transcriptRuns));
2710
2670
  return;
2711
2671
  }
2712
- const modelError = isModelResolutionError(log);
2713
- if (isSuccessfulOpencodeExit(code, modelError, recoveryTracker)) {
2672
+ const stderrModelError = parseOpencodeStderrModelResolutionError(stderrOutput);
2673
+ if (isSuccessfulOpencodeExit(code, stderrModelError, recoveryTracker)) {
2714
2674
  const finalOutput = getPreservedChatOutput({
2715
2675
  chatSessionId,
2716
2676
  log,
@@ -2737,7 +2697,7 @@ export const runChatAgent = ({ chatSessionId, tool, prompt, files = [], cwd, io,
2737
2697
  const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
2738
2698
  const error = resumeSessionId && !executionCapableEventObserved && isTypedPreExecutionContinuationRejection(failureMessage)
2739
2699
  ? new AgentContinuationRejectedError(failureMessage)
2740
- : new Error(failureMessage);
2700
+ : createOpencodeExitError(failureMessage, stderrModelError, recoveryTracker);
2741
2701
  const transcriptRuns = subagentTracker.finalize('error', log, finalResponse);
2742
2702
  rejectOnce(attachTranscriptRunsToError(error, transcriptRuns));
2743
2703
  });
@@ -2938,7 +2898,7 @@ export const runSpecAgent = ({ specSessionId, tool, prompt, files = [], cwd, io,
2938
2898
  }, transcriptRuns));
2939
2899
  return;
2940
2900
  }
2941
- const modelError = isModelResolutionError(finalLog);
2901
+ const modelError = isLegacyModelResolutionError(errOutput);
2942
2902
  if (code === 0 && !modelError) {
2943
2903
  const finalOutput = getPreservedSpecOutput({
2944
2904
  specSessionId,
@@ -3083,8 +3043,8 @@ export const runSpecAgent = ({ specSessionId, tool, prompt, files = [], cwd, io,
3083
3043
  }, transcriptRuns));
3084
3044
  return;
3085
3045
  }
3086
- const modelError = isModelResolutionError(log);
3087
- if (isSuccessfulOpencodeExit(code, modelError, recoveryTracker)) {
3046
+ const stderrModelError = parseOpencodeStderrModelResolutionError(stderrOutput);
3047
+ if (isSuccessfulOpencodeExit(code, stderrModelError, recoveryTracker)) {
3088
3048
  const finalOutput = getPreservedSpecOutput({
3089
3049
  specSessionId,
3090
3050
  log,
@@ -3109,7 +3069,8 @@ export const runSpecAgent = ({ specSessionId, tool, prompt, files = [], cwd, io,
3109
3069
  }
3110
3070
  updateSpecSessionStatusLocal(specSessionId, 'error', log, io, finalResponse);
3111
3071
  const transcriptRuns = subagentTracker.finalize('error', log, finalResponse);
3112
- rejectOnce(attachTranscriptRunsToError(new Error(`Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`), transcriptRuns));
3072
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
3073
+ rejectOnce(attachTranscriptRunsToError(createOpencodeExitError(failureMessage, stderrModelError, recoveryTracker), transcriptRuns));
3113
3074
  });
3114
3075
  child.on('error', err => {
3115
3076
  progressUpdater.cancel();
@@ -3272,7 +3233,7 @@ export const runSpecReviewAgent = ({ specReviewRunId, specSessionId, tool, promp
3272
3233
  });
3273
3234
  return;
3274
3235
  }
3275
- const modelError = isModelResolutionError(finalLog);
3236
+ const modelError = isLegacyModelResolutionError(errOutput);
3276
3237
  if (code === 0 && !modelError) {
3277
3238
  updateSpecReviewRunStreaming(specReviewRunId, finalResponse || null);
3278
3239
  subagentTracker.finalize('done', finalLog || null, finalResponse || null);
@@ -3365,8 +3326,8 @@ export const runSpecReviewAgent = ({ specReviewRunId, specSessionId, tool, promp
3365
3326
  });
3366
3327
  return;
3367
3328
  }
3368
- const modelError = isModelResolutionError(log);
3369
- if (isSuccessfulOpencodeExit(code, modelError, recoveryTracker)) {
3329
+ const stderrModelError = parseOpencodeStderrModelResolutionError(stderrOutput);
3330
+ if (isSuccessfulOpencodeExit(code, stderrModelError, recoveryTracker)) {
3370
3331
  updateSpecReviewRunStreaming(specReviewRunId, finalResponse || null);
3371
3332
  subagentTracker.finalize('done', log || null, finalResponse || null);
3372
3333
  resolveOnce({
@@ -3378,7 +3339,8 @@ export const runSpecReviewAgent = ({ specReviewRunId, specSessionId, tool, promp
3378
3339
  return;
3379
3340
  }
3380
3341
  subagentTracker.finalize('error', log || null, finalResponse || null);
3381
- rejectOnce(new Error(`Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`));
3342
+ const failureMessage = `Agent exited with code ${code ?? 'null'}\n${log}${stderrOutput !== log && stderrOutput ? '\n\n' + stderrOutput : ''}`;
3343
+ rejectOnce(createOpencodeExitError(failureMessage, stderrModelError, recoveryTracker));
3382
3344
  });
3383
3345
  child.on('error', err => {
3384
3346
  progressUpdater.cancel();