mini-coder 0.0.16 → 0.0.17

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 +287 -36
  2. package/package.json +1 -1
package/dist/mc.js CHANGED
@@ -295,6 +295,8 @@ function renderStatusBar(opts) {
295
295
  const left = [c3.cyan(opts.model)];
296
296
  if (opts.thinkingEffort)
297
297
  left.push(c3.dim(`\u2726 ${opts.thinkingEffort}`));
298
+ if (opts.showReasoning)
299
+ left.push(c3.dim("\uD83E\uDD14"));
298
300
  if (opts.provider && opts.provider !== "zen")
299
301
  left.push(c3.dim(opts.provider));
300
302
  left.push(c3.dim(opts.sessionId.slice(0, 8)));
@@ -898,17 +900,20 @@ function renderToolResult(toolName, result, isError, toolCallId) {
898
900
  }
899
901
 
900
902
  // src/cli/stream-render.ts
901
- async function renderTurn(events, spinner) {
903
+ async function renderTurn(events, spinner, opts) {
904
+ const showReasoning = opts?.showReasoning ?? true;
902
905
  let inText = false;
903
906
  let inReasoning = false;
904
907
  let rawBuffer = "";
905
908
  let accumulatedText = "";
909
+ let accumulatedReasoning = "";
906
910
  let inFence = false;
907
911
  let inputTokens = 0;
908
912
  let outputTokens = 0;
909
913
  let contextTokens = 0;
910
914
  let newMessages = [];
911
915
  function renderAndWrite(raw, endWithNewline) {
916
+ spinner.stop();
912
917
  const rendered = renderLine(raw, inFence);
913
918
  inFence = rendered.inFence;
914
919
  const finalOutput = inReasoning ? c7.dim(rendered.output) : rendered.output;
@@ -960,13 +965,15 @@ async function renderTurn(events, spinner) {
960
965
  break;
961
966
  }
962
967
  case "reasoning-delta": {
968
+ accumulatedReasoning += event.delta;
969
+ if (!showReasoning) {
970
+ break;
971
+ }
963
972
  if (!inReasoning) {
964
973
  if (inText) {
965
974
  flushAnyText();
966
975
  }
967
976
  spinner.stop();
968
- write(`${c7.dim("Thinking...")}
969
- `);
970
977
  inReasoning = true;
971
978
  }
972
979
  rawBuffer += event.delta;
@@ -1014,12 +1021,18 @@ async function renderTurn(events, spinner) {
1014
1021
  }
1015
1022
  }
1016
1023
  }
1017
- return { inputTokens, outputTokens, contextTokens, newMessages };
1024
+ return {
1025
+ inputTokens,
1026
+ outputTokens,
1027
+ contextTokens,
1028
+ newMessages,
1029
+ reasoningText: accumulatedReasoning
1030
+ };
1018
1031
  }
1019
1032
 
1020
1033
  // src/cli/output.ts
1021
1034
  var HOME2 = homedir3();
1022
- var PACKAGE_VERSION = "0.0.16";
1035
+ var PACKAGE_VERSION = "0.0.17";
1023
1036
  function tildePath(p) {
1024
1037
  return p.startsWith(HOME2) ? `~${p.slice(HOME2.length)}` : p;
1025
1038
  }
@@ -1473,6 +1486,8 @@ var GOOGLE_BASE = "https://generativelanguage.googleapis.com/v1beta";
1473
1486
  var MODELS_DEV_URL = "https://models.dev/api.json";
1474
1487
  var MODELS_DEV_SYNC_KEY = "last_models_dev_sync_at";
1475
1488
  var PROVIDER_SYNC_KEY_PREFIX = "last_provider_sync_at:";
1489
+ var CACHE_VERSION_KEY = "model_info_cache_version";
1490
+ var CACHE_VERSION = 2;
1476
1491
  var MODEL_INFO_TTL_MS = 7 * 24 * 60 * 60 * 1000;
1477
1492
  var runtimeCache = emptyRuntimeCache();
1478
1493
  var loaded = false;
@@ -1719,6 +1734,8 @@ function getProviderSyncKey(provider) {
1719
1734
  }
1720
1735
  function isModelInfoStale(now = Date.now()) {
1721
1736
  ensureLoaded();
1737
+ if (parseStateInt(CACHE_VERSION_KEY) !== CACHE_VERSION)
1738
+ return true;
1722
1739
  if (isStaleTimestamp(parseStateInt(MODELS_DEV_SYNC_KEY), now))
1723
1740
  return true;
1724
1741
  for (const provider of getProvidersRequiredForFreshness()) {
@@ -1757,8 +1774,7 @@ async function fetchZenModels() {
1757
1774
  const key = process.env.OPENCODE_API_KEY;
1758
1775
  if (!key)
1759
1776
  return null;
1760
- const payload = await fetchJson(`${ZEN_BASE}/models`, { headers: { Authorization: `Bearer ${key}` } }, 8000);
1761
- return processModelsList(payload, "data", "id", (item, modelId) => {
1777
+ return fetchPaginatedModelsList(`${ZEN_BASE}/models`, { headers: { Authorization: `Bearer ${key}` } }, 8000, "data", "id", (item, modelId) => {
1762
1778
  const contextWindow = typeof item.context_window === "number" && Number.isFinite(item.context_window) ? Math.max(0, Math.trunc(item.context_window)) : null;
1763
1779
  return {
1764
1780
  providerModelId: modelId,
@@ -1784,12 +1800,39 @@ function processModelsList(payload, arrayKey, idKey, mapper) {
1784
1800
  }
1785
1801
  return out;
1786
1802
  }
1803
+ async function fetchPaginatedModelsList(url, init, timeoutMs, arrayKey, idKey, mapper) {
1804
+ const out = [];
1805
+ const seen = new Set;
1806
+ const baseUrl = new URL(url);
1807
+ let nextAfter = null;
1808
+ for (let page = 0;page < 10; page += 1) {
1809
+ const currentUrl = new URL(baseUrl);
1810
+ if (nextAfter !== null)
1811
+ currentUrl.searchParams.set("after", nextAfter);
1812
+ const payload = await fetchJson(currentUrl.toString(), init, timeoutMs);
1813
+ const rows = processModelsList(payload, arrayKey, idKey, mapper);
1814
+ if (rows === null) {
1815
+ return null;
1816
+ }
1817
+ for (const row of rows) {
1818
+ if (seen.has(row.providerModelId))
1819
+ continue;
1820
+ seen.add(row.providerModelId);
1821
+ out.push(row);
1822
+ }
1823
+ if (!isRecord(payload))
1824
+ break;
1825
+ if (payload.has_more !== true || typeof payload.last_id !== "string")
1826
+ break;
1827
+ nextAfter = payload.last_id;
1828
+ }
1829
+ return out;
1830
+ }
1787
1831
  async function fetchOpenAIModels() {
1788
1832
  const key = process.env.OPENAI_API_KEY;
1789
1833
  if (!key)
1790
1834
  return null;
1791
- const payload = await fetchJson(`${OPENAI_BASE}/v1/models`, { headers: { Authorization: `Bearer ${key}` } }, 6000);
1792
- return processModelsList(payload, "data", "id", (item, modelId) => ({
1835
+ return fetchPaginatedModelsList(`${OPENAI_BASE}/v1/models`, { headers: { Authorization: `Bearer ${key}` } }, 6000, "data", "id", (item, modelId) => ({
1793
1836
  providerModelId: modelId,
1794
1837
  displayName: item.id,
1795
1838
  contextWindow: null,
@@ -1900,6 +1943,7 @@ async function refreshModelInfoInternal() {
1900
1943
  replaceProviderModels(result.provider, rows);
1901
1944
  setModelInfoState(getProviderSyncKey(result.provider), String(now));
1902
1945
  }
1946
+ setModelInfoState(CACHE_VERSION_KEY, String(CACHE_VERSION));
1903
1947
  loadCacheFromDb();
1904
1948
  }
1905
1949
  function refreshModelInfoInBackground(opts) {
@@ -2157,9 +2201,19 @@ function clampEffort(effort, max) {
2157
2201
  const m = ORDER.indexOf(max);
2158
2202
  return ORDER[Math.min(i, m)];
2159
2203
  }
2160
- function getThinkingProviderOptions(modelString, effort) {
2204
+ var GEMINI_TOOL_CALL_AFFECTED_MODELS = /^gemini-(2\.5|3)/;
2205
+ function shouldDisableGeminiThinkingForTools(modelString) {
2206
+ const { provider, modelId } = parseModelString(modelString);
2207
+ if (provider !== "google" && provider !== "zen")
2208
+ return false;
2209
+ return GEMINI_TOOL_CALL_AFFECTED_MODELS.test(modelId);
2210
+ }
2211
+ function getThinkingProviderOptions(modelString, effort, hasTools = false) {
2161
2212
  if (!supportsThinking2(modelString))
2162
2213
  return null;
2214
+ if (hasTools && shouldDisableGeminiThinkingForTools(modelString)) {
2215
+ return null;
2216
+ }
2163
2217
  const { provider, modelId } = parseModelString(modelString);
2164
2218
  if (provider === "anthropic" || provider === "zen" && modelId.startsWith("claude-")) {
2165
2219
  const isAdaptive = /^claude-3-7/.test(modelId) || /^claude-sonnet-4/.test(modelId) || /^claude-opus-4/.test(modelId);
@@ -2179,7 +2233,7 @@ function getThinkingProviderOptions(modelString, effort) {
2179
2233
  if (provider === "openai" || provider === "zen" && (modelId.startsWith("o") || modelId.startsWith("gpt-5"))) {
2180
2234
  const supportsXhigh = /^gpt-5\.[2-9]/.test(modelId) || /^o4/.test(modelId);
2181
2235
  const clamped = supportsXhigh ? effort : clampEffort(effort, "high");
2182
- return { openai: { reasoningEffort: clamped } };
2236
+ return { openai: { reasoningEffort: clamped, reasoningSummary: "auto" } };
2183
2237
  }
2184
2238
  if (provider === "google" || provider === "zen" && modelId.startsWith("gemini-")) {
2185
2239
  if (/^gemini-3/.test(modelId)) {
@@ -2446,6 +2500,15 @@ function setPreferredThinkingEffort(effort) {
2446
2500
  setSetting("preferred_thinking_effort", effort);
2447
2501
  }
2448
2502
  }
2503
+ function getPreferredShowReasoning() {
2504
+ const v = getSetting("preferred_show_reasoning");
2505
+ if (v === null)
2506
+ return true;
2507
+ return v !== "false";
2508
+ }
2509
+ function setPreferredShowReasoning(show) {
2510
+ setSetting("preferred_show_reasoning", show ? "true" : "false");
2511
+ }
2449
2512
  function getPreferredActiveAgent() {
2450
2513
  return getSetting("preferred_active_agent");
2451
2514
  }
@@ -2685,6 +2748,25 @@ async function handleModel(ctx, args) {
2685
2748
  writeln(c10.dim(" /model <id> to switch \xB7 e.g. /model zen/claude-sonnet-4-6"));
2686
2749
  writeln(c10.dim(" /model effort <low|medium|high|xhigh|off> to set thinking effort"));
2687
2750
  }
2751
+ function handleReasoning(ctx, args) {
2752
+ const mode = args.trim().toLowerCase();
2753
+ if (!mode) {
2754
+ ctx.setShowReasoning(!ctx.showReasoning);
2755
+ writeln(`${PREFIX.success} reasoning display ${ctx.showReasoning ? c10.green("on") : c10.dim("off")}`);
2756
+ return;
2757
+ }
2758
+ if (mode === "on") {
2759
+ ctx.setShowReasoning(true);
2760
+ writeln(`${PREFIX.success} reasoning display ${c10.green("on")}`);
2761
+ return;
2762
+ }
2763
+ if (mode === "off") {
2764
+ ctx.setShowReasoning(false);
2765
+ writeln(`${PREFIX.success} reasoning display ${c10.dim("off")}`);
2766
+ return;
2767
+ }
2768
+ writeln(`${PREFIX.error} usage: /reasoning <on|off>`);
2769
+ }
2688
2770
  function handlePlan(ctx) {
2689
2771
  ctx.setPlanMode(!ctx.planMode);
2690
2772
  if (ctx.planMode) {
@@ -2870,6 +2952,7 @@ function handleHelp(ctx, custom) {
2870
2952
  const cmds = [
2871
2953
  ["/model [id]", "list or switch models (fetches live list)"],
2872
2954
  ["/undo", "remove the last turn from conversation history"],
2955
+ ["/reasoning [on|off]", "toggle display of model reasoning output"],
2873
2956
  ["/plan", "toggle plan mode (read-only tools + MCP)"],
2874
2957
  [
2875
2958
  "/ralph",
@@ -2936,6 +3019,9 @@ async function handleCommand(command, args, ctx) {
2936
3019
  case "undo":
2937
3020
  await handleUndo(ctx);
2938
3021
  return { type: "handled" };
3022
+ case "reasoning":
3023
+ handleReasoning(ctx, args);
3024
+ return { type: "handled" };
2939
3025
  case "plan":
2940
3026
  handlePlan(ctx);
2941
3027
  return { type: "handled" };
@@ -3606,6 +3692,16 @@ import * as c14 from "yoctocolors";
3606
3692
 
3607
3693
  // src/llm-api/turn.ts
3608
3694
  import { dynamicTool, jsonSchema, stepCountIs, streamText } from "ai";
3695
+ function getReasoningDeltaFromStreamChunk(chunk) {
3696
+ if (chunk.type !== "reasoning-delta" && chunk.type !== "reasoning") {
3697
+ return null;
3698
+ }
3699
+ if (typeof chunk.text === "string")
3700
+ return chunk.text;
3701
+ if (typeof chunk.textDelta === "string")
3702
+ return chunk.textDelta;
3703
+ return "";
3704
+ }
3609
3705
  var MAX_STEPS = 50;
3610
3706
  function isZodSchema(s) {
3611
3707
  return s !== null && typeof s === "object" && "_def" in s;
@@ -3624,6 +3720,77 @@ function toCoreTool(def) {
3624
3720
  }
3625
3721
  });
3626
3722
  }
3723
+ function isRecord2(value) {
3724
+ return value !== null && typeof value === "object";
3725
+ }
3726
+ function normalizeProviderOptions(part) {
3727
+ if (!isRecord2(part))
3728
+ return part;
3729
+ if (part.providerOptions !== undefined || part.providerMetadata === undefined) {
3730
+ return part;
3731
+ }
3732
+ return {
3733
+ ...part,
3734
+ providerOptions: part.providerMetadata
3735
+ };
3736
+ }
3737
+ function normalizeMessageProviderOptions(message) {
3738
+ if (!Array.isArray(message.content))
3739
+ return message;
3740
+ return {
3741
+ ...message,
3742
+ content: message.content.map((part) => normalizeProviderOptions(part))
3743
+ };
3744
+ }
3745
+ function getGeminiThoughtSignature(part) {
3746
+ if (!isRecord2(part))
3747
+ return null;
3748
+ const providerOptions = isRecord2(part.providerOptions) ? part.providerOptions : isRecord2(part.providerMetadata) ? part.providerMetadata : null;
3749
+ if (!providerOptions)
3750
+ return null;
3751
+ for (const provider of ["google", "vertex"]) {
3752
+ const metadata = providerOptions[provider];
3753
+ if (!isRecord2(metadata))
3754
+ continue;
3755
+ const signature = metadata.thoughtSignature;
3756
+ if (typeof signature === "string" && signature.length > 0) {
3757
+ return signature;
3758
+ }
3759
+ }
3760
+ return null;
3761
+ }
3762
+ function isToolCallPart(part) {
3763
+ return isRecord2(part) && part.type === "tool-call";
3764
+ }
3765
+ function assistantMessageHasUnsignedGeminiToolCall(message) {
3766
+ if (message.role !== "assistant" || !Array.isArray(message.content)) {
3767
+ return false;
3768
+ }
3769
+ for (const part of message.content) {
3770
+ if (!isToolCallPart(part))
3771
+ continue;
3772
+ if (getGeminiThoughtSignature(part) === null)
3773
+ return true;
3774
+ }
3775
+ return false;
3776
+ }
3777
+ function sanitizeGeminiToolMessages(messages, modelString, hasTools) {
3778
+ if (!hasTools || !shouldDisableGeminiThinkingForTools(modelString)) {
3779
+ return messages;
3780
+ }
3781
+ let sanitized = messages.map((message) => normalizeMessageProviderOptions(message));
3782
+ while (true) {
3783
+ const brokenIndex = sanitized.findIndex((message) => assistantMessageHasUnsignedGeminiToolCall(message));
3784
+ if (brokenIndex === -1)
3785
+ return sanitized;
3786
+ const nextUserIndex = sanitized.findIndex((message, index) => index > brokenIndex && message.role === "user");
3787
+ if (nextUserIndex !== -1) {
3788
+ sanitized = sanitized.slice(nextUserIndex);
3789
+ continue;
3790
+ }
3791
+ return sanitized.slice(0, brokenIndex);
3792
+ }
3793
+ }
3627
3794
  function isOpenAIGPT(modelString) {
3628
3795
  const { provider, modelId } = parseModelString(modelString);
3629
3796
  return (provider === "openai" || provider === "zen") && modelId.startsWith("gpt-");
@@ -3649,8 +3816,22 @@ async function* runTurn(options) {
3649
3816
  const partialState = { messages: [] };
3650
3817
  try {
3651
3818
  const useInstructions = systemPrompt !== undefined && isOpenAIGPT(modelString);
3652
- logApiEvent("turn start", { modelString, messageCount: messages.length });
3653
- const thinkingOpts = thinkingEffort ? getThinkingProviderOptions(modelString, thinkingEffort) : null;
3819
+ const toolCount = Object.keys(toolSet).length;
3820
+ const thinkingOpts = thinkingEffort ? getThinkingProviderOptions(modelString, thinkingEffort, toolCount > 0) : null;
3821
+ const reasoningSummaryRequested = isRecord2(thinkingOpts) && isRecord2(thinkingOpts.openai) && typeof thinkingOpts.openai.reasoningSummary === "string";
3822
+ logApiEvent("turn start", {
3823
+ modelString,
3824
+ messageCount: messages.length,
3825
+ reasoningSummaryRequested
3826
+ });
3827
+ const turnMessages = sanitizeGeminiToolMessages(messages, modelString, toolCount > 0);
3828
+ if (turnMessages.length !== messages.length) {
3829
+ logApiEvent("gemini tool history truncated", {
3830
+ modelString,
3831
+ originalMessages: messages.length,
3832
+ sanitizedMessages: turnMessages.length
3833
+ });
3834
+ }
3654
3835
  const mergedProviderOptions = {
3655
3836
  ...useInstructions ? { openai: { instructions: systemPrompt, store: false } } : {},
3656
3837
  ...thinkingOpts ?? {},
@@ -3664,7 +3845,7 @@ async function* runTurn(options) {
3664
3845
  };
3665
3846
  const streamOpts = {
3666
3847
  model,
3667
- messages,
3848
+ messages: turnMessages,
3668
3849
  tools: toolSet,
3669
3850
  stopWhen: stepCountIs(MAX_STEPS),
3670
3851
  onStepFinish: (step) => {
@@ -3686,7 +3867,7 @@ async function* runTurn(options) {
3686
3867
  }
3687
3868
  return;
3688
3869
  },
3689
- ...systemPrompt ? { system: systemPrompt } : {},
3870
+ ...systemPrompt && !useInstructions ? { system: systemPrompt } : {},
3690
3871
  ...Object.keys(mergedProviderOptions).length > 0 ? { providerOptions: mergedProviderOptions } : {},
3691
3872
  ...signal ? { abortSignal: signal } : {},
3692
3873
  experimental_repairToolCall: async ({ toolCall }) => {
@@ -3697,7 +3878,7 @@ async function* runTurn(options) {
3697
3878
  result.response.catch(() => {});
3698
3879
  for await (const chunk of result.fullStream) {
3699
3880
  const c13 = chunk;
3700
- if (c13.type !== "text-delta" && c13.type !== "reasoning") {
3881
+ if (c13.type !== "text-delta" && c13.type !== "reasoning" && c13.type !== "reasoning-delta") {
3701
3882
  logApiEvent("stream chunk", {
3702
3883
  type: c13.type,
3703
3884
  toolCallId: c13.toolCallId,
@@ -3716,8 +3897,11 @@ async function* runTurn(options) {
3716
3897
  };
3717
3898
  break;
3718
3899
  }
3900
+ case "reasoning-delta":
3719
3901
  case "reasoning": {
3720
- const delta = typeof c13.textDelta === "string" ? c13.textDelta : "";
3902
+ const delta = getReasoningDeltaFromStreamChunk(c13);
3903
+ if (delta === null)
3904
+ break;
3721
3905
  yield {
3722
3906
  type: "reasoning-delta",
3723
3907
  delta
@@ -4998,6 +5182,7 @@ class SessionRunner {
4998
5182
  mcpTools;
4999
5183
  currentModel;
5000
5184
  currentThinkingEffort;
5185
+ showReasoning;
5001
5186
  session;
5002
5187
  coreHistory;
5003
5188
  turnIndex = 1;
@@ -5017,6 +5202,7 @@ class SessionRunner {
5017
5202
  this.mcpTools = opts.mcpTools;
5018
5203
  this.currentModel = opts.initialModel;
5019
5204
  this.currentThinkingEffort = opts.initialThinkingEffort;
5205
+ this.showReasoning = opts.initialShowReasoning;
5020
5206
  this.extraSystemPrompt = opts.extraSystemPrompt;
5021
5207
  this.isSubagent = opts.isSubagent;
5022
5208
  this.killSubprocesses = opts.killSubprocesses;
@@ -5094,7 +5280,9 @@ class SessionRunner {
5094
5280
  signal: abortController.signal,
5095
5281
  ...this.currentThinkingEffort ? { thinkingEffort: this.currentThinkingEffort } : {}
5096
5282
  });
5097
- const { inputTokens, outputTokens, contextTokens, newMessages } = await this.reporter.renderTurn(events);
5283
+ const { inputTokens, outputTokens, contextTokens, newMessages } = await this.reporter.renderTurn(events, {
5284
+ showReasoning: this.showReasoning
5285
+ });
5098
5286
  if (newMessages.length > 0) {
5099
5287
  this.coreHistory.push(...newMessages);
5100
5288
  this.session.messages.push(...newMessages);
@@ -5119,7 +5307,13 @@ class SessionRunner {
5119
5307
  }
5120
5308
 
5121
5309
  // src/tools/worktree.ts
5122
- import { copyFileSync, existsSync as existsSync6, mkdirSync as mkdirSync5, symlinkSync } from "fs";
5310
+ import {
5311
+ copyFileSync,
5312
+ existsSync as existsSync6,
5313
+ mkdirSync as mkdirSync5,
5314
+ rmSync,
5315
+ symlinkSync
5316
+ } from "fs";
5123
5317
  import { dirname as dirname2, join as join13 } from "path";
5124
5318
  async function runGit(cwd, args) {
5125
5319
  try {
@@ -5241,22 +5435,56 @@ async function cleanupBranch(mainCwd, branch) {
5241
5435
  throw gitError(`Failed to delete branch "${branch}"`, (result.stderr || result.stdout).trim());
5242
5436
  }
5243
5437
  }
5438
+ function shouldSkipUntrackedPath(path) {
5439
+ return path === "node_modules" || path.startsWith("node_modules/");
5440
+ }
5441
+ async function syncTrackedChanges(mainRoot, worktreeRoot) {
5442
+ const trackedResult = await runGit(mainRoot, [
5443
+ "diff",
5444
+ "--name-status",
5445
+ "-M",
5446
+ "HEAD"
5447
+ ]);
5448
+ if (trackedResult.exitCode !== 0)
5449
+ return;
5450
+ for (const line of splitNonEmptyLines(trackedResult.stdout)) {
5451
+ const [statusToken, firstPath, secondPath] = line.split("\t");
5452
+ const status = statusToken?.trim() ?? "";
5453
+ if (!status || !firstPath)
5454
+ continue;
5455
+ if (status.startsWith("R") || status.startsWith("C")) {
5456
+ if (!secondPath)
5457
+ continue;
5458
+ const src2 = join13(mainRoot, secondPath);
5459
+ const dst2 = join13(worktreeRoot, secondPath);
5460
+ if (existsSync6(src2)) {
5461
+ mkdirSync5(dirname2(dst2), { recursive: true });
5462
+ copyFileSync(src2, dst2);
5463
+ }
5464
+ if (status.startsWith("R")) {
5465
+ rmSync(join13(worktreeRoot, firstPath), { force: true });
5466
+ }
5467
+ continue;
5468
+ }
5469
+ if (status.startsWith("D")) {
5470
+ rmSync(join13(worktreeRoot, firstPath), { force: true });
5471
+ continue;
5472
+ }
5473
+ const src = join13(mainRoot, firstPath);
5474
+ const dst = join13(worktreeRoot, firstPath);
5475
+ if (!existsSync6(src))
5476
+ continue;
5477
+ mkdirSync5(dirname2(dst), { recursive: true });
5478
+ copyFileSync(src, dst);
5479
+ }
5480
+ }
5244
5481
  async function applyParentChanges(mainCwd, worktreeCwd) {
5245
5482
  try {
5246
5483
  const [mainRoot, worktreeRoot] = await Promise.all([
5247
5484
  getRepoRoot2(mainCwd),
5248
5485
  getRepoRoot2(worktreeCwd)
5249
5486
  ]);
5250
- const diffResult = await runGit(mainRoot, ["diff", "HEAD", "--binary"]);
5251
- if (diffResult.exitCode === 0 && diffResult.stdout.trim()) {
5252
- const proc = Bun.spawn(["git", "apply", "-"], {
5253
- cwd: worktreeRoot,
5254
- stdin: Buffer.from(diffResult.stdout),
5255
- stdout: "pipe",
5256
- stderr: "pipe"
5257
- });
5258
- await proc.exited;
5259
- }
5487
+ await syncTrackedChanges(mainRoot, worktreeRoot);
5260
5488
  const untrackedResult = await runGit(mainRoot, [
5261
5489
  "ls-files",
5262
5490
  "--others",
@@ -5264,6 +5492,8 @@ async function applyParentChanges(mainCwd, worktreeCwd) {
5264
5492
  ]);
5265
5493
  if (untrackedResult.exitCode === 0) {
5266
5494
  for (const file of splitNonEmptyLines(untrackedResult.stdout)) {
5495
+ if (shouldSkipUntrackedPath(file))
5496
+ continue;
5267
5497
  try {
5268
5498
  const src = join13(mainRoot, file);
5269
5499
  const dst = join13(worktreeRoot, file);
@@ -5286,7 +5516,7 @@ function getMcCommand() {
5286
5516
  var MAX_SUBAGENT_DEPTH = 10;
5287
5517
  function createSubagentRunner(cwd, getCurrentModel) {
5288
5518
  const activeProcs = new Map;
5289
- const subagentDepth = parseInt(process.env.MC_SUBAGENT_DEPTH ?? "0", 10);
5519
+ const subagentDepth = Number.parseInt(process.env.MC_SUBAGENT_DEPTH ?? "0", 10);
5290
5520
  let mergeLockTail = Promise.resolve();
5291
5521
  const mergeSubagentBranch = async (branch) => {
5292
5522
  const prev = mergeLockTail;
@@ -5472,6 +5702,7 @@ async function runAgent(opts) {
5472
5702
  mcpTools,
5473
5703
  initialModel: currentModel,
5474
5704
  initialThinkingEffort: opts.initialThinkingEffort,
5705
+ initialShowReasoning: opts.initialShowReasoning,
5475
5706
  sessionId: opts.sessionId,
5476
5707
  extraSystemPrompt: opts.agentSystemPrompt,
5477
5708
  isSubagent: opts.headless,
@@ -5506,6 +5737,13 @@ async function runAgent(opts) {
5506
5737
  runner.currentThinkingEffort = e;
5507
5738
  setPreferredThinkingEffort(e);
5508
5739
  },
5740
+ get showReasoning() {
5741
+ return runner.showReasoning;
5742
+ },
5743
+ setShowReasoning: (show) => {
5744
+ runner.showReasoning = show;
5745
+ setPreferredShowReasoning(show);
5746
+ },
5509
5747
  get planMode() {
5510
5748
  return runner.planMode;
5511
5749
  },
@@ -5561,7 +5799,8 @@ async function runAgent(opts) {
5561
5799
  contextWindow: getContextWindow2(runner.currentModel) ?? 0,
5562
5800
  ralphMode: runner.ralphMode,
5563
5801
  thinkingEffort: runner.currentThinkingEffort,
5564
- activeAgent: activeAgentName
5802
+ activeAgent: activeAgentName,
5803
+ showReasoning: runner.showReasoning
5565
5804
  });
5566
5805
  }
5567
5806
  if (opts.headless) {
@@ -5594,17 +5833,21 @@ class HeadlessReporter {
5594
5833
  writeText(_text) {}
5595
5834
  startSpinner(_label) {}
5596
5835
  stopSpinner() {}
5597
- async renderTurn(events) {
5836
+ async renderTurn(events, _opts) {
5598
5837
  let inputTokens = 0;
5599
5838
  let outputTokens = 0;
5600
5839
  let contextTokens = 0;
5601
5840
  let newMessages = [];
5602
5841
  let accumulatedText = "";
5842
+ let reasoningText = "";
5603
5843
  for await (const event of events) {
5604
5844
  switch (event.type) {
5605
5845
  case "text-delta":
5606
5846
  accumulatedText += event.delta;
5607
5847
  break;
5848
+ case "reasoning-delta":
5849
+ reasoningText += event.delta;
5850
+ break;
5608
5851
  case "turn-complete":
5609
5852
  inputTokens = event.inputTokens;
5610
5853
  outputTokens = event.outputTokens;
@@ -5622,7 +5865,13 @@ class HeadlessReporter {
5622
5865
  }
5623
5866
  }
5624
5867
  }
5625
- return { inputTokens, outputTokens, contextTokens, newMessages };
5868
+ return {
5869
+ inputTokens,
5870
+ outputTokens,
5871
+ contextTokens,
5872
+ newMessages,
5873
+ reasoningText
5874
+ };
5626
5875
  }
5627
5876
  renderStatusBar(_data) {}
5628
5877
  renderHook(_toolName, _scriptPath, _success) {}
@@ -5655,8 +5904,8 @@ class CliReporter {
5655
5904
  stopSpinner() {
5656
5905
  this.spinner.stop();
5657
5906
  }
5658
- async renderTurn(events) {
5659
- return renderTurn(events, this.spinner);
5907
+ async renderTurn(events, opts) {
5908
+ return renderTurn(events, this.spinner, opts);
5660
5909
  }
5661
5910
  renderStatusBar(data) {
5662
5911
  renderStatusBar(data);
@@ -5723,7 +5972,7 @@ function parseArgs(argv) {
5723
5972
  args.agentName = argv[++i] ?? null;
5724
5973
  break;
5725
5974
  case "--output-fd": {
5726
- const fd = parseInt(argv[++i] ?? "", 10);
5975
+ const fd = Number.parseInt(argv[++i] ?? "", 10);
5727
5976
  if (!Number.isNaN(fd))
5728
5977
  args.outputFd = fd;
5729
5978
  break;
@@ -5882,6 +6131,7 @@ async function main() {
5882
6131
  model: modelOverride,
5883
6132
  cwd: runCwd,
5884
6133
  initialThinkingEffort: getPreferredThinkingEffort(),
6134
+ initialShowReasoning: getPreferredShowReasoning(),
5885
6135
  reporter: new HeadlessReporter,
5886
6136
  initialPrompt: args.prompt ?? "",
5887
6137
  headless: true,
@@ -5913,6 +6163,7 @@ async function main() {
5913
6163
  model,
5914
6164
  cwd: args.cwd,
5915
6165
  initialThinkingEffort: getPreferredThinkingEffort(),
6166
+ initialShowReasoning: getPreferredShowReasoning(),
5916
6167
  reporter: new CliReporter
5917
6168
  };
5918
6169
  if (sessionId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mini-coder",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "A small, fast CLI coding agent",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",