@link-assistant/hive-mind 0.51.17 → 0.51.18

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 0.51.18
4
+
5
+ ### Patch Changes
6
+
7
+ - bf6ac23: Fix Claude Code terms acceptance treated as success
8
+ - Detect Claude CLI terms acceptance messages and treat as error requiring human intervention
9
+ - Hide cost estimation section when all values are unknown
10
+ - Fix code block escaping in log comments using zero-width spaces
11
+
3
12
  ## 0.51.17
4
13
 
5
14
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "0.51.17",
3
+ "version": "0.51.18",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -1067,6 +1067,17 @@ export const executeClaudeCommand = async params => {
1067
1067
  if (line.trim() && !line.includes('node:internal')) {
1068
1068
  await log(line, { stream: 'raw' });
1069
1069
  lastMessage = line;
1070
+
1071
+ // Detect Claude Code terms acceptance message (Issue #1015)
1072
+ // When Claude CLI requires terms acceptance, it outputs a non-JSON message like:
1073
+ // "[ACTION REQUIRED] An update to our Consumer Terms and Privacy Policy has taken effect..."
1074
+ // This should be treated as an error requiring human intervention, not success
1075
+ const termsAcceptancePattern = /\[ACTION REQUIRED\].*terms|must run.*claude.*review.*terms/i;
1076
+ if (termsAcceptancePattern.test(line)) {
1077
+ commandFailed = true;
1078
+ await log('\nāŒ Claude Code requires terms acceptance - please run `claude` interactively to accept the updated terms', { level: 'error' });
1079
+ await log(' This is not an error in your code, but Claude CLI needs human interaction.', { level: 'error' });
1080
+ }
1070
1081
  }
1071
1082
  }
1072
1083
  }
