@asathinkeroops/nova-code 0.1.0-beta.6 → 0.1.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +439 -230
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1395,6 +1395,20 @@ var settingsSchema = z2.object({
|
|
|
1395
1395
|
additionalDirectories: [],
|
|
1396
1396
|
autoMode: { llmClassifier: true, classifierTimeoutMs: 8e3 }
|
|
1397
1397
|
}),
|
|
1398
|
+
// Workspace trust. On startup nova checks whether the workspace it was
|
|
1399
|
+
// launched in has been granted file access; an untrusted workspace prompts
|
|
1400
|
+
// the user to confirm, and declining exits. Trust is recorded HERE (in the
|
|
1401
|
+
// user-global config, which a project cannot write) rather than in any
|
|
1402
|
+
// project-checked-in file — mirroring Claude Code's `~/.claude.json` model,
|
|
1403
|
+
// so a cloned repo can never mark itself trusted. `trustedRoots` are absolute
|
|
1404
|
+
// canonical paths; a workspace equal to or nested under any of them is
|
|
1405
|
+
// trusted (so trusting a repo root covers its subdirectories). Users may
|
|
1406
|
+
// pre-seed roots by hand. Set `enabled: false` to restore the legacy
|
|
1407
|
+
// "workspace is always trusted on launch" behavior.
|
|
1408
|
+
trust: z2.object({
|
|
1409
|
+
enabled: z2.boolean().default(true),
|
|
1410
|
+
trustedRoots: z2.array(z2.string().min(1)).default([])
|
|
1411
|
+
}).default({ enabled: true, trustedRoots: [] }),
|
|
1398
1412
|
transcript: z2.object({
|
|
1399
1413
|
enabled: z2.boolean().default(true)
|
|
1400
1414
|
}).default({ enabled: true }),
|
|
@@ -2417,7 +2431,7 @@ function buildSystemPrompt(workspace, memory, sessionId, skillsBlock = "", langu
|
|
|
2417
2431
|
- Run long-lived commands (dev servers, watchers, builds) with runInBackground; it returns immediately and its output is delivered to you automatically when the command finishes \u2014 no need to poll.
|
|
2418
2432
|
- Load specialized knowledge with loadSkill.
|
|
2419
2433
|
- Delegate focused subtasks to parallel sub-agents with createSubAgent (type: explore = read-only retrieval, plan = read-only planning, general-purpose = full tools).
|
|
2420
|
-
- Don't guess file paths. When unsure whether a file
|
|
2434
|
+
- Don't guess file paths. When unsure whether a file or directory exists, locate it with glob/grep/ls before acting \u2014 a read, write, edit, or mkdir on a wrong path just wastes a turn or causes damage.
|
|
2421
2435
|
- Respond in ${language} by default, even when a tool or sub-agent returns content in another language \u2014 relay and summarize it in ${language}. Preserve that exact script and regional variant; do not switch it.
|
|
2422
2436
|
|
|
2423
2437
|
When I ask you to commit, follow the repo's own version-control conventions:
|
|
@@ -5298,13 +5312,15 @@ ${xmlEscape(payload)}
|
|
|
5298
5312
|
|
|
5299
5313
|
// ../../packages/tools/src/builtin/read.ts
|
|
5300
5314
|
import { readFile as readFile10 } from "fs/promises";
|
|
5301
|
-
import { extname as extname2, resolve as resolve9 } from "path";
|
|
5315
|
+
import { basename as basename3, extname as extname2, resolve as resolve9 } from "path";
|
|
5302
5316
|
import { z as z13 } from "zod";
|
|
5303
5317
|
import * as XLSX from "xlsx";
|
|
5318
|
+
import { extractText as extractText2 } from "unpdf";
|
|
5304
5319
|
var MAX_CHARS = 2e5;
|
|
5305
5320
|
var MAX_LINE_CHARS = 16e3;
|
|
5306
5321
|
var LINE_NO_WIDTH = 6;
|
|
5307
5322
|
var EXCEL_EXTENSIONS = /* @__PURE__ */ new Set([".xlsx", ".xls", ".xlsm", ".xlsb", ".ods"]);
|
|
5323
|
+
var MAX_PDF_BYTES = 3e7;
|
|
5308
5324
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".webp"]);
|
|
5309
5325
|
var MAX_IMAGE_BYTES = 2e7;
|
|
5310
5326
|
var IMAGE_MAGIC = {
|
|
@@ -5352,6 +5368,28 @@ function renderLines(lines, total, startIdx, endIdx, path3) {
|
|
|
5352
5368
|
}
|
|
5353
5369
|
return body;
|
|
5354
5370
|
}
|
|
5371
|
+
function paginateLines(raw, input, path3) {
|
|
5372
|
+
const lines = raw.match(/[^\n]*\n|[^\n]+$/g) ?? [];
|
|
5373
|
+
const total = lines.length;
|
|
5374
|
+
const startLine = input.offset ?? 1;
|
|
5375
|
+
const startIdx = startLine - 1;
|
|
5376
|
+
if (startIdx >= total && total > 0) {
|
|
5377
|
+
return {
|
|
5378
|
+
output: `read: offset ${startLine} is past end of file (it has ${total} lines)`,
|
|
5379
|
+
isError: true
|
|
5380
|
+
};
|
|
5381
|
+
}
|
|
5382
|
+
let endIdx = startIdx;
|
|
5383
|
+
let chars = 0;
|
|
5384
|
+
while (endIdx < total) {
|
|
5385
|
+
if (input.limit !== void 0 && endIdx - startIdx >= input.limit) break;
|
|
5386
|
+
const cost = Math.min(lines[endIdx].length, MAX_LINE_CHARS);
|
|
5387
|
+
if (chars > 0 && chars + cost > MAX_CHARS) break;
|
|
5388
|
+
chars += cost;
|
|
5389
|
+
endIdx += 1;
|
|
5390
|
+
}
|
|
5391
|
+
return { output: renderLines(lines, total, startIdx, endIdx, path3) };
|
|
5392
|
+
}
|
|
5355
5393
|
async function readText(abs, input, path3) {
|
|
5356
5394
|
let raw;
|
|
5357
5395
|
try {
|
|
@@ -5379,26 +5417,60 @@ async function readText(abs, input, path3) {
|
|
|
5379
5417
|
isError: true
|
|
5380
5418
|
};
|
|
5381
5419
|
}
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5420
|
+
return paginateLines(raw, input, path3);
|
|
5421
|
+
}
|
|
5422
|
+
async function readPdf(abs, input, path3) {
|
|
5423
|
+
let buf;
|
|
5424
|
+
try {
|
|
5425
|
+
buf = await readFile10(abs);
|
|
5426
|
+
} catch (err) {
|
|
5427
|
+
const code = err.code;
|
|
5428
|
+
if (code === "ENOENT") {
|
|
5429
|
+
return {
|
|
5430
|
+
output: `read failed: no such file: ${path3}. It may not exist at this path (or anywhere) \u2014 use glob/grep to locate it rather than guessing another path.`,
|
|
5431
|
+
isError: true
|
|
5432
|
+
};
|
|
5433
|
+
}
|
|
5434
|
+
if (code === "EISDIR") {
|
|
5435
|
+
return {
|
|
5436
|
+
output: `read failed: ${path3} is a directory, not a file. Use glob to list its contents or grep to search inside it.`,
|
|
5437
|
+
isError: true
|
|
5438
|
+
};
|
|
5439
|
+
}
|
|
5440
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5441
|
+
return { output: `read failed: ${msg}`, isError: true };
|
|
5442
|
+
}
|
|
5443
|
+
if (buf.length > MAX_PDF_BYTES) {
|
|
5444
|
+
const mb = (buf.length / 1e6).toFixed(1);
|
|
5445
|
+
const cap = (MAX_PDF_BYTES / 1e6).toFixed(0);
|
|
5387
5446
|
return {
|
|
5388
|
-
output: `read:
|
|
5447
|
+
output: `read failed: ${path3} is ${mb} MB (PDF cap is ${cap} MB). Use bash with a command-line tool (e.g. \`pdftotext\`, \`qpdf\`) to split or extract it.`,
|
|
5389
5448
|
isError: true
|
|
5390
5449
|
};
|
|
5391
5450
|
}
|
|
5392
|
-
let
|
|
5393
|
-
let
|
|
5394
|
-
|
|
5395
|
-
|
|
5396
|
-
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5451
|
+
let totalPages;
|
|
5452
|
+
let pages;
|
|
5453
|
+
try {
|
|
5454
|
+
const extracted = await extractText2(new Uint8Array(buf), { mergePages: false });
|
|
5455
|
+
totalPages = extracted.totalPages;
|
|
5456
|
+
pages = extracted.text;
|
|
5457
|
+
} catch (err) {
|
|
5458
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5459
|
+
return { output: `read failed: cannot parse ${path3} as a PDF: ${msg}`, isError: true };
|
|
5400
5460
|
}
|
|
5401
|
-
|
|
5461
|
+
const meta = `PDF "${basename3(path3)}" \u2014 ${totalPages} page${totalPages === 1 ? "" : "s"}`;
|
|
5462
|
+
if (pages.every((p) => p.trim() === "")) {
|
|
5463
|
+
return {
|
|
5464
|
+
output: `${meta}
|
|
5465
|
+
read: no extractable text \u2014 this PDF is likely scanned or image-only. Use bash with an OCR tool (e.g. \`ocrmypdf\`, \`tesseract\`) to extract its text.`
|
|
5466
|
+
};
|
|
5467
|
+
}
|
|
5468
|
+
const combined = pages.map((p, i) => `[Page ${i + 1}]
|
|
5469
|
+
${p.trim()}`).join("\n\n");
|
|
5470
|
+
const result = paginateLines(combined, input, path3);
|
|
5471
|
+
if (result.isError) return result;
|
|
5472
|
+
return { output: `${meta}
|
|
5473
|
+
${result.output}` };
|
|
5402
5474
|
}
|
|
5403
5475
|
function resolveSheet(sheetNames, spec) {
|
|
5404
5476
|
if (spec === void 0) return sheetNames[0] ?? null;
|
|
@@ -5564,7 +5636,7 @@ async function readImage(abs, ext, path3) {
|
|
|
5564
5636
|
var readTool = {
|
|
5565
5637
|
definition: {
|
|
5566
5638
|
name: "read",
|
|
5567
|
-
description: "Read a text file, spreadsheet, or image from disk. For text files, output is line-numbered (`<line>\\t<text>`, `cat -n` style, 1-based); returns up to `limit` lines (and at most ~200K characters) per call. If more remains, the result tells you the exact read(path, offset) call to continue from. The line-number prefix is display only \u2014 strip it before passing text to `edit`. For Excel files (.xlsx/.xls/.xlsm/.xlsb/.ods), each row is rendered as a TSV line with a metadata header; use the optional `sheet` parameter to select a sheet. For image files (.png/.jpg/.jpeg/.gif/.webp), returns the image as a base64 block alongside metadata \u2014 only when the active model supports image input; capped at 20 MB.",
|
|
5639
|
+
description: "Read a text file, spreadsheet, PDF, or image from disk. For text files, output is line-numbered (`<line>\\t<text>`, `cat -n` style, 1-based); returns up to `limit` lines (and at most ~200K characters) per call. If more remains, the result tells you the exact read(path, offset) call to continue from. The line-number prefix is display only \u2014 strip it before passing text to `edit`. For Excel files (.xlsx/.xls/.xlsm/.xlsb/.ods), each row is rendered as a TSV line with a metadata header; use the optional `sheet` parameter to select a sheet. For PDF files (.pdf), extracted text is returned line-numbered with a `[Page N]` marker before each page and the same offset/limit paging; scanned/image-only PDFs have no extractable text (capped at 30 MB). For image files (.png/.jpg/.jpeg/.gif/.webp), returns the image as a base64 block alongside metadata \u2014 only when the active model supports image input; capped at 20 MB.",
|
|
5568
5640
|
inputSchema: inputSchema8
|
|
5569
5641
|
},
|
|
5570
5642
|
async run(rawInput, ctx) {
|
|
@@ -5583,6 +5655,9 @@ var readTool = {
|
|
|
5583
5655
|
if (EXCEL_EXTENSIONS.has(ext)) {
|
|
5584
5656
|
return readExcel(abs, input, input.path);
|
|
5585
5657
|
}
|
|
5658
|
+
if (ext === ".pdf") {
|
|
5659
|
+
return readPdf(abs, input, input.path);
|
|
5660
|
+
}
|
|
5586
5661
|
return readText(abs, input, input.path);
|
|
5587
5662
|
}
|
|
5588
5663
|
};
|
|
@@ -5649,11 +5724,14 @@ function parseSkillFile(text) {
|
|
|
5649
5724
|
if (typeof descRaw !== "string" || descRaw.trim().length === 0) {
|
|
5650
5725
|
return { error: "missing description" };
|
|
5651
5726
|
}
|
|
5652
|
-
const
|
|
5653
|
-
const
|
|
5654
|
-
const
|
|
5727
|
+
const whenRaw = meta["when_to_use"];
|
|
5728
|
+
const whenToUse = typeof whenRaw === "string" ? whenRaw.trim() : "";
|
|
5729
|
+
const combined = whenToUse ? `${descRaw} ${whenToUse}` : descRaw;
|
|
5730
|
+
const description = combined.length > DESCRIPTION_MAX ? combined.slice(0, DESCRIPTION_MAX) : combined;
|
|
5731
|
+
const disableModelInvocation = parseBool(meta["disable-model-invocation"], false);
|
|
5732
|
+
const userInvocable = parseBool(meta["user-invocable"], true);
|
|
5655
5733
|
const body = normalized.slice(fm[0].length).trimStart();
|
|
5656
|
-
return { ok: { name, description,
|
|
5734
|
+
return { ok: { name, description, disableModelInvocation, userInvocable, body } };
|
|
5657
5735
|
}
|
|
5658
5736
|
function parseFrontMatter2(src) {
|
|
5659
5737
|
const out = {};
|
|
@@ -5698,6 +5776,13 @@ function parseScalar2(v) {
|
|
|
5698
5776
|
}
|
|
5699
5777
|
return v;
|
|
5700
5778
|
}
|
|
5779
|
+
function parseBool(v, dflt) {
|
|
5780
|
+
if (typeof v !== "string") return dflt;
|
|
5781
|
+
const s = v.trim().toLowerCase();
|
|
5782
|
+
if (s === "true") return true;
|
|
5783
|
+
if (s === "false") return false;
|
|
5784
|
+
return dflt;
|
|
5785
|
+
}
|
|
5701
5786
|
function scan(r, logger) {
|
|
5702
5787
|
const targets = [];
|
|
5703
5788
|
for (const d of r.projectDirs) targets.push({ kind: "project", root: resolve10(r.cwd, d) });
|
|
@@ -5734,7 +5819,8 @@ function scan(r, logger) {
|
|
|
5734
5819
|
list.push({
|
|
5735
5820
|
name: parsed.ok.name,
|
|
5736
5821
|
description: parsed.ok.description,
|
|
5737
|
-
|
|
5822
|
+
disableModelInvocation: parsed.ok.disableModelInvocation,
|
|
5823
|
+
userInvocable: parsed.ok.userInvocable,
|
|
5738
5824
|
location: dir
|
|
5739
5825
|
});
|
|
5740
5826
|
seen.add(parsed.ok.name);
|
|
@@ -8226,7 +8312,7 @@ Working directory: ${workspace}
|
|
|
8226
8312
|
- Use tools to complete the task yourself. Work autonomously; do not ask the parent for clarification unless you are truly blocked.
|
|
8227
8313
|
- You run in isolation. The parent sees ONLY your final message \u2014 it cannot see your intermediate steps or tool output. End by reporting results concisely: what you did, key findings, and concrete file paths / follow-ups.
|
|
8228
8314
|
- Stay within the assigned task. Do not spawn further sub-agents.
|
|
8229
|
-
- Don't guess file paths. When unsure whether a file
|
|
8315
|
+
- Don't guess file paths. When unsure whether a file or directory exists, locate it with glob/grep/ls before acting \u2014 read, write, edit, or mkdir.
|
|
8230
8316
|
- Write your final report in the language of the task you were given, matching its exact script and regional variant (e.g. Simplified vs Traditional Chinese \u2014 don't switch a Simplified-Chinese task to Traditional), not the language of these instructions.
|
|
8231
8317
|
${extra}
|
|
8232
8318
|
Act, don't explain.
|
|
@@ -9833,7 +9919,16 @@ async function writeStamp(dir) {
|
|
|
9833
9919
|
async function git(cwd, args, logger) {
|
|
9834
9920
|
logger?.debug({ args }, "nova-code-guide: git");
|
|
9835
9921
|
try {
|
|
9836
|
-
|
|
9922
|
+
const p = execFileP2("git", [...args], { cwd });
|
|
9923
|
+
const child = p.child;
|
|
9924
|
+
if (child) {
|
|
9925
|
+
const unref = (s) => s?.unref?.();
|
|
9926
|
+
child.unref();
|
|
9927
|
+
unref(child.stdin);
|
|
9928
|
+
unref(child.stdout);
|
|
9929
|
+
unref(child.stderr);
|
|
9930
|
+
}
|
|
9931
|
+
await p;
|
|
9837
9932
|
} catch (err) {
|
|
9838
9933
|
if (isEnoent(err)) {
|
|
9839
9934
|
throw new GuideProvisionError(
|
|
@@ -10732,6 +10827,7 @@ function loadSkillCommandsInto(registry, opts) {
|
|
|
10732
10827
|
const taken = new Set(registry.list().map((c) => c.name));
|
|
10733
10828
|
let added = 0;
|
|
10734
10829
|
for (const item of items) {
|
|
10830
|
+
if (!item.userInvocable) continue;
|
|
10735
10831
|
const cmd = {
|
|
10736
10832
|
name: item.name,
|
|
10737
10833
|
description: item.description,
|
|
@@ -10965,7 +11061,7 @@ import { render } from "ink";
|
|
|
10965
11061
|
|
|
10966
11062
|
// src/ui/app.tsx
|
|
10967
11063
|
import React12 from "react";
|
|
10968
|
-
import { Box as
|
|
11064
|
+
import { Box as Box15, Text as Text15 } from "ink";
|
|
10969
11065
|
import { useShallow as useShallow3 } from "zustand/react/shallow";
|
|
10970
11066
|
|
|
10971
11067
|
// src/ui/input-box.tsx
|
|
@@ -11834,20 +11930,24 @@ import { Box as Box4, Text as Text4 } from "ink";
|
|
|
11834
11930
|
|
|
11835
11931
|
// src/ui/logo.ts
|
|
11836
11932
|
var LOGO = [
|
|
11837
|
-
"\
|
|
11838
|
-
"\u2588\u2588\u2588 \u2588\u2588
|
|
11839
|
-
"
|
|
11840
|
-
"\u2588\u2588
|
|
11841
|
-
"\
|
|
11933
|
+
" \xB7 \u22C6 \u2726 \u22C6 \xB7 ",
|
|
11934
|
+
" \u22C6 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u22C6 ",
|
|
11935
|
+
" \u2727 \xB7 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \xB7 \u2727 ",
|
|
11936
|
+
"\u2726 \u207A \u2588\u2588 \u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u207A \u2726",
|
|
11937
|
+
" \xB7 \u2727 \u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2727 \xB7 ",
|
|
11938
|
+
" \u22C6 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u22C6 ",
|
|
11939
|
+
" \u207A \xB7 \u22C6 \xB7 \u2726 \u207A "
|
|
11842
11940
|
];
|
|
11843
11941
|
var LOGO_GRADIENT = [
|
|
11942
|
+
[140, 246, 255],
|
|
11844
11943
|
[0, 238, 255],
|
|
11845
11944
|
[90, 160, 255],
|
|
11846
11945
|
[170, 110, 245],
|
|
11847
11946
|
[230, 80, 210],
|
|
11848
|
-
[255, 60, 170]
|
|
11947
|
+
[255, 60, 170],
|
|
11948
|
+
[255, 140, 215]
|
|
11849
11949
|
];
|
|
11850
|
-
var LOGO_FALLBACK = [accent, blue, magenta, magenta, magenta];
|
|
11950
|
+
var LOGO_FALLBACK = [accent, accent, blue, magenta, magenta, magenta, magenta];
|
|
11851
11951
|
function bannerLine(line, row) {
|
|
11852
11952
|
if (useTruecolor) {
|
|
11853
11953
|
const stop = LOGO_GRADIENT[row];
|
|
@@ -11951,10 +12051,28 @@ function SetupView({ state }) {
|
|
|
11951
12051
|
] });
|
|
11952
12052
|
}
|
|
11953
12053
|
|
|
12054
|
+
// src/ui/trust-view.tsx
|
|
12055
|
+
import { Box as Box5, Text as Text5 } from "ink";
|
|
12056
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
12057
|
+
function TrustView({ state }) {
|
|
12058
|
+
return /* @__PURE__ */ jsxs4(Box5, { flexDirection: "column", paddingLeft: 1, paddingRight: 1, children: [
|
|
12059
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsxs4(Text5, { children: [
|
|
12060
|
+
/* @__PURE__ */ jsx5(Text5, { color: ACCENT_HEX, children: ">_" }),
|
|
12061
|
+
" Nova Code",
|
|
12062
|
+
" ",
|
|
12063
|
+
/* @__PURE__ */ jsx5(Text5, { dimColor: true, children: `(v${state.version})` })
|
|
12064
|
+
] }) }),
|
|
12065
|
+
/* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginTop: 1, children: LOGO.map((line, i) => /* @__PURE__ */ jsx5(Text5, { color: LOGO_ROW_HEX[i] ?? ACCENT_HEX, children: line }, i)) }),
|
|
12066
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { bold: true, color: ACCENT_HEX, children: "Do you trust the files in this folder?" }) }),
|
|
12067
|
+
/* @__PURE__ */ jsx5(Text5, { children: state.workspace }),
|
|
12068
|
+
/* @__PURE__ */ jsx5(Box5, { flexDirection: "column", marginTop: 1, children: state.lines.map((line, i) => /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: line }, i)) })
|
|
12069
|
+
] });
|
|
12070
|
+
}
|
|
12071
|
+
|
|
11954
12072
|
// src/ui/status-line.tsx
|
|
11955
12073
|
import React3 from "react";
|
|
11956
|
-
import { Box as
|
|
11957
|
-
import { basename as
|
|
12074
|
+
import { Box as Box6, Text as Text6 } from "ink";
|
|
12075
|
+
import { basename as basename4 } from "path";
|
|
11958
12076
|
import { useShallow } from "zustand/react/shallow";
|
|
11959
12077
|
|
|
11960
12078
|
// src/ui/status-format.ts
|
|
@@ -12032,17 +12150,17 @@ function fitSegments(segments, maxWidth, sep3 = " | ") {
|
|
|
12032
12150
|
}
|
|
12033
12151
|
|
|
12034
12152
|
// src/ui/status-line.tsx
|
|
12035
|
-
import { jsx as
|
|
12153
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
12036
12154
|
function SegmentRow({
|
|
12037
12155
|
segments,
|
|
12038
12156
|
termCols
|
|
12039
12157
|
}) {
|
|
12040
12158
|
const shown = fitSegments(segments, Math.max(0, termCols - 2));
|
|
12041
|
-
return /* @__PURE__ */
|
|
12042
|
-
/* @__PURE__ */
|
|
12043
|
-
shown.map((seg, i) => /* @__PURE__ */
|
|
12044
|
-
i > 0 ? /* @__PURE__ */
|
|
12045
|
-
/* @__PURE__ */
|
|
12159
|
+
return /* @__PURE__ */ jsxs5(Box6, { children: [
|
|
12160
|
+
/* @__PURE__ */ jsx6(Text6, { children: " " }),
|
|
12161
|
+
shown.map((seg, i) => /* @__PURE__ */ jsxs5(React3.Fragment, { children: [
|
|
12162
|
+
i > 0 ? /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: " | " }) : null,
|
|
12163
|
+
/* @__PURE__ */ jsxs5(Text6, { color: seg.color, children: [
|
|
12046
12164
|
seg.icon,
|
|
12047
12165
|
" ",
|
|
12048
12166
|
seg.text
|
|
@@ -12083,15 +12201,15 @@ function StatusLine({ store, shellMode = false }) {
|
|
|
12083
12201
|
}))
|
|
12084
12202
|
);
|
|
12085
12203
|
if (shellMode) {
|
|
12086
|
-
return /* @__PURE__ */
|
|
12087
|
-
/* @__PURE__ */
|
|
12088
|
-
/* @__PURE__ */
|
|
12204
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
12205
|
+
/* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { color: SHELL_MODE_INDICATOR.color, children: ` ${SHELL_MODE_INDICATOR.label}` }) }),
|
|
12206
|
+
/* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { children: " " }) })
|
|
12089
12207
|
] });
|
|
12090
12208
|
}
|
|
12091
12209
|
if (copyNotice) {
|
|
12092
|
-
return /* @__PURE__ */
|
|
12093
|
-
/* @__PURE__ */
|
|
12094
|
-
/* @__PURE__ */
|
|
12210
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
12211
|
+
/* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { color: copyNoticeTone === "warn" ? "red" : "green", children: ` ${copyNotice}` }) }),
|
|
12212
|
+
/* @__PURE__ */ jsx6(Box6, { children: /* @__PURE__ */ jsx6(Text6, { children: " " }) })
|
|
12095
12213
|
] });
|
|
12096
12214
|
}
|
|
12097
12215
|
const main = [];
|
|
@@ -12106,7 +12224,7 @@ function StatusLine({ store, shellMode = false }) {
|
|
|
12106
12224
|
main.push({ icon: "\u25CB", text: `${contextBar(pct)} ${pct}%`, color: "yellow" });
|
|
12107
12225
|
}
|
|
12108
12226
|
if (banner?.cwd) {
|
|
12109
|
-
main.push({ icon: "\u25C8", text:
|
|
12227
|
+
main.push({ icon: "\u25C8", text: basename4(banner.cwd) || banner.cwd, color: "green" });
|
|
12110
12228
|
}
|
|
12111
12229
|
if (gitBranch) {
|
|
12112
12230
|
main.push({ icon: "\u2387", text: gitBranch, color: "blue" });
|
|
@@ -12152,15 +12270,15 @@ function StatusLine({ store, shellMode = false }) {
|
|
|
12152
12270
|
color: "#d97706"
|
|
12153
12271
|
});
|
|
12154
12272
|
}
|
|
12155
|
-
return /* @__PURE__ */
|
|
12156
|
-
/* @__PURE__ */
|
|
12157
|
-
/* @__PURE__ */
|
|
12273
|
+
return /* @__PURE__ */ jsxs5(Box6, { flexDirection: "column", children: [
|
|
12274
|
+
/* @__PURE__ */ jsx6(SegmentRow, { segments: main, termCols }),
|
|
12275
|
+
/* @__PURE__ */ jsx6(SegmentRow, { segments: usage, termCols })
|
|
12158
12276
|
] });
|
|
12159
12277
|
}
|
|
12160
12278
|
|
|
12161
12279
|
// src/ui/picker.tsx
|
|
12162
12280
|
import { useState as useState2 } from "react";
|
|
12163
|
-
import { Box as
|
|
12281
|
+
import { Box as Box7, Text as Text7, useInput as useInput2, useStdout as useStdout2 } from "ink";
|
|
12164
12282
|
|
|
12165
12283
|
// src/ui/selection.ts
|
|
12166
12284
|
function sliceVisualCols(line, startCol, endCol) {
|
|
@@ -12256,7 +12374,7 @@ function highlightLines(lines, rect) {
|
|
|
12256
12374
|
}
|
|
12257
12375
|
|
|
12258
12376
|
// src/ui/picker.tsx
|
|
12259
|
-
import { jsx as
|
|
12377
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
12260
12378
|
function highlightRow(text, width) {
|
|
12261
12379
|
const tw = visibleWidth(text);
|
|
12262
12380
|
const padded = tw < width ? text + " ".repeat(width - tw) : text;
|
|
@@ -12359,12 +12477,12 @@ function PickList({ opts, onResolve, panelWidth }) {
|
|
|
12359
12477
|
const text = rendered[i - windowStart];
|
|
12360
12478
|
const body = i === selected && useColor ? highlightRow(text, barWidth) : text;
|
|
12361
12479
|
rows.push(
|
|
12362
|
-
/* @__PURE__ */
|
|
12480
|
+
/* @__PURE__ */ jsx7(Text7, { ...fullWidth ? { wrap: "truncate-end" } : {}, children: body }, i)
|
|
12363
12481
|
);
|
|
12364
12482
|
}
|
|
12365
12483
|
const borderProps = overlayBorderProps(bordered, opts.topRuleColor);
|
|
12366
|
-
return /* @__PURE__ */
|
|
12367
|
-
|
|
12484
|
+
return /* @__PURE__ */ jsxs6(
|
|
12485
|
+
Box7,
|
|
12368
12486
|
{
|
|
12369
12487
|
flexDirection: "column",
|
|
12370
12488
|
marginTop: 1,
|
|
@@ -12372,10 +12490,10 @@ function PickList({ opts, onResolve, panelWidth }) {
|
|
|
12372
12490
|
...fullWidth ? { width: cols } : {},
|
|
12373
12491
|
...borderProps,
|
|
12374
12492
|
children: [
|
|
12375
|
-
opts.header ? /* @__PURE__ */
|
|
12493
|
+
opts.header ? /* @__PURE__ */ jsx7(Text7, { children: opts.header }) : null,
|
|
12376
12494
|
rows,
|
|
12377
|
-
indicator ? /* @__PURE__ */
|
|
12378
|
-
opts.footer ? /* @__PURE__ */
|
|
12495
|
+
indicator ? /* @__PURE__ */ jsx7(Text7, { children: indicator }) : null,
|
|
12496
|
+
opts.footer ? /* @__PURE__ */ jsx7(Text7, { children: opts.footer }) : null
|
|
12379
12497
|
]
|
|
12380
12498
|
}
|
|
12381
12499
|
);
|
|
@@ -12431,13 +12549,13 @@ function ScrollViewer({ opts, onResolve, panelWidth }) {
|
|
|
12431
12549
|
for (let i = 0; i < visible.length; i++) {
|
|
12432
12550
|
const line = visible[i];
|
|
12433
12551
|
const body = line.bg && useColor ? tintRow(line.text, barWidth, line.bg) : line.text;
|
|
12434
|
-
rows.push(/* @__PURE__ */
|
|
12552
|
+
rows.push(/* @__PURE__ */ jsx7(Text7, { children: (line.gutter ?? "") + body }, start + i));
|
|
12435
12553
|
}
|
|
12436
12554
|
const indicator = lines.length > pageSize ? useColor ? dim(` (${start + 1}\u2013${end}/${lines.length})`) : ` (${start + 1}\u2013${end}/${lines.length})` : null;
|
|
12437
12555
|
const fullWidth = !bordered && !!opts.topRuleColor;
|
|
12438
12556
|
const borderProps = overlayBorderProps(bordered, opts.topRuleColor);
|
|
12439
|
-
return /* @__PURE__ */
|
|
12440
|
-
|
|
12557
|
+
return /* @__PURE__ */ jsxs6(
|
|
12558
|
+
Box7,
|
|
12441
12559
|
{
|
|
12442
12560
|
flexDirection: "column",
|
|
12443
12561
|
marginTop: 1,
|
|
@@ -12445,10 +12563,10 @@ function ScrollViewer({ opts, onResolve, panelWidth }) {
|
|
|
12445
12563
|
...fullWidth ? { width: cols } : {},
|
|
12446
12564
|
...borderProps,
|
|
12447
12565
|
children: [
|
|
12448
|
-
opts.header ? /* @__PURE__ */
|
|
12566
|
+
opts.header ? /* @__PURE__ */ jsx7(Text7, { children: opts.header }) : null,
|
|
12449
12567
|
rows,
|
|
12450
|
-
indicator ? /* @__PURE__ */
|
|
12451
|
-
opts.footer ? /* @__PURE__ */
|
|
12568
|
+
indicator ? /* @__PURE__ */ jsx7(Text7, { children: indicator }) : null,
|
|
12569
|
+
opts.footer ? /* @__PURE__ */ jsx7(Text7, { children: opts.footer }) : null
|
|
12452
12570
|
]
|
|
12453
12571
|
}
|
|
12454
12572
|
);
|
|
@@ -12496,11 +12614,11 @@ function PickHorizontal({ opts, onResolve, panelWidth }) {
|
|
|
12496
12614
|
items.forEach((item, i) => {
|
|
12497
12615
|
const badge = opts.badge?.(item) ?? null;
|
|
12498
12616
|
const label = ` ${opts.label(item)} `;
|
|
12499
|
-
if (i > 0) cells.push(/* @__PURE__ */
|
|
12617
|
+
if (i > 0) cells.push(/* @__PURE__ */ jsx7(Text7, { children: separator }, `sep-${i}`));
|
|
12500
12618
|
cells.push(
|
|
12501
|
-
/* @__PURE__ */
|
|
12502
|
-
/* @__PURE__ */
|
|
12503
|
-
badge ? /* @__PURE__ */
|
|
12619
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
12620
|
+
/* @__PURE__ */ jsx7(Text7, { inverse: i === selected, dimColor: i !== selected, children: label }),
|
|
12621
|
+
badge ? /* @__PURE__ */ jsx7(Text7, { color: ACCENT_HEX, bold: true, children: ` ${badge} ` }) : null
|
|
12504
12622
|
] }, i)
|
|
12505
12623
|
);
|
|
12506
12624
|
});
|
|
@@ -12508,8 +12626,8 @@ function PickHorizontal({ opts, onResolve, panelWidth }) {
|
|
|
12508
12626
|
const fullWidth = !bordered && !!opts.topRuleColor;
|
|
12509
12627
|
const cols = panelWidth ?? stdout?.columns ?? 80;
|
|
12510
12628
|
const borderProps = overlayBorderProps(bordered, opts.topRuleColor);
|
|
12511
|
-
return /* @__PURE__ */
|
|
12512
|
-
|
|
12629
|
+
return /* @__PURE__ */ jsxs6(
|
|
12630
|
+
Box7,
|
|
12513
12631
|
{
|
|
12514
12632
|
flexDirection: "column",
|
|
12515
12633
|
marginTop: 1,
|
|
@@ -12518,11 +12636,11 @@ function PickHorizontal({ opts, onResolve, panelWidth }) {
|
|
|
12518
12636
|
...fullWidth ? { width: cols } : {},
|
|
12519
12637
|
...borderProps,
|
|
12520
12638
|
children: [
|
|
12521
|
-
opts.header ? /* @__PURE__ */
|
|
12522
|
-
/* @__PURE__ */
|
|
12523
|
-
/* @__PURE__ */
|
|
12524
|
-
/* @__PURE__ */
|
|
12525
|
-
opts.footer ? /* @__PURE__ */
|
|
12639
|
+
opts.header ? /* @__PURE__ */ jsx7(Text7, { children: opts.header }) : null,
|
|
12640
|
+
/* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
12641
|
+
/* @__PURE__ */ jsx7(Box7, { children: cells }),
|
|
12642
|
+
/* @__PURE__ */ jsx7(Text7, { children: " " }),
|
|
12643
|
+
opts.footer ? /* @__PURE__ */ jsx7(Text7, { children: opts.footer }) : null
|
|
12526
12644
|
]
|
|
12527
12645
|
}
|
|
12528
12646
|
);
|
|
@@ -12530,12 +12648,12 @@ function PickHorizontal({ opts, onResolve, panelWidth }) {
|
|
|
12530
12648
|
|
|
12531
12649
|
// src/ui/viewport.tsx
|
|
12532
12650
|
import React11 from "react";
|
|
12533
|
-
import { Box as
|
|
12651
|
+
import { Box as Box14, Text as Text14 } from "ink";
|
|
12534
12652
|
import { useShallow as useShallow2 } from "zustand/react/shallow";
|
|
12535
12653
|
|
|
12536
12654
|
// src/ui/approval.tsx
|
|
12537
12655
|
import { useState as useState3 } from "react";
|
|
12538
|
-
import { Box as
|
|
12656
|
+
import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
|
|
12539
12657
|
|
|
12540
12658
|
// src/ui/measure.ts
|
|
12541
12659
|
import wrapAnsi2 from "wrap-ansi";
|
|
@@ -13092,7 +13210,7 @@ function wrapThinkingBody(text, width) {
|
|
|
13092
13210
|
return wrapAnsi(trimmed, bodyWidth, { hard: true, wordWrap: false, trim: false }).split("\n");
|
|
13093
13211
|
}
|
|
13094
13212
|
function renderThinking(text, label, width, collapsed = false, expanded = false) {
|
|
13095
|
-
const head = `${magenta("\
|
|
13213
|
+
const head = `${magenta("\u2726")} ${dim(`thinking${label ? ` \xB7 ${label}` : ""}`)}`;
|
|
13096
13214
|
const lines = wrapThinkingBody(text, width);
|
|
13097
13215
|
if (lines.length === 0) return head;
|
|
13098
13216
|
const overflow = collapsed ? Math.max(0, lines.length - THINKING_COLLAPSED_MAX_LINES) : 0;
|
|
@@ -13115,7 +13233,7 @@ function thinkingToggleLineIndex(item, width) {
|
|
|
13115
13233
|
return 1 + shown;
|
|
13116
13234
|
}
|
|
13117
13235
|
function renderRedactedThinking(label) {
|
|
13118
|
-
return `${magenta("\
|
|
13236
|
+
return `${magenta("\u2726")} ${dim(`thinking${label ? ` \xB7 ${label}` : ""} (redacted)`)}`;
|
|
13119
13237
|
}
|
|
13120
13238
|
function renderCard(card) {
|
|
13121
13239
|
const color = cardColor[card.kind];
|
|
@@ -13387,7 +13505,7 @@ function genericUseHeader(use) {
|
|
|
13387
13505
|
return header(use.name, dim(trim(compact)));
|
|
13388
13506
|
}
|
|
13389
13507
|
var DETAIL_MARK = {
|
|
13390
|
-
thinking: "\
|
|
13508
|
+
thinking: "\u2726",
|
|
13391
13509
|
tool_use: "\u2692",
|
|
13392
13510
|
final: "\u2192"
|
|
13393
13511
|
};
|
|
@@ -13586,7 +13704,7 @@ function sliceLines(items, width, offset, viewportRows) {
|
|
|
13586
13704
|
}
|
|
13587
13705
|
|
|
13588
13706
|
// src/ui/approval.tsx
|
|
13589
|
-
import { Fragment as Fragment2, jsx as
|
|
13707
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
13590
13708
|
var TOOL_PROMPTS = {
|
|
13591
13709
|
read: "Allow reading this file?",
|
|
13592
13710
|
write: "Allow writing this file?",
|
|
@@ -13703,8 +13821,8 @@ function ApprovalPrompt({
|
|
|
13703
13821
|
});
|
|
13704
13822
|
const inner = approvalInnerWidth(width);
|
|
13705
13823
|
const { text: detail, truncated } = clampDetail(describeToolInput(input.input));
|
|
13706
|
-
return /* @__PURE__ */
|
|
13707
|
-
|
|
13824
|
+
return /* @__PURE__ */ jsxs7(
|
|
13825
|
+
Box8,
|
|
13708
13826
|
{
|
|
13709
13827
|
flexDirection: "column",
|
|
13710
13828
|
marginTop: 1,
|
|
@@ -13713,31 +13831,31 @@ function ApprovalPrompt({
|
|
|
13713
13831
|
borderStyle: "round",
|
|
13714
13832
|
borderColor: "gray",
|
|
13715
13833
|
children: [
|
|
13716
|
-
/* @__PURE__ */
|
|
13717
|
-
/* @__PURE__ */
|
|
13834
|
+
/* @__PURE__ */ jsx8(Text8, { children: promptFor(input.tool) }),
|
|
13835
|
+
/* @__PURE__ */ jsx8(Text8, { children: " " }),
|
|
13718
13836
|
input.tool === "bash" ? (
|
|
13719
13837
|
// Mirror the message-stream bash rendering: `● bash` header with the
|
|
13720
13838
|
// command under a `⎿` gutter, so heredocs/long one-liners preview the
|
|
13721
13839
|
// way they'll print in the transcript instead of as a flat line.
|
|
13722
|
-
/* @__PURE__ */
|
|
13723
|
-
/* @__PURE__ */
|
|
13724
|
-
/* @__PURE__ */
|
|
13725
|
-
truncated ? /* @__PURE__ */
|
|
13840
|
+
/* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
13841
|
+
/* @__PURE__ */ jsx8(Text8, { children: BASH_HEADER }),
|
|
13842
|
+
/* @__PURE__ */ jsx8(Text8, { children: renderCommandBody(detail, inner) }),
|
|
13843
|
+
truncated ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: `${BASH_BODY_INDENT}\u2026 (truncated)` }) : null
|
|
13726
13844
|
] })
|
|
13727
|
-
) : /* @__PURE__ */
|
|
13728
|
-
/* @__PURE__ */
|
|
13845
|
+
) : /* @__PURE__ */ jsxs7(Text8, { children: [
|
|
13846
|
+
/* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
13729
13847
|
input.tool,
|
|
13730
13848
|
" "
|
|
13731
13849
|
] }),
|
|
13732
|
-
/* @__PURE__ */
|
|
13733
|
-
truncated ? /* @__PURE__ */
|
|
13850
|
+
/* @__PURE__ */ jsx8(Text8, { color: ACCENT_HEX, children: detail }),
|
|
13851
|
+
truncated ? /* @__PURE__ */ jsx8(Text8, { dimColor: true, children: " \u2026 (truncated)" }) : null
|
|
13734
13852
|
] }),
|
|
13735
|
-
/* @__PURE__ */
|
|
13853
|
+
/* @__PURE__ */ jsx8(Box8, { flexDirection: "column", marginTop: 1, children: OPTIONS.map((opt, i) => {
|
|
13736
13854
|
const active = i === cursor;
|
|
13737
|
-
return /* @__PURE__ */
|
|
13855
|
+
return /* @__PURE__ */ jsxs7(Text8, { color: active ? opt.color : void 0, children: [
|
|
13738
13856
|
active ? "\u276F " : " ",
|
|
13739
|
-
/* @__PURE__ */
|
|
13740
|
-
/* @__PURE__ */
|
|
13857
|
+
/* @__PURE__ */ jsx8(Text8, { children: opt.label }),
|
|
13858
|
+
/* @__PURE__ */ jsxs7(Text8, { dimColor: true, children: [
|
|
13741
13859
|
" (",
|
|
13742
13860
|
opt.hint,
|
|
13743
13861
|
")"
|
|
@@ -13751,8 +13869,8 @@ function ApprovalPrompt({
|
|
|
13751
13869
|
|
|
13752
13870
|
// src/ui/ask-user.tsx
|
|
13753
13871
|
import { useState as useState4 } from "react";
|
|
13754
|
-
import { Box as
|
|
13755
|
-
import { Fragment as Fragment3, jsx as
|
|
13872
|
+
import { Box as Box9, Text as Text9, useInput as useInput4 } from "ink";
|
|
13873
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
13756
13874
|
var OTHER_LABEL = "Other";
|
|
13757
13875
|
var CONFIRM_HEADER = "Confirm";
|
|
13758
13876
|
var CONFIRM_SUBMIT = 0;
|
|
@@ -14023,25 +14141,25 @@ function AskPanel({ req, onResolve }) {
|
|
|
14023
14141
|
});
|
|
14024
14142
|
const labelWidth = q ? Math.max(...q.options.map((o) => visibleWidth(o.label))) : 0;
|
|
14025
14143
|
const everyAnswered = allAnswered(states);
|
|
14026
|
-
return /* @__PURE__ */
|
|
14027
|
-
/* @__PURE__ */
|
|
14028
|
-
/* @__PURE__ */
|
|
14144
|
+
return /* @__PURE__ */ jsxs8(Box9, { flexDirection: "column", padding: 1, marginTop: 1, marginBottom: 1, borderStyle: "round", children: [
|
|
14145
|
+
/* @__PURE__ */ jsxs8(Text9, { children: [
|
|
14146
|
+
/* @__PURE__ */ jsx9(Text9, { bold: true, color: ACCENT_HEX, children: "?" }),
|
|
14029
14147
|
" ",
|
|
14030
14148
|
isConfirm ? "Review your answers and submit." : q?.spec.question
|
|
14031
14149
|
] }),
|
|
14032
|
-
/* @__PURE__ */
|
|
14150
|
+
/* @__PURE__ */ jsxs8(Box9, { children: [
|
|
14033
14151
|
states.map((s, i) => {
|
|
14034
14152
|
const status = isAnswered(s) ? "\u2713" : i === tab ? "\u25CF" : "\u25CB";
|
|
14035
14153
|
const text = ` ${status} ${s.spec.header} `;
|
|
14036
|
-
return /* @__PURE__ */
|
|
14154
|
+
return /* @__PURE__ */ jsxs8(Text9, { color: i === tab ? ACCENT_HEX : void 0, dimColor: i !== tab, children: [
|
|
14037
14155
|
i > 0 ? " " : "",
|
|
14038
14156
|
"[",
|
|
14039
14157
|
text,
|
|
14040
14158
|
"]"
|
|
14041
14159
|
] }, i);
|
|
14042
14160
|
}),
|
|
14043
|
-
/* @__PURE__ */
|
|
14044
|
-
|
|
14161
|
+
/* @__PURE__ */ jsxs8(
|
|
14162
|
+
Text9,
|
|
14045
14163
|
{
|
|
14046
14164
|
color: isConfirm ? ACCENT_HEX : everyAnswered ? "green" : void 0,
|
|
14047
14165
|
dimColor: !isConfirm,
|
|
@@ -14056,34 +14174,34 @@ function AskPanel({ req, onResolve }) {
|
|
|
14056
14174
|
}
|
|
14057
14175
|
)
|
|
14058
14176
|
] }),
|
|
14059
|
-
/* @__PURE__ */
|
|
14060
|
-
isConfirm ? /* @__PURE__ */
|
|
14177
|
+
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
14178
|
+
isConfirm ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
14061
14179
|
states.map((s, i) => {
|
|
14062
14180
|
const labels = answerLabels(s);
|
|
14063
14181
|
const val = labels.length > 0 ? labels.join(", ") : "(no answer)";
|
|
14064
|
-
return /* @__PURE__ */
|
|
14182
|
+
return /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
14065
14183
|
" ",
|
|
14066
|
-
/* @__PURE__ */
|
|
14184
|
+
/* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
|
|
14067
14185
|
s.spec.header,
|
|
14068
14186
|
":"
|
|
14069
14187
|
] }),
|
|
14070
14188
|
" ",
|
|
14071
|
-
/* @__PURE__ */
|
|
14189
|
+
/* @__PURE__ */ jsx9(Text9, { color: labels.length > 0 ? void 0 : "yellow", children: val })
|
|
14072
14190
|
] }, i);
|
|
14073
14191
|
}),
|
|
14074
|
-
/* @__PURE__ */
|
|
14192
|
+
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
14075
14193
|
[
|
|
14076
14194
|
{ idx: CONFIRM_SUBMIT, label: "Submit", color: "green" },
|
|
14077
14195
|
{ idx: CONFIRM_CANCEL, label: "Cancel", color: "red" }
|
|
14078
14196
|
].map((b) => {
|
|
14079
14197
|
const isCur = confirmIndex === b.idx;
|
|
14080
14198
|
const disabled = b.idx === CONFIRM_SUBMIT && !everyAnswered;
|
|
14081
|
-
return /* @__PURE__ */
|
|
14199
|
+
return /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
14082
14200
|
" ",
|
|
14083
|
-
/* @__PURE__ */
|
|
14201
|
+
/* @__PURE__ */ jsx9(Text9, { color: isCur ? ACCENT_HEX : void 0, children: isCur ? "\u276F" : " " }),
|
|
14084
14202
|
" ",
|
|
14085
|
-
/* @__PURE__ */
|
|
14086
|
-
disabled ? /* @__PURE__ */
|
|
14203
|
+
/* @__PURE__ */ jsx9(Text9, { color: isCur ? b.color : void 0, dimColor: disabled && !isCur, children: b.label }),
|
|
14204
|
+
disabled ? /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: " (answer all questions first)" }) : null
|
|
14087
14205
|
] }, b.idx);
|
|
14088
14206
|
})
|
|
14089
14207
|
] }) : q?.options.map((o, i) => {
|
|
@@ -14092,34 +14210,34 @@ function AskPanel({ req, onResolve }) {
|
|
|
14092
14210
|
const marker2 = q.spec.multiSelect ? isSelected ? "[x]" : "[ ]" : isSelected ? "\u25CF" : "\u25CB";
|
|
14093
14211
|
const cur = isCur ? "\u276F" : " ";
|
|
14094
14212
|
const pad = " ".repeat(Math.max(0, labelWidth - visibleWidth(o.label)));
|
|
14095
|
-
return /* @__PURE__ */
|
|
14213
|
+
return /* @__PURE__ */ jsxs8(Text9, { children: [
|
|
14096
14214
|
" ",
|
|
14097
|
-
/* @__PURE__ */
|
|
14215
|
+
/* @__PURE__ */ jsx9(Text9, { color: isCur ? ACCENT_HEX : void 0, children: cur }),
|
|
14098
14216
|
" ",
|
|
14099
14217
|
marker2,
|
|
14100
14218
|
" ",
|
|
14101
|
-
/* @__PURE__ */
|
|
14219
|
+
/* @__PURE__ */ jsx9(Text9, { color: isCur ? ACCENT_HEX : void 0, children: o.label }),
|
|
14102
14220
|
pad,
|
|
14103
|
-
o.description ? /* @__PURE__ */
|
|
14221
|
+
o.description ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
14104
14222
|
" ",
|
|
14105
|
-
/* @__PURE__ */
|
|
14223
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: o.description })
|
|
14106
14224
|
] }) : null
|
|
14107
14225
|
] }, i);
|
|
14108
14226
|
}),
|
|
14109
|
-
phase === "freeform" ? /* @__PURE__ */
|
|
14110
|
-
/* @__PURE__ */
|
|
14111
|
-
/* @__PURE__ */
|
|
14112
|
-
/* @__PURE__ */
|
|
14113
|
-
/* @__PURE__ */
|
|
14114
|
-
/* @__PURE__ */
|
|
14115
|
-
freeformBuffer.length === 0 ? /* @__PURE__ */
|
|
14227
|
+
phase === "freeform" ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
14228
|
+
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
14229
|
+
/* @__PURE__ */ jsxs8(Box9, { children: [
|
|
14230
|
+
/* @__PURE__ */ jsx9(Text9, { color: ACCENT_HEX, children: " \u203A " }),
|
|
14231
|
+
/* @__PURE__ */ jsx9(Text9, { children: freeformBuffer }),
|
|
14232
|
+
/* @__PURE__ */ jsx9(Text9, { inverse: true, children: " " }),
|
|
14233
|
+
freeformBuffer.length === 0 ? /* @__PURE__ */ jsxs8(Text9, { dimColor: true, children: [
|
|
14116
14234
|
" ",
|
|
14117
14235
|
"type your custom answer, Enter to confirm, Esc to cancel"
|
|
14118
14236
|
] }) : null
|
|
14119
14237
|
] })
|
|
14120
14238
|
] }) : null,
|
|
14121
|
-
/* @__PURE__ */
|
|
14122
|
-
/* @__PURE__ */
|
|
14239
|
+
/* @__PURE__ */ jsx9(Text9, { children: " " }),
|
|
14240
|
+
/* @__PURE__ */ jsx9(Text9, { dimColor: true, children: [
|
|
14123
14241
|
"\u2190/\u2192 tab",
|
|
14124
14242
|
isConfirm ? "\u2191/\u2193 button" : "\u2191/\u2193 option",
|
|
14125
14243
|
!isConfirm && q?.spec.multiSelect ? "space toggle" : "",
|
|
@@ -14131,8 +14249,8 @@ function AskPanel({ req, onResolve }) {
|
|
|
14131
14249
|
|
|
14132
14250
|
// src/ui/slider.tsx
|
|
14133
14251
|
import { useEffect as useEffect2, useState as useState5 } from "react";
|
|
14134
|
-
import { Box as
|
|
14135
|
-
import { Fragment as Fragment4, jsx as
|
|
14252
|
+
import { Box as Box10, Text as Text10, useInput as useInput5, useStdout as useStdout3 } from "ink";
|
|
14253
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
14136
14254
|
var SEP = 3;
|
|
14137
14255
|
function hslToRgb(h, s, l) {
|
|
14138
14256
|
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
@@ -14234,8 +14352,8 @@ function SliderPicker({ opts, onResolve, panelWidth }) {
|
|
|
14234
14352
|
const fullWidth = !!opts.topRuleColor;
|
|
14235
14353
|
const cols = panelWidth ?? stdout?.columns ?? 80;
|
|
14236
14354
|
const borderProps = overlayBorderProps(false, opts.topRuleColor);
|
|
14237
|
-
return /* @__PURE__ */
|
|
14238
|
-
|
|
14355
|
+
return /* @__PURE__ */ jsxs9(
|
|
14356
|
+
Box10,
|
|
14239
14357
|
{
|
|
14240
14358
|
flexDirection: "column",
|
|
14241
14359
|
marginTop: 1,
|
|
@@ -14243,15 +14361,15 @@ function SliderPicker({ opts, onResolve, panelWidth }) {
|
|
|
14243
14361
|
...fullWidth ? { width: cols } : {},
|
|
14244
14362
|
...borderProps,
|
|
14245
14363
|
children: [
|
|
14246
|
-
/* @__PURE__ */
|
|
14247
|
-
/* @__PURE__ */
|
|
14248
|
-
description ? /* @__PURE__ */
|
|
14249
|
-
/* @__PURE__ */
|
|
14250
|
-
/* @__PURE__ */
|
|
14364
|
+
/* @__PURE__ */ jsx10(Text10, { children: scaleLine }),
|
|
14365
|
+
/* @__PURE__ */ jsx10(Text10, { children: itemLine }),
|
|
14366
|
+
description ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
14367
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
14368
|
+
/* @__PURE__ */ jsx10(Text10, { children: dim(description) })
|
|
14251
14369
|
] }) : null,
|
|
14252
|
-
opts.footer ? /* @__PURE__ */
|
|
14253
|
-
/* @__PURE__ */
|
|
14254
|
-
/* @__PURE__ */
|
|
14370
|
+
opts.footer ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
14371
|
+
/* @__PURE__ */ jsx10(Text10, { children: " " }),
|
|
14372
|
+
/* @__PURE__ */ jsx10(Text10, { children: opts.footer })
|
|
14255
14373
|
] }) : null
|
|
14256
14374
|
]
|
|
14257
14375
|
}
|
|
@@ -14478,9 +14596,10 @@ function appendAssistantItems(items, msg, resultIndex, thinkingLabel, nextKey, t
|
|
|
14478
14596
|
|
|
14479
14597
|
// src/ui/spinner.tsx
|
|
14480
14598
|
import { useEffect as useEffect3, useState as useState6 } from "react";
|
|
14481
|
-
import { Box as
|
|
14482
|
-
import { jsx as
|
|
14483
|
-
var FRAMES = ["\
|
|
14599
|
+
import { Box as Box11, Text as Text11 } from "ink";
|
|
14600
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
14601
|
+
var FRAMES = ["\xB7", "\u2726", "\u2727", "\u2736", "\u2738", "\u273A", "\u2738", "\u2736", "\u2727", "\u2726"];
|
|
14602
|
+
var ANIM_SLOWDOWN = 2;
|
|
14484
14603
|
function shimmer(text, frame, [r, g, b]) {
|
|
14485
14604
|
let out = "\x1B[1m";
|
|
14486
14605
|
for (let i = 0; i < text.length; i++) {
|
|
@@ -14511,28 +14630,29 @@ function Spinner({ spec }) {
|
|
|
14511
14630
|
return () => clearInterval(id);
|
|
14512
14631
|
}, [tickMs]);
|
|
14513
14632
|
const elapsed = formatElapsed(Date.now() - spec.startedAt);
|
|
14514
|
-
const
|
|
14633
|
+
const phase = Math.floor(frame / ANIM_SLOWDOWN);
|
|
14634
|
+
const frameChar = FRAMES[phase % FRAMES.length] ?? "";
|
|
14515
14635
|
const upStr = spec.inputTokens != null ? ` \xB7 \u2191 ${formatTokenCount(spec.inputTokens)} tok` : "";
|
|
14516
14636
|
const downStr = spec.tokens != null ? ` \xB7 \u2193 ~${formatTokenCount(spec.tokens)} tok` : "";
|
|
14517
14637
|
const tokenStr = `${upStr}${downStr}`;
|
|
14518
14638
|
const hintStr = spec.hint ? ` \xB7 ${spec.hint}` : "";
|
|
14519
14639
|
let line;
|
|
14520
14640
|
if (canShimmer && tint) {
|
|
14521
|
-
const head = shimmer(frameChar,
|
|
14522
|
-
const word = shimmer(spec.activeWord,
|
|
14641
|
+
const head = shimmer(frameChar, phase + 1, tint);
|
|
14642
|
+
const word = shimmer(spec.activeWord, phase, tint);
|
|
14523
14643
|
line = `${head} ${word} \xB7 ${elapsed}${tokenStr}${hintStr}`;
|
|
14524
14644
|
} else {
|
|
14525
14645
|
const renderedFrame = isStatic ? frameChar : bold(colorize(frameChar));
|
|
14526
14646
|
const word = isStatic ? spec.activeWord : bold(colorize(spec.activeWord));
|
|
14527
14647
|
line = `${renderedFrame} ${word} \xB7 ${elapsed}${tokenStr}${hintStr}`;
|
|
14528
14648
|
}
|
|
14529
|
-
return /* @__PURE__ */
|
|
14649
|
+
return /* @__PURE__ */ jsx11(Box11, { marginTop: 1, marginBottom: 1, flexDirection: "column", children: /* @__PURE__ */ jsx11(Text11, { children: line }) });
|
|
14530
14650
|
}
|
|
14531
14651
|
|
|
14532
14652
|
// src/ui/task-footer.tsx
|
|
14533
14653
|
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
14534
|
-
import { Box as
|
|
14535
|
-
import { jsx as
|
|
14654
|
+
import { Box as Box12, Text as Text12 } from "ink";
|
|
14655
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
14536
14656
|
var MAX_VISIBLE = 5;
|
|
14537
14657
|
var MIN_VISIBLE_TASKS = 2;
|
|
14538
14658
|
function taskFooterVisible(tasks) {
|
|
@@ -14544,28 +14664,28 @@ var STATUS_RANK = {
|
|
|
14544
14664
|
completed: 2
|
|
14545
14665
|
};
|
|
14546
14666
|
function TaskRow({ task, isFirst }) {
|
|
14547
|
-
const prefix = isFirst ? /* @__PURE__ */
|
|
14548
|
-
const suffix = task.blockedBy.length > 0 ? /* @__PURE__ */
|
|
14667
|
+
const prefix = isFirst ? /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: " \u23BF " }) : /* @__PURE__ */ jsx12(Text12, { children: " " });
|
|
14668
|
+
const suffix = task.blockedBy.length > 0 ? /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: ` \u27F5 ${task.blockedBy.length}` }) : null;
|
|
14549
14669
|
switch (task.status) {
|
|
14550
14670
|
case "completed":
|
|
14551
|
-
return /* @__PURE__ */
|
|
14671
|
+
return /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
14552
14672
|
prefix,
|
|
14553
|
-
/* @__PURE__ */
|
|
14673
|
+
/* @__PURE__ */ jsx12(Text12, { color: "green", children: "\u2713" }),
|
|
14554
14674
|
" ",
|
|
14555
|
-
/* @__PURE__ */
|
|
14675
|
+
/* @__PURE__ */ jsx12(Text12, { color: "gray", strikethrough: true, children: task.description }),
|
|
14556
14676
|
suffix
|
|
14557
14677
|
] });
|
|
14558
14678
|
case "in_progress":
|
|
14559
|
-
return /* @__PURE__ */
|
|
14679
|
+
return /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
14560
14680
|
prefix,
|
|
14561
|
-
/* @__PURE__ */
|
|
14681
|
+
/* @__PURE__ */ jsx12(Text12, { color: ACCENT_HEX, children: "\u25A0" }),
|
|
14562
14682
|
" ",
|
|
14563
|
-
/* @__PURE__ */
|
|
14683
|
+
/* @__PURE__ */ jsx12(Text12, { color: ACCENT_HEX, bold: true, children: task.description }),
|
|
14564
14684
|
suffix
|
|
14565
14685
|
] });
|
|
14566
14686
|
case "pending":
|
|
14567
14687
|
default:
|
|
14568
|
-
return /* @__PURE__ */
|
|
14688
|
+
return /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
14569
14689
|
prefix,
|
|
14570
14690
|
"\u25A1 ",
|
|
14571
14691
|
task.description,
|
|
@@ -14577,9 +14697,9 @@ function SummaryRow({
|
|
|
14577
14697
|
hidden,
|
|
14578
14698
|
counts
|
|
14579
14699
|
}) {
|
|
14580
|
-
return /* @__PURE__ */
|
|
14700
|
+
return /* @__PURE__ */ jsxs10(Text12, { children: [
|
|
14581
14701
|
" ",
|
|
14582
|
-
/* @__PURE__ */
|
|
14702
|
+
/* @__PURE__ */ jsxs10(Text12, { dimColor: true, children: [
|
|
14583
14703
|
"... ",
|
|
14584
14704
|
hidden,
|
|
14585
14705
|
" More, ",
|
|
@@ -14628,17 +14748,17 @@ function TaskFooter({ tasks }) {
|
|
|
14628
14748
|
startedAt,
|
|
14629
14749
|
activeWord: `TASK: ${spinnerTask.description}...`
|
|
14630
14750
|
} : null;
|
|
14631
|
-
return /* @__PURE__ */
|
|
14632
|
-
spinnerSpec ? /* @__PURE__ */
|
|
14633
|
-
visible.map((t, i) => /* @__PURE__ */
|
|
14634
|
-
hidden > 0 ? /* @__PURE__ */
|
|
14751
|
+
return /* @__PURE__ */ jsxs10(Box12, { flexDirection: "column", marginTop: 1, children: [
|
|
14752
|
+
spinnerSpec ? /* @__PURE__ */ jsx12(Spinner, { spec: spinnerSpec }) : null,
|
|
14753
|
+
visible.map((t, i) => /* @__PURE__ */ jsx12(TaskRow, { task: t, isFirst: i === 0 }, t.id)),
|
|
14754
|
+
hidden > 0 ? /* @__PURE__ */ jsx12(SummaryRow, { hidden, counts }) : null
|
|
14635
14755
|
] });
|
|
14636
14756
|
}
|
|
14637
14757
|
|
|
14638
14758
|
// src/ui/todo-footer.tsx
|
|
14639
14759
|
import { useEffect as useEffect5, useState as useState8 } from "react";
|
|
14640
|
-
import { Box as
|
|
14641
|
-
import { jsx as
|
|
14760
|
+
import { Box as Box13, Text as Text13 } from "ink";
|
|
14761
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
14642
14762
|
var MAX_VISIBLE2 = 5;
|
|
14643
14763
|
var MIN_VISIBLE_TODOS = 2;
|
|
14644
14764
|
function todoFooterVisible(todos) {
|
|
@@ -14650,25 +14770,25 @@ var STATUS_RANK2 = {
|
|
|
14650
14770
|
completed: 2
|
|
14651
14771
|
};
|
|
14652
14772
|
function TodoRow({ todo, isFirst }) {
|
|
14653
|
-
const prefix = isFirst ? /* @__PURE__ */
|
|
14773
|
+
const prefix = isFirst ? /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: " \u23BF " }) : /* @__PURE__ */ jsx13(Text13, { children: " " });
|
|
14654
14774
|
switch (todo.status) {
|
|
14655
14775
|
case "completed":
|
|
14656
|
-
return /* @__PURE__ */
|
|
14776
|
+
return /* @__PURE__ */ jsxs11(Text13, { children: [
|
|
14657
14777
|
prefix,
|
|
14658
|
-
/* @__PURE__ */
|
|
14778
|
+
/* @__PURE__ */ jsx13(Text13, { color: "green", children: "\u2713" }),
|
|
14659
14779
|
" ",
|
|
14660
|
-
/* @__PURE__ */
|
|
14780
|
+
/* @__PURE__ */ jsx13(Text13, { color: "gray", strikethrough: true, children: todo.description })
|
|
14661
14781
|
] });
|
|
14662
14782
|
case "in_progress":
|
|
14663
|
-
return /* @__PURE__ */
|
|
14783
|
+
return /* @__PURE__ */ jsxs11(Text13, { children: [
|
|
14664
14784
|
prefix,
|
|
14665
|
-
/* @__PURE__ */
|
|
14785
|
+
/* @__PURE__ */ jsx13(Text13, { color: "blue", children: "\u25A0" }),
|
|
14666
14786
|
" ",
|
|
14667
|
-
/* @__PURE__ */
|
|
14787
|
+
/* @__PURE__ */ jsx13(Text13, { color: "blue", bold: true, children: todo.description })
|
|
14668
14788
|
] });
|
|
14669
14789
|
case "pending":
|
|
14670
14790
|
default:
|
|
14671
|
-
return /* @__PURE__ */
|
|
14791
|
+
return /* @__PURE__ */ jsxs11(Text13, { children: [
|
|
14672
14792
|
prefix,
|
|
14673
14793
|
"\u25A1 ",
|
|
14674
14794
|
todo.description
|
|
@@ -14679,9 +14799,9 @@ function SummaryRow2({
|
|
|
14679
14799
|
hidden,
|
|
14680
14800
|
counts
|
|
14681
14801
|
}) {
|
|
14682
|
-
return /* @__PURE__ */
|
|
14802
|
+
return /* @__PURE__ */ jsxs11(Text13, { children: [
|
|
14683
14803
|
" ",
|
|
14684
|
-
/* @__PURE__ */
|
|
14804
|
+
/* @__PURE__ */ jsxs11(Text13, { dimColor: true, children: [
|
|
14685
14805
|
"... ",
|
|
14686
14806
|
hidden,
|
|
14687
14807
|
" More, ",
|
|
@@ -14730,15 +14850,15 @@ function TodoFooter({ todos }) {
|
|
|
14730
14850
|
startedAt,
|
|
14731
14851
|
activeWord: `TODO: ${spinnerTodo.description}...`
|
|
14732
14852
|
} : null;
|
|
14733
|
-
return /* @__PURE__ */
|
|
14734
|
-
spinnerSpec ? /* @__PURE__ */
|
|
14735
|
-
visible.map((t, i) => /* @__PURE__ */
|
|
14736
|
-
hidden > 0 ? /* @__PURE__ */
|
|
14853
|
+
return /* @__PURE__ */ jsxs11(Box13, { flexDirection: "column", marginTop: 1, children: [
|
|
14854
|
+
spinnerSpec ? /* @__PURE__ */ jsx13(Spinner, { spec: spinnerSpec }) : null,
|
|
14855
|
+
visible.map((t, i) => /* @__PURE__ */ jsx13(TodoRow, { todo: t, isFirst: i === 0 }, t.id)),
|
|
14856
|
+
hidden > 0 ? /* @__PURE__ */ jsx13(SummaryRow2, { hidden, counts }) : null
|
|
14737
14857
|
] });
|
|
14738
14858
|
}
|
|
14739
14859
|
|
|
14740
14860
|
// src/ui/viewport.tsx
|
|
14741
|
-
import { Fragment as Fragment5, jsx as
|
|
14861
|
+
import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
14742
14862
|
var MIN_ROWS = 3;
|
|
14743
14863
|
var H_PAD = 2;
|
|
14744
14864
|
function Viewport({ store, rows, resolveModal }) {
|
|
@@ -14852,7 +14972,7 @@ function Viewport({ store, rows, resolveModal }) {
|
|
|
14852
14972
|
}, [hasPending]);
|
|
14853
14973
|
const displayLines = hasPending && !blinkOn ? highlighted.map((l) => blinkPendingOff(l)) : highlighted;
|
|
14854
14974
|
if (inStreamModal) {
|
|
14855
|
-
const modalEl = /* @__PURE__ */
|
|
14975
|
+
const modalEl = /* @__PURE__ */ jsx14(
|
|
14856
14976
|
InStreamModal,
|
|
14857
14977
|
{
|
|
14858
14978
|
modal: inStreamModal,
|
|
@@ -14862,26 +14982,26 @@ function Viewport({ store, rows, resolveModal }) {
|
|
|
14862
14982
|
}
|
|
14863
14983
|
);
|
|
14864
14984
|
if (inStreamModal.kind === "approval") {
|
|
14865
|
-
return /* @__PURE__ */
|
|
14866
|
-
displayLines.length > 0 ? /* @__PURE__ */
|
|
14985
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflowY: "hidden", paddingX: H_PAD, children: [
|
|
14986
|
+
displayLines.length > 0 ? /* @__PURE__ */ jsx14(Text14, { children: displayLines.join("\n") }) : null,
|
|
14867
14987
|
modalEl,
|
|
14868
|
-
/* @__PURE__ */
|
|
14988
|
+
/* @__PURE__ */ jsx14(Box14, { flexGrow: 1 })
|
|
14869
14989
|
] });
|
|
14870
14990
|
}
|
|
14871
|
-
return /* @__PURE__ */
|
|
14872
|
-
displayLines.length > 0 ? /* @__PURE__ */
|
|
14873
|
-
/* @__PURE__ */
|
|
14991
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflowY: "hidden", paddingX: H_PAD, children: [
|
|
14992
|
+
displayLines.length > 0 ? /* @__PURE__ */ jsx14(Text14, { children: displayLines.join("\n") }) : null,
|
|
14993
|
+
/* @__PURE__ */ jsx14(Box14, { flexGrow: 1 }),
|
|
14874
14994
|
modalEl
|
|
14875
14995
|
] });
|
|
14876
14996
|
}
|
|
14877
|
-
return /* @__PURE__ */
|
|
14878
|
-
displayLines.length > 0 ? /* @__PURE__ */
|
|
14879
|
-
hasSpinner && !anyFooterVisible ? /* @__PURE__ */
|
|
14880
|
-
hasSpinner && anyFooterVisible ? /* @__PURE__ */
|
|
14881
|
-
/* @__PURE__ */
|
|
14882
|
-
/* @__PURE__ */
|
|
14997
|
+
return /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflowY: "hidden", paddingX: H_PAD, children: [
|
|
14998
|
+
displayLines.length > 0 ? /* @__PURE__ */ jsx14(Text14, { children: displayLines.join("\n") }) : null,
|
|
14999
|
+
hasSpinner && !anyFooterVisible ? /* @__PURE__ */ jsx14(SpinnerWrapper, { store }) : null,
|
|
15000
|
+
hasSpinner && anyFooterVisible ? /* @__PURE__ */ jsxs12(Fragment5, { children: [
|
|
15001
|
+
/* @__PURE__ */ jsx14(TaskFooter, { tasks }),
|
|
15002
|
+
/* @__PURE__ */ jsx14(TodoFooter, { todos })
|
|
14883
15003
|
] }) : null,
|
|
14884
|
-
/* @__PURE__ */
|
|
15004
|
+
/* @__PURE__ */ jsx14(Box14, { flexGrow: 1 })
|
|
14885
15005
|
] });
|
|
14886
15006
|
}
|
|
14887
15007
|
function SpinnerWrapper({
|
|
@@ -14889,7 +15009,7 @@ function SpinnerWrapper({
|
|
|
14889
15009
|
}) {
|
|
14890
15010
|
const spec = store((s) => s.spinner);
|
|
14891
15011
|
if (!spec) return null;
|
|
14892
|
-
return /* @__PURE__ */
|
|
15012
|
+
return /* @__PURE__ */ jsx14(Spinner, { spec });
|
|
14893
15013
|
}
|
|
14894
15014
|
function chromeRowsFor(hasSpinner, modal, todos, tasks, cols) {
|
|
14895
15015
|
if (modal) {
|
|
@@ -14964,7 +15084,7 @@ function InStreamModal({
|
|
|
14964
15084
|
}) {
|
|
14965
15085
|
switch (modal.kind) {
|
|
14966
15086
|
case "approval":
|
|
14967
|
-
return /* @__PURE__ */
|
|
15087
|
+
return /* @__PURE__ */ jsx14(
|
|
14968
15088
|
ApprovalPrompt,
|
|
14969
15089
|
{
|
|
14970
15090
|
decision: modal.decision,
|
|
@@ -14976,9 +15096,9 @@ function InStreamModal({
|
|
|
14976
15096
|
}
|
|
14977
15097
|
);
|
|
14978
15098
|
case "ask":
|
|
14979
|
-
return /* @__PURE__ */
|
|
15099
|
+
return /* @__PURE__ */ jsx14(AskPanel, { req: modal.req, onResolve: (value) => resolveModal(value) });
|
|
14980
15100
|
case "pick":
|
|
14981
|
-
return /* @__PURE__ */
|
|
15101
|
+
return /* @__PURE__ */ jsx14(
|
|
14982
15102
|
PickList,
|
|
14983
15103
|
{
|
|
14984
15104
|
opts: modal.opts,
|
|
@@ -14987,7 +15107,7 @@ function InStreamModal({
|
|
|
14987
15107
|
}
|
|
14988
15108
|
);
|
|
14989
15109
|
case "pickH":
|
|
14990
|
-
return /* @__PURE__ */
|
|
15110
|
+
return /* @__PURE__ */ jsx14(
|
|
14991
15111
|
PickHorizontal,
|
|
14992
15112
|
{
|
|
14993
15113
|
opts: modal.opts,
|
|
@@ -14996,7 +15116,7 @@ function InStreamModal({
|
|
|
14996
15116
|
}
|
|
14997
15117
|
);
|
|
14998
15118
|
case "slider":
|
|
14999
|
-
return /* @__PURE__ */
|
|
15119
|
+
return /* @__PURE__ */ jsx14(
|
|
15000
15120
|
SliderPicker,
|
|
15001
15121
|
{
|
|
15002
15122
|
opts: modal.opts,
|
|
@@ -15005,7 +15125,7 @@ function InStreamModal({
|
|
|
15005
15125
|
}
|
|
15006
15126
|
);
|
|
15007
15127
|
case "viewer":
|
|
15008
|
-
return /* @__PURE__ */
|
|
15128
|
+
return /* @__PURE__ */ jsx14(
|
|
15009
15129
|
ScrollViewer,
|
|
15010
15130
|
{
|
|
15011
15131
|
opts: modal.opts,
|
|
@@ -15028,7 +15148,7 @@ function hitTestJumpButton(row, col) {
|
|
|
15028
15148
|
}
|
|
15029
15149
|
|
|
15030
15150
|
// src/ui/app.tsx
|
|
15031
|
-
import { Fragment as Fragment6, jsx as
|
|
15151
|
+
import { Fragment as Fragment6, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
15032
15152
|
function pinnedBottomRows(inputRows, extraRows) {
|
|
15033
15153
|
return STATUS_LINE_ROWS + INPUT_TOP_SPACER_ROWS + inputRows + extraRows;
|
|
15034
15154
|
}
|
|
@@ -15059,12 +15179,13 @@ function JumpToBottomHint({
|
|
|
15059
15179
|
store.getState().setJumpButtonHovered(false);
|
|
15060
15180
|
};
|
|
15061
15181
|
}, [show, row, colStart, colEnd, store]);
|
|
15062
|
-
return /* @__PURE__ */
|
|
15182
|
+
return /* @__PURE__ */ jsx15(Box15, { flexShrink: 0, height: INPUT_TOP_SPACER_ROWS, justifyContent: "center", children: show ? /* @__PURE__ */ jsx15(Text15, { color: "black", backgroundColor: hovered ? "cyan" : "gray", children: JUMP_TO_BOTTOM_LABEL }) : null });
|
|
15063
15183
|
}
|
|
15064
15184
|
var MIN_FRAME_ROWS = 4;
|
|
15065
15185
|
function App({ store }) {
|
|
15066
15186
|
const {
|
|
15067
15187
|
setup,
|
|
15188
|
+
trust,
|
|
15068
15189
|
modal,
|
|
15069
15190
|
slashCommands,
|
|
15070
15191
|
mentionFiles,
|
|
@@ -15079,6 +15200,7 @@ function App({ store }) {
|
|
|
15079
15200
|
} = store(
|
|
15080
15201
|
useShallow3((s) => ({
|
|
15081
15202
|
setup: s.setup,
|
|
15203
|
+
trust: s.trust,
|
|
15082
15204
|
modal: s.modal,
|
|
15083
15205
|
slashCommands: s.slashCommands,
|
|
15084
15206
|
mentionFiles: s.mentionFiles,
|
|
@@ -15115,12 +15237,13 @@ function App({ store }) {
|
|
|
15115
15237
|
[store]
|
|
15116
15238
|
);
|
|
15117
15239
|
React12.useEffect(() => {
|
|
15118
|
-
if (setup || overlayModal) setCursorTarget(null);
|
|
15119
|
-
}, [setup, overlayModal]);
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15240
|
+
if (setup || trust || overlayModal) setCursorTarget(null);
|
|
15241
|
+
}, [setup, trust, overlayModal]);
|
|
15242
|
+
const fullscreenView = setup ? /* @__PURE__ */ jsx15(SetupView, { state: setup }) : trust ? /* @__PURE__ */ jsx15(TrustView, { state: trust }) : null;
|
|
15243
|
+
if (fullscreenView) {
|
|
15244
|
+
return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", children: [
|
|
15245
|
+
fullscreenView,
|
|
15246
|
+
modal?.kind === "input" ? /* @__PURE__ */ jsx15(
|
|
15124
15247
|
InputBox,
|
|
15125
15248
|
{
|
|
15126
15249
|
options: modal.opts,
|
|
@@ -15129,14 +15252,14 @@ function App({ store }) {
|
|
|
15129
15252
|
onMeasure: onMeasureInput
|
|
15130
15253
|
}
|
|
15131
15254
|
) : null,
|
|
15132
|
-
modal?.kind === "pickH" ? /* @__PURE__ */
|
|
15255
|
+
modal?.kind === "pickH" ? /* @__PURE__ */ jsx15(
|
|
15133
15256
|
PickHorizontal,
|
|
15134
15257
|
{
|
|
15135
15258
|
opts: modal.opts,
|
|
15136
15259
|
onResolve: (value) => resolveModal(value)
|
|
15137
15260
|
}
|
|
15138
15261
|
) : null,
|
|
15139
|
-
modal?.kind === "pick" ? /* @__PURE__ */
|
|
15262
|
+
modal?.kind === "pick" ? /* @__PURE__ */ jsx15(
|
|
15140
15263
|
PickList,
|
|
15141
15264
|
{
|
|
15142
15265
|
opts: modal.opts,
|
|
@@ -15149,10 +15272,10 @@ function App({ store }) {
|
|
|
15149
15272
|
const indicatorRows = modeIndicator ? 1 : 0;
|
|
15150
15273
|
const bottomChromeRows = overlayModal ? 0 : pinnedBottomRows(inputRows, indicatorRows);
|
|
15151
15274
|
const viewportRows = Math.max(3, termRows - bottomChromeRows - 1);
|
|
15152
|
-
return /* @__PURE__ */
|
|
15153
|
-
/* @__PURE__ */
|
|
15154
|
-
overlayModal ? null : /* @__PURE__ */
|
|
15155
|
-
/* @__PURE__ */
|
|
15275
|
+
return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", height: Math.max(MIN_FRAME_ROWS, termRows - 1), overflowY: "hidden", children: [
|
|
15276
|
+
/* @__PURE__ */ jsx15(Viewport, { store, rows: viewportRows, resolveModal }),
|
|
15277
|
+
overlayModal ? null : /* @__PURE__ */ jsxs13(Fragment6, { children: [
|
|
15278
|
+
/* @__PURE__ */ jsx15(
|
|
15156
15279
|
JumpToBottomHint,
|
|
15157
15280
|
{
|
|
15158
15281
|
store,
|
|
@@ -15163,7 +15286,7 @@ function App({ store }) {
|
|
|
15163
15286
|
indicatorRows
|
|
15164
15287
|
}
|
|
15165
15288
|
),
|
|
15166
|
-
/* @__PURE__ */
|
|
15289
|
+
/* @__PURE__ */ jsx15(Box15, { flexShrink: 0, flexDirection: "column", children: /* @__PURE__ */ jsx15(
|
|
15167
15290
|
InputBox,
|
|
15168
15291
|
{
|
|
15169
15292
|
options: {
|
|
@@ -15189,11 +15312,11 @@ function App({ store }) {
|
|
|
15189
15312
|
onImageAttached: imagePaste?.attached
|
|
15190
15313
|
}
|
|
15191
15314
|
) }),
|
|
15192
|
-
/* @__PURE__ */
|
|
15193
|
-
/* @__PURE__ */
|
|
15194
|
-
modeIndicator ? /* @__PURE__ */
|
|
15195
|
-
/* @__PURE__ */
|
|
15196
|
-
/* @__PURE__ */
|
|
15315
|
+
/* @__PURE__ */ jsxs13(Box15, { flexShrink: 0, flexDirection: "column", children: [
|
|
15316
|
+
/* @__PURE__ */ jsx15(StatusLine, { store, shellMode }),
|
|
15317
|
+
modeIndicator ? /* @__PURE__ */ jsxs13(Box15, { children: [
|
|
15318
|
+
/* @__PURE__ */ jsx15(Text15, { color: modeIndicator.color, children: ` ${modeIndicator.label}` }),
|
|
15319
|
+
/* @__PURE__ */ jsx15(Text15, { dimColor: true, children: ` ${PERMISSION_MODE_HINT}` })
|
|
15197
15320
|
] }) : null
|
|
15198
15321
|
] })
|
|
15199
15322
|
] })
|
|
@@ -15567,6 +15690,7 @@ function createAppStore(opts = {}) {
|
|
|
15567
15690
|
escHandler: null,
|
|
15568
15691
|
thinkingLabel: void 0,
|
|
15569
15692
|
setup: null,
|
|
15693
|
+
trust: null,
|
|
15570
15694
|
termCols: process.stdout.columns ?? 80,
|
|
15571
15695
|
termRows: process.stdout.rows ?? 24,
|
|
15572
15696
|
scrollOffset: 0,
|
|
@@ -15708,6 +15832,12 @@ function createAppStore(opts = {}) {
|
|
|
15708
15832
|
beginSetup(state) {
|
|
15709
15833
|
set({ setup: state });
|
|
15710
15834
|
},
|
|
15835
|
+
beginTrust(state) {
|
|
15836
|
+
set({ trust: state });
|
|
15837
|
+
},
|
|
15838
|
+
endTrust() {
|
|
15839
|
+
set({ trust: null });
|
|
15840
|
+
},
|
|
15711
15841
|
setSetupPrompt(prompt) {
|
|
15712
15842
|
const cur = get().setup;
|
|
15713
15843
|
if (!cur) return;
|
|
@@ -16446,6 +16576,12 @@ var Screen = class {
|
|
|
16446
16576
|
endSetup() {
|
|
16447
16577
|
this.store.getState().endSetup();
|
|
16448
16578
|
}
|
|
16579
|
+
beginTrust(state) {
|
|
16580
|
+
this.store.getState().beginTrust(state);
|
|
16581
|
+
}
|
|
16582
|
+
endTrust() {
|
|
16583
|
+
this.store.getState().endTrust();
|
|
16584
|
+
}
|
|
16449
16585
|
async promptInput(opts) {
|
|
16450
16586
|
return this.store.getState().openInputModal(opts);
|
|
16451
16587
|
}
|
|
@@ -17196,7 +17332,7 @@ async function handleDiff(ctx, args) {
|
|
|
17196
17332
|
|
|
17197
17333
|
// src/doctor.ts
|
|
17198
17334
|
import { readFile as readFile21 } from "fs/promises";
|
|
17199
|
-
import { basename as
|
|
17335
|
+
import { basename as basename5 } from "path";
|
|
17200
17336
|
import { Command } from "commander";
|
|
17201
17337
|
function zodIssues(err) {
|
|
17202
17338
|
if (err && typeof err === "object" && Array.isArray(err.issues)) {
|
|
@@ -17314,7 +17450,7 @@ async function diagnoseConfig(opts = {}) {
|
|
|
17314
17450
|
for (const e of hooks.errors) {
|
|
17315
17451
|
issues.push({
|
|
17316
17452
|
level: "warn",
|
|
17317
|
-
title: `invalid hook file: ${
|
|
17453
|
+
title: `invalid hook file: ${basename5(e.source)}`,
|
|
17318
17454
|
detail: e.message,
|
|
17319
17455
|
hint: "fix or remove it \u2014 nova skips it and continues"
|
|
17320
17456
|
});
|
|
@@ -18611,8 +18747,7 @@ async function handleSkills(ctx) {
|
|
|
18611
18747
|
topRuleColor: PURPLE_HEX,
|
|
18612
18748
|
render: (s, selected) => {
|
|
18613
18749
|
const name = s.name.padEnd(nameWidth, " ");
|
|
18614
|
-
|
|
18615
|
-
return `${pickerArrow(selected)} ${name} ${s.description}${trig}`;
|
|
18750
|
+
return `${pickerArrow(selected)} ${name} ${s.description}`;
|
|
18616
18751
|
}
|
|
18617
18752
|
});
|
|
18618
18753
|
}
|
|
@@ -19211,7 +19346,8 @@ async function createContext(settings, screen, cliOpts) {
|
|
|
19211
19346
|
logger
|
|
19212
19347
|
} : void 0;
|
|
19213
19348
|
const skillItems = skillsOpts ? getSkillList(skillsOpts) : [];
|
|
19214
|
-
const
|
|
19349
|
+
const modelSkillItems = skillItems.filter((s) => !s.disableModelInvocation);
|
|
19350
|
+
const skillsBlock = skillsOpts ? renderSkillsBlock(modelSkillItems, settings.skills.maxIndexBytes) : "";
|
|
19215
19351
|
if (skillsOpts) {
|
|
19216
19352
|
await transcript.append({
|
|
19217
19353
|
kind: "skills_loaded",
|
|
@@ -21578,6 +21714,68 @@ function buildUpgradeCommand() {
|
|
|
21578
21714
|
});
|
|
21579
21715
|
}
|
|
21580
21716
|
|
|
21717
|
+
// src/workspace-trust.ts
|
|
21718
|
+
import { homedir as homedir17 } from "os";
|
|
21719
|
+
async function isWorkspaceTrusted(settings, workspace) {
|
|
21720
|
+
if (!settings.trust.enabled) return true;
|
|
21721
|
+
const wsCanon = await canonicalizePath(workspace, ".");
|
|
21722
|
+
for (const root of settings.trust.trustedRoots) {
|
|
21723
|
+
const rootCanon = await canonicalizePath(workspace, root);
|
|
21724
|
+
if (isWithin(rootCanon, wsCanon)) return true;
|
|
21725
|
+
}
|
|
21726
|
+
return false;
|
|
21727
|
+
}
|
|
21728
|
+
async function trustWorkspace(settings, workspace, configPath) {
|
|
21729
|
+
const wsCanon = await canonicalizePath(workspace, ".");
|
|
21730
|
+
const roots = settings.trust.trustedRoots.includes(wsCanon) ? settings.trust.trustedRoots : [...settings.trust.trustedRoots, wsCanon];
|
|
21731
|
+
settings.trust = { ...settings.trust, trustedRoots: roots };
|
|
21732
|
+
const home = await canonicalizePath(homedir17(), ".");
|
|
21733
|
+
if (wsCanon === home) return;
|
|
21734
|
+
await saveSettings({ trust: settings.trust }, configPath);
|
|
21735
|
+
}
|
|
21736
|
+
async function ensureWorkspaceTrust(settings, screen, workspace, configPath) {
|
|
21737
|
+
if (await isWorkspaceTrusted(settings, workspace)) return;
|
|
21738
|
+
const wsCanon = await canonicalizePath(workspace, ".");
|
|
21739
|
+
screen.beginTrust({
|
|
21740
|
+
version: await readCliVersion(),
|
|
21741
|
+
workspace: wsCanon,
|
|
21742
|
+
lines: [
|
|
21743
|
+
"nova has not been granted access to this folder yet. Granting access",
|
|
21744
|
+
"lets it read and edit files here (and in subdirectories) without",
|
|
21745
|
+
"confirming each time, and runs any project hooks the folder defines.",
|
|
21746
|
+
"Only trust folders you recognize \u2014 declining exits without touching",
|
|
21747
|
+
"anything."
|
|
21748
|
+
]
|
|
21749
|
+
});
|
|
21750
|
+
try {
|
|
21751
|
+
const choice = await screen.pickOne({
|
|
21752
|
+
items: [{ trust: true }, { trust: false }],
|
|
21753
|
+
footer: dim("\u2191/\u2193 choose \xB7 Enter confirm \xB7 Ctrl+C to exit"),
|
|
21754
|
+
border: false,
|
|
21755
|
+
topRuleColor: PURPLE_HEX,
|
|
21756
|
+
render: (it, selected) => {
|
|
21757
|
+
const label = it.trust ? "Yes, trust this folder" : "No, exit";
|
|
21758
|
+
return `${pickerArrow(selected)} ${label}`;
|
|
21759
|
+
}
|
|
21760
|
+
});
|
|
21761
|
+
if (choice === null || !choice.trust) {
|
|
21762
|
+
await fatalExit(screen, `workspace not trusted \u2014 exiting.
|
|
21763
|
+
${wsCanon}`, 1);
|
|
21764
|
+
}
|
|
21765
|
+
try {
|
|
21766
|
+
await trustWorkspace(settings, workspace, configPath);
|
|
21767
|
+
} catch (err) {
|
|
21768
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
21769
|
+
screen.card(`could not persist workspace trust: ${msg}`, {
|
|
21770
|
+
kind: "warn",
|
|
21771
|
+
title: "workspace trust"
|
|
21772
|
+
});
|
|
21773
|
+
}
|
|
21774
|
+
} finally {
|
|
21775
|
+
screen.endTrust();
|
|
21776
|
+
}
|
|
21777
|
+
}
|
|
21778
|
+
|
|
21581
21779
|
// src/index.ts
|
|
21582
21780
|
function applyCliOverrides(settings, opts) {
|
|
21583
21781
|
if (opts.model) {
|
|
@@ -21651,6 +21849,14 @@ async function runHeadlessMode(settings, positional, opts) {
|
|
|
21651
21849
|
dieHeadless(err instanceof Error ? err.message : String(err), 2);
|
|
21652
21850
|
}
|
|
21653
21851
|
const approvalPolicy = opts.dangerouslySkipPermissions ? "allow" : "deny";
|
|
21852
|
+
const headlessCwd = opts.cwd ?? process.cwd();
|
|
21853
|
+
if (!opts.dangerouslySkipPermissions && !await isWorkspaceTrusted(settings, headlessCwd)) {
|
|
21854
|
+
dieHeadless(
|
|
21855
|
+
`workspace not trusted: ${headlessCwd}
|
|
21856
|
+
Trust it by running nova interactively here once, by adding it to trust.trustedRoots in nova.config.json, or by passing --dangerously-skip-permissions.`,
|
|
21857
|
+
1
|
|
21858
|
+
);
|
|
21859
|
+
}
|
|
21654
21860
|
let code;
|
|
21655
21861
|
try {
|
|
21656
21862
|
code = await runHeadless(settings, {
|
|
@@ -21721,6 +21927,9 @@ ${formatIssues(report)}
|
|
|
21721
21927
|
"apiKey is not set in nova.config.json (or equivalent settings file)."
|
|
21722
21928
|
);
|
|
21723
21929
|
}
|
|
21930
|
+
if (!opts.dangerouslySkipPermissions) {
|
|
21931
|
+
await ensureWorkspaceTrust(settings, screen, opts.cwd ?? process.cwd());
|
|
21932
|
+
}
|
|
21724
21933
|
const ctx = await createContext(settings, screen, {
|
|
21725
21934
|
...opts.cwd !== void 0 ? { cwd: opts.cwd } : {},
|
|
21726
21935
|
...opts.resume !== void 0 ? { resume: opts.resume } : {},
|