@link-assistant/hive-mind 2.11.6 → 2.11.7
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 +13 -0
- package/package.json +1 -1
- package/src/budget-stats-policy.lib.mjs +31 -0
- package/src/solve.auto-merge.lib.mjs +14 -15
- package/src/solve.config.lib.mjs +2 -2
- package/src/solve.mjs +0 -2
- package/src/solve.results.lib.mjs +29 -24
- package/src/solve.watch.lib.mjs +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 2.11.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 815a63c: Keep context/cost budget statistics out of the working session summary (issue #2132).
|
|
8
|
+
|
|
9
|
+
Cost estimation and token/context usage are now published only in the working
|
|
10
|
+
session log comment, and only when `--attach-logs` is enabled — previously every
|
|
11
|
+
session posted the identical blocks twice, and the summary could publish them even
|
|
12
|
+
with log attachment disabled. The per-session budget stats derivation used by the
|
|
13
|
+
top-level run, watch iterations and auto-restart-until-mergeable iterations is now
|
|
14
|
+
a single shared implementation.
|
|
15
|
+
|
|
3
16
|
## 2.11.6
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Issue #2132: single source of truth for *where* context/cost budget statistics
|
|
5
|
+
* may be published.
|
|
6
|
+
*
|
|
7
|
+
* Rules encoded here:
|
|
8
|
+
* 1. Budget stats belong to the working session **log** comment only. The
|
|
9
|
+
* "Working session summary" comment reports what the AI did, never how many
|
|
10
|
+
* tokens or dollars it took (see `attachSolutionSummary`).
|
|
11
|
+
* 2. `--attach-logs` disabled ⇒ no log comment ⇒ no published budget stats.
|
|
12
|
+
* `--tokens-budget-stats` alone is not enough to publish them to GitHub; it
|
|
13
|
+
* only controls the local terminal rendering of the same facts.
|
|
14
|
+
*
|
|
15
|
+
* Keeping this in one module means the top-level run, the watch loop and the
|
|
16
|
+
* auto-restart-until-mergeable loop cannot drift apart again.
|
|
17
|
+
*
|
|
18
|
+
* @see https://github.com/link-assistant/hive-mind/issues/2132
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/** Whether `--attach-logs` is enabled (both camelCase and kebab-case forms). */
|
|
22
|
+
export const isAttachLogsEnabled = argv => !!(argv && (argv.attachLogs || argv['attach-logs']));
|
|
23
|
+
|
|
24
|
+
/** Whether `--tokens-budget-stats` is enabled (both camelCase and kebab-case forms). */
|
|
25
|
+
export const isTokensBudgetStatsEnabled = argv => !!(argv && (argv.tokensBudgetStats || argv['tokens-budget-stats']));
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether context/cost budget statistics may be published to GitHub for this run.
|
|
29
|
+
* Requires BOTH `--tokens-budget-stats` and `--attach-logs`.
|
|
30
|
+
*/
|
|
31
|
+
export const shouldPublishBudgetStats = argv => isTokensBudgetStatsEnabled(argv) && isAttachLogsEnabled(argv);
|
|
@@ -1052,19 +1052,20 @@ Once the billing issue is resolved, you can re-run the CI checks or push a new c
|
|
|
1052
1052
|
latestAnthropicCost = toolResult.anthropicTotalCostUSD;
|
|
1053
1053
|
}
|
|
1054
1054
|
|
|
1055
|
-
// Issue #1508: Compute budget stats for auto-restart-until-mergeable log comment
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1055
|
+
// Issue #1508: Compute budget stats for auto-restart-until-mergeable log comment.
|
|
1056
|
+
// Issue #2132: shared with the top-level run and the watch loop via
|
|
1057
|
+
// buildSessionBudgetStatsData, so every working session derives its own
|
|
1058
|
+
// stats the same way (and skips them when `--attach-logs` is disabled).
|
|
1059
|
+
const { buildSessionBudgetStatsData } = await import('./solve.results.lib.mjs');
|
|
1060
|
+
const autoMergeBudgetStatsData = await buildSessionBudgetStatsData({
|
|
1061
|
+
argv,
|
|
1062
|
+
sessionId: latestSessionId,
|
|
1063
|
+
tempDir,
|
|
1064
|
+
resultModelUsage: toolResult.resultModelUsage,
|
|
1065
|
+
streamTokenUsage: toolResult.streamTokenUsage || null,
|
|
1066
|
+
subAgentCalls: toolResult.subAgentCalls || null,
|
|
1067
|
+
pricingInfo: toolResult.pricingInfo || null,
|
|
1068
|
+
});
|
|
1068
1069
|
|
|
1069
1070
|
// Issue #1761: Post the working session **summary** BEFORE uploading
|
|
1070
1071
|
// the working session **log** so the summary always appears above
|
|
@@ -1090,8 +1091,6 @@ Once the billing issue is resolved, you can re-run the CI checks or push a new c
|
|
|
1090
1091
|
prNumber,
|
|
1091
1092
|
issueNumber,
|
|
1092
1093
|
success: true,
|
|
1093
|
-
publicPricingEstimate: toolResult.publicPricingEstimate,
|
|
1094
|
-
anthropicTotalCostUSD: latestAnthropicCost,
|
|
1095
1094
|
pricingInfo: toolResult.pricingInfo,
|
|
1096
1095
|
budgetStatsData: autoMergeBudgetStatsData,
|
|
1097
1096
|
});
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -136,7 +136,7 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
136
136
|
},
|
|
137
137
|
'attach-logs': {
|
|
138
138
|
type: 'boolean',
|
|
139
|
-
description:
|
|
139
|
+
description: "Upload the solution draft log file to the Pull Request on completion, together with that working session's cost estimation and context/token budget statistics (⚠️ WARNING: May expose sensitive data). Disabled means no log comment and no published budget statistics.",
|
|
140
140
|
default: false,
|
|
141
141
|
},
|
|
142
142
|
'dangerously-skip-output-sanitization': {
|
|
@@ -505,7 +505,7 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
505
505
|
},
|
|
506
506
|
'tokens-budget-stats': {
|
|
507
507
|
type: 'boolean',
|
|
508
|
-
description: 'Show detailed token budget statistics including context window usage and ratios (enabled by default, use --no-tokens-budget-stats to disable). Supported for --tool claude, --tool codex, and any tool that returns detailed token usage.',
|
|
508
|
+
description: 'Show detailed token budget statistics including context window usage and ratios (enabled by default, use --no-tokens-budget-stats to disable). Shown in the terminal; publishing them to the pull request additionally requires --attach-logs, and they appear only in the working session log comment (never in the working session summary). Supported for --tool claude, --tool codex, and any tool that returns detailed token usage.',
|
|
509
509
|
default: true,
|
|
510
510
|
},
|
|
511
511
|
'prompt-issue-reporting': {
|
package/src/solve.mjs
CHANGED
|
@@ -29,8 +29,6 @@ import { safeExit } from './exit-handler.lib.mjs';
|
|
|
29
29
|
// Import GitHub-related functions
|
|
30
30
|
const githubLib = await import('./github.lib.mjs');
|
|
31
31
|
const { sanitizeLogContent, attachLogToGitHub } = githubLib;
|
|
32
|
-
const { buildCostInfoString } = await import('./github-cost-info.lib.mjs');
|
|
33
|
-
const { buildBudgetStatsString } = await import('./claude.budget-stats.lib.mjs');
|
|
34
32
|
|
|
35
33
|
// Issue #1745: process-wide sanitization counters used to print a one-line
|
|
36
34
|
// "we masked N secrets" summary at the end of each run.
|
|
@@ -674,7 +672,18 @@ export const showSessionSummary = async (sessionId, limitReached, argv, issueUrl
|
|
|
674
672
|
// same observed facts (working-session summary and attached log alike).
|
|
675
673
|
export const buildSessionBudgetStatsData = async ({ argv, sessionId = null, tempDir = null, resultModelUsage = null, streamTokenUsage = null, subAgentCalls = null, pricingInfo = null }) => {
|
|
676
674
|
let budgetStatsData = null;
|
|
677
|
-
|
|
675
|
+
// Issue #2132: budget stats are a property of the working session **log**.
|
|
676
|
+
// With `--attach-logs` disabled there is no log comment, so they must not be
|
|
677
|
+
// computed or published anywhere.
|
|
678
|
+
const { shouldPublishBudgetStats, isAttachLogsEnabled, isTokensBudgetStatsEnabled } = await import('./budget-stats-policy.lib.mjs');
|
|
679
|
+
if (!shouldPublishBudgetStats(argv)) {
|
|
680
|
+
if (argv?.verbose) {
|
|
681
|
+
const reason = !isTokensBudgetStatsEnabled(argv) ? '--no-tokens-budget-stats' : !isAttachLogsEnabled(argv) ? '--attach-logs is disabled' : 'unknown';
|
|
682
|
+
await log(` ℹ️ Skipping context/cost budget stats publication (${reason})`, { verbose: true });
|
|
683
|
+
}
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
686
|
+
if (sessionId && tempDir) {
|
|
678
687
|
try {
|
|
679
688
|
const { calculateSessionTokens } = await import('./claude.lib.mjs');
|
|
680
689
|
const tokenUsage = await calculateSessionTokens(sessionId, tempDir, resultModelUsage);
|
|
@@ -686,7 +695,7 @@ export const buildSessionBudgetStatsData = async ({ argv, sessionId = null, temp
|
|
|
686
695
|
}
|
|
687
696
|
}
|
|
688
697
|
// Issue #1526: Build budget stats from Agent CLI token/context data when no JSONL session available
|
|
689
|
-
if (!budgetStatsData &&
|
|
698
|
+
if (!budgetStatsData && pricingInfo?.tokenUsage) {
|
|
690
699
|
try {
|
|
691
700
|
const { buildAgentBudgetStats } = await import('./claude.budget-stats.lib.mjs');
|
|
692
701
|
const agentBudgetData = buildAgentBudgetStats(pricingInfo.tokenUsage, pricingInfo);
|
|
@@ -1264,15 +1273,19 @@ export const checkForAiCreatedComments = async (sessionStartTime, owner, repo, p
|
|
|
1264
1273
|
* @param {string} options.repo - Repository name
|
|
1265
1274
|
* @returns {Promise<boolean>} - True if comment was posted successfully
|
|
1266
1275
|
*/
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1276
|
+
/**
|
|
1277
|
+
* Issue #2132: the working session summary must describe *what the AI did* and
|
|
1278
|
+
* nothing else. Cost estimation and context/token budget statistics belong to
|
|
1279
|
+
* the working session log comment (`--attach-logs`), where they are already
|
|
1280
|
+
* published once per working session. Rendering them in the summary as well
|
|
1281
|
+
* duplicated the very same block in two consecutive comments.
|
|
1282
|
+
*
|
|
1283
|
+
* Kept as an exported function returning an empty string so the invariant is
|
|
1284
|
+
* directly testable and any future caller cannot silently re-add the block.
|
|
1285
|
+
*/
|
|
1286
|
+
export const buildWorkingSessionSummaryDetails = () => '';
|
|
1274
1287
|
|
|
1275
|
-
export const attachSolutionSummary = async ({ resultSummary, prNumber, issueNumber, owner, repo,
|
|
1288
|
+
export const attachSolutionSummary = async ({ resultSummary, prNumber, issueNumber, owner, repo, changeStats = null }) => {
|
|
1276
1289
|
if (!resultSummary || typeof resultSummary !== 'string') {
|
|
1277
1290
|
await log('⚠️ No working session summary available to attach', { verbose: true });
|
|
1278
1291
|
return false;
|
|
@@ -1287,12 +1300,6 @@ export const attachSolutionSummary = async ({ resultSummary, prNumber, issueNumb
|
|
|
1287
1300
|
}
|
|
1288
1301
|
|
|
1289
1302
|
try {
|
|
1290
|
-
const usageDetails = buildWorkingSessionSummaryDetails({
|
|
1291
|
-
publicPricingEstimate,
|
|
1292
|
-
anthropicTotalCostUSD,
|
|
1293
|
-
pricingInfo,
|
|
1294
|
-
budgetStatsData,
|
|
1295
|
-
});
|
|
1296
1303
|
// Issue #2119: publish what the session actually produced. The reported
|
|
1297
1304
|
// summary said "The `pwd` command completed" and printed the solver's own
|
|
1298
1305
|
// /tmp workspace, on a pull request that was still empty.
|
|
@@ -1302,7 +1309,7 @@ export const attachSolutionSummary = async ({ resultSummary, prNumber, issueNumb
|
|
|
1302
1309
|
const comment = `${toolComments.WORKING_SESSION_SUMMARY_AUTOMATION_MARKER}
|
|
1303
1310
|
## ${toolComments.WORKING_SESSION_SUMMARY_MARKER}
|
|
1304
1311
|
|
|
1305
|
-
${summaryBody}${noChangesNotice ? `\n\n${noChangesNotice}` : ''}
|
|
1312
|
+
${summaryBody}${noChangesNotice ? `\n\n${noChangesNotice}` : ''}
|
|
1306
1313
|
|
|
1307
1314
|
---
|
|
1308
1315
|
*${toolComments.WORKING_SESSION_SUMMARY_AUTOMATED_FOOTER}*`;
|
|
@@ -1359,7 +1366,7 @@ ${summaryBody}${noChangesNotice ? `\n\n${noChangesNotice}` : ''}${usageDetails ?
|
|
|
1359
1366
|
* @param {boolean} [options.success=true] - skip attachment for failed iterations
|
|
1360
1367
|
* @returns {Promise<{attached: boolean, reason: string}>}
|
|
1361
1368
|
*/
|
|
1362
|
-
export const maybeAttachWorkingSessionSummary = async ({ argv, resultSummary, workStartTime, owner, repo, prNumber, issueNumber, success = true,
|
|
1369
|
+
export const maybeAttachWorkingSessionSummary = async ({ argv, resultSummary, workStartTime, owner, repo, prNumber, issueNumber, success = true, pricingInfo = null, budgetStatsData = null, sessionUsage = null }) => {
|
|
1363
1370
|
if (!success) {
|
|
1364
1371
|
return { attached: false, reason: 'iteration_failed' };
|
|
1365
1372
|
}
|
|
@@ -1408,16 +1415,14 @@ export const maybeAttachWorkingSessionSummary = async ({ argv, resultSummary, wo
|
|
|
1408
1415
|
// say so, instead of reading as a report of completed work.
|
|
1409
1416
|
const changeStats = prNumber ? await getPullRequestChangeStats({ owner, repo, prNumber, $ }) : null;
|
|
1410
1417
|
|
|
1418
|
+
// Issue #2132: the summary carries no cost/budget block. `resolvedBudgetStatsData`
|
|
1419
|
+
// is computed only so the caller can reuse it for this session's log comment.
|
|
1411
1420
|
const ok = await attachSolutionSummary({
|
|
1412
1421
|
resultSummary,
|
|
1413
1422
|
prNumber,
|
|
1414
1423
|
issueNumber,
|
|
1415
1424
|
owner,
|
|
1416
1425
|
repo,
|
|
1417
|
-
publicPricingEstimate,
|
|
1418
|
-
anthropicTotalCostUSD,
|
|
1419
|
-
pricingInfo,
|
|
1420
|
-
budgetStatsData: resolvedBudgetStatsData,
|
|
1421
1426
|
changeStats,
|
|
1422
1427
|
});
|
|
1423
1428
|
return { attached: !!ok, reason: ok ? 'attached' : 'post_failed', budgetStatsData: resolvedBudgetStatsData };
|
package/src/solve.watch.lib.mjs
CHANGED
|
@@ -567,19 +567,21 @@ export const watchForFeedback = async params => {
|
|
|
567
567
|
latestResultModelUsage = toolResult.resultModelUsage;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
// Issue #1508: Compute budget stats for auto-restart log comment
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
570
|
+
// Issue #1508: Compute budget stats for auto-restart log comment.
|
|
571
|
+
// Issue #2132: shared with the top-level run and the
|
|
572
|
+
// auto-restart-until-mergeable loop via buildSessionBudgetStatsData,
|
|
573
|
+
// so every working session derives its own stats the same way (and
|
|
574
|
+
// skips them entirely when `--attach-logs` is disabled).
|
|
575
|
+
const { buildSessionBudgetStatsData } = await import('./solve.results.lib.mjs');
|
|
576
|
+
const autoRestartBudgetStatsData = await buildSessionBudgetStatsData({
|
|
577
|
+
argv,
|
|
578
|
+
sessionId: latestSessionId,
|
|
579
|
+
tempDir,
|
|
580
|
+
resultModelUsage: toolResult.resultModelUsage,
|
|
581
|
+
streamTokenUsage: toolResult.streamTokenUsage || null,
|
|
582
|
+
subAgentCalls: toolResult.subAgentCalls || null,
|
|
583
|
+
pricingInfo: toolResult.pricingInfo || null,
|
|
584
|
+
});
|
|
583
585
|
|
|
584
586
|
// Issue #1761: Post the working session **summary** BEFORE uploading
|
|
585
587
|
// the working session **log** so the summary always appears above
|
|
@@ -604,8 +606,6 @@ export const watchForFeedback = async params => {
|
|
|
604
606
|
prNumber,
|
|
605
607
|
issueNumber,
|
|
606
608
|
success: true,
|
|
607
|
-
publicPricingEstimate: toolResult.publicPricingEstimate,
|
|
608
|
-
anthropicTotalCostUSD: latestAnthropicCost,
|
|
609
609
|
pricingInfo: toolResult.pricingInfo,
|
|
610
610
|
budgetStatsData: autoRestartBudgetStatsData,
|
|
611
611
|
});
|