@link-assistant/hive-mind 1.2.1 ā 1.2.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.
- package/CHANGELOG.md +21 -0
- package/package.json +1 -1
- package/src/claude.lib.mjs +45 -53
- package/src/github.lib.mjs +33 -0
- package/src/log-upload.lib.mjs +6 -1
- package/src/solve.mjs +3 -1
- package/src/solve.results.lib.mjs +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5411e77: Fix gh-upload-log command invocation error caused by empty string argument
|
|
8
|
+
- Fixed bug where `gh-upload-log` failed with "Unknown argument: ''" when verbose=false
|
|
9
|
+
- The issue was caused by template literal interpolation `${verbose ? '--verbose' : ''}` passing empty string as an argument
|
|
10
|
+
- Now using array-based command building to avoid empty arguments
|
|
11
|
+
- Added improved handling for `error_during_execution` result subtype from Claude CLI
|
|
12
|
+
- Added tests for log upload command construction to prevent regression
|
|
13
|
+
|
|
14
|
+
## 1.2.2
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- db84104: Remove QEMU from CI/CD entirely
|
|
19
|
+
- Remove unnecessary QEMU and Docker Buildx setup from docker-pr-check job
|
|
20
|
+
- The PR check only builds for linux/amd64, so QEMU was never needed
|
|
21
|
+
- docker-publish jobs already use native ARM64 runners (ubuntu-24.04-arm)
|
|
22
|
+
- This addresses feedback to remove QEMU from CI/CD to avoid slowdowns and freezes
|
|
23
|
+
|
|
3
24
|
## 1.2.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/package.json
CHANGED
package/src/claude.lib.mjs
CHANGED
|
@@ -680,6 +680,24 @@ const displayModelUsage = async (usage, log) => {
|
|
|
680
680
|
await log(' Cost: Not available (could not fetch pricing)');
|
|
681
681
|
}
|
|
682
682
|
};
|
|
683
|
+
/**
|
|
684
|
+
* Display cost comparison between public pricing and Anthropic's official cost
|
|
685
|
+
* @param {number|null} publicCost - Public pricing estimate
|
|
686
|
+
* @param {number|null} anthropicCost - Anthropic's official cost
|
|
687
|
+
* @param {Function} log - Logging function
|
|
688
|
+
*/
|
|
689
|
+
const displayCostComparison = async (publicCost, anthropicCost, log) => {
|
|
690
|
+
await log('\n š° Cost estimation:');
|
|
691
|
+
await log(` Public pricing estimate: ${publicCost !== null && publicCost !== undefined ? `$${publicCost.toFixed(6)} USD` : 'unknown'}`);
|
|
692
|
+
await log(` Calculated by Anthropic: ${anthropicCost !== null && anthropicCost !== undefined ? `$${anthropicCost.toFixed(6)} USD` : 'unknown'}`);
|
|
693
|
+
if (publicCost !== null && publicCost !== undefined && anthropicCost !== null && anthropicCost !== undefined) {
|
|
694
|
+
const difference = anthropicCost - publicCost;
|
|
695
|
+
const percentDiff = publicCost > 0 ? (difference / publicCost) * 100 : 0;
|
|
696
|
+
await log(` Difference: $${difference.toFixed(6)} (${percentDiff > 0 ? '+' : ''}${percentDiff.toFixed(2)}%)`);
|
|
697
|
+
} else {
|
|
698
|
+
await log(' Difference: unknown');
|
|
699
|
+
}
|
|
700
|
+
};
|
|
683
701
|
export const calculateSessionTokens = async (sessionId, tempDir) => {
|
|
684
702
|
const os = (await use('os')).default;
|
|
685
703
|
const homeDir = os.homedir();
|
|
@@ -885,6 +903,7 @@ export const executeClaudeCommand = async params => {
|
|
|
885
903
|
let is503Error = false;
|
|
886
904
|
let stderrErrors = [];
|
|
887
905
|
let anthropicTotalCostUSD = null; // Capture Anthropic's official total_cost_usd from result
|
|
906
|
+
let errorDuringExecution = false; // Issue #1088: Track if error_during_execution subtype occurred
|
|
888
907
|
|
|
889
908
|
// Create interactive mode handler if enabled
|
|
890
909
|
let interactiveHandler = null;
|
|
@@ -1011,21 +1030,24 @@ export const executeClaudeCommand = async params => {
|
|
|
1011
1030
|
} else if (data.type === 'tool_use') {
|
|
1012
1031
|
toolUseCount++;
|
|
1013
1032
|
}
|
|
1014
|
-
// Handle session result type from Claude CLI
|
|
1015
|
-
//
|
|
1016
|
-
// Example: {"type": "result", "subtype": "success", "is_error": true, "result": "Session limit reached ā resets 10am"}
|
|
1033
|
+
// Handle session result type from Claude CLI (emitted when session completes)
|
|
1034
|
+
// Subtypes: "success", "error_during_execution" (work may have been done), etc.
|
|
1017
1035
|
if (data.type === 'result') {
|
|
1018
|
-
// Capture Anthropic's official total_cost_usd from the result
|
|
1019
1036
|
if (data.total_cost_usd !== undefined && data.total_cost_usd !== null) {
|
|
1020
1037
|
anthropicTotalCostUSD = data.total_cost_usd;
|
|
1021
|
-
await log(`š° Anthropic official cost captured: $${anthropicTotalCostUSD.toFixed(6)}`, {
|
|
1022
|
-
verbose: true,
|
|
1023
|
-
});
|
|
1038
|
+
await log(`š° Anthropic official cost captured: $${anthropicTotalCostUSD.toFixed(6)}`, { verbose: true });
|
|
1024
1039
|
}
|
|
1025
1040
|
if (data.is_error === true) {
|
|
1026
|
-
commandFailed = true;
|
|
1027
1041
|
lastMessage = data.result || JSON.stringify(data);
|
|
1028
|
-
|
|
1042
|
+
const subtype = data.subtype || 'unknown';
|
|
1043
|
+
// Issue #1088: "error_during_execution" = warning (work may exist), others = failure
|
|
1044
|
+
if (subtype === 'error_during_execution') {
|
|
1045
|
+
errorDuringExecution = true;
|
|
1046
|
+
await log(`ā ļø Error during execution (subtype: ${subtype}) - work may be completed`, { verbose: true });
|
|
1047
|
+
} else {
|
|
1048
|
+
commandFailed = true;
|
|
1049
|
+
await log(`ā ļø Detected error from Claude CLI (subtype: ${subtype})`, { verbose: true });
|
|
1050
|
+
}
|
|
1029
1051
|
if (lastMessage.includes('Session limit reached') || lastMessage.includes('limit reached')) {
|
|
1030
1052
|
limitReached = true;
|
|
1031
1053
|
await log('ā ļø Detected session limit in result', { verbose: true });
|
|
@@ -1264,9 +1286,16 @@ export const executeClaudeCommand = async params => {
|
|
|
1264
1286
|
limitResetTime,
|
|
1265
1287
|
messageCount,
|
|
1266
1288
|
toolUseCount,
|
|
1289
|
+
errorDuringExecution,
|
|
1267
1290
|
};
|
|
1268
1291
|
}
|
|
1269
|
-
|
|
1292
|
+
// Issue #1088: If error_during_execution occurred but command didn't fail,
|
|
1293
|
+
// log it as "Finished with errors" instead of pure success
|
|
1294
|
+
if (errorDuringExecution) {
|
|
1295
|
+
await log('\n\nā ļø Claude command finished with errors');
|
|
1296
|
+
} else {
|
|
1297
|
+
await log('\n\nā
Claude command completed');
|
|
1298
|
+
}
|
|
1270
1299
|
await log(`š Total messages: ${messageCount}, Tool uses: ${toolUseCount}`);
|
|
1271
1300
|
// Calculate and display total token usage from session JSONL file
|
|
1272
1301
|
if (sessionId && tempDir) {
|
|
@@ -1289,49 +1318,11 @@ export const executeClaudeCommand = async params => {
|
|
|
1289
1318
|
// Show totals if multiple models were used
|
|
1290
1319
|
if (modelIds.length > 1) {
|
|
1291
1320
|
await log('\n š Total across all models:');
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
await log(' Public pricing estimate: unknown');
|
|
1298
|
-
}
|
|
1299
|
-
if (anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined) {
|
|
1300
|
-
await log(` Calculated by Anthropic: $${anthropicTotalCostUSD.toFixed(6)} USD`);
|
|
1301
|
-
// Show comparison if both are available
|
|
1302
|
-
if (tokenUsage.totalCostUSD !== null && tokenUsage.totalCostUSD !== undefined) {
|
|
1303
|
-
const difference = anthropicTotalCostUSD - tokenUsage.totalCostUSD;
|
|
1304
|
-
const percentDiff = tokenUsage.totalCostUSD > 0 ? (difference / tokenUsage.totalCostUSD) * 100 : 0;
|
|
1305
|
-
await log(` Difference: $${difference.toFixed(6)} (${percentDiff > 0 ? '+' : ''}${percentDiff.toFixed(2)}%)`);
|
|
1306
|
-
} else {
|
|
1307
|
-
await log(' Difference: unknown');
|
|
1308
|
-
}
|
|
1309
|
-
} else {
|
|
1310
|
-
await log(' Calculated by Anthropic: unknown');
|
|
1311
|
-
await log(' Difference: unknown');
|
|
1312
|
-
}
|
|
1313
|
-
} else {
|
|
1314
|
-
// Single model - show cost comparison
|
|
1315
|
-
await log('\n š° Cost estimation:');
|
|
1316
|
-
if (tokenUsage.totalCostUSD !== null && tokenUsage.totalCostUSD !== undefined) {
|
|
1317
|
-
await log(` Public pricing estimate: $${tokenUsage.totalCostUSD.toFixed(6)} USD`);
|
|
1318
|
-
} else {
|
|
1319
|
-
await log(' Public pricing estimate: unknown');
|
|
1320
|
-
}
|
|
1321
|
-
if (anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined) {
|
|
1322
|
-
await log(` Calculated by Anthropic: $${anthropicTotalCostUSD.toFixed(6)} USD`);
|
|
1323
|
-
// Show comparison if both are available
|
|
1324
|
-
if (tokenUsage.totalCostUSD !== null && tokenUsage.totalCostUSD !== undefined) {
|
|
1325
|
-
const difference = anthropicTotalCostUSD - tokenUsage.totalCostUSD;
|
|
1326
|
-
const percentDiff = tokenUsage.totalCostUSD > 0 ? (difference / tokenUsage.totalCostUSD) * 100 : 0;
|
|
1327
|
-
await log(` Difference: $${difference.toFixed(6)} (${percentDiff > 0 ? '+' : ''}${percentDiff.toFixed(2)}%)`);
|
|
1328
|
-
} else {
|
|
1329
|
-
await log(' Difference: unknown');
|
|
1330
|
-
}
|
|
1331
|
-
} else {
|
|
1332
|
-
await log(' Calculated by Anthropic: unknown');
|
|
1333
|
-
await log(' Difference: unknown');
|
|
1334
|
-
}
|
|
1321
|
+
}
|
|
1322
|
+
// Show cost comparison (for both single and multiple models)
|
|
1323
|
+
await displayCostComparison(tokenUsage.totalCostUSD, anthropicTotalCostUSD, log);
|
|
1324
|
+
// Show total tokens for single model only
|
|
1325
|
+
if (modelIds.length === 1) {
|
|
1335
1326
|
await log(` Total tokens: ${formatNumber(tokenUsage.totalTokens)}`);
|
|
1336
1327
|
}
|
|
1337
1328
|
} else {
|
|
@@ -1365,6 +1356,7 @@ export const executeClaudeCommand = async params => {
|
|
|
1365
1356
|
messageCount,
|
|
1366
1357
|
toolUseCount,
|
|
1367
1358
|
anthropicTotalCostUSD, // Pass Anthropic's official total cost
|
|
1359
|
+
errorDuringExecution, // Issue #1088: Track if error_during_execution subtype occurred
|
|
1368
1360
|
};
|
|
1369
1361
|
} catch (error) {
|
|
1370
1362
|
reportError(error, {
|
package/src/github.lib.mjs
CHANGED
|
@@ -380,6 +380,8 @@ export async function attachLogToGitHub(options) {
|
|
|
380
380
|
// New parameters for agent tool pricing support
|
|
381
381
|
publicPricingEstimate = null,
|
|
382
382
|
pricingInfo = null,
|
|
383
|
+
// Issue #1088: Track error_during_execution for "Finished with errors" state
|
|
384
|
+
errorDuringExecution = false,
|
|
383
385
|
} = options;
|
|
384
386
|
const targetName = targetType === 'pr' ? 'Pull Request' : 'Issue';
|
|
385
387
|
const ghCommand = targetType === 'pr' ? 'pr' : 'issue';
|
|
@@ -498,6 +500,25 @@ ${logContent}
|
|
|
498
500
|
|
|
499
501
|
</details>
|
|
500
502
|
|
|
503
|
+
---
|
|
504
|
+
*Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
|
|
505
|
+
} else if (errorDuringExecution) {
|
|
506
|
+
// Issue #1088: "Finished with errors" format - work may have been completed but errors occurred
|
|
507
|
+
const costInfo = buildCostInfoString(totalCostUSD, anthropicTotalCostUSD, pricingInfo);
|
|
508
|
+
logComment = `## ā ļø Solution Draft Finished with Errors
|
|
509
|
+
This log file contains the complete execution trace of the AI ${targetType === 'pr' ? 'solution draft' : 'analysis'} process.${costInfo}
|
|
510
|
+
|
|
511
|
+
**Note**: The session encountered errors during execution, but some work may have been completed. Please review the changes carefully.
|
|
512
|
+
|
|
513
|
+
<details>
|
|
514
|
+
<summary>Click to expand solution draft log (${Math.round(logStats.size / 1024)}KB)</summary>
|
|
515
|
+
|
|
516
|
+
\`\`\`
|
|
517
|
+
${logContent}
|
|
518
|
+
\`\`\`
|
|
519
|
+
|
|
520
|
+
</details>
|
|
521
|
+
|
|
501
522
|
---
|
|
502
523
|
*Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
|
|
503
524
|
} else {
|
|
@@ -624,6 +645,18 @@ ${errorMessage}
|
|
|
624
645
|
š **Failure log uploaded as ${uploadTypeLabel}${chunkInfo}** (${Math.round(logStats.size / 1024)}KB)
|
|
625
646
|
š [View complete failure log](${logUrl})
|
|
626
647
|
---
|
|
648
|
+
*Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
|
|
649
|
+
} else if (errorDuringExecution) {
|
|
650
|
+
// Issue #1088: "Finished with errors" format - work may have been completed but errors occurred
|
|
651
|
+
const costInfo = buildCostInfoString(totalCostUSD, anthropicTotalCostUSD, pricingInfo);
|
|
652
|
+
logUploadComment = `## ā ļø Solution Draft Finished with Errors
|
|
653
|
+
This log file contains the complete execution trace of the AI ${targetType === 'pr' ? 'solution draft' : 'analysis'} process.${costInfo}
|
|
654
|
+
|
|
655
|
+
**Note**: The session encountered errors during execution, but some work may have been completed. Please review the changes carefully.
|
|
656
|
+
|
|
657
|
+
š **Log file uploaded as ${uploadTypeLabel}${chunkInfo}** (${Math.round(logStats.size / 1024)}KB)
|
|
658
|
+
š [View complete solution draft log](${logUrl})
|
|
659
|
+
---
|
|
627
660
|
*Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
|
|
628
661
|
} else {
|
|
629
662
|
// Success log format - use helper function for cost info
|
package/src/log-upload.lib.mjs
CHANGED
|
@@ -44,7 +44,12 @@ export const uploadLogWithGhUploadLog = async ({ logFile, isPublic, description,
|
|
|
44
44
|
await log(` š¤ Running: ${command}`, { verbose: true });
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
// Build command arguments array, filtering out empty strings to prevent "Unknown argument: ''" error
|
|
48
|
+
const commandArgs = [`"${logFile}"`, publicFlag];
|
|
49
|
+
if (verbose) {
|
|
50
|
+
commandArgs.push('--verbose');
|
|
51
|
+
}
|
|
52
|
+
const uploadResult = await $`gh-upload-log ${commandArgs.join(' ')}`;
|
|
48
53
|
const output = (uploadResult.stdout?.toString() || '') + (uploadResult.stderr?.toString() || '');
|
|
49
54
|
|
|
50
55
|
if (uploadResult.code !== 0) {
|
package/src/solve.mjs
CHANGED
|
@@ -891,6 +891,7 @@ try {
|
|
|
891
891
|
let anthropicTotalCostUSD = toolResult.anthropicTotalCostUSD;
|
|
892
892
|
let publicPricingEstimate = toolResult.publicPricingEstimate; // Used by agent tool
|
|
893
893
|
let pricingInfo = toolResult.pricingInfo; // Used by agent tool for detailed pricing
|
|
894
|
+
let errorDuringExecution = toolResult.errorDuringExecution || false; // Issue #1088: Track error_during_execution
|
|
894
895
|
limitReached = toolResult.limitReached;
|
|
895
896
|
cleanupContext.limitReached = limitReached;
|
|
896
897
|
|
|
@@ -1127,7 +1128,8 @@ try {
|
|
|
1127
1128
|
// Search for newly created pull requests and comments
|
|
1128
1129
|
// Pass shouldRestart to prevent early exit when auto-restart is needed
|
|
1129
1130
|
// Include agent tool pricing data when available (publicPricingEstimate, pricingInfo)
|
|
1130
|
-
|
|
1131
|
+
// Issue #1088: Pass errorDuringExecution for "Finished with errors" state
|
|
1132
|
+
await verifyResults(owner, repo, branchName, issueNumber, prNumber, prUrl, referenceTime, argv, shouldAttachLogs, shouldRestart, sessionId, tempDir, anthropicTotalCostUSD, publicPricingEstimate, pricingInfo, errorDuringExecution);
|
|
1131
1133
|
|
|
1132
1134
|
// Start watch mode if enabled OR if we need to handle uncommitted changes
|
|
1133
1135
|
if (argv.verbose) {
|
|
@@ -414,7 +414,7 @@ export const showSessionSummary = async (sessionId, limitReached, argv, issueUrl
|
|
|
414
414
|
};
|
|
415
415
|
|
|
416
416
|
// Verify results by searching for new PRs and comments
|
|
417
|
-
export const verifyResults = async (owner, repo, branchName, issueNumber, prNumber, prUrl, referenceTime, argv, shouldAttachLogs, shouldRestart = false, sessionId = null, tempDir = null, anthropicTotalCostUSD = null, publicPricingEstimate = null, pricingInfo = null) => {
|
|
417
|
+
export const verifyResults = async (owner, repo, branchName, issueNumber, prNumber, prUrl, referenceTime, argv, shouldAttachLogs, shouldRestart = false, sessionId = null, tempDir = null, anthropicTotalCostUSD = null, publicPricingEstimate = null, pricingInfo = null, errorDuringExecution = false) => {
|
|
418
418
|
await log('\nš Searching for created pull requests or comments...');
|
|
419
419
|
|
|
420
420
|
try {
|
|
@@ -545,6 +545,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
|
|
|
545
545
|
// Pass agent tool pricing data when available
|
|
546
546
|
publicPricingEstimate,
|
|
547
547
|
pricingInfo,
|
|
548
|
+
// Issue #1088: Pass errorDuringExecution for "Finished with errors" state
|
|
549
|
+
errorDuringExecution,
|
|
548
550
|
});
|
|
549
551
|
}
|
|
550
552
|
|
|
@@ -608,6 +610,8 @@ export const verifyResults = async (owner, repo, branchName, issueNumber, prNumb
|
|
|
608
610
|
// Pass agent tool pricing data when available
|
|
609
611
|
publicPricingEstimate,
|
|
610
612
|
pricingInfo,
|
|
613
|
+
// Issue #1088: Pass errorDuringExecution for "Finished with errors" state
|
|
614
|
+
errorDuringExecution,
|
|
611
615
|
});
|
|
612
616
|
}
|
|
613
617
|
|