reasonix 0.7.5 → 0.7.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -8401,17 +8401,41 @@ function parseCitationUrl(url) {
8401
8401
  }
8402
8402
  return { path: trimmed };
8403
8403
  }
8404
+ var SIBLING_EXTENSIONS = /* @__PURE__ */ new Map([
8405
+ [".ts", [".tsx", ".mts", ".cts"]],
8406
+ [".tsx", [".ts"]],
8407
+ [".js", [".jsx", ".mjs", ".cjs"]],
8408
+ [".jsx", [".js"]],
8409
+ [".mjs", [".js", ".cjs"]],
8410
+ [".cjs", [".js", ".mjs"]],
8411
+ [".mts", [".ts"]],
8412
+ [".cts", [".ts"]]
8413
+ ]);
8414
+ function extOf(p) {
8415
+ const m = /\.[^./\\]+$/.exec(p);
8416
+ return m ? m[0] : "";
8417
+ }
8404
8418
  function validateCitation(url, projectRoot) {
8405
8419
  const parts = parseCitationUrl(url);
8406
8420
  if (!parts || !parts.path) return { ok: false, reason: "empty path" };
8407
8421
  const normalized = parts.path.replace(/^[/\\]+/, "");
8408
- const fullPath = isAbsolute4(normalized) ? normalized : join11(projectRoot, normalized);
8409
- let stat;
8410
- try {
8411
- stat = statSync6(fullPath);
8412
- } catch {
8413
- return { ok: false, reason: "file not found" };
8422
+ const baseFullPath = isAbsolute4(normalized) ? normalized : join11(projectRoot, normalized);
8423
+ const siblings = SIBLING_EXTENSIONS.get(extOf(baseFullPath)) ?? [];
8424
+ const candidates = [
8425
+ baseFullPath,
8426
+ ...siblings.map((ext) => baseFullPath.replace(/\.[^./\\]+$/, ext))
8427
+ ];
8428
+ let fullPath = baseFullPath;
8429
+ let stat = null;
8430
+ for (const candidate of candidates) {
8431
+ try {
8432
+ stat = statSync6(candidate);
8433
+ fullPath = candidate;
8434
+ break;
8435
+ } catch {
8436
+ }
8414
8437
  }
8438
+ if (!stat) return { ok: false, reason: "file not found" };
8415
8439
  if (!stat.isFile()) return { ok: false, reason: "not a file" };
8416
8440
  if (parts.startLine === void 0) return { ok: true };
8417
8441
  let lineCount;
@@ -9840,8 +9864,11 @@ function processMultilineKey(value, cursor, keyIn) {
9840
9864
  if (key.pageDown) {
9841
9865
  return cursor === value.length ? NOOP : { next: null, cursor: value.length, submit: false };
9842
9866
  }
9843
- if (value.length === 0 && (key.upArrow || key.downArrow)) {
9844
- return { ...NOOP, historyHandoff: key.upArrow ? "prev" : "next" };
9867
+ if (key.ctrl && key.input === "p") {
9868
+ return { ...NOOP, historyHandoff: "prev" };
9869
+ }
9870
+ if (key.ctrl && key.input === "n") {
9871
+ return { ...NOOP, historyHandoff: "next" };
9845
9872
  }
9846
9873
  if (key.leftArrow) {
9847
9874
  return { next: null, cursor: Math.max(0, cursor - 1), submit: false };
@@ -9851,13 +9878,11 @@ function processMultilineKey(value, cursor, keyIn) {
9851
9878
  }
9852
9879
  if (key.upArrow) {
9853
9880
  const moved = moveCursorUp(value, cursor);
9854
- if (moved === cursor) return { ...NOOP, historyHandoff: "prev" };
9855
- return { next: null, cursor: moved, submit: false };
9881
+ return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
9856
9882
  }
9857
9883
  if (key.downArrow) {
9858
9884
  const moved = moveCursorDown(value, cursor);
9859
- if (moved === cursor) return { ...NOOP, historyHandoff: "next" };
9860
- return { next: null, cursor: moved, submit: false };
9885
+ return moved === cursor ? NOOP : { next: null, cursor: moved, submit: false };
9861
9886
  }
9862
9887
  if (key.ctrl && key.input === "a") {
9863
9888
  return { next: null, cursor: startOfLine(value, cursor), submit: false };
@@ -10258,15 +10283,12 @@ function PromptInput({
10258
10283
  const continuationIndent = BAR + " ".repeat(promptBody.length);
10259
10284
  const prefixCells = promptPrefix.length;
10260
10285
  const visibleCells = Math.max(8, cols - prefixCells - 3);
10261
- const placeholderActive = narrow ? "type a message, or /command" : "type a message, or /command \xB7 [Ctrl+J] newline (Shift+Enter where supported)";
10286
+ const placeholderActive = narrow ? "type a message, or /command" : "type a message, or /command \xB7 [Ctrl+J] newline \xB7 [Ctrl+P/N] history";
10262
10287
  const effectivePlaceholder = disabled ? placeholder ?? "\u2026waiting for response\u2026" : placeholder ?? placeholderActive;
10263
10288
  const lines = value.length > 0 ? value.split("\n") : [""];
10264
10289
  const accentColor = disabled ? "gray" : "cyan";
10265
- const animate = !disabled && cols >= 100;
10266
- const tick = useTick();
10267
- const barOffset = animate ? Math.floor(tick / 6) : 0;
10268
- const barColorAt = (rowIdx) => disabled ? "gray" : GRADIENT[((rowIdx + barOffset) % GRADIENT.length + GRADIENT.length) % GRADIENT.length];
10269
- const cursorVisible = animate ? Math.floor(tick / 4) % 2 === 0 : true;
10290
+ const barColorAt = (rowIdx) => disabled ? "gray" : GRADIENT[(rowIdx % GRADIENT.length + GRADIENT.length) % GRADIENT.length];
10291
+ const cursorVisible = true;
10270
10292
  const { line: cursorLine, col: cursorCol } = lineAndColumn(value, cursor);
10271
10293
  const renderItems = collapseLinesForDisplay(lines, cursorLine);
10272
10294
  const showHugeBufferHints = lines.length > 20;
@@ -10599,14 +10621,11 @@ function SuggestionRow({ spec, isSelected }) {
10599
10621
  import { Box as Box19, Text as Text17, useStdout as useStdout6 } from "ink";
10600
10622
  import React21 from "react";
10601
10623
  var WORDMARK_LETTERS = ["R", "E", "A", "S", "O", "N", "I", "X"];
10602
- function Wordmark({ busy, animate }) {
10603
- const tick = useTick();
10604
- const pulsePeriod = busy ? 5 : 12;
10605
- const bright = animate ? Math.floor(tick / pulsePeriod) % 2 === 0 : true;
10606
- const rotateEvery = busy ? 2 : 4;
10607
- const offset = animate ? Math.floor(tick / rotateEvery) : 0;
10608
- const colorAt = (i) => GRADIENT[((i + offset) % GRADIENT.length + GRADIENT.length) % GRADIENT.length];
10609
- return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: colorAt(0), bold: bright }, "\u25C8"), /* @__PURE__ */ React21.createElement(Text17, null, " "), WORDMARK_LETTERS.map((letter, i) => /* @__PURE__ */ React21.createElement(Text17, { key: letter, color: colorAt(i + 1), bold: true }, letter)));
10624
+ function Wordmark({
10625
+ busy: _busy,
10626
+ animate: _animate
10627
+ }) {
10628
+ return /* @__PURE__ */ React21.createElement(Text17, null, /* @__PURE__ */ React21.createElement(Text17, { color: GRADIENT[0], bold: true }, "\u25C8"), /* @__PURE__ */ React21.createElement(Text17, null, " "), WORDMARK_LETTERS.map((letter, i) => /* @__PURE__ */ React21.createElement(Text17, { key: letter, color: GRADIENT[i % GRADIENT.length], bold: true }, letter)));
10610
10629
  }
10611
10630
  var NARROW_BREAKPOINT = 120;
10612
10631
  var COLD_START_TURNS = 3;
@@ -10632,73 +10651,44 @@ function StatsPanel({
10632
10651
  const columns = stdout2?.columns ?? 80;
10633
10652
  const narrow = columns < NARROW_BREAKPOINT;
10634
10653
  const coldStart = summary.turns <= COLD_START_TURNS;
10635
- const ruleWidth = Math.max(20, columns - 2);
10636
- const animate = columns >= 100;
10637
- return (
10638
- // Borderless layout: no `borderStyle`, no rounded box. Bordered
10639
- // Boxes were the most visible amplifier of Ink's eraseLines
10640
- // miscount on Windows terminals. Visual weight here comes from
10641
- // truecolor gradient rules at the top and bottom (rendered as
10642
- // pure Text so they never trigger the eraseLines bug), the
10643
- // animated wordmark + pill row, and a soft inner padding.
10644
- /* @__PURE__ */ React21.createElement(Box19, { flexDirection: "column", paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React21.createElement(GradientRule, { width: ruleWidth, animate }), /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(
10645
- Header,
10646
- {
10647
- model: model2,
10648
- prefixHash,
10649
- harvestOn,
10650
- branchOn,
10651
- branchBudget: branchBudget ?? 1,
10652
- reasoningEffort,
10653
- planMode,
10654
- editMode,
10655
- turns: summary.turns,
10656
- updateAvailable,
10657
- narrow,
10658
- busy: busy ?? false,
10659
- proArmed: proArmed ?? false,
10660
- escalated: escalated ?? false,
10661
- animate
10662
- }
10663
- )), narrow ? /* @__PURE__ */ React21.createElement(
10664
- StackedMetrics,
10665
- {
10666
- summary,
10667
- ctxRatio,
10668
- ctxMax,
10669
- balance,
10670
- coldStart
10671
- }
10672
- ) : /* @__PURE__ */ React21.createElement(
10673
- InlineMetrics,
10674
- {
10675
- summary,
10676
- ctxRatio,
10677
- ctxMax,
10678
- balance,
10679
- coldStart
10680
- }
10681
- ), /* @__PURE__ */ React21.createElement(Box19, { marginTop: 1 }, /* @__PURE__ */ React21.createElement(GradientRule, { width: ruleWidth, thin: true, animate })))
10682
- );
10683
- }
10684
- function GradientRule({
10685
- width,
10686
- thin,
10687
- animate
10688
- }) {
10689
- const tick = useTick();
10690
- const offset = animate ? Math.floor(tick / 6) : 0;
10691
- const ch = thin ? "\u2581" : "\u2584";
10692
- const len = GRADIENT.length;
10693
- return /* @__PURE__ */ React21.createElement(Box19, null, Array.from({ length: width }, (_, i) => {
10694
- const t = width === 1 ? 0 : i * (len - 1) / (width - 1);
10695
- const idx = (Math.round(t) + offset) % len;
10696
- const color = GRADIENT[(idx % len + len) % len];
10697
- return (
10698
- // biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient cells never reorder
10699
- /* @__PURE__ */ React21.createElement(Text17, { key: `grule-${i}`, color }, ch)
10700
- );
10701
- }));
10654
+ return /* @__PURE__ */ React21.createElement(Box19, { flexDirection: "column", paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React21.createElement(
10655
+ Header,
10656
+ {
10657
+ model: model2,
10658
+ prefixHash,
10659
+ harvestOn,
10660
+ branchOn,
10661
+ branchBudget: branchBudget ?? 1,
10662
+ reasoningEffort,
10663
+ planMode,
10664
+ editMode,
10665
+ turns: summary.turns,
10666
+ updateAvailable,
10667
+ narrow,
10668
+ busy: busy ?? false,
10669
+ proArmed: proArmed ?? false,
10670
+ escalated: escalated ?? false,
10671
+ animate: false
10672
+ }
10673
+ ), narrow ? /* @__PURE__ */ React21.createElement(
10674
+ StackedMetrics,
10675
+ {
10676
+ summary,
10677
+ ctxRatio,
10678
+ ctxMax,
10679
+ balance,
10680
+ coldStart
10681
+ }
10682
+ ) : /* @__PURE__ */ React21.createElement(
10683
+ InlineMetrics,
10684
+ {
10685
+ summary,
10686
+ ctxRatio,
10687
+ ctxMax,
10688
+ balance,
10689
+ coldStart
10690
+ }
10691
+ ));
10702
10692
  }
10703
10693
  function Header({
10704
10694
  model: model2,
@@ -10827,9 +10817,9 @@ function WelcomeBanner({ inCodeMode }) {
10827
10817
  const { stdout: stdout2 } = useStdout7();
10828
10818
  const cols = stdout2?.columns ?? 80;
10829
10819
  const ruleWidth = Math.min(60, Math.max(28, cols - 4));
10830
- return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React22.createElement(GradientRule2, { width: ruleWidth }), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.brand }, "\u25C8 welcome"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \xB7 type a message to start")), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.primary }, "quick start")), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/help", desc: "every command + keyboard shortcut" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/skill", desc: "invoke a stored playbook" }), inCodeMode ? /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "@path", desc: "inline a file in your message" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "!cmd", desc: "run a shell command, output goes to context" })) : null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "/exit", desc: "quit (Ctrl+C also works)" }), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true, italic: true }, "tip:"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " Ctrl+J inserts a newline \xB7 trailing \\ also continues")), /* @__PURE__ */ React22.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(GradientRule2, { width: ruleWidth, thin: true })));
10820
+ return /* @__PURE__ */ React22.createElement(Box20, { flexDirection: "column", paddingX: 1, marginY: 1 }, /* @__PURE__ */ React22.createElement(GradientRule, { width: ruleWidth }), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.brand }, "\u25C8 welcome"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " \xB7 type a message to start")), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.primary }, "quick start")), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/help", desc: "every command + keyboard shortcut" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "/skill", desc: "invoke a stored playbook" }), inCodeMode ? /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "@path", desc: "inline a file in your message" }), /* @__PURE__ */ React22.createElement(Hint, { cmd: "!cmd", desc: "run a shell command, output goes to context" })) : null, /* @__PURE__ */ React22.createElement(Hint, { cmd: "/exit", desc: "quit (Ctrl+C also works)" }), /* @__PURE__ */ React22.createElement(BarRow, null), /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { dimColor: true, italic: true }, "tip:"), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, " Ctrl+J inserts a newline \xB7 trailing \\ also continues")), /* @__PURE__ */ React22.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React22.createElement(GradientRule, { width: ruleWidth, thin: true })));
10831
10821
  }
10832
- function GradientRule2({ width, thin }) {
10822
+ function GradientRule({ width, thin }) {
10833
10823
  const cells = gradientCells(width, thin ? "\u2581" : "\u2584");
10834
10824
  return /* @__PURE__ */ React22.createElement(Box20, null, cells.map((c, i) => (
10835
10825
  // biome-ignore lint/suspicious/noArrayIndexKey: fixed-width gradient row, never reordered
@@ -13192,6 +13182,24 @@ function App({
13192
13182
  stdout2.write("\x1B[>4m");
13193
13183
  };
13194
13184
  }, [stdout2]);
13185
+ const [isResizing, setIsResizing] = useState10(false);
13186
+ useEffect6(() => {
13187
+ if (!stdout2 || !stdout2.isTTY) return;
13188
+ let timer = null;
13189
+ const onResize = () => {
13190
+ setIsResizing(true);
13191
+ if (timer) clearTimeout(timer);
13192
+ timer = setTimeout(() => {
13193
+ setIsResizing(false);
13194
+ timer = null;
13195
+ }, 400);
13196
+ };
13197
+ stdout2.on("resize", onResize);
13198
+ return () => {
13199
+ stdout2.off("resize", onResize);
13200
+ if (timer) clearTimeout(timer);
13201
+ };
13202
+ }, [stdout2]);
13195
13203
  const { activity: subagentActivity, sinkRef: subagentSinkRef } = useSubagent({
13196
13204
  session,
13197
13205
  setHistorical
@@ -14768,7 +14776,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
14768
14776
  return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(
14769
14777
  TickerProvider,
14770
14778
  {
14771
- disabled: PLAIN_UI || !!pendingPlan || !!pendingShell || !!pendingEditReview || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision
14779
+ disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingShell || !!pendingEditReview || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision
14772
14780
  },
14773
14781
  /* @__PURE__ */ React23.createElement(Box21, { flexDirection: "column" }, /* @__PURE__ */ React23.createElement(
14774
14782
  StatsPanel,
@@ -15137,9 +15145,6 @@ async function chatCommand(opts) {
15137
15145
  } else if (opts.session && opts.forceNew) {
15138
15146
  rewriteSession(opts.session, []);
15139
15147
  }
15140
- if (process.stdout.isTTY) {
15141
- process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
15142
- }
15143
15148
  const { waitUntilExit } = render(
15144
15149
  /* @__PURE__ */ React26.createElement(
15145
15150
  Root,