mini-coder 0.0.11 → 0.0.12

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.
Files changed (2) hide show
  1. package/dist/mc.js +180 -22
  2. package/package.json +1 -1
package/dist/mc.js CHANGED
@@ -931,6 +931,8 @@ function fmtTokens(n) {
931
931
  function renderStatusBar(opts) {
932
932
  const cols = process.stdout.columns ?? 80;
933
933
  const left = [c5.cyan(opts.model)];
934
+ if (opts.thinkingEffort)
935
+ left.push(c5.dim(`\u2726 ${opts.thinkingEffort}`));
934
936
  if (opts.provider && opts.provider !== "zen")
935
937
  left.push(c5.dim(opts.provider));
936
938
  left.push(c5.dim(opts.sessionId.slice(0, 8)));
@@ -976,7 +978,7 @@ function renderError(err, context = "render") {
976
978
 
977
979
  // src/cli/output.ts
978
980
  var HOME2 = homedir3();
979
- var PACKAGE_VERSION = "0.0.11";
981
+ var PACKAGE_VERSION = "0.0.12";
980
982
  function tildePath(p) {
981
983
  return p.startsWith(HOME2) ? `~${p.slice(HOME2.length)}` : p;
982
984
  }
@@ -1347,6 +1349,87 @@ var CONTEXT_WINDOW_TABLE = [
1347
1349
  [/^glm-/, 128000],
1348
1350
  [/^qwen3-/, 131000]
1349
1351
  ];
1352
+ var REASONING_MODELS = [
1353
+ /^claude-3-5-sonnet/,
1354
+ /^claude-3-7/,
1355
+ /^claude-sonnet-4/,
1356
+ /^claude-opus-4/,
1357
+ /^o1/,
1358
+ /^o3/,
1359
+ /^o4/,
1360
+ /^gpt-5/,
1361
+ /^gemini-2\.5/,
1362
+ /^gemini-3/
1363
+ ];
1364
+ function supportsThinking(modelString) {
1365
+ const { modelId } = parseModelString(modelString);
1366
+ return REASONING_MODELS.some((p) => p.test(modelId));
1367
+ }
1368
+ var ANTHROPIC_BUDGET = {
1369
+ low: 4096,
1370
+ medium: 8192,
1371
+ high: 16384,
1372
+ xhigh: 32768
1373
+ };
1374
+ function clampEffort(effort, max) {
1375
+ const ORDER = ["low", "medium", "high", "xhigh"];
1376
+ const i = ORDER.indexOf(effort);
1377
+ const m = ORDER.indexOf(max);
1378
+ return ORDER[Math.min(i, m)];
1379
+ }
1380
+ function getThinkingProviderOptions(modelString, effort) {
1381
+ if (!supportsThinking(modelString))
1382
+ return null;
1383
+ const { provider, modelId } = parseModelString(modelString);
1384
+ if (provider === "anthropic" || provider === "zen" && modelId.startsWith("claude-")) {
1385
+ const isAdaptive = /^claude-3-7/.test(modelId) || /^claude-sonnet-4/.test(modelId) || /^claude-opus-4/.test(modelId);
1386
+ if (isAdaptive) {
1387
+ const isOpus = /^claude-opus-4/.test(modelId);
1388
+ const mapped = effort === "xhigh" ? isOpus ? "max" : "high" : effort;
1389
+ return { anthropic: { thinking: { type: "adaptive" }, effort: mapped } };
1390
+ }
1391
+ const budget = ANTHROPIC_BUDGET[effort];
1392
+ return {
1393
+ anthropic: {
1394
+ thinking: { type: "enabled", budgetTokens: budget },
1395
+ betas: ["interleaved-thinking-2025-05-14"]
1396
+ }
1397
+ };
1398
+ }
1399
+ if (provider === "openai" || provider === "zen" && (modelId.startsWith("o") || modelId.startsWith("gpt-5"))) {
1400
+ const supportsXhigh = /^gpt-5\.[2-9]/.test(modelId) || /^o4/.test(modelId);
1401
+ const clamped = supportsXhigh ? effort : clampEffort(effort, "high");
1402
+ return { openai: { reasoningEffort: clamped } };
1403
+ }
1404
+ if (provider === "google" || provider === "zen" && modelId.startsWith("gemini-")) {
1405
+ if (/^gemini-3/.test(modelId)) {
1406
+ const level = clampEffort(effort, "high");
1407
+ return {
1408
+ google: {
1409
+ thinkingConfig: {
1410
+ includeThoughts: true,
1411
+ thinkingLevel: level
1412
+ }
1413
+ }
1414
+ };
1415
+ }
1416
+ const GEMINI_BUDGET = {
1417
+ low: 4096,
1418
+ medium: 8192,
1419
+ high: 16384,
1420
+ xhigh: 24575
1421
+ };
1422
+ return {
1423
+ google: {
1424
+ thinkingConfig: {
1425
+ includeThoughts: true,
1426
+ thinkingBudget: GEMINI_BUDGET[effort]
1427
+ }
1428
+ }
1429
+ };
1430
+ }
1431
+ return null;
1432
+ }
1350
1433
  function getContextWindow(modelString) {
1351
1434
  const { modelId } = parseModelString(modelString);
1352
1435
  for (const [pattern, tokens] of CONTEXT_WINDOW_TABLE) {
@@ -1698,6 +1781,19 @@ function getPreferredModel() {
1698
1781
  function setPreferredModel(model) {
1699
1782
  setSetting("preferred_model", model);
1700
1783
  }
1784
+ function getPreferredThinkingEffort() {
1785
+ const v = getSetting("preferred_thinking_effort");
1786
+ if (v === "low" || v === "medium" || v === "high" || v === "xhigh")
1787
+ return v;
1788
+ return null;
1789
+ }
1790
+ function setPreferredThinkingEffort(effort) {
1791
+ if (effort === null) {
1792
+ getDb().run("DELETE FROM settings WHERE key = 'preferred_thinking_effort'");
1793
+ } else {
1794
+ setSetting("preferred_thinking_effort", effort);
1795
+ }
1796
+ }
1701
1797
  // src/session/db/mcp-repo.ts
1702
1798
  function listMcpServers() {
1703
1799
  return getDb().query("SELECT name, transport, url, command, args, env FROM mcp_servers ORDER BY name").all();
@@ -1786,7 +1882,15 @@ function isOpenAIGPT(modelString) {
1786
1882
  return (provider === "openai" || provider === "zen") && modelId.startsWith("gpt-");
1787
1883
  }
1788
1884
  async function* runTurn(options) {
1789
- const { model, modelString, messages, tools, systemPrompt, signal } = options;
1885
+ const {
1886
+ model,
1887
+ modelString,
1888
+ messages,
1889
+ tools,
1890
+ systemPrompt,
1891
+ signal,
1892
+ thinkingEffort
1893
+ } = options;
1790
1894
  let stepCount = 0;
1791
1895
  let warningClaimed = false;
1792
1896
  function claimWarning() {
@@ -1805,6 +1909,18 @@ async function* runTurn(options) {
1805
1909
  try {
1806
1910
  const useInstructions = systemPrompt !== undefined && isOpenAIGPT(modelString);
1807
1911
  logApiEvent("turn start", { modelString, messageCount: messages.length });
1912
+ const thinkingOpts = thinkingEffort ? getThinkingProviderOptions(modelString, thinkingEffort) : null;
1913
+ const mergedProviderOptions = {
1914
+ ...useInstructions ? { openai: { instructions: systemPrompt, store: false } } : {},
1915
+ ...thinkingOpts ?? {},
1916
+ ...useInstructions && thinkingOpts?.openai ? {
1917
+ openai: {
1918
+ instructions: systemPrompt,
1919
+ store: false,
1920
+ ...thinkingOpts.openai
1921
+ }
1922
+ } : {}
1923
+ };
1808
1924
  const streamOpts = {
1809
1925
  model,
1810
1926
  messages,
@@ -1829,14 +1945,7 @@ async function* runTurn(options) {
1829
1945
  return;
1830
1946
  },
1831
1947
  ...systemPrompt ? { system: systemPrompt } : {},
1832
- ...useInstructions ? {
1833
- providerOptions: {
1834
- openai: {
1835
- instructions: systemPrompt,
1836
- store: false
1837
- }
1838
- }
1839
- } : {},
1948
+ ...Object.keys(mergedProviderOptions).length > 0 ? { providerOptions: mergedProviderOptions } : {},
1840
1949
  ...signal ? { abortSignal: signal } : {}
1841
1950
  };
1842
1951
  const result = streamText(streamOpts);
@@ -2885,7 +2994,7 @@ function buildReadOnlyToolSet(opts) {
2885
2994
  }
2886
2995
 
2887
2996
  // src/agent/subagent-runner.ts
2888
- function createSubagentRunner(cwd, reporter, getCurrentModel) {
2997
+ function createSubagentRunner(cwd, reporter, getCurrentModel, getThinkingEffort) {
2889
2998
  let nextLaneId = 1;
2890
2999
  const activeLanes = new Set;
2891
3000
  const runSubagent = async (prompt, depth = 0, agentName, modelOverride, parentLabel) => {
@@ -2913,12 +3022,14 @@ function createSubagentRunner(cwd, reporter, getCurrentModel) {
2913
3022
  let result = "";
2914
3023
  let inputTokens = 0;
2915
3024
  let outputTokens = 0;
3025
+ const effort = getThinkingEffort();
2916
3026
  const events = runTurn({
2917
3027
  model: subLlm,
2918
3028
  modelString: model,
2919
3029
  messages: subMessages,
2920
3030
  tools: subTools,
2921
- systemPrompt
3031
+ systemPrompt,
3032
+ ...effort ? { thinkingEffort: effort } : {}
2922
3033
  });
2923
3034
  for await (const event of events) {
2924
3035
  reporter.stopSpinner();
@@ -3375,20 +3486,50 @@ async function expandTemplate(template, args, cwd) {
3375
3486
 
3376
3487
  // src/cli/commands.ts
3377
3488
  async function handleModel(ctx, args) {
3378
- if (args) {
3379
- let modelId = args;
3380
- if (!args.includes("/")) {
3489
+ const parts = args.trim().split(/\s+/).filter(Boolean);
3490
+ if (parts.length > 0) {
3491
+ if (parts[0] === "effort") {
3492
+ const effortArg2 = parts[1] ?? "";
3493
+ if (effortArg2 === "off") {
3494
+ ctx.setThinkingEffort(null);
3495
+ writeln(`${PREFIX.success} thinking effort disabled`);
3496
+ } else if (["low", "medium", "high", "xhigh"].includes(effortArg2)) {
3497
+ ctx.setThinkingEffort(effortArg2);
3498
+ writeln(`${PREFIX.success} thinking effort \u2192 ${c10.cyan(effortArg2)}`);
3499
+ } else {
3500
+ writeln(`${PREFIX.error} usage: /model effort <low|medium|high|xhigh|off>`);
3501
+ }
3502
+ return;
3503
+ }
3504
+ const idArg = parts[0] ?? "";
3505
+ let modelId = idArg;
3506
+ if (!idArg.includes("/")) {
3381
3507
  const models2 = await fetchAvailableModels();
3382
- const match = models2.find((m) => m.id.split("/").slice(1).join("/") === args || m.id === args);
3508
+ const match = models2.find((m) => m.id.split("/").slice(1).join("/") === idArg || m.id === idArg);
3383
3509
  if (match) {
3384
3510
  modelId = match.id;
3385
3511
  } else {
3386
- writeln(`${PREFIX.error} unknown model ${c10.cyan(args)} ${c10.dim("\u2014 run /models for the full list")}`);
3512
+ writeln(`${PREFIX.error} unknown model ${c10.cyan(idArg)} ${c10.dim("\u2014 run /models for the full list")}`);
3387
3513
  return;
3388
3514
  }
3389
3515
  }
3390
3516
  ctx.setModel(modelId);
3391
- writeln(`${PREFIX.success} model \u2192 ${c10.cyan(modelId)}`);
3517
+ const effortArg = parts[1];
3518
+ if (effortArg) {
3519
+ if (effortArg === "off") {
3520
+ ctx.setThinkingEffort(null);
3521
+ writeln(`${PREFIX.success} model \u2192 ${c10.cyan(modelId)} ${c10.dim("(thinking disabled)")}`);
3522
+ } else if (["low", "medium", "high", "xhigh"].includes(effortArg)) {
3523
+ ctx.setThinkingEffort(effortArg);
3524
+ writeln(`${PREFIX.success} model \u2192 ${c10.cyan(modelId)} ${c10.dim(`(\u2726 ${effortArg})`)}`);
3525
+ } else {
3526
+ writeln(`${PREFIX.success} model \u2192 ${c10.cyan(modelId)}`);
3527
+ writeln(`${PREFIX.error} unknown effort level ${c10.cyan(effortArg)} (use low, medium, high, xhigh, off)`);
3528
+ }
3529
+ } else {
3530
+ const e = ctx.thinkingEffort ? c10.dim(` (\u2726 ${ctx.thinkingEffort})`) : "";
3531
+ writeln(`${PREFIX.success} model \u2192 ${c10.cyan(modelId)}${e}`);
3532
+ }
3392
3533
  return;
3393
3534
  }
3394
3535
  writeln(`${c10.dim(" fetching models\u2026")}`);
@@ -3415,13 +3556,15 @@ async function handleModel(ctx, args) {
3415
3556
  const isCurrent = ctx.currentModel === m.id;
3416
3557
  const freeTag = m.free ? c10.green(" free") : "";
3417
3558
  const ctxTag = m.context ? c10.dim(` ${Math.round(m.context / 1000)}k`) : "";
3559
+ const effortTag = isCurrent && ctx.thinkingEffort ? c10.dim(` \u2726 ${ctx.thinkingEffort}`) : "";
3418
3560
  const cur = isCurrent ? c10.cyan(" \u25C0") : "";
3419
- writeln(` ${c10.dim("\xB7")} ${m.displayName}${freeTag}${ctxTag}${cur}`);
3561
+ writeln(` ${c10.dim("\xB7")} ${m.displayName}${freeTag}${ctxTag}${cur}${effortTag}`);
3420
3562
  writeln(` ${c10.dim(m.id)}`);
3421
3563
  }
3422
3564
  }
3423
3565
  writeln();
3424
3566
  writeln(c10.dim(" /model <id> to switch \xB7 e.g. /model zen/claude-sonnet-4-6"));
3567
+ writeln(c10.dim(" /model effort <low|medium|high|xhigh|off> to set thinking effort"));
3425
3568
  }
3426
3569
  function handlePlan(ctx) {
3427
3570
  ctx.setPlanMode(!ctx.planMode);
@@ -4288,6 +4431,7 @@ class SessionRunner {
4288
4431
  tools;
4289
4432
  mcpTools;
4290
4433
  currentModel;
4434
+ currentThinkingEffort;
4291
4435
  session;
4292
4436
  coreHistory;
4293
4437
  turnIndex = 1;
@@ -4303,6 +4447,7 @@ class SessionRunner {
4303
4447
  this.tools = opts.tools;
4304
4448
  this.mcpTools = opts.mcpTools;
4305
4449
  this.currentModel = opts.initialModel;
4450
+ this.currentThinkingEffort = opts.initialThinkingEffort;
4306
4451
  this.initSession(opts.sessionId);
4307
4452
  }
4308
4453
  initSession(sessionId) {
@@ -4385,7 +4530,8 @@ class SessionRunner {
4385
4530
  messages: this.coreHistory,
4386
4531
  tools: this.planMode ? [...buildReadOnlyToolSet({ cwd: this.cwd }), ...this.mcpTools] : this.tools,
4387
4532
  systemPrompt,
4388
- signal: abortController.signal
4533
+ signal: abortController.signal,
4534
+ ...this.currentThinkingEffort ? { thinkingEffort: this.currentThinkingEffort } : {}
4389
4535
  });
4390
4536
  const { inputTokens, outputTokens, contextTokens, newMessages } = await this.reporter.renderTurn(events);
4391
4537
  if (newMessages.length > 0) {
@@ -4431,7 +4577,8 @@ class SessionRunner {
4431
4577
  async function runAgent(opts) {
4432
4578
  const cwd = opts.cwd;
4433
4579
  let currentModel = opts.model;
4434
- const runSubagent = createSubagentRunner(cwd, opts.reporter, () => currentModel);
4580
+ let currentThinkingEffort = opts.initialThinkingEffort;
4581
+ const runSubagent = createSubagentRunner(cwd, opts.reporter, () => currentModel, () => currentThinkingEffort);
4435
4582
  const agents = loadAgents(cwd);
4436
4583
  const tools = buildToolSet({
4437
4584
  cwd,
@@ -4472,6 +4619,7 @@ async function runAgent(opts) {
4472
4619
  tools,
4473
4620
  mcpTools,
4474
4621
  initialModel: currentModel,
4622
+ initialThinkingEffort: opts.initialThinkingEffort,
4475
4623
  sessionId: opts.sessionId
4476
4624
  });
4477
4625
  const cmdCtx = {
@@ -4484,6 +4632,14 @@ async function runAgent(opts) {
4484
4632
  setPreferredModel(m);
4485
4633
  currentModel = m;
4486
4634
  },
4635
+ get thinkingEffort() {
4636
+ return runner.currentThinkingEffort;
4637
+ },
4638
+ setThinkingEffort: (e) => {
4639
+ runner.currentThinkingEffort = e;
4640
+ setPreferredThinkingEffort(e);
4641
+ currentThinkingEffort = e;
4642
+ },
4487
4643
  get planMode() {
4488
4644
  return runner.planMode;
4489
4645
  },
@@ -4527,7 +4683,8 @@ async function runAgent(opts) {
4527
4683
  outputTokens: runner.totalOut,
4528
4684
  contextTokens: runner.lastContextTokens,
4529
4685
  contextWindow: getContextWindow(runner.currentModel) ?? 0,
4530
- ralphMode: runner.ralphMode
4686
+ ralphMode: runner.ralphMode,
4687
+ thinkingEffort: runner.currentThinkingEffort
4531
4688
  });
4532
4689
  }
4533
4690
  if (opts.initialPrompt) {
@@ -4703,6 +4860,7 @@ async function main() {
4703
4860
  const agentOpts = {
4704
4861
  model,
4705
4862
  cwd: args.cwd,
4863
+ initialThinkingEffort: getPreferredThinkingEffort(),
4706
4864
  reporter: new CliReporter
4707
4865
  };
4708
4866
  if (sessionId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mini-coder",
3
- "version": "0.0.11",
3
+ "version": "0.0.12",
4
4
  "description": "A small, fast CLI coding agent",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",