@link-assistant/hive-mind 1.46.9 → 1.47.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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @link-assistant/hive-mind
2
2
 
3
+ ## 1.47.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3bbd66e: Improve Context and tokens usage output format: move percentage before unit label, parenthesize cached tokens in Total line, use consistent X / Y (Z%) format for output tokens when limit is known, and show sub-sessions under model heading instead of globally
8
+
9
+ ## 1.47.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 7997308: feat: update free models for --tool agent, set qwen3.6-plus-free as default (#1543)
14
+ - Change default agent model from `minimax-m2.5-free` to `qwen3.6-plus-free` (~1M context window)
15
+ - Add `qwen3.6-plus-free` (Alibaba Qwen, ~1M context) to free models
16
+ - Add `nemotron-3-super-free` (NVIDIA hybrid Mamba-Transformer, ~262K context) to free models
17
+ - Update documentation, tests, and provider priority lists
18
+ - Syncs with upstream agent PR #234
19
+
3
20
  ## 1.46.9
4
21
 
5
22
  ### Patch Changes
package/README.md CHANGED
@@ -445,10 +445,11 @@ Examples:
445
445
  /solve https://github.com/owner/repo/issues/123 --model opus --think max
446
446
 
447
447
  Free Models (with --tool agent):
448
+ /solve https://github.com/owner/repo/issues/123 --tool agent --model qwen3.6-plus-free
449
+ /solve https://github.com/owner/repo/issues/123 --tool agent --model opencode/qwen3.6-plus-free
450
+ /solve https://github.com/owner/repo/issues/123 --tool agent --model nemotron-3-super-free
448
451
  /solve https://github.com/owner/repo/issues/123 --tool agent --model minimax-m2.5-free
449
- /solve https://github.com/owner/repo/issues/123 --tool agent --model opencode/minimax-m2.5-free
450
452
  /solve https://github.com/owner/repo/issues/123 --tool agent --model gpt-5-nano
451
- /solve https://github.com/owner/repo/issues/123 --tool agent --model big-pickle
452
453
 
453
454
  Free Models via Kilo Gateway (with --tool agent):
454
455
  /solve https://github.com/owner/repo/issues/123 --tool agent --model kilo/glm-5-free
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@link-assistant/hive-mind",
3
- "version": "1.46.9",
3
+ "version": "1.47.1",
4
4
  "description": "AI-powered issue solver and hive mind for collaborative problem solving",
5
5
  "main": "src/hive.mjs",
6
6
  "type": "module",
