reasonix 0.31.0 → 0.32.0

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/index.js CHANGED
@@ -294,165 +294,6 @@ var DeepSeekClient = class {
294
294
  }
295
295
  };
296
296
 
297
- // src/harvest.ts
298
- function emptyPlanState() {
299
- return { subgoals: [], hypotheses: [], uncertainties: [], rejectedPaths: [] };
300
- }
301
- function isPlanStateEmpty(s) {
302
- if (!s) return true;
303
- return s.subgoals.length === 0 && s.hypotheses.length === 0 && s.uncertainties.length === 0 && s.rejectedPaths.length === 0;
304
- }
305
- var SYSTEM_PROMPT = `You extract a typed plan state from a reasoning trace produced by another LLM.
306
- Output ONLY a JSON object. No markdown, no prose, no backticks.
307
-
308
- Schema:
309
- {
310
- "subgoals": string[], // concrete intermediate objectives the trace identifies
311
- "hypotheses": string[], // candidate approaches or assumptions being weighed
312
- "uncertainties": string[], // facts the trace flags as unclear / to verify
313
- "rejectedPaths": string[] // approaches the trace considered and then abandoned
314
- }
315
-
316
- Constraints:
317
- - Every field must be present. Use [] if not applicable.
318
- - Each array has at most {maxItems} items.
319
- - Each item is plain text, at most {maxItemLen} characters, no markdown.
320
- - Write in the same language as the trace (Chinese in \u2192 Chinese out, etc.).
321
- - Do not quote back the trace; write short, specific phrases.`;
322
- async function harvest(reasoningContent, client, options = {}, signal) {
323
- if (!client || !reasoningContent) return emptyPlanState();
324
- if (signal?.aborted) return emptyPlanState();
325
- const minLen = options.minReasoningLen ?? 40;
326
- const trimmed = reasoningContent.trim();
327
- if (trimmed.length < minLen) return emptyPlanState();
328
- const model = options.model ?? "deepseek-v4-flash";
329
- const maxItems = options.maxItems ?? 5;
330
- const maxItemLen = options.maxItemLen ?? 80;
331
- const system = SYSTEM_PROMPT.replace("{maxItems}", String(maxItems)).replace(
332
- "{maxItemLen}",
333
- String(maxItemLen)
334
- );
335
- try {
336
- const resp = await client.chat({
337
- model,
338
- messages: [
339
- { role: "system", content: system },
340
- { role: "user", content: trimmed }
341
- ],
342
- responseFormat: { type: "json_object" },
343
- temperature: 0,
344
- maxTokens: 600,
345
- // Pin mode + effort so a future default-model swap (e.g. someone
346
- // sets `options.model = "deepseek-v4-pro"`) can't accidentally
347
- // turn this micro-extraction into a multi-thousand-reasoning-
348
- // token call. DeepSeek ignores these on non-thinking models, so
349
- // the request stays valid regardless of the chosen model.
350
- thinking: "disabled",
351
- reasoningEffort: "high",
352
- signal
353
- });
354
- return parsePlanState(resp.content, maxItems, maxItemLen);
355
- } catch {
356
- return emptyPlanState();
357
- }
358
- }
359
- function parsePlanState(raw, maxItems, maxItemLen) {
360
- const text = (raw ?? "").trim();
361
- if (!text) return emptyPlanState();
362
- let parsed;
363
- try {
364
- parsed = JSON.parse(text);
365
- } catch {
366
- const match = text.match(/\{[\s\S]*\}/);
367
- if (!match) return emptyPlanState();
368
- try {
369
- parsed = JSON.parse(match[0]);
370
- } catch {
371
- return emptyPlanState();
372
- }
373
- }
374
- if (!parsed || typeof parsed !== "object") return emptyPlanState();
375
- const obj = parsed;
376
- return {
377
- subgoals: sanitizeArray(obj.subgoals, maxItems, maxItemLen),
378
- hypotheses: sanitizeArray(obj.hypotheses, maxItems, maxItemLen),
379
- uncertainties: sanitizeArray(obj.uncertainties, maxItems, maxItemLen),
380
- rejectedPaths: sanitizeArray(obj.rejectedPaths ?? obj.rejected_paths, maxItems, maxItemLen)
381
- };
382
- }
383
- function sanitizeArray(raw, maxItems, maxItemLen) {
384
- if (!Array.isArray(raw)) return [];
385
- const out = [];
386
- for (const item of raw) {
387
- if (out.length >= maxItems) break;
388
- if (typeof item !== "string") continue;
389
- const cleaned = item.trim().replace(/\s+/g, " ");
390
- if (!cleaned) continue;
391
- out.push(cleaned.length <= maxItemLen ? cleaned : `${cleaned.slice(0, maxItemLen - 1)}\u2026`);
392
- }
393
- return out;
394
- }
395
-
396
- // src/consistency.ts
397
- var defaultSelector = (samples) => {
398
- if (samples.length === 0) throw new Error("defaultSelector: samples is empty");
399
- return samples.slice().sort((a, b) => {
400
- const uDiff = a.planState.uncertainties.length - b.planState.uncertainties.length;
401
- if (uDiff !== 0) return uDiff;
402
- const aLen = a.response.content?.length ?? 0;
403
- const bLen = b.response.content?.length ?? 0;
404
- return aLen - bLen;
405
- })[0];
406
- };
407
- async function runBranches(client, request, opts = {}) {
408
- const budget = Math.max(1, opts.budget ?? 1);
409
- const temperatures = resolveTemperatures(budget, opts.temperatures);
410
- const selector = opts.selector ?? defaultSelector;
411
- const samples = await Promise.all(
412
- temperatures.map(async (temperature, index) => {
413
- const response = await client.chat({ ...request, temperature });
414
- const planState = await harvest(response.reasoningContent, client, opts.harvestOptions);
415
- const sample = { index, temperature, response, planState };
416
- try {
417
- opts.onSampleDone?.(sample);
418
- } catch {
419
- }
420
- return sample;
421
- })
422
- );
423
- return { chosen: selector(samples), samples };
424
- }
425
- function aggregateBranchUsage(samples) {
426
- let promptTokens = 0;
427
- let completionTokens = 0;
428
- let totalTokens = 0;
429
- let promptCacheHitTokens = 0;
430
- let promptCacheMissTokens = 0;
431
- for (const s of samples) {
432
- promptTokens += s.response.usage.promptTokens;
433
- completionTokens += s.response.usage.completionTokens;
434
- totalTokens += s.response.usage.totalTokens;
435
- promptCacheHitTokens += s.response.usage.promptCacheHitTokens;
436
- promptCacheMissTokens += s.response.usage.promptCacheMissTokens;
437
- }
438
- return {
439
- promptTokens,
440
- completionTokens,
441
- totalTokens,
442
- promptCacheHitTokens,
443
- promptCacheMissTokens
444
- };
445
- }
446
- function resolveTemperatures(budget, custom) {
447
- if (custom && custom.length >= budget) return [...custom.slice(0, budget)];
448
- if (budget === 1) return [0];
449
- const out = [];
450
- for (let i = 0; i < budget; i++) {
451
- out.push(Number((i / (budget - 1)).toFixed(2)));
452
- }
453
- return out;
454
- }
455
-
456
297
  // src/core/pause-gate.ts
