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.
- package/dist/mc.js +287 -36
- 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 {
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 {
|
|
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
|
-
|
|
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 {
|
|
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)
|