@link-assistant/hive-mind 1.56.4 ā 1.56.5
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.
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/codex.lib.mjs +99 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
package/src/codex.lib.mjs
CHANGED
|
@@ -183,6 +183,57 @@ const upsertCodexItemError = (itemErrors, item) => {
|
|
|
183
183
|
});
|
|
184
184
|
};
|
|
185
185
|
|
|
186
|
+
const unwrapCodexErrorMessage = value => {
|
|
187
|
+
if (!value) return '';
|
|
188
|
+
if (typeof value !== 'string') {
|
|
189
|
+
if (typeof value?.error?.message === 'string') return unwrapCodexErrorMessage(value.error.message);
|
|
190
|
+
if (typeof value?.message === 'string') return unwrapCodexErrorMessage(value.message);
|
|
191
|
+
return String(value);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let text = value.trim();
|
|
195
|
+
for (let i = 0; i < 3; i++) {
|
|
196
|
+
if (!text.startsWith('{') && !text.startsWith('[')) break;
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(text);
|
|
199
|
+
if (typeof parsed?.error?.message === 'string') return unwrapCodexErrorMessage(parsed.error.message);
|
|
200
|
+
if (typeof parsed?.message === 'string') {
|
|
201
|
+
text = parsed.message.trim();
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
return JSON.stringify(parsed);
|
|
205
|
+
} catch {
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return text;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export const getCodexErrorEventSummary = codexJsonState => {
|
|
213
|
+
const events = [];
|
|
214
|
+
const addEvents = (type, items = []) => {
|
|
215
|
+
for (const item of items) {
|
|
216
|
+
const message = unwrapCodexErrorMessage(item?.message);
|
|
217
|
+
events.push({ type, message: message || 'Codex emitted an error event' });
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
addEvents('item', codexJsonState?.itemErrors);
|
|
222
|
+
addEvents('turn', codexJsonState?.turnFailures);
|
|
223
|
+
addEvents('stream', codexJsonState?.streamErrors);
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
hasError: events.length > 0,
|
|
227
|
+
message: events[0]?.message || null,
|
|
228
|
+
events,
|
|
229
|
+
counts: {
|
|
230
|
+
item: codexJsonState?.itemErrors?.length || 0,
|
|
231
|
+
turn: codexJsonState?.turnFailures?.length || 0,
|
|
232
|
+
stream: codexJsonState?.streamErrors?.length || 0,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
};
|
|
236
|
+
|
|
186
237
|
export const parseCodexExecJsonOutput = (output, state = {}, requestedModelId = null) => {
|
|
187
238
|
const nextState = {
|
|
188
239
|
sessionId: state.sessionId || null,
|
|
@@ -597,7 +648,7 @@ export const executeCodex = async params => {
|
|
|
597
648
|
};
|
|
598
649
|
|
|
599
650
|
export const executeCodexCommand = async params => {
|
|
600
|
-
const { tempDir, branchName, prompt, systemPrompt, argv, log, formatAligned, getResourceSnapshot, forkedRepo, feedbackLines, codexPath, $, owner, repo, prNumber } = params;
|
|
651
|
+
const { tempDir, branchName, prompt, systemPrompt, argv, log, formatAligned, getResourceSnapshot, forkedRepo, feedbackLines, codexPath, $, owner, repo, prNumber, calculatePricing = calculateCodexPricing } = params;
|
|
601
652
|
|
|
602
653
|
const shellQuote = value => `"${String(value).replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`;
|
|
603
654
|
|
|
@@ -852,7 +903,7 @@ export const executeCodexCommand = async params => {
|
|
|
852
903
|
}
|
|
853
904
|
|
|
854
905
|
const firstActualModelId = mappedModel;
|
|
855
|
-
const pricingInfo = firstActualModelId ? await
|
|
906
|
+
const pricingInfo = firstActualModelId ? await calculatePricing(firstActualModelId, codexJsonState.tokenUsage.stepCount > 0 ? codexJsonState.tokenUsage : null) : null;
|
|
856
907
|
if (pricingInfo?.totalCostUSD !== null && pricingInfo?.totalCostUSD !== undefined) {
|
|
857
908
|
await log(`š° Codex public pricing estimate: $${new Decimal(pricingInfo.totalCostUSD).toFixed(6)}`, { verbose: true });
|
|
858
909
|
if (pricingInfo.usesLongContextPricing) {
|
|
@@ -876,6 +927,49 @@ export const executeCodexCommand = async params => {
|
|
|
876
927
|
throw error;
|
|
877
928
|
}
|
|
878
929
|
|
|
930
|
+
const codexErrorSummary = getCodexErrorEventSummary(codexJsonState);
|
|
931
|
+
if (codexErrorSummary.hasError) {
|
|
932
|
+
const limitInfo = detectUsageLimit(codexErrorSummary.message || lastMessage);
|
|
933
|
+
if (limitInfo.isUsageLimit) {
|
|
934
|
+
limitReached = true;
|
|
935
|
+
limitResetTime = limitInfo.resetTime;
|
|
936
|
+
|
|
937
|
+
const messageLines = formatUsageLimitMessage({
|
|
938
|
+
tool: 'OpenAI Codex',
|
|
939
|
+
resetTime: limitInfo.resetTime,
|
|
940
|
+
sessionId,
|
|
941
|
+
resumeCommand: sessionId ? `${process.argv[0]} ${process.argv[1]} ${argv.url} --resume ${sessionId}` : null,
|
|
942
|
+
});
|
|
943
|
+
|
|
944
|
+
for (const line of messageLines) {
|
|
945
|
+
await log(line, { level: 'warning' });
|
|
946
|
+
}
|
|
947
|
+
} else {
|
|
948
|
+
await log(`\n\nā Codex emitted error event: ${codexErrorSummary.message}`, { level: 'error' });
|
|
949
|
+
await log(` Error events: item=${codexErrorSummary.counts.item}, turn=${codexErrorSummary.counts.turn}, stream=${codexErrorSummary.counts.stream}`, { level: 'error' });
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
const resourcesAfter = await getResourceSnapshot();
|
|
953
|
+
await log('\nš System resources after execution:', { verbose: true });
|
|
954
|
+
await log(` Memory: ${resourcesAfter.memory.split('\n')[1]}`, { verbose: true });
|
|
955
|
+
await log(` Load: ${resourcesAfter.load}`, { verbose: true });
|
|
956
|
+
|
|
957
|
+
return {
|
|
958
|
+
success: false,
|
|
959
|
+
sessionId,
|
|
960
|
+
limitReached,
|
|
961
|
+
limitResetTime,
|
|
962
|
+
pricingInfo,
|
|
963
|
+
publicPricingEstimate: pricingInfo?.totalCostUSD ?? null,
|
|
964
|
+
resultModelUsage,
|
|
965
|
+
subAgentCalls: codexJsonState.subAgentCalls.length > 0 ? codexJsonState.subAgentCalls : null,
|
|
966
|
+
codexJsonDetails: codexJsonState,
|
|
967
|
+
errorInfo: codexErrorSummary,
|
|
968
|
+
result: codexErrorSummary.message,
|
|
969
|
+
resultSummary: lastTextContent || null, // Issue #1263: Use last text content from JSON output stream
|
|
970
|
+
};
|
|
971
|
+
}
|
|
972
|
+
|
|
879
973
|
if (exitCode !== 0) {
|
|
880
974
|
// Check for usage limit errors first (more specific)
|
|
881
975
|
const limitInfo = detectUsageLimit(lastMessage);
|
|
@@ -915,6 +1009,7 @@ export const executeCodexCommand = async params => {
|
|
|
915
1009
|
resultModelUsage,
|
|
916
1010
|
subAgentCalls: codexJsonState.subAgentCalls.length > 0 ? codexJsonState.subAgentCalls : null,
|
|
917
1011
|
codexJsonDetails: codexJsonState,
|
|
1012
|
+
errorInfo: getCodexErrorEventSummary(codexJsonState),
|
|
918
1013
|
resultSummary: lastTextContent || null, // Issue #1263: Use last text content from JSON output stream
|
|
919
1014
|
};
|
|
920
1015
|
}
|
|
@@ -965,6 +1060,8 @@ export const executeCodexCommand = async params => {
|
|
|
965
1060
|
limitResetTime: null,
|
|
966
1061
|
pricingInfo: null,
|
|
967
1062
|
publicPricingEstimate: null,
|
|
1063
|
+
errorInfo: { hasError: true, message: error.message, events: [{ type: 'exception', message: error.message }], counts: { item: 0, turn: 0, stream: 0 } },
|
|
1064
|
+
result: error.message,
|
|
968
1065
|
resultSummary: null, // Issue #1263: No result summary available on error
|
|
969
1066
|
};
|
|
970
1067
|
} finally {
|