457
298
  var PauseGate = class {
458
299
  _nextId = 0;
@@ -775,21 +616,16 @@ var EN = {
775
616
  resumeHint: "force-resume the named session (even if idle)",
776
617
  newHint: "force a fresh session (ignore --session / --continue)",
777
618
  transcriptHint: "path to write the JSONL transcript",
778
- harvestHint: "opt into Pillar-2 plan-state extraction (costs +1 flash call per turn)",
779
619
  budgetHint: "session USD cap \u2014 warns at 80%, refuses next turn at 100%",
780
620
  modelIdHint: "DeepSeek model id (e.g. deepseek-v4-flash)",
781
621
  systemPromptHint: "override the default system prompt",
782
622
  presetHint: "model bundle \u2014 auto|flash|pro",
783
- harvestOptInHint: "opt into Pillar-2 plan-state extraction",
784
- branchHint: "run N parallel samples per turn (N>=2, manual only)",
785
623
  sessionNameHint: "session name (default: 'default')",
786
624
  ephemeralHint: "disable session persistence for this run",
787
625
  mcpSpecHint: "MCP server spec (repeatable)",
788
626
  mcpPrefixHint: "prefix MCP tool names with this string",
789
627
  noConfigHint: "ignore ~/.reasonix/config.json for this run",
790
628
  presetHintShort: "model bundle \u2014 auto|flash|pro",
791
- harvestHintShort: "Pillar-2 plan-state extraction",
792
- branchHintShort: "parallel samples per turn (N>=2)",
793
629
  budgetHintShort: "session USD cap",
794
630
  transcriptHintShort: "JSONL transcript path",
795
631
  mcpSpecHintShort: "MCP server spec (repeatable)",
@@ -847,12 +683,6 @@ var EN = {
847
683
  success: "Language switched to English.",
848
684
  unsupported: "Unsupported language code: {code}. Supported: {supported}."
849
685
  },
850
- harvest: { description: "toggle Pillar-2 plan-state extraction", argsHint: "[on|off]" },
851
- branch: { description: "run N parallel samples per turn (N>=2)", argsHint: "<N|off>" },
852
- effort: {
853
- description: "reasoning_effort cap \u2014 max is default (agent-class), high is cheaper/faster",
854
- argsHint: "<high|max>"
855
- },
856
686
  pro: {
857
687
  description: "arm v4-pro for the NEXT turn only (one-shot \xB7 auto-disarms after turn)",
858
688
  argsHint: "[off]"
@@ -870,7 +700,6 @@ var EN = {
870
700
  description: "browse + fetch MCP prompts (no arg \u2192 list names; <name> \u2192 render prompt)",
871
701
  argsHint: "[name]"
872
702
  },
873
- tool: { description: "dump full output of the Nth tool call (1=latest)", argsHint: "[N]" },
874
703
  memory: {
875
704
  description: "show / manage pinned memory (REASONIX.md + ~/.reasonix/memory)",
876
705
  argsHint: "[list|show <name>|forget <name>|clear <scope> confirm]"
@@ -900,7 +729,6 @@ var EN = {
900
729
  argsHint: "[text]"
901
730
  },
902
731
  doctor: { description: "health check (api / config / api-reach / index / hooks / project)" },
903
- think: { description: "dump the last turn's full R1 reasoning (reasoner only)" },
904
732
  context: { description: "show context-window breakdown (system / tools / log / input)" },
905
733
  retry: { description: "truncate & resend your last message (fresh sample)" },
906
734
  compact: {
@@ -914,12 +742,6 @@ var EN = {
914
742
  argsHint: "[N]"
915
743
  },
916
744
  sessions: { description: "list saved sessions (current marked with \u25B8)" },
917
- rename: { description: "rename the current session on disk", argsHint: "<new-name>" },
918
- resume: {
919
- description: "show the launch command to resume a saved session",
920
- argsHint: "<name>"
921
- },
922
- forget: { description: "delete the current session from disk" },
923
745
  setup: { description: "reminds you to exit and run `reasonix setup`" },
924
746
  semantic: {
925
747
  description: "show semantic_search status \u2014 built? Ollama installed? how to enable"
@@ -965,9 +787,6 @@ var EN = {
965
787
  description: "toggle read-only plan mode (writes bounced until submit_plan + approval)",
966
788
  argsHint: "[on|off]"
967
789
  },
968
- "apply-plan": {
969
- description: "force-approve a pending / in-text plan (fallback if picker was missed)"
970
- },
971
790
  mode: {
972
791
  description: "edit-gate: review (queue) \xB7 auto (apply+undo) \xB7 yolo (apply+auto-shell). Shift+Tab cycles.",
973
792
  argsHint: "[review|auto|yolo]"
@@ -1111,49 +930,8 @@ var EN = {
1111
930
  },
1112
931
  handlers: {
1113
932
  basic: {
1114
- clearInfo: "\u25B8 terminal cleared (viewport + scrollback). Context (message log) is intact \u2014 next turn still sees everything. Use /new to start fresh, or /forget to delete the session entirely.",
1115
933
  newInfo: "\u25B8 new conversation \u2014 dropped {count} message(s) from context. Same session, fresh slate.",
1116
934
  helpTitle: "Commands:",
1117
- helpHelp: " /help this message",
1118
- helpKeys: " /keys keyboard shortcuts + prompt prefixes (!, @, /)",
1119
- helpStatus: " /status show current settings",
1120
- helpPreset: " /preset <auto|flash|pro> model bundle \u2014 see below",
1121
- helpModel: " /model <id> deepseek-v4-flash or deepseek-v4-pro",
1122
- helpPro: " /pro [off] arm v4-pro for NEXT turn only (one-shot, auto-disarms)",
1123
- helpHarvest: " /harvest [on|off] Pillar 2: structured plan-state extraction (OPT-IN \u2014 costs extra)",
1124
- helpBranch: " /branch <N|off> run N parallel samples (N>=2) \u2014 MANUAL ONLY, N\xD7 cost",
1125
- helpEffort: " /effort <high|max> reasoning_effort cap (max=full thinking, high=cheaper/faster)",
1126
- helpMcp: " /mcp list MCP servers + tools attached to this session",
1127
- helpResource: " /resource [uri] browse + read MCP resources (no arg \u2192 list URIs; <uri> \u2192 fetch)",
1128
- helpPrompt: " /prompt [name] browse + fetch MCP prompts (no arg \u2192 list names; <name> \u2192 render)",
1129
- helpCompact: " /compact fold older turns into a summary (cache-safe; auto-fires at 50% ctx)",
1130
- helpThink: " /think dump the most recent turn's full R1 reasoning (reasoner only)",
1131
- helpTool: " /tool [N] list tool calls (or dump full output of #N, 1=most recent)",
1132
- helpCost: " /cost [text] bare \u2192 last turn's spend; with text \u2192 estimate cost of sending it next",
1133
- helpMemory: " /memory [sub] show pinned memory (REASONIX.md + ~/.reasonix/memory).",
1134
- helpMemorySub: " subs: list | show <name> | forget <name> | clear <scope> confirm",
1135
- helpSkill: " /skill [sub] list / run user skills (project/.reasonix/skills + ~/.reasonix/skills).",
1136
- helpSkillSub: " subs: list | show <name> | <name> [args] (injects skill body as user turn)",
1137
- helpRetry: " /retry truncate & resend your last message (fresh sample from the model)",
1138
- helpApply: " /apply [N|1,3|1-4] (code mode) commit pending edit blocks (no arg \u2192 all; index \u2192 subset)",
1139
- helpDiscard: " /discard [N|1,3|1-4] (code mode) drop pending edits (no arg \u2192 all; index \u2192 subset)",
1140
- helpWalk: " /walk (code mode) step through pending edits one block at a time (y/n per block, a apply rest, A flip AUTO)",
1141
- helpUndo: " /undo (code mode) roll back the latest non-undone edit batch",
1142
- helpHistory: " /history (code mode) list every edit batch this session",
1143
- helpShow: " /show [id] (code mode) dump a stored edit diff (newest when id omitted)",
1144
- helpCommit: ' /commit "msg" (code mode) git add -A && git commit -m "msg"',
1145
- helpPlan: " /plan [on|off] (code mode) toggle read-only plan mode; writes gated behind submit_plan + your approval",
1146
- helpApplyPlan: " /apply-plan (code mode) force-approve pending/in-text plan (fallback)",
1147
- helpMode: " /mode [review|auto|yolo] (code mode) review = queue \xB7 auto = apply+undo banner \xB7 yolo = apply+auto-shell. Shift+Tab cycles all three.",
1148
- helpJobs: " /jobs (code mode) list background processes (run_background) \u2014 running and exited",
1149
- helpKill: " /kill <id> (code mode) stop a background job by id (SIGTERM \u2192 SIGKILL)",
1150
- helpLogs: " /logs <id> [lines] (code mode) tail a background job's output (default 80 lines)",
1151
- helpSessions: " /sessions list saved sessions (current is marked with \u25B8)",
1152
- helpForget: " /forget delete the current session from disk",
1153
- helpNew: " /new start fresh: drop all context + clear scrollback",
1154
- helpClear: " /clear clear displayed scrollback only (context kept \u2014 model still sees it)",
1155
- helpLoop: " /loop <interval> <prompt> auto-resubmit <prompt> every <interval> (5s..6h). /loop stop \xB7 type anything to cancel.",
1156
- helpExit: " /exit quit (aliases: /quit, /q)",
1157
935
  helpShellTitle: "Shell shortcut:",
1158
936
  helpShell: " !<cmd> run <cmd> in the sandbox root; output goes into",
1159
937
  helpShellDetail: " the conversation so the model sees it next turn.",
@@ -1180,46 +958,6 @@ var EN = {
1180
958
  helpSessionsTitle: "Sessions (auto-enabled by default, named 'default'):",
1181
959
  helpSessionCustom: " reasonix chat --session <name> use a different named session",
1182
960
  helpSessionNone: " reasonix chat --no-session disable persistence for this run",
1183
- helpLimitationTitle: "Known limitation:",
1184
- helpLimitation1: " Resizing the terminal mid-session may stack ghost header frames in",
1185
- helpLimitation2: " scrollback (Ink library's live-region clear doesn't account for line",
1186
- helpLimitation3: " re-wrapping at the new width). Scroll-up history is unaffected; the",
1187
- helpLimitation4: " artifact is purely visual and clears the next time you /clear.",
1188
- keysTitle: "Keyboard & prompt shortcuts:",
1189
- keysEnter: " Enter submit the current prompt",
1190
- keysNewline: " Shift+Enter / Ctrl+J insert a newline (multi-line prompt)",
1191
- keysContinue: " \\<Enter> bash-style line continuation",
1192
- keysArrow: " \u2190 \u2192 \u2191 \u2193 move cursor / recall history at buffer boundary",
1193
- keysPage: " PageUp / PageDown jump to top / bottom of the WHOLE buffer (handy after a big paste)",
1194
- keysHomeEnd: " Ctrl+A / Ctrl+E jump to start / end of the CURRENT line",
1195
- keysClearLine: " Ctrl+U clear the entire input buffer",
1196
- keysDeleteWord: " Ctrl+W delete the word before the cursor",
1197
- keysBackspace: " Backspace delete left; Delete delete under cursor",
1198
- keysEsc: " Esc abort the in-flight turn",
1199
- keysEditYn: " y / n accept / reject pending edits (code mode)",
1200
- keysEditTab: " Shift+Tab cycle edit gate: review \u2194 AUTO (code mode, persists to config)",
1201
- keysEditUndo: " u undo the latest non-undone edit batch (session-wide, not just banner)",
1202
- keysPromptTitle: "Prompt prefixes:",
1203
- keysSlash: " /<name> slash command; Tab/Enter picks from the suggestion list",
1204
- keysAtFile: " @<path> inline a file under [Referenced files] (code mode).",
1205
- keysAtFilePicker: " Trailing `@\u2026` opens a file picker; \u2191/\u2193 navigate, Tab/Enter pick.",
1206
- keysAtUrl: " @https://... fetch the URL, strip HTML, inline under [Referenced URLs].",
1207
- keysAtUrlCache: " Cached per session \u2014 same URL twice fetches once.",
1208
- keysBang: " !<cmd> run <cmd> as shell in the sandbox root; output goes into context",
1209
- keysBangDetail: " so the model sees it next turn. No allowlist gate.",
1210
- keysHash: " #<note> append <note> to <project>/REASONIX.md (committable, team-shared).",
1211
- keysHashGlobal: " #g <note> append <note> to ~/.reasonix/REASONIX.md (global, never committed).",
1212
- keysHashBoth: " Both pin into the immutable prefix every future session.",
1213
- keysHashEscape: " Use `\\#literal` if you actually want a `#` heading sent to the model.",
1214
- keysPickersTitle: "Pickers (slash + @-mention):",
1215
- keysPickerNav: " \u2191 / \u2193 navigate the suggestion list",
1216
- keysPickerTab: " Tab insert the highlighted item without submitting",
1217
- keysPickerEnter: " Enter insert and (slash) run it, (@) keep editing",
1218
- keysMcpTitle: "MCP exploration:",
1219
- keysMcpServers: " /mcp servers + tool/resource/prompt counts",
1220
- keysMcpResource: " /resource [uri] browse & read resources exposed by your MCP servers",
1221
- keysMcpPrompt: " /prompt [name] browse & fetch prompts exposed by your MCP servers",
1222
- keysUseful: "Useful slashes: /help \xB7 /context \xB7 /stats \xB7 /compact \xB7 /new \xB7 /exit",
1223
961
  retryNone: "nothing to retry \u2014 no prior user message in this session's log.",
1224
962
  retryInfo: '\u25B8 retrying: "{preview}"',
1225
963
  loopTuiOnly: "/loop is only available in the interactive TUI (not in run/replay).",
@@ -1269,9 +1007,6 @@ var EN = {
1269
1007
  planCodeOnly: "/plan is only available inside `reasonix code` \u2014 chat mode doesn't gate tool writes.",
1270
1008
  planOn: "\u25B8 plan mode ON \u2014 write tools are gated; the model MUST call `submit_plan` before anything executes. (The model can also call submit_plan on its own for big tasks even when plan mode is off \u2014 this toggle is the stronger, explicit constraint.) Type /plan off to leave.",
1271
1009
  planOff: "\u25B8 plan mode OFF \u2014 write tools are live again. Model can still propose plans autonomously for large tasks.",
1272
- applyPlanCodeOnly: "/apply-plan is only available inside `reasonix code`.",
1273
- applyPlanInfo: "\u25B8 plan approved \u2014 implementing",
1274
- applyPlanResubmit: "The plan above has been approved. Implement it now. You are out of plan mode \u2014 use edit_file / write_file / run_command as needed. Stick to the plan unless you discover a concrete reason to deviate; if you do, tell me and wait for a response before making that deviation.",
1275
1010
  modeCodeOnly: "/mode is only available inside `reasonix code`.",
1276
1011
  modeUsage: "usage: /mode <review|auto|yolo> (Shift+Tab also cycles)",
1277
1012
  modeYolo: "\u25B8 edit mode: YOLO \u2014 edits AND shell commands auto-run with no prompt. /undo still rolls back edits. Use carefully.",
@@ -1304,24 +1039,10 @@ var EN = {
1304
1039
  modelUsage: "usage: /model <id> ({hint})",
1305
1040
  modelNotInCatalog: "model \u2192 {id} (\u26A0 not in the fetched catalog: {list}. If this is wrong the next call will 400 \u2014 run /models to refresh.)",
1306
1041
  modelSet: "model \u2192 {id}",
1307
- modelsFetching: "fetching /models from DeepSeek\u2026 run /models again in a moment. If it stays empty, your API key may lack permission or the network is blocked.",
1308
- modelsEmpty: "DeepSeek /models returned an empty list. Try /models again, or check your account status at api-docs.deepseek.com.",
1309
- modelsHeader: "Available models (DeepSeek /models \xB7 {count} total):",
1310
- modelsCurrent: "\u25B8 {id} (current)",
1311
- modelsSwitch: "Switch with: /model <id>",
1312
- harvestOn: "harvest \u2192 on (Pillar-2 plan-state extraction \xB7 +1 cheap flash call per turn \xB7 opt-in only; no preset turns it on)",
1313
- harvestOff: "harvest \u2192 off",
1314
1042
  presetAuto: "preset \u2192 auto (v4-flash \u2192 v4-pro on hard turns \xB7 default)",
1315
1043
  presetFlash: "preset \u2192 flash (v4-flash always \xB7 cheapest \xB7 /pro still bumps one turn)",
1316
1044
  presetPro: "preset \u2192 pro (v4-pro always \xB7 ~3\xD7 flash \xB7 for hard multi-turn work)",
1317
1045
  presetUsage: "usage: /preset <auto|flash|pro>",
1318
- branchOff: "branch \u2192 off",
1319
- branchUsage: "usage: /branch <N> (N>=2, or 'off')",
1320
- branchCapped: "branch budget capped at 8 to prevent runaway cost",
1321
- branchSet: "branch \u2192 {n} (runs {n} parallel samples per turn \xB7 {n}\xD7 per-turn cost \xB7 streaming disabled \xB7 manual only, no preset enables branching)",
1322
- effortStatus: "reasoning_effort \u2192 {effort} (use /effort high for cheaper/faster, /effort max for the agent-class default \xB7 persisted across relaunches)",
1323
- effortUsage: "usage: /effort <high|max>",
1324
- effortSet: "reasoning_effort \u2192 {effort} (persisted)",
1325
1046
  proNothingArmed: "nothing armed \u2014 /pro with no args will arm pro for your next turn",
1326
1047
  proDisarmed: "\u25B8 /pro disarmed \u2014 next turn falls back to the current preset",
1327
1048
  proUsage: "usage: /pro arm pro for the next turn (one-shot, auto-disarms after)\n /pro off cancel armed state before the next turn",
@@ -1333,18 +1054,6 @@ var EN = {
1333
1054
  budgetExhausted: "\u25B2 budget \u2192 ${cap} but already spent ${spent}. Next turn will be refused \u2014 bump the cap higher to keep going, or end the session.",
1334
1055
  budgetSet: "budget \u2192 ${cap} (so far: ${spent} \xB7 warns at 80%, refuses next turn at 100% \xB7 /budget off to clear)"
1335
1056
  },
1336
- sessions: {
1337
- forgetNoSession: "not in a session \u2014 nothing to forget",
1338
- forgetInfo: '\u25B8 deleted session "{name}" \u2014 current screen still shows the conversation, but next launch starts fresh',
1339
- forgetFailed: 'could not delete session "{name}" (already gone?)',
1340
- renameUsage: "usage: /rename <new-name>",
1341
- renameNoSession: "not in a session \u2014 nothing to rename",
1342
- renameFailed: 'could not rename \u2014 "{name}" already exists or sanitises to the same id as the current session',
1343
- renameInfo: '\u25B8 renamed session \u2192 "{name}". Restart the TUI to pick it up under its new name.',
1344
- resumeUsage: "usage: /resume <session-name> \u2014 list with /sessions",
1345
- resumeNotFound: 'no session named "{name}" \u2014 list with /sessions',
1346
- resumeInfo: '\u25B8 to resume "{name}", quit and run: reasonix chat --session {name}\n (mid-session swap requires a restart so the message log can rewind cleanly)'
1347
- },
1348
1057
  permissions: {
1349
1058
  mutateCodeOnly: "/permissions add / remove / clear are only available inside `reasonix code` \u2014 they edit the project-scoped allowlist (`~/.reasonix/config.json` projects[<root>].shellAllowed).",
1350
1059
  addUsage: 'usage: /permissions add <prefix> (multi-token OK: /permissions add "git push origin")',
@@ -1386,13 +1095,6 @@ var EN = {
1386
1095
  starting: "\u25B8 starting dashboard server\u2026"
1387
1096
  },
1388
1097
  observability: {
1389
- thinkEmpty: "no reasoning cached. `/think` shows the full thinking-mode thought for the most recent turn \u2014 only thinking-mode models (deepseek-v4-flash / -v4-pro / -reasoner) produce it, and only once the turn completes.",
1390
- thinkInfo: "\u21B3 full thinking ({count} chars):",
1391
- toolEmpty: "no tool calls yet in this session. `/tool` lists them once the model has actually used a tool; `/tool N` dumps the full (untruncated) output of the Nth-most-recent.",
1392
- toolUsage: "usage: /tool [N] (no arg \u2192 list; N=1 \u2192 most recent result in full, N=2 \u2192 previous, \u2026)",
1393
- toolOob: "only {count} tool call(s) in history \u2014 asked for #{n}. Try /tool with no arg to see the list.",
1394
- toolNotFound: "could not read tool call #{n}",
1395
- toolInfo: "\u21B3 tool<{name}> #{n} ({chars} chars):",
1396
1098
  contextInfo: "context: ~{total} of {max} ({pct}%) \xB7 system {sys} \xB7 tools {tools} \xB7 log {log}",
1397
1099
  compactStarting: "\u25B8 folding older turns into a summary\u2026",
1398
1100
  compactNoop: "\u25B8 nothing to fold \u2014 log already small or recent turns alone exceed the budget.",
@@ -1406,7 +1108,7 @@ var EN = {
1406
1108
  costLikely: " likely ({pct}% session cache hit): {input} input + ~{output} output \u2248 {total}",
1407
1109
  costLikelyCold: " likely: matches worst case until cache fills (no completed turns yet)",
1408
1110
  statusModel: " model {model}",
1409
- statusFlags: " flags harvest={harvest} \xB7 branch={branch} \xB7 stream={stream} \xB7 effort={effort}",
1111
+ statusFlags: " flags stream={stream} \xB7 effort={effort}",
1410
1112
  statusCtx: " ctx {bar} {used}/{max} ({pct}%)",
1411
1113
  statusCtxNone: " ctx no turns yet",
1412
1114
  statusCost: " cost ${cost} \xB7 cache {bar} {pct}% \xB7 turns {turns}",
@@ -1508,10 +1210,6 @@ var EN = {
1508
1210
  existsPinned: " pinned into the system prompt every launch as-is.",
1509
1211
  info: "\u25B8 /init \u2014 model will scan the project and synthesize REASONIX.md.\n The result lands as a pending edit; review with /apply or /walk."
1510
1212
  },
1511
- semantic: {
1512
- codeOnly: "/semantic is only available inside `reasonix code` (needs a project root).",
1513
- checking: "\u25B8 checking semantic_search status\u2026"
1514
- },
1515
1213
  webSearchEngine: {
1516
1214
  currentEngine: "Current web search engine: {engine}",
1517
1215
  endpoint: "SearXNG endpoint: {url}",
@@ -1608,21 +1306,16 @@ var zhCN = {
1608
1306
  resumeHint: "\u5F3A\u5236\u6062\u590D\u6307\u5B9A\u4F1A\u8BDD\uFF08\u5373\u4F7F\u7A7A\u95F2\uFF09",
1609
1307
  newHint: "\u5F3A\u5236\u521B\u5EFA\u65B0\u4F1A\u8BDD\uFF08\u5FFD\u7565 --session / --continue\uFF09",
1610
1308
  transcriptHint: "JSONL \u8F6C\u5F55\u7A3F\u7684\u5199\u5165\u8DEF\u5F84",
1611
- harvestHint: "\u542F\u7528 Pillar-2 \u8BA1\u5212\u72B6\u6001\u63D0\u53D6\uFF08\u6BCF\u8F6E\u989D\u5916\u6D88\u8017 1 \u6B21 flash \u8C03\u7528\uFF09",
1612
1309
  budgetHint: "\u4F1A\u8BDD\u7F8E\u5143\u4E0A\u9650 \u2014 80% \u65F6\u8B66\u544A\uFF0C100% \u65F6\u62D2\u7EDD\u4E0B\u4E00\u8F6E",
1613
1310
  modelIdHint: "DeepSeek \u6A21\u578B ID\uFF08\u4F8B\u5982 deepseek-v4-flash\uFF09",
1614
1311
  systemPromptHint: "\u8986\u76D6\u9ED8\u8BA4\u7CFB\u7EDF\u63D0\u793A\u8BCD",
1615
1312
  presetHint: "\u6A21\u578B\u7EC4\u5408 \u2014 auto|flash|pro",
1616
- harvestOptInHint: "\u542F\u7528 Pillar-2 \u8BA1\u5212\u72B6\u6001\u63D0\u53D6",
1617
- branchHint: "\u6BCF\u8F6E\u8FD0\u884C N \u4E2A\u5E76\u884C\u91C7\u6837\uFF08N>=2\uFF0C\u4EC5\u624B\u52A8\uFF09",
1618
1313
  sessionNameHint: "\u4F1A\u8BDD\u540D\u79F0\uFF08\u9ED8\u8BA4\uFF1A'default'\uFF09",
1619
1314
  ephemeralHint: "\u7981\u7528\u672C\u6B21\u8FD0\u884C\u7684\u4F1A\u8BDD\u6301\u4E45\u5316",
1620
1315
  mcpSpecHint: "MCP \u670D\u52A1\u5668\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF09",
1621
1316
  mcpPrefixHint: "\u7528\u6B64\u5B57\u7B26\u4E32\u4E3A MCP \u5DE5\u5177\u540D\u6DFB\u52A0\u524D\u7F00",
1622
1317
  noConfigHint: "\u672C\u6B21\u8FD0\u884C\u5FFD\u7565 ~/.reasonix/config.json",
1623
1318
  presetHintShort: "\u6A21\u578B\u7EC4\u5408 \u2014 auto|flash|pro",
1624
- harvestHintShort: "Pillar-2 \u8BA1\u5212\u72B6\u6001\u63D0\u53D6",
1625
- branchHintShort: "\u6BCF\u8F6E\u5E76\u884C\u91C7\u6837\u6570\uFF08N>=2\uFF09",
1626
1319
  budgetHintShort: "\u4F1A\u8BDD\u7F8E\u5143\u4E0A\u9650",
1627
1320
  transcriptHintShort: "JSONL \u8F6C\u5F55\u7A3F\u8DEF\u5F84",
1628
1321
  mcpSpecHintShort: "MCP \u670D\u52A1\u5668\u89C4\u683C\uFF08\u53EF\u91CD\u590D\uFF09",
@@ -1680,12 +1373,6 @@ var zhCN = {
1680
1373
  success: "\u8BED\u8A00\u5DF2\u5207\u6362\u4E3A\u7B80\u4F53\u4E2D\u6587\u3002",
1681
1374
  unsupported: "\u4E0D\u652F\u6301\u7684\u8BED\u8A00\u4EE3\u7801\uFF1A{code}\u3002\u652F\u6301\u7684\u8BED\u8A00\uFF1A{supported}\u3002"
1682
1375
  },
1683
- harvest: { description: "\u5207\u6362 Pillar-2 \u8BA1\u5212\u72B6\u6001\u63D0\u53D6", argsHint: "[on|off]" },
1684
- branch: { description: "\u6BCF\u8F6E\u8FD0\u884C N \u4E2A\u5E76\u884C\u91C7\u6837\uFF08N>=2\uFF09", argsHint: "<N|off>" },
1685
- effort: {
1686
- description: "reasoning_effort \u4E0A\u9650 \u2014 max \u4E3A\u9ED8\u8BA4\uFF08\u667A\u80FD\u4F53\u7EA7\uFF09\uFF0Chigh \u66F4\u4FBF\u5B9C/\u66F4\u5FEB",
1687
- argsHint: "<high|max>"
1688
- },
1689
1376
  pro: {
1690
1377
  description: "\u4EC5\u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 v4-pro\uFF08\u4E00\u6B21\u6027 \xB7 \u81EA\u52A8\u89E3\u9664\uFF09",
1691
1378
  argsHint: "[off]"
@@ -1703,7 +1390,6 @@ var zhCN = {
1703
1390
  description: "\u6D4F\u89C8 + \u83B7\u53D6 MCP \u63D0\u793A\uFF08\u65E0\u53C2\u6570 \u2192 \u5217\u51FA\u540D\u79F0\uFF1B<name> \u2192 \u6E32\u67D3\u63D0\u793A\uFF09",
1704
1391
  argsHint: "[name]"
1705
1392
  },
1706
- tool: { description: "\u8F6C\u50A8\u7B2C N \u4E2A\u5DE5\u5177\u8C03\u7528\u7684\u5B8C\u6574\u8F93\u51FA\uFF081=\u6700\u8FD1\uFF09", argsHint: "[N]" },
1707
1393
  memory: {
1708
1394
  description: "\u663E\u793A / \u7BA1\u7406\u56FA\u5B9A\u8BB0\u5FC6\uFF08REASONIX.md + ~/.reasonix/memory\uFF09",
1709
1395
  argsHint: "[list|show <name>|forget <name>|clear <scope> confirm]"
@@ -1735,7 +1421,6 @@ var zhCN = {
1735
1421
  doctor: {
1736
1422
  description: "\u5065\u5EB7\u68C0\u67E5\uFF08api / config / api-reach / index / hooks / project\uFF09"
1737
1423
  },
1738
- think: { description: "\u8F6C\u50A8\u6700\u8FD1\u4E00\u8F6E\u7684\u5B8C\u6574 R1 \u63A8\u7406\uFF08\u4EC5\u63A8\u7406\u6A21\u578B\uFF09" },
1739
1424
  context: { description: "\u663E\u793A\u4E0A\u4E0B\u6587\u7A97\u53E3\u5206\u89E3\uFF08\u7CFB\u7EDF / \u5DE5\u5177 / \u65E5\u5FD7 / \u8F93\u5165\uFF09" },
1740
1425
  retry: { description: "\u622A\u65AD\u5E76\u91CD\u53D1\u60A8\u7684\u6700\u540E\u4E00\u6761\u6D88\u606F\uFF08\u91CD\u65B0\u91C7\u6837\uFF09" },
1741
1426
  compact: {
@@ -1749,12 +1434,6 @@ var zhCN = {
1749
1434
  argsHint: "[N]"
1750
1435
  },
1751
1436
  sessions: { description: "\u5217\u51FA\u5DF2\u4FDD\u5B58\u7684\u4F1A\u8BDD\uFF08\u5F53\u524D\u6807\u8BB0\u4E3A \u25B8\uFF09" },
1752
- rename: { description: "\u91CD\u547D\u540D\u78C1\u76D8\u4E0A\u7684\u5F53\u524D\u4F1A\u8BDD", argsHint: "<new-name>" },
1753
- resume: {
1754
- description: "\u663E\u793A\u6062\u590D\u5DF2\u4FDD\u5B58\u4F1A\u8BDD\u7684\u542F\u52A8\u547D\u4EE4",
1755
- argsHint: "<name>"
1756
- },
1757
- forget: { description: "\u4ECE\u78C1\u76D8\u5220\u9664\u5F53\u524D\u4F1A\u8BDD" },
1758
1437
  setup: { description: "\u63D0\u9192\u60A8\u9000\u51FA\u5E76\u8FD0\u884C `reasonix setup`" },
1759
1438
  semantic: {
1760
1439
  description: "\u663E\u793A semantic_search \u72B6\u6001 \u2014 \u5DF2\u6784\u5EFA\uFF1FOllama \u5DF2\u5B89\u88C5\uFF1F\u5982\u4F55\u542F\u7528"
@@ -1802,9 +1481,6 @@ var zhCN = {
1802
1481
  description: "\u5207\u6362\u53EA\u8BFB\u8BA1\u5212\u6A21\u5F0F\uFF08\u5199\u5165\u88AB\u5F39\u56DE\u76F4\u5230 submit_plan + \u5BA1\u6279\uFF09",
1803
1482
  argsHint: "[on|off]"
1804
1483
  },
1805
- "apply-plan": {
1806
- description: "\u5F3A\u5236\u6279\u51C6\u5F85\u5904\u7406 / \u6587\u672C\u4E2D\u7684\u8BA1\u5212\uFF08\u5982\u679C\u9519\u8FC7\u4E86\u9009\u62E9\u5668\u65F6\u7684\u56DE\u9000\uFF09"
1807
- },
1808
1484
  mode: {
1809
1485
  description: "\u7F16\u8F91\u95E8\u63A7\uFF1Areview\uFF08\u6392\u961F\uFF09\xB7 auto\uFF08\u5E94\u7528+\u64A4\u6D88\uFF09\xB7 yolo\uFF08\u5E94\u7528+\u81EA\u52A8 shell\uFF09\u3002Shift+Tab \u5FAA\u73AF\u3002",
1810
1486
  argsHint: "[review|auto|yolo]"
@@ -1948,49 +1624,8 @@ var zhCN = {
1948
1624
  },
1949
1625
  handlers: {
1950
1626
  basic: {
1951
- clearInfo: "\u25B8 \u7EC8\u7AEF\u5DF2\u6E05\u9664\uFF08\u89C6\u53E3 + \u6EDA\u52A8\u56DE\u653E\uFF09\u3002\u4E0A\u4E0B\u6587\uFF08\u6D88\u606F\u65E5\u5FD7\uFF09\u5B8C\u597D\u65E0\u635F \u2014 \u4E0B\u4E00\u8F6E\u4ECD\u80FD\u770B\u5230\u6240\u6709\u5185\u5BB9\u3002\u4F7F\u7528 /new \u5168\u65B0\u5F00\u59CB\uFF0C\u6216 /forget \u5220\u9664\u6574\u4E2A\u4F1A\u8BDD\u3002",
1952
1627
  newInfo: "\u25B8 \u65B0\u5BF9\u8BDD \u2014 \u5DF2\u4ECE\u4E0A\u4E0B\u6587\u4E2D\u4E22\u5F03 {count} \u6761\u6D88\u606F\u3002\u540C\u4E00\u4F1A\u8BDD\uFF0C\u5168\u65B0\u5F00\u59CB\u3002",
1953
1628
  helpTitle: "\u547D\u4EE4\uFF1A",
1954
- helpHelp: " /help \u663E\u793A\u6B64\u6D88\u606F",
1955
- helpKeys: " /keys \u952E\u76D8\u5FEB\u6377\u952E + \u63D0\u793A\u524D\u7F00 (!, @, /)",
1956
- helpStatus: " /status \u663E\u793A\u5F53\u524D\u8BBE\u7F6E",
1957
- helpPreset: " /preset <auto|flash|pro> \u6A21\u578B\u7EC4\u5408 \u2014 \u89C1\u4E0B\u6587",
1958
- helpModel: " /model <id> deepseek-v4-flash \u6216 deepseek-v4-pro",
1959
- helpPro: " /pro [off] \u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 v4-pro\uFF08\u4E00\u6B21\u6027\uFF0C\u81EA\u52A8\u89E3\u9664\uFF09",
1960
- helpHarvest: " /harvest [on|off] Pillar 2\uFF1A\u7ED3\u6784\u5316\u8BA1\u5212\u72B6\u6001\u63D0\u53D6\uFF08\u53EF\u9009 \u2014 \u989D\u5916\u6536\u8D39\uFF09",
1961
- helpBranch: " /branch <N|off> \u8FD0\u884C N \u4E2A\u5E76\u884C\u91C7\u6837\uFF08N>=2\uFF09\u2014 \u4EC5\u624B\u52A8\uFF0CN \u500D\u6210\u672C",
1962
- helpEffort: " /effort <high|max> reasoning_effort \u4E0A\u9650\uFF08max=\u5B8C\u6574\u601D\u8003\uFF0Chigh=\u66F4\u4FBF\u5B9C/\u66F4\u5FEB\uFF09",
1963
- helpMcp: " /mcp \u5217\u51FA\u9644\u52A0\u5230\u6B64\u4F1A\u8BDD\u7684 MCP \u670D\u52A1\u5668 + \u5DE5\u5177",
1964
- helpResource: " /resource [uri] \u6D4F\u89C8 + \u8BFB\u53D6 MCP \u8D44\u6E90\uFF08\u65E0\u53C2\u6570 \u2192 \u5217\u51FA URI\uFF1B<uri> \u2192 \u83B7\u53D6\uFF09",
1965
- helpPrompt: " /prompt [name] \u6D4F\u89C8 + \u83B7\u53D6 MCP \u63D0\u793A\uFF08\u65E0\u53C2\u6570 \u2192 \u5217\u51FA\u540D\u79F0\uFF1B<name> \u2192 \u6E32\u67D3\uFF09",
1966
- helpCompact: " /compact \u6298\u53E0\u65E7\u8F6E\u6B21\u4E3A\u6458\u8981\uFF08cache-safe\uFF0C50% \u81EA\u52A8\u89E6\u53D1\uFF09",
1967
- helpThink: " /think \u8F6C\u50A8\u6700\u8FD1\u4E00\u8F6E\u7684\u5B8C\u6574 R1 \u63A8\u7406\uFF08\u4EC5\u63A8\u7406\u6A21\u578B\uFF09",
1968
- helpTool: " /tool [N] \u5217\u51FA\u5DE5\u5177\u8C03\u7528\uFF08\u6216\u8F6C\u50A8\u7B2C N \u4E2A\u7684\u5B8C\u6574\u8F93\u51FA\uFF0C1=\u6700\u8FD1\uFF09",
1969
- helpCost: " /cost [text] \u7A7A \u2192 \u4E0A\u4E00\u8F6E\u82B1\u8D39\uFF1B\u5E26\u6587\u672C \u2192 \u4F30\u7B97\u53D1\u9001\u6210\u672C",
1970
- helpMemory: " /memory [sub] \u663E\u793A\u56FA\u5B9A\u8BB0\u5FC6\uFF08REASONIX.md + ~/.reasonix/memory\uFF09\u3002",
1971
- helpMemorySub: " \u5B50\u547D\u4EE4\uFF1Alist | show <name> | forget <name> | clear <scope> confirm",
1972
- helpSkill: " /skill [sub] \u5217\u51FA / \u8FD0\u884C\u7528\u6237\u6280\u80FD\uFF08project/.reasonix/skills + ~/.reasonix/skills\uFF09\u3002",
1973
- helpSkillSub: " \u5B50\u547D\u4EE4\uFF1Alist | show <name> | <name> [args]\uFF08\u5C06\u6280\u80FD\u4F53\u6CE8\u5165\u4E3A\u7528\u6237\u8F6E\u6B21\uFF09",
1974
- helpRetry: " /retry \u622A\u65AD\u5E76\u91CD\u53D1\u60A8\u7684\u6700\u540E\u4E00\u6761\u6D88\u606F\uFF08\u6A21\u578B\u91CD\u65B0\u91C7\u6837\uFF09",
1975
- helpApply: " /apply [N|1,3|1-4] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u63D0\u4EA4\u5F85\u5904\u7406\u7684\u7F16\u8F91\u5757\uFF08\u65E0\u53C2\u6570 \u2192 \u5168\u90E8\uFF1B\u7D22\u5F15 \u2192 \u5B50\u96C6\uFF09",
1976
- helpDiscard: " /discard [N|1,3|1-4] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u4E22\u5F03\u5F85\u5904\u7406\u7684\u7F16\u8F91\uFF08\u65E0\u53C2\u6570 \u2192 \u5168\u90E8\uFF1B\u7D22\u5F15 \u2192 \u5B50\u96C6\uFF09",
1977
- helpWalk: " /walk \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u9010\u5757\u9010\u6B65\u5904\u7406\u5F85\u5904\u7406\u7684\u7F16\u8F91\uFF08\u6BCF\u5757 y/n\uFF0Ca \u5E94\u7528\u5269\u4F59\uFF0CA \u5207\u6362 AUTO\uFF09",
1978
- helpUndo: " /undo \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u56DE\u6EDA\u6700\u8FD1\u672A\u64A4\u6D88\u7684\u7F16\u8F91\u6279\u5904\u7406",
1979
- helpHistory: " /history \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u5217\u51FA\u6B64\u4F1A\u8BDD\u7684\u6BCF\u4E2A\u7F16\u8F91\u6279\u5904\u7406",
1980
- helpShow: " /show [id] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u8F6C\u50A8\u5B58\u50A8\u7684\u7F16\u8F91\u5DEE\u5F02\uFF08\u7701\u7565 id \u65F6\u4E3A\u6700\u65B0\uFF09",
1981
- helpCommit: ' /commit "msg" \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09git add -A && git commit -m "msg"',
1982
- helpPlan: " /plan [on|off] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u5207\u6362\u53EA\u8BFB\u8BA1\u5212\u6A21\u5F0F\uFF1B\u5199\u5165\u9700\u7ECF submit_plan + \u5BA1\u6279",
1983
- helpApplyPlan: " /apply-plan \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u5F3A\u5236\u6279\u51C6\u5F85\u5904\u7406/\u6587\u672C\u4E2D\u7684\u8BA1\u5212\uFF08\u56DE\u9000\uFF09",
1984
- helpMode: " /mode [review|auto|yolo] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09review = \u6392\u961F \xB7 auto = \u5E94\u7528+\u64A4\u6D88\u6A2A\u5E45 \xB7 yolo = \u5E94\u7528+\u81EA\u52A8 shell\u3002Shift+Tab \u5FAA\u73AF\u5207\u6362\u3002",
1985
- helpJobs: " /jobs \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u5217\u51FA\u540E\u53F0\u8FDB\u7A0B\uFF08run_background\uFF09\u2014 \u8FD0\u884C\u4E2D\u548C\u5DF2\u9000\u51FA",
1986
- helpKill: " /kill <id> \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u6309 ID \u505C\u6B62\u540E\u53F0\u4F5C\u4E1A\uFF08SIGTERM \u2192 SIGKILL\uFF09",
1987
- helpLogs: " /logs <id> [lines] \uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u8DDF\u8E2A\u540E\u53F0\u4F5C\u4E1A\u8F93\u51FA\uFF08\u9ED8\u8BA4\u6700\u540E 80 \u884C\uFF09",
1988
- helpSessions: " /sessions \u5217\u51FA\u5DF2\u4FDD\u5B58\u7684\u4F1A\u8BDD\uFF08\u5F53\u524D\u6807\u8BB0\u4E3A \u25B8\uFF09",
1989
- helpForget: " /forget \u4ECE\u78C1\u76D8\u5220\u9664\u5F53\u524D\u4F1A\u8BDD",
1990
- helpNew: " /new \u5168\u65B0\u5F00\u59CB\uFF1A\u4E22\u5F03\u6240\u6709\u4E0A\u4E0B\u6587 + \u6E05\u9664\u6EDA\u52A8\u56DE\u653E",
1991
- helpClear: " /clear \u4EC5\u6E05\u9664\u663E\u793A\u7684\u6EDA\u52A8\u56DE\u653E\uFF08\u4E0A\u4E0B\u6587\u4FDD\u7559 \u2014 \u6A21\u578B\u4ECD\u80FD\u770B\u5230\uFF09",
1992
- helpLoop: " /loop <interval> <prompt> \u6BCF <interval> \u81EA\u52A8\u91CD\u65B0\u63D0\u4EA4 <prompt>\uFF085\u79D2..6\u5C0F\u65F6\uFF09\u3002/loop stop \xB7 \u8F93\u5165\u4EFB\u4F55\u5185\u5BB9\u53D6\u6D88\u3002",
1993
- helpExit: " /exit \u9000\u51FA\uFF08\u522B\u540D\uFF1A/quit, /q\uFF09",
1994
1629
  helpShellTitle: "Shell \u5FEB\u6377\u65B9\u5F0F\uFF1A",
1995
1630
  helpShell: " !<cmd> \u5728\u6C99\u7BB1\u6839\u76EE\u5F55\u8FD0\u884C <cmd>\uFF1B\u8F93\u51FA\u8FDB\u5165\u5BF9\u8BDD",
1996
1631
  helpShellDetail: " \u4EE5\u4FBF\u6A21\u578B\u5728\u4E0B\u4E00\u8F6E\u770B\u5230\u3002\u65E0\u5141\u8BB8\u5217\u8868\u9650\u5236\u3002",
@@ -2017,46 +1652,6 @@ var zhCN = {
2017
1652
  helpSessionsTitle: "\u4F1A\u8BDD\uFF08\u9ED8\u8BA4\u81EA\u52A8\u542F\u7528\uFF0C\u547D\u540D\u4E3A 'default'\uFF09\uFF1A",
2018
1653
  helpSessionCustom: " reasonix chat --session <name> \u4F7F\u7528\u4E0D\u540C\u7684\u547D\u540D\u4F1A\u8BDD",
2019
1654
  helpSessionNone: " reasonix chat --no-session \u7981\u7528\u672C\u6B21\u8FD0\u884C\u7684\u6301\u4E45\u5316",
2020
- helpLimitationTitle: "\u5DF2\u77E5\u9650\u5236\uFF1A",
2021
- helpLimitation1: " \u5728\u4F1A\u8BDD\u4E2D\u9014\u8C03\u6574\u7EC8\u7AEF\u5927\u5C0F\u53EF\u80FD\u4F1A\u5728\u6EDA\u52A8\u56DE\u653E\u4E2D\u5806\u53E0\u5E7D\u7075\u6807\u9898\u5E27",
2022
- helpLimitation2: " \uFF08Ink \u5E93\u7684\u6D3B\u52A8\u533A\u57DF\u6E05\u9664\u672A\u8003\u8651\u65B0\u5BBD\u5EA6\u4E0B\u7684\u884C\u91CD\u6392\uFF09\u3002",
2023
- helpLimitation3: " \u6EDA\u52A8\u5386\u53F2\u4E0D\u53D7\u5F71\u54CD\uFF1B\u8BE5\u7455\u75B5\u7EAF\u5C5E\u89C6\u89C9\u95EE\u9898\uFF0C",
2024
- helpLimitation4: " \u4E0B\u6B21 /clear \u65F6\u6E05\u9664\u3002",
2025
- keysTitle: "\u952E\u76D8\u548C\u63D0\u793A\u5FEB\u6377\u952E\uFF1A",
2026
- keysEnter: " Enter \u63D0\u4EA4\u5F53\u524D\u63D0\u793A",
2027
- keysNewline: " Shift+Enter / Ctrl+J \u63D2\u5165\u6362\u884C\uFF08\u591A\u884C\u63D0\u793A\uFF09",
2028
- keysContinue: " \\<Enter> bash \u98CE\u683C\u7684\u884C\u7EE7\u7EED",
2029
- keysArrow: " \u2190 \u2192 \u2191 \u2193 \u79FB\u52A8\u5149\u6807 / \u5728\u7F13\u51B2\u533A\u8FB9\u754C\u53EC\u56DE\u5386\u53F2",
2030
- keysPage: " PageUp / PageDown \u8DF3\u8F6C\u5230\u6574\u4E2A\u7F13\u51B2\u533A\u7684\u9876\u90E8/\u5E95\u90E8\uFF08\u5927\u6BB5\u7C98\u8D34\u540E\u5F88\u6709\u7528\uFF09",
2031
- keysHomeEnd: " Ctrl+A / Ctrl+E \u8DF3\u8F6C\u5230\u5F53\u524D\u884C\u7684\u5F00\u5934/\u7ED3\u5C3E",
2032
- keysClearLine: " Ctrl+U \u6E05\u9664\u6574\u4E2A\u8F93\u5165\u7F13\u51B2\u533A",
2033
- keysDeleteWord: " Ctrl+W \u5220\u9664\u5149\u6807\u524D\u7684\u5355\u8BCD",
2034
- keysBackspace: " Backspace \u5411\u5DE6\u5220\u9664\uFF1BDelete \u5220\u9664\u5149\u6807\u4E0B\u7684\u5B57\u7B26",
2035
- keysEsc: " Esc \u4E2D\u6B62\u6B63\u5728\u8FDB\u884C\u7684\u8F6E\u6B21",
2036
- keysEditYn: " y / n \u63A5\u53D7/\u62D2\u7EDD\u5F85\u5904\u7406\u7684\u7F16\u8F91\uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09",
2037
- keysEditTab: " Shift+Tab \u5FAA\u73AF\u7F16\u8F91\u95E8\u63A7\uFF1Areview \u2194 AUTO\uFF08\u4EE3\u7801\u6A21\u5F0F\uFF0C\u6301\u4E45\u5316\u5230\u914D\u7F6E\uFF09",
2038
- keysEditUndo: " u \u64A4\u6D88\u6700\u8FD1\u672A\u64A4\u6D88\u7684\u7F16\u8F91\u6279\u5904\u7406\uFF08\u4F1A\u8BDD\u8303\u56F4\uFF0C\u975E\u4EC5\u6A2A\u5E45\uFF09",
2039
- keysPromptTitle: "\u63D0\u793A\u524D\u7F00\uFF1A",
2040
- keysSlash: " /<name> \u659C\u6760\u547D\u4EE4\uFF1BTab/Enter \u4ECE\u5EFA\u8BAE\u5217\u8868\u4E2D\u9009\u62E9",
2041
- keysAtFile: " @<path> \u5C06\u6587\u4EF6\u5185\u8054\u5230 [Referenced files] \u4E0B\uFF08\u4EE3\u7801\u6A21\u5F0F\uFF09\u3002",
2042
- keysAtFilePicker: " \u5C3E\u90E8 `@\u2026` \u6253\u5F00\u6587\u4EF6\u9009\u62E9\u5668\uFF1B\u2191/\u2193 \u5BFC\u822A\uFF0CTab/Enter \u9009\u62E9\u3002",
2043
- keysAtUrl: " @https://... \u83B7\u53D6 URL\uFF0C\u5265\u79BB HTML\uFF0C\u5185\u8054\u5230 [Referenced URLs] \u4E0B\u3002",
2044
- keysAtUrlCache: " \u6BCF\u4F1A\u8BDD\u7F13\u5B58 \u2014 \u76F8\u540C URL \u83B7\u53D6\u4E24\u6B21\u53EA\u53D6\u4E00\u6B21\u3002",
2045
- keysBang: " !<cmd> \u5728\u6C99\u7BB1\u6839\u76EE\u5F55\u8FD0\u884C <cmd>\uFF1B\u8F93\u51FA\u8FDB\u5165\u4E0A\u4E0B\u6587",
2046
- keysBangDetail: " \u4EE5\u4FBF\u6A21\u578B\u5728\u4E0B\u4E00\u8F6E\u770B\u5230\u3002\u65E0\u5141\u8BB8\u5217\u8868\u9650\u5236\u3002",
2047
- keysHash: " #<note> \u5C06 <note> \u8FFD\u52A0\u5230 <project>/REASONIX.md\uFF08\u53EF\u63D0\u4EA4\uFF0C\u56E2\u961F\u5171\u4EAB\uFF09\u3002",
2048
- keysHashGlobal: " #g <note> \u5C06 <note> \u8FFD\u52A0\u5230 ~/.reasonix/REASONIX.md\uFF08\u5168\u5C40\uFF0C\u4E0D\u63D0\u4EA4\uFF09\u3002",
2049
- keysHashBoth: " \u4E24\u8005\u90FD\u56FA\u5B9A\u5230\u6BCF\u4E2A\u672A\u6765\u4F1A\u8BDD\u7684\u4E0D\u53EF\u53D8\u524D\u7F00\u4E2D\u3002",
2050
- keysHashEscape: " \u4F7F\u7528 `\\#literal` \u5982\u679C\u60A8\u786E\u5B9E\u60F3\u53D1\u9001 `#` \u6807\u9898\u7ED9\u6A21\u578B\u3002",
2051
- keysPickersTitle: "\u9009\u62E9\u5668\uFF08\u659C\u6760 + @\u63D0\u53CA\uFF09\uFF1A",
2052
- keysPickerNav: " \u2191 / \u2193 \u5BFC\u822A\u5EFA\u8BAE\u5217\u8868",
2053
- keysPickerTab: " Tab \u63D2\u5165\u9AD8\u4EAE\u9879\u76EE\u4F46\u4E0D\u63D0\u4EA4",
2054
- keysPickerEnter: " Enter \u63D2\u5165\u5E76\uFF08\u659C\u6760\uFF09\u8FD0\u884C\uFF0C\uFF08@\uFF09\u7EE7\u7EED\u7F16\u8F91",
2055
- keysMcpTitle: "MCP \u63A2\u7D22\uFF1A",
2056
- keysMcpServers: " /mcp \u670D\u52A1\u5668 + \u5DE5\u5177/\u8D44\u6E90/\u63D0\u793A\u8BA1\u6570",
2057
- keysMcpResource: " /resource [uri] \u6D4F\u89C8\u5E76\u8BFB\u53D6 MCP \u670D\u52A1\u5668\u66B4\u9732\u7684\u8D44\u6E90",
2058
- keysMcpPrompt: " /prompt [name] \u6D4F\u89C8\u5E76\u83B7\u53D6 MCP \u670D\u52A1\u5668\u66B4\u9732\u7684\u63D0\u793A",
2059
- keysUseful: "\u5E38\u7528\u659C\u6760\u547D\u4EE4\uFF1A/help \xB7 /context \xB7 /stats \xB7 /compact \xB7 /new \xB7 /exit",
2060
1655
  retryNone: "\u6CA1\u6709\u53EF\u91CD\u8BD5\u7684\u5185\u5BB9 \u2014 \u6B64\u4F1A\u8BDD\u65E5\u5FD7\u4E2D\u6CA1\u6709\u5148\u524D\u7684\u7528\u6237\u6D88\u606F\u3002",
2061
1656
  retryInfo: '\u25B8 \u91CD\u8BD5\u4E2D\uFF1A"{preview}"',
2062
1657
  loopTuiOnly: "/loop \u4EC5\u5728\u4EA4\u4E92\u5F0F TUI \u4E2D\u53EF\u7528\uFF08\u4E0D\u5728 run/replay \u4E2D\uFF09\u3002",
@@ -2106,9 +1701,6 @@ var zhCN = {
2106
1701
  planCodeOnly: "/plan \u4EC5\u5728 `reasonix code` \u4E2D\u53EF\u7528 \u2014 \u804A\u5929\u6A21\u5F0F\u4E0D\u9650\u5236\u5DE5\u5177\u5199\u5165\u3002",
2107
1702
  planOn: "\u25B8 \u8BA1\u5212\u6A21\u5F0F\u5F00\u542F \u2014 \u5199\u5165\u5DE5\u5177\u88AB\u9650\u5236\uFF1B\u6A21\u578B\u5FC5\u987B\u5148\u8C03\u7528 `submit_plan` \u624D\u80FD\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002\uFF08\u6A21\u578B\u4E5F\u53EF\u4EE5\u5728\u8BA1\u5212\u6A21\u5F0F\u5173\u95ED\u65F6\u81EA\u4E3B\u8C03\u7528 submit_plan \u5904\u7406\u5927\u578B\u4EFB\u52A1 \u2014 \u6B64\u5F00\u5173\u662F\u66F4\u5F3A\u7684\u663E\u5F0F\u7EA6\u675F\u3002\uFF09\u8F93\u5165 /plan off \u9000\u51FA\u3002",
2108
1703
  planOff: "\u25B8 \u8BA1\u5212\u6A21\u5F0F\u5173\u95ED \u2014 \u5199\u5165\u5DE5\u5177\u518D\u6B21\u53EF\u7528\u3002\u6A21\u578B\u4ECD\u53EF\u4E3A\u5927\u578B\u4EFB\u52A1\u81EA\u4E3B\u63D0\u51FA\u8BA1\u5212\u3002",
2109
- applyPlanCodeOnly: "/apply-plan \u4EC5\u5728 `reasonix code` \u4E2D\u53EF\u7528\u3002",
2110
- applyPlanInfo: "\u25B8 \u8BA1\u5212\u5DF2\u6279\u51C6 \u2014 \u6B63\u5728\u6267\u884C",
2111
- applyPlanResubmit: "\u4E0A\u65B9\u7684\u8BA1\u5212\u5DF2\u88AB\u6279\u51C6\u3002\u7ACB\u5373\u6267\u884C\u3002\u60A8\u5DF2\u9000\u51FA\u8BA1\u5212\u6A21\u5F0F \u2014 \u6839\u636E\u9700\u8981\u4F7F\u7528 edit_file / write_file / run_command\u3002\u9664\u975E\u53D1\u73B0\u5177\u4F53\u539F\u56E0\uFF0C\u5426\u5219\u8BF7\u9075\u5FAA\u8BA1\u5212\uFF1B\u5982\u679C\u786E\u5B9E\u9700\u8981\u504F\u79BB\uFF0C\u8BF7\u544A\u77E5\u5E76\u7B49\u5F85\u56DE\u590D\u540E\u518D\u8FDB\u884C\u3002",
2112
1704
  modeCodeOnly: "/mode \u4EC5\u5728 `reasonix code` \u4E2D\u53EF\u7528\u3002",
2113
1705
  modeUsage: "\u7528\u6CD5\uFF1A/mode <review|auto|yolo> \uFF08Shift+Tab \u4E5F\u53EF\u5FAA\u73AF\uFF09",
2114
1706
  modeYolo: "\u25B8 \u7F16\u8F91\u6A21\u5F0F\uFF1AYOLO \u2014 \u7F16\u8F91\u548C Shell \u547D\u4EE4\u81EA\u52A8\u8FD0\u884C\uFF0C\u65E0\u63D0\u793A\u3002/undo \u4ECD\u53EF\u56DE\u6EDA\u7F16\u8F91\u3002\u8BF7\u8C28\u614E\u4F7F\u7528\u3002",
@@ -2141,24 +1733,10 @@ var zhCN = {
2141
1733
  modelUsage: "\u7528\u6CD5\uFF1A/model <id> \uFF08{hint}\uFF09",
2142
1734
  modelNotInCatalog: "model \u2192 {id} \uFF08\u26A0 \u4E0D\u5728\u83B7\u53D6\u7684\u76EE\u5F55\u4E2D\uFF1A{list}\u3002\u5982\u679C\u8FD9\u662F\u9519\u8BEF\u7684\uFF0C\u4E0B\u6B21\u8C03\u7528\u5C06\u8FD4\u56DE 400 \u2014 \u8FD0\u884C /models \u5237\u65B0\u3002\uFF09",
2143
1735
  modelSet: "model \u2192 {id}",
2144
- modelsFetching: "\u6B63\u5728\u4ECE DeepSeek \u83B7\u53D6 /models\u2026 \u7A0D\u540E\u518D\u8FD0\u884C /models\u3002\u5982\u679C\u6301\u7EED\u4E3A\u7A7A\uFF0C\u60A8\u7684 API \u5BC6\u94A5\u53EF\u80FD\u7F3A\u5C11\u6743\u9650\u6216\u7F51\u7EDC\u88AB\u963B\u6B62\u3002",
2145
- modelsEmpty: "DeepSeek /models \u8FD4\u56DE\u4E86\u7A7A\u5217\u8868\u3002\u518D\u8BD5 /models\uFF0C\u6216\u5728 api-docs.deepseek.com \u68C0\u67E5\u60A8\u7684\u8D26\u6237\u72B6\u6001\u3002",
2146
- modelsHeader: "\u53EF\u7528\u6A21\u578B\uFF08DeepSeek /models \xB7 \u5171 {count} \u4E2A\uFF09\uFF1A",
2147
- modelsCurrent: "\u25B8 {id} \uFF08\u5F53\u524D\uFF09",
2148
- modelsSwitch: "\u5207\u6362\u65B9\u5F0F\uFF1A/model <id>",
2149
- harvestOn: "harvest \u2192 \u5F00\u542F \uFF08Pillar-2 \u8BA1\u5212\u72B6\u6001\u63D0\u53D6 \xB7 \u6BCF\u8F6E\u989D\u5916 1 \u6B21\u5EC9\u4EF7 flash \u8C03\u7528 \xB7 \u4EC5\u624B\u52A8\u9009\u62E9\uFF1B\u65E0\u9884\u8BBE\u4F1A\u5F00\u542F\u5B83\uFF09",
2150
- harvestOff: "harvest \u2192 \u5173\u95ED",
2151
1736
  presetAuto: "preset \u2192 auto \uFF08v4-flash \u2192 v4-pro \u5728\u56F0\u96BE\u8F6E\u6B21\u5207\u6362 \xB7 \u9ED8\u8BA4\uFF09",
2152
1737
  presetFlash: "preset \u2192 flash \uFF08\u59CB\u7EC8\u4F7F\u7528 v4-flash \xB7 \u6700\u4FBF\u5B9C \xB7 /pro \u4ECD\u53EF\u4E34\u65F6\u63D0\u5347\u4E00\u8F6E\uFF09",
2153
1738
  presetPro: "preset \u2192 pro \uFF08\u59CB\u7EC8\u4F7F\u7528 v4-pro \xB7 \u7EA6 3 \u500D flash \xB7 \u7528\u4E8E\u56F0\u96BE\u7684\u591A\u8F6E\u5DE5\u4F5C\uFF09",
2154
1739
  presetUsage: "\u7528\u6CD5\uFF1A/preset <auto|flash|pro>",
2155
- branchOff: "branch \u2192 \u5173\u95ED",
2156
- branchUsage: "\u7528\u6CD5\uFF1A/branch <N> \uFF08N>=2\uFF0C\u6216 'off'\uFF09",
2157
- branchCapped: "branch \u9884\u7B97\u4E0A\u9650\u4E3A 8\uFF0C\u9632\u6B62\u6210\u672C\u5931\u63A7",
2158
- branchSet: "branch \u2192 {n} \uFF08\u6BCF\u8F6E\u8FD0\u884C {n} \u4E2A\u5E76\u884C\u91C7\u6837 \xB7 {n} \u500D\u6BCF\u8F6E\u6210\u672C \xB7 \u7981\u7528\u6D41\u5F0F \xB7 \u4EC5\u624B\u52A8\uFF0C\u65E0\u9884\u8BBE\u542F\u7528\u5206\u652F\uFF09",
2159
- effortStatus: "reasoning_effort \u2192 {effort} \uFF08\u4F7F\u7528 /effort high \u66F4\u4FBF\u5B9C/\u66F4\u5FEB\uFF0C/effort max \u4E3A\u667A\u80FD\u4F53\u7EA7\u9ED8\u8BA4 \xB7 \u8DE8\u91CD\u542F\u6301\u4E45\u5316\uFF09",
2160
- effortUsage: "\u7528\u6CD5\uFF1A/effort <high|max>",
2161
- effortSet: "reasoning_effort \u2192 {effort}\uFF08\u5DF2\u6301\u4E45\u5316\uFF09",
2162
1740
  proNothingArmed: "\u672A\u542F\u7528 \u2014 /pro \u4E0D\u5E26\u53C2\u6570\u5C06\u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 pro",
2163
1741
  proDisarmed: "\u25B8 /pro \u5DF2\u89E3\u9664 \u2014 \u4E0B\u4E00\u8F6E\u56DE\u9000\u5230\u5F53\u524D\u9884\u8BBE",
2164
1742
  proUsage: "\u7528\u6CD5\uFF1A/pro \u4E3A\u4E0B\u4E00\u8F6E\u542F\u7528 pro\uFF08\u4E00\u6B21\u6027\uFF0C\u81EA\u52A8\u89E3\u9664\uFF09\n /pro off \u5728\u4E0B\u4E00\u8F6E\u524D\u53D6\u6D88\u542F\u7528\u72B6\u6001",
@@ -2170,18 +1748,6 @@ var zhCN = {
2170
1748
  budgetExhausted: "\u25B2 budget \u2192 ${cap} \u4F46\u5DF2\u82B1\u8D39 ${spent}\u3002\u4E0B\u4E00\u8F6E\u5C06\u88AB\u62D2\u7EDD \u2014 \u63D0\u9AD8\u4E0A\u9650\u4EE5\u7EE7\u7EED\uFF0C\u6216\u7ED3\u675F\u4F1A\u8BDD\u3002",
2171
1749
  budgetSet: "budget \u2192 ${cap} \uFF08\u8FC4\u4ECA\uFF1A${spent} \xB7 80% \u65F6\u8B66\u544A\uFF0C100% \u65F6\u62D2\u7EDD\u4E0B\u4E00\u8F6E \xB7 /budget off \u6E05\u9664\uFF09"
2172
1750
  },
2173
- sessions: {
2174
- forgetNoSession: "\u4E0D\u5728\u4F1A\u8BDD\u4E2D \u2014 \u65E0\u5185\u5BB9\u53EF\u9057\u5FD8",
2175
- forgetInfo: '\u25B8 \u5DF2\u5220\u9664\u4F1A\u8BDD "{name}" \u2014 \u5F53\u524D\u5C4F\u5E55\u4ECD\u663E\u793A\u5BF9\u8BDD\uFF0C\u4F46\u4E0B\u6B21\u542F\u52A8\u5C06\u5168\u65B0\u5F00\u59CB',
2176
- forgetFailed: '\u65E0\u6CD5\u5220\u9664\u4F1A\u8BDD "{name}"\uFF08\u5DF2\u6D88\u5931\uFF1F\uFF09',
2177
- renameUsage: "\u7528\u6CD5\uFF1A/rename <new-name>",
2178
- renameNoSession: "\u4E0D\u5728\u4F1A\u8BDD\u4E2D \u2014 \u65E0\u5185\u5BB9\u53EF\u91CD\u547D\u540D",
2179
- renameFailed: '\u65E0\u6CD5\u91CD\u547D\u540D \u2014 "{name}" \u5DF2\u5B58\u5728\u6216\u6E05\u7406\u540E\u4E0E\u5F53\u524D\u4F1A\u8BDD ID \u76F8\u540C',
2180
- renameInfo: '\u25B8 \u4F1A\u8BDD\u5DF2\u91CD\u547D\u540D\u4E3A \u2192 "{name}"\u3002\u91CD\u542F TUI \u4EE5\u4F7F\u7528\u65B0\u540D\u79F0\u3002',
2181
- resumeUsage: "\u7528\u6CD5\uFF1A/resume <session-name> \u2014 \u4F7F\u7528 /sessions \u5217\u51FA",
2182
- resumeNotFound: '\u6CA1\u6709\u540D\u4E3A "{name}" \u7684\u4F1A\u8BDD \u2014 \u4F7F\u7528 /sessions \u5217\u51FA',
2183
- resumeInfo: '\u25B8 \u8981\u6062\u590D "{name}"\uFF0C\u8BF7\u9000\u51FA\u5E76\u8FD0\u884C\uFF1Areasonix chat --session {name}\n \uFF08\u4F1A\u8BDD\u4E2D\u5207\u6362\u9700\u8981\u91CD\u542F\uFF0C\u4EE5\u4FBF\u6D88\u606F\u65E5\u5FD7\u53EF\u4EE5\u5E72\u51C0\u5730\u56DE\u9000\uFF09'
2184
- },
2185
1751
  permissions: {
2186
1752
  mutateCodeOnly: "/permissions add / remove / clear \u4EC5\u5728 `reasonix code` \u4E2D\u53EF\u7528 \u2014 \u5B83\u4EEC\u7F16\u8F91\u9879\u76EE\u8303\u56F4\u7684\u5141\u8BB8\u5217\u8868\uFF08`~/.reasonix/config.json` projects[<root>].shellAllowed\uFF09\u3002",
2187
1753
  addUsage: '\u7528\u6CD5\uFF1A/permissions add <prefix> \uFF08\u591A token \u53EF\u7528\uFF1A/permissions add "git push origin"\uFF09',
@@ -2223,13 +1789,6 @@ var zhCN = {
2223
1789
  starting: "\u25B8 \u6B63\u5728\u542F\u52A8\u4EEA\u8868\u677F\u670D\u52A1\u5668\u2026"
2224
1790
  },
2225
1791
  observability: {
2226
- thinkEmpty: "\u672A\u7F13\u5B58\u63A8\u7406\u5185\u5BB9\u3002`/think` \u663E\u793A\u6700\u8FD1\u4E00\u8F6E\u7684\u5B8C\u6574\u601D\u8003\u6A21\u5F0F\u601D\u7EF4 \u2014 \u4EC5\u601D\u8003\u6A21\u5F0F\u6A21\u578B\uFF08deepseek-v4-flash / -v4-pro / -reasoner\uFF09\u4EA7\u751F\u5B83\uFF0C\u4E14\u4EC5\u5728\u8F6E\u6B21\u5B8C\u6210\u540E\u3002",
2227
- thinkInfo: "\u21B3 \u5B8C\u6574\u601D\u8003\uFF08{count} \u5B57\u7B26\uFF09\uFF1A",
2228
- toolEmpty: "\u6B64\u4F1A\u8BDD\u4E2D\u5C1A\u65E0\u5DE5\u5177\u8C03\u7528\u3002`/tool` \u5728\u6A21\u578B\u5B9E\u9645\u4F7F\u7528\u5DE5\u5177\u540E\u5217\u51FA\u5B83\u4EEC\uFF1B`/tool N` \u8F6C\u50A8\u7B2C N \u4E2A\u6700\u8FD1\u7684\u5B8C\u6574\uFF08\u672A\u622A\u65AD\uFF09\u8F93\u51FA\u3002",
2229
- toolUsage: "\u7528\u6CD5\uFF1A/tool [N] \uFF08\u65E0\u53C2\u6570 \u2192 \u5217\u8868\uFF1BN=1 \u2192 \u6700\u8FD1\u7684\u5B8C\u6574\u7ED3\u679C\uFF0CN=2 \u2192 \u4E0A\u4E00\u4E2A\uFF0C\u2026\uFF09",
2230
- toolOob: "\u5386\u53F2\u4E2D\u4EC5\u6709 {count} \u6B21\u5DE5\u5177\u8C03\u7528 \u2014 \u8BF7\u6C42\u4E86 #{n}\u3002\u5C1D\u8BD5\u4E0D\u5E26\u53C2\u6570\u7684 /tool \u67E5\u770B\u5217\u8868\u3002",
2231
- toolNotFound: "\u65E0\u6CD5\u8BFB\u53D6\u5DE5\u5177\u8C03\u7528 #{n}",
2232
- toolInfo: "\u21B3 tool<{name}> #{n}\uFF08{chars} \u5B57\u7B26\uFF09\uFF1A",
2233
1792
  contextInfo: "\u4E0A\u4E0B\u6587\uFF1A~{total} / {max}\uFF08{pct}%\uFF09\xB7 \u7CFB\u7EDF {sys} \xB7 \u5DE5\u5177 {tools} \xB7 \u65E5\u5FD7 {log}",
2234
1793
  compactStarting: "\u25B8 \u6B63\u5728\u6298\u53E0\u65E7\u8F6E\u6B21\u4E3A\u6458\u8981\u2026",
2235
1794
  compactNoop: "\u25B8 \u65E0\u9700\u6298\u53E0 \u2014 \u65E5\u5FD7\u5DF2\u8DB3\u591F\u5C0F\uFF0C\u6216\u6700\u8FD1\u8F6E\u6B21\u672C\u8EAB\u5DF2\u8D85\u8FC7\u9884\u7B97\u3002",
@@ -2243,7 +1802,7 @@ var zhCN = {
2243
1802
  costLikely: " \u53EF\u80FD\uFF08{pct}% \u4F1A\u8BDD\u7F13\u5B58\u547D\u4E2D\uFF09\uFF1A{input} \u8F93\u5165 + ~{output} \u8F93\u51FA \u2248 {total}",
2244
1803
  costLikelyCold: " \u53EF\u80FD\uFF1A\u5728\u7F13\u5B58\u586B\u5145\u524D\u4E0E\u6700\u574F\u60C5\u51B5\u76F8\u540C\uFF08\u65E0\u5DF2\u5B8C\u6210\u7684\u8F6E\u6B21\uFF09",
2245
1804
  statusModel: " \u6A21\u578B {model}",
2246
- statusFlags: " \u6807\u5FD7 harvest={harvest} \xB7 branch={branch} \xB7 stream={stream} \xB7 effort={effort}",
1805
+ statusFlags: " \u6807\u5FD7 stream={stream} \xB7 effort={effort}",
2247
1806
  statusCtx: " \u4E0A\u4E0B\u6587 {bar} {used}/{max}\uFF08{pct}%\uFF09",
2248
1807
  statusCtxNone: " \u4E0A\u4E0B\u6587 \u5C1A\u65E0\u8F6E\u6B21",
2249
1808
  statusCost: " \u6210\u672C ${cost} \xB7 \u7F13\u5B58 {bar} {pct}% \xB7 \u8F6E\u6B21 {turns}",
@@ -2345,10 +1904,6 @@ var zhCN = {
2345
1904
  existsPinned: " \u56FA\u5B9A\u5230\u6BCF\u6B21\u542F\u52A8\u7684\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E2D\u3002",
2346
1905
  info: "\u25B8 /init \u2014 \u6A21\u578B\u5C06\u626B\u63CF\u9879\u76EE\u5E76\u5408\u6210 REASONIX.md\u3002\n \u7ED3\u679C\u5C06\u4F5C\u4E3A\u5F85\u5904\u7406\u7684\u7F16\u8F91\uFF1B\u4F7F\u7528 /apply \u6216 /walk \u5BA1\u67E5\u3002"
2347
1906
  },
2348
- semantic: {
2349
- codeOnly: "/semantic \u4EC5\u5728 `reasonix code` \u4E2D\u53EF\u7528\uFF08\u9700\u8981\u9879\u76EE\u6839\u76EE\u5F55\uFF09\u3002",
2350
- checking: "\u25B8 \u6B63\u5728\u68C0\u67E5 semantic_search \u72B6\u6001\u2026"
2351
- },
2352
1907
  webSearchEngine: {
2353
1908
  currentEngine: "\u5F53\u524D\u7F51\u9875\u641C\u7D22\u5F15\u64CE\uFF1A{engine}",
2354
1909
  endpoint: "SearXNG \u7AEF\u70B9\uFF1A{url}",
@@ -3579,16 +3134,6 @@ var ContextManager = class {
3579
3134
  }
3580
3135
  };
3581
3136
 
3582
- // src/loop/branch.ts
3583
- function summarizeBranch(chosen, samples) {
3584
- return {
3585
- budget: samples.length,
3586
- chosenIndex: chosen.index,
3587
- uncertainties: samples.map((s) => s.planState.uncertainties.length),
3588
- temperatures: samples.map((s) => s.temperature)
3589
- };
3590
- }
3591
-
3592
3137
  // src/loop/errors.ts
3593
3138
  function formatLoopError(err, probe) {
3594
3139
  const msg = err.message ?? "";
@@ -4351,13 +3896,9 @@ var CacheFirstLoop = class {
4351
3896
  stats = new SessionStats();
4352
3897
  repair;
4353
3898
  // Mutable via configure() — slash commands in the TUI / library callers tweak
4354
- // these mid-session so users don't have to restart to try harvest or branch.
3899
+ // these mid-session so users don't have to restart.
4355
3900
  model;
4356
3901
  stream;
4357
- harvestEnabled;
4358
- harvestOptions;
4359
- branchEnabled;
4360
- branchOptions;
4361
3902
  reasoningEffort;
4362
3903
  autoEscalate = true;
4363
3904
  budgetUsd;
@@ -4395,19 +3936,8 @@ var CacheFirstLoop = class {
4395
3936
  this.hooks = opts.hooks ?? [];
4396
3937
  this.hookCwd = opts.hookCwd ?? process.cwd();
4397
3938
  this.confirmationGate = opts.confirmationGate ?? pauseGate;
4398
- if (typeof opts.branch === "number") {
4399
- this.branchOptions = { budget: opts.branch };
4400
- } else if (opts.branch && typeof opts.branch === "object") {
4401
- this.branchOptions = opts.branch;
4402
- } else {
4403
- this.branchOptions = {};
4404
- }
4405
- this.branchEnabled = (this.branchOptions.budget ?? 1) > 1;
4406
- const harvestForced = this.branchEnabled;
4407
- this.harvestEnabled = harvestForced || opts.harvest === true || typeof opts.harvest === "object" && opts.harvest !== null;
4408
- this.harvestOptions = typeof opts.harvest === "object" && opts.harvest !== null ? opts.harvest : this.branchOptions.harvestOptions ?? {};
4409
3939
  this._streamPreference = opts.stream ?? true;
4410
- this.stream = this.branchEnabled ? false : this._streamPreference;
3940
+ this.stream = this._streamPreference;
4411
3941
  const allowedNames = /* @__PURE__ */ new Set([...this.prefix.toolSpecs.map((s) => s.function.name)]);
4412
3942
  const registry = this.tools;
4413
3943
  const isMutating = (call) => {
@@ -4525,29 +4055,12 @@ var CacheFirstLoop = class {
4525
4055
  }
4526
4056
  configure(opts) {
4527
4057
  if (opts.model !== void 0) this.model = opts.model;
4528
- if (opts.stream !== void 0) this._streamPreference = opts.stream;
4058
+ if (opts.stream !== void 0) {
4059
+ this._streamPreference = opts.stream;
4060
+ this.stream = opts.stream;
4061
+ }
4529
4062
  if (opts.reasoningEffort !== void 0) this.reasoningEffort = opts.reasoningEffort;
4530
4063
  if (opts.autoEscalate !== void 0) this.autoEscalate = opts.autoEscalate;
4531
- if (opts.branch !== void 0) {
4532
- if (typeof opts.branch === "number") {
4533
- this.branchOptions = { budget: opts.branch };
4534
- } else if (opts.branch && typeof opts.branch === "object") {
4535
- this.branchOptions = opts.branch;
4536
- } else {
4537
- this.branchOptions = {};
4538
- }
4539
- this.branchEnabled = (this.branchOptions.budget ?? 1) > 1;
4540
- }
4541
- if (opts.harvest !== void 0) {
4542
- const want = opts.harvest === true || typeof opts.harvest === "object" && opts.harvest !== null;
4543
- this.harvestEnabled = want || this.branchEnabled;
4544
- if (typeof opts.harvest === "object" && opts.harvest !== null) {
4545
- this.harvestOptions = opts.harvest;
4546
- }
4547
- } else if (this.branchEnabled) {
4548
- this.harvestEnabled = true;
4549
- }
4550
- this.stream = this.branchEnabled ? false : this._streamPreference;
4551
4064
  }
4552
4065
  /** `null` disables the cap; any change re-arms the 80% warning. */
4553
4066
  setBudget(usd) {
@@ -4789,89 +4302,8 @@ ${reason}`
4789
4302
  let reasoningContent = "";
4790
4303
  let toolCalls = [];
4791
4304
  let usage = null;
4792
- let branchSummary;
4793
- let preHarvestedPlanState;
4794
4305
  try {
4795
- if (this.branchEnabled) {
4796
- const budget = this.branchOptions.budget ?? 1;
4797
- yield {
4798
- turn: this._turn,
4799
- role: "branch_start",
4800
- content: "",
4801
- branchProgress: {
4802
- completed: 0,
4803
- total: budget,
4804
- latestIndex: -1,
4805
- latestTemperature: -1,
4806
- latestUncertainties: -1
4807
- }
4808
- };
4809
- const queue = [];
4810
- let waiter = null;
4811
- const onSampleDone = (sample) => {
4812
- if (waiter) {
4813
- const w = waiter;
4814
- waiter = null;
4815
- w(sample);
4816
- } else {
4817
- queue.push(sample);
4818
- }
4819
- };
4820
- const callModel = this.modelForCurrentCall();
4821
- const branchPromise = runBranches(
4822
- this.client,
4823
- {
4824
- model: callModel,
4825
- messages,
4826
- tools: toolSpecs.length ? toolSpecs : void 0,
4827
- signal,
4828
- thinking: thinkingModeForModel(callModel),
4829
- reasoningEffort: this.reasoningEffort
4830
- },
4831
- {
4832
- ...this.branchOptions,
4833
- harvestOptions: this.harvestOptions,
4834
- onSampleDone
4835
- }
4836
- );
4837
- for (let k = 0; k < budget; k++) {
4838
- const sample = queue.shift() ?? await new Promise((resolve10) => {
4839
- waiter = resolve10;
4840
- });
4841
- yield {
4842
- turn: this._turn,
4843
- role: "branch_progress",
4844
- content: "",
4845
- branchProgress: {
4846
- completed: k + 1,
4847
- total: budget,
4848
- latestIndex: sample.index,
4849
- latestTemperature: sample.temperature,
4850
- latestUncertainties: sample.planState.uncertainties.length
4851
- }
4852
- };
4853
- }
4854
- const result = await branchPromise;
4855
- assistantContent = result.chosen.response.content;
4856
- reasoningContent = result.chosen.response.reasoningContent ?? "";
4857
- toolCalls = result.chosen.response.toolCalls;
4858
- const agg = aggregateBranchUsage(result.samples);
4859
- usage = new Usage(
4860
- agg.promptTokens,
4861
- agg.completionTokens,
4862
- agg.totalTokens,
4863
- agg.promptCacheHitTokens,
4864
- agg.promptCacheMissTokens
4865
- );
4866
- preHarvestedPlanState = result.chosen.planState;
4867
- branchSummary = summarizeBranch(result.chosen, result.samples);
4868
- yield {
4869
- turn: this._turn,
4870
- role: "branch_done",
4871
- content: "",
4872
- branch: branchSummary
4873
- };
4874
- } else if (this.stream) {
4306
+ if (this.stream) {
4875
4307
  const callBuf = /* @__PURE__ */ new Map();
4876
4308
  const readyIndices = /* @__PURE__ */ new Set();
4877
4309
  const callModel = this.modelForCurrentCall();
@@ -5001,8 +4433,6 @@ ${reason}`
5001
4433
  reasoningContent = "";
5002
4434
  toolCalls = [];
5003
4435
  usage = null;
5004
- branchSummary = void 0;
5005
- preHarvestedPlanState = void 0;
5006
4436
  iter--;
5007
4437
  continue;
5008
4438
  }
@@ -5016,14 +4446,6 @@ ${reason}`
5016
4446
  pendingUser = null;
5017
4447
  }
5018
4448
  this.scratch.reasoning = reasoningContent || null;
5019
- if (!preHarvestedPlanState && this.harvestEnabled && (reasoningContent?.trim().length ?? 0) >= 40) {
5020
- yield {
5021
- turn: this._turn,
5022
- role: "status",
5023
- content: t("loop.harvestStatus")
5024
- };
5025
- }
5026
- const planState = preHarvestedPlanState ? preHarvestedPlanState : this.harvestEnabled ? await harvest(reasoningContent || null, this.client, this.harvestOptions, signal) : emptyPlanState();
5027
4449
  const { calls: repairedCalls, report } = this.repair.process(
5028
4450
  toolCalls,
5029
4451
  reasoningContent || null,
@@ -5042,9 +4464,7 @@ ${reason}`
5042
4464
  role: "assistant_final",
5043
4465
  content: assistantContent,
5044
4466
  stats: turnStats,
5045
- planState,
5046
- repair: report,
5047
- branch: branchSummary
4467
+ repair: report
5048
4468
  };
5049
4469
  if (this.noteToolFailureSignal("", report)) {
5050
4470
  yield {
@@ -5278,6 +4698,7 @@ function ignoredByLayers(layers, abs, isDir) {
5278
4698
 
5279
4699
  // src/at-mentions.ts
5280
4700
  var DEFAULT_AT_MENTION_MAX_BYTES = 64 * 1024;
4701
+ var DEFAULT_AT_DIR_MAX_ENTRIES = 200;
5281
4702
  var DEFAULT_PICKER_IGNORE_DIRS = [
5282
4703
  "node_modules",
5283
4704
  ".git",
@@ -5333,6 +4754,16 @@ function listFilesWithStatsSync(root, opts = {}) {
5333
4754
  } catch {
5334
4755
  }
5335
4756
  out.push({ path: relPath, mtimeMs });
4757
+ } else if (ent.isSymbolicLink()) {
4758
+ let target = null;
4759
+ try {
4760
+ target = statSync2(absPath);
4761
+ } catch {
4762
+ continue;
4763
+ }
4764
+ if (!target.isFile()) continue;
4765
+ if (ignoredByLayers(effectiveLayers, absPath, false)) continue;
4766
+ out.push({ path: relPath, mtimeMs: target.mtimeMs });
5336
4767
  }
5337
4768
  }
5338
4769
  };
@@ -5373,7 +4804,7 @@ async function listFilesWithStatsAsync(root, opts = {}) {
5373
4804
  if (out.length >= maxResults) return;
5374
4805
  }
5375
4806
  await walk2(absPath, relPath, effectiveLayers);
5376
- } else if (ent.isFile()) {
4807
+ } else if (ent.isFile() || ent.isSymbolicLink()) {
5377
4808
  fileEnts.push(ent);
5378
4809
  }
5379
4810
  }
@@ -5393,14 +4824,18 @@ async function statBatch(ents, dirAbs, dirRel, out, maxResults, layers) {
5393
4824
  }
5394
4825
  const stats = await Promise.all(
5395
4826
  accepted.map(
5396
- (e) => stat(join5(dirAbs, e.name)).then((s) => s.mtimeMs).catch(() => 0)
4827
+ (e) => stat(join5(dirAbs, e.name)).then((s) => ({ mtimeMs: s.mtimeMs, isFile: s.isFile() })).catch(() => null)
5397
4828
  )
5398
4829
  );
5399
4830
  for (let i = 0; i < accepted.length; i++) {
5400
4831
  const ent = accepted[i];
4832
+ const s = stats[i];
4833
+ if (ent.isSymbolicLink()) {
4834
+ if (!s || !s.isFile) continue;
4835
+ }
5401
4836
  out.push({
5402
4837
  path: dirRel ? `${dirRel}/${ent.name}` : ent.name,
5403
- mtimeMs: stats[i] ?? 0
4838
+ mtimeMs: s?.mtimeMs ?? 0
5404
4839
  });
5405
4840
  }
5406
4841
  }
@@ -5461,25 +4896,37 @@ function rankPickerCandidates(files, query, limitOrOpts) {
5461
4896
  var AT_MENTION_PATTERN = /(?<=^|\s)@([a-zA-Z0-9_./\\-]+)/g;
5462
4897
  function expandAtMentions(text, rootDir, opts = {}) {
5463
4898
  const maxBytes = opts.maxBytes ?? DEFAULT_AT_MENTION_MAX_BYTES;
4899
+ const maxDirEntries = Math.max(1, opts.maxDirEntries ?? DEFAULT_AT_DIR_MAX_ENTRIES);
5464
4900
  const fs4 = opts.fs ?? defaultFs;
5465
4901
  const root = resolve(rootDir);
5466
4902
  const seen = /* @__PURE__ */ new Map();
5467
4903
  const expansions = [];
4904
+ const dirListings = /* @__PURE__ */ new Map();
5468
4905
  for (const match of text.matchAll(AT_MENTION_PATTERN)) {
5469
4906
  const rawPath = match[1] ?? "";
5470
4907
  let cleaned = rawPath;
5471
4908
  while (cleaned.endsWith(".")) cleaned = cleaned.slice(0, -1);
4909
+ if (cleaned.endsWith("/") || cleaned.endsWith("\\")) cleaned = cleaned.slice(0, -1);
5472
4910
  if (!cleaned) continue;
5473
4911
  const token = `@${cleaned}`;
5474
4912
  if (seen.has(token)) continue;
5475
- const expansion = resolveMention(cleaned, root, maxBytes, fs4);
4913
+ const expansion = resolveMention(cleaned, root, maxBytes, maxDirEntries, fs4, dirListings);
5476
4914
  seen.set(token, expansion);
5477
4915
  expansions.push(expansion);
5478
4916
  }
5479
4917
  if (expansions.length === 0) return { text, expansions };
5480
4918
  const blocks = [];
5481
4919
  for (const ex of expansions) {
5482
- if (ex.ok) {
4920
+ if (ex.ok && ex.isDirectory) {
4921
+ const files = dirListings.get(ex.path) ?? [];
4922
+ const truncAttr = ex.truncated ? ' truncated="true"' : "";
4923
+ const body = files.length > 0 ? `
4924
+ ${files.join("\n")}
4925
+ ` : "\n";
4926
+ blocks.push(
4927
+ `<directory path="${ex.path}" entries="${ex.entries ?? files.length}"${truncAttr}>${body}</directory>`
4928
+ );
4929
+ } else if (ex.ok) {
5483
4930
  const content = readSafe(root, ex.path, fs4);
5484
4931
  blocks.push(`<file path="${ex.path}">
5485
4932
  ${content}
@@ -5494,7 +4941,7 @@ ${content}
5494
4941
  ${blocks.join("\n\n")}`;
5495
4942
  return { text: augmented, expansions };
5496
4943
  }
5497
- function resolveMention(rawPath, root, maxBytes, fs4) {
4944
+ function resolveMention(rawPath, root, maxBytes, maxDirEntries, fs4, dirListings) {
5498
4945
  if (isAbsolute(rawPath)) {
5499
4946
  return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "escape" };
5500
4947
  }
@@ -5506,14 +4953,26 @@ function resolveMention(rawPath, root, maxBytes, fs4) {
5506
4953
  if (!fs4.exists(resolved)) {
5507
4954
  return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "missing" };
5508
4955
  }
5509
- if (!fs4.isFile(resolved)) {
5510
- return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "not-file" };
4956
+ if (fs4.isFile(resolved)) {
4957
+ const size = fs4.size(resolved);
4958
+ if (size > maxBytes) {
4959
+ return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "too-large", bytes: size };
4960
+ }
4961
+ return { token: `@${rawPath}`, path: rawPath, ok: true, bytes: size };
5511
4962
  }
5512
- const size = fs4.size(resolved);
5513
- if (size > maxBytes) {
5514
- return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "too-large", bytes: size };
4963
+ if (fs4.isDir?.(resolved) && fs4.listDir) {
4964
+ const { files, truncated } = fs4.listDir(resolved, root, maxDirEntries);
4965
+ dirListings.set(rawPath, files);
4966
+ return {
4967
+ token: `@${rawPath}`,
4968
+ path: rawPath,
4969
+ ok: true,
4970
+ isDirectory: true,
4971
+ entries: files.length,
4972
+ truncated
4973
+ };
5515
4974
  }
5516
- return { token: `@${rawPath}`, path: rawPath, ok: true, bytes: size };
4975
+ return { token: `@${rawPath}`, path: rawPath, ok: false, skip: "not-file" };
5517
4976
  }
5518
4977
  function readSafe(root, rawPath, fs4) {
5519
4978
  const resolved = resolve(root, rawPath);
@@ -5532,6 +4991,24 @@ var defaultFs = {
5532
4991
  return false;
5533
4992
  }
5534
4993
  },
4994
+ isDir: (p) => {
4995
+ try {
4996
+ return statSync2(p).isDirectory();
4997
+ } catch {
4998
+ return false;
4999
+ }
5000
+ },
5001
+ listDir: (dirAbs, root, max) => {
5002
+ const dirRel = relative(root, dirAbs).split(/[\\/]/).join("/");
5003
+ const walkCap = Math.max(max * 4, 5e3);
5004
+ const all = listFilesSync(root, { maxResults: walkCap });
5005
+ const prefix = dirRel ? `${dirRel}/` : "";
5006
+ const filtered = dirRel ? all.filter((f) => f === dirRel || f.startsWith(prefix)) : all;
5007
+ return {
5008
+ files: filtered.slice(0, max),
5009
+ truncated: filtered.length > max
5010
+ };
5011
+ },
5535
5012
  size: (p) => {
5536
5013
  try {
5537
5014
  return statSync2(p).size;
@@ -9621,14 +9098,6 @@ function recordFromLoopEvent(ev, extra) {
9621
9098
  if (ev.toolName !== void 0) rec.tool = ev.toolName;
9622
9099
  if (ev.toolArgs !== void 0) rec.args = ev.toolArgs;
9623
9100
  if (ev.error !== void 0) rec.error = ev.error;
9624
- if (ev.planState && !isPlanStateEmptyShape(ev.planState)) {
9625
- rec.planState = {
9626
- subgoals: [...ev.planState.subgoals],
9627
- hypotheses: [...ev.planState.hypotheses],
9628
- uncertainties: [...ev.planState.uncertainties],
9629
- rejectedPaths: [...ev.planState.rejectedPaths]
9630
- };
9631
- }
9632
9101
  if (ev.stats) {
9633
9102
  rec.usage = {
9634
9103
  prompt_tokens: ev.stats.usage.promptTokens,
@@ -9664,9 +9133,6 @@ function readTranscript(path2) {
9664
9133
  const raw = readFileSync11(path2, "utf8");
9665
9134
  return parseTranscript(raw);
9666
9135
  }
9667
- function isPlanStateEmptyShape(s) {
9668
- return s.subgoals.length === 0 && s.hypotheses.length === 0 && s.uncertainties.length === 0 && s.rejectedPaths.length === 0;
9669
- }
9670
9136
  function parseTranscript(raw) {
9671
9137
  const out = { meta: null, records: [] };
9672
9138
  for (const line of raw.split(/\r?\n/)) {
@@ -9702,20 +9168,12 @@ function computeReplayStats(records) {
9702
9168
  const prefixHashes = /* @__PURE__ */ new Set();
9703
9169
  let userTurns = 0;
9704
9170
  let toolCalls = 0;
9705
- let harvestedTurns = 0;
9706
- let totalUncertainties = 0;
9707
- let totalSubgoals = 0;
9708
9171
  for (const rec of records) {
9709
9172
  if (rec.role === "user") userTurns++;
9710
9173
  else if (rec.role === "tool") toolCalls++;
9711
9174
  else if (rec.role === "assistant_final") {
9712
9175
  if (rec.model) models.add(rec.model);
9713
9176
  if (rec.prefixHash) prefixHashes.add(rec.prefixHash);
9714
- if (rec.planState) {
9715
- harvestedTurns++;
9716
- totalUncertainties += rec.planState.uncertainties.length;
9717
- totalSubgoals += rec.planState.subgoals.length;
9718
- }
9719
9177
  if (rec.usage && rec.model) {
9720
9178
  const u = new Usage(
9721
9179
  rec.usage.prompt_tokens ?? 0,
@@ -9743,9 +9201,6 @@ function computeReplayStats(records) {
9743
9201
  prefixHashes: [...prefixHashes],
9744
9202
  userTurns,
9745
9203
  toolCalls,
9746
- harvestedTurns,
9747
- totalUncertainties,
9748
- totalSubgoals,
9749
9204
  ...summarizeTurns(turns)
9750
9205
  };
9751
9206
  }
@@ -9923,41 +9378,6 @@ function renderSummaryTable(report, _opts = {}) {
9923
9378
  )
9924
9379
  );
9925
9380
  lines.push(statRow("prefix hashes", a.stats.prefixHashes.length, b.stats.prefixHashes.length));
9926
- if (a.stats.harvestedTurns > 0 || b.stats.harvestedTurns > 0) {
9927
- lines.push(
9928
- row(
9929
- [
9930
- "harvest turns",
9931
- `${a.stats.harvestedTurns}`,
9932
- `${b.stats.harvestedTurns}`,
9933
- signed(b.stats.harvestedTurns - a.stats.harvestedTurns)
9934
- ],
9935
- [20, 14, 14, 14]
9936
- )
9937
- );
9938
- lines.push(
9939
- row(
9940
- [
9941
- " subgoals",
9942
- `${a.stats.totalSubgoals}`,
9943
- `${b.stats.totalSubgoals}`,
9944
- signed(b.stats.totalSubgoals - a.stats.totalSubgoals)
9945
- ],
9946
- [20, 14, 14, 14]
9947
- )
9948
- );
9949
- lines.push(
9950
- row(
9951
- [
9952
- " uncertainties",
9953
- `${a.stats.totalUncertainties}`,
9954
- `${b.stats.totalUncertainties}`,
9955
- signed(b.stats.totalUncertainties - a.stats.totalUncertainties)
9956
- ],
9957
- [20, 14, 14, 14]
9958
- )
9959
- );
9960
- }
9961
9381
  lines.push("");
9962
9382
  const aPrefixStable = a.stats.prefixHashes.length <= 1;
9963
9383
  const bPrefixStable = b.stats.prefixHashes.length <= 1;
@@ -10029,17 +9449,6 @@ function renderMarkdown(report) {
10029
9449
  out.push(
10030
9450
  `| prefix hashes | ${a.stats.prefixHashes.length} | ${b.stats.prefixHashes.length} | \u2014 |`
10031
9451
  );
10032
- if (a.stats.harvestedTurns > 0 || b.stats.harvestedTurns > 0) {
10033
- out.push(
10034
- `| harvest turns | ${a.stats.harvestedTurns} | ${b.stats.harvestedTurns} | ${signed(b.stats.harvestedTurns - a.stats.harvestedTurns)} |`
10035
- );
10036
- out.push(
10037
- `| harvest subgoals | ${a.stats.totalSubgoals} | ${b.stats.totalSubgoals} | ${signed(b.stats.totalSubgoals - a.stats.totalSubgoals)} |`
10038
- );
10039
- out.push(
10040
- `| harvest uncertainties | ${a.stats.totalUncertainties} | ${b.stats.totalUncertainties} | ${signed(b.stats.totalUncertainties - a.stats.totalUncertainties)} |`
10041
- );
10042
- }
10043
9452
  out.push("");
10044
9453
  out.push("## Turn-by-turn");
10045
9454
  out.push("");
@@ -11588,6 +10997,7 @@ export {
11588
10997
  CODE_SYSTEM_PROMPT,
11589
10998
  CacheFirstLoop,
11590
10999
  ChoiceRequestedError,
11000
+ DEFAULT_AT_DIR_MAX_ENTRIES,
11591
11001
  DEFAULT_AT_MENTION_MAX_BYTES,
11592
11002
  DEFAULT_MAX_RESULT_CHARS,
11593
11003
  DEFAULT_MAX_RESULT_TOKENS,
@@ -11620,7 +11030,6 @@ export {
11620
11030
  Usage,
11621
11031
  VERSION,
11622
11032
  VolatileScratch,
11623
- aggregateBranchUsage,
11624
11033
  aggregateUsage,
11625
11034
  analyzeSchema,
11626
11035
  appendSessionMessage,
@@ -11640,13 +11049,11 @@ export {
11640
11049
  costUsd,
11641
11050
  decideOutcome,
11642
11051
  defaultConfigPath,
11643
- defaultSelector,
11644
11052
  defaultUsageLogPath,
11645
11053
  deleteSession,
11646
11054
  detectAtPicker,
11647
11055
  detectShellOperator,
11648
11056
  diffTranscripts,
11649
- emptyPlanState,
11650
11057
  expandAtMentions,
11651
11058
  fetchWithRetry,
11652
11059
  fixToolCallPairing,
@@ -11660,7 +11067,6 @@ export {
11660
11067
  formatSearchResults,
11661
11068
  getLatestVersion,
11662
11069
  globalSettingsPath,
11663
- harvest,
11664
11070
  healLoadedMessages,
11665
11071
  healLoadedMessagesByTokens,
11666
11072
  htmlToText,
@@ -11670,7 +11076,6 @@ export {
11670
11076
  isAllowed,
11671
11077
  isJsonRpcError,
11672
11078
  isNpxInstall,
11673
- isPlanStateEmpty,
11674
11079
  isPlausibleKey,
11675
11080
  listFilesSync,
11676
11081
  listFilesWithStatsAsync,
@@ -11714,7 +11119,6 @@ export {
11714
11119
  replayFromFile,
11715
11120
  resolveExecutable,
11716
11121
  restoreSnapshots,
11717
- runBranches,
11718
11122
  runCommand,
11719
11123
  runHooks,
11720
11124
  sanitizeMemoryName,