@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.
@@ -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
- if (scope === "model" && before?.provider === providerId)
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
- const existing = scope === "model" ? await new JsonCredentialStore(config.authFile).read(providerId) : null;
555
- if (scope === "model")
556
- config.authMode = existing?.type === "oauth" ? "oauth" : existing ? "stored-key" : "unconfigured";
557
- else {
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
- return { config: next, output: [`Pi target changed to ${provider}/${model}`] };
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-X7UWW2PN.js";
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-VWEV4LTH.js";
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-X7UWW2PN.js";
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-PFEV3HWI.js";
28
+ } from "./chunk-KJ4HJCTK.js";
29
29
  import {
30
30
  runnerManifests,
31
31
  runnerPlugin
32
- } from "./chunk-VWEV4LTH.js";
32
+ } from "./chunk-D2DVAH37.js";
33
33
  import "./chunk-YH6YJ2IB.js";
34
34
  import "./chunk-QBD6EJ2Z.js";
35
- import "./chunk-X7UWW2PN.js";
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 spawn3 } from "node:child_process";
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 join6, resolve as resolve3 } from "node:path";
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 join4 } from "node:path";
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("2", value),
11277
- subtle: (value) => paint("2", value),
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
- " \u2584\u2584",
11290
- " \u2584\u2580\u2580 \u2588\u2584",
11291
- " \u2584\u2584\u2588\u2588\u2580\u2588\u2580\u2580 \u2588",
11292
- " \u2588\u2580 \u2588 \u2588\u2588\u2588\u2588 \u2588 \u2584\u2588",
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 = join4(stateDir, "ledger.sqlite");
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
- spawn(command, args2, { detached: true, stdio: "ignore" }).unref();
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 spawn2 } from "node:child_process";
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 join5, resolve as resolve2 } from "node:path";
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, 1, tuiTheme.userMessage).render(width);
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
- if (text === "/quit" || text === "/exit")
11808
- return { action: "quit", text };
11809
- if (text === "/help")
11810
- return { action: "help", text };
11811
- if (text === "/status")
11812
- return { action: "status", text };
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: 8, shrink: 0 }
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(`${tuiTheme.strong("Commands")}
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(join5(stateDir, "daemon.log"), "a");
12469
- spawn2(process.execPath, [process.argv[1], "start", "--config", resolve2(configPath)], { cwd: process.cwd(), detached: true, stdio: ["ignore", log, log], env: process.env }).unref();
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") ?? join6(config.stateDir, "status.html");
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(join6(stateDir, "daemon.log"), "a");
12867
- const child = spawn3(process.execPath, [process.argv[1], "start", "--config", resolve3(configPath)], { cwd: process.cwd(), detached: true, stdio: ["ignore", log, log], env: process.env });
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 = spawn3(command, args2, { detached: true, stdio: "ignore" });
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-M776E3SE.js")).runnerManifests())
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 = join6(config.stateDir, "daemon.log");
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-X7UWW2PN.js";
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-PFEV3HWI.js";
35
- import "./chunk-VWEV4LTH.js";
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-X7UWW2PN.js";
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
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-XALZLRYK.js";
6
6
  import {
7
7
  runProcessWorker
8
- } from "./chunk-X7UWW2PN.js";
8
+ } from "./chunk-7E7V6OIU.js";
9
9
  import {
10
10
  createPiModel,
11
11
  fauxAssistantMessage,
package/dist/runner-pi.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  resolveEnvSpec,
12
12
  runProcessWorker,
13
13
  verificationWorkerPath
14
- } from "./chunk-X7UWW2PN.js";
14
+ } from "./chunk-7E7V6OIU.js";
15
15
  import {
16
16
  LOCAL_PROVIDERS,
17
17
  defaultAuthFile,
@@ -3,8 +3,8 @@ const require = __goahCreateRequire(import.meta.url);
3
3
  import {
4
4
  runnerManifests,
5
5
  runnerPlugin
6
- } from "./chunk-VWEV4LTH.js";
7
- import "./chunk-X7UWW2PN.js";
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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goah/cli",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "license": "Apache-2.0",
5
5
  "repository": {
6
6
  "type": "git",