reasonix 0.44.2-rc.4 → 0.45.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.
@@ -72,9 +72,8 @@ import {
72
72
  import {
73
73
  KeystrokeProvider,
74
74
  SingleSelect,
75
- sanitizePasteText,
76
75
  useKeystroke
77
- } from "./chunk-MRHHQJAQ.js";
76
+ } from "./chunk-IBJIK2DD.js";
78
77
  import {
79
78
  COLOR,
80
79
  GLYPH,
@@ -44791,174 +44790,25 @@ function cancelAllPromptInputs() {
44791
44790
  // src/cli/ui/scene/trace.ts
44792
44791
  import { appendFileSync, closeSync, openSync } from "fs";
44793
44792
 
44794
- // src/cli/ui/scene/renderer-process.ts
44795
- import { spawn } from "child_process";
44796
- function spawnRenderer(opts) {
44797
- const command = opts.command;
44798
- const baseArgs = [];
44799
- const [cmd, ...rest] = command;
44800
- baseArgs.push(...rest);
44801
- if (opts.integrated) {
44802
- baseArgs.push("--integrated");
44803
- }
44804
- if (!cmd) {
44805
- throw new Error("spawnRenderer: empty command");
44806
- }
44807
- const stderrStdio = opts.integrated ? "pipe" : "inherit";
44808
- const child = spawn(cmd, baseArgs, {
44809
- cwd: opts.cwd,
44810
- env: opts.env ?? process.env,
44811
- stdio: ["pipe", "inherit", stderrStdio]
44812
- });
44813
- child.on("error", (err) => {
44814
- process.stderr.write(`[spawnRenderer] child error: ${err.message}
44815
- `);
44816
- });
44817
- let exited = false;
44818
- let aliveMs = 0;
44819
- const spawnedAt = Date.now();
44820
- const exitPromise = new Promise((resolve3) => {
44821
- child.once("exit", (code, signal) => {
44822
- exited = true;
44823
- aliveMs = Date.now() - spawnedAt;
44824
- process.stderr.write(
44825
- `[spawnRenderer] child exit: code=${code} signal=${signal} aliveMs=${aliveMs}
44826
- `
44827
- );
44828
- resolve3(code);
44829
- if (opts.integrated && opts.onEvent && aliveMs >= 1500) {
44830
- try {
44831
- opts.onEvent({ event: "exit" });
44832
- } catch {
44833
- }
44834
- }
44835
- });
44836
- });
44837
- child.stdin?.on("error", () => {
44838
- exited = true;
44839
- });
44840
- if (opts.integrated && opts.onEvent && child.stderr) {
44841
- let buf = "";
44842
- child.stderr.setEncoding("utf8");
44843
- child.stderr.on("data", (chunk) => {
44844
- buf += chunk;
44845
- for (; ; ) {
44846
- const nl = buf.indexOf("\n");
44847
- if (nl === -1) break;
44848
- const line = buf.slice(0, nl).trim();
44849
- buf = buf.slice(nl + 1);
44850
- if (line.length === 0) continue;
44851
- try {
44852
- const parsed = JSON.parse(line);
44853
- if (parsed && typeof parsed.event === "string") {
44854
- opts.onEvent?.(parsed);
44855
- continue;
44856
- }
44857
- } catch {
44858
- }
44859
- process.stderr.write(`[rust-stderr] ${line}
44860
- `);
44861
- }
44862
- });
44863
- }
44864
- return {
44865
- emit(message) {
44866
- if (exited) return;
44867
- const stdin = child.stdin;
44868
- if (!stdin || stdin.destroyed || !stdin.writable) return;
44869
- stdin.write(`${JSON.stringify(message)}
44870
- `);
44871
- },
44872
- close() {
44873
- const stdin = child.stdin;
44874
- if (stdin && !stdin.destroyed && stdin.writable) {
44875
- stdin.end();
44876
- }
44877
- return exitPromise;
44878
- }
44879
- };
44880
- }
44881
-
44882
- // src/cli/ui/scene/renderer-resolver.ts
44883
- import { execSync } from "child_process";
44793
+ // src/cli/ui/scene/renderer.ts
44884
44794
  import { existsSync as existsSync2 } from "fs";
44885
44795
  import { createRequire } from "module";
44886
44796
  import { dirname as dirname3, join as join3 } from "path";
44887
44797
  import { fileURLToPath } from "url";
44888
- var cached;
44889
- function resolveRenderer() {
44890
- if (cached) return cached;
44891
- cached = resolveRendererWith(defaultIO());
44892
- return cached;
44893
- }
44894
- function resolveRendererWith(io) {
44895
- const base = pickBase(io);
44896
- const renderEnv = io.envCmd("REASONIX_RENDER_CMD");
44897
- const inputEnv = io.envCmd("REASONIX_INPUT_CMD");
44898
- if (!renderEnv && !inputEnv) return base;
44899
- return {
44900
- command: renderEnv ?? base.command,
44901
- inputCommand: inputEnv ?? base.inputCommand,
44902
- source: base.source ?? "env-cmd"
44903
- };
44904
- }
44905
- function pickBase(io) {
44906
- const binEnv = io.envBin();
44907
- if (binEnv && io.hasFile(binEnv)) return fromBinary(binEnv, "env-bin");
44908
- const optional = io.resolveOptionalDep(io.platform, process.arch);
44909
- if (optional) return fromBinary(optional, "optional-dep");
44910
- const sourceRoot = io.findReasonixSourceTree();
44911
- if (sourceRoot) {
44912
- const binName = io.platform === "win32" ? "reasonix-render.exe" : "reasonix-render";
44913
- const release2 = join3(sourceRoot, "target", "release", binName);
44914
- if (io.hasFile(release2)) return fromBinary(release2, "prebuilt-release");
44915
- const debug = join3(sourceRoot, "target", "debug", binName);
44916
- if (io.hasFile(debug)) return fromBinary(debug, "prebuilt-debug");
44917
- if (io.hasCargo()) return fromCargo();
44918
- }
44919
- return { command: [], inputCommand: [], source: null };
44920
- }
44921
- function fromBinary(bin, source) {
44922
- return { command: [bin], inputCommand: [bin, "--emit-input"], source };
44923
- }
44924
- function fromCargo() {
44925
- const cmd = ["cargo", "run", "--quiet", "--bin", "reasonix-render"];
44926
- return { command: cmd, inputCommand: [...cmd, "--", "--emit-input"], source: "cargo" };
44927
- }
44928
- function defaultIO() {
44929
- return {
44930
- envCmd: parseEnvCmd,
44931
- envBin: () => process.env.REASONIX_RENDER_BIN,
44932
- hasFile: existsSync2,
44933
- resolveOptionalDep: locateOptionalDepBinary,
44934
- findReasonixSourceTree: detectReasonixSourceTree,
44935
- hasCargo: detectCargo,
44936
- platform: process.platform
44937
- };
44938
- }
44939
- function parseEnvCmd(name) {
44940
- const raw = process.env[name];
44941
- if (!raw || raw.length === 0) return void 0;
44942
- try {
44943
- const parsed = JSON.parse(raw);
44944
- if (Array.isArray(parsed) && parsed.every((p) => typeof p === "string")) return parsed;
44945
- } catch {
44946
- }
44947
- return void 0;
44948
- }
44949
- function locateOptionalDepBinary(platform2, arch) {
44950
- const pkg = `@reasonix/render-${platform2}-${arch}`;
44951
- try {
44952
- const require_ = createRequire(import.meta.url);
44953
- const pkgJson = require_.resolve(`${pkg}/package.json`);
44954
- const binName = platform2 === "win32" ? "reasonix-render.exe" : "reasonix-render";
44955
- const binPath = join3(dirname3(pkgJson), "bin", binName);
44956
- return existsSync2(binPath) ? binPath : void 0;
44957
- } catch {
44958
- return void 0;
44959
- }
44798
+ var TRIPLES = {
44799
+ "win32-x64": "win32-x64-msvc",
44800
+ "win32-arm64": "win32-arm64-msvc",
44801
+ "darwin-arm64": "darwin-arm64",
44802
+ "darwin-x64": "darwin-x64",
44803
+ "linux-x64": "linux-x64-gnu",
44804
+ "linux-arm64": "linux-arm64-gnu"
44805
+ };
44806
+ var requireCJS = createRequire(import.meta.url);
44807
+ var cachedBinding = null;
44808
+ function tripleFor(platform2, arch) {
44809
+ return TRIPLES[`${platform2}-${arch}`] ?? null;
44960
44810
  }
44961
- function detectReasonixSourceTree() {
44811
+ function findDevTree() {
44962
44812
  let dir = dirname3(fileURLToPath(import.meta.url));
44963
44813
  for (let i = 0; i < 12; i++) {
44964
44814
  if (existsSync2(join3(dir, "crates", "reasonix-render", "Cargo.toml"))) return dir;
@@ -44966,27 +44816,78 @@ function detectReasonixSourceTree() {
44966
44816
  if (parent === dir) break;
44967
44817
  dir = parent;
44968
44818
  }
44969
- return void 0;
44819
+ return null;
44970
44820
  }
44971
- function detectCargo() {
44821
+ function loadBinding() {
44822
+ if (cachedBinding) return cachedBinding;
44823
+ const { platform: platform2, arch } = process;
44824
+ const triple = tripleFor(platform2, arch);
44825
+ if (!triple) {
44826
+ throw new Error(
44827
+ `reasonix-render: unsupported platform ${platform2}-${arch}. Supported: ${Object.keys(TRIPLES).join(", ")}.`
44828
+ );
44829
+ }
44830
+ const devTree = findDevTree();
44831
+ if (devTree) {
44832
+ const devNode = join3(devTree, "crates", "reasonix-render", `reasonix-render.${triple}.node`);
44833
+ if (existsSync2(devNode)) {
44834
+ cachedBinding = requireCJS(devNode);
44835
+ return cachedBinding;
44836
+ }
44837
+ }
44838
+ const pkg = `@reasonix/render-${platform2}-${arch}`;
44972
44839
  try {
44973
- execSync("cargo --version", { stdio: "ignore" });
44840
+ cachedBinding = requireCJS(pkg);
44841
+ return cachedBinding;
44842
+ } catch (err) {
44843
+ const reason = err instanceof Error ? err.message : String(err);
44844
+ throw new Error(
44845
+ `reasonix-render: no native binding found for ${platform2}-${arch}. Tried dev tree + ${pkg}. Run \`npm run build:rust\` for source builds, or reinstall reasonix so npm fetches the optional dep. (${reason})`
44846
+ );
44847
+ }
44848
+ }
44849
+ function isRendererAvailable() {
44850
+ try {
44851
+ loadBinding();
44974
44852
  return true;
44975
44853
  } catch {
44976
44854
  return false;
44977
44855
  }
44978
44856
  }
44857
+ function createRenderer(opts = {}) {
44858
+ const binding = loadBinding();
44859
+ const handle = binding.createRenderer((eventJson) => {
44860
+ if (!opts.onEvent) return;
44861
+ try {
44862
+ const parsed = JSON.parse(eventJson);
44863
+ if (parsed && typeof parsed.event === "string") opts.onEvent(parsed);
44864
+ } catch {
44865
+ }
44866
+ });
44867
+ let closed = false;
44868
+ return {
44869
+ emit(message) {
44870
+ if (closed) return;
44871
+ handle.emit(JSON.stringify(message));
44872
+ },
44873
+ async close() {
44874
+ if (closed) return;
44875
+ closed = true;
44876
+ handle.close();
44877
+ }
44878
+ };
44879
+ }
44979
44880
 
44980
44881
  // src/cli/ui/scene/trace.ts
44981
44882
  var FILE_VAR = "REASONIX_SCENE_TRACE";
44982
44883
  var RENDERER_VAR = "REASONIX_RENDERER";
44983
- var INTEGRATED_VAR = "REASONIX_RENDERER_INTEGRATED";
44984
44884
  var integratedHandler = null;
44985
44885
  function setIntegratedEventHandler(handler) {
44986
44886
  integratedHandler = handler;
44987
44887
  }
44988
44888
  function isIntegratedRendererRequested() {
44989
- return process.env[RENDERER_VAR] !== "node" && process.env[INTEGRATED_VAR] !== "0";
44889
+ if (process.env[RENDERER_VAR] === "node") return false;
44890
+ return isRendererAvailable();
44990
44891
  }
44991
44892
  var state = { mode: "off", opened: false, path: null, child: null };
44992
44893
  function isSceneTraceEnabled() {
@@ -44999,10 +44900,8 @@ function emitSceneMessage(message) {
44999
44900
  case "off":
45000
44901
  return;
45001
44902
  case "file":
45002
- if (state.path) {
45003
- appendFileSync(state.path, `${JSON.stringify(message)}
44903
+ if (state.path) appendFileSync(state.path, `${JSON.stringify(message)}
45004
44904
  `);
45005
- }
45006
44905
  return;
45007
44906
  case "child":
45008
44907
  state.child?.emit(message);
@@ -45011,10 +44910,6 @@ function emitSceneMessage(message) {
45011
44910
  }
45012
44911
  function ensureSceneTraceReady() {
45013
44912
  ensureInitialized();
45014
- if (state.mode === "child" && state.child) {
45015
- state.child.emit({ type: "trace" });
45016
- process.stderr.write("[trace] seed frame written\n");
45017
- }
45018
44913
  }
45019
44914
  function ensureInitialized() {
45020
44915
  if (state.opened) return;
@@ -45027,24 +44922,11 @@ function ensureInitialized() {
45027
44922
  return;
45028
44923
  }
45029
44924
  if (process.env[RENDERER_VAR] === "node") return;
45030
- const { command, source } = resolveRenderer();
45031
- process.stderr.write(`[trace] resolver source=${source} command=${JSON.stringify(command)}
45032
- `);
45033
- if (source === null || command.length === 0) {
45034
- process.stderr.write(
45035
- "\u25B2 trace.ts: resolveRenderer() returned no usable command \u2014 scene trace stays off. Check optional-dep install (`ls node_modules/@reasonix/render-*`) or set REASONIX_RENDER_BIN.\n"
45036
- );
45037
- return;
45038
- }
45039
- const integrated = process.env[INTEGRATED_VAR] !== "0";
45040
- process.stderr.write(`[trace] spawning rust child (integrated=${integrated})
45041
- `);
44925
+ if (!isRendererAvailable()) return;
44926
+ const opts = {};
44927
+ if (integratedHandler) opts.onEvent = integratedHandler;
45042
44928
  state.mode = "child";
45043
- state.child = spawnRenderer({
45044
- command,
45045
- integrated,
45046
- onEvent: integrated && integratedHandler ? integratedHandler : void 0
45047
- });
44929
+ state.child = createRenderer(opts);
45048
44930
  }
45049
44931
  function truncate(path) {
45050
44932
  const fd = openSync(path, "w");
@@ -45824,7 +45706,7 @@ function recordSlashUse(name) {
45824
45706
  }
45825
45707
 
45826
45708
  // src/cli/edit/external-editor.ts
45827
- import { spawn as spawn2 } from "child_process";
45709
+ import { spawn } from "child_process";
45828
45710
  import { mkdtempSync, readFileSync as readFileSync4, rmSync, writeFileSync as writeFileSync4 } from "fs";
45829
45711
  import { tmpdir } from "os";
45830
45712
  import { join as join5 } from "path";
@@ -45866,7 +45748,7 @@ async function openInExternalEditor(initial2) {
45866
45748
  }
45867
45749
  function spawnEditor(editor, path) {
45868
45750
  return new Promise((resolve3, reject) => {
45869
- const child = spawn2(`${editor} "${path}"`, {
45751
+ const child = spawn(`${editor} "${path}"`, {
45870
45752
  shell: true,
45871
45753
  stdio: "inherit"
45872
45754
  });
@@ -46205,14 +46087,14 @@ function ViewportBudgetProvider({
46205
46087
  initialRows
46206
46088
  }) {
46207
46089
  const { stdout } = use_stdout_default();
46208
- const [state2, dispatch2] = (0, import_react7.useReducer)(reducer, void 0, () => ({
46090
+ const [state2, dispatch] = (0, import_react7.useReducer)(reducer, void 0, () => ({
46209
46091
  claims: /* @__PURE__ */ new Map(),
46210
46092
  totalRows: initialRows ?? stdout?.rows ?? 40
46211
46093
  }));
46212
46094
  (0, import_react7.useEffect)(() => {
46213
46095
  if (initialRows !== void 0) return void 0;
46214
46096
  if (!stdout) return void 0;
46215
- const onResize = () => dispatch2({ type: "resize", rows: stdout.rows ?? 40 });
46097
+ const onResize = () => dispatch({ type: "resize", rows: stdout.rows ?? 40 });
46216
46098
  onResize();
46217
46099
  stdout.on("resize", onResize);
46218
46100
  return () => {
@@ -46231,7 +46113,7 @@ function ViewportBudgetProvider({
46231
46113
  totalRows: state2.totalRows,
46232
46114
  allocations,
46233
46115
  claims: state2.claims,
46234
- dispatch: dispatch2
46116
+ dispatch
46235
46117
  }),
46236
46118
  [state2.totalRows, allocations, state2.claims]
46237
46119
  );
@@ -46239,14 +46121,14 @@ function ViewportBudgetProvider({
46239
46121
  }
46240
46122
  function useReserveRows(zone, spec) {
46241
46123
  const ctx = (0, import_react7.useContext)(BudgetContext);
46242
- const dispatch2 = ctx?.dispatch;
46124
+ const dispatch = ctx?.dispatch;
46243
46125
  (0, import_react7.useEffect)(() => {
46244
- if (!dispatch2) return void 0;
46245
- dispatch2({ type: "claim", zone, spec: { min: spec.min, max: spec.max } });
46126
+ if (!dispatch) return void 0;
46127
+ dispatch({ type: "claim", zone, spec: { min: spec.min, max: spec.max } });
46246
46128
  return () => {
46247
- dispatch2({ type: "release", zone });
46129
+ dispatch({ type: "release", zone });
46248
46130
  };
46249
- }, [dispatch2, zone, spec.min, spec.max]);
46131
+ }, [dispatch, zone, spec.min, spec.max]);
46250
46132
  if (!ctx) return Number.isFinite(spec.max) ? spec.max : 40;
46251
46133
  const allocated = ctx.allocations.get(zone);
46252
46134
  if (allocated !== void 0) return allocated;
@@ -53802,17 +53684,17 @@ function formatTok(n) {
53802
53684
  return String(n);
53803
53685
  }
53804
53686
  function useScrollback() {
53805
- const dispatch2 = useDispatch();
53687
+ const dispatch = useDispatch();
53806
53688
  return (0, import_react46.useMemo)(
53807
53689
  () => ({
53808
53690
  pushUser(text) {
53809
53691
  const id = nextId2("u");
53810
- dispatch2({ type: "user.submit", text });
53692
+ dispatch({ type: "user.submit", text });
53811
53693
  return id;
53812
53694
  },
53813
53695
  pushWarning(title2, message) {
53814
53696
  const id = nextId2("warn");
53815
- dispatch2({
53697
+ dispatch({
53816
53698
  type: "live.show",
53817
53699
  id,
53818
53700
  ts: Date.now(),
@@ -53825,7 +53707,7 @@ function useScrollback() {
53825
53707
  },
53826
53708
  pushError(title2, message, stack) {
53827
53709
  const id = nextId2("err");
53828
- dispatch2({
53710
+ dispatch({
53829
53711
  type: "live.show",
53830
53712
  id,
53831
53713
  ts: Date.now(),
@@ -53839,7 +53721,7 @@ ${stack}` : message
53839
53721
  },
53840
53722
  pushInfo(text, tone = "info") {
53841
53723
  const id = nextId2("info");
53842
- dispatch2({
53724
+ dispatch({
53843
53725
  type: "live.show",
53844
53726
  id,
53845
53727
  ts: Date.now(),
@@ -53851,7 +53733,7 @@ ${stack}` : message
53851
53733
  },
53852
53734
  pushTip({ topic, sections, footer, oneTime = true }) {
53853
53735
  const id = nextId2("tip");
53854
- dispatch2({
53736
+ dispatch({
53855
53737
  type: "tip.show",
53856
53738
  id,
53857
53739
  ts: Date.now(),
@@ -53872,7 +53754,7 @@ ${stack}` : message
53872
53754
  const tone = pct >= 95 ? "err" : "warn";
53873
53755
  const used = formatTok(usedTokens);
53874
53756
  const max = formatTok(ctxMax);
53875
- dispatch2({
53757
+ dispatch({
53876
53758
  type: "live.show",
53877
53759
  id: nextId2("ctxp"),
53878
53760
  ts: Date.now(),
@@ -53885,7 +53767,7 @@ ${stack}` : message
53885
53767
  pushStepProgress(stepIndex, total, title2, elapsedMs) {
53886
53768
  const id = nextId2("step");
53887
53769
  const meta = elapsedMs !== void 0 ? `${(elapsedMs / 1e3).toFixed(1)}s \xB7 done` : "done";
53888
- dispatch2({
53770
+ dispatch({
53889
53771
  type: "live.show",
53890
53772
  id,
53891
53773
  ts: Date.now(),
@@ -53898,7 +53780,7 @@ ${stack}` : message
53898
53780
  },
53899
53781
  pushPlanAnnounce(text) {
53900
53782
  const id = nextId2("plan");
53901
- dispatch2({
53783
+ dispatch({
53902
53784
  type: "live.show",
53903
53785
  id,
53904
53786
  ts: Date.now(),
@@ -53911,12 +53793,12 @@ ${stack}` : message
53911
53793
  },
53912
53794
  showDoctor(checks) {
53913
53795
  const id = nextId2("doc");
53914
- dispatch2({ type: "doctor.show", id, checks: [...checks] });
53796
+ dispatch({ type: "doctor.show", id, checks: [...checks] });
53915
53797
  return id;
53916
53798
  },
53917
53799
  showUsageVerbose(args) {
53918
53800
  const id = nextId2("cost");
53919
- dispatch2({
53801
+ dispatch({
53920
53802
  type: "usage.show",
53921
53803
  id,
53922
53804
  turn: args.turn,
@@ -53937,49 +53819,49 @@ ${stack}` : message
53937
53819
  },
53938
53820
  showPlan({ title: title2, steps, variant }) {
53939
53821
  const id = nextId2("plan");
53940
- dispatch2({ type: "plan.show", id, title: title2, steps, variant });
53822
+ dispatch({ type: "plan.show", id, title: title2, steps, variant });
53941
53823
  return id;
53942
53824
  },
53943
53825
  completePlanStep(stepId) {
53944
- dispatch2({ type: "plan.step.complete", stepId });
53826
+ dispatch({ type: "plan.step.complete", stepId });
53945
53827
  },
53946
53828
  showCtx(args) {
53947
53829
  const id = nextId2("ctx");
53948
- dispatch2({ type: "ctx.show", id, ...args, topTools: [...args.topTools] });
53830
+ dispatch({ type: "ctx.show", id, ...args, topTools: [...args.topTools] });
53949
53831
  return id;
53950
53832
  },
53951
53833
  startReasoning(model2) {
53952
53834
  const id = nextId2("r");
53953
- dispatch2({ type: "reasoning.start", id, ...model2 ? { model: model2 } : {} });
53835
+ dispatch({ type: "reasoning.start", id, ...model2 ? { model: model2 } : {} });
53954
53836
  return id;
53955
53837
  },
53956
53838
  appendReasoning(id, chunk) {
53957
- if (chunk.length > 0) dispatch2({ type: "reasoning.chunk", id, text: chunk });
53839
+ if (chunk.length > 0) dispatch({ type: "reasoning.chunk", id, text: chunk });
53958
53840
  },
53959
53841
  endReasoning(id, paragraphs, tokens, aborted) {
53960
- dispatch2({ type: "reasoning.end", id, paragraphs, tokens, aborted });
53842
+ dispatch({ type: "reasoning.end", id, paragraphs, tokens, aborted });
53961
53843
  },
53962
53844
  startStreaming(model2) {
53963
53845
  const id = nextId2("s");
53964
- dispatch2({ type: "streaming.start", id, ...model2 ? { model: model2 } : {} });
53846
+ dispatch({ type: "streaming.start", id, ...model2 ? { model: model2 } : {} });
53965
53847
  return id;
53966
53848
  },
53967
53849
  appendStreaming(id, chunk) {
53968
- if (chunk.length > 0) dispatch2({ type: "streaming.chunk", id, text: chunk });
53850
+ if (chunk.length > 0) dispatch({ type: "streaming.chunk", id, text: chunk });
53969
53851
  },
53970
53852
  endStreaming(id, aborted) {
53971
- dispatch2({ type: "streaming.end", id, aborted });
53853
+ dispatch({ type: "streaming.end", id, aborted });
53972
53854
  },
53973
53855
  startTool(name, args, presetId) {
53974
53856
  const id = presetId ?? nextId2("tool");
53975
- dispatch2({ type: "tool.start", id, name, args });
53857
+ dispatch({ type: "tool.start", id, name, args });
53976
53858
  return id;
53977
53859
  },
53978
53860
  appendToolOutput(id, chunk) {
53979
- if (chunk.length > 0) dispatch2({ type: "tool.chunk", id, text: chunk });
53861
+ if (chunk.length > 0) dispatch({ type: "tool.chunk", id, text: chunk });
53980
53862
  },
53981
53863
  endTool(id, info) {
53982
- dispatch2({
53864
+ dispatch({
53983
53865
  type: "tool.end",
53984
53866
  id,
53985
53867
  output: info.output,
@@ -53989,18 +53871,18 @@ ${stack}` : message
53989
53871
  });
53990
53872
  },
53991
53873
  retryTool(id, attempt, max) {
53992
- dispatch2({ type: "tool.retry", id, attempt, max });
53874
+ dispatch({ type: "tool.retry", id, attempt, max });
53993
53875
  },
53994
53876
  thinking() {
53995
53877
  const id = nextId2("think");
53996
- dispatch2({ type: "turn.thinking" });
53878
+ dispatch({ type: "turn.thinking" });
53997
53879
  return id;
53998
53880
  },
53999
53881
  abortTurn() {
54000
- dispatch2({ type: "turn.abort" });
53882
+ dispatch({ type: "turn.abort" });
54001
53883
  },
54002
53884
  endTurn(usage, extras) {
54003
- dispatch2({
53885
+ dispatch({
54004
53886
  type: "turn.end",
54005
53887
  usage,
54006
53888
  promptCap: extras?.promptCap,
@@ -54009,10 +53891,10 @@ ${stack}` : message
54009
53891
  });
54010
53892
  },
54011
53893
  reset() {
54012
- dispatch2({ type: "session.reset" });
53894
+ dispatch({ type: "session.reset" });
54013
53895
  }
54014
53896
  }),
54015
- [dispatch2]
53897
+ [dispatch]
54016
53898
  );
54017
53899
  }
54018
53900
 
@@ -56275,7 +56157,7 @@ function bodyColor(toast, now) {
56275
56157
  }
56276
56158
  function ToastRail() {
56277
56159
  const toasts = useAgentState((s) => s.toasts);
56278
- const dispatch2 = useDispatch();
56160
+ const dispatch = useDispatch();
56279
56161
  useSlowTick();
56280
56162
  const { stdout } = use_stdout_default();
56281
56163
  const cols = stdout?.columns ?? 80;
@@ -56285,12 +56167,12 @@ function ToastRail() {
56285
56167
  const timers = [];
56286
56168
  for (const t2 of toasts) {
56287
56169
  const remaining = Math.max(0, t2.ttlMs - (Date.now() - t2.bornAt));
56288
- timers.push(setTimeout(() => dispatch2({ type: "toast.hide", id: t2.id }), remaining));
56170
+ timers.push(setTimeout(() => dispatch({ type: "toast.hide", id: t2.id }), remaining));
56289
56171
  }
56290
56172
  return () => {
56291
56173
  for (const id of timers) clearTimeout(id);
56292
56174
  };
56293
- }, [toasts, dispatch2]);
56175
+ }, [toasts, dispatch]);
56294
56176
  const visible = toasts.filter((t2) => now - t2.bornAt < t2.ttlMs);
56295
56177
  if (visible.length === 0) return null;
56296
56178
  return /* @__PURE__ */ import_react82.default.createElement(Box_default, { flexDirection: "column" }, visible.map((t2) => {
@@ -56574,7 +56456,7 @@ function replaceMcpServerSummary(servers, target, updated) {
56574
56456
  }
56575
56457
 
56576
56458
  // src/cli/ui/open-url.ts
56577
- import { spawn as spawn3 } from "child_process";
56459
+ import { spawn as spawn2 } from "child_process";
56578
56460
  import { platform } from "os";
56579
56461
  function openUrl(url) {
56580
56462
  if (process.env.CI) return { opened: false, reason: "ci" };
@@ -56593,7 +56475,7 @@ function openUrl(url) {
56593
56475
  args = [url];
56594
56476
  }
56595
56477
  try {
56596
- const child = spawn3(cmd, args, { detached: true, stdio: "ignore" });
56478
+ const child = spawn2(cmd, args, { detached: true, stdio: "ignore" });
56597
56479
  child.unref();
56598
56480
  return { opened: true };
56599
56481
  } catch {
@@ -63413,122 +63295,6 @@ async function drainTtyResponses(timeoutMs = 50) {
63413
63295
  });
63414
63296
  }
63415
63297
 
63416
- // src/cli/ui/scene/input-source.ts
63417
- import { spawn as spawn4 } from "child_process";
63418
- function spawnInputSource(opts) {
63419
- const command = opts.command;
63420
- const [cmd, ...args] = command;
63421
- if (!cmd) {
63422
- throw new Error("spawnInputSource: empty command");
63423
- }
63424
- const child = spawn4(cmd, args, {
63425
- cwd: opts.cwd,
63426
- env: opts.env ?? process.env,
63427
- stdio: ["ignore", "pipe", "inherit"]
63428
- });
63429
- const buses = { keys: /* @__PURE__ */ new Set(), pastes: /* @__PURE__ */ new Set(), mice: /* @__PURE__ */ new Set() };
63430
- let buf = "";
63431
- child.stdout?.setEncoding("utf8");
63432
- child.stdout?.on("data", (chunk) => {
63433
- buf += chunk;
63434
- let nl = buf.indexOf("\n");
63435
- while (nl >= 0) {
63436
- const line = buf.slice(0, nl);
63437
- buf = buf.slice(nl + 1);
63438
- dispatch(line, buses);
63439
- nl = buf.indexOf("\n");
63440
- }
63441
- });
63442
- child.stdout?.on("end", () => {
63443
- if (buf.length > 0) {
63444
- dispatch(buf, buses);
63445
- buf = "";
63446
- }
63447
- });
63448
- const exitPromise = new Promise((resolve3) => {
63449
- child.once("exit", (code) => resolve3(code));
63450
- });
63451
- return {
63452
- onKey(handler) {
63453
- buses.keys.add(handler);
63454
- return () => {
63455
- buses.keys.delete(handler);
63456
- };
63457
- },
63458
- onPaste(handler) {
63459
- buses.pastes.add(handler);
63460
- return () => {
63461
- buses.pastes.delete(handler);
63462
- };
63463
- },
63464
- onMouse(handler) {
63465
- buses.mice.add(handler);
63466
- return () => {
63467
- buses.mice.delete(handler);
63468
- };
63469
- },
63470
- async close() {
63471
- if (child.exitCode === null && !child.killed) {
63472
- child.kill("SIGINT");
63473
- }
63474
- return exitPromise;
63475
- },
63476
- wait() {
63477
- return exitPromise;
63478
- }
63479
- };
63480
- }
63481
- function dispatch(line, buses) {
63482
- if (line.trim().length === 0) return;
63483
- let parsed;
63484
- try {
63485
- parsed = JSON.parse(line);
63486
- } catch {
63487
- return;
63488
- }
63489
- if (isKeyEvent(parsed)) {
63490
- for (const handler of buses.keys) handler(parsed);
63491
- return;
63492
- }
63493
- if (isPasteEvent(parsed)) {
63494
- for (const handler of buses.pastes) handler(parsed);
63495
- return;
63496
- }
63497
- if (isMouseEvent(parsed)) {
63498
- for (const handler of buses.mice) handler(parsed);
63499
- return;
63500
- }
63501
- }
63502
- function isKeyEvent(value) {
63503
- if (typeof value !== "object" || value === null) return false;
63504
- const obj = value;
63505
- if (obj.event !== "key" || typeof obj.code !== "string") return false;
63506
- if (obj.char !== void 0 && typeof obj.char !== "string") return false;
63507
- if (obj.modifiers !== void 0 && !Array.isArray(obj.modifiers)) return false;
63508
- return true;
63509
- }
63510
- function isPasteEvent(value) {
63511
- if (typeof value !== "object" || value === null) return false;
63512
- const obj = value;
63513
- return obj.event === "paste" && typeof obj.text === "string";
63514
- }
63515
- var MOUSE_KINDS = /* @__PURE__ */ new Set([
63516
- "click",
63517
- "drag",
63518
- "release",
63519
- "scroll-up",
63520
- "scroll-down"
63521
- ]);
63522
- function isMouseEvent(value) {
63523
- if (typeof value !== "object" || value === null) return false;
63524
- const obj = value;
63525
- if (obj.event !== "mouse") return false;
63526
- if (typeof obj.kind !== "string" || !MOUSE_KINDS.has(obj.kind)) return false;
63527
- if (typeof obj.row !== "number" || typeof obj.col !== "number") return false;
63528
- if (obj.modifiers !== void 0 && !Array.isArray(obj.modifiers)) return false;
63529
- return true;
63530
- }
63531
-
63532
63298
  // src/cli/ui/scene/input-adapter.ts
63533
63299
  var nullKeystrokeReader = {
63534
63300
  start() {
@@ -63538,115 +63304,6 @@ var nullKeystrokeReader = {
63538
63304
  };
63539
63305
  }
63540
63306
  };
63541
- function createRustKeystrokeReader(opts) {
63542
- const source = spawnInputSource(opts);
63543
- const handlers19 = /* @__PURE__ */ new Set();
63544
- source.onKey((rust) => {
63545
- const ev = translate(rust);
63546
- if (!ev) return;
63547
- for (const h of handlers19) h(ev);
63548
- });
63549
- source.onPaste((rust) => {
63550
- const ev = translatePaste(rust);
63551
- for (const h of handlers19) h(ev);
63552
- });
63553
- source.onMouse((rust) => {
63554
- const ev = translateMouse(rust);
63555
- for (const h of handlers19) h(ev);
63556
- });
63557
- return {
63558
- start() {
63559
- },
63560
- subscribe(handler) {
63561
- handlers19.add(handler);
63562
- return () => {
63563
- handlers19.delete(handler);
63564
- };
63565
- },
63566
- close() {
63567
- return source.close();
63568
- },
63569
- wait() {
63570
- return source.wait();
63571
- }
63572
- };
63573
- }
63574
- function translate(rust) {
63575
- const mods = new Set(rust.modifiers ?? []);
63576
- const ctrl = mods.has("ctrl");
63577
- const shift = mods.has("shift");
63578
- const alt = mods.has("alt");
63579
- switch (rust.code) {
63580
- case "Char": {
63581
- if (rust.char === void 0) return null;
63582
- const ev = { input: rust.char };
63583
- if (ctrl) ev.ctrl = true;
63584
- if (alt) ev.meta = true;
63585
- if (shift) ev.shift = true;
63586
- return ev;
63587
- }
63588
- case "Enter":
63589
- return withMods({ input: "", return: true }, ctrl, shift, alt);
63590
- case "Esc":
63591
- return { input: "", escape: true };
63592
- case "Up":
63593
- return { input: "", upArrow: true };
63594
- case "Down":
63595
- return { input: "", downArrow: true };
63596
- case "Left":
63597
- return { input: "", leftArrow: true };
63598
- case "Right":
63599
- return { input: "", rightArrow: true };
63600
- case "Backspace":
63601
- return { input: "", backspace: true };
63602
- case "Tab":
63603
- return withMods({ input: "", tab: true }, ctrl, shift, alt);
63604
- case "BackTab":
63605
- return { input: "", tab: true, shift: true };
63606
- case "Home":
63607
- return { input: "", home: true };
63608
- case "End":
63609
- return { input: "", end: true };
63610
- case "PageUp":
63611
- return { input: "", pageUp: true };
63612
- case "PageDown":
63613
- return { input: "", pageDown: true };
63614
- case "Delete":
63615
- return { input: "", delete: true };
63616
- default:
63617
- return null;
63618
- }
63619
- }
63620
- function withMods(ev, ctrl, shift, alt) {
63621
- if (ctrl) ev.ctrl = true;
63622
- if (shift) ev.shift = true;
63623
- if (alt) ev.meta = true;
63624
- return ev;
63625
- }
63626
- function translatePaste(rust) {
63627
- return { input: sanitizePasteText(rust.text), paste: true };
63628
- }
63629
- function translateMouse(rust) {
63630
- const ev = { input: "", mouseRow: rust.row, mouseCol: rust.col };
63631
- switch (rust.kind) {
63632
- case "click":
63633
- ev.mouseClick = true;
63634
- break;
63635
- case "drag":
63636
- ev.mouseDrag = true;
63637
- break;
63638
- case "release":
63639
- ev.mouseRelease = true;
63640
- break;
63641
- case "scroll-up":
63642
- ev.mouseScrollUp = true;
63643
- break;
63644
- case "scroll-down":
63645
- ev.mouseScrollDown = true;
63646
- break;
63647
- }
63648
- return ev;
63649
- }
63650
63307
 
63651
63308
  // src/cli/ui/scene/null-stdin.ts
63652
63309
  import { Readable } from "stream";
@@ -63893,27 +63550,21 @@ async function chatCommand(opts) {
63893
63550
  `);
63894
63551
  }
63895
63552
  }
63896
- let rustRendererActive = process.env.REASONIX_RENDERER !== "node";
63897
- let resolved = rustRendererActive ? resolveRenderer() : void 0;
63898
- if (rustRendererActive && (!resolved || resolved.source === null)) {
63553
+ let rustRendererActive = isIntegratedRendererRequested();
63554
+ if (process.env.REASONIX_RENDERER !== "node" && !rustRendererActive) {
63899
63555
  process.stderr.write(
63900
- `\u25B2 Rust renderer binary not found \u2014 falling back to the Node/Ink TUI.
63901
- Install @reasonix/render-${process.platform}-${process.arch}, set REASONIX_RENDER_BIN to a built binary, or run from source with cargo on PATH.
63556
+ `\u25B2 Rust renderer native binding not loadable for ${process.platform}-${process.arch} \u2014 falling back to the Node/Ink TUI.
63557
+ Run \`npm run build:rust\` for a source build, or reinstall reasonix to fetch the optional dep.
63902
63558
  `
63903
63559
  );
63904
63560
  process.env.REASONIX_RENDERER = "node";
63905
63561
  rustRendererActive = false;
63906
- resolved = void 0;
63907
63562
  }
63908
- const rustIntegrated = rustRendererActive && isIntegratedRendererRequested();
63909
63563
  const inkStdout = rustRendererActive ? makeNullStdout() : void 0;
63910
63564
  const inkStdin = rustRendererActive ? makeNullStdin() : void 0;
63911
- const rustInputChild = rustRendererActive && !rustIntegrated && resolved ? createRustKeystrokeReader({ command: resolved.inputCommand }) : void 0;
63912
- const keystrokeReader = rustIntegrated ? nullKeystrokeReader : rustInputChild;
63565
+ const keystrokeReader = rustRendererActive ? nullKeystrokeReader : void 0;
63913
63566
  const stderrRestore = rustRendererActive ? redirectStderrToLogFile() : void 0;
63914
- const rustKeepAlive = rustRendererActive ? setInterval(() => {
63915
- }, 2147483647) : void 0;
63916
- if (rustIntegrated) {
63567
+ if (rustRendererActive) {
63917
63568
  setIntegratedEventHandler((event) => {
63918
63569
  if (event.event === "submit") {
63919
63570
  qqSubmitRef.current?.(event.text);
@@ -63985,10 +63636,8 @@ async function chatCommand(opts) {
63985
63636
  try {
63986
63637
  await waitUntilExit();
63987
63638
  } finally {
63988
- if (rustKeepAlive) clearInterval(rustKeepAlive);
63989
63639
  await runtime.closeAll();
63990
63640
  qqChannel?.stop();
63991
- if (rustInputChild) await rustInputChild.close();
63992
63641
  if (stderrRestore) stderrRestore();
63993
63642
  await drainTtyResponses();
63994
63643
  }
@@ -63997,4 +63646,4 @@ async function chatCommand(opts) {
63997
63646
  export {
63998
63647
  chatCommand
63999
63648
  };
64000
- //# sourceMappingURL=chunk-DFP43NI5.js.map
63649
+ //# sourceMappingURL=chunk-KQBNRLFZ.js.map