reasonix 0.11.0 → 0.11.1
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/{chunk-GXABXQMU.js → chunk-JDVY4JDU.js} +11 -1
- package/dist/cli/chunk-JDVY4JDU.js.map +1 -0
- package/dist/cli/index.js +500 -189
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{prompt-FMYQ7IDW.js → prompt-YRY4HPMZ.js} +2 -2
- package/dist/index.d.ts +7 -3
- package/dist/index.js +45 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/cli/chunk-GXABXQMU.js.map +0 -1
- /package/dist/cli/{prompt-FMYQ7IDW.js.map → prompt-YRY4HPMZ.js.map} +0 -0
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
memoryEnabled,
|
|
11
11
|
readProjectMemory,
|
|
12
12
|
sanitizeMemoryName
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-JDVY4JDU.js";
|
|
14
14
|
|
|
15
15
|
// src/cli/index.ts
|
|
16
16
|
import { Command } from "commander";
|
|
@@ -156,8 +156,8 @@ function computeWait(attempt, initial, cap, retryAfter) {
|
|
|
156
156
|
}
|
|
157
157
|
function sleep(ms, signal) {
|
|
158
158
|
if (ms <= 0) return Promise.resolve();
|
|
159
|
-
return new Promise((
|
|
160
|
-
const timer = setTimeout(
|
|
159
|
+
return new Promise((resolve12, reject) => {
|
|
160
|
+
const timer = setTimeout(resolve12, ms);
|
|
161
161
|
if (signal) {
|
|
162
162
|
const onAbort = () => {
|
|
163
163
|
clearTimeout(timer);
|
|
@@ -642,7 +642,7 @@ function matchesTool(hook, toolName) {
|
|
|
642
642
|
}
|
|
643
643
|
}
|
|
644
644
|
function defaultSpawner(input) {
|
|
645
|
-
return new Promise((
|
|
645
|
+
return new Promise((resolve12) => {
|
|
646
646
|
const child = spawn(input.command, {
|
|
647
647
|
cwd: input.cwd,
|
|
648
648
|
shell: true,
|
|
@@ -669,7 +669,7 @@ function defaultSpawner(input) {
|
|
|
669
669
|
});
|
|
670
670
|
child.once("error", (err) => {
|
|
671
671
|
clearTimeout(timer);
|
|
672
|
-
|
|
672
|
+
resolve12({
|
|
673
673
|
exitCode: null,
|
|
674
674
|
stdout: stdout3,
|
|
675
675
|
stderr,
|
|
@@ -679,7 +679,7 @@ function defaultSpawner(input) {
|
|
|
679
679
|
});
|
|
680
680
|
child.once("close", (code) => {
|
|
681
681
|
clearTimeout(timer);
|
|
682
|
-
|
|
682
|
+
resolve12({
|
|
683
683
|
exitCode: code,
|
|
684
684
|
stdout: stdout3.trim(),
|
|
685
685
|
stderr: stderr.trim(),
|
|
@@ -720,8 +720,8 @@ async function runHooks(opts) {
|
|
|
720
720
|
for (const hook of matching) {
|
|
721
721
|
const start = Date.now();
|
|
722
722
|
const timeoutMs = hook.timeout ?? DEFAULT_TIMEOUTS_MS[event];
|
|
723
|
-
const
|
|
724
|
-
const raw = await spawner({ command: hook.command, cwd, stdin: stdin4, timeoutMs });
|
|
723
|
+
const cwd2 = hook.cwd ?? opts.payload.cwd;
|
|
724
|
+
const raw = await spawner({ command: hook.command, cwd: cwd2, stdin: stdin4, timeoutMs });
|
|
725
725
|
const decision = decideOutcome(event, raw);
|
|
726
726
|
outcomes.push({
|
|
727
727
|
hook,
|
|
@@ -1867,7 +1867,11 @@ var CacheFirstLoop = class {
|
|
|
1867
1867
|
* tool call is one array length check.
|
|
1868
1868
|
*/
|
|
1869
1869
|
hooks;
|
|
1870
|
-
/**
|
|
1870
|
+
/**
|
|
1871
|
+
* `cwd` reported to hook stdin. Mutable so `/cwd` can switch the
|
|
1872
|
+
* working directory mid-session — the App keeps it in sync with
|
|
1873
|
+
* the same currentRootDir that drives tool re-registration.
|
|
1874
|
+
*/
|
|
1871
1875
|
hookCwd;
|
|
1872
1876
|
/** Number of messages that were pre-loaded from the session file. */
|
|
1873
1877
|
resumedMessageCount;
|
|
@@ -2344,6 +2348,7 @@ var CacheFirstLoop = class {
|
|
|
2344
2348
|
};
|
|
2345
2349
|
this.autoCompactToolResultsOnTurnEnd();
|
|
2346
2350
|
yield { turn: this._turn, role: "done", content: stoppedMsg };
|
|
2351
|
+
this._turnAbort = new AbortController();
|
|
2347
2352
|
return;
|
|
2348
2353
|
}
|
|
2349
2354
|
if (iter > 0) {
|
|
@@ -2437,8 +2442,8 @@ var CacheFirstLoop = class {
|
|
|
2437
2442
|
}
|
|
2438
2443
|
);
|
|
2439
2444
|
for (let k = 0; k < budget; k++) {
|
|
2440
|
-
const sample = queue.shift() ?? await new Promise((
|
|
2441
|
-
waiter =
|
|
2445
|
+
const sample = queue.shift() ?? await new Promise((resolve12) => {
|
|
2446
|
+
waiter = resolve12;
|
|
2442
2447
|
});
|
|
2443
2448
|
yield {
|
|
2444
2449
|
turn: this._turn,
|
|
@@ -5168,7 +5173,7 @@ async function runCommand(cmd, opts) {
|
|
|
5168
5173
|
};
|
|
5169
5174
|
const { bin, args, spawnOverrides } = prepareSpawn(argv);
|
|
5170
5175
|
const effectiveSpawnOpts = { ...spawnOpts, ...spawnOverrides };
|
|
5171
|
-
return await new Promise((
|
|
5176
|
+
return await new Promise((resolve12, reject) => {
|
|
5172
5177
|
let child;
|
|
5173
5178
|
try {
|
|
5174
5179
|
child = spawn3(bin, args, effectiveSpawnOpts);
|
|
@@ -5176,7 +5181,9 @@ async function runCommand(cmd, opts) {
|
|
|
5176
5181
|
reject(err);
|
|
5177
5182
|
return;
|
|
5178
5183
|
}
|
|
5179
|
-
|
|
5184
|
+
const chunks = [];
|
|
5185
|
+
let totalBytes = 0;
|
|
5186
|
+
const byteCap = maxChars * 2 * 4;
|
|
5180
5187
|
let timedOut = false;
|
|
5181
5188
|
const killTimer = setTimeout(() => {
|
|
5182
5189
|
timedOut = true;
|
|
@@ -5185,8 +5192,16 @@ async function runCommand(cmd, opts) {
|
|
|
5185
5192
|
const onAbort = () => child.kill("SIGKILL");
|
|
5186
5193
|
opts.signal?.addEventListener("abort", onAbort, { once: true });
|
|
5187
5194
|
const onData = (chunk) => {
|
|
5188
|
-
|
|
5189
|
-
if (
|
|
5195
|
+
const b = typeof chunk === "string" ? Buffer.from(chunk) : chunk;
|
|
5196
|
+
if (totalBytes >= byteCap) return;
|
|
5197
|
+
const remaining = byteCap - totalBytes;
|
|
5198
|
+
if (b.length > remaining) {
|
|
5199
|
+
chunks.push(b.subarray(0, remaining));
|
|
5200
|
+
totalBytes = byteCap;
|
|
5201
|
+
} else {
|
|
5202
|
+
chunks.push(b);
|
|
5203
|
+
totalBytes += b.length;
|
|
5204
|
+
}
|
|
5190
5205
|
};
|
|
5191
5206
|
child.stdout?.on("data", onData);
|
|
5192
5207
|
child.stderr?.on("data", onData);
|
|
@@ -5198,13 +5213,29 @@ async function runCommand(cmd, opts) {
|
|
|
5198
5213
|
child.on("close", (code) => {
|
|
5199
5214
|
clearTimeout(killTimer);
|
|
5200
5215
|
opts.signal?.removeEventListener("abort", onAbort);
|
|
5216
|
+
const merged = Buffer.concat(chunks);
|
|
5217
|
+
const buf = smartDecodeOutput(merged);
|
|
5201
5218
|
const output = buf.length > maxChars ? `${buf.slice(0, maxChars)}
|
|
5202
5219
|
|
|
5203
5220
|
[\u2026 truncated ${buf.length - maxChars} chars \u2026]` : buf;
|
|
5204
|
-
|
|
5221
|
+
resolve12({ exitCode: code, output, timedOut });
|
|
5205
5222
|
});
|
|
5206
5223
|
});
|
|
5207
5224
|
}
|
|
5225
|
+
function smartDecodeOutput(buf) {
|
|
5226
|
+
if (buf.length === 0) return "";
|
|
5227
|
+
try {
|
|
5228
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(buf);
|
|
5229
|
+
} catch {
|
|
5230
|
+
}
|
|
5231
|
+
if (process.platform === "win32") {
|
|
5232
|
+
try {
|
|
5233
|
+
return new TextDecoder("gb18030").decode(buf);
|
|
5234
|
+
} catch {
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
return buf.toString("utf8");
|
|
5238
|
+
}
|
|
5208
5239
|
function resolveExecutable(cmd, opts = {}) {
|
|
5209
5240
|
const platform = opts.platform ?? process.platform;
|
|
5210
5241
|
if (platform !== "win32") return cmd;
|
|
@@ -6391,7 +6422,7 @@ var McpClient = class {
|
|
|
6391
6422
|
const id = this.nextId++;
|
|
6392
6423
|
const frame = { jsonrpc: "2.0", id, method, params };
|
|
6393
6424
|
let abortHandler = null;
|
|
6394
|
-
const promise = new Promise((
|
|
6425
|
+
const promise = new Promise((resolve12, reject) => {
|
|
6395
6426
|
const timeout = setTimeout(() => {
|
|
6396
6427
|
this.pending.delete(id);
|
|
6397
6428
|
if (abortHandler && signal) signal.removeEventListener("abort", abortHandler);
|
|
@@ -6400,7 +6431,7 @@ var McpClient = class {
|
|
|
6400
6431
|
);
|
|
6401
6432
|
}, this.requestTimeoutMs);
|
|
6402
6433
|
this.pending.set(id, {
|
|
6403
|
-
resolve:
|
|
6434
|
+
resolve: resolve12,
|
|
6404
6435
|
reject,
|
|
6405
6436
|
timeout
|
|
6406
6437
|
});
|
|
@@ -6523,12 +6554,12 @@ var StdioTransport = class {
|
|
|
6523
6554
|
}
|
|
6524
6555
|
async send(message) {
|
|
6525
6556
|
if (this.closed) throw new Error("MCP transport is closed");
|
|
6526
|
-
return new Promise((
|
|
6557
|
+
return new Promise((resolve12, reject) => {
|
|
6527
6558
|
const line = `${JSON.stringify(message)}
|
|
6528
6559
|
`;
|
|
6529
6560
|
this.child.stdin.write(line, "utf8", (err) => {
|
|
6530
6561
|
if (err) reject(err);
|
|
6531
|
-
else
|
|
6562
|
+
else resolve12();
|
|
6532
6563
|
});
|
|
6533
6564
|
});
|
|
6534
6565
|
}
|
|
@@ -6539,8 +6570,8 @@ var StdioTransport = class {
|
|
|
6539
6570
|
continue;
|
|
6540
6571
|
}
|
|
6541
6572
|
if (this.closed) return;
|
|
6542
|
-
const next = await new Promise((
|
|
6543
|
-
this.waiters.push(
|
|
6573
|
+
const next = await new Promise((resolve12) => {
|
|
6574
|
+
this.waiters.push(resolve12);
|
|
6544
6575
|
});
|
|
6545
6576
|
if (next === null) return;
|
|
6546
6577
|
yield next;
|
|
@@ -6606,8 +6637,8 @@ var SseTransport = class {
|
|
|
6606
6637
|
constructor(opts) {
|
|
6607
6638
|
this.url = opts.url;
|
|
6608
6639
|
this.headers = opts.headers ?? {};
|
|
6609
|
-
this.endpointReady = new Promise((
|
|
6610
|
-
this.resolveEndpoint =
|
|
6640
|
+
this.endpointReady = new Promise((resolve12, reject) => {
|
|
6641
|
+
this.resolveEndpoint = resolve12;
|
|
6611
6642
|
this.rejectEndpoint = reject;
|
|
6612
6643
|
});
|
|
6613
6644
|
this.endpointReady.catch(() => void 0);
|
|
@@ -6634,8 +6665,8 @@ var SseTransport = class {
|
|
|
6634
6665
|
continue;
|
|
6635
6666
|
}
|
|
6636
6667
|
if (this.closed) return;
|
|
6637
|
-
const next = await new Promise((
|
|
6638
|
-
this.waiters.push(
|
|
6668
|
+
const next = await new Promise((resolve12) => {
|
|
6669
|
+
this.waiters.push(resolve12);
|
|
6639
6670
|
});
|
|
6640
6671
|
if (next === null) return;
|
|
6641
6672
|
yield next;
|
|
@@ -7223,13 +7254,14 @@ function formatLogSize(path5 = defaultUsageLogPath()) {
|
|
|
7223
7254
|
}
|
|
7224
7255
|
|
|
7225
7256
|
// src/cli/commands/chat.tsx
|
|
7226
|
-
import { existsSync as
|
|
7257
|
+
import { existsSync as existsSync15, statSync as statSync9 } from "fs";
|
|
7227
7258
|
import { render } from "ink";
|
|
7228
|
-
import
|
|
7259
|
+
import React27, { useState as useState12 } from "react";
|
|
7229
7260
|
|
|
7230
7261
|
// src/cli/ui/App.tsx
|
|
7231
|
-
import
|
|
7232
|
-
import
|
|
7262
|
+
import * as pathMod6 from "path";
|
|
7263
|
+
import { Box as Box22, Static, Text as Text20, useApp, useStdout as useStdout8 } from "ink";
|
|
7264
|
+
import React24, { useCallback as useCallback4, useEffect as useEffect6, useMemo as useMemo3, useRef as useRef6, useState as useState10 } from "react";
|
|
7233
7265
|
|
|
7234
7266
|
// src/code/pending-edits.ts
|
|
7235
7267
|
import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
@@ -7521,6 +7553,60 @@ ${skill2.body}${argsBlock}`;
|
|
|
7521
7553
|
return registry;
|
|
7522
7554
|
}
|
|
7523
7555
|
|
|
7556
|
+
// src/tools/workspace.ts
|
|
7557
|
+
import { existsSync as existsSync11, statSync as statSync6 } from "fs";
|
|
7558
|
+
import * as pathMod4 from "path";
|
|
7559
|
+
var WorkspaceConfirmationError = class extends Error {
|
|
7560
|
+
path;
|
|
7561
|
+
constructor(path5) {
|
|
7562
|
+
super(
|
|
7563
|
+
`change_workspace: switching to "${path5}" needs the user's approval before it takes effect. STOP calling tools now \u2014 the TUI has already prompted the user to press Enter (switch) or Esc (deny). Wait for their next message; it will either confirm the switch (and your subsequent file/shell tools will resolve against the new root) or tell you to continue without changing directories.`
|
|
7564
|
+
);
|
|
7565
|
+
this.name = "WorkspaceConfirmationError";
|
|
7566
|
+
this.path = path5;
|
|
7567
|
+
}
|
|
7568
|
+
};
|
|
7569
|
+
function registerWorkspaceTool(registry) {
|
|
7570
|
+
registry.register({
|
|
7571
|
+
name: "change_workspace",
|
|
7572
|
+
description: "Switch the session's working directory to a different project root. Re-registers filesystem / shell / memory tools against the new path so subsequent file reads, edits, and run_command calls all land there. EVERY switch requires explicit user approval via a modal \u2014 do NOT batch switches or chain a switch with subsequent tool calls before the user has confirmed. Use ONLY when the user explicitly asked to change directory or open a different project; never use to 'preview' a sibling repo. MCP servers stay anchored to the original launch root (their child processes can't be reconnected mid-session); the modal warns the user about this.",
|
|
7573
|
+
parameters: {
|
|
7574
|
+
type: "object",
|
|
7575
|
+
required: ["path"],
|
|
7576
|
+
properties: {
|
|
7577
|
+
path: {
|
|
7578
|
+
type: "string",
|
|
7579
|
+
description: "Target directory. Absolute paths land verbatim. Leading `~` expands to the user's home. Relative paths resolve against the user's launch cwd (not the current session root, so paths the user typed in chat resolve where they expect)."
|
|
7580
|
+
}
|
|
7581
|
+
}
|
|
7582
|
+
},
|
|
7583
|
+
fn: (rawArgs) => {
|
|
7584
|
+
const args = rawArgs ?? {};
|
|
7585
|
+
if (typeof args.path !== "string" || args.path.trim() === "") {
|
|
7586
|
+
throw new Error("change_workspace: `path` must be a non-empty string");
|
|
7587
|
+
}
|
|
7588
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
7589
|
+
const expanded = args.path.startsWith("~") && home ? pathMod4.join(home, args.path.slice(1)) : args.path;
|
|
7590
|
+
const abs = pathMod4.resolve(expanded);
|
|
7591
|
+
if (!existsSync11(abs)) {
|
|
7592
|
+
throw new Error(`change_workspace: path does not exist \u2014 ${abs}`);
|
|
7593
|
+
}
|
|
7594
|
+
try {
|
|
7595
|
+
if (!statSync6(abs).isDirectory()) {
|
|
7596
|
+
throw new Error(`change_workspace: not a directory \u2014 ${abs}`);
|
|
7597
|
+
}
|
|
7598
|
+
} catch (err) {
|
|
7599
|
+
if (err.code === "ENOENT") {
|
|
7600
|
+
throw new Error(`change_workspace: path does not exist \u2014 ${abs}`);
|
|
7601
|
+
}
|
|
7602
|
+
throw err;
|
|
7603
|
+
}
|
|
7604
|
+
throw new WorkspaceConfirmationError(abs);
|
|
7605
|
+
}
|
|
7606
|
+
});
|
|
7607
|
+
return registry;
|
|
7608
|
+
}
|
|
7609
|
+
|
|
7524
7610
|
// src/cli/ui/AtMentionSuggestions.tsx
|
|
7525
7611
|
import { Box, Text } from "ink";
|
|
7526
7612
|
import React from "react";
|
|
@@ -8315,8 +8401,8 @@ function RiskLegend() {
|
|
|
8315
8401
|
var PlanStepList = React8.memo(PlanStepListInner);
|
|
8316
8402
|
|
|
8317
8403
|
// src/cli/ui/markdown.tsx
|
|
8318
|
-
import { readFileSync as readFileSync13, statSync as
|
|
8319
|
-
import { isAbsolute as isAbsolute4, join as
|
|
8404
|
+
import { readFileSync as readFileSync13, statSync as statSync7 } from "fs";
|
|
8405
|
+
import { isAbsolute as isAbsolute4, join as join12 } from "path";
|
|
8320
8406
|
import { Box as Box8, Text as Text7 } from "ink";
|
|
8321
8407
|
import React9 from "react";
|
|
8322
8408
|
var SUPERSCRIPT = {
|
|
@@ -8358,7 +8444,32 @@ function toSubscript(s) {
|
|
|
8358
8444
|
for (const c of s) out += SUBSCRIPT[c] ?? c;
|
|
8359
8445
|
return out;
|
|
8360
8446
|
}
|
|
8447
|
+
var HAS_MATH_RE = new RegExp(
|
|
8448
|
+
[
|
|
8449
|
+
"\\$",
|
|
8450
|
+
// dollar-delimited (block or inline)
|
|
8451
|
+
"\\\\[([]",
|
|
8452
|
+
// \( or \[
|
|
8453
|
+
"\\\\[a-zA-Z]+\\s*\\{",
|
|
8454
|
+
// \anyCommand{...} — covers catch-all braced transforms
|
|
8455
|
+
// Bare (no-brace) LaTeX commands the pipeline knows how to handle.
|
|
8456
|
+
// Listed explicitly because a generic `\\[a-zA-Z]+` would also match
|
|
8457
|
+
// Windows paths (`F:\TEST1`) and re-introduce the bug we're fixing.
|
|
8458
|
+
"\\\\(?:cdot|times|div|pm|mp|leq|geq|neq|approx|in|notin|infty|sum|prod|int|alpha|beta|gamma|delta|theta|lambda|mu|pi|sigma|phi|omega|implies|iff|to|rightarrow|leftarrow|Rightarrow|Leftarrow|ldots|cdots|quad|qquad)(?![a-zA-Z])",
|
|
8459
|
+
"[\\^_]\\{",
|
|
8460
|
+
// LaTeX braced super/subscript: ^{2}, _{ij}
|
|
8461
|
+
"\\^[0-9+\\-n](?![A-Za-z])",
|
|
8462
|
+
// LaTeX single-char super: ^2, ^-, ^n
|
|
8463
|
+
"_[0-9+\\-](?![A-Za-z])",
|
|
8464
|
+
// LaTeX single-char sub: _1, _+, _-
|
|
8465
|
+
"\\^[A-Za-z0-9+\\-]+\\^",
|
|
8466
|
+
// Pandoc super: ^2^, ^abc^
|
|
8467
|
+
"(?<!~)~[A-Za-z0-9+\\-]+~(?!~)"
|
|
8468
|
+
// Pandoc sub: ~2~ (lookarounds avoid ~~strike~~)
|
|
8469
|
+
].join("|")
|
|
8470
|
+
);
|
|
8361
8471
|
function stripMath(s) {
|
|
8472
|
+
if (!HAS_MATH_RE.test(s)) return s;
|
|
8362
8473
|
return s.replace(/\$\$([\s\S]+?)\$\$/g, (_m, c) => `
|
|
8363
8474
|
|
|
8364
8475
|
${c.trim()}
|
|
@@ -8532,7 +8643,7 @@ function validateCitation(url, projectRoot) {
|
|
|
8532
8643
|
const parts = parseCitationUrl(url);
|
|
8533
8644
|
if (!parts || !parts.path) return { ok: false, reason: "empty path" };
|
|
8534
8645
|
const normalized = parts.path.replace(/^[/\\]+/, "");
|
|
8535
|
-
const baseFullPath = isAbsolute4(normalized) ? normalized :
|
|
8646
|
+
const baseFullPath = isAbsolute4(normalized) ? normalized : join12(projectRoot, normalized);
|
|
8536
8647
|
const siblings = SIBLING_EXTENSIONS.get(extOf(baseFullPath)) ?? [];
|
|
8537
8648
|
const candidates = [
|
|
8538
8649
|
baseFullPath,
|
|
@@ -8542,7 +8653,7 @@ function validateCitation(url, projectRoot) {
|
|
|
8542
8653
|
let stat = null;
|
|
8543
8654
|
for (const candidate of candidates) {
|
|
8544
8655
|
try {
|
|
8545
|
-
stat =
|
|
8656
|
+
stat = statSync7(candidate);
|
|
8546
8657
|
fullPath = candidate;
|
|
8547
8658
|
break;
|
|
8548
8659
|
} catch {
|
|
@@ -10945,6 +11056,39 @@ function Hint({ cmd, desc }) {
|
|
|
10945
11056
|
return /* @__PURE__ */ React22.createElement(BarRow, null, /* @__PURE__ */ React22.createElement(Text18, { bold: true, color: COLOR.accent }, cmd.padEnd(8)), /* @__PURE__ */ React22.createElement(Text18, { dimColor: true }, ` ${desc}`));
|
|
10946
11057
|
}
|
|
10947
11058
|
|
|
11059
|
+
// src/cli/ui/WorkspaceConfirm.tsx
|
|
11060
|
+
import { Box as Box21, Text as Text19 } from "ink";
|
|
11061
|
+
import React23 from "react";
|
|
11062
|
+
function WorkspaceConfirm({
|
|
11063
|
+
path: path5,
|
|
11064
|
+
currentRoot,
|
|
11065
|
+
mcpServerCount,
|
|
11066
|
+
onChoose
|
|
11067
|
+
}) {
|
|
11068
|
+
const subtitle = mcpServerCount > 0 ? `MCP servers (${mcpServerCount}) stay anchored to the original launch root.` : "Re-registers filesystem / shell / memory tools at the new path.";
|
|
11069
|
+
return /* @__PURE__ */ React23.createElement(ModalCard, { accent: "#f59e0b", icon: "\u21C4", title: "switch workspace", subtitle }, /* @__PURE__ */ React23.createElement(Box21, { flexDirection: "column", marginBottom: 1 }, /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "from "), /* @__PURE__ */ React23.createElement(Text19, { color: "#a3a3a3" }, currentRoot)), /* @__PURE__ */ React23.createElement(Box21, null, /* @__PURE__ */ React23.createElement(Text19, { dimColor: true }, "to "), /* @__PURE__ */ React23.createElement(Text19, { color: "#67e8f9", bold: true }, path5))), /* @__PURE__ */ React23.createElement(
|
|
11070
|
+
SingleSelect,
|
|
11071
|
+
{
|
|
11072
|
+
initialValue: "switch",
|
|
11073
|
+
items: [
|
|
11074
|
+
{
|
|
11075
|
+
value: "switch",
|
|
11076
|
+
label: "Switch",
|
|
11077
|
+
hint: "Re-register filesystem / shell / memory tools against the new root."
|
|
11078
|
+
},
|
|
11079
|
+
{
|
|
11080
|
+
value: "deny",
|
|
11081
|
+
label: "Deny",
|
|
11082
|
+
hint: "Tell the model the user refused; it will continue without changing directories."
|
|
11083
|
+
}
|
|
11084
|
+
],
|
|
11085
|
+
onSubmit: (v) => onChoose(v),
|
|
11086
|
+
onCancel: () => onChoose("deny"),
|
|
11087
|
+
footer: "[\u2191\u2193] navigate \xB7 [Enter] select \xB7 [Esc] deny"
|
|
11088
|
+
}
|
|
11089
|
+
));
|
|
11090
|
+
}
|
|
11091
|
+
|
|
10948
11092
|
// src/cli/ui/bang.ts
|
|
10949
11093
|
function detectBangCommand(text) {
|
|
10950
11094
|
if (!text.startsWith("!")) return null;
|
|
@@ -11038,9 +11182,9 @@ function describeRepair(repair) {
|
|
|
11038
11182
|
}
|
|
11039
11183
|
|
|
11040
11184
|
// src/cli/ui/hash-memory.ts
|
|
11041
|
-
import { appendFileSync as appendFileSync3, existsSync as
|
|
11185
|
+
import { appendFileSync as appendFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync14, writeFileSync as writeFileSync7 } from "fs";
|
|
11042
11186
|
import { homedir as homedir6 } from "os";
|
|
11043
|
-
import { dirname as dirname10, join as
|
|
11187
|
+
import { dirname as dirname10, join as join13 } from "path";
|
|
11044
11188
|
var PROJECT_HEADER = `# Reasonix project memory
|
|
11045
11189
|
|
|
11046
11190
|
Notes the user pinned via the \`#\` prompt prefix. The whole file is
|
|
@@ -11072,12 +11216,12 @@ function detectHashMemory(text) {
|
|
|
11072
11216
|
return { kind: "memory", note: body };
|
|
11073
11217
|
}
|
|
11074
11218
|
function appendProjectMemory(rootDir, note) {
|
|
11075
|
-
return appendBulletToFile(
|
|
11219
|
+
return appendBulletToFile(join13(rootDir, PROJECT_MEMORY_FILE), note, PROJECT_HEADER);
|
|
11076
11220
|
}
|
|
11077
11221
|
var GLOBAL_MEMORY_DIR = ".reasonix";
|
|
11078
11222
|
var GLOBAL_MEMORY_FILE = "REASONIX.md";
|
|
11079
11223
|
function globalMemoryPath(homeDir = homedir6()) {
|
|
11080
|
-
return
|
|
11224
|
+
return join13(homeDir, GLOBAL_MEMORY_DIR, GLOBAL_MEMORY_FILE);
|
|
11081
11225
|
}
|
|
11082
11226
|
function appendGlobalMemory(note, homeDir) {
|
|
11083
11227
|
return appendBulletToFile(globalMemoryPath(homeDir), note, GLOBAL_HEADER);
|
|
@@ -11087,7 +11231,7 @@ function appendBulletToFile(path5, note, newFileHeader) {
|
|
|
11087
11231
|
if (!trimmed) throw new Error("note body cannot be empty");
|
|
11088
11232
|
const bullet = `- ${trimmed}
|
|
11089
11233
|
`;
|
|
11090
|
-
if (!
|
|
11234
|
+
if (!existsSync12(path5)) {
|
|
11091
11235
|
mkdirSync8(dirname10(path5), { recursive: true });
|
|
11092
11236
|
writeFileSync7(path5, `${newFileHeader}${bullet}`, "utf8");
|
|
11093
11237
|
return { path: path5, created: true };
|
|
@@ -11435,6 +11579,11 @@ var SLASH_COMMANDS = [
|
|
|
11435
11579
|
argsHint: "[reload]",
|
|
11436
11580
|
summary: "list active hooks (settings.json under .reasonix/) \xB7 reload re-reads from disk"
|
|
11437
11581
|
},
|
|
11582
|
+
{
|
|
11583
|
+
cmd: "cwd",
|
|
11584
|
+
argsHint: "<path>",
|
|
11585
|
+
summary: "switch session working directory (re-registers code tools, reloads hooks; MCP servers stay)"
|
|
11586
|
+
},
|
|
11438
11587
|
{
|
|
11439
11588
|
cmd: "update",
|
|
11440
11589
|
summary: "show current vs latest version + the shell command to upgrade"
|
|
@@ -11581,8 +11730,12 @@ function parseSlash(text) {
|
|
|
11581
11730
|
return { cmd, args: parts.slice(1) };
|
|
11582
11731
|
}
|
|
11583
11732
|
|
|
11733
|
+
// src/cli/ui/slash/handlers/admin.ts
|
|
11734
|
+
import { existsSync as existsSync14, statSync as statSync8 } from "fs";
|
|
11735
|
+
import * as pathMod5 from "path";
|
|
11736
|
+
|
|
11584
11737
|
// src/cli/commands/stats.ts
|
|
11585
|
-
import { existsSync as
|
|
11738
|
+
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
11586
11739
|
function statsCommand(opts) {
|
|
11587
11740
|
if (opts.transcript) {
|
|
11588
11741
|
transcriptSummary(opts.transcript);
|
|
@@ -11591,7 +11744,7 @@ function statsCommand(opts) {
|
|
|
11591
11744
|
dashboard(opts);
|
|
11592
11745
|
}
|
|
11593
11746
|
function transcriptSummary(path5) {
|
|
11594
|
-
if (!
|
|
11747
|
+
if (!existsSync13(path5)) {
|
|
11595
11748
|
console.error(`no such transcript: ${path5}`);
|
|
11596
11749
|
process.exit(1);
|
|
11597
11750
|
}
|
|
@@ -11815,9 +11968,51 @@ var stats = () => {
|
|
|
11815
11968
|
const agg = aggregateUsage(records);
|
|
11816
11969
|
return { info: renderDashboard(agg, path5) };
|
|
11817
11970
|
};
|
|
11971
|
+
var cwd = (args, _loop, ctx) => {
|
|
11972
|
+
if (!ctx.setCwd) {
|
|
11973
|
+
return {
|
|
11974
|
+
info: "/cwd is not available in this context (no setCwd callback wired)."
|
|
11975
|
+
};
|
|
11976
|
+
}
|
|
11977
|
+
const raw = (args[0] ?? "").trim();
|
|
11978
|
+
if (!raw) {
|
|
11979
|
+
return {
|
|
11980
|
+
info: "usage: /cwd <path> (absolute or relative, ~ expands to home)"
|
|
11981
|
+
};
|
|
11982
|
+
}
|
|
11983
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
11984
|
+
const expanded = raw.startsWith("~") && home ? pathMod5.join(home, raw.slice(1)) : raw;
|
|
11985
|
+
const abs = pathMod5.resolve(expanded);
|
|
11986
|
+
if (!existsSync14(abs)) {
|
|
11987
|
+
return { info: `\u25B8 /cwd: path does not exist \u2014 ${abs}` };
|
|
11988
|
+
}
|
|
11989
|
+
let isDir = false;
|
|
11990
|
+
try {
|
|
11991
|
+
isDir = statSync8(abs).isDirectory();
|
|
11992
|
+
} catch {
|
|
11993
|
+
}
|
|
11994
|
+
if (!isDir) {
|
|
11995
|
+
return { info: `\u25B8 /cwd: not a directory \u2014 ${abs}` };
|
|
11996
|
+
}
|
|
11997
|
+
let info;
|
|
11998
|
+
try {
|
|
11999
|
+
info = ctx.setCwd(abs);
|
|
12000
|
+
} catch (err) {
|
|
12001
|
+
return { info: `\u25B8 /cwd failed: ${err.message}` };
|
|
12002
|
+
}
|
|
12003
|
+
const lines = [info];
|
|
12004
|
+
if (ctx.mcpServers && ctx.mcpServers.length > 0) {
|
|
12005
|
+
lines.push(
|
|
12006
|
+
` note: ${ctx.mcpServers.length} MCP server(s) still anchored to the original cwd \u2014`,
|
|
12007
|
+
" their tools won't follow this switch. Restart the session for full reset."
|
|
12008
|
+
);
|
|
12009
|
+
}
|
|
12010
|
+
return { info: lines.join("\n") };
|
|
12011
|
+
};
|
|
11818
12012
|
var handlers = {
|
|
11819
12013
|
hook: hooks,
|
|
11820
12014
|
hooks,
|
|
12015
|
+
cwd,
|
|
11821
12016
|
update,
|
|
11822
12017
|
stats
|
|
11823
12018
|
};
|
|
@@ -13173,7 +13368,7 @@ async function startOllamaDaemon(opts = {}) {
|
|
|
13173
13368
|
return { ready: false, pid };
|
|
13174
13369
|
}
|
|
13175
13370
|
async function pullOllamaModel(modelName, opts = {}) {
|
|
13176
|
-
return new Promise((
|
|
13371
|
+
return new Promise((resolve12) => {
|
|
13177
13372
|
const child = spawn5("ollama", ["pull", modelName], {
|
|
13178
13373
|
stdio: ["ignore", "pipe", "pipe"],
|
|
13179
13374
|
windowsHide: true
|
|
@@ -13185,8 +13380,8 @@ async function pullOllamaModel(modelName, opts = {}) {
|
|
|
13185
13380
|
}
|
|
13186
13381
|
streamLines(child.stdout, (l) => opts.onLine?.(l, "stdout"));
|
|
13187
13382
|
streamLines(child.stderr, (l) => opts.onLine?.(l, "stderr"));
|
|
13188
|
-
child.once("exit", (code) =>
|
|
13189
|
-
child.once("error", () =>
|
|
13383
|
+
child.once("exit", (code) => resolve12(code ?? -1));
|
|
13384
|
+
child.once("error", () => resolve12(-1));
|
|
13190
13385
|
});
|
|
13191
13386
|
}
|
|
13192
13387
|
function streamLines(stream, cb) {
|
|
@@ -13426,6 +13621,7 @@ function useCompletionPickers({
|
|
|
13426
13621
|
input,
|
|
13427
13622
|
setInput,
|
|
13428
13623
|
codeMode,
|
|
13624
|
+
rootDir,
|
|
13429
13625
|
models: models2,
|
|
13430
13626
|
mcpServers
|
|
13431
13627
|
}) {
|
|
@@ -13443,13 +13639,13 @@ function useCompletionPickers({
|
|
|
13443
13639
|
}, [slashMatches]);
|
|
13444
13640
|
const [atSelected, setAtSelected] = useState6(0);
|
|
13445
13641
|
const atFiles = useMemo2(() => {
|
|
13446
|
-
if (!codeMode
|
|
13642
|
+
if (!codeMode) return [];
|
|
13447
13643
|
try {
|
|
13448
|
-
return listFilesWithStatsSync(
|
|
13644
|
+
return listFilesWithStatsSync(rootDir, { maxResults: 500 });
|
|
13449
13645
|
} catch {
|
|
13450
13646
|
return [];
|
|
13451
13647
|
}
|
|
13452
|
-
}, [codeMode
|
|
13648
|
+
}, [codeMode, rootDir]);
|
|
13453
13649
|
const recentFilesRef = useRef3([]);
|
|
13454
13650
|
const recordRecentFile = useCallback((p) => {
|
|
13455
13651
|
const list = recentFilesRef.current;
|
|
@@ -13459,10 +13655,10 @@ function useCompletionPickers({
|
|
|
13459
13655
|
if (list.length > 20) list.length = 20;
|
|
13460
13656
|
}, []);
|
|
13461
13657
|
const atPicker = useMemo2(() => {
|
|
13462
|
-
if (!codeMode
|
|
13658
|
+
if (!codeMode) return null;
|
|
13463
13659
|
if (slashMatches !== null) return null;
|
|
13464
13660
|
return detectAtPicker(input);
|
|
13465
|
-
}, [codeMode
|
|
13661
|
+
}, [codeMode, input, slashMatches]);
|
|
13466
13662
|
const atMatches = useMemo2(() => {
|
|
13467
13663
|
if (!atPicker) return null;
|
|
13468
13664
|
return rankPickerCandidates(atFiles, atPicker.query, {
|
|
@@ -13902,13 +14098,13 @@ var PLAIN_UI = process.env.REASONIX_UI === "plain";
|
|
|
13902
14098
|
function LoopStatusRow({
|
|
13903
14099
|
loop: loop2
|
|
13904
14100
|
}) {
|
|
13905
|
-
const [, setTick] =
|
|
13906
|
-
|
|
14101
|
+
const [, setTick] = React24.useState(0);
|
|
14102
|
+
React24.useEffect(() => {
|
|
13907
14103
|
const id = setInterval(() => setTick((t2) => t2 + 1), 1e3);
|
|
13908
14104
|
return () => clearInterval(id);
|
|
13909
14105
|
}, []);
|
|
13910
14106
|
const nextFireMs = Math.max(0, loop2.nextFireAt - Date.now());
|
|
13911
|
-
return /* @__PURE__ */
|
|
14107
|
+
return /* @__PURE__ */ React24.createElement(Box22, null, /* @__PURE__ */ React24.createElement(Text20, { color: "cyan" }, `\u25B8 ${formatLoopStatus(loop2.prompt, nextFireMs, loop2.iter)} \xB7 /loop stop or type to cancel`));
|
|
13912
14108
|
}
|
|
13913
14109
|
function App({
|
|
13914
14110
|
model: model2,
|
|
@@ -13967,10 +14163,12 @@ function App({
|
|
|
13967
14163
|
setHistorical
|
|
13968
14164
|
});
|
|
13969
14165
|
const [statusLine, setStatusLine] = useState10(null);
|
|
14166
|
+
const [currentRootDir, setCurrentRootDir] = useState10(
|
|
14167
|
+
() => codeMode?.rootDir ?? process.cwd()
|
|
14168
|
+
);
|
|
13970
14169
|
const [hookList, setHookList] = useState10(
|
|
13971
14170
|
() => loadHooks({ projectRoot: codeMode?.rootDir })
|
|
13972
14171
|
);
|
|
13973
|
-
const hookCwd = codeMode?.rootDir ?? process.cwd();
|
|
13974
14172
|
const {
|
|
13975
14173
|
undoBanner,
|
|
13976
14174
|
recordEdit,
|
|
@@ -14012,6 +14210,7 @@ function App({
|
|
|
14012
14210
|
}, 1200);
|
|
14013
14211
|
}, [editMode]);
|
|
14014
14212
|
const [pendingShell, setPendingShell] = useState10(null);
|
|
14213
|
+
const [pendingWorkspace, setPendingWorkspace] = useState10(null);
|
|
14015
14214
|
const [pendingPlan, setPendingPlan] = useState10(null);
|
|
14016
14215
|
const [stagedInput, setStagedInput] = useState10(null);
|
|
14017
14216
|
const [pendingCheckpoint, setPendingCheckpoint] = useState10(null);
|
|
@@ -14106,6 +14305,9 @@ function App({
|
|
|
14106
14305
|
}
|
|
14107
14306
|
});
|
|
14108
14307
|
}
|
|
14308
|
+
if (tools && !tools.has("change_workspace")) {
|
|
14309
|
+
registerWorkspaceTool(tools);
|
|
14310
|
+
}
|
|
14109
14311
|
const prefix = new ImmutablePrefix({
|
|
14110
14312
|
system,
|
|
14111
14313
|
toolSpecs: tools?.specs()
|
|
@@ -14119,7 +14321,7 @@ function App({
|
|
|
14119
14321
|
branch: branch2,
|
|
14120
14322
|
session,
|
|
14121
14323
|
hooks: hookList,
|
|
14122
|
-
hookCwd,
|
|
14324
|
+
hookCwd: currentRootDir,
|
|
14123
14325
|
// Restore the user's last-chosen effort cap. Without this a
|
|
14124
14326
|
// `/effort high` silently reverted to `max` on relaunch — the
|
|
14125
14327
|
// loop's constructor default wins over persisted state.
|
|
@@ -14131,6 +14333,49 @@ function App({
|
|
|
14131
14333
|
useEffect6(() => {
|
|
14132
14334
|
loop2.hooks = hookList;
|
|
14133
14335
|
}, [loop2, hookList]);
|
|
14336
|
+
const applyCwdChange = useCallback4(
|
|
14337
|
+
(newRoot) => {
|
|
14338
|
+
setCurrentRootDir(newRoot);
|
|
14339
|
+
const fresh = loadHooks({ projectRoot: codeMode ? newRoot : void 0 });
|
|
14340
|
+
setHookList(fresh);
|
|
14341
|
+
const codeRebound = codeMode?.reregisterTools !== void 0;
|
|
14342
|
+
if (codeMode?.reregisterTools) {
|
|
14343
|
+
codeMode.reregisterTools(newRoot);
|
|
14344
|
+
}
|
|
14345
|
+
if (tools) {
|
|
14346
|
+
registerSkillTools(tools, {
|
|
14347
|
+
projectRoot: codeMode ? newRoot : void 0,
|
|
14348
|
+
subagentRunner: async (skill2, task) => {
|
|
14349
|
+
const result = await spawnSubagent({
|
|
14350
|
+
client: loop2.client,
|
|
14351
|
+
parentRegistry: tools,
|
|
14352
|
+
system: skill2.body,
|
|
14353
|
+
task,
|
|
14354
|
+
model: skill2.model,
|
|
14355
|
+
sink: subagentSinkRef.current,
|
|
14356
|
+
skillName: skill2.name
|
|
14357
|
+
});
|
|
14358
|
+
return formatSubagentResult(result);
|
|
14359
|
+
}
|
|
14360
|
+
});
|
|
14361
|
+
}
|
|
14362
|
+
const lines = [`\u25B8 cwd \u2192 ${newRoot}`, ` hooks reloaded (${fresh.length} active)`];
|
|
14363
|
+
if (codeMode) {
|
|
14364
|
+
lines.push(
|
|
14365
|
+
codeRebound ? " filesystem / shell / memory tools rebound to new root" : " warning: reregisterTools callback missing \u2014 tool sandbox unchanged"
|
|
14366
|
+
);
|
|
14367
|
+
lines.push(
|
|
14368
|
+
" note: system prompt context (gitignore, REASONIX.md stack) was",
|
|
14369
|
+
" baked at session start and still references the original root."
|
|
14370
|
+
);
|
|
14371
|
+
}
|
|
14372
|
+
return lines.join("\n");
|
|
14373
|
+
},
|
|
14374
|
+
[codeMode, loop2, tools, subagentSinkRef]
|
|
14375
|
+
);
|
|
14376
|
+
useEffect6(() => {
|
|
14377
|
+
loop2.hookCwd = currentRootDir;
|
|
14378
|
+
}, [loop2, currentRootDir]);
|
|
14134
14379
|
const {
|
|
14135
14380
|
balance,
|
|
14136
14381
|
models: models2,
|
|
@@ -14155,7 +14400,14 @@ function App({
|
|
|
14155
14400
|
slashArgSelected,
|
|
14156
14401
|
setSlashArgSelected,
|
|
14157
14402
|
pickSlashArg
|
|
14158
|
-
} = useCompletionPickers({
|
|
14403
|
+
} = useCompletionPickers({
|
|
14404
|
+
input,
|
|
14405
|
+
setInput,
|
|
14406
|
+
codeMode,
|
|
14407
|
+
rootDir: currentRootDir,
|
|
14408
|
+
models: models2,
|
|
14409
|
+
mcpServers
|
|
14410
|
+
});
|
|
14159
14411
|
useEffect6(() => {
|
|
14160
14412
|
if (!progressSink) return;
|
|
14161
14413
|
progressSink.current = (info) => {
|
|
@@ -14275,11 +14527,11 @@ function App({
|
|
|
14275
14527
|
if (key.escape && busy) {
|
|
14276
14528
|
if (abortedThisTurn.current) return;
|
|
14277
14529
|
abortedThisTurn.current = true;
|
|
14278
|
-
const
|
|
14279
|
-
if (
|
|
14530
|
+
const resolve12 = editReviewResolveRef.current;
|
|
14531
|
+
if (resolve12) {
|
|
14280
14532
|
editReviewResolveRef.current = null;
|
|
14281
14533
|
setPendingEditReview(null);
|
|
14282
|
-
|
|
14534
|
+
resolve12("reject");
|
|
14283
14535
|
}
|
|
14284
14536
|
if (activeLoopRef.current) stopLoop();
|
|
14285
14537
|
loop2.abort();
|
|
@@ -14302,7 +14554,7 @@ function App({
|
|
|
14302
14554
|
]);
|
|
14303
14555
|
return;
|
|
14304
14556
|
}
|
|
14305
|
-
if (codeMode && key.shift && key.tab && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
14557
|
+
if (codeMode && key.shift && key.tab && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision) {
|
|
14306
14558
|
setEditMode((m) => {
|
|
14307
14559
|
const next = m === "review" ? "auto" : m === "auto" ? "yolo" : "review";
|
|
14308
14560
|
const message = next === "yolo" ? "\u25B8 edit mode: YOLO \u2014 edits AND shell commands auto-run. /undo still rolls back edits. Use carefully." : next === "auto" ? "\u25B8 edit mode: AUTO \u2014 edits apply immediately; press u within 5s to undo. Shell commands still ask." : "\u25B8 edit mode: review \u2014 edits queue for /apply (or y) / /discard (or n)";
|
|
@@ -14314,7 +14566,7 @@ function App({
|
|
|
14314
14566
|
});
|
|
14315
14567
|
return;
|
|
14316
14568
|
}
|
|
14317
|
-
if (codeMode && input.length === 0 && (chKey === "u" || chKey === "U") && !pendingShell && !pendingPlan && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision && // Fire when EITHER the banner is up OR there's any non-undone
|
|
14569
|
+
if (codeMode && input.length === 0 && (chKey === "u" || chKey === "U") && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !walkthroughActive && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision && // Fire when EITHER the banner is up OR there's any non-undone
|
|
14318
14570
|
// history entry — the keybind is useful long after the 5-second
|
|
14319
14571
|
// banner expires, which users rightly want.
|
|
14320
14572
|
(undoBanner || hasUndoable())) {
|
|
@@ -14403,11 +14655,11 @@ function App({
|
|
|
14403
14655
|
block = { path: relPath, search, replace, offset: 0 };
|
|
14404
14656
|
} else {
|
|
14405
14657
|
const content = typeof args.content === "string" ? args.content : "";
|
|
14406
|
-
block = toWholeFileEditBlock(relPath, content,
|
|
14658
|
+
block = toWholeFileEditBlock(relPath, content, currentRootDir);
|
|
14407
14659
|
}
|
|
14408
14660
|
const applyNow = () => {
|
|
14409
|
-
const snaps = snapshotBeforeEdits([block],
|
|
14410
|
-
const results = applyEditBlocks([block],
|
|
14661
|
+
const snaps = snapshotBeforeEdits([block], currentRootDir);
|
|
14662
|
+
const results = applyEditBlocks([block], currentRootDir);
|
|
14411
14663
|
const good = results.some((r) => r.status === "applied" || r.status === "created");
|
|
14412
14664
|
if (good) {
|
|
14413
14665
|
recordEdit("auto", [block], results, snaps);
|
|
@@ -14476,8 +14728,8 @@ function App({
|
|
|
14476
14728
|
if (selected.length === 0) {
|
|
14477
14729
|
return "\u25B8 no edits matched those indices \u2014 nothing applied. Use /apply with no args to commit them all.";
|
|
14478
14730
|
}
|
|
14479
|
-
const snaps = snapshotBeforeEdits(selected,
|
|
14480
|
-
const results = applyEditBlocks(selected,
|
|
14731
|
+
const snaps = snapshotBeforeEdits(selected, currentRootDir);
|
|
14732
|
+
const results = applyEditBlocks(selected, currentRootDir);
|
|
14481
14733
|
const anyApplied = results.some((r) => r.status === "applied" || r.status === "created");
|
|
14482
14734
|
if (anyApplied) recordEdit("review-apply", selected, results, snaps);
|
|
14483
14735
|
pendingEdits.current = remaining;
|
|
@@ -14488,7 +14740,7 @@ function App({
|
|
|
14488
14740
|
\u25B8 ${remaining.length} edit block(s) still pending \u2014 /apply or /discard to clear them.` : "";
|
|
14489
14741
|
return formatEditResults(results) + tail;
|
|
14490
14742
|
},
|
|
14491
|
-
[codeMode, session, syncPendingCount, recordEdit]
|
|
14743
|
+
[codeMode, currentRootDir, session, syncPendingCount, recordEdit]
|
|
14492
14744
|
);
|
|
14493
14745
|
const codeDiscard = useCallback4(
|
|
14494
14746
|
(indices) => {
|
|
@@ -14653,7 +14905,7 @@ function App({
|
|
|
14653
14905
|
const hashParse = detectHashMemory(text);
|
|
14654
14906
|
if (hashParse?.kind === "memory" || hashParse?.kind === "memory-global") {
|
|
14655
14907
|
const isGlobal = hashParse.kind === "memory-global";
|
|
14656
|
-
const memRoot =
|
|
14908
|
+
const memRoot = currentRootDir;
|
|
14657
14909
|
promptHistory.current.push(text);
|
|
14658
14910
|
try {
|
|
14659
14911
|
const result = isGlobal ? appendGlobalMemory(hashParse.note) : appendProjectMemory(memRoot, hashParse.note);
|
|
@@ -14684,7 +14936,7 @@ function App({
|
|
|
14684
14936
|
}
|
|
14685
14937
|
const bangCmd = detectBangCommand(text);
|
|
14686
14938
|
if (bangCmd !== null) {
|
|
14687
|
-
const bangRoot =
|
|
14939
|
+
const bangRoot = currentRootDir;
|
|
14688
14940
|
promptHistory.current.push(text);
|
|
14689
14941
|
setHistorical((prev) => [
|
|
14690
14942
|
...prev,
|
|
@@ -14747,10 +14999,10 @@ function App({
|
|
|
14747
14999
|
codeDiscard: codeMode ? codeDiscard : void 0,
|
|
14748
15000
|
codeHistory: codeMode ? codeHistory : void 0,
|
|
14749
15001
|
codeShowEdit: codeMode ? codeShowEdit : void 0,
|
|
14750
|
-
codeRoot: codeMode
|
|
15002
|
+
codeRoot: codeMode ? currentRootDir : void 0,
|
|
14751
15003
|
pendingEditCount: codeMode ? pendingEdits.current.length : void 0,
|
|
14752
15004
|
toolHistory: () => toolHistoryRef.current,
|
|
14753
|
-
memoryRoot:
|
|
15005
|
+
memoryRoot: currentRootDir,
|
|
14754
15006
|
planMode,
|
|
14755
15007
|
setPlanMode: codeMode ? togglePlanMode : void 0,
|
|
14756
15008
|
clearPendingPlan: codeMode ? clearPendingPlan : void 0,
|
|
@@ -14774,10 +15026,11 @@ function App({
|
|
|
14774
15026
|
{ id: `sys-late-${Date.now()}-${Math.random()}`, role: "info", text: text2 }
|
|
14775
15027
|
]),
|
|
14776
15028
|
reloadHooks: () => {
|
|
14777
|
-
const fresh = loadHooks({ projectRoot: codeMode
|
|
15029
|
+
const fresh = loadHooks({ projectRoot: codeMode ? currentRootDir : void 0 });
|
|
14778
15030
|
setHookList(fresh);
|
|
14779
15031
|
return fresh.length;
|
|
14780
15032
|
},
|
|
15033
|
+
setCwd: (newRoot) => applyCwdChange(newRoot),
|
|
14781
15034
|
latestVersion,
|
|
14782
15035
|
refreshLatestVersion,
|
|
14783
15036
|
models: models2,
|
|
@@ -14858,7 +15111,7 @@ function App({
|
|
|
14858
15111
|
if (hookList.some((h) => h.event === "UserPromptSubmit")) {
|
|
14859
15112
|
const promptReport = await runHooks({
|
|
14860
15113
|
hooks: hookList,
|
|
14861
|
-
payload: { event: "UserPromptSubmit", cwd:
|
|
15114
|
+
payload: { event: "UserPromptSubmit", cwd: currentRootDir, prompt: text }
|
|
14862
15115
|
});
|
|
14863
15116
|
if (promptReport.outcomes.length > 0) {
|
|
14864
15117
|
setHistorical((prev) => [
|
|
@@ -14926,8 +15179,8 @@ function App({
|
|
|
14926
15179
|
};
|
|
14927
15180
|
const timer = PLAIN_UI ? null : setInterval(flush, FLUSH_INTERVAL_MS);
|
|
14928
15181
|
let modelInput = text;
|
|
14929
|
-
if (codeMode
|
|
14930
|
-
const expanded = expandAtMentions(text,
|
|
15182
|
+
if (codeMode) {
|
|
15183
|
+
const expanded = expandAtMentions(text, currentRootDir);
|
|
14931
15184
|
if (expanded.expansions.length > 0) {
|
|
14932
15185
|
modelInput = expanded.text;
|
|
14933
15186
|
const inlined = expanded.expansions.filter((ex) => ex.ok).map((ex) => `${ex.path} (${(ex.bytes ?? 0).toLocaleString()} bytes)`);
|
|
@@ -15058,8 +15311,8 @@ function App({
|
|
|
15058
15311
|
const blocks = parseEditBlocks(finalText);
|
|
15059
15312
|
if (blocks.length > 0) {
|
|
15060
15313
|
if (editModeRef.current === "auto" || editModeRef.current === "yolo") {
|
|
15061
|
-
const snaps = snapshotBeforeEdits(blocks,
|
|
15062
|
-
const results = applyEditBlocks(blocks,
|
|
15314
|
+
const snaps = snapshotBeforeEdits(blocks, currentRootDir);
|
|
15315
|
+
const results = applyEditBlocks(blocks, currentRootDir);
|
|
15063
15316
|
const good = results.some(
|
|
15064
15317
|
(r) => r.status === "applied" || r.status === "created"
|
|
15065
15318
|
);
|
|
@@ -15145,6 +15398,18 @@ function App({
|
|
|
15145
15398
|
} catch {
|
|
15146
15399
|
}
|
|
15147
15400
|
}
|
|
15401
|
+
if (ev.toolName === "change_workspace" && ev.content.includes('"WorkspaceConfirmationError:') && ev.toolArgs) {
|
|
15402
|
+
try {
|
|
15403
|
+
const parsed = JSON.parse(ev.toolArgs);
|
|
15404
|
+
if (typeof parsed.path === "string" && parsed.path.trim()) {
|
|
15405
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
15406
|
+
const expanded = parsed.path.startsWith("~") && home ? pathMod6.join(home, parsed.path.slice(1)) : parsed.path;
|
|
15407
|
+
const abs = pathMod6.resolve(expanded);
|
|
15408
|
+
setPendingWorkspace({ path: abs });
|
|
15409
|
+
}
|
|
15410
|
+
} catch {
|
|
15411
|
+
}
|
|
15412
|
+
}
|
|
15148
15413
|
if (codeMode && ev.toolName === "submit_plan" && ev.content.includes('"PlanProposedError:')) {
|
|
15149
15414
|
try {
|
|
15150
15415
|
const parsed = JSON.parse(ev.content);
|
|
@@ -15267,7 +15532,7 @@ function App({
|
|
|
15267
15532
|
hooks: hookList,
|
|
15268
15533
|
payload: {
|
|
15269
15534
|
event: "Stop",
|
|
15270
|
-
cwd:
|
|
15535
|
+
cwd: currentRootDir,
|
|
15271
15536
|
lastAssistantText: streamRef.text,
|
|
15272
15537
|
turn: loop2.stats.summary().turns
|
|
15273
15538
|
}
|
|
@@ -15305,8 +15570,8 @@ function App({
|
|
|
15305
15570
|
codeMode,
|
|
15306
15571
|
codeShowEdit,
|
|
15307
15572
|
codeUndo,
|
|
15573
|
+
currentRootDir,
|
|
15308
15574
|
exit2,
|
|
15309
|
-
hookCwd,
|
|
15310
15575
|
hookList,
|
|
15311
15576
|
loop2,
|
|
15312
15577
|
latestVersion,
|
|
@@ -15341,7 +15606,8 @@ function App({
|
|
|
15341
15606
|
stopLoop,
|
|
15342
15607
|
startLoop,
|
|
15343
15608
|
getLoopStatus,
|
|
15344
|
-
startWalkthrough
|
|
15609
|
+
startWalkthrough,
|
|
15610
|
+
applyCwdChange
|
|
15345
15611
|
]
|
|
15346
15612
|
);
|
|
15347
15613
|
useEffect6(() => {
|
|
@@ -15398,13 +15664,13 @@ function App({
|
|
|
15398
15664
|
} else {
|
|
15399
15665
|
if (choice === "always_allow") {
|
|
15400
15666
|
const prefix = derivePrefix(cmd);
|
|
15401
|
-
addProjectShellAllowed(
|
|
15667
|
+
addProjectShellAllowed(currentRootDir, prefix);
|
|
15402
15668
|
setHistorical((prev) => [
|
|
15403
15669
|
...prev,
|
|
15404
15670
|
{
|
|
15405
15671
|
id: `sh-allow-${Date.now()}`,
|
|
15406
15672
|
role: "info",
|
|
15407
|
-
text: `\u25B8 always allowed "${prefix}" for ${
|
|
15673
|
+
text: `\u25B8 always allowed "${prefix}" for ${currentRootDir}`
|
|
15408
15674
|
}
|
|
15409
15675
|
]);
|
|
15410
15676
|
}
|
|
@@ -15421,7 +15687,7 @@ function App({
|
|
|
15421
15687
|
let jobId = null;
|
|
15422
15688
|
let preview = "";
|
|
15423
15689
|
try {
|
|
15424
|
-
const res = await codeMode.jobs.start(cmd, { cwd:
|
|
15690
|
+
const res = await codeMode.jobs.start(cmd, { cwd: currentRootDir });
|
|
15425
15691
|
startedOk = true;
|
|
15426
15692
|
jobId = res.jobId;
|
|
15427
15693
|
preview = res.preview;
|
|
@@ -15455,7 +15721,7 @@ ${msg}`;
|
|
|
15455
15721
|
} else {
|
|
15456
15722
|
let body;
|
|
15457
15723
|
try {
|
|
15458
|
-
const res = await runCommand(cmd, { cwd:
|
|
15724
|
+
const res = await runCommand(cmd, { cwd: currentRootDir });
|
|
15459
15725
|
body = formatCommandResult(cmd, res);
|
|
15460
15726
|
} catch (err) {
|
|
15461
15727
|
body = `$ ${cmd}
|
|
@@ -15477,7 +15743,7 @@ ${body}`;
|
|
|
15477
15743
|
await handleSubmit(synthetic);
|
|
15478
15744
|
}
|
|
15479
15745
|
},
|
|
15480
|
-
[pendingShell, codeMode, handleSubmit, busy, loop2]
|
|
15746
|
+
[pendingShell, codeMode, currentRootDir, handleSubmit, busy, loop2]
|
|
15481
15747
|
);
|
|
15482
15748
|
useEffect6(() => {
|
|
15483
15749
|
if (!busy && queuedSubmit !== null) {
|
|
@@ -15486,6 +15752,40 @@ ${body}`;
|
|
|
15486
15752
|
void handleSubmit(text);
|
|
15487
15753
|
}
|
|
15488
15754
|
}, [busy, queuedSubmit, handleSubmit]);
|
|
15755
|
+
const handleWorkspaceConfirm = useCallback4(
|
|
15756
|
+
async (choice) => {
|
|
15757
|
+
const pending = pendingWorkspace;
|
|
15758
|
+
if (!pending) return;
|
|
15759
|
+
const target = pending.path;
|
|
15760
|
+
setPendingWorkspace(null);
|
|
15761
|
+
let synthetic;
|
|
15762
|
+
if (choice === "deny") {
|
|
15763
|
+
setHistorical((prev) => [
|
|
15764
|
+
...prev,
|
|
15765
|
+
{
|
|
15766
|
+
id: `ws-deny-${Date.now()}`,
|
|
15767
|
+
role: "info",
|
|
15768
|
+
text: `\u25B8 denied workspace switch: ${target}`
|
|
15769
|
+
}
|
|
15770
|
+
]);
|
|
15771
|
+
synthetic = `I denied switching the workspace to \`${target}\`. Please continue without changing directories.`;
|
|
15772
|
+
} else {
|
|
15773
|
+
const info = applyCwdChange(target);
|
|
15774
|
+
setHistorical((prev) => [
|
|
15775
|
+
...prev,
|
|
15776
|
+
{ id: `ws-switch-${Date.now()}`, role: "info", text: info }
|
|
15777
|
+
]);
|
|
15778
|
+
synthetic = `I approved the workspace switch. The session is now rooted at \`${target}\` \u2014 your filesystem / shell / memory tools resolve against that path on every subsequent call. Continue with my original request from this new root.`;
|
|
15779
|
+
}
|
|
15780
|
+
if (busy) {
|
|
15781
|
+
loop2.abort();
|
|
15782
|
+
setQueuedSubmit(synthetic);
|
|
15783
|
+
} else {
|
|
15784
|
+
await handleSubmit(synthetic);
|
|
15785
|
+
}
|
|
15786
|
+
},
|
|
15787
|
+
[pendingWorkspace, applyCwdChange, busy, loop2, handleSubmit]
|
|
15788
|
+
);
|
|
15489
15789
|
const handlePlanConfirm = useCallback4(
|
|
15490
15790
|
async (choice) => {
|
|
15491
15791
|
const hadPendingPlan = pendingPlan !== null;
|
|
@@ -15792,12 +16092,12 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15792
16092
|
async (choice) => handleReviseConfirmRef.current(choice),
|
|
15793
16093
|
[]
|
|
15794
16094
|
);
|
|
15795
|
-
return /* @__PURE__ */
|
|
16095
|
+
return /* @__PURE__ */ React24.createElement(React24.Fragment, null, /* @__PURE__ */ React24.createElement(
|
|
15796
16096
|
TickerProvider,
|
|
15797
16097
|
{
|
|
15798
|
-
disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingShell || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision
|
|
16098
|
+
disabled: PLAIN_UI || isResizing || !!pendingPlan || !!pendingShell || !!pendingWorkspace || !!pendingEditReview || walkthroughActive || !!pendingCheckpoint || !!stagedCheckpointRevise || !!pendingChoice || !!stagedChoiceCustom || !!pendingRevision
|
|
15799
16099
|
},
|
|
15800
|
-
/* @__PURE__ */
|
|
16100
|
+
/* @__PURE__ */ React24.createElement(Box22, { flexDirection: "column" }, /* @__PURE__ */ React24.createElement(
|
|
15801
16101
|
StatsPanel,
|
|
15802
16102
|
{
|
|
15803
16103
|
summary,
|
|
@@ -15814,28 +16114,28 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15814
16114
|
proArmed,
|
|
15815
16115
|
escalated: turnOnPro
|
|
15816
16116
|
}
|
|
15817
|
-
), /* @__PURE__ */
|
|
16117
|
+
), /* @__PURE__ */ React24.createElement(Static, { items: historical }, (item) => /* @__PURE__ */ React24.createElement(EventRow, { key: item.id, event: item, projectRoot: currentRootDir })), !historical.some((e) => e.role === "user" || e.role === "assistant") && !busy && !streaming ? /* @__PURE__ */ React24.createElement(WelcomeBanner, { inCodeMode: !!codeMode }) : null, !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && streaming ? /* @__PURE__ */ React24.createElement(Box22, { marginY: 1 }, /* @__PURE__ */ React24.createElement(EventRow, { event: streaming, projectRoot: currentRootDir })) : null, !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && ongoingTool ? /* @__PURE__ */ React24.createElement(OngoingToolRow, { tool: ongoingTool, progress: toolProgress }) : null, !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && subagentActivity ? /* @__PURE__ */ React24.createElement(SubagentRow, { activity: subagentActivity }) : null, !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !ongoingTool && statusLine ? /* @__PURE__ */ React24.createElement(StatusRow, { text: statusLine }) : null, !PLAIN_UI && undoBanner && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && !pendingChoice && !stagedChoiceCustom && !pendingRevision ? /* @__PURE__ */ React24.createElement(UndoBanner, { banner: undoBanner }) : null, !PLAIN_UI && !pendingShell && !pendingWorkspace && !pendingPlan && !stagedInput && !pendingEditReview && !pendingCheckpoint && !stagedCheckpointRevise && busy && !streaming && !ongoingTool && !statusLine ? /* @__PURE__ */ React24.createElement(StatusRow, { text: "processing\u2026" }) : null, stagedInput ? /* @__PURE__ */ React24.createElement(
|
|
15818
16118
|
PlanRefineInput,
|
|
15819
16119
|
{
|
|
15820
16120
|
mode: stagedInput.mode,
|
|
15821
16121
|
onSubmit: handleStagedInputSubmit,
|
|
15822
16122
|
onCancel: handleStagedInputCancel
|
|
15823
16123
|
}
|
|
15824
|
-
) : stagedCheckpointRevise ? /* @__PURE__ */
|
|
16124
|
+
) : stagedCheckpointRevise ? /* @__PURE__ */ React24.createElement(
|
|
15825
16125
|
PlanRefineInput,
|
|
15826
16126
|
{
|
|
15827
16127
|
mode: "checkpoint-revise",
|
|
15828
16128
|
onSubmit: handleCheckpointReviseSubmit,
|
|
15829
16129
|
onCancel: handleCheckpointReviseCancel
|
|
15830
16130
|
}
|
|
15831
|
-
) : stagedChoiceCustom ? /* @__PURE__ */
|
|
16131
|
+
) : stagedChoiceCustom ? /* @__PURE__ */ React24.createElement(
|
|
15832
16132
|
PlanRefineInput,
|
|
15833
16133
|
{
|
|
15834
16134
|
mode: "choice-custom",
|
|
15835
16135
|
onSubmit: handleChoiceCustomSubmit,
|
|
15836
16136
|
onCancel: handleChoiceCustomCancel
|
|
15837
16137
|
}
|
|
15838
|
-
) : pendingChoice ? /* @__PURE__ */
|
|
16138
|
+
) : pendingChoice ? /* @__PURE__ */ React24.createElement(
|
|
15839
16139
|
ChoiceConfirm,
|
|
15840
16140
|
{
|
|
15841
16141
|
question: pendingChoice.question,
|
|
@@ -15843,7 +16143,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15843
16143
|
allowCustom: pendingChoice.allowCustom,
|
|
15844
16144
|
onChoose: stableHandleChoiceConfirm
|
|
15845
16145
|
}
|
|
15846
|
-
) : pendingRevision ? /* @__PURE__ */
|
|
16146
|
+
) : pendingRevision ? /* @__PURE__ */ React24.createElement(
|
|
15847
16147
|
PlanReviseConfirm,
|
|
15848
16148
|
{
|
|
15849
16149
|
reason: pendingRevision.reason,
|
|
@@ -15854,7 +16154,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15854
16154
|
summary: pendingRevision.summary,
|
|
15855
16155
|
onChoose: stableHandleReviseConfirm
|
|
15856
16156
|
}
|
|
15857
|
-
) : pendingCheckpoint ? /* @__PURE__ */
|
|
16157
|
+
) : pendingCheckpoint ? /* @__PURE__ */ React24.createElement(
|
|
15858
16158
|
PlanCheckpointConfirm,
|
|
15859
16159
|
{
|
|
15860
16160
|
stepId: pendingCheckpoint.stepId,
|
|
@@ -15865,16 +16165,16 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15865
16165
|
completedStepIds: completedStepIdsRef.current,
|
|
15866
16166
|
onChoose: stableHandleCheckpointConfirm
|
|
15867
16167
|
}
|
|
15868
|
-
) : pendingPlan ? /* @__PURE__ */
|
|
16168
|
+
) : pendingPlan ? /* @__PURE__ */ React24.createElement(
|
|
15869
16169
|
PlanConfirm,
|
|
15870
16170
|
{
|
|
15871
16171
|
plan: pendingPlan,
|
|
15872
16172
|
steps: planStepsRef.current ?? void 0,
|
|
15873
16173
|
summary: planSummaryRef.current ?? void 0,
|
|
15874
16174
|
onChoose: stableHandlePlanConfirm,
|
|
15875
|
-
projectRoot:
|
|
16175
|
+
projectRoot: currentRootDir
|
|
15876
16176
|
}
|
|
15877
|
-
) : pendingShell ? /* @__PURE__ */
|
|
16177
|
+
) : pendingShell ? /* @__PURE__ */ React24.createElement(
|
|
15878
16178
|
ShellConfirm,
|
|
15879
16179
|
{
|
|
15880
16180
|
command: pendingShell.command,
|
|
@@ -15882,26 +16182,34 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15882
16182
|
kind: pendingShell.kind,
|
|
15883
16183
|
onChoose: handleShellConfirm
|
|
15884
16184
|
}
|
|
15885
|
-
) :
|
|
16185
|
+
) : pendingWorkspace ? /* @__PURE__ */ React24.createElement(
|
|
16186
|
+
WorkspaceConfirm,
|
|
16187
|
+
{
|
|
16188
|
+
path: pendingWorkspace.path,
|
|
16189
|
+
currentRoot: currentRootDir,
|
|
16190
|
+
mcpServerCount: mcpServers?.length ?? 0,
|
|
16191
|
+
onChoose: handleWorkspaceConfirm
|
|
16192
|
+
}
|
|
16193
|
+
) : pendingEditReview ? /* @__PURE__ */ React24.createElement(
|
|
15886
16194
|
EditConfirm,
|
|
15887
16195
|
{
|
|
15888
16196
|
block: pendingEditReview,
|
|
15889
16197
|
onChoose: (choice) => {
|
|
15890
|
-
const
|
|
15891
|
-
if (
|
|
16198
|
+
const resolve12 = editReviewResolveRef.current;
|
|
16199
|
+
if (resolve12) {
|
|
15892
16200
|
editReviewResolveRef.current = null;
|
|
15893
|
-
|
|
16201
|
+
resolve12(choice);
|
|
15894
16202
|
}
|
|
15895
16203
|
}
|
|
15896
16204
|
}
|
|
15897
|
-
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */
|
|
16205
|
+
) : walkthroughActive && pendingEdits.current.length > 0 ? /* @__PURE__ */ React24.createElement(
|
|
15898
16206
|
EditConfirm,
|
|
15899
16207
|
{
|
|
15900
16208
|
key: `walk-${pendingTick}`,
|
|
15901
16209
|
block: pendingEdits.current[0],
|
|
15902
16210
|
onChoose: handleWalkChoice
|
|
15903
16211
|
}
|
|
15904
|
-
) : /* @__PURE__ */
|
|
16212
|
+
) : /* @__PURE__ */ React24.createElement(React24.Fragment, null, codeMode ? /* @__PURE__ */ React24.createElement(
|
|
15905
16213
|
ModeStatusBar,
|
|
15906
16214
|
{
|
|
15907
16215
|
editMode,
|
|
@@ -15911,7 +16219,7 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15911
16219
|
undoArmed: !!undoBanner || hasUndoable(),
|
|
15912
16220
|
jobs: codeMode.jobs
|
|
15913
16221
|
}
|
|
15914
|
-
) : null, activeLoop ? /* @__PURE__ */
|
|
16222
|
+
) : null, activeLoop ? /* @__PURE__ */ React24.createElement(LoopStatusRow, { loop: activeLoop }) : null, /* @__PURE__ */ React24.createElement(
|
|
15915
16223
|
PromptInput,
|
|
15916
16224
|
{
|
|
15917
16225
|
value: input,
|
|
@@ -15921,14 +16229,14 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15921
16229
|
onHistoryPrev: recallPrev,
|
|
15922
16230
|
onHistoryNext: recallNext
|
|
15923
16231
|
}
|
|
15924
|
-
), /* @__PURE__ */
|
|
16232
|
+
), /* @__PURE__ */ React24.createElement(SlashSuggestions, { matches: slashMatches, selectedIndex: slashSelected }), /* @__PURE__ */ React24.createElement(
|
|
15925
16233
|
AtMentionSuggestions,
|
|
15926
16234
|
{
|
|
15927
16235
|
matches: atMatches,
|
|
15928
16236
|
selectedIndex: atSelected,
|
|
15929
16237
|
query: atPicker?.query ?? ""
|
|
15930
16238
|
}
|
|
15931
|
-
), slashArgContext ? /* @__PURE__ */
|
|
16239
|
+
), slashArgContext ? /* @__PURE__ */ React24.createElement(
|
|
15932
16240
|
SlashArgPicker,
|
|
15933
16241
|
{
|
|
15934
16242
|
matches: slashArgMatches,
|
|
@@ -15942,15 +16250,15 @@ Continue executing from the next pending step. Call mark_step_complete after eac
|
|
|
15942
16250
|
}
|
|
15943
16251
|
|
|
15944
16252
|
// src/cli/ui/SessionPicker.tsx
|
|
15945
|
-
import { Box as
|
|
15946
|
-
import
|
|
16253
|
+
import { Box as Box23, Text as Text21 } from "ink";
|
|
16254
|
+
import React25 from "react";
|
|
15947
16255
|
function SessionPicker({
|
|
15948
16256
|
sessionName,
|
|
15949
16257
|
messageCount,
|
|
15950
16258
|
lastActive,
|
|
15951
16259
|
onChoose
|
|
15952
16260
|
}) {
|
|
15953
|
-
return /* @__PURE__ */
|
|
16261
|
+
return /* @__PURE__ */ React25.createElement(Box23, { flexDirection: "column", marginY: 1 }, /* @__PURE__ */ React25.createElement(Box23, { marginBottom: 1 }, /* @__PURE__ */ React25.createElement(Text21, { bold: true, color: "cyan" }, `Session "${sessionName}" has ${messageCount} prior message${messageCount === 1 ? "" : "s"}`), /* @__PURE__ */ React25.createElement(Text21, { dimColor: true }, ` \xB7 last active ${relativeTime2(lastActive)}`)), /* @__PURE__ */ React25.createElement(
|
|
15954
16262
|
SingleSelect,
|
|
15955
16263
|
{
|
|
15956
16264
|
initialValue: "new",
|
|
@@ -15973,7 +16281,7 @@ function SessionPicker({
|
|
|
15973
16281
|
],
|
|
15974
16282
|
onSubmit: (v) => onChoose(v)
|
|
15975
16283
|
}
|
|
15976
|
-
), /* @__PURE__ */
|
|
16284
|
+
), /* @__PURE__ */ React25.createElement(Box23, { marginTop: 1 }, /* @__PURE__ */ React25.createElement(Text21, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] select")));
|
|
15977
16285
|
}
|
|
15978
16286
|
function relativeTime2(date) {
|
|
15979
16287
|
const ms = Date.now() - date.getTime();
|
|
@@ -15989,9 +16297,9 @@ function relativeTime2(date) {
|
|
|
15989
16297
|
}
|
|
15990
16298
|
|
|
15991
16299
|
// src/cli/ui/Setup.tsx
|
|
15992
|
-
import { Box as
|
|
16300
|
+
import { Box as Box24, Text as Text22, useApp as useApp2 } from "ink";
|
|
15993
16301
|
import TextInput from "ink-text-input";
|
|
15994
|
-
import
|
|
16302
|
+
import React26, { useState as useState11 } from "react";
|
|
15995
16303
|
function Setup({ onReady }) {
|
|
15996
16304
|
const [value, setValue] = useState11("");
|
|
15997
16305
|
const [error, setError] = useState11(null);
|
|
@@ -16015,7 +16323,7 @@ function Setup({ onReady }) {
|
|
|
16015
16323
|
}
|
|
16016
16324
|
onReady(trimmed);
|
|
16017
16325
|
};
|
|
16018
|
-
return /* @__PURE__ */
|
|
16326
|
+
return /* @__PURE__ */ React26.createElement(Box24, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React26.createElement(Text22, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React26.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React26.createElement(Text22, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React26.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React26.createElement(Text22, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React26.createElement(
|
|
16019
16327
|
TextInput,
|
|
16020
16328
|
{
|
|
16021
16329
|
value,
|
|
@@ -16024,7 +16332,7 @@ function Setup({ onReady }) {
|
|
|
16024
16332
|
mask: "\u2022",
|
|
16025
16333
|
placeholder: "sk-..."
|
|
16026
16334
|
}
|
|
16027
|
-
)), error ? /* @__PURE__ */
|
|
16335
|
+
)), error ? /* @__PURE__ */ React26.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React26.createElement(Text22, { color: "red" }, error)) : value ? /* @__PURE__ */ React26.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, "preview: ", redactKey(value))) : null, /* @__PURE__ */ React26.createElement(Box24, { marginTop: 1 }, /* @__PURE__ */ React26.createElement(Text22, { dimColor: true }, "(Type /exit to abort.)")));
|
|
16028
16336
|
}
|
|
16029
16337
|
|
|
16030
16338
|
// src/cli/commands/chat.tsx
|
|
@@ -16040,7 +16348,7 @@ function Root({
|
|
|
16040
16348
|
const [key, setKey] = useState12(initialKey);
|
|
16041
16349
|
const [pending, setPending] = useState12(sessionPreview);
|
|
16042
16350
|
if (!key) {
|
|
16043
|
-
return /* @__PURE__ */
|
|
16351
|
+
return /* @__PURE__ */ React27.createElement(
|
|
16044
16352
|
Setup,
|
|
16045
16353
|
{
|
|
16046
16354
|
onReady: (k) => {
|
|
@@ -16052,7 +16360,7 @@ function Root({
|
|
|
16052
16360
|
}
|
|
16053
16361
|
process.env.DEEPSEEK_API_KEY = key;
|
|
16054
16362
|
if (pending && appProps.session) {
|
|
16055
|
-
return /* @__PURE__ */
|
|
16363
|
+
return /* @__PURE__ */ React27.createElement(KeystrokeProvider, null, /* @__PURE__ */ React27.createElement(
|
|
16056
16364
|
SessionPicker,
|
|
16057
16365
|
{
|
|
16058
16366
|
sessionName: appProps.session,
|
|
@@ -16067,7 +16375,7 @@ function Root({
|
|
|
16067
16375
|
}
|
|
16068
16376
|
));
|
|
16069
16377
|
}
|
|
16070
|
-
return /* @__PURE__ */
|
|
16378
|
+
return /* @__PURE__ */ React27.createElement(KeystrokeProvider, null, /* @__PURE__ */ React27.createElement(
|
|
16071
16379
|
App,
|
|
16072
16380
|
{
|
|
16073
16381
|
model: appProps.model,
|
|
@@ -16165,14 +16473,14 @@ async function chatCommand(opts) {
|
|
|
16165
16473
|
const prior = loadSessionMessages(opts.session);
|
|
16166
16474
|
if (prior.length > 0) {
|
|
16167
16475
|
const p = sessionPath(opts.session);
|
|
16168
|
-
const mtime =
|
|
16476
|
+
const mtime = existsSync15(p) ? statSync9(p).mtime : /* @__PURE__ */ new Date();
|
|
16169
16477
|
sessionPreview = { messageCount: prior.length, lastActive: mtime };
|
|
16170
16478
|
}
|
|
16171
16479
|
} else if (opts.session && opts.forceNew) {
|
|
16172
16480
|
rewriteSession(opts.session, []);
|
|
16173
16481
|
}
|
|
16174
16482
|
const { waitUntilExit } = render(
|
|
16175
|
-
/* @__PURE__ */
|
|
16483
|
+
/* @__PURE__ */ React27.createElement(
|
|
16176
16484
|
Root,
|
|
16177
16485
|
{
|
|
16178
16486
|
initialKey,
|
|
@@ -16196,7 +16504,7 @@ async function chatCommand(opts) {
|
|
|
16196
16504
|
}
|
|
16197
16505
|
|
|
16198
16506
|
// src/cli/commands/code.tsx
|
|
16199
|
-
import { basename as basename2, resolve as
|
|
16507
|
+
import { basename as basename2, resolve as resolve10 } from "path";
|
|
16200
16508
|
|
|
16201
16509
|
// src/index/semantic/builder.ts
|
|
16202
16510
|
import { promises as fs5 } from "fs";
|
|
@@ -16843,29 +17151,32 @@ async function bootstrapSemanticSearchInCodeMode(registry, rootDir, opts = {}) {
|
|
|
16843
17151
|
|
|
16844
17152
|
// src/cli/commands/code.tsx
|
|
16845
17153
|
async function codeCommand(opts = {}) {
|
|
16846
|
-
const { codeSystemPrompt: codeSystemPrompt2 } = await import("./prompt-
|
|
16847
|
-
const rootDir =
|
|
17154
|
+
const { codeSystemPrompt: codeSystemPrompt2 } = await import("./prompt-YRY4HPMZ.js");
|
|
17155
|
+
const rootDir = resolve10(opts.dir ?? process.cwd());
|
|
16848
17156
|
const session = opts.noSession ? void 0 : `code-${sanitizeName(basename2(rootDir))}`;
|
|
16849
17157
|
const tools = new ToolRegistry();
|
|
16850
|
-
registerFilesystemTools(tools, { rootDir });
|
|
16851
17158
|
const jobs2 = new JobRegistry();
|
|
16852
|
-
|
|
16853
|
-
rootDir
|
|
16854
|
-
|
|
16855
|
-
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
|
|
16859
|
-
|
|
16860
|
-
|
|
16861
|
-
|
|
16862
|
-
|
|
16863
|
-
|
|
16864
|
-
|
|
16865
|
-
|
|
17159
|
+
const registerRootedTools = (root) => {
|
|
17160
|
+
registerFilesystemTools(tools, { rootDir: root });
|
|
17161
|
+
registerShellTools(tools, {
|
|
17162
|
+
rootDir: root,
|
|
17163
|
+
// Per-project "always allow" list persisted from prior ShellConfirm
|
|
17164
|
+
// choices; merged on top of the built-in allowlist in shell.ts.
|
|
17165
|
+
// GETTER form — re-read every dispatch so a prefix the user adds
|
|
17166
|
+
// via ShellConfirm mid-session takes effect on the next shell call
|
|
17167
|
+
// instead of waiting for `/new` or a relaunch.
|
|
17168
|
+
extraAllowed: () => loadProjectShellAllowed(root),
|
|
17169
|
+
// `yolo` edit-mode disables shell confirmations entirely. Re-read
|
|
17170
|
+
// from config on each dispatch so /mode yolo (or Shift+Tab cycling
|
|
17171
|
+
// through to it) flips the gate live without forcing a relaunch.
|
|
17172
|
+
allowAll: () => loadEditMode() === "yolo",
|
|
17173
|
+
jobs: jobs2
|
|
17174
|
+
});
|
|
17175
|
+
registerMemoryTools(tools, { projectRoot: root });
|
|
17176
|
+
};
|
|
17177
|
+
registerRootedTools(rootDir);
|
|
16866
17178
|
registerPlanTool(tools);
|
|
16867
17179
|
registerChoiceTool(tools);
|
|
16868
|
-
registerMemoryTools(tools, { projectRoot: rootDir });
|
|
16869
17180
|
const semantic2 = await bootstrapSemanticSearchInCodeMode(tools, rootDir);
|
|
16870
17181
|
process.stderr.write(
|
|
16871
17182
|
`\u25B8 reasonix code: rooted at ${rootDir}, session "${session ?? "(ephemeral)"}" \xB7 ${tools.size} native tool(s)${semantic2.enabled ? " \xB7 semantic_search on" : ""}
|
|
@@ -16881,7 +17192,7 @@ async function codeCommand(opts = {}) {
|
|
|
16881
17192
|
transcript: opts.transcript,
|
|
16882
17193
|
session,
|
|
16883
17194
|
seedTools: tools,
|
|
16884
|
-
codeMode: { rootDir, jobs: jobs2 },
|
|
17195
|
+
codeMode: { rootDir, jobs: jobs2, reregisterTools: registerRootedTools },
|
|
16885
17196
|
forceResume: opts.forceResume,
|
|
16886
17197
|
forceNew: opts.forceNew
|
|
16887
17198
|
});
|
|
@@ -16891,35 +17202,35 @@ async function codeCommand(opts = {}) {
|
|
|
16891
17202
|
import { writeFileSync as writeFileSync8 } from "fs";
|
|
16892
17203
|
import { basename as basename3 } from "path";
|
|
16893
17204
|
import { render as render2 } from "ink";
|
|
16894
|
-
import
|
|
17205
|
+
import React30 from "react";
|
|
16895
17206
|
|
|
16896
17207
|
// src/cli/ui/DiffApp.tsx
|
|
16897
|
-
import { Box as
|
|
16898
|
-
import
|
|
17208
|
+
import { Box as Box26, Static as Static2, Text as Text24, useApp as useApp3, useInput } from "ink";
|
|
17209
|
+
import React29, { useState as useState13 } from "react";
|
|
16899
17210
|
|
|
16900
17211
|
// src/cli/ui/RecordView.tsx
|
|
16901
|
-
import { Box as
|
|
16902
|
-
import
|
|
17212
|
+
import { Box as Box25, Text as Text23 } from "ink";
|
|
17213
|
+
import React28 from "react";
|
|
16903
17214
|
function RecordView({ rec, compact: compact2 = false }) {
|
|
16904
17215
|
const toolArgsMax = compact2 ? 120 : 200;
|
|
16905
17216
|
const toolContentMax = compact2 ? 200 : 400;
|
|
16906
17217
|
if (rec.role === "user") {
|
|
16907
17218
|
const content = rec.content.includes("\n") ? rec.content.split("\n").join("\n ") : rec.content;
|
|
16908
|
-
return /* @__PURE__ */
|
|
17219
|
+
return /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text23, { bold: true, color: "cyan" }, "you \u203A", " "), /* @__PURE__ */ React28.createElement(Text23, null, content));
|
|
16909
17220
|
}
|
|
16910
17221
|
if (rec.role === "assistant_final") {
|
|
16911
|
-
return /* @__PURE__ */
|
|
17222
|
+
return /* @__PURE__ */ React28.createElement(Box25, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React28.createElement(Box25, null, /* @__PURE__ */ React28.createElement(Text23, { bold: true, color: "green" }, "assistant"), rec.cost !== void 0 ? /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, " $", rec.cost.toFixed(6)) : null, rec.usage ? /* @__PURE__ */ React28.createElement(CacheBadge, { usage: rec.usage }) : null), rec.planState ? /* @__PURE__ */ React28.createElement(PlanStateBlock, { planState: rec.planState }) : null, rec.content ? /* @__PURE__ */ React28.createElement(Text23, null, rec.content) : /* @__PURE__ */ React28.createElement(Text23, { dimColor: true, italic: true }, "(tool-call response only)"));
|
|
16912
17223
|
}
|
|
16913
17224
|
if (rec.role === "tool") {
|
|
16914
|
-
return /* @__PURE__ */
|
|
17225
|
+
return /* @__PURE__ */ React28.createElement(Box25, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text23, { color: "yellow" }, "tool<", rec.tool ?? "?", ">"), rec.args ? /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, " args: ", truncate2(rec.args, toolArgsMax)) : null, /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, " \u2192 ", truncate2(rec.content, toolContentMax)));
|
|
16915
17226
|
}
|
|
16916
17227
|
if (rec.role === "error") {
|
|
16917
|
-
return /* @__PURE__ */
|
|
17228
|
+
return /* @__PURE__ */ React28.createElement(Box25, { marginTop: 1 }, /* @__PURE__ */ React28.createElement(Text23, { color: "red", bold: true }, "error", " "), /* @__PURE__ */ React28.createElement(Text23, { color: "red" }, rec.error ?? rec.content));
|
|
16918
17229
|
}
|
|
16919
17230
|
if (rec.role === "done" || rec.role === "assistant_delta") {
|
|
16920
17231
|
return null;
|
|
16921
17232
|
}
|
|
16922
|
-
return /* @__PURE__ */
|
|
17233
|
+
return /* @__PURE__ */ React28.createElement(Box25, null, /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, "[", rec.role, "] ", rec.content));
|
|
16923
17234
|
}
|
|
16924
17235
|
function CacheBadge({ usage }) {
|
|
16925
17236
|
const hit = usage.prompt_cache_hit_tokens ?? 0;
|
|
@@ -16928,7 +17239,7 @@ function CacheBadge({ usage }) {
|
|
|
16928
17239
|
if (total === 0) return null;
|
|
16929
17240
|
const pct2 = hit / total * 100;
|
|
16930
17241
|
const color = pct2 >= 70 ? "green" : pct2 >= 40 ? "yellow" : "red";
|
|
16931
|
-
return /* @__PURE__ */
|
|
17242
|
+
return /* @__PURE__ */ React28.createElement(Text23, null, /* @__PURE__ */ React28.createElement(Text23, { dimColor: true }, " \xB7 cache "), /* @__PURE__ */ React28.createElement(Text23, { color }, pct2.toFixed(1), "%"));
|
|
16932
17243
|
}
|
|
16933
17244
|
function truncate2(s, max) {
|
|
16934
17245
|
return s.length <= max ? s : `${s.slice(0, max)}\u2026 (+${s.length - max} chars)`;
|
|
@@ -16962,7 +17273,7 @@ function DiffApp({ report }) {
|
|
|
16962
17273
|
}
|
|
16963
17274
|
});
|
|
16964
17275
|
const pair = report.pairs[idx];
|
|
16965
|
-
return /* @__PURE__ */
|
|
17276
|
+
return /* @__PURE__ */ React29.createElement(Box26, { flexDirection: "column" }, /* @__PURE__ */ React29.createElement(DiffHeader, { report }), /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1, paddingX: 1, justifyContent: "space-between" }, /* @__PURE__ */ React29.createElement(Text24, { color: "cyan", bold: true }, "turn ", pair?.turn ?? "?", " (", idx + 1, " / ", report.pairs.length, ")"), /* @__PURE__ */ React29.createElement(Text24, null, pair ? /* @__PURE__ */ React29.createElement(KindBadge, { kind: pair.kind }) : null)), /* @__PURE__ */ React29.createElement(Box26, { flexDirection: "row", marginTop: 1 }, /* @__PURE__ */ React29.createElement(Pane, { label: report.a.label, headerColor: "blue", records: paneRecords(pair, "a") }), /* @__PURE__ */ React29.createElement(Pane, { label: report.b.label, headerColor: "magenta", records: paneRecords(pair, "b") })), pair?.divergenceNote ? /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React29.createElement(Text24, { color: "yellow" }, "\u2605 "), /* @__PURE__ */ React29.createElement(Text24, null, pair.divergenceNote)) : null, /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "j"), "/", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "\u2193"), " next \xB7 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "k"), "/", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "\u2191"), " ", "prev \xB7 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "n"), " next-diverge \xB7 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "N"), "/", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "p"), " ", "prev-diverge \xB7 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "g"), "/", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "G"), " first/last \xB7 ", /* @__PURE__ */ React29.createElement(Text24, { bold: true }, "q"), " ", "quit")));
|
|
16966
17277
|
}
|
|
16967
17278
|
function DiffHeader({ report }) {
|
|
16968
17279
|
const a = report.a;
|
|
@@ -16980,15 +17291,15 @@ function DiffHeader({ report }) {
|
|
|
16980
17291
|
} else if (a.stats.prefixHashes[0] && a.stats.prefixHashes[0] === b.stats.prefixHashes[0]) {
|
|
16981
17292
|
prefixLine = `shared prefix hash ${a.stats.prefixHashes[0].slice(0, 12)}\u2026 \u2014 cache delta attributable to log stability, not prompt change.`;
|
|
16982
17293
|
}
|
|
16983
|
-
return /* @__PURE__ */
|
|
17294
|
+
return /* @__PURE__ */ React29.createElement(Box26, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React29.createElement(Box26, { justifyContent: "space-between" }, /* @__PURE__ */ React29.createElement(Text24, null, /* @__PURE__ */ React29.createElement(Text24, { color: "cyan", bold: true }, "reasonix diff"), /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, " \xB7 A="), /* @__PURE__ */ React29.createElement(Text24, { color: "blue" }, a.label), /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, " vs B="), /* @__PURE__ */ React29.createElement(Text24, { color: "magenta" }, b.label)), /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, report.pairs.length, " turns aligned")), /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1, gap: 3 }, /* @__PURE__ */ React29.createElement(Text24, null, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, "cache "), /* @__PURE__ */ React29.createElement(Text24, null, (a.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React29.createElement(Text24, null, (b.stats.cacheHitRatio * 100).toFixed(1), "%"), /* @__PURE__ */ React29.createElement(Text24, { color: cacheDelta >= 0 ? "green" : "red", bold: true }, " ", cacheDelta >= 0 ? "+" : "", (cacheDelta * 100).toFixed(1), "pp")), /* @__PURE__ */ React29.createElement(Text24, null, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, "cost "), /* @__PURE__ */ React29.createElement(Text24, null, "$", a.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, " \u2192 "), /* @__PURE__ */ React29.createElement(Text24, null, "$", b.stats.totalCostUsd.toFixed(6)), /* @__PURE__ */ React29.createElement(Text24, { color: costDelta2 <= 0 ? "green" : "red", bold: true }, " ", costDelta2 >= 0 ? "+" : "", costDelta2.toFixed(1), "%")), /* @__PURE__ */ React29.createElement(Text24, null, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true }, "model calls "), /* @__PURE__ */ React29.createElement(Text24, null, a.stats.turns, " \u2192 ", b.stats.turns))), prefixLine ? /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true, italic: true }, prefixLine)) : null);
|
|
16984
17295
|
}
|
|
16985
17296
|
function Pane({
|
|
16986
17297
|
label,
|
|
16987
17298
|
headerColor,
|
|
16988
17299
|
records
|
|
16989
17300
|
}) {
|
|
16990
|
-
return /* @__PURE__ */
|
|
16991
|
-
|
|
17301
|
+
return /* @__PURE__ */ React29.createElement(
|
|
17302
|
+
Box26,
|
|
16992
17303
|
{
|
|
16993
17304
|
flexDirection: "column",
|
|
16994
17305
|
flexGrow: 1,
|
|
@@ -16996,21 +17307,21 @@ function Pane({
|
|
|
16996
17307
|
borderStyle: "single",
|
|
16997
17308
|
borderColor: headerColor
|
|
16998
17309
|
},
|
|
16999
|
-
/* @__PURE__ */
|
|
17000
|
-
records.length === 0 ? /* @__PURE__ */
|
|
17310
|
+
/* @__PURE__ */ React29.createElement(Text24, { color: headerColor, bold: true }, label),
|
|
17311
|
+
records.length === 0 ? /* @__PURE__ */ React29.createElement(Box26, { marginTop: 1 }, /* @__PURE__ */ React29.createElement(Text24, { dimColor: true, italic: true }, "(no records on this side for this turn)")) : /* @__PURE__ */ React29.createElement(Static2, { items: records.map((rec, i) => ({ key: `${label}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React29.createElement(RecordView, { key, rec, compact: true }))
|
|
17001
17312
|
);
|
|
17002
17313
|
}
|
|
17003
17314
|
function KindBadge({ kind }) {
|
|
17004
17315
|
if (kind === "match") {
|
|
17005
|
-
return /* @__PURE__ */
|
|
17316
|
+
return /* @__PURE__ */ React29.createElement(Text24, { color: "green" }, "\u2713 match");
|
|
17006
17317
|
}
|
|
17007
17318
|
if (kind === "diverge") {
|
|
17008
|
-
return /* @__PURE__ */
|
|
17319
|
+
return /* @__PURE__ */ React29.createElement(Text24, { color: "yellow" }, "\u2605 diverge");
|
|
17009
17320
|
}
|
|
17010
17321
|
if (kind === "only_in_a") {
|
|
17011
|
-
return /* @__PURE__ */
|
|
17322
|
+
return /* @__PURE__ */ React29.createElement(Text24, { color: "blue" }, "\u2190 only in A");
|
|
17012
17323
|
}
|
|
17013
|
-
return /* @__PURE__ */
|
|
17324
|
+
return /* @__PURE__ */ React29.createElement(Text24, { color: "magenta" }, "\u2192 only in B");
|
|
17014
17325
|
}
|
|
17015
17326
|
function paneRecords(pair, side) {
|
|
17016
17327
|
if (!pair) return [];
|
|
@@ -17041,7 +17352,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
17041
17352
|
return;
|
|
17042
17353
|
}
|
|
17043
17354
|
if (wantTui) {
|
|
17044
|
-
const { waitUntilExit } = render2(
|
|
17355
|
+
const { waitUntilExit } = render2(React30.createElement(DiffApp, { report }), {
|
|
17045
17356
|
exitOnCtrlC: true,
|
|
17046
17357
|
patchConsole: false
|
|
17047
17358
|
});
|
|
@@ -17052,7 +17363,7 @@ markdown report written to ${opts.mdPath}`);
|
|
|
17052
17363
|
}
|
|
17053
17364
|
|
|
17054
17365
|
// src/cli/commands/index.ts
|
|
17055
|
-
import { resolve as
|
|
17366
|
+
import { resolve as resolve11 } from "path";
|
|
17056
17367
|
|
|
17057
17368
|
// src/index/semantic/preflight.ts
|
|
17058
17369
|
import { stdin as stdin2, stdout } from "process";
|
|
@@ -17126,7 +17437,7 @@ async function confirm(question, defaultYes) {
|
|
|
17126
17437
|
|
|
17127
17438
|
// src/cli/commands/index.ts
|
|
17128
17439
|
async function indexCommand(opts = {}) {
|
|
17129
|
-
const root =
|
|
17440
|
+
const root = resolve11(opts.dir ?? process.cwd());
|
|
17130
17441
|
const tty = process.stderr.isTTY === true && process.stdin.isTTY === true;
|
|
17131
17442
|
const model2 = opts.model ?? process.env.REASONIX_EMBED_MODEL ?? "nomic-embed-text";
|
|
17132
17443
|
const preflightOk = await ollamaPreflight({
|
|
@@ -17376,11 +17687,11 @@ function pad2(s, width) {
|
|
|
17376
17687
|
|
|
17377
17688
|
// src/cli/commands/replay.ts
|
|
17378
17689
|
import { render as render3 } from "ink";
|
|
17379
|
-
import
|
|
17690
|
+
import React32 from "react";
|
|
17380
17691
|
|
|
17381
17692
|
// src/cli/ui/ReplayApp.tsx
|
|
17382
|
-
import { Box as
|
|
17383
|
-
import
|
|
17693
|
+
import { Box as Box27, Static as Static3, Text as Text25, useApp as useApp4, useInput as useInput2 } from "ink";
|
|
17694
|
+
import React31, { useMemo as useMemo4, useState as useState14 } from "react";
|
|
17384
17695
|
function ReplayApp({ meta, pages }) {
|
|
17385
17696
|
const { exit: exit2 } = useApp4();
|
|
17386
17697
|
const maxIdx = Math.max(0, pages.length - 1);
|
|
@@ -17420,14 +17731,14 @@ function ReplayApp({ meta, pages }) {
|
|
|
17420
17731
|
const prefixHash = cumStats.prefixHashes.length === 1 ? cumStats.prefixHashes[0].slice(0, 16) : cumStats.prefixHashes.length === 0 ? "(untracked)" : `(churned \xD7${cumStats.prefixHashes.length})`;
|
|
17421
17732
|
const currentPage = pages[idx];
|
|
17422
17733
|
const progressLabel = pages.length === 0 ? "empty transcript" : `turn ${idx + 1} / ${pages.length}`;
|
|
17423
|
-
return /* @__PURE__ */
|
|
17734
|
+
return /* @__PURE__ */ React31.createElement(Box27, { flexDirection: "column" }, /* @__PURE__ */ React31.createElement(
|
|
17424
17735
|
StatsPanel,
|
|
17425
17736
|
{
|
|
17426
17737
|
summary,
|
|
17427
17738
|
model: cumStats.models[0] ?? meta?.model ?? "?",
|
|
17428
17739
|
prefixHash
|
|
17429
17740
|
}
|
|
17430
|
-
), /* @__PURE__ */
|
|
17741
|
+
), /* @__PURE__ */ React31.createElement(Box27, { flexDirection: "column", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React31.createElement(Box27, { justifyContent: "space-between" }, /* @__PURE__ */ React31.createElement(Text25, { color: "cyan", bold: true }, progressLabel), meta ? /* @__PURE__ */ React31.createElement(Text25, { dimColor: true }, meta.source, meta.task ? ` \xB7 ${meta.task}` : "", meta.mode ? ` \xB7 ${meta.mode}` : "") : null), currentPage ? /* @__PURE__ */ React31.createElement(Static3, { items: currentPage.records.map((rec, i) => ({ key: `${idx}-${i}`, rec })) }, ({ key, rec }) => /* @__PURE__ */ React31.createElement(RecordView, { key, rec })) : /* @__PURE__ */ React31.createElement(Text25, { dimColor: true, italic: true }, "no records")), /* @__PURE__ */ React31.createElement(Box27, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "gray" }, /* @__PURE__ */ React31.createElement(Text25, { dimColor: true }, /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "j"), "/", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "\u2193"), "/", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "space"), " next \xB7 ", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "k"), "/", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "\u2191"), " prev \xB7 ", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "g"), " first \xB7 ", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "G"), " last \xB7", " ", /* @__PURE__ */ React31.createElement(Text25, { bold: true }, "q"), " quit")));
|
|
17431
17742
|
}
|
|
17432
17743
|
|
|
17433
17744
|
// src/cli/commands/replay.ts
|
|
@@ -17439,7 +17750,7 @@ async function replayCommand(opts) {
|
|
|
17439
17750
|
}
|
|
17440
17751
|
const { parsed } = replayFromFile(opts.path);
|
|
17441
17752
|
const pages = groupRecordsByTurn(parsed.records);
|
|
17442
|
-
const { waitUntilExit } = render3(
|
|
17753
|
+
const { waitUntilExit } = render3(React32.createElement(ReplayApp, { meta: parsed.meta, pages }), {
|
|
17443
17754
|
exitOnCtrlC: true,
|
|
17444
17755
|
patchConsole: false
|
|
17445
17756
|
});
|
|
@@ -17744,12 +18055,12 @@ function truncate3(s, max) {
|
|
|
17744
18055
|
|
|
17745
18056
|
// src/cli/commands/setup.tsx
|
|
17746
18057
|
import { render as render4 } from "ink";
|
|
17747
|
-
import
|
|
18058
|
+
import React34 from "react";
|
|
17748
18059
|
|
|
17749
18060
|
// src/cli/ui/Wizard.tsx
|
|
17750
|
-
import { Box as
|
|
18061
|
+
import { Box as Box28, Text as Text26, useApp as useApp5, useInput as useInput3 } from "ink";
|
|
17751
18062
|
import TextInput2 from "ink-text-input";
|
|
17752
|
-
import
|
|
18063
|
+
import React33, { useState as useState15 } from "react";
|
|
17753
18064
|
|
|
17754
18065
|
// src/cli/ui/presets.ts
|
|
17755
18066
|
var PRESETS = {
|
|
@@ -17797,7 +18108,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17797
18108
|
if (key.escape && step !== "saved" && onCancel) onCancel();
|
|
17798
18109
|
});
|
|
17799
18110
|
if (step === "apiKey") {
|
|
17800
|
-
return /* @__PURE__ */
|
|
18111
|
+
return /* @__PURE__ */ React33.createElement(
|
|
17801
18112
|
ApiKeyStep,
|
|
17802
18113
|
{
|
|
17803
18114
|
onSubmit: (key) => {
|
|
@@ -17811,7 +18122,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17811
18122
|
);
|
|
17812
18123
|
}
|
|
17813
18124
|
if (step === "preset") {
|
|
17814
|
-
return /* @__PURE__ */
|
|
18125
|
+
return /* @__PURE__ */ React33.createElement(StepFrame, { title: "Pick a preset", step: 1, total: 3 }, /* @__PURE__ */ React33.createElement(
|
|
17815
18126
|
SingleSelect,
|
|
17816
18127
|
{
|
|
17817
18128
|
items: presetItems(),
|
|
@@ -17821,10 +18132,10 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17821
18132
|
setStep("mcp");
|
|
17822
18133
|
}
|
|
17823
18134
|
}
|
|
17824
|
-
), /* @__PURE__ */
|
|
18135
|
+
), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "[\u2191\u2193] navigate \xB7 [Enter] confirm \xB7 [Esc] cancel")));
|
|
17825
18136
|
}
|
|
17826
18137
|
if (step === "mcp") {
|
|
17827
|
-
return /* @__PURE__ */
|
|
18138
|
+
return /* @__PURE__ */ React33.createElement(StepFrame, { title: "Which MCP servers should Reasonix wire up for you?", step: 2, total: 3 }, /* @__PURE__ */ React33.createElement(
|
|
17828
18139
|
MultiSelect,
|
|
17829
18140
|
{
|
|
17830
18141
|
items: mcpItems(),
|
|
@@ -17849,7 +18160,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17849
18160
|
}
|
|
17850
18161
|
const currentName = pending[0];
|
|
17851
18162
|
const entry = CATALOG_BY_NAME.get(currentName);
|
|
17852
|
-
return /* @__PURE__ */
|
|
18163
|
+
return /* @__PURE__ */ React33.createElement(
|
|
17853
18164
|
McpArgsStep,
|
|
17854
18165
|
{
|
|
17855
18166
|
entry,
|
|
@@ -17867,7 +18178,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17867
18178
|
}
|
|
17868
18179
|
if (step === "review") {
|
|
17869
18180
|
const specs = data.selectedCatalog.map((name) => buildSpec(name, data.catalogArgs));
|
|
17870
|
-
return /* @__PURE__ */
|
|
18181
|
+
return /* @__PURE__ */ React33.createElement(StepFrame, { title: "Ready to save", step: 3, total: 3 }, /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(SummaryLine, { label: "API key", value: redactKey(data.apiKey) }), /* @__PURE__ */ React33.createElement(SummaryLine, { label: "Preset", value: data.preset }), /* @__PURE__ */ React33.createElement(
|
|
17871
18182
|
SummaryLine,
|
|
17872
18183
|
{
|
|
17873
18184
|
label: "MCP",
|
|
@@ -17875,8 +18186,8 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17875
18186
|
}
|
|
17876
18187
|
), specs.map((spec, i) => (
|
|
17877
18188
|
// biome-ignore lint/suspicious/noArrayIndexKey: review-only render, order fixed
|
|
17878
|
-
/* @__PURE__ */
|
|
17879
|
-
)), /* @__PURE__ */
|
|
18189
|
+
/* @__PURE__ */ React33.createElement(Box28, { key: i, paddingLeft: 14 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "\xB7 ", spec))
|
|
18190
|
+
)), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, null, "Saves to ", defaultConfigPath())), error ? /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { color: "red" }, error)) : null, /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "[Enter] save \xB7 [Esc] cancel"))), /* @__PURE__ */ React33.createElement(
|
|
17880
18191
|
ReviewConfirm,
|
|
17881
18192
|
{
|
|
17882
18193
|
onConfirm: () => {
|
|
@@ -17902,7 +18213,7 @@ function Wizard({ onComplete, onCancel, existingApiKey, initial }) {
|
|
|
17902
18213
|
}
|
|
17903
18214
|
));
|
|
17904
18215
|
}
|
|
17905
|
-
return /* @__PURE__ */
|
|
18216
|
+
return /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 1 }, /* @__PURE__ */ React33.createElement(Text26, { bold: true, color: "green" }, "\u25B8 Saved."), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, null, "Run `reasonix` any time to start chatting \u2014 your settings are remembered.")), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "[Enter] to exit")), /* @__PURE__ */ React33.createElement(ExitOnEnter, { onExit: exit2 }));
|
|
17906
18217
|
}
|
|
17907
18218
|
function ApiKeyStep({
|
|
17908
18219
|
onSubmit,
|
|
@@ -17910,7 +18221,7 @@ function ApiKeyStep({
|
|
|
17910
18221
|
onError
|
|
17911
18222
|
}) {
|
|
17912
18223
|
const [value, setValue] = useState15("");
|
|
17913
|
-
return /* @__PURE__ */
|
|
18224
|
+
return /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React33.createElement(Text26, { bold: true, color: "cyan" }, "Welcome to Reasonix."), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, null, "Paste your DeepSeek API key to get started.")), /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "Get one (free credit on signup): https://platform.deepseek.com/api_keys"), /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "Saved locally to ", defaultConfigPath()), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { bold: true, color: "cyan" }, "key \u203A "), /* @__PURE__ */ React33.createElement(
|
|
17914
18225
|
TextInput2,
|
|
17915
18226
|
{
|
|
17916
18227
|
value,
|
|
@@ -17927,7 +18238,7 @@ function ApiKeyStep({
|
|
|
17927
18238
|
mask: "\u2022",
|
|
17928
18239
|
placeholder: "sk-..."
|
|
17929
18240
|
}
|
|
17930
|
-
)), error ? /* @__PURE__ */
|
|
18241
|
+
)), error ? /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { color: "red" }, error)) : value ? /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "preview: ", redactKey(value))) : null);
|
|
17931
18242
|
}
|
|
17932
18243
|
function McpArgsStep({
|
|
17933
18244
|
entry,
|
|
@@ -17936,7 +18247,7 @@ function McpArgsStep({
|
|
|
17936
18247
|
onError
|
|
17937
18248
|
}) {
|
|
17938
18249
|
const [value, setValue] = useState15("");
|
|
17939
|
-
return /* @__PURE__ */
|
|
18250
|
+
return /* @__PURE__ */ React33.createElement(StepFrame, { title: `Configure ${entry.name}`, step: 2, total: 3 }, /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column" }, /* @__PURE__ */ React33.createElement(Text26, null, entry.summary), entry.note ? /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, entry.note)) : null, /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, null, "Required parameter: "), /* @__PURE__ */ React33.createElement(Text26, { bold: true }, entry.userArgs)), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { bold: true, color: "cyan" }, entry.userArgs, " \u203A "), /* @__PURE__ */ React33.createElement(
|
|
17940
18251
|
TextInput2,
|
|
17941
18252
|
{
|
|
17942
18253
|
value,
|
|
@@ -17952,7 +18263,7 @@ function McpArgsStep({
|
|
|
17952
18263
|
},
|
|
17953
18264
|
placeholder: placeholderFor(entry)
|
|
17954
18265
|
}
|
|
17955
|
-
)), error ? /* @__PURE__ */
|
|
18266
|
+
)), error ? /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1 }, /* @__PURE__ */ React33.createElement(Text26, { color: "red" }, error)) : null));
|
|
17956
18267
|
}
|
|
17957
18268
|
function ReviewConfirm({ onConfirm }) {
|
|
17958
18269
|
useInput3((_i, key) => {
|
|
@@ -17972,10 +18283,10 @@ function StepFrame({
|
|
|
17972
18283
|
total,
|
|
17973
18284
|
children
|
|
17974
18285
|
}) {
|
|
17975
|
-
return /* @__PURE__ */
|
|
18286
|
+
return /* @__PURE__ */ React33.createElement(Box28, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1 }, /* @__PURE__ */ React33.createElement(Box28, null, /* @__PURE__ */ React33.createElement(Text26, { dimColor: true }, "Step ", step, "/", total, " \xB7", " "), /* @__PURE__ */ React33.createElement(Text26, { bold: true, color: "cyan" }, title)), /* @__PURE__ */ React33.createElement(Box28, { marginTop: 1, flexDirection: "column" }, children));
|
|
17976
18287
|
}
|
|
17977
18288
|
function SummaryLine({ label, value }) {
|
|
17978
|
-
return /* @__PURE__ */
|
|
18289
|
+
return /* @__PURE__ */ React33.createElement(Box28, null, /* @__PURE__ */ React33.createElement(Text26, null, label.padEnd(12)), /* @__PURE__ */ React33.createElement(Text26, { bold: true }, value));
|
|
17979
18290
|
}
|
|
17980
18291
|
function presetItems() {
|
|
17981
18292
|
return ["fast", "smart", "max"].map((name) => ({
|
|
@@ -18031,7 +18342,7 @@ async function setupCommand(_opts = {}) {
|
|
|
18031
18342
|
const existingKey = loadApiKey();
|
|
18032
18343
|
const existing = readConfig();
|
|
18033
18344
|
const { waitUntilExit, unmount } = render4(
|
|
18034
|
-
/* @__PURE__ */
|
|
18345
|
+
/* @__PURE__ */ React34.createElement(
|
|
18035
18346
|
Wizard,
|
|
18036
18347
|
{
|
|
18037
18348
|
existingApiKey: existingKey,
|
|
@@ -18079,13 +18390,13 @@ function planUpdate(input) {
|
|
|
18079
18390
|
};
|
|
18080
18391
|
}
|
|
18081
18392
|
function defaultSpawn(argv) {
|
|
18082
|
-
return new Promise((
|
|
18393
|
+
return new Promise((resolve12, reject) => {
|
|
18083
18394
|
const child = spawn6(argv[0], argv.slice(1), {
|
|
18084
18395
|
stdio: "inherit",
|
|
18085
18396
|
shell: process.platform === "win32"
|
|
18086
18397
|
});
|
|
18087
18398
|
child.once("error", reject);
|
|
18088
|
-
child.once("exit", (code) =>
|
|
18399
|
+
child.once("exit", (code) => resolve12(code ?? 1));
|
|
18089
18400
|
});
|
|
18090
18401
|
}
|
|
18091
18402
|
async function updateCommand(opts = {}) {
|