@@ -22,19 +22,22 @@ import { batchCheckPullRequestsForIssues as batchCheckPRs, batchCheckArchivedRep
22
22
  * @param {number|null} totalCostUSD - Public pricing estimate
23
23
  * @param {number|null} anthropicTotalCostUSD - Cost calculated by Anthropic (Claude-specific)
24
24
  * @param {Object|null} pricingInfo - Pricing info from agent tool
25
- * @returns {string} Formatted cost info string for markdown
25
+ * @returns {string} Formatted cost info string for markdown (empty if no data available)
26
26
  */
27
27
  const buildCostInfoString = (totalCostUSD, anthropicTotalCostUSD, pricingInfo) => {
28
+ // Issue #1015: Don't show cost section when all values are unknown (clutters output)
29
+ const hasPublic = totalCostUSD !== null && totalCostUSD !== undefined;
30
+ const hasAnthropic = anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined;
31
+ const hasPricing = pricingInfo && (pricingInfo.modelName || pricingInfo.tokenUsage || pricingInfo.isFreeModel);
32
+ if (!hasPublic && !hasAnthropic && !hasPricing) return '';
28
33
  let costInfo = '\n\nšŸ’° **Cost estimation:**';
29
- if (pricingInfo && pricingInfo.modelName) {
34
+ if (pricingInfo?.modelName) {
30
35
  costInfo += `\n- Model: ${pricingInfo.modelName}`;
31
36
  if (pricingInfo.provider) costInfo += `\n- Provider: ${pricingInfo.provider}`;
32
37
  }
33
- if (totalCostUSD !== null && totalCostUSD !== undefined) {
38
+ if (hasPublic) {
34
39
  costInfo += pricingInfo?.isFreeModel ? '\n- Public pricing estimate: $0.00 (Free model)' : `\n- Public pricing estimate: $${totalCostUSD.toFixed(6)} USD`;
35
- } else {
36
- costInfo += '\n- Public pricing estimate: unknown';
37
- }
40
+ } else if (hasPricing) costInfo += '\n- Public pricing estimate: unknown';
38
41
  if (pricingInfo?.tokenUsage) {
39
42
  const u = pricingInfo.tokenUsage;
40
43
  let tokenInfo = `\n- Token usage: ${u.inputTokens?.toLocaleString() || 0} input, ${u.outputTokens?.toLocaleString() || 0} output`;
@@ -42,17 +45,13 @@ const buildCostInfoString = (totalCostUSD, anthropicTotalCostUSD, pricingInfo) =
42
45
  if (u.cacheReadTokens > 0 || u.cacheWriteTokens > 0) tokenInfo += `, ${u.cacheReadTokens?.toLocaleString() || 0} cache read, ${u.cacheWriteTokens?.toLocaleString() || 0} cache write`;
43
46
  costInfo += tokenInfo;
44
47
  }
45
- if (anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined) {
48
+ if (hasAnthropic) {
46
49
  costInfo += `\n- Calculated by Anthropic: $${anthropicTotalCostUSD.toFixed(6)} USD`;
47
- if (totalCostUSD !== null) {
50
+ if (hasPublic) {
48
51
  const diff = anthropicTotalCostUSD - totalCostUSD;
49
52
  const pct = totalCostUSD > 0 ? (diff / totalCostUSD) * 100 : 0;
50
53
  costInfo += `\n- Difference: $${diff.toFixed(6)} (${pct > 0 ? '+' : ''}${pct.toFixed(2)}%)`;
51
- } else {
52
- costInfo += '\n- Difference: unknown';
53
54
  }
54
- } else if (!pricingInfo) {
55
- costInfo += '\n- Calculated by Anthropic: unknown\n- Difference: unknown';
56
55
  }
57
56
  return costInfo;
58
57
  };
@@ -143,16 +142,8 @@ export const getGitHubTokensFromCommand = async () => {
143
142
 
144
143
  return tokens;
145
144
  };
146
- // Helper function to escape code blocks in log content for safe embedding in markdown
147
- // When log content is placed inside a markdown code block, any triple backticks (```)
148
- // in the content will prematurely close the outer code block, breaking the markdown.
149
- // This function escapes those backticks by replacing them with \`\`\` (with backslashes).
150
- export const escapeCodeBlocksInLog = logContent => {
151
- // Replace all occurrences of triple backticks with escaped version
152
- // We add backslashes before backticks to prevent them from being
153
- // interpreted as markdown code block delimiters
154
- return logContent.replace(/```/g, '\\`\\`\\`');
155
- };
145
+ // Escape ``` in logs for safe markdown embedding (replaces with \`\`\` to prevent code block closure)
146
+ export const escapeCodeBlocksInLog = logContent => logContent.replace(/```/g, '\\`\\`\\`');
156
147
  // Helper function to sanitize log content by masking GitHub tokens
157
148
  export const sanitizeLogContent = async logContent => {
158
149
  let sanitized = logContent;
@@ -612,6 +603,7 @@ ${resumeCommand}
612
603
  \`\`\`
613
604
  ${logContent}
614
605
  \`\`\`
606
+
615
607
  </details>
616
608
 
617
609
  ---
@@ -623,12 +615,16 @@ The automated solution draft encountered an error:
623
615
  \`\`\`
624
616
  ${errorMessage}
625
617
  \`\`\`
618
+
626
619
  <details>
627
620
  <summary>Click to expand failure log (${Math.round(logStats.size / 1024)}KB)</summary>
621
+
628
622
  \`\`\`
629
623
  ${logContent}
630
624
  \`\`\`
625
+
631
626
  </details>
627
+
632
628
  ---
633
629
  *Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
634
630
  } else {
@@ -636,12 +632,16 @@ ${logContent}
636
632
  const costInfo = buildCostInfoString(totalCostUSD, anthropicTotalCostUSD, pricingInfo);
637
633
  logComment = `## ${customTitle}
638
634
  This log file contains the complete execution trace of the AI ${targetType === 'pr' ? 'solution draft' : 'analysis'} process.${costInfo}
635
+
639
636
  <details>
640
637
  <summary>Click to expand solution draft log (${Math.round(logStats.size / 1024)}KB)</summary>
638
+
641
639
  \`\`\`
642
640
  ${logContent}
643
641
  \`\`\`
642
+
644
643
  </details>
644
+
645
645
  ---
646
646
  *Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
647
647
  }
@@ -836,12 +836,16 @@ async function attachTruncatedLog(options) {
836
836
  const truncatedComment = `## šŸ¤– Solution Draft Log (Truncated)
837
837
  This log file contains the complete execution trace of the AI ${targetType === 'pr' ? 'solution draft' : 'analysis'} process.
838
838
  āš ļø **Log was truncated** due to GitHub comment size limits.
839
+
839
840
  <details>
840
841
  <summary>Click to expand solution draft log (${Math.round(logStats.size / 1024)}KB, truncated)</summary>
842
+
841
843
  \`\`\`
842
844
  ${truncatedContent}
843
845
  \`\`\`
846
+
844
847
  </details>
848
+
845
849
  ---
846
850
  *Now working session is ended, feel free to review and add any feedback on the solution draft.*`;
847
851
  const tempFile = `/tmp/log-truncated-comment-${targetType}-${Date.now()}.md`;