@link-assistant/hive-mind 1.51.0 ā 1.52.1
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 +12 -0
- package/package.json +2 -1
- package/src/agent-token-usage.lib.mjs +96 -0
- package/src/agent.lib.mjs +32 -134
- package/src/agent.prompts.lib.mjs +4 -9
- package/src/claude.budget-stats.lib.mjs +41 -61
- package/src/claude.lib.mjs +14 -14
- package/src/claude.prompts.lib.mjs +5 -13
- package/src/codex.lib.mjs +52 -5
- package/src/codex.options.lib.mjs +1 -0
- package/src/codex.prompts.lib.mjs +4 -9
- package/src/config.lib.mjs +133 -31
- package/src/github-cost-info.lib.mjs +70 -0
- package/src/github.lib.mjs +2 -54
- package/src/models/index.mjs +11 -6
- package/src/opencode.lib.mjs +47 -0
- package/src/opencode.prompts.lib.mjs +4 -9
- package/src/solve.config.lib.mjs +7 -2
- package/src/telegram-bot.mjs +1 -1
- package/src/thinking-prompt.lib.mjs +61 -0
package/src/github.lib.mjs
CHANGED
|
@@ -14,60 +14,8 @@ import { formatResetTimeWithRelative } from './usage-limit.lib.mjs'; // See: htt
|
|
|
14
14
|
import { getToolDisplayName, getModelInfoForComment } from './models/index.mjs';
|
|
15
15
|
export { getToolDisplayName }; // Re-export for use by other modules
|
|
16
16
|
import { buildBudgetStatsString } from './claude.budget-stats.lib.mjs';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const buildCostInfoString = (totalCostUSD, anthropicTotalCostUSD, pricingInfo) => {
|
|
20
|
-
const hasPublic = totalCostUSD !== null && totalCostUSD !== undefined;
|
|
21
|
-
const hasAnthropic = anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined;
|
|
22
|
-
const hasPricing = pricingInfo && (pricingInfo.modelName || pricingInfo.tokenUsage || pricingInfo.isFreeModel || pricingInfo.isOpencodeFreeModel);
|
|
23
|
-
const hasOpencodeCost = pricingInfo?.opencodeCost !== null && pricingInfo?.opencodeCost !== undefined;
|
|
24
|
-
if (!hasPublic && !hasAnthropic && !hasPricing && !hasOpencodeCost) return '';
|
|
25
|
-
// Issue #1557: Simplified display when public and Anthropic costs match
|
|
26
|
-
if (hasPublic && hasAnthropic && totalCostUSD.toFixed(6) === anthropicTotalCostUSD.toFixed(6)) return `\n\n### š° Cost: **$${anthropicTotalCostUSD.toFixed(6)}**`;
|
|
27
|
-
let costInfo = '\n\n### š° **Cost estimation:**';
|
|
28
|
-
if (pricingInfo?.modelName) {
|
|
29
|
-
costInfo += `\n- Model: ${pricingInfo.modelName}`;
|
|
30
|
-
if (pricingInfo.provider) costInfo += `\n- Provider: ${pricingInfo.provider}`;
|
|
31
|
-
}
|
|
32
|
-
if (hasPublic) {
|
|
33
|
-
if (pricingInfo?.isFreeModel && totalCostUSD === 0 && !pricingInfo?.baseModelName) {
|
|
34
|
-
costInfo += '\n- Public pricing estimate: $0.00 (Free model)';
|
|
35
|
-
} else {
|
|
36
|
-
let pricingRef = '';
|
|
37
|
-
if (pricingInfo?.baseModelName && pricingInfo?.originalProvider) {
|
|
38
|
-
pricingRef = ` (based on ${pricingInfo.originalProvider} ${pricingInfo.baseModelName} prices)`;
|
|
39
|
-
} else if (pricingInfo?.originalProvider) {
|
|
40
|
-
pricingRef = ` (based on ${pricingInfo.originalProvider} prices)`;
|
|
41
|
-
}
|
|
42
|
-
costInfo += `\n- Public pricing estimate: $${totalCostUSD.toFixed(6)}${pricingRef}`;
|
|
43
|
-
}
|
|
44
|
-
} else if (hasPricing) {
|
|
45
|
-
costInfo += '\n- Public pricing estimate: unknown';
|
|
46
|
-
}
|
|
47
|
-
if (hasOpencodeCost) {
|
|
48
|
-
if (pricingInfo.isOpencodeFreeModel) {
|
|
49
|
-
costInfo += '\n- Calculated by OpenCode Zen: $0.00 (Free model)';
|
|
50
|
-
} else {
|
|
51
|
-
costInfo += `\n- Calculated by OpenCode Zen: $${pricingInfo.opencodeCost.toFixed(6)}`;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (pricingInfo?.tokenUsage) {
|
|
55
|
-
const u = pricingInfo.tokenUsage;
|
|
56
|
-
let tokenInfo = `\n- Token usage: ${u.inputTokens?.toLocaleString() || 0} input, ${u.outputTokens?.toLocaleString() || 0} output`;
|
|
57
|
-
if (u.reasoningTokens > 0) tokenInfo += `, ${u.reasoningTokens.toLocaleString()} reasoning`;
|
|
58
|
-
if (u.cacheReadTokens > 0 || u.cacheWriteTokens > 0) tokenInfo += `, ${u.cacheReadTokens?.toLocaleString() || 0} cache read, ${u.cacheWriteTokens?.toLocaleString() || 0} cache write`;
|
|
59
|
-
costInfo += tokenInfo;
|
|
60
|
-
}
|
|
61
|
-
if (hasAnthropic) {
|
|
62
|
-
costInfo += `\n- Calculated by Anthropic: $${anthropicTotalCostUSD.toFixed(6)}`;
|
|
63
|
-
if (hasPublic) {
|
|
64
|
-
const diff = anthropicTotalCostUSD - totalCostUSD;
|
|
65
|
-
const pct = totalCostUSD > 0 ? (diff / totalCostUSD) * 100 : 0;
|
|
66
|
-
costInfo += `\n- Difference: $${diff.toFixed(6)} (${pct > 0 ? '+' : ''}${pct.toFixed(2)}%)`;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return costInfo;
|
|
70
|
-
};
|
|
17
|
+
import { buildCostInfoString } from './github-cost-info.lib.mjs';
|
|
18
|
+
export { buildCostInfoString };
|
|
71
19
|
export const maskGitHubToken = maskToken; // Alias for backward compatibility
|
|
72
20
|
export const escapeCodeBlocksInLog = logContent => logContent.replace(/```/g, '\\`\\`\\`'); // Escape ``` in logs
|
|
73
21
|
export const checkFileInBranch = async (owner, repo, fileName, branchName) => {
|
package/src/models/index.mjs
CHANGED
|
@@ -23,23 +23,25 @@ import { log } from '../lib.mjs';
|
|
|
23
23
|
// āāā MODEL DATA āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
24
24
|
|
|
25
25
|
// Claude models (Anthropic API)
|
|
26
|
-
// Updated for Opus 4.5/4.6 and Sonnet 4.6 support (Issue #1221, Issue #1238, Issue #1329, Issue #1433)
|
|
26
|
+
// Updated for Opus 4.5/4.6/4.7 and Sonnet 4.6 support (Issue #1221, Issue #1238, Issue #1329, Issue #1433, Issue #1620)
|
|
27
27
|
export const claudeModels = {
|
|
28
28
|
sonnet: 'claude-sonnet-4-6', // Sonnet 4.6 (default, Issue #1329)
|
|
29
|
-
opus: 'claude-opus-4-
|
|
29
|
+
opus: 'claude-opus-4-7', // Opus 4.7 (Issue #1620)
|
|
30
30
|
haiku: 'claude-haiku-4-5-20251001', // Haiku 4.5
|
|
31
31
|
'haiku-3-5': 'claude-3-5-haiku-20241022', // Haiku 3.5
|
|
32
32
|
'haiku-3': 'claude-3-haiku-20240307', // Haiku 3
|
|
33
33
|
opusplan: 'opusplan', // Special mode: Opus for planning, Sonnet for execution (Issue #1223)
|
|
34
34
|
// Shorter version aliases (Issue #1221, Issue #1329 - PR comment feedback)
|
|
35
35
|
'sonnet-4-6': 'claude-sonnet-4-6', // Sonnet 4.6 short alias (Issue #1329)
|
|
36
|
-
'opus-4-
|
|
36
|
+
'opus-4-7': 'claude-opus-4-7', // Opus 4.7 short alias (Issue #1620)
|
|
37
|
+
'opus-4-6': 'claude-opus-4-6', // Opus 4.6 short alias (backward compatibility)
|
|
37
38
|
'opus-4-5': 'claude-opus-4-5-20251101', // Opus 4.5 short alias
|
|
38
39
|
'sonnet-4-5': 'claude-sonnet-4-5-20250929', // Sonnet 4.5 short alias (backward compatibility)
|
|
39
40
|
'haiku-4-5': 'claude-haiku-4-5-20251001', // Haiku 4.5 short alias
|
|
40
|
-
// Version aliases for backward compatibility (Issue #1221, Issue #1329)
|
|
41
|
+
// Version aliases for backward compatibility (Issue #1221, Issue #1329, Issue #1620)
|
|
42
|
+
'claude-opus-4-7': 'claude-opus-4-7', // Opus 4.7 (Issue #1620)
|
|
41
43
|
'claude-sonnet-4-6': 'claude-sonnet-4-6', // Sonnet 4.6 (Issue #1329)
|
|
42
|
-
'claude-opus-4-6': 'claude-opus-4-6', // Opus 4.6
|
|
44
|
+
'claude-opus-4-6': 'claude-opus-4-6', // Opus 4.6 (backward compatibility)
|
|
43
45
|
'claude-opus-4-5': 'claude-opus-4-5-20251101', // Opus 4.5
|
|
44
46
|
'claude-sonnet-4-5': 'claude-sonnet-4-5-20250929', // Sonnet 4.5 (backward compatibility)
|
|
45
47
|
'claude-haiku-4-5': 'claude-haiku-4-5-20251001', // Haiku 4.5
|
|
@@ -129,6 +131,7 @@ export const defaultModels = {
|
|
|
129
131
|
// Models that support 1M token context window via [1m] suffix (Issue #1221, Issue #1238, Issue #1329)
|
|
130
132
|
// See: https://code.claude.com/docs/en/model-config
|
|
131
133
|
export const MODELS_SUPPORTING_1M_CONTEXT = [
|
|
134
|
+
'claude-opus-4-7', // Opus 4.7 (Issue #1620)
|
|
132
135
|
'claude-opus-4-6',
|
|
133
136
|
'claude-opus-4-5-20251101',
|
|
134
137
|
'claude-sonnet-4-6', // Sonnet 4.6 (Issue #1329)
|
|
@@ -136,7 +139,8 @@ export const MODELS_SUPPORTING_1M_CONTEXT = [
|
|
|
136
139
|
'claude-sonnet-4-5',
|
|
137
140
|
'sonnet', // Now maps to Sonnet 4.6 (Issue #1329)
|
|
138
141
|
'sonnet-4-6', // Short alias (Issue #1329)
|
|
139
|
-
'opus',
|
|
142
|
+
'opus', // Now maps to Opus 4.7 (Issue #1620)
|
|
143
|
+
'opus-4-7', // Short alias (Issue #1620)
|
|
140
144
|
'opus-4-6', // Short alias (Issue #1221 - PR comment feedback)
|
|
141
145
|
'opus-4-5', // Short alias (Issue #1238)
|
|
142
146
|
'sonnet-4-5', // Short alias (Issue #1221 - PR comment feedback)
|
|
@@ -165,6 +169,7 @@ export const freeToBaseModelMap = {
|
|
|
165
169
|
|
|
166
170
|
export const CLAUDE_MODELS = {
|
|
167
171
|
...claudeModels,
|
|
172
|
+
'claude-opus-4-7': 'claude-opus-4-7', // Opus 4.7 full ID (Issue #1620)
|
|
168
173
|
'claude-sonnet-4-5-20250929': 'claude-sonnet-4-5-20250929',
|
|
169
174
|
'claude-opus-4-5-20251101': 'claude-opus-4-5-20251101',
|
|
170
175
|
'claude-haiku-4-5-20251001': 'claude-haiku-4-5-20251001',
|
package/src/opencode.lib.mjs
CHANGED
|
@@ -19,6 +19,10 @@ import { timeouts } from './config.lib.mjs';
|
|
|
19
19
|
import { detectUsageLimit, formatUsageLimitMessage } from './usage-limit.lib.mjs';
|
|
20
20
|
import { sanitizeObjectStrings } from './unicode-sanitization.lib.mjs';
|
|
21
21
|
import { opencodeModels, defaultModels } from './models/index.mjs';
|
|
22
|
+
import { createAgentTokenUsage, accumulateAgentStepFinishUsage, parseAgentTokenUsage as parseOpenCodeTokenUsage } from './agent-token-usage.lib.mjs';
|
|
23
|
+
import { calculateAgentPricing } from './agent.lib.mjs';
|
|
24
|
+
|
|
25
|
+
export { parseOpenCodeTokenUsage };
|
|
22
26
|
|
|
23
27
|
// Model mapping to translate aliases to full model IDs for OpenCode
|
|
24
28
|
// Issue #1473: Uses centralized opencodeModels from models/index.mjs (single source of truth)
|
|
@@ -242,6 +246,7 @@ export const executeOpenCodeCommand = async params => {
|
|
|
242
246
|
|
|
243
247
|
// Map model alias to full ID
|
|
244
248
|
const mappedModel = mapModelToId(argv.model);
|
|
249
|
+
const streamingTokenUsage = createAgentTokenUsage();
|
|
245
250
|
|
|
246
251
|
// Build opencode command arguments
|
|
247
252
|
let opencodeArgs = `run --format json --model ${mappedModel}`;
|
|
@@ -268,6 +273,15 @@ export const executeOpenCodeCommand = async params => {
|
|
|
268
273
|
await log(`${fullCommand}`);
|
|
269
274
|
await log('');
|
|
270
275
|
|
|
276
|
+
const buildPricingInfo = async () => {
|
|
277
|
+
const tokenUsage = streamingTokenUsage;
|
|
278
|
+
if (tokenUsage.stepCount === 0) {
|
|
279
|
+
return { tokenUsage, pricingInfo: null, publicPricingEstimate: null };
|
|
280
|
+
}
|
|
281
|
+
const pricingInfo = await calculateAgentPricing(mappedModel, tokenUsage);
|
|
282
|
+
return { tokenUsage, pricingInfo, publicPricingEstimate: pricingInfo?.totalCostUSD ?? null };
|
|
283
|
+
};
|
|
284
|
+
|
|
271
285
|
try {
|
|
272
286
|
// Pipe the prompt file to opencode via stdin
|
|
273
287
|
if (argv.resume) {
|
|
@@ -313,6 +327,7 @@ export const executeOpenCodeCommand = async params => {
|
|
|
313
327
|
for (const line of lines) {
|
|
314
328
|
if (!line.trim()) continue;
|
|
315
329
|
const data = sanitizeObjectStrings(JSON.parse(line));
|
|
330
|
+
accumulateAgentStepFinishUsage(streamingTokenUsage, data);
|
|
316
331
|
// Track text content for result summary
|
|
317
332
|
// OpenCode outputs text via 'text', 'assistant', 'message', or 'result' type events
|
|
318
333
|
if (data.type === 'text' && data.text) {
|
|
@@ -355,6 +370,7 @@ export const executeOpenCodeCommand = async params => {
|
|
|
355
370
|
for (const line of lines) {
|
|
356
371
|
if (!line.trim()) continue;
|
|
357
372
|
const data = sanitizeObjectStrings(JSON.parse(line));
|
|
373
|
+
accumulateAgentStepFinishUsage(streamingTokenUsage, data);
|
|
358
374
|
if (data.type === 'text' && data.text) {
|
|
359
375
|
lastTextContent = data.text;
|
|
360
376
|
} else if (data.type === 'assistant' && data.message?.content) {
|
|
@@ -427,12 +443,14 @@ export const executeOpenCodeCommand = async params => {
|
|
|
427
443
|
await log(` Memory: ${resourcesAfter.memory.split('\n')[1]}`, { verbose: true });
|
|
428
444
|
await log(` Load: ${resourcesAfter.load}`, { verbose: true });
|
|
429
445
|
|
|
446
|
+
const pricingResult = await buildPricingInfo();
|
|
430
447
|
return {
|
|
431
448
|
success: false,
|
|
432
449
|
sessionId,
|
|
433
450
|
limitReached: false,
|
|
434
451
|
limitResetTime: null,
|
|
435
452
|
permissionPromptDetected: true,
|
|
453
|
+
...pricingResult,
|
|
436
454
|
resultSummary: lastTextContent || null, // Issue #1263: Use last text content from JSON output stream
|
|
437
455
|
};
|
|
438
456
|
}
|
|
@@ -466,17 +484,41 @@ export const executeOpenCodeCommand = async params => {
|
|
|
466
484
|
await log(` Memory: ${resourcesAfter.memory.split('\n')[1]}`, { verbose: true });
|
|
467
485
|
await log(` Load: ${resourcesAfter.load}`, { verbose: true });
|
|
468
486
|
|
|
487
|
+
const pricingResult = await buildPricingInfo();
|
|
469
488
|
return {
|
|
470
489
|
success: false,
|
|
471
490
|
sessionId,
|
|
472
491
|
limitReached,
|
|
473
492
|
limitResetTime,
|
|
493
|
+
...pricingResult,
|
|
474
494
|
resultSummary: lastTextContent || null, // Issue #1263: Use last text content from JSON output stream
|
|
475
495
|
};
|
|
476
496
|
}
|
|
477
497
|
|
|
478
498
|
await log('\n\nā
OpenCode command completed');
|
|
479
499
|
|
|
500
|
+
const pricingResult = await buildPricingInfo();
|
|
501
|
+
if (pricingResult.tokenUsage.stepCount > 0) {
|
|
502
|
+
await log('\nš° Token Usage Summary:');
|
|
503
|
+
await log(` š ${pricingResult.pricingInfo?.modelName || mappedModel} (${pricingResult.tokenUsage.stepCount} steps):`);
|
|
504
|
+
await log(` Input tokens: ${pricingResult.tokenUsage.inputTokens.toLocaleString()}`);
|
|
505
|
+
await log(` Output tokens: ${pricingResult.tokenUsage.outputTokens.toLocaleString()}`);
|
|
506
|
+
if (pricingResult.tokenUsage.reasoningTokens > 0 || pricingResult.tokenUsage.tokenFieldAvailability?.reasoningTokens) {
|
|
507
|
+
await log(` Reasoning tokens: ${pricingResult.tokenUsage.reasoningTokens.toLocaleString()}`);
|
|
508
|
+
}
|
|
509
|
+
if (pricingResult.tokenUsage.cacheReadTokens > 0 || pricingResult.tokenUsage.tokenFieldAvailability?.cacheReadTokens) {
|
|
510
|
+
await log(` Cache read: ${pricingResult.tokenUsage.cacheReadTokens.toLocaleString()}`);
|
|
511
|
+
}
|
|
512
|
+
if (pricingResult.tokenUsage.cacheWriteTokens > 0 || pricingResult.tokenUsage.tokenFieldAvailability?.cacheWriteTokens) {
|
|
513
|
+
await log(` Cache write: ${pricingResult.tokenUsage.cacheWriteTokens.toLocaleString()}`);
|
|
514
|
+
}
|
|
515
|
+
if (pricingResult.pricingInfo?.totalCostUSD !== null && pricingResult.pricingInfo?.totalCostUSD !== undefined) {
|
|
516
|
+
await log(` Public pricing estimate: $${pricingResult.pricingInfo.totalCostUSD.toFixed(6)}`);
|
|
517
|
+
} else {
|
|
518
|
+
await log(' Cost: Not available (could not fetch pricing)');
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
480
522
|
// Issue #1263: Log if result summary was captured
|
|
481
523
|
if (lastTextContent) {
|
|
482
524
|
await log('š Captured result summary from OpenCode output', { verbose: true });
|
|
@@ -487,6 +529,7 @@ export const executeOpenCodeCommand = async params => {
|
|
|
487
529
|
sessionId,
|
|
488
530
|
limitReached,
|
|
489
531
|
limitResetTime,
|
|
532
|
+
...pricingResult,
|
|
490
533
|
resultSummary: lastTextContent || null, // Issue #1263: Use last text content from JSON output stream
|
|
491
534
|
};
|
|
492
535
|
} catch (error) {
|
|
@@ -510,6 +553,9 @@ export const executeOpenCodeCommand = async params => {
|
|
|
510
553
|
sessionId: null,
|
|
511
554
|
limitReached: false,
|
|
512
555
|
limitResetTime: null,
|
|
556
|
+
tokenUsage: streamingTokenUsage.stepCount > 0 ? streamingTokenUsage : null,
|
|
557
|
+
pricingInfo: null,
|
|
558
|
+
publicPricingEstimate: null,
|
|
513
559
|
resultSummary: null, // Issue #1263: No result summary available on error
|
|
514
560
|
};
|
|
515
561
|
}
|
|
@@ -610,4 +656,5 @@ export default {
|
|
|
610
656
|
executeOpenCode,
|
|
611
657
|
executeOpenCodeCommand,
|
|
612
658
|
checkForUncommittedChanges,
|
|
659
|
+
parseOpenCodeTokenUsage,
|
|
613
660
|
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
|
|
7
7
|
import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
|
|
8
|
+
import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Build the user prompt for OpenCode
|
|
@@ -58,15 +59,9 @@ export const buildUserPrompt = params => {
|
|
|
58
59
|
promptLines.push('');
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
low: 'Think.',
|
|
65
|
-
medium: 'Think hard.',
|
|
66
|
-
high: 'Think harder.',
|
|
67
|
-
max: 'Ultrathink.',
|
|
68
|
-
};
|
|
69
|
-
promptLines.push(thinkMessages[argv.think]);
|
|
62
|
+
const thinkingPromptInstruction = getThinkingPromptInstruction({ tool: 'opencode', argv });
|
|
63
|
+
if (thinkingPromptInstruction) {
|
|
64
|
+
promptLines.push(thinkingPromptInstruction);
|
|
70
65
|
}
|
|
71
66
|
|
|
72
67
|
// Final instruction
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -229,8 +229,8 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
229
229
|
},
|
|
230
230
|
think: {
|
|
231
231
|
type: 'string',
|
|
232
|
-
description: 'Thinking level hint. For Claude, translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, max=31999). For Codex, mapped to reasoning effort (off=none, low=low, medium=medium, high=high, max=xhigh).',
|
|
233
|
-
choices: ['off', 'low', 'medium', 'high', 'max'],
|
|
232
|
+
description: 'Thinking level hint. For Claude, translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, xhigh/max=31999) and to CLAUDE_CODE_EFFORT_LEVEL when supported. Opus 4.7 supports xhigh and max; Opus 4.6/Sonnet 4.6/Mythos support max; Opus 4.5 uses high for xhigh/max. For Codex, mapped to reasoning effort (off=none, low=low, medium=medium, high=high, xhigh/max=xhigh).',
|
|
233
|
+
choices: ['off', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
234
234
|
default: undefined,
|
|
235
235
|
},
|
|
236
236
|
'thinking-budget': {
|
|
@@ -248,6 +248,11 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
248
248
|
description: 'Maximum thinking budget for calculating --think level mappings (default: 31999 for Claude Code). Values: off=0, low=max/4, medium=max/2, high=max*3/4, max=max.',
|
|
249
249
|
default: 31999,
|
|
250
250
|
},
|
|
251
|
+
'show-thinking-content': {
|
|
252
|
+
type: 'boolean',
|
|
253
|
+
description: 'Show thinking content in Claude responses. Opus 4.7 omits thinking content by default; this option opts in to receive summarized thinking blocks. Disabled by default. Only affects --tool claude.',
|
|
254
|
+
default: false,
|
|
255
|
+
},
|
|
251
256
|
'prompt-plan-sub-agent': {
|
|
252
257
|
type: 'boolean',
|
|
253
258
|
description: 'Encourage AI to use a planning sub-agent or planning workflow for initial planning. Supported for --tool claude and --tool codex.',
|
package/src/telegram-bot.mjs
CHANGED
|
@@ -651,7 +651,7 @@ bot.command('help', async ctx => {
|
|
|
651
651
|
message += 'š§ *Common Options:*\n';
|
|
652
652
|
message += `⢠\`--model <model>\` or \`-m\` - ${buildModelOptionDescription()}\n`;
|
|
653
653
|
message += '⢠`--base-branch <branch>` or `-b` - Target branch for PR (default: repo default branch)\n';
|
|
654
|
-
message += '⢠`--think <level>` - Thinking level (off/low/medium/high/max) | `--thinking-budget <num>` - Token budget (0-63999)\n';
|
|
654
|
+
message += '⢠`--think <level>` - Thinking level (off/low/medium/high/xhigh/max) | `--thinking-budget <num>` - Token budget (0-63999)\n';
|
|
655
655
|
message += '⢠`--verbose` or `-v` - Verbose output | `--attach-logs` - Attach logs to PR\n';
|
|
656
656
|
message += '\nš” *Tip:* Many more options available. See full documentation for complete list.\n';
|
|
657
657
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { supportsEffortLevel, supportsThinkingBudget } from './config.lib.mjs';
|
|
4
|
+
import { defaultModels, mapModelForTool } from './models/index.mjs';
|
|
5
|
+
|
|
6
|
+
export const THINK_PROMPT_MESSAGES = Object.freeze({
|
|
7
|
+
low: 'Think.',
|
|
8
|
+
medium: 'Think hard.',
|
|
9
|
+
high: 'Think harder.',
|
|
10
|
+
xhigh: 'Ultrathink.',
|
|
11
|
+
max: 'Ultrathink.',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
export const isClaudeLikeModel = model => {
|
|
15
|
+
if (!model) return false;
|
|
16
|
+
const normalized = String(model).toLowerCase();
|
|
17
|
+
return normalized === 'opusplan' || normalized.includes('claude') || normalized.startsWith('anthropic/');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const resolvePromptModelForTool = (tool = 'claude', model) => {
|
|
21
|
+
const selectedModel = model || defaultModels[tool];
|
|
22
|
+
return selectedModel ? mapModelForTool(tool, selectedModel) : null;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const toolSupportsStructuredThinkingBudget = ({ tool = 'claude', claudeVersion, thinkingBudgetClaudeMinimumVersion } = {}) => {
|
|
26
|
+
if (tool === 'claude') {
|
|
27
|
+
return supportsThinkingBudget(claudeVersion || '0.0.0', thinkingBudgetClaudeMinimumVersion || '2.1.12');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Codex maps --think/--thinking-budget to model_reasoning_effort instead of prompt text.
|
|
31
|
+
return tool === 'codex';
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const shouldAddThinkingPromptInstruction = ({ tool = 'claude', argv, claudeVersion } = {}) => {
|
|
35
|
+
const thinkLevel = argv?.think;
|
|
36
|
+
if (!thinkLevel || !THINK_PROMPT_MESSAGES[thinkLevel]) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const resolvedModel = resolvePromptModelForTool(tool, argv?.model);
|
|
41
|
+
if (!isClaudeLikeModel(resolvedModel)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (supportsEffortLevel(resolvedModel)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return !toolSupportsStructuredThinkingBudget({
|
|
50
|
+
tool,
|
|
51
|
+
claudeVersion,
|
|
52
|
+
thinkingBudgetClaudeMinimumVersion: argv?.thinkingBudgetClaudeMinimumVersion,
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const getThinkingPromptInstruction = options => {
|
|
57
|
+
if (!shouldAddThinkingPromptInstruction(options)) {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
return THINK_PROMPT_MESSAGES[options?.argv?.think];
|
|
61
|
+
};
|