@goah/cli 0.13.1 → 0.13.3
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 +1202 -74
- 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
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
|
|
54
|
-
import { closeSync as closeSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as
|
|
55
|
-
import { join as
|
|
53
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
54
|
+
import { closeSync as closeSync2, existsSync as existsSync3, mkdirSync as mkdirSync2, openSync as openSync2, readFileSync as readFileSync3, writeFileSync } from "node:fs";
|
|
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;
|
|
@@ -2467,6 +3035,92 @@ var _kittyProtocolActive = false;
|
|
|
2467
3035
|
function setKittyProtocolActive(active) {
|
|
2468
3036
|
_kittyProtocolActive = active;
|
|
2469
3037
|
}
|
|
3038
|
+
var Key = {
|
|
3039
|
+
// Special keys
|
|
3040
|
+
escape: "escape",
|
|
3041
|
+
esc: "esc",
|
|
3042
|
+
enter: "enter",
|
|
3043
|
+
return: "return",
|
|
3044
|
+
tab: "tab",
|
|
3045
|
+
space: "space",
|
|
3046
|
+
backspace: "backspace",
|
|
3047
|
+
delete: "delete",
|
|
3048
|
+
insert: "insert",
|
|
3049
|
+
clear: "clear",
|
|
3050
|
+
home: "home",
|
|
3051
|
+
end: "end",
|
|
3052
|
+
pageUp: "pageUp",
|
|
3053
|
+
pageDown: "pageDown",
|
|
3054
|
+
up: "up",
|
|
3055
|
+
down: "down",
|
|
3056
|
+
left: "left",
|
|
3057
|
+
right: "right",
|
|
3058
|
+
f1: "f1",
|
|
3059
|
+
f2: "f2",
|
|
3060
|
+
f3: "f3",
|
|
3061
|
+
f4: "f4",
|
|
3062
|
+
f5: "f5",
|
|
3063
|
+
f6: "f6",
|
|
3064
|
+
f7: "f7",
|
|
3065
|
+
f8: "f8",
|
|
3066
|
+
f9: "f9",
|
|
3067
|
+
f10: "f10",
|
|
3068
|
+
f11: "f11",
|
|
3069
|
+
f12: "f12",
|
|
3070
|
+
// Symbol keys
|
|
3071
|
+
backtick: "`",
|
|
3072
|
+
hyphen: "-",
|
|
3073
|
+
equals: "=",
|
|
3074
|
+
leftbracket: "[",
|
|
3075
|
+
rightbracket: "]",
|
|
3076
|
+
backslash: "\\",
|
|
3077
|
+
semicolon: ";",
|
|
3078
|
+
quote: "'",
|
|
3079
|
+
comma: ",",
|
|
3080
|
+
period: ".",
|
|
3081
|
+
slash: "/",
|
|
3082
|
+
exclamation: "!",
|
|
3083
|
+
at: "@",
|
|
3084
|
+
hash: "#",
|
|
3085
|
+
dollar: "$",
|
|
3086
|
+
percent: "%",
|
|
3087
|
+
caret: "^",
|
|
3088
|
+
ampersand: "&",
|
|
3089
|
+
asterisk: "*",
|
|
3090
|
+
leftparen: "(",
|
|
3091
|
+
rightparen: ")",
|
|
3092
|
+
underscore: "_",
|
|
3093
|
+
plus: "+",
|
|
3094
|
+
pipe: "|",
|
|
3095
|
+
tilde: "~",
|
|
3096
|
+
leftbrace: "{",
|
|
3097
|
+
rightbrace: "}",
|
|
3098
|
+
colon: ":",
|
|
3099
|
+
lessthan: "<",
|
|
3100
|
+
greaterthan: ">",
|
|
3101
|
+
question: "?",
|
|
3102
|
+
// Single modifiers
|
|
3103
|
+
ctrl: (key) => `ctrl+${key}`,
|
|
3104
|
+
shift: (key) => `shift+${key}`,
|
|
3105
|
+
alt: (key) => `alt+${key}`,
|
|
3106
|
+
super: (key) => `super+${key}`,
|
|
3107
|
+
// Combined modifiers
|
|
3108
|
+
ctrlShift: (key) => `ctrl+shift+${key}`,
|
|
3109
|
+
shiftCtrl: (key) => `shift+ctrl+${key}`,
|
|
3110
|
+
ctrlAlt: (key) => `ctrl+alt+${key}`,
|
|
3111
|
+
altCtrl: (key) => `alt+ctrl+${key}`,
|
|
3112
|
+
shiftAlt: (key) => `shift+alt+${key}`,
|
|
3113
|
+
altShift: (key) => `alt+shift+${key}`,
|
|
3114
|
+
ctrlSuper: (key) => `ctrl+super+${key}`,
|
|
3115
|
+
superCtrl: (key) => `super+ctrl+${key}`,
|
|
3116
|
+
shiftSuper: (key) => `shift+super+${key}`,
|
|
3117
|
+
superShift: (key) => `super+shift+${key}`,
|
|
3118
|
+
altSuper: (key) => `alt+super+${key}`,
|
|
3119
|
+
superAlt: (key) => `super+alt+${key}`,
|
|
3120
|
+
// Triple modifiers
|
|
3121
|
+
ctrlShiftAlt: (key) => `ctrl+shift+alt+${key}`,
|
|
3122
|
+
ctrlShiftSuper: (key) => `ctrl+shift+super+${key}`
|
|
3123
|
+
};
|
|
2470
3124
|
var SYMBOL_KEYS = /* @__PURE__ */ new Set([
|
|
2471
3125
|
"`",
|
|
2472
3126
|
"-",
|
|
@@ -3496,8 +4150,14 @@ function parseTerminalColorSchemeReport(data) {
|
|
|
3496
4150
|
|
|
3497
4151
|
// ../../node_modules/@earendil-works/pi-tui/dist/terminal-image.js
|
|
3498
4152
|
import { execSync } from "node:child_process";
|
|
4153
|
+
import { homedir as homedir2 } from "node:os";
|
|
4154
|
+
import { isAbsolute } from "node:path";
|
|
4155
|
+
import { pathToFileURL } from "node:url";
|
|
3499
4156
|
var cachedCapabilities = null;
|
|
3500
4157
|
var cellDimensions = { widthPx: 9, heightPx: 18 };
|
|
4158
|
+
function getCellDimensions() {
|
|
4159
|
+
return cellDimensions;
|
|
4160
|
+
}
|
|
3501
4161
|
function setCellDimensions(dims) {
|
|
3502
4162
|
cellDimensions = dims;
|
|
3503
4163
|
}
|
|
@@ -3575,6 +4235,41 @@ function isImageLine(line) {
|
|
|
3575
4235
|
}
|
|
3576
4236
|
return line.includes(KITTY_PREFIX) || line.includes(ITERM2_PREFIX);
|
|
3577
4237
|
}
|
|
4238
|
+
function allocateImageId() {
|
|
4239
|
+
return Math.floor(Math.random() * 4294967294) + 1;
|
|
4240
|
+
}
|
|
4241
|
+
function encodeKitty(base64Data, options = {}) {
|
|
4242
|
+
const CHUNK_SIZE = 4096;
|
|
4243
|
+
const params = ["a=T", "f=100", "q=2"];
|
|
4244
|
+
if (options.moveCursor === false)
|
|
4245
|
+
params.push("C=1");
|
|
4246
|
+
if (options.columns)
|
|
4247
|
+
params.push(`c=${options.columns}`);
|
|
4248
|
+
if (options.rows)
|
|
4249
|
+
params.push(`r=${options.rows}`);
|
|
4250
|
+
if (options.imageId)
|
|
4251
|
+
params.push(`i=${options.imageId}`);
|
|
4252
|
+
if (base64Data.length <= CHUNK_SIZE) {
|
|
4253
|
+
return `\x1B_G${params.join(",")};${base64Data}\x1B\\`;
|
|
4254
|
+
}
|
|
4255
|
+
const chunks = [];
|
|
4256
|
+
let offset = 0;
|
|
4257
|
+
let isFirst = true;
|
|
4258
|
+
while (offset < base64Data.length) {
|
|
4259
|
+
const chunk = base64Data.slice(offset, offset + CHUNK_SIZE);
|
|
4260
|
+
const isLast = offset + CHUNK_SIZE >= base64Data.length;
|
|
4261
|
+
if (isFirst) {
|
|
4262
|
+
chunks.push(`\x1B_G${params.join(",")},m=1;${chunk}\x1B\\`);
|
|
4263
|
+
isFirst = false;
|
|
4264
|
+
} else if (isLast) {
|
|
4265
|
+
chunks.push(`\x1B_Gm=0;${chunk}\x1B\\`);
|
|
4266
|
+
} else {
|
|
4267
|
+
chunks.push(`\x1B_Gm=1;${chunk}\x1B\\`);
|
|
4268
|
+
}
|
|
4269
|
+
offset += CHUNK_SIZE;
|
|
4270
|
+
}
|
|
4271
|
+
return chunks.join("");
|
|
4272
|
+
}
|
|
3578
4273
|
function deleteKittyImage(imageId) {
|
|
3579
4274
|
return `\x1B_Ga=d,d=I,i=${imageId},q=2\x1B\\`;
|
|
3580
4275
|
}
|
|
@@ -3584,7 +4279,36 @@ function deleteAllKittyImages() {
|
|
|
3584
4279
|
function deleteAllKittyPlacements() {
|
|
3585
4280
|
return "\x1B_Ga=d,d=a,q=2\x1B\\";
|
|
3586
4281
|
}
|
|
4282
|
+
function encodeITerm2(base64Data, options = {}) {
|
|
4283
|
+
const params = [
|
|
4284
|
+
`inline=${options.inline !== false ? 1 : 0}`,
|
|
4285
|
+
`size=${Buffer.byteLength(base64Data, "base64")}`
|
|
4286
|
+
];
|
|
4287
|
+
if (options.width !== void 0)
|
|
4288
|
+
params.push(`width=${options.width}`);
|
|
4289
|
+
if (options.height !== void 0)
|
|
4290
|
+
params.push(`height=${options.height}`);
|
|
4291
|
+
if (options.name) {
|
|
4292
|
+
const nameBase64 = Buffer.from(options.name).toString("base64");
|
|
4293
|
+
params.push(`name=${nameBase64}`);
|
|
4294
|
+
}
|
|
4295
|
+
if (options.preserveAspectRatio === false) {
|
|
4296
|
+
params.push("preserveAspectRatio=0");
|
|
4297
|
+
}
|
|
4298
|
+
return `\x1B]1337;File=${params.join(";")}:${base64Data}\x07`;
|
|
4299
|
+
}
|
|
3587
4300
|
var kittyImageMetadata = /* @__PURE__ */ new Map();
|
|
4301
|
+
var kittyTransmissionGeneration = 0;
|
|
4302
|
+
function registerKittyImageMetadata(metadata) {
|
|
4303
|
+
kittyTransmissionGeneration += 1;
|
|
4304
|
+
kittyImageMetadata.delete(metadata.imageId);
|
|
4305
|
+
kittyImageMetadata.set(metadata.imageId, { ...metadata, transmissionGeneration: kittyTransmissionGeneration });
|
|
4306
|
+
if (kittyImageMetadata.size > 1e3) {
|
|
4307
|
+
const oldestImageId = kittyImageMetadata.keys().next().value;
|
|
4308
|
+
if (oldestImageId !== void 0)
|
|
4309
|
+
kittyImageMetadata.delete(oldestImageId);
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
3588
4312
|
function getRegisteredKittyImageMetadata(line) {
|
|
3589
4313
|
const controls = /\x1b_G([^;]*);/.exec(line)?.[1];
|
|
3590
4314
|
if (!controls)
|
|
@@ -3672,9 +4396,203 @@ function cropKittyImageLine(line, hiddenRows, visibleRows) {
|
|
|
3672
4396
|
controls.push(`y=${sourceY}`, `h=${sourceHeight}`, `r=${croppedRows}`);
|
|
3673
4397
|
return `${line.slice(0, match.index)}\x1B_G${controls.join(",")};${line.slice(match.index + match[0].length)}`;
|
|
3674
4398
|
}
|
|
4399
|
+
function calculateImageCellSize(imageDimensions, maxWidthCells, maxHeightCells, cellDimensions2 = { widthPx: 9, heightPx: 18 }) {
|
|
4400
|
+
const maxWidth = Math.max(1, Math.floor(maxWidthCells));
|
|
4401
|
+
const maxHeight = maxHeightCells === void 0 ? void 0 : Math.max(1, Math.floor(maxHeightCells));
|
|
4402
|
+
const imageWidth = Math.max(1, imageDimensions.widthPx);
|
|
4403
|
+
const imageHeight = Math.max(1, imageDimensions.heightPx);
|
|
4404
|
+
const widthScale = maxWidth * cellDimensions2.widthPx / imageWidth;
|
|
4405
|
+
const heightScale = maxHeight === void 0 ? widthScale : maxHeight * cellDimensions2.heightPx / imageHeight;
|
|
4406
|
+
const scale = Math.min(widthScale, heightScale);
|
|
4407
|
+
const scaledWidthPx = imageWidth * scale;
|
|
4408
|
+
const scaledHeightPx = imageHeight * scale;
|
|
4409
|
+
const columns = Math.ceil(scaledWidthPx / cellDimensions2.widthPx);
|
|
4410
|
+
const rows = Math.ceil(scaledHeightPx / cellDimensions2.heightPx);
|
|
4411
|
+
return {
|
|
4412
|
+
columns: Math.max(1, Math.min(maxWidth, columns)),
|
|
4413
|
+
rows: Math.max(1, maxHeight === void 0 ? rows : Math.min(maxHeight, rows))
|
|
4414
|
+
};
|
|
4415
|
+
}
|
|
4416
|
+
function getPngDimensions(base64Data) {
|
|
4417
|
+
try {
|
|
4418
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
4419
|
+
if (buffer.length < 24) {
|
|
4420
|
+
return null;
|
|
4421
|
+
}
|
|
4422
|
+
if (buffer[0] !== 137 || buffer[1] !== 80 || buffer[2] !== 78 || buffer[3] !== 71) {
|
|
4423
|
+
return null;
|
|
4424
|
+
}
|
|
4425
|
+
const width = buffer.readUInt32BE(16);
|
|
4426
|
+
const height = buffer.readUInt32BE(20);
|
|
4427
|
+
return { widthPx: width, heightPx: height };
|
|
4428
|
+
} catch {
|
|
4429
|
+
return null;
|
|
4430
|
+
}
|
|
4431
|
+
}
|
|
4432
|
+
function getJpegDimensions(base64Data) {
|
|
4433
|
+
try {
|
|
4434
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
4435
|
+
if (buffer.length < 2) {
|
|
4436
|
+
return null;
|
|
4437
|
+
}
|
|
4438
|
+
if (buffer[0] !== 255 || buffer[1] !== 216) {
|
|
4439
|
+
return null;
|
|
4440
|
+
}
|
|
4441
|
+
let offset = 2;
|
|
4442
|
+
while (offset < buffer.length - 9) {
|
|
4443
|
+
if (buffer[offset] !== 255) {
|
|
4444
|
+
offset++;
|
|
4445
|
+
continue;
|
|
4446
|
+
}
|
|
4447
|
+
const marker = buffer[offset + 1];
|
|
4448
|
+
if (marker >= 192 && marker <= 194) {
|
|
4449
|
+
const height = buffer.readUInt16BE(offset + 5);
|
|
4450
|
+
const width = buffer.readUInt16BE(offset + 7);
|
|
4451
|
+
return { widthPx: width, heightPx: height };
|
|
4452
|
+
}
|
|
4453
|
+
if (offset + 3 >= buffer.length) {
|
|
4454
|
+
return null;
|
|
4455
|
+
}
|
|
4456
|
+
const length = buffer.readUInt16BE(offset + 2);
|
|
4457
|
+
if (length < 2) {
|
|
4458
|
+
return null;
|
|
4459
|
+
}
|
|
4460
|
+
offset += 2 + length;
|
|
4461
|
+
}
|
|
4462
|
+
return null;
|
|
4463
|
+
} catch {
|
|
4464
|
+
return null;
|
|
4465
|
+
}
|
|
4466
|
+
}
|
|
4467
|
+
function getGifDimensions(base64Data) {
|
|
4468
|
+
try {
|
|
4469
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
4470
|
+
if (buffer.length < 10) {
|
|
4471
|
+
return null;
|
|
4472
|
+
}
|
|
4473
|
+
const sig = buffer.slice(0, 6).toString("ascii");
|
|
4474
|
+
if (sig !== "GIF87a" && sig !== "GIF89a") {
|
|
4475
|
+
return null;
|
|
4476
|
+
}
|
|
4477
|
+
const width = buffer.readUInt16LE(6);
|
|
4478
|
+
const height = buffer.readUInt16LE(8);
|
|
4479
|
+
return { widthPx: width, heightPx: height };
|
|
4480
|
+
} catch {
|
|
4481
|
+
return null;
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4484
|
+
function getWebpDimensions(base64Data) {
|
|
4485
|
+
try {
|
|
4486
|
+
const buffer = Buffer.from(base64Data, "base64");
|
|
4487
|
+
if (buffer.length < 30) {
|
|
4488
|
+
return null;
|
|
4489
|
+
}
|
|
4490
|
+
const riff = buffer.slice(0, 4).toString("ascii");
|
|
4491
|
+
const webp = buffer.slice(8, 12).toString("ascii");
|
|
4492
|
+
if (riff !== "RIFF" || webp !== "WEBP") {
|
|
4493
|
+
return null;
|
|
4494
|
+
}
|
|
4495
|
+
const chunk = buffer.slice(12, 16).toString("ascii");
|
|
4496
|
+
if (chunk === "VP8 ") {
|
|
4497
|
+
if (buffer.length < 30)
|
|
4498
|
+
return null;
|
|
4499
|
+
const width = buffer.readUInt16LE(26) & 16383;
|
|
4500
|
+
const height = buffer.readUInt16LE(28) & 16383;
|
|
4501
|
+
return { widthPx: width, heightPx: height };
|
|
4502
|
+
} else if (chunk === "VP8L") {
|
|
4503
|
+
if (buffer.length < 25)
|
|
4504
|
+
return null;
|
|
4505
|
+
const bits = buffer.readUInt32LE(21);
|
|
4506
|
+
const width = (bits & 16383) + 1;
|
|
4507
|
+
const height = (bits >> 14 & 16383) + 1;
|
|
4508
|
+
return { widthPx: width, heightPx: height };
|
|
4509
|
+
} else if (chunk === "VP8X") {
|
|
4510
|
+
if (buffer.length < 30)
|
|
4511
|
+
return null;
|
|
4512
|
+
const width = (buffer[24] | buffer[25] << 8 | buffer[26] << 16) + 1;
|
|
4513
|
+
const height = (buffer[27] | buffer[28] << 8 | buffer[29] << 16) + 1;
|
|
4514
|
+
return { widthPx: width, heightPx: height };
|
|
4515
|
+
}
|
|
4516
|
+
return null;
|
|
4517
|
+
} catch {
|
|
4518
|
+
return null;
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
function getImageDimensions(base64Data, mimeType) {
|
|
4522
|
+
if (mimeType === "image/png") {
|
|
4523
|
+
return getPngDimensions(base64Data);
|
|
4524
|
+
}
|
|
4525
|
+
if (mimeType === "image/jpeg") {
|
|
4526
|
+
return getJpegDimensions(base64Data);
|
|
4527
|
+
}
|
|
4528
|
+
if (mimeType === "image/gif") {
|
|
4529
|
+
return getGifDimensions(base64Data);
|
|
4530
|
+
}
|
|
4531
|
+
if (mimeType === "image/webp") {
|
|
4532
|
+
return getWebpDimensions(base64Data);
|
|
4533
|
+
}
|
|
4534
|
+
return null;
|
|
4535
|
+
}
|
|
4536
|
+
function renderImage(base64Data, imageDimensions, options = {}) {
|
|
4537
|
+
const caps = getCapabilities();
|
|
4538
|
+
if (!caps.images) {
|
|
4539
|
+
return null;
|
|
4540
|
+
}
|
|
4541
|
+
const maxWidth = options.maxWidthCells ?? 80;
|
|
4542
|
+
const size = calculateImageCellSize(imageDimensions, maxWidth, options.maxHeightCells, getCellDimensions());
|
|
4543
|
+
if (caps.images === "kitty") {
|
|
4544
|
+
if (options.imageId !== void 0) {
|
|
4545
|
+
registerKittyImageMetadata({
|
|
4546
|
+
imageId: options.imageId,
|
|
4547
|
+
columns: size.columns,
|
|
4548
|
+
rows: size.rows,
|
|
4549
|
+
widthPx: imageDimensions.widthPx,
|
|
4550
|
+
heightPx: imageDimensions.heightPx
|
|
4551
|
+
});
|
|
4552
|
+
}
|
|
4553
|
+
const sequence = encodeKitty(base64Data, {
|
|
4554
|
+
columns: size.columns,
|
|
4555
|
+
rows: size.rows,
|
|
4556
|
+
imageId: options.imageId,
|
|
4557
|
+
moveCursor: options.moveCursor
|
|
4558
|
+
});
|
|
4559
|
+
return { sequence, columns: size.columns, rows: size.rows, imageId: options.imageId };
|
|
4560
|
+
}
|
|
4561
|
+
if (caps.images === "iterm2") {
|
|
4562
|
+
const sequence = encodeITerm2(base64Data, {
|
|
4563
|
+
width: size.columns,
|
|
4564
|
+
height: "auto",
|
|
4565
|
+
preserveAspectRatio: options.preserveAspectRatio ?? true
|
|
4566
|
+
});
|
|
4567
|
+
return { sequence, columns: size.columns, rows: size.rows };
|
|
4568
|
+
}
|
|
4569
|
+
return null;
|
|
4570
|
+
}
|
|
3675
4571
|
function hyperlink(text, url) {
|
|
3676
4572
|
return `\x1B]8;;${url}\x1B\\${text}\x1B]8;;\x1B\\`;
|
|
3677
4573
|
}
|
|
4574
|
+
function shortenImagePath(filename) {
|
|
4575
|
+
const home = homedir2();
|
|
4576
|
+
if (home && (filename === home || filename.startsWith(`${home}/`) || filename.startsWith(`${home}\\`))) {
|
|
4577
|
+
return `~${filename.slice(home.length)}`;
|
|
4578
|
+
}
|
|
4579
|
+
return filename;
|
|
4580
|
+
}
|
|
4581
|
+
function imageFallback(mimeType, dimensions, filename) {
|
|
4582
|
+
const parts = [];
|
|
4583
|
+
if (filename) {
|
|
4584
|
+
const display = shortenImagePath(filename);
|
|
4585
|
+
if (getCapabilities().hyperlinks && isAbsolute(filename)) {
|
|
4586
|
+
parts.push(hyperlink(display, pathToFileURL(filename).href));
|
|
4587
|
+
} else {
|
|
4588
|
+
parts.push(display);
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4591
|
+
parts.push(`[${mimeType}]`);
|
|
4592
|
+
if (dimensions)
|
|
4593
|
+
parts.push(`${dimensions.widthPx}x${dimensions.heightPx}`);
|
|
4594
|
+
return `[Image: ${parts.join(" ")}]`;
|
|
4595
|
+
}
|
|
3678
4596
|
|
|
3679
4597
|
// ../../node_modules/@earendil-works/pi-tui/dist/tui.js
|
|
3680
4598
|
function isFocusable(component) {
|
|
@@ -6494,6 +7412,125 @@ function allocateStackSizes(entries, intrinsicSizes, availableSize, gap) {
|
|
|
6494
7412
|
return sizes;
|
|
6495
7413
|
}
|
|
6496
7414
|
|
|
7415
|
+
// ../../node_modules/@earendil-works/pi-tui/dist/components/h-stack.js
|
|
7416
|
+
var HStack = class extends Stack {
|
|
7417
|
+
layoutType = "hstack";
|
|
7418
|
+
constructor(children = [], options = {}) {
|
|
7419
|
+
super(children, options);
|
|
7420
|
+
}
|
|
7421
|
+
render(width) {
|
|
7422
|
+
const safeWidth = Math.max(1, width);
|
|
7423
|
+
const viewport = { width: safeWidth, height: Number.MAX_SAFE_INTEGER };
|
|
7424
|
+
const entries = visibleStackEntries(this.entries, viewport);
|
|
7425
|
+
if (entries.length === 0)
|
|
7426
|
+
return [];
|
|
7427
|
+
const intrinsicWidths = entries.map((entry) => {
|
|
7428
|
+
const lines = entry.component.render(safeWidth);
|
|
7429
|
+
return lines.reduce((max, line) => Math.max(max, visibleWidth(line)), 0);
|
|
7430
|
+
});
|
|
7431
|
+
const widths = allocateStackSizes(entries, intrinsicWidths, safeWidth, this.gap);
|
|
7432
|
+
const rendered = entries.map((entry, index) => widths[index] === 0 ? [] : entry.component.render(widths[index]));
|
|
7433
|
+
const height = rendered.reduce((max, lines) => Math.max(max, lines.length), 0);
|
|
7434
|
+
const result = Array.from({ length: height }, () => "");
|
|
7435
|
+
let x2 = 0;
|
|
7436
|
+
for (let index = 0; index < rendered.length; index++) {
|
|
7437
|
+
const lines = rendered[index];
|
|
7438
|
+
const childWidth = widths[index];
|
|
7439
|
+
let offset = 0;
|
|
7440
|
+
if (this.align === "center")
|
|
7441
|
+
offset = Math.floor((height - lines.length) / 2);
|
|
7442
|
+
else if (this.align === "end")
|
|
7443
|
+
offset = height - lines.length;
|
|
7444
|
+
for (let row = 0; row < lines.length; row++) {
|
|
7445
|
+
const target = row + offset;
|
|
7446
|
+
if (target < 0 || target >= result.length)
|
|
7447
|
+
continue;
|
|
7448
|
+
result[target] = compositeTuiLine(result[target], lines[row], x2, childWidth, safeWidth);
|
|
7449
|
+
}
|
|
7450
|
+
x2 += childWidth + this.gap;
|
|
7451
|
+
}
|
|
7452
|
+
return result;
|
|
7453
|
+
}
|
|
7454
|
+
};
|
|
7455
|
+
|
|
7456
|
+
// ../../node_modules/@earendil-works/pi-tui/dist/components/image.js
|
|
7457
|
+
var Image = class {
|
|
7458
|
+
base64Data;
|
|
7459
|
+
mimeType;
|
|
7460
|
+
dimensions;
|
|
7461
|
+
theme;
|
|
7462
|
+
options;
|
|
7463
|
+
imageId;
|
|
7464
|
+
cachedLines;
|
|
7465
|
+
cachedWidth;
|
|
7466
|
+
constructor(base64Data, mimeType, theme2, options = {}, dimensions) {
|
|
7467
|
+
this.base64Data = base64Data;
|
|
7468
|
+
this.mimeType = mimeType;
|
|
7469
|
+
this.theme = theme2;
|
|
7470
|
+
this.options = options;
|
|
7471
|
+
this.dimensions = dimensions || getImageDimensions(base64Data, mimeType) || { widthPx: 800, heightPx: 600 };
|
|
7472
|
+
this.imageId = options.imageId;
|
|
7473
|
+
}
|
|
7474
|
+
/** Get the Kitty image ID used by this image (if any). */
|
|
7475
|
+
getImageId() {
|
|
7476
|
+
return this.imageId;
|
|
7477
|
+
}
|
|
7478
|
+
invalidate() {
|
|
7479
|
+
this.cachedLines = void 0;
|
|
7480
|
+
this.cachedWidth = void 0;
|
|
7481
|
+
}
|
|
7482
|
+
render(width) {
|
|
7483
|
+
if (this.cachedLines && this.cachedWidth === width) {
|
|
7484
|
+
return this.cachedLines;
|
|
7485
|
+
}
|
|
7486
|
+
const maxWidth = Math.max(1, Math.min(width - 2, this.options.maxWidthCells ?? 60));
|
|
7487
|
+
const cellDimensions2 = getCellDimensions();
|
|
7488
|
+
const defaultMaxHeight = Math.max(1, Math.ceil(maxWidth * cellDimensions2.widthPx / cellDimensions2.heightPx));
|
|
7489
|
+
const maxHeight = this.options.maxHeightCells ?? defaultMaxHeight;
|
|
7490
|
+
const caps = getCapabilities();
|
|
7491
|
+
let lines;
|
|
7492
|
+
if (caps.images) {
|
|
7493
|
+
if (caps.images === "kitty" && this.imageId === void 0) {
|
|
7494
|
+
this.imageId = allocateImageId();
|
|
7495
|
+
}
|
|
7496
|
+
const result = renderImage(this.base64Data, this.dimensions, {
|
|
7497
|
+
maxWidthCells: maxWidth,
|
|
7498
|
+
maxHeightCells: maxHeight,
|
|
7499
|
+
imageId: this.imageId,
|
|
7500
|
+
moveCursor: false
|
|
7501
|
+
});
|
|
7502
|
+
if (result) {
|
|
7503
|
+
if (result.imageId) {
|
|
7504
|
+
this.imageId = result.imageId;
|
|
7505
|
+
}
|
|
7506
|
+
if (caps.images === "kitty") {
|
|
7507
|
+
lines = [result.sequence];
|
|
7508
|
+
for (let i = 0; i < result.rows - 1; i++) {
|
|
7509
|
+
lines.push("");
|
|
7510
|
+
}
|
|
7511
|
+
} else {
|
|
7512
|
+
lines = [];
|
|
7513
|
+
for (let i = 0; i < result.rows - 1; i++) {
|
|
7514
|
+
lines.push("");
|
|
7515
|
+
}
|
|
7516
|
+
const rowOffset = result.rows - 1;
|
|
7517
|
+
const moveUp = rowOffset > 0 ? `\x1B[${rowOffset}A` : "";
|
|
7518
|
+
lines.push(moveUp + result.sequence);
|
|
7519
|
+
}
|
|
7520
|
+
} else {
|
|
7521
|
+
const fallback = imageFallback(this.mimeType, this.dimensions, this.options.filename);
|
|
7522
|
+
lines = [truncateToWidth(this.theme.fallbackColor(fallback), width)];
|
|
7523
|
+
}
|
|
7524
|
+
} else {
|
|
7525
|
+
const fallback = imageFallback(this.mimeType, this.dimensions, this.options.filename);
|
|
7526
|
+
lines = [truncateToWidth(this.theme.fallbackColor(fallback), width)];
|
|
7527
|
+
}
|
|
7528
|
+
this.cachedLines = lines;
|
|
7529
|
+
this.cachedWidth = width;
|
|
7530
|
+
return lines;
|
|
7531
|
+
}
|
|
7532
|
+
};
|
|
7533
|
+
|
|
6497
7534
|
// ../../node_modules/@earendil-works/pi-tui/dist/components/input.js
|
|
6498
7535
|
var segmenter = getGraphemeSegmenter();
|
|
6499
7536
|
var Input = class {
|
|
@@ -11260,7 +12297,7 @@ async function reloadDaemon(stateDir, configPath) {
|
|
|
11260
12297
|
// node_modules/.dist-original/welcome.js
|
|
11261
12298
|
import { DatabaseSync } from "node:sqlite";
|
|
11262
12299
|
import { existsSync } from "node:fs";
|
|
11263
|
-
import { join as
|
|
12300
|
+
import { join as join5 } from "node:path";
|
|
11264
12301
|
|
|
11265
12302
|
// node_modules/.dist-original/tui-theme.js
|
|
11266
12303
|
var enabled = !process.env.NO_COLOR && process.env.TERM !== "dumb";
|
|
@@ -11273,8 +12310,8 @@ var tuiTheme = {
|
|
|
11273
12310
|
userMessage: (value) => paint("38;5;236;48;5;230", value),
|
|
11274
12311
|
strong: (value) => paint("1", value),
|
|
11275
12312
|
underline: (value) => paint("4", value),
|
|
11276
|
-
muted: (value) => paint("
|
|
11277
|
-
subtle: (value) => paint("
|
|
12313
|
+
muted: (value) => paint("38;5;243", value),
|
|
12314
|
+
subtle: (value) => paint("38;5;244", value),
|
|
11278
12315
|
success: (value) => paint("38;5;35", value),
|
|
11279
12316
|
warning: (value) => paint("38;5;214", value),
|
|
11280
12317
|
error: (value) => paint("38;5;196", value),
|
|
@@ -11286,15 +12323,15 @@ var WELCOME_TEAM_SLOTS = 3;
|
|
|
11286
12323
|
var WELCOME_HANDOFF_SLOTS = 2;
|
|
11287
12324
|
var WELCOME_CONVERSATION_SLOTS = 240;
|
|
11288
12325
|
var GOAH_TERMINAL_MARK = [
|
|
11289
|
-
"
|
|
11290
|
-
"
|
|
11291
|
-
"
|
|
11292
|
-
"
|
|
11293
|
-
"
|
|
11294
|
-
"
|
|
12326
|
+
"\u2800\u2800\u2800\u2880\u28F4\u281F\u281B\u2832\u2840\u2800\u2800\u2800",
|
|
12327
|
+
"\u2800\u2800\u2880\u28FF\u28E5\u2836\u2836\u281E\u28BB\u281B\u2812\u2800",
|
|
12328
|
+
"\u28F0\u281E\u28BB\u284F\u28F0\u28FE\u28F6\u2844\u28B8\u285F\u28B3\u2844",
|
|
12329
|
+
"\u283B\u28E6\u28F8\u28C7\u28D9\u28FF\u28DF\u28C1\u28FF\u28F4\u283E\u2803",
|
|
12330
|
+
"\u2800\u2800\u2809\u28BF\u2849\u2809\u28C9\u28FF\u2803\u2800\u2800\u2800",
|
|
12331
|
+
"\u2800\u2800\u2800\u2808\u281B\u281B\u280B\u2801\u2800\u2800\u2800\u2800"
|
|
11295
12332
|
];
|
|
11296
12333
|
function welcomeSnapshot(stateDir, runner) {
|
|
11297
|
-
const database =
|
|
12334
|
+
const database = join5(stateDir, "ledger.sqlite");
|
|
11298
12335
|
if (!existsSync(database))
|
|
11299
12336
|
return { root: null, team: [], handoffs: [], conversation: [], runner: runner.runner, target: runner.target };
|
|
11300
12337
|
const db = new DatabaseSync(database, { readOnly: true });
|
|
@@ -11314,7 +12351,7 @@ function welcomeSnapshot(stateDir, runner) {
|
|
|
11314
12351
|
return [{ agent: row.actor, result: "" }];
|
|
11315
12352
|
}
|
|
11316
12353
|
});
|
|
11317
|
-
const itemRows = db.prepare("SELECT i.type,i.data FROM turn_items i JOIN turns t ON t.id=i.turn_id JOIN threads th ON th.id=t.thread_id WHERE th.agent='ceo' AND t.trigger_kind='user_message' AND t.status
|
|
12354
|
+
const itemRows = db.prepare("SELECT i.type,i.data FROM turn_items i JOIN turns t ON t.id=i.turn_id JOIN threads th ON th.id=t.thread_id WHERE th.agent='ceo' AND t.trigger_kind='user_message' AND t.status='completed' AND i.status='completed' AND i.type IN ('user_message','assistant_message') AND (i.type='user_message' OR t.goal_id IS NULL OR EXISTS (SELECT 1 FROM events e WHERE e.stream_id='turn:'||t.id AND e.type='response.committed' AND json_extract(e.data,'$.messageItemId')=i.id)) ORDER BY i.rowid DESC LIMIT ?").all(WELCOME_CONVERSATION_SLOTS);
|
|
11318
12355
|
const conversation = itemRows.reverse().flatMap((row) => {
|
|
11319
12356
|
try {
|
|
11320
12357
|
const data = JSON.parse(row.data);
|
|
@@ -11328,18 +12365,9 @@ function welcomeSnapshot(stateDir, runner) {
|
|
|
11328
12365
|
db.close();
|
|
11329
12366
|
}
|
|
11330
12367
|
}
|
|
11331
|
-
function renderWelcome(snapshot, hasHistory) {
|
|
11332
|
-
const lines = ["", ...GOAH_TERMINAL_MARK.map((line) => tuiTheme.accent(line)), "", ` ${tuiTheme.strong(hasHistory ? "Welcome back." : "Ready when you are.")}`, ` ${tuiTheme.accent(snapshot.target)} ${tuiTheme.muted(`\xB7 ${snapshot.runner}`)}`];
|
|
11333
|
-
if (!snapshot.root)
|
|
11334
|
-
lines.push(` ${tuiTheme.muted("Chat normally \xB7 /goal for durable work \xB7 /help")}`);
|
|
11335
|
-
if (snapshot.team.length)
|
|
11336
|
-
lines.push(` ${tuiTheme.muted(`${snapshot.team.length} Goal Agent${snapshot.team.length === 1 ? "" : "s"} in the organization`)}`);
|
|
11337
|
-
lines.push("");
|
|
11338
|
-
return lines;
|
|
11339
|
-
}
|
|
11340
12368
|
|
|
11341
12369
|
// node_modules/.dist-original/setup-wizard.js
|
|
11342
|
-
import { spawn } from "node:child_process";
|
|
12370
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
11343
12371
|
|
|
11344
12372
|
// node_modules/.dist-original/searchable-select.js
|
|
11345
12373
|
var SearchableSelect = class {
|
|
@@ -11576,13 +12604,13 @@ function summarize(config) {
|
|
|
11576
12604
|
function openUrl(url) {
|
|
11577
12605
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
11578
12606
|
const args2 = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
11579
|
-
|
|
12607
|
+
spawn2(command, args2, { detached: true, stdio: "ignore" }).unref();
|
|
11580
12608
|
}
|
|
11581
12609
|
|
|
11582
12610
|
// node_modules/.dist-original/tui.js
|
|
11583
|
-
import { spawn as
|
|
11584
|
-
import { closeSync, existsSync as existsSync2, mkdirSync, openSync } from "node:fs";
|
|
11585
|
-
import { join as
|
|
12611
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
12612
|
+
import { closeSync, existsSync as existsSync2, mkdirSync, openSync, readFileSync as readFileSync2 } from "node:fs";
|
|
12613
|
+
import { join as join6, resolve as resolve2 } from "node:path";
|
|
11586
12614
|
var HeaderBar = class {
|
|
11587
12615
|
runner;
|
|
11588
12616
|
target;
|
|
@@ -11636,7 +12664,10 @@ var ConversationView = class {
|
|
|
11636
12664
|
liveThinking = "";
|
|
11637
12665
|
thinkingActive = false;
|
|
11638
12666
|
constructor(initial) {
|
|
11639
|
-
this.entries = [{ kind: "text", content: initial.join("\n") }];
|
|
12667
|
+
this.entries = initial.length ? [{ kind: "text", content: initial.join("\n") }] : [];
|
|
12668
|
+
}
|
|
12669
|
+
addComponent(component) {
|
|
12670
|
+
this.entries.push({ kind: "component", component });
|
|
11640
12671
|
}
|
|
11641
12672
|
addText(content) {
|
|
11642
12673
|
this.entries.push({ kind: "text", content });
|
|
@@ -11711,7 +12742,7 @@ var ConversationView = class {
|
|
|
11711
12742
|
this.entries.splice(1, this.entries.length - 240);
|
|
11712
12743
|
}
|
|
11713
12744
|
render(width) {
|
|
11714
|
-
const rendered = this.entries.flatMap((entry) => entry.kind === "markdown" ? [...new Markdown(entry.content, 2, 0, markdownTheme).render(width), ""] : entry.kind === "user" ? renderUserMessage(entry.content, width) : entry.kind === "thinking" ? [tuiTheme.muted(" thinking"), ...new Markdown(entry.content, 2, 0, markdownTheme, { color: tuiTheme.muted, italic: true }).render(width), ""] : entry.kind === "tool" ? new Text(toolActivityLine(entry), 2, 0).render(width) : new Text(entry.content, 2, 0).render(width));
|
|
12745
|
+
const rendered = this.entries.flatMap((entry) => entry.kind === "component" ? entry.component.render(width) : entry.kind === "markdown" ? [...new Markdown(entry.content, 2, 0, markdownTheme).render(width), ""] : entry.kind === "user" ? renderUserMessage(entry.content, width) : entry.kind === "thinking" ? [tuiTheme.muted(" thinking"), ...new Markdown(entry.content, 2, 0, markdownTheme, { color: tuiTheme.muted, italic: true }).render(width), ""] : entry.kind === "tool" ? new Text(toolActivityLine(entry), 2, 0).render(width) : new Text(entry.content, 2, 0).render(width));
|
|
11715
12746
|
if (this.liveThinking)
|
|
11716
12747
|
rendered.push(tuiTheme.muted(" thinking"), ...new Markdown(this.liveThinking, 2, 0, markdownTheme, { color: tuiTheme.muted, italic: true }).render(width));
|
|
11717
12748
|
else if (this.thinkingActive)
|
|
@@ -11723,6 +12754,48 @@ var ConversationView = class {
|
|
|
11723
12754
|
invalidate() {
|
|
11724
12755
|
}
|
|
11725
12756
|
};
|
|
12757
|
+
var WelcomeLockup = class {
|
|
12758
|
+
mark;
|
|
12759
|
+
details;
|
|
12760
|
+
horizontal;
|
|
12761
|
+
constructor(snapshot, hasHistory, imageData = null) {
|
|
12762
|
+
this.mark = imageData ? new Image(imageData, "image/png", { fallbackColor: tuiTheme.accent }, { maxWidthCells: 10, maxHeightCells: 5, filename: "Goah" }) : new Text(GOAH_TERMINAL_MARK.map((line) => tuiTheme.accent(line)).join("\n"), 0, 0);
|
|
12763
|
+
const lines = [
|
|
12764
|
+
tuiTheme.strong(hasHistory ? "Welcome back." : "Ready when you are."),
|
|
12765
|
+
`${tuiTheme.accent(snapshot.target)} ${tuiTheme.muted(`\xB7 ${snapshot.runner}`)}`
|
|
12766
|
+
];
|
|
12767
|
+
if (!snapshot.root)
|
|
12768
|
+
lines.push(tuiTheme.muted("Chat normally \xB7 /goal for durable work \xB7 /help"));
|
|
12769
|
+
if (snapshot.team.length)
|
|
12770
|
+
lines.push(tuiTheme.muted(`${snapshot.team.length} Goal Agent${snapshot.team.length === 1 ? "" : "s"} in the organization`));
|
|
12771
|
+
this.details = new Text(lines.join("\n"), 0, 0);
|
|
12772
|
+
this.horizontal = new HStack([
|
|
12773
|
+
{ component: this.mark, basis: 14, shrink: 0 },
|
|
12774
|
+
{ component: this.details, grow: 1, minSize: 24 }
|
|
12775
|
+
], { gap: 2, align: "center" });
|
|
12776
|
+
}
|
|
12777
|
+
render(width) {
|
|
12778
|
+
const contentWidth = Math.max(1, width - 4);
|
|
12779
|
+
if (width < 58) {
|
|
12780
|
+
return ["", ...this.mark.render(Math.min(14, contentWidth)).map((line) => ` ${line}`), "", ...this.details.render(contentWidth).map((line) => ` ${line}`), ""];
|
|
12781
|
+
}
|
|
12782
|
+
return ["", ...this.horizontal.render(contentWidth).map((line) => ` ${line}`), ""];
|
|
12783
|
+
}
|
|
12784
|
+
invalidate() {
|
|
12785
|
+
this.mark.invalidate();
|
|
12786
|
+
this.details.invalidate();
|
|
12787
|
+
this.horizontal.invalidate();
|
|
12788
|
+
}
|
|
12789
|
+
};
|
|
12790
|
+
function terminalLogoData() {
|
|
12791
|
+
if (getCapabilities().images !== "kitty")
|
|
12792
|
+
return null;
|
|
12793
|
+
try {
|
|
12794
|
+
return readFileSync2(new URL("./console/goah-orbital-mark.png", import.meta.url)).toString("base64");
|
|
12795
|
+
} catch {
|
|
12796
|
+
return null;
|
|
12797
|
+
}
|
|
12798
|
+
}
|
|
11726
12799
|
var StreamCoordinator = class {
|
|
11727
12800
|
#active = null;
|
|
11728
12801
|
#pending = null;
|
|
@@ -11780,7 +12853,7 @@ var StreamCoordinator = class {
|
|
|
11780
12853
|
}
|
|
11781
12854
|
};
|
|
11782
12855
|
function renderUserMessage(content, width) {
|
|
11783
|
-
return new Text(content, 2,
|
|
12856
|
+
return new Text(content, 2, 0, tuiTheme.userMessage).render(width);
|
|
11784
12857
|
}
|
|
11785
12858
|
function renderTuiHeader(width, runner, target, version) {
|
|
11786
12859
|
const brand = " GOAH ";
|
|
@@ -11800,40 +12873,76 @@ function statusText(mode, queued = 0) {
|
|
|
11800
12873
|
return tuiTheme.accent("opening setup\u2026");
|
|
11801
12874
|
return `${tuiTheme.muted("ready")} ${tuiTheme.accent("/help")}`;
|
|
11802
12875
|
}
|
|
12876
|
+
var TUI_COMMANDS = [
|
|
12877
|
+
{ name: "goal", action: "goal", description: "Start or revise durable work", argumentHint: "<objective>", acceptsArguments: true, requiresArgument: true },
|
|
12878
|
+
{ name: "model", action: "model", description: "Choose a provider and model", argumentHint: "[provider/model]", acceptsArguments: true },
|
|
12879
|
+
{ name: "status", action: "status", description: "Inspect the current workspace" },
|
|
12880
|
+
{ name: "setup", action: "setup", description: "Configure Goah", argumentHint: "[runner|model|auth]", acceptsArguments: true },
|
|
12881
|
+
{ name: "records", action: "records", description: "Browse current work records", argumentHint: "[goal]", acceptsArguments: true },
|
|
12882
|
+
{ name: "history", action: "records", description: "Show a Goal's record history", argumentHint: "<goal>", acceptsArguments: true, requiresArgument: true },
|
|
12883
|
+
{ name: "observe", action: "goal", description: "Set how the active Goal is observed", argumentHint: "<method>", acceptsArguments: true, requiresArgument: true },
|
|
12884
|
+
{ name: "login", action: "login", description: "Add provider credentials", argumentHint: "[provider]", acceptsArguments: true },
|
|
12885
|
+
{ name: "logout", action: "logout", description: "Remove provider credentials", argumentHint: "[provider]", acceptsArguments: true },
|
|
12886
|
+
{ name: "stop", action: "stop", description: "Stop the current Turn" },
|
|
12887
|
+
{ name: "help", action: "help", description: "Show all commands" },
|
|
12888
|
+
{ name: "quit", action: "quit", description: "Leave Goah", aliases: ["exit"] }
|
|
12889
|
+
];
|
|
12890
|
+
function commandDefinition(text) {
|
|
12891
|
+
const token = text.trim().split(/\s+/, 1)[0] ?? "";
|
|
12892
|
+
if (!token.startsWith("/"))
|
|
12893
|
+
return null;
|
|
12894
|
+
const name = token.slice(1);
|
|
12895
|
+
const definition = TUI_COMMANDS.find((candidate) => candidate.name === name || candidate.aliases?.includes(name));
|
|
12896
|
+
if (!definition)
|
|
12897
|
+
return null;
|
|
12898
|
+
return { definition, hasArguments: Boolean(text.trim().slice(token.length).trim()) };
|
|
12899
|
+
}
|
|
12900
|
+
function commandAwaitingArgument(text) {
|
|
12901
|
+
const match = commandDefinition(text);
|
|
12902
|
+
return match && match.definition.requiresArgument && !match.hasArguments ? `/${match.definition.name} ` : null;
|
|
12903
|
+
}
|
|
12904
|
+
function createTuiAutocompleteProvider(basePath = process.cwd()) {
|
|
12905
|
+
const commands = TUI_COMMANDS.map(({ name, description, argumentHint, getArgumentCompletions }) => ({ name, ...description ? { description } : {}, ...argumentHint ? { argumentHint } : {}, ...getArgumentCompletions ? { getArgumentCompletions } : {} }));
|
|
12906
|
+
return new CombinedAutocompleteProvider(commands, basePath);
|
|
12907
|
+
}
|
|
12908
|
+
function renderTuiCommandHelp() {
|
|
12909
|
+
return [tuiTheme.strong("Commands"), ...TUI_COMMANDS.map((command) => {
|
|
12910
|
+
const invocation = `/${command.name}${command.argumentHint ? ` ${command.argumentHint}` : ""}`;
|
|
12911
|
+
return ` ${invocation.padEnd(28)} ${tuiTheme.muted(command.description ?? "")}`;
|
|
12912
|
+
}), "", tuiTheme.strong("Keyboard"), ` ${"Ctrl+C".padEnd(28)} ${tuiTheme.muted("Clear input \xB7 interrupt current Turn \xB7 exit when idle")}`, ` ${"Ctrl+D".padEnd(28)} ${tuiTheme.muted("Exit when idle")}`, ""].join("\n");
|
|
12913
|
+
}
|
|
11803
12914
|
function classifyTuiInput(value, busy) {
|
|
11804
12915
|
const text = value.trim();
|
|
11805
12916
|
if (!text)
|
|
11806
12917
|
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 };
|
|
12918
|
+
const command = commandDefinition(text);
|
|
12919
|
+
if (command) {
|
|
12920
|
+
if (command.hasArguments && !command.definition.acceptsArguments)
|
|
12921
|
+
return { action: "unknown", text };
|
|
12922
|
+
return { action: command.definition.action, text };
|
|
12923
|
+
}
|
|
11827
12924
|
if (text.startsWith("/"))
|
|
11828
12925
|
return { action: "unknown", text };
|
|
11829
12926
|
return { action: busy ? "steer" : "send", text };
|
|
11830
12927
|
}
|
|
12928
|
+
function classifyTuiControlKey(data, inputText, busy) {
|
|
12929
|
+
if (isKeyRelease(data))
|
|
12930
|
+
return "forward";
|
|
12931
|
+
if (matchesKey(data, Key.ctrl("c"))) {
|
|
12932
|
+
if (inputText.length > 0)
|
|
12933
|
+
return "clear";
|
|
12934
|
+
return busy ? "interrupt" : "exit";
|
|
12935
|
+
}
|
|
12936
|
+
if (matchesKey(data, Key.ctrl("d")) && !inputText && !busy)
|
|
12937
|
+
return "exit";
|
|
12938
|
+
return "forward";
|
|
12939
|
+
}
|
|
11831
12940
|
async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
11832
12941
|
if (!process.stdout.isTTY || !process.stdin.isTTY)
|
|
11833
12942
|
return runNonInteractive(configPath, stateDir, initialMessage);
|
|
11834
12943
|
const runner = readRunnerDisplay(configPath);
|
|
11835
12944
|
const snapshot = welcomeSnapshot(stateDir, runner);
|
|
11836
|
-
const
|
|
12945
|
+
const hasHistory = Boolean(snapshot.root || snapshot.handoffs.length || snapshot.conversation.length);
|
|
11837
12946
|
await ensureDaemon(configPath, stateDir);
|
|
11838
12947
|
const liveSnapshot = await requestControl(stateDir, { op: "status" }).catch(() => null);
|
|
11839
12948
|
const liveTurns = liveSnapshot && typeof liveSnapshot === "object" && !Array.isArray(liveSnapshot) && Array.isArray(liveSnapshot.turns) ? liveSnapshot.turns : [];
|
|
@@ -11842,7 +12951,8 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
11842
12951
|
const tui = new TuiAltScreen(terminal, true, void 0, { mouse: true });
|
|
11843
12952
|
terminal.setTitle(`Goah \xB7 ${runner.target}`);
|
|
11844
12953
|
const headerView = new HeaderBar(runner.runner, runner.target, installedVersion());
|
|
11845
|
-
const transcriptView = new ConversationView(
|
|
12954
|
+
const transcriptView = new ConversationView([]);
|
|
12955
|
+
transcriptView.addComponent(new WelcomeLockup(snapshot, hasHistory, terminalLogoData()));
|
|
11846
12956
|
for (const row of snapshot.conversation)
|
|
11847
12957
|
if (row.speaker === "You")
|
|
11848
12958
|
transcriptView.addUser(row.text);
|
|
@@ -11854,13 +12964,14 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
11854
12964
|
borderColor: tuiTheme.accent,
|
|
11855
12965
|
selectList: { selectedPrefix: tuiTheme.accent, selectedText: tuiTheme.strong, description: tuiTheme.muted, scrollInfo: tuiTheme.muted, noMatch: tuiTheme.error }
|
|
11856
12966
|
}, { paddingX: 1, autocompleteMaxVisible: 6 });
|
|
12967
|
+
input.setAutocompleteProvider(createTuiAutocompleteProvider());
|
|
11857
12968
|
const statusView = new Text(statusText("ready"), 1, 0);
|
|
11858
12969
|
const shell = new VStack([
|
|
11859
12970
|
{ component: headerView, basis: 1, shrink: 0 },
|
|
11860
12971
|
{ component: conversationScroll, grow: 1, minSize: 1 },
|
|
11861
12972
|
{ component: goalView, basis: 1, shrink: 0 },
|
|
11862
12973
|
{ component: statusView, basis: 1, shrink: 0 },
|
|
11863
|
-
{ component: input, basis: "auto", minSize: 3, maxSize:
|
|
12974
|
+
{ component: input, basis: "auto", minSize: 3, maxSize: 11, shrink: 0 }
|
|
11864
12975
|
]);
|
|
11865
12976
|
const busy = { active: false };
|
|
11866
12977
|
const queued = [];
|
|
@@ -11870,6 +12981,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
11870
12981
|
let steeringTail = Promise.resolve();
|
|
11871
12982
|
let configuring = false;
|
|
11872
12983
|
let exiting = false;
|
|
12984
|
+
let interrupting = false;
|
|
11873
12985
|
const push = (line) => {
|
|
11874
12986
|
transcriptView.addText(line);
|
|
11875
12987
|
tui.requestRender();
|
|
@@ -11902,6 +13014,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
11902
13014
|
};
|
|
11903
13015
|
const finishIdle = async () => {
|
|
11904
13016
|
busy.active = false;
|
|
13017
|
+
interrupting = false;
|
|
11905
13018
|
await refreshGoalBar(stateDir, goalView, tui);
|
|
11906
13019
|
statusView.setText(statusText(queuedTurnIds.length || queued.length ? "queued" : "ready", queuedTurnIds.length + queued.length));
|
|
11907
13020
|
continuePending();
|
|
@@ -12017,6 +13130,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12017
13130
|
if (!streams.complete(controller))
|
|
12018
13131
|
return;
|
|
12019
13132
|
busy.active = false;
|
|
13133
|
+
interrupting = false;
|
|
12020
13134
|
await refreshGoalBar(stateDir, goalView, tui);
|
|
12021
13135
|
statusView.setText(statusText("ready"));
|
|
12022
13136
|
continuePending();
|
|
@@ -12137,6 +13251,11 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12137
13251
|
push(await reloadDaemon(stateDir, configPath) ? "Configuration updated \u2014 applies to the next Turn." : "Configuration saved \u2014 restart Goah to apply it.");
|
|
12138
13252
|
});
|
|
12139
13253
|
input.onSubmit = (line) => {
|
|
13254
|
+
const waiting = commandAwaitingArgument(line);
|
|
13255
|
+
if (waiting) {
|
|
13256
|
+
input.setText(waiting);
|
|
13257
|
+
return;
|
|
13258
|
+
}
|
|
12140
13259
|
const { action, text } = classifyTuiInput(line, busy.active);
|
|
12141
13260
|
input.setText("");
|
|
12142
13261
|
if (action === "quit") {
|
|
@@ -12147,10 +13266,7 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12147
13266
|
return;
|
|
12148
13267
|
}
|
|
12149
13268
|
if (action === "help") {
|
|
12150
|
-
push(
|
|
12151
|
-
/model /login /logout /setup /status
|
|
12152
|
-
/records /history /goal /observe /stop /quit
|
|
12153
|
-
`);
|
|
13269
|
+
push(renderTuiCommandHelp());
|
|
12154
13270
|
return;
|
|
12155
13271
|
}
|
|
12156
13272
|
if (action === "status") {
|
|
@@ -12203,10 +13319,22 @@ async function runGoahTui(configPath, stateDir, initialMessage) {
|
|
|
12203
13319
|
tui.setFocus(input);
|
|
12204
13320
|
const { promise: exited, resolve: resolveExit } = Promise.withResolvers();
|
|
12205
13321
|
tui.addInputListener((data) => {
|
|
12206
|
-
|
|
13322
|
+
const action = classifyTuiControlKey(data, input.getText(), busy.active);
|
|
13323
|
+
if (action === "forward")
|
|
12207
13324
|
return void 0;
|
|
13325
|
+
if (action === "clear") {
|
|
13326
|
+
input.setText("");
|
|
13327
|
+
tui.requestRender();
|
|
13328
|
+
return { consume: true };
|
|
13329
|
+
}
|
|
13330
|
+
if (action === "interrupt" && !interrupting) {
|
|
13331
|
+
interrupting = true;
|
|
13332
|
+
statusView.setText(`${tuiTheme.warning("stopping")} ${tuiTheme.muted("press Ctrl+C again to exit")}`);
|
|
13333
|
+
tui.requestRender();
|
|
13334
|
+
void stopCeoWake(stateDir, push);
|
|
13335
|
+
return { consume: true };
|
|
13336
|
+
}
|
|
12208
13337
|
exiting = true;
|
|
12209
|
-
push(busy.active ? "Detached \u2014 the current Turn continues in the daemon. Use /stop before detaching when you intend to cancel it." : "Detached.");
|
|
12210
13338
|
streams.abortAll();
|
|
12211
13339
|
tui.stop();
|
|
12212
13340
|
resolveExit();
|
|
@@ -12465,8 +13593,8 @@ async function ensureDaemon(configPath, stateDir) {
|
|
|
12465
13593
|
await new Promise((resolveWait) => setTimeout(resolveWait, 50));
|
|
12466
13594
|
}
|
|
12467
13595
|
mkdirSync(stateDir, { recursive: true });
|
|
12468
|
-
const log = openSync(
|
|
12469
|
-
|
|
13596
|
+
const log = openSync(join6(stateDir, "daemon.log"), "a");
|
|
13597
|
+
spawn3(process.execPath, [process.argv[1], "start", "--config", resolve2(configPath)], { cwd: process.cwd(), detached: true, stdio: ["ignore", log, log], env: process.env }).unref();
|
|
12470
13598
|
closeSync(log);
|
|
12471
13599
|
const deadline = Date.now() + 1e4;
|
|
12472
13600
|
while (Date.now() < deadline) {
|
|
@@ -12826,7 +13954,7 @@ async function main() {
|
|
|
12826
13954
|
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
13955
|
console.log(JSON.stringify({ goal }, null, 2));
|
|
12828
13956
|
} else if (command === "dashboard") {
|
|
12829
|
-
const path4 = option("--output") ??
|
|
13957
|
+
const path4 = option("--output") ?? join7(config.stateDir, "status.html");
|
|
12830
13958
|
writeFileSync(path4, (await import("./dist-KNR2XL6J.js")).renderDashboard(ledger));
|
|
12831
13959
|
console.log(path4);
|
|
12832
13960
|
} else
|
|
@@ -12863,8 +13991,8 @@ async function ensureDaemon2(configPath, stateDir) {
|
|
|
12863
13991
|
await new Promise((resolveWait) => setTimeout(resolveWait, 50));
|
|
12864
13992
|
}
|
|
12865
13993
|
mkdirSync2(stateDir, { recursive: true });
|
|
12866
|
-
const log = openSync2(
|
|
12867
|
-
const child =
|
|
13994
|
+
const log = openSync2(join7(stateDir, "daemon.log"), "a");
|
|
13995
|
+
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
13996
|
closeSync2(log);
|
|
12869
13997
|
child.unref();
|
|
12870
13998
|
const deadline = Date.now() + 1e4;
|
|
@@ -12880,7 +14008,7 @@ async function ensureDaemon2(configPath, stateDir) {
|
|
|
12880
14008
|
function openUrl2(url) {
|
|
12881
14009
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
12882
14010
|
const args2 = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
12883
|
-
const child =
|
|
14011
|
+
const child = spawn4(command, args2, { detached: true, stdio: "ignore" });
|
|
12884
14012
|
child.unref();
|
|
12885
14013
|
}
|
|
12886
14014
|
function remoteRequest(command) {
|
|
@@ -13072,7 +14200,7 @@ async function runRunnerCommand(command, commandArgs, configPath) {
|
|
|
13072
14200
|
async function runRunnerEarly(configPath) {
|
|
13073
14201
|
const action = args[1] ?? "list";
|
|
13074
14202
|
if (action === "list") {
|
|
13075
|
-
for (const manifest of (await import("./runner-registry-
|
|
14203
|
+
for (const manifest of (await import("./runner-registry-GD4BYCQC.js")).runnerManifests())
|
|
13076
14204
|
console.log(`${manifest.id.padEnd(16)} ${manifest.description}`);
|
|
13077
14205
|
return;
|
|
13078
14206
|
}
|
|
@@ -13132,7 +14260,7 @@ async function runRunnerManagement(config, configPath) {
|
|
|
13132
14260
|
throw new Error("usage: goah runner profile assign AGENT PROFILE");
|
|
13133
14261
|
if (!config.runnerProfiles?.some((profile) => profile.id === profileId))
|
|
13134
14262
|
throw new Error(`Runner Profile not found: ${profileId}`);
|
|
13135
|
-
const raw = JSON.parse(
|
|
14263
|
+
const raw = JSON.parse(readFileSync3(resolve3(configPath), "utf8"));
|
|
13136
14264
|
const target = raw.profiles?.find((profile) => profile.agent === agent);
|
|
13137
14265
|
if (!target)
|
|
13138
14266
|
throw new Error(`Agent profile not found: ${agent}`);
|
|
@@ -13173,12 +14301,12 @@ async function runDaemonCommand(config, configPath) {
|
|
|
13173
14301
|
return;
|
|
13174
14302
|
}
|
|
13175
14303
|
if (action === "logs") {
|
|
13176
|
-
const path4 =
|
|
14304
|
+
const path4 = join7(config.stateDir, "daemon.log");
|
|
13177
14305
|
if (!existsSync3(path4)) {
|
|
13178
14306
|
console.log(`No daemon log at ${path4}`);
|
|
13179
14307
|
return;
|
|
13180
14308
|
}
|
|
13181
|
-
console.log(
|
|
14309
|
+
console.log(readFileSync3(path4, "utf8").split("\n").slice(-100).join("\n"));
|
|
13182
14310
|
return;
|
|
13183
14311
|
}
|
|
13184
14312
|
if (action === "stop" || action === "restart") {
|
|
@@ -13211,7 +14339,7 @@ function stdioInteraction() {
|
|
|
13211
14339
|
};
|
|
13212
14340
|
}
|
|
13213
14341
|
function packageVersion() {
|
|
13214
|
-
return JSON.parse(
|
|
14342
|
+
return JSON.parse(readFileSync3(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
13215
14343
|
}
|
|
13216
14344
|
function closestCommand(value) {
|
|
13217
14345
|
let best = null;
|