@@ -165,16 +165,15 @@ export const displayBudgetStats = async (usage, tokenUsage, log) => {
165
165
  const sub = subSessions[i];
166
166
  const subPeak = sub.peakContextUsage || 0;
167
167
  // Issue #1539: Only use peak per-request context for context window display.
168
- // Cumulative totals across all requests can exceed the context limit and produce
169
- // impossible percentages (e.g. 250%). When peak is unknown, skip context display.
168
+ // Issue #1547: Percentage before unit label: X / Y (Z%) input tokens
170
169
  const parts = [];
171
170
  if (contextLimit && subPeak > 0) {
172
171
  const pct = ((subPeak / contextLimit) * 100).toFixed(0);
173
- parts.push(`${formatNumber(subPeak)} / ${formatNumber(contextLimit)} input tokens (${pct}%)`);
172
+ parts.push(`${formatNumber(subPeak)} / ${formatNumber(contextLimit)} (${pct}%) input tokens`);
174
173
  }
175
174
  if (outputLimit) {
176
175
  const outPct = ((sub.outputTokens / outputLimit) * 100).toFixed(0);
177
- parts.push(`${formatNumber(sub.outputTokens)} / ${formatNumber(outputLimit)} output tokens (${outPct}%)`);
176
+ parts.push(`${formatNumber(sub.outputTokens)} / ${formatNumber(outputLimit)} (${outPct}%) output tokens`);
178
177
  }
179
178
  if (parts.length > 0) {
180
179
  await log(` ${i + 1}. Context window: ${parts.join(', ')}`);
@@ -182,14 +181,15 @@ export const displayBudgetStats = async (usage, tokenUsage, log) => {
182
181
  }
183
182
  } else if (peakContext > 0) {
184
183
  // Single sub-session with known peak: single-line format
184
+ // Issue #1547: Percentage before unit label
185
185
  const parts = [];
186
186
  if (contextLimit) {
187
187
  const pct = ((peakContext / contextLimit) * 100).toFixed(0);
188
- parts.push(`${formatNumber(peakContext)} / ${formatNumber(contextLimit)} input tokens (${pct}%)`);
188
+ parts.push(`${formatNumber(peakContext)} / ${formatNumber(contextLimit)} (${pct}%) input tokens`);
189
189
  }
190
190
  if (outputLimit) {
191
191
  const outPct = ((usage.outputTokens / outputLimit) * 100).toFixed(0);
192
- parts.push(`${formatNumber(usage.outputTokens)} / ${formatNumber(outputLimit)} output tokens (${outPct}%)`);
192
+ parts.push(`${formatNumber(usage.outputTokens)} / ${formatNumber(outputLimit)} (${outPct}%) output tokens`);
193
193
  }
194
194
  if (parts.length > 0) {
195
195
  await log(` Context window: ${parts.join(', ')}`);
@@ -199,15 +199,20 @@ export const displayBudgetStats = async (usage, tokenUsage, log) => {
199
199
  // Cumulative totals are shown on the Total line below — no duplication needed.
200
200
 
201
201
  // Cumulative totals — single line
202
+ // Issue #1547: Parenthesized cached format and consistent output format
202
203
  const totalInputNonCached = usage.inputTokens + usage.cacheCreationTokens;
203
204
  const cachedTokens = usage.cacheReadTokens;
204
- let totalLine = `${formatNumber(totalInputNonCached)}`;
205
- if (cachedTokens > 0) totalLine += ` + ${formatNumber(cachedTokens)} cached`;
206
- totalLine += ` input tokens, ${formatNumber(usage.outputTokens)} output tokens`;
207
- // Issue #1539: When peakContextUsage is unknown, embed output percentage in Total line
205
+ let totalLine;
206
+ if (cachedTokens > 0) {
207
+ totalLine = `(${formatNumber(totalInputNonCached)} + ${formatNumber(cachedTokens)} cached) input tokens`;
208
+ } else {
209
+ totalLine = `${formatNumber(totalInputNonCached)} input tokens`;
210
+ }
208
211
  if (peakContext === 0 && outputLimit) {
209
212
  const outPct = ((usage.outputTokens / outputLimit) * 100).toFixed(0);
210
- totalLine += ` (${outPct}% of ${formatNumber(outputLimit)} output limit)`;
213
+ totalLine += `, ${formatNumber(usage.outputTokens)} / ${formatNumber(outputLimit)} (${outPct}%) output tokens`;
214
+ } else {
215
+ totalLine += `, ${formatNumber(usage.outputTokens)} output tokens`;
211
216
  }
212
217
  await log(` Total: ${totalLine}`);
213
218
  };
@@ -325,12 +330,12 @@ const formatContextOutputLine = (peakContext, contextLimit, outputTokens, output
325
330
  // context window metrics and produce impossible percentages (e.g. 250%).
326
331
  if (peakContext > 0) {
327
332
  const pct = ((peakContext / contextLimit) * 100).toFixed(0);
328
- parts.push(`${formatTokensCompact(peakContext)} / ${formatTokensCompact(contextLimit)} input tokens (${pct}%)`);
333
+ parts.push(`${formatTokensCompact(peakContext)} / ${formatTokensCompact(contextLimit)} (${pct}%) input tokens`);
329
334
  }
330
335
  }
331
336
  if (outputLimit) {
332
337
  const outPct = ((outputTokens / outputLimit) * 100).toFixed(0);
333
- parts.push(`${formatTokensCompact(outputTokens)} / ${formatTokensCompact(outputLimit)} output tokens (${outPct}%)`);
338
+ parts.push(`${formatTokensCompact(outputTokens)} / ${formatTokensCompact(outputLimit)} (${outPct}%) output tokens`);
334
339
  }
335
340
  if (parts.length === 0) return '';
336
341
  return `\n${prefix}Context window: ${parts.join(', ')}`;
@@ -364,15 +369,6 @@ export const buildBudgetStatsString = tokenUsage => {
364
369
  const subSessions = tokenUsage.subSessions || [];
365
370
  const hasMultipleSubSessions = subSessions.length > 1;
366
371
 
367
- if (isMultiModel && hasMultipleSubSessions) {
368
- // Issue #1508: For multi-model sessions, show global sub-sessions once (not per-model),
369
- // since sub-sessions track compactification boundaries which are session-wide.
370
- // Per-model context/output limits are shown below under each model heading.
371
- const primaryModelId = modelIds[0];
372
- const primaryUsage = tokenUsage.modelUsage[primaryModelId];
373
- stats += formatSubSessionsList(subSessions, primaryUsage.modelInfo?.limit?.context, primaryUsage.modelInfo?.limit?.output);
374
- }
375
-
376
372
  for (const modelId of modelIds) {
377
373
  const usage = tokenUsage.modelUsage[modelId];
378
374
  const modelName = usage.modelName || modelId;
@@ -383,8 +379,9 @@ export const buildBudgetStatsString = tokenUsage => {
383
379
 
384
380
  const peakContext = usage.peakContextUsage || 0;
385
381
 
386
- if (!isMultiModel && hasMultipleSubSessions) {
387
- // Single-model + multiple sub-sessions: show numbered sub-sessions under that model
382
+ if (hasMultipleSubSessions && (!isMultiModel || modelId === modelIds[0])) {
383
+ // Issue #1547: Show sub-sessions under the primary model heading (not globally).
384
+ // For single-model sessions, show under that model. For multi-model, under the first model.
388
385
  stats += formatSubSessionsList(subSessions, contextLimit, outputLimit);
389
386
  } else if (peakContext > 0) {
390
387
  // Issue #1526: Single line format for context window + output tokens
@@ -394,18 +391,22 @@ export const buildBudgetStatsString = tokenUsage => {
394
391
  // Cumulative totals are shown on the Total line below — no duplication needed.
395
392
 
396
393
  // Cumulative totals per model: input tokens + cached shown separately
397
- // Issue #1526: Shorter format single "Total:" line
394
+ // Issue #1547: Parenthesized cached format: (X + Y cached) input tokens
398
395
  const totalInputNonCached = usage.inputTokens + usage.cacheCreationTokens;
399
396
  const cachedTokens = usage.cacheReadTokens;
400
- let totalLine = `${formatTokensCompact(totalInputNonCached)}`;
401
- if (cachedTokens > 0) totalLine += ` + ${formatTokensCompact(cachedTokens)} cached`;
402
- totalLine += ` input tokens, ${formatTokensCompact(usage.outputTokens)} output tokens`;
397
+ let totalLine;
398
+ if (cachedTokens > 0) {
399
+ totalLine = `(${formatTokensCompact(totalInputNonCached)} + ${formatTokensCompact(cachedTokens)} cached) input tokens`;
400
+ } else {
401
+ totalLine = `${formatTokensCompact(totalInputNonCached)} input tokens`;
402
+ }
403
403
 
404
- // Issue #1539: When peakContextUsage is unknown (no per-request data), embed
405
- // output token percentage in the Total line so no data is lost.
404
+ // Issue #1547: Consistent output format use X / Y (Z%) output tokens when limit known
406
405
  if (peakContext === 0 && outputLimit) {
407
406
  const outPct = ((usage.outputTokens / outputLimit) * 100).toFixed(0);
408
- totalLine += ` (${outPct}% of ${formatTokensCompact(outputLimit)} output limit)`;
407
+ totalLine += `, ${formatTokensCompact(usage.outputTokens)} / ${formatTokensCompact(outputLimit)} (${outPct}%) output tokens`;
408
+ } else {
409
+ totalLine += `, ${formatTokensCompact(usage.outputTokens)} output tokens`;
409
410
  }
410
411
 
411
412
  // Issue #1508: Show per-model cost when available
@@ -47,6 +47,7 @@ export const claudeModels = {
47
47
 
48
48
  // Agent models (OpenCode API and Kilo Gateway via agent CLI)
49
49
  // Issue #1300: Updated free models to match agent PR #191
50
+ // Issue #1543: Added qwen3.6-plus-free (new default) and nemotron-3-super-free per agent PR #234
50
51
  export const agentModels = {
51
52
  // OpenCode Zen free models (current)
52
53
  grok: 'opencode/grok-code',
@@ -54,7 +55,9 @@ export const agentModels = {
54
55
  'grok-code-fast-1': 'opencode/grok-code',
55
56
  'big-pickle': 'opencode/big-pickle',
56
57
  'gpt-5-nano': 'opencode/gpt-5-nano',
57
- 'minimax-m2.5-free': 'opencode/minimax-m2.5-free', // New: upgraded from M2.1 (Issue #1391: now default)
58
+ 'minimax-m2.5-free': 'opencode/minimax-m2.5-free', // Upgraded from M2.1 (Issue #1391)
59
+ 'qwen3.6-plus-free': 'opencode/qwen3.6-plus-free', // New: ~1M context, default (Issue #1543)
60
+ 'nemotron-3-super-free': 'opencode/nemotron-3-super-free', // New: NVIDIA hybrid Mamba-Transformer (Issue #1543)
58
61
  // Kilo Gateway free models (Issue #1282, updated in #1300)
59
62
  // Short names for Kilo-exclusive models (Issue #1300)
60
63
  'glm-5-free': 'kilo/glm-5-free', // Kilo-exclusive
@@ -112,7 +115,7 @@ export const codexModels = {
112
115
  // Default model for each tool (Issue #1473: centralized to avoid scattered hardcoded defaults)
113
116
  export const defaultModels = {
114
117
  claude: 'sonnet',
115
- agent: 'minimax-m2.5-free',
118
+ agent: 'qwen3.6-plus-free', // Issue #1543: changed from minimax-m2.5-free per agent PR #234
116
119
  opencode: 'grok-code-fast-1',
117
120
  codex: 'gpt-5',
118
121
  };
@@ -140,6 +143,8 @@ export const freeToBaseModelMap = {
140
143
  'glm-4.7-free': 'glm-4.7',
141
144
  'minimax-m2.1-free': 'minimax-m2.1',
142
145
  'minimax-m2.5-free': 'minimax-m2.5',
146
+ 'qwen3.6-plus-free': 'qwen3.6-plus', // Issue #1543
147
+ 'nemotron-3-super-free': 'nemotron-3-super', // Issue #1543
143
148
  'glm-5-free': 'glm-5',
144
149
  'glm-4.5-air-free': 'glm-4.5-air',
145
150
  'deepseek-r1-free': 'deepseek-r1',
@@ -187,6 +192,8 @@ export const AGENT_MODELS = {
187
192
  'opencode/big-pickle': 'opencode/big-pickle',
188
193
  'opencode/gpt-5-nano': 'opencode/gpt-5-nano',
189
194
  'opencode/minimax-m2.5-free': 'opencode/minimax-m2.5-free',
195
+ 'opencode/qwen3.6-plus-free': 'opencode/qwen3.6-plus-free', // Issue #1543
196
+ 'opencode/nemotron-3-super-free': 'opencode/nemotron-3-super-free', // Issue #1543
190
197
  'opencode/kimi-k2.5-free': 'opencode/kimi-k2.5-free', // Deprecated
191
198
  'opencode/glm-4.7-free': 'opencode/glm-4.7-free', // Deprecated
192
199
  'opencode/minimax-m2.1-free': 'opencode/minimax-m2.1-free', // Deprecated
@@ -297,7 +304,7 @@ export const primaryModelNames = {
297
304
  claude: ['opus', 'sonnet', 'haiku', 'opusplan'],
298
305
  opencode: ['grok', 'gpt4o'],
299
306
  codex: ['gpt5', 'gpt5-codex', 'o3'],
300
- agent: ['minimax-m2.5-free', 'big-pickle', 'gpt-5-nano', 'glm-5-free', 'deepseek-r1-free'],
307
+ agent: ['qwen3.6-plus-free', 'nemotron-3-super-free', 'minimax-m2.5-free', 'big-pickle', 'gpt-5-nano', 'glm-5-free', 'deepseek-r1-free'],
301
308
  };
302
309
 
303
310
  /**