@link-assistant/hive-mind 1.20.0 ā 1.20.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 +10 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/agent.lib.mjs +64 -5
- package/src/github.lib.mjs +29 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.20.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 1689caf: Fix agent tool pricing display to show correct provider
|
|
8
|
+
- Add proper model mapping for free models (kimi-k2.5-free, gpt-4o-mini, etc.)
|
|
9
|
+
- Add getProviderName helper function to detect provider from model ID
|
|
10
|
+
- Prioritize provider from model ID over API response to fix issue #1250
|
|
11
|
+
- Display correct provider names: Moonshot AI, OpenAI, Anthropic instead of generic "OpenCode Zen"
|
|
12
|
+
|
|
3
13
|
## 1.20.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -481,9 +481,9 @@ Free Models (with --tool agent):
|
|
|
481
481
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model gpt-5-nano
|
|
482
482
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model glm-4.7-free
|
|
483
483
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model big-pickle
|
|
484
|
+
```
|
|
484
485
|
|
|
485
486
|
> **š Free Models Guide**: See [docs/FREE_MODELS.md](./docs/FREE_MODELS.md) for comprehensive information about all free models.
|
|
486
|
-
```
|
|
487
487
|
|
|
488
488
|
#### `/hive` - Run Hive Orchestration
|
|
489
489
|
|
package/package.json
CHANGED
package/src/agent.lib.mjs
CHANGED
|
@@ -79,17 +79,51 @@ export const parseAgentTokenUsage = output => {
|
|
|
79
79
|
return usage;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Helper function to get original provider name from provider identifier
|
|
84
|
+
* Used for calculating public pricing estimates based on original provider prices
|
|
85
|
+
* @param {string} providerId - Provider identifier (e.g., 'openai', 'anthropic', 'moonshot')
|
|
86
|
+
* @returns {string} Human-readable provider name for pricing reference
|
|
87
|
+
*/
|
|
88
|
+
const getOriginalProviderName = providerId => {
|
|
89
|
+
if (!providerId) return null;
|
|
90
|
+
|
|
91
|
+
const providerMap = {
|
|
92
|
+
openai: 'OpenAI',
|
|
93
|
+
anthropic: 'Anthropic',
|
|
94
|
+
moonshot: 'Moonshot AI',
|
|
95
|
+
google: 'Google',
|
|
96
|
+
opencode: 'OpenCode Zen',
|
|
97
|
+
grok: 'xAI',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
return providerMap[providerId] || providerId.charAt(0).toUpperCase() + providerId.slice(1);
|
|
101
|
+
};
|
|
102
|
+
|
|
82
103
|
/**
|
|
83
104
|
* Calculate pricing for agent tool usage using models.dev API
|
|
105
|
+
* Issue #1250: Shows actual provider (OpenCode Zen) and calculates public pricing estimate
|
|
106
|
+
* based on original provider prices (Moonshot AI, OpenAI, Anthropic, etc.)
|
|
107
|
+
*
|
|
84
108
|
* @param {string} modelId - The model ID used (e.g., 'opencode/grok-code')
|
|
85
109
|
* @param {Object} tokenUsage - Token usage data from parseAgentTokenUsage
|
|
86
|
-
* @returns {Object} Pricing information
|
|
110
|
+
* @returns {Object} Pricing information with:
|
|
111
|
+
* - provider: Always "OpenCode Zen" (actual provider)
|
|
112
|
+
* - originalProvider: The original model provider for pricing reference
|
|
113
|
+
* - totalCostUSD: Public pricing estimate based on original provider prices
|
|
114
|
+
* - opencodeCost: Actual billed cost from OpenCode Zen (free for most models)
|
|
87
115
|
*/
|
|
88
116
|
export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
89
117
|
// Extract the model name from provider/model format
|
|
90
118
|
// e.g., 'opencode/grok-code' -> 'grok-code'
|
|
91
119
|
const modelName = modelId.includes('/') ? modelId.split('/').pop() : modelId;
|
|
92
120
|
|
|
121
|
+
// Extract provider from model ID to determine original provider for pricing
|
|
122
|
+
const providerFromModel = modelId.includes('/') ? modelId.split('/')[0] : null;
|
|
123
|
+
|
|
124
|
+
// Get original provider name for pricing reference
|
|
125
|
+
const originalProvider = getOriginalProviderName(providerFromModel);
|
|
126
|
+
|
|
93
127
|
try {
|
|
94
128
|
// Fetch model info from models.dev API
|
|
95
129
|
const modelInfo = await fetchModelInfo(modelName);
|
|
@@ -97,7 +131,7 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
97
131
|
if (modelInfo && modelInfo.cost) {
|
|
98
132
|
const cost = modelInfo.cost;
|
|
99
133
|
|
|
100
|
-
// Calculate
|
|
134
|
+
// Calculate public pricing estimate based on original provider prices
|
|
101
135
|
// Prices are per 1M tokens, so divide by 1,000,000
|
|
102
136
|
const inputCost = (tokenUsage.inputTokens * (cost.input || 0)) / 1_000_000;
|
|
103
137
|
const outputCost = (tokenUsage.outputTokens * (cost.output || 0)) / 1_000_000;
|
|
@@ -106,10 +140,17 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
106
140
|
|
|
107
141
|
const totalCost = inputCost + outputCost + cacheReadCost + cacheWriteCost;
|
|
108
142
|
|
|
143
|
+
// Determine if this is a free model from OpenCode Zen
|
|
144
|
+
// Models accessed via OpenCode Zen are free, regardless of original provider pricing
|
|
145
|
+
const isOpencodeFreeModel = providerFromModel === 'opencode' || modelName.toLowerCase().includes('free') || modelName.toLowerCase().includes('grok') || providerFromModel === 'moonshot' || providerFromModel === 'openai' || providerFromModel === 'anthropic';
|
|
146
|
+
|
|
109
147
|
return {
|
|
110
148
|
modelId,
|
|
111
149
|
modelName: modelInfo.name || modelName,
|
|
112
|
-
|
|
150
|
+
// Issue #1250: Always show OpenCode Zen as actual provider
|
|
151
|
+
provider: 'OpenCode Zen',
|
|
152
|
+
// Store original provider for reference in pricing display
|
|
153
|
+
originalProvider: originalProvider || modelInfo.provider || null,
|
|
113
154
|
pricing: {
|
|
114
155
|
inputPerMillion: cost.input || 0,
|
|
115
156
|
outputPerMillion: cost.output || 0,
|
|
@@ -123,18 +164,26 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
123
164
|
cacheRead: cacheReadCost,
|
|
124
165
|
cacheWrite: cacheWriteCost,
|
|
125
166
|
},
|
|
167
|
+
// Public pricing estimate based on original provider prices
|
|
126
168
|
totalCostUSD: totalCost,
|
|
169
|
+
// Actual cost from OpenCode Zen (free for supported models)
|
|
170
|
+
opencodeCost: isOpencodeFreeModel ? 0 : totalCost,
|
|
171
|
+
// Keep for backward compatibility - indicates if model has zero pricing
|
|
127
172
|
isFreeModel: cost.input === 0 && cost.output === 0,
|
|
173
|
+
// New flag to indicate if OpenCode Zen provides this model for free
|
|
174
|
+
isOpencodeFreeModel,
|
|
128
175
|
};
|
|
129
176
|
}
|
|
130
|
-
|
|
131
177
|
// Model not found in API, return what we have
|
|
132
178
|
return {
|
|
133
179
|
modelId,
|
|
134
180
|
modelName,
|
|
135
|
-
provider: '
|
|
181
|
+
provider: 'OpenCode Zen',
|
|
182
|
+
originalProvider,
|
|
136
183
|
tokenUsage,
|
|
137
184
|
totalCostUSD: null,
|
|
185
|
+
opencodeCost: 0, // OpenCode Zen is free
|
|
186
|
+
isOpencodeFreeModel: true,
|
|
138
187
|
error: 'Model not found in models.dev API',
|
|
139
188
|
};
|
|
140
189
|
} catch (error) {
|
|
@@ -142,8 +191,12 @@ export const calculateAgentPricing = async (modelId, tokenUsage) => {
|
|
|
142
191
|
return {
|
|
143
192
|
modelId,
|
|
144
193
|
modelName,
|
|
194
|
+
provider: 'OpenCode Zen',
|
|
195
|
+
originalProvider,
|
|
145
196
|
tokenUsage,
|
|
146
197
|
totalCostUSD: null,
|
|
198
|
+
opencodeCost: 0, // OpenCode Zen is free
|
|
199
|
+
isOpencodeFreeModel: true,
|
|
147
200
|
error: error.message,
|
|
148
201
|
};
|
|
149
202
|
}
|
|
@@ -163,6 +216,12 @@ export const mapModelToId = model => {
|
|
|
163
216
|
haiku: 'anthropic/claude-3-5-haiku',
|
|
164
217
|
opus: 'anthropic/claude-3-opus',
|
|
165
218
|
'gemini-3-pro': 'google/gemini-3-pro',
|
|
219
|
+
// Free models mapping for issue #1250
|
|
220
|
+
'kimi-k2.5-free': 'moonshot/kimi-k2.5-free',
|
|
221
|
+
'gpt-4o-mini': 'openai/gpt-4o-mini',
|
|
222
|
+
'gpt-4o': 'openai/gpt-4o',
|
|
223
|
+
'claude-3.5-haiku': 'anthropic/claude-3.5-haiku',
|
|
224
|
+
'claude-3.5-sonnet': 'anthropic/claude-3.5-sonnet',
|
|
166
225
|
};
|
|
167
226
|
|
|
168
227
|
// Return mapped model ID if it's an alias, otherwise return as-is
|
package/src/github.lib.mjs
CHANGED
|
@@ -22,25 +22,50 @@ import { uploadLogWithGhUploadLog } from './log-upload.lib.mjs';
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Build cost estimation string for log comments
|
|
25
|
+
* Issue #1250: Enhanced to show both public pricing estimate and actual provider cost
|
|
26
|
+
*
|
|
25
27
|
* @param {number|null} totalCostUSD - Public pricing estimate
|
|
26
28
|
* @param {number|null} anthropicTotalCostUSD - Cost calculated by Anthropic (Claude-specific)
|
|
27
29
|
* @param {Object|null} pricingInfo - Pricing info from agent tool
|
|
30
|
+
* - opencodeCost: Actual billed cost from OpenCode Zen (for agent tool)
|
|
31
|
+
* - isOpencodeFreeModel: Whether OpenCode Zen provides this model for free
|
|
32
|
+
* - originalProvider: Original provider for pricing reference
|
|
28
33
|
* @returns {string} Formatted cost info string for markdown (empty if no data available)
|
|
29
34
|
*/
|
|
30
35
|
const buildCostInfoString = (totalCostUSD, anthropicTotalCostUSD, pricingInfo) => {
|
|
31
36
|
// Issue #1015: Don't show cost section when all values are unknown (clutters output)
|
|
32
37
|
const hasPublic = totalCostUSD !== null && totalCostUSD !== undefined;
|
|
33
38
|
const hasAnthropic = anthropicTotalCostUSD !== null && anthropicTotalCostUSD !== undefined;
|
|
34
|
-
const hasPricing = pricingInfo && (pricingInfo.modelName || pricingInfo.tokenUsage || pricingInfo.isFreeModel);
|
|
35
|
-
|
|
39
|
+
const hasPricing = pricingInfo && (pricingInfo.modelName || pricingInfo.tokenUsage || pricingInfo.isFreeModel || pricingInfo.isOpencodeFreeModel);
|
|
40
|
+
// Issue #1250: Check for OpenCode Zen actual cost
|
|
41
|
+
const hasOpencodeCost = pricingInfo?.opencodeCost !== null && pricingInfo?.opencodeCost !== undefined;
|
|
42
|
+
if (!hasPublic && !hasAnthropic && !hasPricing && !hasOpencodeCost) return '';
|
|
36
43
|
let costInfo = '\n\nš° **Cost estimation:**';
|
|
37
44
|
if (pricingInfo?.modelName) {
|
|
38
45
|
costInfo += `\n- Model: ${pricingInfo.modelName}`;
|
|
39
46
|
if (pricingInfo.provider) costInfo += `\n- Provider: ${pricingInfo.provider}`;
|
|
40
47
|
}
|
|
48
|
+
// Issue #1250: Show public pricing estimate based on original provider prices
|
|
41
49
|
if (hasPublic) {
|
|
42
|
-
|
|
43
|
-
|
|
50
|
+
// For models with zero pricing from original provider, show as free
|
|
51
|
+
if (pricingInfo?.isFreeModel && totalCostUSD === 0) {
|
|
52
|
+
costInfo += '\n- Public pricing estimate: $0.00 (Free model)';
|
|
53
|
+
} else {
|
|
54
|
+
// Show actual public pricing estimate with original provider reference
|
|
55
|
+
const originalProviderRef = pricingInfo?.originalProvider ? ` (based on ${pricingInfo.originalProvider} prices)` : '';
|
|
56
|
+
costInfo += `\n- Public pricing estimate: $${totalCostUSD.toFixed(6)}${originalProviderRef}`;
|
|
57
|
+
}
|
|
58
|
+
} else if (hasPricing) {
|
|
59
|
+
costInfo += '\n- Public pricing estimate: unknown';
|
|
60
|
+
}
|
|
61
|
+
// Issue #1250: Show actual cost from OpenCode Zen for agent tool
|
|
62
|
+
if (hasOpencodeCost) {
|
|
63
|
+
if (pricingInfo.isOpencodeFreeModel) {
|
|
64
|
+
costInfo += '\n- Calculated by OpenCode Zen: $0.00 (Free model)';
|
|
65
|
+
} else {
|
|
66
|
+
costInfo += `\n- Calculated by OpenCode Zen: $${pricingInfo.opencodeCost.toFixed(6)}`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
44
69
|
if (pricingInfo?.tokenUsage) {
|
|
45
70
|
const u = pricingInfo.tokenUsage;
|
|
46
71
|
let tokenInfo = `\n- Token usage: ${u.inputTokens?.toLocaleString() || 0} input, ${u.outputTokens?.toLocaleString() || 0} output`;
|