@goah/cli 0.13.1 → 0.13.2
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/{chunk-X7UWW2PN.js → chunk-7E7V6OIU.js} +45 -8
- package/dist/{chunk-VWEV4LTH.js → chunk-D2DVAH37.js} +1 -1
- package/dist/{chunk-PFEV3HWI.js → chunk-KJ4HJCTK.js} +2 -2
- package/dist/cli.js +646 -53
- package/dist/faux-runner-worker.js +1 -1
- package/dist/index.js +3 -3
- package/dist/pi-worker.js +1 -1
- package/dist/runner-pi.js +1 -1
- package/dist/{runner-registry-M776E3SE.js → runner-registry-GD4BYCQC.js} +2 -2
- package/package.json +1 -1
|
@@ -546,15 +546,15 @@ async function setupPi(current, interaction, scope = "full", setupAuthFile = def
|
|
|
546
546
|
const model = selected === "__custom__" ? await interaction.input({ title: "Model ID", description: `Enter the model identifier accepted by ${providerId}.`, prompt: "Model", progress: { current: 3, total: 5 }, ...before?.provider === providerId ? { initial: before.model } : {} }) : selected;
|
|
547
547
|
if (!model)
|
|
548
548
|
return null;
|
|
549
|
-
|
|
550
|
-
return { ...before, model };
|
|
551
|
-
const config = { provider: providerId, model, thinking: before?.thinking ?? (providerId === "faux" ? "off" : "medium"), authFile: before?.authFile ?? setupAuthFile, authMode: providerId === "faux" || ["ollama", "lm-studio", "llama.cpp"].includes(providerId) ? "local" : "unconfigured" };
|
|
549
|
+
const config = scope === "model" && before?.provider === providerId ? { ...before, model, authFile: before.authFile ?? setupAuthFile } : { provider: providerId, model, thinking: before?.thinking ?? (providerId === "faux" ? "off" : "medium"), authFile: scope === "full" ? setupAuthFile : before?.authFile ?? setupAuthFile, authMode: providerId === "faux" || ["ollama", "lm-studio", "llama.cpp"].includes(providerId) ? "local" : "unconfigured" };
|
|
552
550
|
const descriptor = providers.find((entry) => entry.id === provider);
|
|
553
551
|
if (!descriptor.local && provider !== "faux") {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
552
|
+
if (scope === "model") {
|
|
553
|
+
const authenticated = await requireAuthentication(config, descriptor, interaction, legacyCredential);
|
|
554
|
+
if (authenticated === "back")
|
|
555
|
+
return setupPi(current, interaction, scope, setupAuthFile);
|
|
556
|
+
Object.assign(config, authenticated);
|
|
557
|
+
} else {
|
|
558
558
|
const auth = await configureAuthentication(providerId, descriptor, config.authFile, interaction, legacyCredential);
|
|
559
559
|
if (auth === "back")
|
|
560
560
|
return setupPi(current, interaction, scope, setupAuthFile);
|
|
@@ -620,6 +620,39 @@ async function configureAuthentication(provider, descriptor, authFile, interacti
|
|
|
620
620
|
}
|
|
621
621
|
return { authMode: "unconfigured" };
|
|
622
622
|
}
|
|
623
|
+
async function requireAuthentication(config, descriptor, interaction, legacyCredential = false) {
|
|
624
|
+
if (descriptor.local || config.provider === "faux" || ["ollama", "lm-studio", "llama.cpp"].includes(config.provider)) {
|
|
625
|
+
const local = { ...config, authMode: "local" };
|
|
626
|
+
delete local.apiKeyEnv;
|
|
627
|
+
return local;
|
|
628
|
+
}
|
|
629
|
+
const authFile = config.authFile ?? defaultAuthFile();
|
|
630
|
+
const stored = await new JsonCredentialStore(authFile).read(config.provider);
|
|
631
|
+
if (stored) {
|
|
632
|
+
const saved = { ...config, authFile, authMode: stored.type === "oauth" ? "oauth" : "stored-key" };
|
|
633
|
+
delete saved.apiKeyEnv;
|
|
634
|
+
return saved;
|
|
635
|
+
}
|
|
636
|
+
if (environmentAuthenticationAvailable(config))
|
|
637
|
+
return { ...config, authFile, authMode: "environment", apiKeyEnv: config.apiKeyEnv ?? defaultApiKeyEnv(config.provider) };
|
|
638
|
+
const auth = await configureAuthentication(config.provider, descriptor, authFile, interaction, legacyCredential, false, true);
|
|
639
|
+
if (auth === "back")
|
|
640
|
+
return "back";
|
|
641
|
+
const next = { ...config, ...auth, authFile };
|
|
642
|
+
if (auth.authMode !== "environment")
|
|
643
|
+
delete next.apiKeyEnv;
|
|
644
|
+
if (next.authMode === "environment" && !environmentAuthenticationAvailable(next))
|
|
645
|
+
throw new Error(`Environment variable ${next.apiKeyEnv ?? defaultApiKeyEnv(next.provider)} is not set. Set it first or choose \u201CPaste an API key\u201D.`);
|
|
646
|
+
return next;
|
|
647
|
+
}
|
|
648
|
+
function environmentAuthenticationAvailable(config) {
|
|
649
|
+
const key = config.api ? "GOAH_PI_API_KEY" : defaultApiKeyEnv(config.provider);
|
|
650
|
+
try {
|
|
651
|
+
return Boolean(resolveEnvSpec(piEnvironment(config), { root: process.cwd() })[key]);
|
|
652
|
+
} catch {
|
|
653
|
+
return false;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
623
656
|
async function doctorPi(value, context) {
|
|
624
657
|
const config = piConfig(value);
|
|
625
658
|
const env = resolveEnvSpec(piEnvironment(config), { root: context?.root ?? process.cwd() });
|
|
@@ -688,7 +721,11 @@ async function runPiCommand(command, args, value, interaction) {
|
|
|
688
721
|
const existing = provider === config.provider || provider === "faux" || ["ollama", "lm-studio", "llama.cpp"].includes(provider) ? void 0 : await new JsonCredentialStore(config.authFile ?? defaultAuthFile()).read(provider);
|
|
689
722
|
const next = provider === config.provider ? { ...config, model } : { provider, model, thinking: config.thinking ?? (provider === "faux" ? "off" : "medium"), authFile: config.authFile ?? defaultAuthFile(), authMode: provider === "faux" || ["ollama", "lm-studio", "llama.cpp"].includes(provider) ? "local" : existing?.type === "oauth" ? "oauth" : existing ? "stored-key" : "unconfigured" };
|
|
690
723
|
createPiModel(provider, model, piEnvironment(next));
|
|
691
|
-
|
|
724
|
+
const descriptor = providerCatalog().find((entry) => entry.id === provider) ?? { id: provider, name: provider, oauth: false, apiKey: true, local: false, modelCount: 0 };
|
|
725
|
+
const authenticated = await requireAuthentication(next, descriptor, interaction);
|
|
726
|
+
if (authenticated === "back")
|
|
727
|
+
return { output: ["No change."] };
|
|
728
|
+
return { config: authenticated, output: [`Pi target changed to ${provider}/${model}`] };
|
|
692
729
|
}
|
|
693
730
|
if (command === "auth") {
|
|
694
731
|
const authFile = config.authFile ?? defaultAuthFile();
|
|
@@ -3,7 +3,7 @@ const require = __goahCreateRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
createPiProcessRunner,
|
|
5
5
|
piRunnerConfigurator
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7E7V6OIU.js";
|
|
7
7
|
|
|
8
8
|
// node_modules/.dist-original/runner-registry.js
|
|
9
9
|
var plugins = /* @__PURE__ */ new Map([
|
|
@@ -2,7 +2,7 @@ import { createRequire as __goahCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __goahCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
runnerPlugin
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-D2DVAH37.js";
|
|
6
6
|
import {
|
|
7
7
|
SQLITE_SCHEMA_VERSION,
|
|
8
8
|
SqliteLedger
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
ProcessRunner,
|
|
17
17
|
piWorkerPath,
|
|
18
18
|
resolveEnvSpec
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7E7V6OIU.js";
|
|
20
20
|
import {
|
|
21
21
|
createPiModel
|
|
22
22
|
} from "./chunk-6M3OOCKO.js";
|
package/dist/cli.js
CHANGED
|
@@ -25,14 +25,14 @@ import {
|
|
|
25
25
|
streamEvents,
|
|
26
26
|
updateWorkspaceRunnerProfile,
|
|
27
27
|
writeDefaultConfig
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-KJ4HJCTK.js";
|
|
29
29
|
import {
|
|
30
30
|
runnerManifests,
|
|
31
31
|
runnerPlugin
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-D2DVAH37.js";
|
|
33
33
|
import "./chunk-YH6YJ2IB.js";
|
|
34
34
|
import "./chunk-QBD6EJ2Z.js";
|
|
35
|
-
import "./chunk-
|
|
35
|
+
import "./chunk-7E7V6OIU.js";
|
|
36
36
|
import "./chunk-6M3OOCKO.js";
|
|
37
37
|
import "./chunk-K26BVR6O.js";
|
|
38
38
|
import "./chunk-IIJQ3DW4.js";
|
|
@@ -50,9 +50,9 @@ import {
|
|
|
50
50
|
import "./chunk-XPQKM3L7.js";
|
|
51
51
|
|
|
52
52
|
// node_modules/.dist-original/cli.js
|
|
53
|
-
import { spawn as
|
|
53
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
54
54
|
import { closeSync as closeSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
55
|
-
import { join as
|
|
55
|
+
import { join as join7, resolve as resolve3 } from "node:path";
|
|
56
56
|
|
|
57
57
|
// ../../node_modules/marked/lib/marked.esm.js
|
|
58
58
|
function M() {
|
|
@@ -1293,6 +1293,12 @@ var Xt = g.parseInline;
|
|
|
1293
1293
|
var Vt = b.parse;
|
|
1294
1294
|
var Yt = x.lex;
|
|
1295
1295
|
|
|
1296
|
+
// ../../node_modules/@earendil-works/pi-tui/dist/autocomplete.js
|
|
1297
|
+
import { spawn } from "child_process";
|
|
1298
|
+
import { readdirSync, statSync } from "fs";
|
|
1299
|
+
import { homedir } from "os";
|
|
1300
|
+
import { basename, dirname, join } from "path";
|
|
1301
|
+
|
|
1296
1302
|
// ../../node_modules/@earendil-works/pi-tui/dist/fuzzy.js
|
|
1297
1303
|
function fuzzyMatch(query, text) {
|
|
1298
1304
|
const queryLower = query.toLowerCase();
|
|
@@ -1382,6 +1388,568 @@ function fuzzyFilter(items, query, getText) {
|
|
|
1382
1388
|
return results.map((r) => r.item);
|
|
1383
1389
|
}
|
|
1384
1390
|
|
|
1391
|
+
// ../../node_modules/@earendil-works/pi-tui/dist/autocomplete.js
|
|
1392
|
+
var PATH_DELIMITERS = /* @__PURE__ */ new Set([" ", " ", '"', "'", "="]);
|
|
1393
|
+
function toDisplayPath(value) {
|
|
1394
|
+
return value.replace(/\\/g, "/");
|
|
1395
|
+
}
|
|
1396
|
+
function escapeRegex(value) {
|
|
1397
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1398
|
+
}
|
|
1399
|
+
function buildFdPathQuery(query) {
|
|
1400
|
+
const normalized = toDisplayPath(query);
|
|
1401
|
+
if (!normalized.includes("/")) {
|
|
1402
|
+
return normalized;
|
|
1403
|
+
}
|
|
1404
|
+
const hasTrailingSeparator = normalized.endsWith("/");
|
|
1405
|
+
const trimmed = normalized.replace(/^\/+|\/+$/g, "");
|
|
1406
|
+
if (!trimmed) {
|
|
1407
|
+
return normalized;
|
|
1408
|
+
}
|
|
1409
|
+
const separatorPattern = "[\\\\/]";
|
|
1410
|
+
const segments = trimmed.split("/").filter(Boolean).map((segment) => escapeRegex(segment));
|
|
1411
|
+
if (segments.length === 0) {
|
|
1412
|
+
return normalized;
|
|
1413
|
+
}
|
|
1414
|
+
let pattern = segments.join(separatorPattern);
|
|
1415
|
+
if (hasTrailingSeparator) {
|
|
1416
|
+
pattern += separatorPattern;
|
|
1417
|
+
}
|
|
1418
|
+
return pattern;
|
|
1419
|
+
}
|
|
1420
|
+
function findLastDelimiter(text) {
|
|
1421
|
+
for (let i = text.length - 1; i >= 0; i -= 1) {
|
|
1422
|
+
if (PATH_DELIMITERS.has(text[i] ?? "")) {
|
|
1423
|
+
return i;
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
return -1;
|
|
1427
|
+
}
|
|
1428
|
+
function findUnclosedQuoteStart(text) {
|
|
1429
|
+
let inQuotes = false;
|
|
1430
|
+
let quoteStart = -1;
|
|
1431
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
1432
|
+
if (text[i] === '"') {
|
|
1433
|
+
inQuotes = !inQuotes;
|
|
1434
|
+
if (inQuotes) {
|
|
1435
|
+
quoteStart = i;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
return inQuotes ? quoteStart : null;
|
|
1440
|
+
}
|
|
1441
|
+
function isTokenStart(text, index) {
|
|
1442
|
+
return index === 0 || PATH_DELIMITERS.has(text[index - 1] ?? "");
|
|
1443
|
+
}
|
|
1444
|
+
function extractQuotedPrefix(text) {
|
|
1445
|
+
const quoteStart = findUnclosedQuoteStart(text);
|
|
1446
|
+
if (quoteStart === null) {
|
|
1447
|
+
return null;
|
|
1448
|
+
}
|
|
1449
|
+
if (quoteStart > 0 && text[quoteStart - 1] === "@") {
|
|
1450
|
+
if (!isTokenStart(text, quoteStart - 1)) {
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
return text.slice(quoteStart - 1);
|
|
1454
|
+
}
|
|
1455
|
+
if (!isTokenStart(text, quoteStart)) {
|
|
1456
|
+
return null;
|
|
1457
|
+
}
|
|
1458
|
+
return text.slice(quoteStart);
|
|
1459
|
+
}
|
|
1460
|
+
function parsePathPrefix(prefix) {
|
|
1461
|
+
if (prefix.startsWith('@"')) {
|
|
1462
|
+
return { rawPrefix: prefix.slice(2), isAtPrefix: true, isQuotedPrefix: true };
|
|
1463
|
+
}
|
|
1464
|
+
if (prefix.startsWith('"')) {
|
|
1465
|
+
return { rawPrefix: prefix.slice(1), isAtPrefix: false, isQuotedPrefix: true };
|
|
1466
|
+
}
|
|
1467
|
+
if (prefix.startsWith("@")) {
|
|
1468
|
+
return { rawPrefix: prefix.slice(1), isAtPrefix: true, isQuotedPrefix: false };
|
|
1469
|
+
}
|
|
1470
|
+
return { rawPrefix: prefix, isAtPrefix: false, isQuotedPrefix: false };
|
|
1471
|
+
}
|
|
1472
|
+
function buildCompletionValue(path4, options) {
|
|
1473
|
+
const needsQuotes = options.isQuotedPrefix || path4.includes(" ");
|
|
1474
|
+
const prefix = options.isAtPrefix ? "@" : "";
|
|
1475
|
+
if (!needsQuotes) {
|
|
1476
|
+
return `${prefix}${path4}`;
|
|
1477
|
+
}
|
|
1478
|
+
const openQuote = `${prefix}"`;
|
|
1479
|
+
const closeQuote = '"';
|
|
1480
|
+
return `${openQuote}${path4}${closeQuote}`;
|
|
1481
|
+
}
|
|
1482
|
+
async function walkDirectoryWithFd(baseDir, fdPath, query, maxResults, signal) {
|
|
1483
|
+
const args2 = [
|
|
1484
|
+
"--base-directory",
|
|
1485
|
+
baseDir,
|
|
1486
|
+
"--max-results",
|
|
1487
|
+
String(maxResults),
|
|
1488
|
+
"--type",
|
|
1489
|
+
"f",
|
|
1490
|
+
"--type",
|
|
1491
|
+
"d",
|
|
1492
|
+
"--follow",
|
|
1493
|
+
"--hidden",
|
|
1494
|
+
"--exclude",
|
|
1495
|
+
".git",
|
|
1496
|
+
"--exclude",
|
|
1497
|
+
".git/*",
|
|
1498
|
+
"--exclude",
|
|
1499
|
+
".git/**"
|
|
1500
|
+
];
|
|
1501
|
+
if (toDisplayPath(query).includes("/")) {
|
|
1502
|
+
args2.push("--full-path");
|
|
1503
|
+
}
|
|
1504
|
+
if (query) {
|
|
1505
|
+
args2.push(buildFdPathQuery(query));
|
|
1506
|
+
}
|
|
1507
|
+
return await new Promise((resolve4) => {
|
|
1508
|
+
if (signal.aborted) {
|
|
1509
|
+
resolve4([]);
|
|
1510
|
+
return;
|
|
1511
|
+
}
|
|
1512
|
+
const child = spawn(fdPath, args2, {
|
|
1513
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
1514
|
+
});
|
|
1515
|
+
let stdout = "";
|
|
1516
|
+
let resolved = false;
|
|
1517
|
+
const finish = (results) => {
|
|
1518
|
+
if (resolved)
|
|
1519
|
+
return;
|
|
1520
|
+
resolved = true;
|
|
1521
|
+
signal.removeEventListener("abort", onAbort);
|
|
1522
|
+
resolve4(results);
|
|
1523
|
+
};
|
|
1524
|
+
const onAbort = () => {
|
|
1525
|
+
if (child.exitCode === null) {
|
|
1526
|
+
child.kill("SIGKILL");
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
1530
|
+
child.stdout.setEncoding("utf-8");
|
|
1531
|
+
child.stdout.on("data", (chunk) => {
|
|
1532
|
+
stdout += chunk;
|
|
1533
|
+
});
|
|
1534
|
+
child.on("error", () => {
|
|
1535
|
+
finish([]);
|
|
1536
|
+
});
|
|
1537
|
+
child.on("close", (code) => {
|
|
1538
|
+
if (signal.aborted || code !== 0 || !stdout) {
|
|
1539
|
+
finish([]);
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
const lines = stdout.trim().split("\n").filter(Boolean);
|
|
1543
|
+
const results = [];
|
|
1544
|
+
for (const line of lines) {
|
|
1545
|
+
const displayLine = toDisplayPath(line);
|
|
1546
|
+
const hasTrailingSeparator = displayLine.endsWith("/");
|
|
1547
|
+
const normalizedPath = hasTrailingSeparator ? displayLine.slice(0, -1) : displayLine;
|
|
1548
|
+
if (normalizedPath === ".git" || normalizedPath.startsWith(".git/") || normalizedPath.includes("/.git/")) {
|
|
1549
|
+
continue;
|
|
1550
|
+
}
|
|
1551
|
+
results.push({
|
|
1552
|
+
path: displayLine,
|
|
1553
|
+
isDirectory: hasTrailingSeparator
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
finish(results);
|
|
1557
|
+
});
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
var CombinedAutocompleteProvider = class {
|
|
1561
|
+
commands;
|
|
1562
|
+
basePath;
|
|
1563
|
+
fdPath;
|
|
1564
|
+
constructor(commands = [], basePath, fdPath = null) {
|
|
1565
|
+
this.commands = commands;
|
|
1566
|
+
this.basePath = basePath;
|
|
1567
|
+
this.fdPath = fdPath;
|
|
1568
|
+
}
|
|
1569
|
+
async getSuggestions(lines, cursorLine, cursorCol, options) {
|
|
1570
|
+
const currentLine = lines[cursorLine] || "";
|
|
1571
|
+
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
1572
|
+
const atPrefix = this.extractAtPrefix(textBeforeCursor);
|
|
1573
|
+
if (atPrefix) {
|
|
1574
|
+
const { rawPrefix, isQuotedPrefix } = parsePathPrefix(atPrefix);
|
|
1575
|
+
const suggestions2 = await this.getFuzzyFileSuggestions(rawPrefix, {
|
|
1576
|
+
isQuotedPrefix,
|
|
1577
|
+
signal: options.signal
|
|
1578
|
+
});
|
|
1579
|
+
if (suggestions2.length === 0)
|
|
1580
|
+
return null;
|
|
1581
|
+
return {
|
|
1582
|
+
items: suggestions2,
|
|
1583
|
+
prefix: atPrefix
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
if (!options.force && textBeforeCursor.startsWith("/")) {
|
|
1587
|
+
const spaceIndex = textBeforeCursor.indexOf(" ");
|
|
1588
|
+
if (spaceIndex === -1) {
|
|
1589
|
+
const prefix = textBeforeCursor.slice(1);
|
|
1590
|
+
const commandItems = this.commands.map((cmd) => {
|
|
1591
|
+
const name = "name" in cmd ? cmd.name : cmd.value;
|
|
1592
|
+
const hint = "argumentHint" in cmd && cmd.argumentHint ? cmd.argumentHint : void 0;
|
|
1593
|
+
const desc = cmd.description ?? "";
|
|
1594
|
+
const fullDesc = hint ? desc ? `${hint} \u2014 ${desc}` : hint : desc;
|
|
1595
|
+
return {
|
|
1596
|
+
name,
|
|
1597
|
+
label: name,
|
|
1598
|
+
description: fullDesc || void 0
|
|
1599
|
+
};
|
|
1600
|
+
});
|
|
1601
|
+
const filtered = fuzzyFilter(commandItems, prefix, (item) => item.name).map((item) => ({
|
|
1602
|
+
value: item.name,
|
|
1603
|
+
label: item.label,
|
|
1604
|
+
...item.description && { description: item.description }
|
|
1605
|
+
}));
|
|
1606
|
+
if (filtered.length === 0)
|
|
1607
|
+
return null;
|
|
1608
|
+
return {
|
|
1609
|
+
items: filtered,
|
|
1610
|
+
prefix: textBeforeCursor
|
|
1611
|
+
};
|
|
1612
|
+
}
|
|
1613
|
+
const commandName = textBeforeCursor.slice(1, spaceIndex);
|
|
1614
|
+
const argumentText = textBeforeCursor.slice(spaceIndex + 1);
|
|
1615
|
+
const command = this.commands.find((cmd) => {
|
|
1616
|
+
const name = "name" in cmd ? cmd.name : cmd.value;
|
|
1617
|
+
return name === commandName;
|
|
1618
|
+
});
|
|
1619
|
+
if (!command || !("getArgumentCompletions" in command) || !command.getArgumentCompletions) {
|
|
1620
|
+
return null;
|
|
1621
|
+
}
|
|
1622
|
+
const argumentSuggestions = await command.getArgumentCompletions(argumentText);
|
|
1623
|
+
if (!Array.isArray(argumentSuggestions) || argumentSuggestions.length === 0) {
|
|
1624
|
+
return null;
|
|
1625
|
+
}
|
|
1626
|
+
return {
|
|
1627
|
+
items: argumentSuggestions,
|
|
1628
|
+
prefix: argumentText
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1631
|
+
const pathMatch = this.extractPathPrefix(textBeforeCursor, options.force ?? false);
|
|
1632
|
+
if (pathMatch === null) {
|
|
1633
|
+
return null;
|
|
1634
|
+
}
|
|
1635
|
+
const suggestions = this.getFileSuggestions(pathMatch);
|
|
1636
|
+
if (suggestions.length === 0)
|
|
1637
|
+
return null;
|
|
1638
|
+
return {
|
|
1639
|
+
items: suggestions,
|
|
1640
|
+
prefix: pathMatch
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
|
|
1644
|
+
const currentLine = lines[cursorLine] || "";
|
|
1645
|
+
const beforePrefix = currentLine.slice(0, cursorCol - prefix.length);
|
|
1646
|
+
const afterCursor = currentLine.slice(cursorCol);
|
|
1647
|
+
const isQuotedPrefix = prefix.startsWith('"') || prefix.startsWith('@"');
|
|
1648
|
+
const hasLeadingQuoteAfterCursor = afterCursor.startsWith('"');
|
|
1649
|
+
const hasTrailingQuoteInItem = item.value.endsWith('"');
|
|
1650
|
+
const adjustedAfterCursor = isQuotedPrefix && hasTrailingQuoteInItem && hasLeadingQuoteAfterCursor ? afterCursor.slice(1) : afterCursor;
|
|
1651
|
+
const isSlashCommand = prefix.startsWith("/") && beforePrefix.trim() === "" && !prefix.slice(1).includes("/");
|
|
1652
|
+
if (isSlashCommand) {
|
|
1653
|
+
const newLine2 = `${beforePrefix}/${item.value} ${adjustedAfterCursor}`;
|
|
1654
|
+
const newLines2 = [...lines];
|
|
1655
|
+
newLines2[cursorLine] = newLine2;
|
|
1656
|
+
return {
|
|
1657
|
+
lines: newLines2,
|
|
1658
|
+
cursorLine,
|
|
1659
|
+
cursorCol: beforePrefix.length + item.value.length + 2
|
|
1660
|
+
// +2 for "/" and space
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
if (prefix.startsWith("@")) {
|
|
1664
|
+
const isDirectory2 = item.label.endsWith("/");
|
|
1665
|
+
const suffix = isDirectory2 ? "" : " ";
|
|
1666
|
+
const newLine2 = `${beforePrefix + item.value}${suffix}${adjustedAfterCursor}`;
|
|
1667
|
+
const newLines2 = [...lines];
|
|
1668
|
+
newLines2[cursorLine] = newLine2;
|
|
1669
|
+
const hasTrailingQuote2 = item.value.endsWith('"');
|
|
1670
|
+
const cursorOffset2 = isDirectory2 && hasTrailingQuote2 ? item.value.length - 1 : item.value.length;
|
|
1671
|
+
return {
|
|
1672
|
+
lines: newLines2,
|
|
1673
|
+
cursorLine,
|
|
1674
|
+
cursorCol: beforePrefix.length + cursorOffset2 + suffix.length
|
|
1675
|
+
};
|
|
1676
|
+
}
|
|
1677
|
+
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
1678
|
+
if (textBeforeCursor.includes("/") && textBeforeCursor.includes(" ")) {
|
|
1679
|
+
const newLine2 = beforePrefix + item.value + adjustedAfterCursor;
|
|
1680
|
+
const newLines2 = [...lines];
|
|
1681
|
+
newLines2[cursorLine] = newLine2;
|
|
1682
|
+
const isDirectory2 = item.label.endsWith("/");
|
|
1683
|
+
const hasTrailingQuote2 = item.value.endsWith('"');
|
|
1684
|
+
const cursorOffset2 = isDirectory2 && hasTrailingQuote2 ? item.value.length - 1 : item.value.length;
|
|
1685
|
+
return {
|
|
1686
|
+
lines: newLines2,
|
|
1687
|
+
cursorLine,
|
|
1688
|
+
cursorCol: beforePrefix.length + cursorOffset2
|
|
1689
|
+
};
|
|
1690
|
+
}
|
|
1691
|
+
const newLine = beforePrefix + item.value + adjustedAfterCursor;
|
|
1692
|
+
const newLines = [...lines];
|
|
1693
|
+
newLines[cursorLine] = newLine;
|
|
1694
|
+
const isDirectory = item.label.endsWith("/");
|
|
1695
|
+
const hasTrailingQuote = item.value.endsWith('"');
|
|
1696
|
+
const cursorOffset = isDirectory && hasTrailingQuote ? item.value.length - 1 : item.value.length;
|
|
1697
|
+
return {
|
|
1698
|
+
lines: newLines,
|
|
1699
|
+
cursorLine,
|
|
1700
|
+
cursorCol: beforePrefix.length + cursorOffset
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
// Extract @ prefix for fuzzy file suggestions
|
|
1704
|
+
extractAtPrefix(text) {
|
|
1705
|
+
const quotedPrefix = extractQuotedPrefix(text);
|
|
1706
|
+
if (quotedPrefix?.startsWith('@"')) {
|
|
1707
|
+
return quotedPrefix;
|
|
1708
|
+
}
|
|
1709
|
+
const lastDelimiterIndex = findLastDelimiter(text);
|
|
1710
|
+
const tokenStart = lastDelimiterIndex === -1 ? 0 : lastDelimiterIndex + 1;
|
|
1711
|
+
if (text[tokenStart] === "@") {
|
|
1712
|
+
return text.slice(tokenStart);
|
|
1713
|
+
}
|
|
1714
|
+
return null;
|
|
1715
|
+
}
|
|
1716
|
+
// Extract a path-like prefix from the text before cursor
|
|
1717
|
+
extractPathPrefix(text, forceExtract = false) {
|
|
1718
|
+
const quotedPrefix = extractQuotedPrefix(text);
|
|
1719
|
+
if (quotedPrefix) {
|
|
1720
|
+
return quotedPrefix;
|
|
1721
|
+
}
|
|
1722
|
+
const lastDelimiterIndex = findLastDelimiter(text);
|
|
1723
|
+
const pathPrefix = lastDelimiterIndex === -1 ? text : text.slice(lastDelimiterIndex + 1);
|
|
1724
|
+
if (forceExtract) {
|
|
1725
|
+
return pathPrefix;
|
|
1726
|
+
}
|
|
1727
|
+
if (pathPrefix.includes("/") || pathPrefix.startsWith(".") || pathPrefix.startsWith("~/")) {
|
|
1728
|
+
return pathPrefix;
|
|
1729
|
+
}
|
|
1730
|
+
if (pathPrefix === "" && text.endsWith(" ")) {
|
|
1731
|
+
return pathPrefix;
|
|
1732
|
+
}
|
|
1733
|
+
return null;
|
|
1734
|
+
}
|
|
1735
|
+
// Expand home directory (~/) to actual home path
|
|
1736
|
+
expandHomePath(path4) {
|
|
1737
|
+
if (path4.startsWith("~/")) {
|
|
1738
|
+
const expandedPath = join(homedir(), path4.slice(2));
|
|
1739
|
+
return path4.endsWith("/") && !expandedPath.endsWith("/") ? `${expandedPath}/` : expandedPath;
|
|
1740
|
+
} else if (path4 === "~") {
|
|
1741
|
+
return homedir();
|
|
1742
|
+
}
|
|
1743
|
+
return path4;
|
|
1744
|
+
}
|
|
1745
|
+
resolveScopedFuzzyQuery(rawQuery) {
|
|
1746
|
+
const normalizedQuery = toDisplayPath(rawQuery);
|
|
1747
|
+
const slashIndex = normalizedQuery.lastIndexOf("/");
|
|
1748
|
+
if (slashIndex === -1) {
|
|
1749
|
+
return null;
|
|
1750
|
+
}
|
|
1751
|
+
const displayBase = normalizedQuery.slice(0, slashIndex + 1);
|
|
1752
|
+
const query = normalizedQuery.slice(slashIndex + 1);
|
|
1753
|
+
let baseDir;
|
|
1754
|
+
if (displayBase.startsWith("~/")) {
|
|
1755
|
+
baseDir = this.expandHomePath(displayBase);
|
|
1756
|
+
} else if (displayBase.startsWith("/")) {
|
|
1757
|
+
baseDir = displayBase;
|
|
1758
|
+
} else {
|
|
1759
|
+
baseDir = join(this.basePath, displayBase);
|
|
1760
|
+
}
|
|
1761
|
+
try {
|
|
1762
|
+
if (!statSync(baseDir).isDirectory()) {
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
} catch {
|
|
1766
|
+
return null;
|
|
1767
|
+
}
|
|
1768
|
+
return { baseDir, query, displayBase };
|
|
1769
|
+
}
|
|
1770
|
+
scopedPathForDisplay(displayBase, relativePath) {
|
|
1771
|
+
const normalizedRelativePath = toDisplayPath(relativePath);
|
|
1772
|
+
if (displayBase === "/") {
|
|
1773
|
+
return `/${normalizedRelativePath}`;
|
|
1774
|
+
}
|
|
1775
|
+
return `${toDisplayPath(displayBase)}${normalizedRelativePath}`;
|
|
1776
|
+
}
|
|
1777
|
+
// Get file/directory suggestions for a given path prefix
|
|
1778
|
+
getFileSuggestions(prefix) {
|
|
1779
|
+
try {
|
|
1780
|
+
let searchDir;
|
|
1781
|
+
let searchPrefix;
|
|
1782
|
+
const { rawPrefix, isAtPrefix, isQuotedPrefix } = parsePathPrefix(prefix);
|
|
1783
|
+
let expandedPrefix = rawPrefix;
|
|
1784
|
+
if (expandedPrefix.startsWith("~")) {
|
|
1785
|
+
expandedPrefix = this.expandHomePath(expandedPrefix);
|
|
1786
|
+
}
|
|
1787
|
+
const isRootPrefix = rawPrefix === "" || rawPrefix === "./" || rawPrefix === "../" || rawPrefix === "~" || rawPrefix === "~/" || rawPrefix === "/" || isAtPrefix && rawPrefix === "";
|
|
1788
|
+
if (isRootPrefix) {
|
|
1789
|
+
if (rawPrefix.startsWith("~") || expandedPrefix.startsWith("/")) {
|
|
1790
|
+
searchDir = expandedPrefix;
|
|
1791
|
+
} else {
|
|
1792
|
+
searchDir = join(this.basePath, expandedPrefix);
|
|
1793
|
+
}
|
|
1794
|
+
searchPrefix = "";
|
|
1795
|
+
} else if (rawPrefix.endsWith("/")) {
|
|
1796
|
+
if (rawPrefix.startsWith("~") || expandedPrefix.startsWith("/")) {
|
|
1797
|
+
searchDir = expandedPrefix;
|
|
1798
|
+
} else {
|
|
1799
|
+
searchDir = join(this.basePath, expandedPrefix);
|
|
1800
|
+
}
|
|
1801
|
+
searchPrefix = "";
|
|
1802
|
+
} else {
|
|
1803
|
+
const dir = dirname(expandedPrefix);
|
|
1804
|
+
const file = basename(expandedPrefix);
|
|
1805
|
+
if (rawPrefix.startsWith("~") || expandedPrefix.startsWith("/")) {
|
|
1806
|
+
searchDir = dir;
|
|
1807
|
+
} else {
|
|
1808
|
+
searchDir = join(this.basePath, dir);
|
|
1809
|
+
}
|
|
1810
|
+
searchPrefix = file;
|
|
1811
|
+
}
|
|
1812
|
+
const entries = readdirSync(searchDir, { withFileTypes: true });
|
|
1813
|
+
const suggestions = [];
|
|
1814
|
+
for (const entry of entries) {
|
|
1815
|
+
if (!entry.name.toLowerCase().startsWith(searchPrefix.toLowerCase())) {
|
|
1816
|
+
continue;
|
|
1817
|
+
}
|
|
1818
|
+
let isDirectory = entry.isDirectory();
|
|
1819
|
+
if (!isDirectory && entry.isSymbolicLink()) {
|
|
1820
|
+
try {
|
|
1821
|
+
const fullPath = join(searchDir, entry.name);
|
|
1822
|
+
isDirectory = statSync(fullPath).isDirectory();
|
|
1823
|
+
} catch {
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
let relativePath;
|
|
1827
|
+
const name = entry.name;
|
|
1828
|
+
const displayPrefix = rawPrefix;
|
|
1829
|
+
if (displayPrefix.endsWith("/")) {
|
|
1830
|
+
relativePath = displayPrefix + name;
|
|
1831
|
+
} else if (displayPrefix.includes("/") || displayPrefix.includes("\\")) {
|
|
1832
|
+
if (displayPrefix.startsWith("~/")) {
|
|
1833
|
+
const homeRelativeDir = displayPrefix.slice(2);
|
|
1834
|
+
const dir = dirname(homeRelativeDir);
|
|
1835
|
+
relativePath = `~/${dir === "." ? name : join(dir, name)}`;
|
|
1836
|
+
} else if (displayPrefix.startsWith("/")) {
|
|
1837
|
+
const dir = dirname(displayPrefix);
|
|
1838
|
+
if (dir === "/") {
|
|
1839
|
+
relativePath = `/${name}`;
|
|
1840
|
+
} else {
|
|
1841
|
+
relativePath = `${dir}/${name}`;
|
|
1842
|
+
}
|
|
1843
|
+
} else {
|
|
1844
|
+
relativePath = join(dirname(displayPrefix), name);
|
|
1845
|
+
if (displayPrefix.startsWith("./") && !relativePath.startsWith("./")) {
|
|
1846
|
+
relativePath = `./${relativePath}`;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
} else {
|
|
1850
|
+
if (displayPrefix.startsWith("~")) {
|
|
1851
|
+
relativePath = `~/${name}`;
|
|
1852
|
+
} else {
|
|
1853
|
+
relativePath = name;
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
relativePath = toDisplayPath(relativePath);
|
|
1857
|
+
const pathValue = isDirectory ? `${relativePath}/` : relativePath;
|
|
1858
|
+
const value = buildCompletionValue(pathValue, {
|
|
1859
|
+
isDirectory,
|
|
1860
|
+
isAtPrefix,
|
|
1861
|
+
isQuotedPrefix
|
|
1862
|
+
});
|
|
1863
|
+
suggestions.push({
|
|
1864
|
+
value,
|
|
1865
|
+
label: name + (isDirectory ? "/" : "")
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
suggestions.sort((a, b2) => {
|
|
1869
|
+
const aIsDir = a.value.endsWith("/");
|
|
1870
|
+
const bIsDir = b2.value.endsWith("/");
|
|
1871
|
+
if (aIsDir && !bIsDir)
|
|
1872
|
+
return -1;
|
|
1873
|
+
if (!aIsDir && bIsDir)
|
|
1874
|
+
return 1;
|
|
1875
|
+
return a.label.localeCompare(b2.label);
|
|
1876
|
+
});
|
|
1877
|
+
return suggestions;
|
|
1878
|
+
} catch (_e2) {
|
|
1879
|
+
return [];
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
// Score an entry against the query (higher = better match)
|
|
1883
|
+
// isDirectory adds bonus to prioritize folders
|
|
1884
|
+
scoreEntry(filePath, query, isDirectory) {
|
|
1885
|
+
const fileName = basename(filePath);
|
|
1886
|
+
const lowerFileName = fileName.toLowerCase();
|
|
1887
|
+
const lowerQuery = query.toLowerCase();
|
|
1888
|
+
let score = 0;
|
|
1889
|
+
if (lowerFileName === lowerQuery)
|
|
1890
|
+
score = 100;
|
|
1891
|
+
else if (lowerFileName.startsWith(lowerQuery))
|
|
1892
|
+
score = 80;
|
|
1893
|
+
else if (lowerFileName.includes(lowerQuery))
|
|
1894
|
+
score = 50;
|
|
1895
|
+
else if (filePath.toLowerCase().includes(lowerQuery))
|
|
1896
|
+
score = 30;
|
|
1897
|
+
if (isDirectory && score > 0)
|
|
1898
|
+
score += 10;
|
|
1899
|
+
return score;
|
|
1900
|
+
}
|
|
1901
|
+
// Fuzzy file search using fd (fast, respects .gitignore)
|
|
1902
|
+
async getFuzzyFileSuggestions(query, options) {
|
|
1903
|
+
if (!this.fdPath || options.signal.aborted) {
|
|
1904
|
+
return [];
|
|
1905
|
+
}
|
|
1906
|
+
try {
|
|
1907
|
+
const scopedQuery = this.resolveScopedFuzzyQuery(query);
|
|
1908
|
+
const fdBaseDir = scopedQuery?.baseDir ?? this.basePath;
|
|
1909
|
+
const fdQuery = scopedQuery?.query ?? query;
|
|
1910
|
+
const entries = await walkDirectoryWithFd(fdBaseDir, this.fdPath, fdQuery, 100, options.signal);
|
|
1911
|
+
if (options.signal.aborted) {
|
|
1912
|
+
return [];
|
|
1913
|
+
}
|
|
1914
|
+
const scoredEntries = entries.map((entry) => ({
|
|
1915
|
+
...entry,
|
|
1916
|
+
score: fdQuery ? this.scoreEntry(entry.path, fdQuery, entry.isDirectory) : 1
|
|
1917
|
+
})).filter((entry) => entry.score > 0);
|
|
1918
|
+
scoredEntries.sort((a, b2) => b2.score - a.score);
|
|
1919
|
+
const topEntries = scoredEntries.slice(0, 20);
|
|
1920
|
+
const suggestions = [];
|
|
1921
|
+
for (const { path: entryPath, isDirectory } of topEntries) {
|
|
1922
|
+
const pathWithoutSlash = isDirectory ? entryPath.slice(0, -1) : entryPath;
|
|
1923
|
+
const displayPath = scopedQuery ? this.scopedPathForDisplay(scopedQuery.displayBase, pathWithoutSlash) : pathWithoutSlash;
|
|
1924
|
+
const entryName = basename(pathWithoutSlash);
|
|
1925
|
+
const completionPath = isDirectory ? `${displayPath}/` : displayPath;
|
|
1926
|
+
const value = buildCompletionValue(completionPath, {
|
|
1927
|
+
isDirectory,
|
|
1928
|
+
isAtPrefix: true,
|
|
1929
|
+
isQuotedPrefix: options.isQuotedPrefix
|
|
1930
|
+
});
|
|
1931
|
+
suggestions.push({
|
|
1932
|
+
value,
|
|
1933
|
+
label: entryName + (isDirectory ? "/" : ""),
|
|
1934
|
+
description: displayPath
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
return suggestions;
|
|
1938
|
+
} catch {
|
|
1939
|
+
return [];
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
// Check if we should trigger file completion (called on Tab key)
|
|
1943
|
+
shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
|
|
1944
|
+
const currentLine = lines[cursorLine] || "";
|
|
1945
|
+
const textBeforeCursor = currentLine.slice(0, cursorCol);
|
|
1946
|
+
if (textBeforeCursor.trim().startsWith("/") && !textBeforeCursor.trim().includes(" ")) {
|
|
1947
|
+
return false;
|
|
1948
|
+
}
|
|
1949
|
+
return true;
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
|
|
1385
1953
|
// ../../node_modules/get-east-asian-width/lookup-data.js
|
|
1386
1954
|
var ambiguousMinimalCodePoint = 161;
|
|
1387
1955
|
var ambiguousMaximumCodePoint = 1114109;
|
|
@@ -11260,7 +11828,7 @@ async function reloadDaemon(stateDir, configPath) {
|
|
|
11260
11828
|
// node_modules/.dist-original/welcome.js
|
|
11261
11829
|
import { DatabaseSync } from "node:sqlite";
|
|
11262
11830
|
import { existsSync } from "node:fs";
|
|
11263
|
-
import { join as
|
|
11831
|
+
import { join as join5 } from "node:path";
|
|
11264
11832
|
|
|
11265
11833
|
// node_modules/.dist-original/tui-theme.js
|
|
11266
11834
|
var enabled = !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
@@ -11273,8 +11841,8 @@ var tuiTheme = {
|
|
|
11273
11841
|
userMessage: (value) => paint("38;5;236;48;5;230", value),
|
|
11274
11842
|
strong: (value) => paint("1", value),
|
|
11275
11843
|
underline: (value) => paint("4", value),
|
|
11276
|
-
muted: (value) => paint("
|
|
11277
|
-
subtle: (value) => paint("
|
|
11844
|
+
muted: (value) => paint("38;5;243", value),
|
|
11845
|
+
subtle: (value) => paint("38;5;244", value),
|
|
11278
11846
|
success: (value) => paint("38;5;35", value),
|
|
11279
11847
|
warning: (value) => paint("38;5;214", value),
|
|
11280
11848
|
error: (value) => paint("38;5;196", value),
|
|
@@ -11286,15 +11854,13 @@ var WELCOME_TEAM_SLOTS = 3;
|
|
|
11286
11854
|
var WELCOME_HANDOFF_SLOTS = 2;
|
|
11287
11855
|
var WELCOME_CONVERSATION_SLOTS = 240;
|
|
11288
11856
|
var GOAH_TERMINAL_MARK = [
|
|
11289
|
-
"
|
|
11290
|
-
"
|
|
11291
|
-
"
|
|
11292
|
-
"
|
|
11293
|
-
" \u2580\u2580\u2588\u2588\u2584\u2588\u2580\u2584\u2588\u2580\u2580\u2580",
|
|
11294
|
-
" \u2580\u2584\u2584\u2584\u2580\u2580"
|
|
11857
|
+
" \u256D\u2500\u2500\u2500\u2500\u256E",
|
|
11858
|
+
" \u256D\u2500\u2500\u2500\u256F \u25CF \u2570\u2500\u2500\u2500\u256E",
|
|
11859
|
+
" \u2570\u2500\u2500\u2500\u256E \u256D\u2500\u2500\u2500\u256F",
|
|
11860
|
+
" \u2570\u2500\u2500\u2500\u2500\u256F"
|
|
11295
11861
|
];
|
|
11296
11862
|
function welcomeSnapshot(stateDir, runner) {
|
|
11297
|
-
const database =
|
|
11863
|
+
const database = join5(stateDir, "ledger.sqlite");
|
|
11298
11864
|
if (!existsSync(database))
|
|
11299
11865
|
return { root: null, team: [], handoffs: [], conversation: [], runner: runner.runner, target: runner.target };
|
|
11300
11866
|
const db = new DatabaseSync(database, { readOnly: true });
|
|
@@ -11339,7 +11905,7 @@ function renderWelcome(snapshot, hasHistory) {
|
|
|
11339
11905
|
}
|
|
11340
11906
|
|
|
11341
11907
|
// node_modules/.dist-original/setup-wizard.js
|
|
11342
|
-
import { spawn } from "node:child_process";
|
|
11908
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
11343
11909
|
|
|
11344
11910
|
// node_modules/.dist-original/searchable-select.js
|
|
11345
11911
|
var SearchableSelect = class {
|
|
@@ -11576,13 +12142,13 @@ function summarize(config) {
|
|
|
11576
12142
|
function openUrl(url) {
|
|
11577
12143
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
11578
12144
|
const args2 = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
11579
|
-
|
|
12145
|
+
spawn2(command, args2, { detached: true, stdio: "ignore" }).unref();
|
|
11580
12146
|
}
|
|
11581
12147
|
|
|
11582
12148
|
// node_modules/.dist-original/tui.js
|
|
11583
|
-
import { spawn as
|
|
12149
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
11584
12150
|
import { closeSync, existsSync as existsSync2, mkdirSync, openSync } from "node:fs";
|
|
11585
|
-
import { join as
|
|
12151
|
+
import { join as join6, resolve as resolve2 } from "node:path";
|
|
11586
12152
|
var HeaderBar = class {
|
|
11587
12153
|
runner;
|
|
11588
12154
|
target;
|
|
@@ -11780,7 +12346,7 @@ var StreamCoordinator = class {
|
|
|
11780
12346
|
}
|
|
11781
12347
|
};
|
|
11782
12348
|
function renderUserMessage(content, width) {
|
|
11783
|
-
return new Text(content, 2,
|
|
12349
|
+
return new Text(content, 2, 0, tuiTheme.userMessage).render(width);
|
|
11784
12350
|
}
|
|
11785
12351
|
function renderTuiHeader(width, runner, target, version) {
|
|
11786
12352
|
const brand = " GOAH ";
|
|
@@ -11800,30 +12366,54 @@ function statusText(mode, queued = 0) {
|
|
|
11800
12366
|
return tuiTheme.accent("opening setup\u2026");
|
|
11801
12367
|
return `${tuiTheme.muted("ready")} ${tuiTheme.accent("/help")}`;
|
|
11802
12368
|
}
|
|
12369
|
+
var TUI_COMMANDS = [
|
|
12370
|
+
{ name: "goal", action: "goal", description: "Start or revise durable work", argumentHint: "<objective>", acceptsArguments: true, requiresArgument: true },
|
|
12371
|
+
{ name: "model", action: "model", description: "Choose a provider and model", argumentHint: "[provider/model]", acceptsArguments: true },
|
|
12372
|
+
{ name: "status", action: "status", description: "Inspect the current workspace" },
|
|
12373
|
+
{ name: "setup", action: "setup", description: "Configure Goah", argumentHint: "[runner|model|auth]", acceptsArguments: true },
|
|
12374
|
+
{ name: "records", action: "records", description: "Browse current work records", argumentHint: "[goal]", acceptsArguments: true },
|
|
12375
|
+
{ name: "history", action: "records", description: "Show a Goal's record history", argumentHint: "<goal>", acceptsArguments: true, requiresArgument: true },
|
|
12376
|
+
{ name: "observe", action: "goal", description: "Set how the active Goal is observed", argumentHint: "<method>", acceptsArguments: true, requiresArgument: true },
|
|
12377
|
+
{ name: "login", action: "login", description: "Add provider credentials", argumentHint: "[provider]", acceptsArguments: true },
|
|
12378
|
+
{ name: "logout", action: "logout", description: "Remove provider credentials", argumentHint: "[provider]", acceptsArguments: true },
|
|
12379
|
+
{ name: "stop", action: "stop", description: "Stop the current Turn" },
|
|
12380
|
+
{ name: "help", action: "help", description: "Show all commands" },
|
|
12381
|
+
{ name: "quit", action: "quit", description: "Leave Goah", aliases: ["exit"] }
|
|
12382
|
+
];
|
|
12383
|
+
function commandDefinition(text) {
|
|
12384
|
+
const token = text.trim().split(/\s+/, 1)[0] ?? "";
|
|
12385
|
+
if (!token.startsWith("/"))
|
|
12386
|
+
return null;
|
|
12387
|
+
const name = token.slice(1);
|
|
12388
|
+
const definition = TUI_COMMANDS.find((candidate) => candidate.name === name || candidate.aliases?.includes(name));
|
|
12389
|
+
if (!definition)
|
|
12390
|
+
return null;
|
|
12391
|
+
return { definition, hasArguments: Boolean(text.trim().slice(token.length).trim()) };
|
|
12392
|
+
}
|
|
12393
|
+
function commandAwaitingArgument(text) {
|
|
12394
|
+
const match = commandDefinition(text);
|
|
12395
|
+
return match && match.definition.requiresArgument && !match.hasArguments ? `/${match.definition.name} ` : null;
|
|
12396
|
+
}
|
|
12397
|
+
function createTuiAutocompleteProvider(basePath = process.cwd()) {
|
|
12398
|
+
const commands = TUI_COMMANDS.map(({ name, description, argumentHint, getArgumentCompletions }) => ({ name, ...description ? { description } : {}, ...argumentHint ? { argumentHint } : {}, ...getArgumentCompletions ? { getArgumentCompletions } : {} }));
|
|
12399
|
+
return new CombinedAutocompleteProvider(commands, basePath);
|
|
12400
|
+
}
|
|
12401
|
+
function renderTuiCommandHelp() {
|
|
12402
|
+
return [tuiTheme.strong("Commands"), ...TUI_COMMANDS.map((command) => {
|
|
12403
|
+
const invocation = `/${command.name}${command.argumentHint ? ` ${command.argumentHint}` : ""}`;
|
|
12404
|
+
return ` ${invocation.padEnd(28)} ${tuiTheme.muted(command.description ?? "")}`;
|
|
12405
|
+
}), ""].join("\n");
|
|
12406
|
+
}
|
|
11803
12407
|
function classifyTuiInput(value, busy) {
|
|
11804
12408
|
const text = value.trim();
|
|
11805
12409
|
if (!text)
|
|
11806
12410
|
return { action: "empty", text };
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
if (text === "/records" || text.startsWith("/records ") || text.startsWith("/history "))
|
|
11814
|
-
return { action: "records", text };
|
|
11815
|
-
if (text === "/stop")
|
|
11816
|
-
return { action: "stop", text };
|
|
11817
|
-
if (text === "/model" || text.startsWith("/model "))
|
|
11818
|
-
return { action: "model", text };
|
|
11819
|
-
if (text === "/login" || text.startsWith("/login "))
|
|
11820
|
-
return { action: "login", text };
|
|
11821
|
-
if (text === "/logout" || text.startsWith("/logout "))
|
|
11822
|
-
return { action: "logout", text };
|
|
11823
|
-
if (text === "/setup" || text.startsWith("/setup "))
|
|
11824
|
-
return { action: "setup", text };
|
|
11825
|
-
if (text.startsWith("/goal ") || text.startsWith("/observe "))
|
|
11826
|
-
return { action: "goal", text };
|
|
12411
|
+
const command = commandDefinition(text);
|
|
12412
|
+
if (command) {
|
|
12413
|
+
if (command.hasArguments && !command.definition.acceptsArguments)
|
|
12414
|
+
return { action: "unknown", text };
|
|
12415
|
+
return { action: command.definition.action, text };
|
|
12416
|
+
}
|
|
11827
12417
|
if (text.startsWith("/"))
|
|
11828
12418
|
return { action: "unknown", text };
|
|
11829
12419
|
return { action: busy ? "steer" : "send", text };
|
|
@@ -11854,13 +12444,14 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
11854
12444
|
borderColor: tuiTheme.accent,
|
|
11855
12445
|
selectList: { selectedPrefix: tuiTheme.accent, selectedText: tuiTheme.strong, description: tuiTheme.muted, scrollInfo: tuiTheme.muted, noMatch: tuiTheme.error }
|
|
11856
12446
|
}, { paddingX: 1, autocompleteMaxVisible: 6 });
|
|
12447
|
+
input.setAutocompleteProvider(createTuiAutocompleteProvider());
|
|
11857
12448
|
const statusView = new Text(statusText("ready"), 1, 0);
|
|
11858
12449
|
const shell = new VStack([
|
|
11859
12450
|
{ component: headerView, basis: 1, shrink: 0 },
|
|
11860
12451
|
{ component: conversationScroll, grow: 1, minSize: 1 },
|
|
11861
12452
|
{ component: goalView, basis: 1, shrink: 0 },
|
|
11862
12453
|
{ component: statusView, basis: 1, shrink: 0 },
|
|
11863
|
-
{ component: input, basis: "auto", minSize: 3, maxSize:
|
|
12454
|
+
{ component: input, basis: "auto", minSize: 3, maxSize: 11, shrink: 0 }
|
|
11864
12455
|
]);
|
|
11865
12456
|
const busy = { active: false };
|
|
11866
12457
|
const queued = [];
|
|
@@ -12137,6 +12728,11 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12137
12728
|
push(await reloadDaemon(stateDir, configPath) ? "Configuration updated \u2014 applies to the next Turn." : "Configuration saved \u2014 restart Goah to apply it.");
|
|
12138
12729
|
});
|
|
12139
12730
|
input.onSubmit = (line) => {
|
|
12731
|
+
const waiting = commandAwaitingArgument(line);
|
|
12732
|
+
if (waiting) {
|
|
12733
|
+
input.setText(waiting);
|
|
12734
|
+
return;
|
|
12735
|
+
}
|
|
12140
12736
|
const { action, text } = classifyTuiInput(line, busy.active);
|
|
12141
12737
|
input.setText("");
|
|
12142
12738
|
if (action === "quit") {
|
|
@@ -12147,10 +12743,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12147
12743
|
return;
|
|
12148
12744
|
}
|
|
12149
12745
|
if (action === "help") {
|
|
12150
|
-
push(
|
|
12151
|
-
/model /login /logout /setup /status
|
|
12152
|
-
/records /history /goal /observe /stop /quit
|
|
12153
|
-
`);
|
|
12746
|
+
push(renderTuiCommandHelp());
|
|
12154
12747
|
return;
|
|
12155
12748
|
}
|
|
12156
12749
|
if (action === "status") {
|
|
@@ -12465,8 +13058,8 @@ async function ensureDaemon(configPath, stateDir) {
|
|
|
12465
13058
|
await new Promise((resolveWait) => setTimeout(resolveWait, 50));
|
|
12466
13059
|
}
|
|
12467
13060
|
mkdirSync(stateDir, { recursive: true });
|
|
12468
|
-
const log = openSync(
|
|
12469
|
-
|
|
13061
|
+
const log = openSync(join6(stateDir, "daemon.log"), "a");
|
|
13062
|
+
spawn3(process.execPath, [process.argv[1], "start", "--config", resolve2(configPath)], { cwd: process.cwd(), detached: true, stdio: ["ignore", log, log], env: process.env }).unref();
|
|
12470
13063
|
closeSync(log);
|
|
12471
13064
|
const deadline = Date.now() + 1e4;
|
|
12472
13065
|
while (Date.now() < deadline) {
|
|
@@ -12826,7 +13419,7 @@ async function main() {
|
|
|
12826
13419
|
const goal = command === "goal-complete" ? supervisor.completeGoal({ goalId: id, revision: current.revision, reason: required("--reason"), evidence: evidence() }, actor) : supervisor.transitionGoal(id, command === "goal-pause" ? "paused" : "active", actor);
|
|
12827
13420
|
console.log(JSON.stringify({ goal }, null, 2));
|
|
12828
13421
|
} else if (command === "dashboard") {
|
|
12829
|
-
const path4 = option("--output") ??
|
|
13422
|
+
const path4 = option("--output") ?? join7(config.stateDir, "status.html");
|
|
12830
13423
|
writeFileSync(path4, (await import("./dist-KNR2XL6J.js")).renderDashboard(ledger));
|
|
12831
13424
|
console.log(path4);
|
|
12832
13425
|
} else
|
|
@@ -12863,8 +13456,8 @@ async function ensureDaemon2(configPath, stateDir) {
|
|
|
12863
13456
|
await new Promise((resolveWait) => setTimeout(resolveWait, 50));
|
|
12864
13457
|
}
|
|
12865
13458
|
mkdirSync2(stateDir, { recursive: true });
|
|
12866
|
-
const log = openSync2(
|
|
12867
|
-
const child =
|
|
13459
|
+
const log = openSync2(join7(stateDir, "daemon.log"), "a");
|
|
13460
|
+
const child = spawn4(process.execPath, [process.argv[1], "start", "--config", resolve3(configPath)], { cwd: process.cwd(), detached: true, stdio: ["ignore", log, log], env: process.env });
|
|
12868
13461
|
closeSync2(log);
|
|
12869
13462
|
child.unref();
|
|
12870
13463
|
const deadline = Date.now() + 1e4;
|
|
@@ -12880,7 +13473,7 @@ async function ensureDaemon2(configPath, stateDir) {
|
|
|
12880
13473
|
function openUrl2(url) {
|
|
12881
13474
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
12882
13475
|
const args2 = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
12883
|
-
const child =
|
|
13476
|
+
const child = spawn4(command, args2, { detached: true, stdio: "ignore" });
|
|
12884
13477
|
child.unref();
|
|
12885
13478
|
}
|
|
12886
13479
|
function remoteRequest(command) {
|
|
@@ -13072,7 +13665,7 @@ async function runRunnerCommand(command, commandArgs, configPath) {
|
|
|
13072
13665
|
async function runRunnerEarly(configPath) {
|
|
13073
13666
|
const action = args[1] ?? "list";
|
|
13074
13667
|
if (action === "list") {
|
|
13075
|
-
for (const manifest of (await import("./runner-registry-
|
|
13668
|
+
for (const manifest of (await import("./runner-registry-GD4BYCQC.js")).runnerManifests())
|
|
13076
13669
|
console.log(`${manifest.id.padEnd(16)} ${manifest.description}`);
|
|
13077
13670
|
return;
|
|
13078
13671
|
}
|
|
@@ -13173,7 +13766,7 @@ async function runDaemonCommand(config, configPath) {
|
|
|
13173
13766
|
return;
|
|
13174
13767
|
}
|
|
13175
13768
|
if (action === "logs") {
|
|
13176
|
-
const path4 =
|
|
13769
|
+
const path4 = join7(config.stateDir, "daemon.log");
|
|
13177
13770
|
if (!existsSync3(path4)) {
|
|
13178
13771
|
console.log(`No daemon log at ${path4}`);
|
|
13179
13772
|
return;
|
|
@@ -2,7 +2,7 @@ import { createRequire as __goahCreateRequire } from "node:module";
|
|
|
2
2
|
const require = __goahCreateRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
runProcessWorker
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7E7V6OIU.js";
|
|
6
6
|
import "./chunk-6M3OOCKO.js";
|
|
7
7
|
import "./chunk-K26BVR6O.js";
|
|
8
8
|
import "./chunk-IIJQ3DW4.js";
|
package/dist/index.js
CHANGED
|
@@ -31,11 +31,11 @@ import {
|
|
|
31
31
|
updateWorkspaceRunnerProfile,
|
|
32
32
|
writeDefaultConfig,
|
|
33
33
|
writeDefaultRunnerProfile
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import "./chunk-
|
|
34
|
+
} from "./chunk-KJ4HJCTK.js";
|
|
35
|
+
import "./chunk-D2DVAH37.js";
|
|
36
36
|
import "./chunk-YH6YJ2IB.js";
|
|
37
37
|
import "./chunk-QBD6EJ2Z.js";
|
|
38
|
-
import "./chunk-
|
|
38
|
+
import "./chunk-7E7V6OIU.js";
|
|
39
39
|
import "./chunk-6M3OOCKO.js";
|
|
40
40
|
import "./chunk-K26BVR6O.js";
|
|
41
41
|
import "./chunk-IIJQ3DW4.js";
|
package/dist/pi-worker.js
CHANGED
package/dist/runner-pi.js
CHANGED
|
@@ -3,8 +3,8 @@ const require = __goahCreateRequire(import.meta.url);
|
|
|
3
3
|
import {
|
|
4
4
|
runnerManifests,
|
|
5
5
|
runnerPlugin
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-D2DVAH37.js";
|
|
7
|
+
import "./chunk-7E7V6OIU.js";
|
|
8
8
|
import "./chunk-6M3OOCKO.js";
|
|
9
9
|
import "./chunk-K26BVR6O.js";
|
|
10
10
|
import "./chunk-IIJQ3DW4.js";
|