@garuda-agent/garuda 0.18.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +3 -2
  3. package/dist/{acpCommand-IUZPLPLI.js → acpCommand-JAYNMIMP.js} +17 -14
  4. package/dist/advise-HDKJGNBL.js +195 -0
  5. package/dist/brief-RWKESOPT.js +91 -0
  6. package/dist/buildCheck-HB46NWLX.js +19 -0
  7. package/dist/buildInfo-K73FFI5S.js +8 -0
  8. package/dist/chunk-2OYTNNUJ.js +216 -0
  9. package/dist/{chunk-OQ26W5L4.js → chunk-34WBDQBL.js} +134 -77
  10. package/dist/chunk-4QRTTRVK.js +88 -0
  11. package/dist/{chunk-NHWHG3SW.js → chunk-5UDYQ5MK.js} +354 -59
  12. package/dist/chunk-CWVXOSAA.js +894 -0
  13. package/dist/{chunk-FARS4R67.js → chunk-DQSCCE77.js} +18 -1
  14. package/dist/chunk-DUYLVGPY.js +821 -0
  15. package/dist/{chunk-Q4P3W657.js → chunk-GKU62MHQ.js} +10 -1124
  16. package/dist/chunk-H7LIBGZT.js +9 -0
  17. package/dist/{chunk-FOPBOB7W.js → chunk-IKPGHM54.js} +6 -4
  18. package/dist/chunk-IYGJWX65.js +9 -0
  19. package/dist/{chunk-65NUEOI7.js → chunk-JMH5W5DG.js} +1 -44
  20. package/dist/chunk-L55VUSX3.js +54 -0
  21. package/dist/{chunk-B4SJY7KT.js → chunk-LMKGSYJC.js} +77 -8
  22. package/dist/{chunk-23FXBNBB.js → chunk-MNE7HHX2.js} +2 -1
  23. package/dist/chunk-NH72AELP.js +48 -0
  24. package/dist/{chunk-UKIE4AAM.js → chunk-NLS7GMF7.js} +11 -105
  25. package/dist/{chunk-2FIV2VZP.js → chunk-QLBCM2YQ.js} +2 -2
  26. package/dist/{chunk-6XHON3Q6.js → chunk-QXTHEFKP.js} +3 -3
  27. package/dist/{chunk-4BVCYCQT.js → chunk-R7RCW4BQ.js} +9 -7
  28. package/dist/chunk-TLA2PDGM.js +156 -0
  29. package/dist/{chunk-5B5HDTUR.js → chunk-TWQ7V2L6.js} +2 -2
  30. package/dist/chunk-ULAJPMY7.js +107 -0
  31. package/dist/chunk-VISKX36R.js +306 -0
  32. package/dist/{chunk-55CFEEIN.js → chunk-WK5NE6RY.js} +2 -2
  33. package/dist/chunk-Y62J7PTD.js +90 -0
  34. package/dist/chunk-YAQ6QLKB.js +40 -0
  35. package/dist/{chunk-7TH3NHCQ.js → chunk-ZKT4P2PC.js} +2 -2
  36. package/dist/cli/index.js +252 -61
  37. package/dist/{create-W6BV75QX.js → create-OACSGJ37.js} +5 -5
  38. package/dist/{evalCommand-SKJQ6CW2.js → evalCommand-BLJJ4G76.js} +43 -33
  39. package/dist/{evalTune-CZRCPSZ3.js → evalTune-W53KAD4V.js} +25 -18
  40. package/dist/{export-SJ3DUP6W.js → export-E677HIQS.js} +27 -4
  41. package/dist/exportHtml-BMV73YRO.js +21 -0
  42. package/dist/{inkChat-WYYAFZXD.js → inkChat-EVLYDC3K.js} +258 -42
  43. package/dist/{install-TKWN5AYH.js → install-4ST5BNRG.js} +3 -3
  44. package/dist/{jobCommand-2ODQLHB3.js → jobCommand-ILOTYOX3.js} +8 -7
  45. package/dist/{launchd-3A3ONEW5.js → launchd-QG6R5RAK.js} +4 -4
  46. package/dist/{lspCommand-ZZ6R4PA2.js → lspCommand-X4FTTONR.js} +3 -3
  47. package/dist/{manager-TCYTA5XU.js → manager-L25IUXHW.js} +3 -3
  48. package/dist/{nightCommand-WJU6VZA6.js → nightCommand-XPWT6CQZ.js} +8 -7
  49. package/dist/receiptView-YFDHV253.js +19 -0
  50. package/dist/{remove-42WQNVPX.js → remove-STX5UO7X.js} +3 -3
  51. package/dist/{run-PTMRQCIU.js → run-W4TK52WT.js} +5 -5
  52. package/dist/{server-VEYIJHEU.js → server-ASM73QVY.js} +3 -3
  53. package/dist/{setupCommand-YMF6I3MD.js → setupCommand-OSOMFHDQ.js} +9 -8
  54. package/dist/tour-CEVMAC5S.js +18 -0
  55. package/dist/tune-VX2WQTHS.js +52 -0
  56. package/dist/uiState-YFJQ43D7.js +16 -0
  57. package/package.json +1 -1
  58. package/dist/chunk-4JSUUDFQ.js +0 -118
  59. package/dist/chunk-C57GHLKP.js +0 -9
  60. package/dist/chunk-DOCDCQVM.js +0 -484
  61. package/dist/tune-YVI2KWQF.js +0 -31
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ git
4
+ } from "./chunk-QXTHEFKP.js";
5
+ import {
6
+ HostExecutor
7
+ } from "./chunk-LMKGSYJC.js";
8
+
9
+ // src/buildCheck.ts
10
+ import { existsSync } from "fs";
11
+ import { dirname, join } from "path";
12
+ import { fileURLToPath } from "url";
13
+ async function garudaCommit() {
14
+ let dir;
15
+ try {
16
+ dir = dirname(fileURLToPath(import.meta.url));
17
+ } catch {
18
+ return void 0;
19
+ }
20
+ for (let i = 0; i < 4; i++) {
21
+ if (existsSync(join(dir, ".git"))) {
22
+ const r = await git(new HostExecutor(), dir, ["rev-parse", "HEAD"], { check: false });
23
+ return r.exitCode === 0 ? r.stdout.trim() : void 0;
24
+ }
25
+ dir = dirname(dir);
26
+ }
27
+ return void 0;
28
+ }
29
+ function staleBuildNote(build, checkout, what = "The tasks and the code that run are the older ones") {
30
+ if (build === void 0 || checkout === void 0 || build === checkout) return void 0;
31
+ return `This build is from commit ${build.slice(0, 7)}, but the checkout is at ${checkout.slice(0, 7)}. ${what}: run pnpm build first.`;
32
+ }
33
+ var CHAT_STALE = "The code that runs is the older one";
34
+
35
+ export {
36
+ garudaCommit,
37
+ staleBuildNote,
38
+ CHAT_STALE
39
+ };
40
+ //# sourceMappingURL=chunk-YAQ6QLKB.js.map
@@ -6,7 +6,7 @@ import {
6
6
  } from "./chunk-EU7PA45O.js";
7
7
  import {
8
8
  DEFAULT_ENV_ALLOWLIST
9
- } from "./chunk-B4SJY7KT.js";
9
+ } from "./chunk-LMKGSYJC.js";
10
10
 
11
11
  // src/lsp/install.ts
12
12
  import { mkdir } from "fs/promises";
@@ -70,4 +70,4 @@ export {
70
70
  installCommand,
71
71
  installServer
72
72
  };
73
- //# sourceMappingURL=chunk-7TH3NHCQ.js.map
73
+ //# sourceMappingURL=chunk-ZKT4P2PC.js.map
package/dist/cli/index.js CHANGED
@@ -1,39 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  BUILD_PROMPT,
4
+ CONTINUE_PROMPT,
4
5
  CommandArgs,
5
6
  FOCUS_REPORTING_OFF,
6
7
  FocusTracker,
8
+ SUMMARY_PROMPT,
7
9
  commandNames,
8
10
  complete,
9
11
  describeError,
10
- formatTokens,
11
12
  planHandoff,
12
13
  reportsFocus,
13
14
  rootFiles,
14
15
  rootLister,
15
16
  runCommand,
16
17
  runTurnInTerminal,
17
- stopMessage
18
- } from "../chunk-OQ26W5L4.js";
19
- import {
20
- SwitchApprover,
21
- TerminalApprover
22
- } from "../chunk-4JSUUDFQ.js";
23
- import {
24
- PlainRenderer
25
- } from "../chunk-FARS4R67.js";
18
+ stopHandoff
19
+ } from "../chunk-34WBDQBL.js";
26
20
  import {
27
21
  AutoApprover
28
22
  } from "../chunk-NXJ4XLB5.js";
29
- import {
30
- NO_MODEL,
31
- chooseModel,
32
- keepProviderKeys,
33
- loadModelsConfig,
34
- providerKeySource,
35
- resolveModel
36
- } from "../chunk-2FIV2VZP.js";
37
23
  import {
38
24
  DEFAULT_MAX_TOKENS,
39
25
  Runtime,
@@ -43,16 +29,38 @@ import {
43
29
  rebuildState,
44
30
  runAgent,
45
31
  signature
46
- } from "../chunk-NHWHG3SW.js";
47
- import {
48
- loadCatalog
49
- } from "../chunk-65NUEOI7.js";
32
+ } from "../chunk-5UDYQ5MK.js";
50
33
  import "../chunk-G2AX7MGS.js";
51
- import "../chunk-A2QAIRQL.js";
52
34
  import {
53
35
  Notifier,
54
36
  pickChannel
55
37
  } from "../chunk-N4I6YS3E.js";
38
+ import "../chunk-ULAJPMY7.js";
39
+ import {
40
+ loadCatalog
41
+ } from "../chunk-JMH5W5DG.js";
42
+ import {
43
+ NO_MODEL,
44
+ chooseModel,
45
+ keepProviderKeys,
46
+ loadModelsConfig,
47
+ providerKeySource,
48
+ resolveModel
49
+ } from "../chunk-QLBCM2YQ.js";
50
+ import "../chunk-NH72AELP.js";
51
+ import {
52
+ SwitchApprover,
53
+ TerminalApprover
54
+ } from "../chunk-VISKX36R.js";
55
+ import {
56
+ PlainRenderer
57
+ } from "../chunk-DQSCCE77.js";
58
+ import "../chunk-4QRTTRVK.js";
59
+ import "../chunk-A2QAIRQL.js";
60
+ import {
61
+ formatTokens,
62
+ stopMessage
63
+ } from "../chunk-2OYTNNUJ.js";
56
64
  import {
57
65
  FileSessionStore,
58
66
  closeOpenToolCalls,
@@ -63,18 +71,22 @@ import {
63
71
  popPoint,
64
72
  pushPoint,
65
73
  redoPoint
66
- } from "../chunk-UKIE4AAM.js";
74
+ } from "../chunk-NLS7GMF7.js";
67
75
  import "../chunk-7KBOIPUT.js";
76
+ import {
77
+ tourChoice
78
+ } from "../chunk-Y62J7PTD.js";
68
79
  import {
69
80
  loadSearchConfig
70
81
  } from "../chunk-B25VL4RU.js";
71
82
  import {
72
83
  BUILTIN_COMMANDS
73
- } from "../chunk-23FXBNBB.js";
84
+ } from "../chunk-MNE7HHX2.js";
85
+ import "../chunk-42DSA4EA.js";
74
86
  import "../chunk-EU7PA45O.js";
75
87
  import {
76
88
  VERSION
77
- } from "../chunk-C57GHLKP.js";
89
+ } from "../chunk-IYGJWX65.js";
78
90
  import "../chunk-5DEWP3YX.js";
79
91
  import "../chunk-PZS3V6P3.js";
80
92
  import "../chunk-QANRZW7W.js";
@@ -82,7 +94,7 @@ import "../chunk-ATW7BNIG.js";
82
94
  import "../chunk-AOGFYUKG.js";
83
95
  import {
84
96
  JOB_DENIAL
85
- } from "../chunk-B4SJY7KT.js";
97
+ } from "../chunk-LMKGSYJC.js";
86
98
  import "../chunk-BHZ6G65V.js";
87
99
  import "../chunk-P6XWWIEK.js";
88
100
  import "../chunk-VTMD5IHD.js";
@@ -95,6 +107,7 @@ import { existsSync, readFileSync, realpathSync } from "fs";
95
107
  import { homedir as homedir2 } from "os";
96
108
  import { join } from "path";
97
109
  import { Writable } from "stream";
110
+ import { styleText } from "util";
98
111
  import { Command, Option } from "commander";
99
112
 
100
113
  // src/loop/replay.ts
@@ -297,6 +310,37 @@ function compare(a, b) {
297
310
 
298
311
  // src/cli/banner.ts
299
312
  import { homedir } from "os";
313
+ var WORDMARK_LARGE_COLUMNS = 130;
314
+ function wordmark3d(scale, face, shadow) {
315
+ const rows = WORDMARK.map((row) => row.padEnd(Math.max(...WORDMARK.map((r) => r.length))));
316
+ const lit = (x, y) => x >= 0 && y >= 0 && rows[Math.floor(y / scale)]?.[Math.floor(x / scale)] === "\u2588";
317
+ const dx = scale;
318
+ const dy = 1;
319
+ const width = (rows[0]?.length ?? 0) * scale + dx;
320
+ const height = rows.length * scale + dy;
321
+ const out = [];
322
+ for (let y = 0; y < height; y++) {
323
+ let line = "";
324
+ for (let x = 0; x < width; x++) {
325
+ line += lit(x, y) ? face(x, width) : lit(x - dx, y - dy) ? shadow(x, width) : " ";
326
+ }
327
+ out.push(line.replace(/\s+$/, ""));
328
+ }
329
+ return out;
330
+ }
331
+ function visibleWidth(line) {
332
+ return [...line.replace(/\u001b\[[0-9;]*m/g, "")].length;
333
+ }
334
+ function centerBlock(lines, width, columns) {
335
+ const pad = Math.floor((columns - width) / 2);
336
+ return pad <= 0 ? [...lines] : lines.map((line) => `${" ".repeat(pad)}${line}`);
337
+ }
338
+ function centerLines(lines, columns) {
339
+ return lines.map((line) => {
340
+ const pad = Math.floor((columns - visibleWidth(line)) / 2);
341
+ return line === "" || pad <= 0 ? line : `${" ".repeat(pad)}${line}`;
342
+ });
343
+ }
300
344
  var WORDMARK = [
301
345
  " \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 ",
302
346
  "\u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588 \u2588\u2588",
@@ -314,17 +358,38 @@ function colorLevel(stream = process.stdout, env = process.env) {
314
358
  function banner(info, options) {
315
359
  const c = paint(options.color);
316
360
  const lines = [];
317
- if (options.columns >= WORDMARK_MIN_COLUMNS) {
318
- const width = WORDMARK[0]?.length ?? 1;
319
- for (const row of WORDMARK) lines.push(c.gradient(row, width));
320
- lines.push("");
361
+ let markWidth;
362
+ const block = (rows, width) => options.center === true ? centerBlock(rows, width, options.columns) : rows;
363
+ if (options.screenReader === true) {
364
+ } else if (options.center === true && options.columns >= WORDMARK_MIN_COLUMNS) {
365
+ const scale = options.columns >= WORDMARK_LARGE_COLUMNS ? 2 : 1;
366
+ const mark = wordmark3d(scale, c.face, c.shadow);
367
+ const height = mark.length + 12;
368
+ const top = options.rows === void 0 ? 0 : Math.floor((options.rows - height) / 4);
369
+ for (let i = 0; i < Math.min(Math.max(0, top), 6); i++) lines.push("");
370
+ markWidth = Math.max(...mark.map(visibleWidth));
371
+ lines.push(...block(mark, markWidth), "");
372
+ } else if (options.columns >= WORDMARK_MIN_COLUMNS) {
373
+ const width = Math.max(...WORDMARK.map((row) => row.length));
374
+ lines.push(
375
+ ...block(
376
+ WORDMARK.map((row) => c.gradient(row, width)),
377
+ width
378
+ ),
379
+ ""
380
+ );
321
381
  }
322
- lines.push(...card(info, options, c));
382
+ const cardLines = card(info, options, c, markWidth);
383
+ lines.push(...block(cardLines, Math.max(...cardLines.map(visibleWidth))));
323
384
  const tips = info.ink ? "/help \xB7 Esc stops a task \xB7 \\ then Enter: new line \xB7 Ctrl-G editor \xB7 Ctrl-P commands" : "/help \xB7 Ctrl-C stops a task \xB7 \\ at the end: new line";
385
+ if (options.center === true) {
386
+ lines.push(...centerLines([c.dim(tips)], options.columns), "");
387
+ return lines.join("\n");
388
+ }
324
389
  lines.push(c.dim(` ${tips}`), "");
325
390
  return lines.join("\n");
326
391
  }
327
- function card(info, options, c) {
392
+ function card(info, options, c, minWidth) {
328
393
  const home = options.home ?? homedir();
329
394
  const folder = info.root === home || info.root.startsWith(`${home}/`) ? `~${info.root.slice(home.length)}` : info.root;
330
395
  const title = `\u2726 Garuda ${info.version} \xB7 a terminal coding agent`;
@@ -354,7 +419,10 @@ function card(info, options, c) {
354
419
  const labelWidth = Math.max(9, maxLabel + 2);
355
420
  const prefix = 2 + labelWidth;
356
421
  const natural = Math.max(title.length, ...rows.map(([, v]) => prefix + v.length));
357
- const inner = Math.max(20, Math.min(natural + 1, options.columns - 4));
422
+ const inner = Math.max(
423
+ 20,
424
+ Math.min(Math.max(natural + 1, (minWidth ?? 0) - 4), options.columns - 4)
425
+ );
358
426
  const cutStart = (text, max) => text.length <= max ? text : `\u2026${text.slice(text.length - max + 1)}`;
359
427
  const border = (left, right) => c.dim(`${left}${"\u2500".repeat(inner + 2)}${right}`);
360
428
  const line = (plain, styled) => `${c.dim("\u2502")} ${styled}${" ".repeat(Math.max(0, inner - plain.length))} ${c.dim("\u2502")}`;
@@ -378,15 +446,37 @@ function card(info, options, c) {
378
446
  function paint(level) {
379
447
  const esc = (code, text, reset) => `\x1B[${code}m${text}\x1B[${reset}m`;
380
448
  if (level === "none") {
381
- return { gradient: (t) => t, gold: (t) => t, bold: (t) => t, dim: (t) => t };
449
+ return {
450
+ gradient: (t) => t,
451
+ face: () => "\u2588",
452
+ shadow: () => "\u2591",
453
+ gold: (t) => t,
454
+ bold: (t) => t,
455
+ dim: (t) => t
456
+ };
382
457
  }
383
458
  const bold = (t) => esc("1", t, "22");
384
459
  const dim = (t) => esc("2", t, "22");
385
460
  if (level === "basic") {
386
- return { gradient: (t) => esc("33", t, "39"), gold: (t) => esc("33", t, "39"), bold, dim };
461
+ return {
462
+ gradient: (t) => esc("33", t, "39"),
463
+ face: () => esc("33", "\u2588", "39"),
464
+ shadow: () => esc("31", "\u2593", "39"),
465
+ gold: (t) => esc("33", t, "39"),
466
+ bold,
467
+ dim
468
+ };
387
469
  }
388
470
  const rgb = ([r, g, b]) => `38;2;${r};${g};${b}`;
471
+ const mixAt = (x, width) => {
472
+ const t = width <= 1 ? 0 : x / (width - 1);
473
+ return FROM.map((f, k) => Math.round(f + ((TO[k] ?? f) - f) * t));
474
+ };
389
475
  return {
476
+ face: (x, width) => esc(rgb(mixAt(x, width)), "\u2588", "39"),
477
+ // The shadow: the face's colour at half its brightness, so it reads as depth on light and
478
+ // dark backgrounds.
479
+ shadow: (x, width) => esc(rgb(mixAt(x, width).map((v) => Math.round(v * 0.45))), "\u2588", "39"),
390
480
  gradient: (text, width) => [...text].map((ch, i) => {
391
481
  if (ch === " ") return ch;
392
482
  const t = width <= 1 ? 0 : i / (width - 1);
@@ -402,6 +492,36 @@ function paint(level) {
402
492
  // src/cli/jsonOutput.ts
403
493
  import { randomUUID } from "crypto";
404
494
  var OUTPUT_FORMATS = ["text", "json", "stream-json"];
495
+ function receiptJson(r) {
496
+ return {
497
+ turn: r.turn,
498
+ stop_reason: r.stopReason,
499
+ steps: r.steps,
500
+ duration_ms: r.durationMs,
501
+ ...r.costUsd === void 0 ? { cost_is_unknown: true } : { cost_usd: r.costUsd },
502
+ ...r.costIncomplete === true ? { cost_is_incomplete: true } : {},
503
+ files: r.files === void 0 ? null : r.files.map((f) => ({
504
+ path: f.path,
505
+ ...f.added === void 0 ? { binary: true } : { added: f.added, removed: f.removed }
506
+ })),
507
+ ...r.tests === void 0 ? {} : {
508
+ tests: {
509
+ command: r.tests.command,
510
+ passed: r.tests.passed,
511
+ ...r.tests.timedOut === true ? { timed_out: true } : {},
512
+ ...r.tests.total === void 0 ? {} : { total: r.tests.total, failed: r.tests.failed },
513
+ ...r.tests.previousTotal === void 0 ? {} : { previous_total: r.tests.previousTotal }
514
+ }
515
+ },
516
+ commands: {
517
+ sandboxed: r.commands.sandboxed,
518
+ outside: r.commands.outside,
519
+ blocked_hosts: r.commands.blockedHosts
520
+ },
521
+ context_percent: r.contextPercent,
522
+ ...r.keptChanges === void 0 ? {} : { kept_changes: r.keptChanges }
523
+ };
524
+ }
405
525
  var JsonOutput = class {
406
526
  constructor(options) {
407
527
  this.options = options;
@@ -623,13 +743,15 @@ function resultLine(outcome, info) {
623
743
  },
624
744
  permission_denials: info.denials,
625
745
  ...errors === void 0 ? {} : { errors },
626
- ...stop?.terminal === void 0 ? {} : { terminal_reason: stop.terminal }
746
+ ...stop?.terminal === void 0 ? {} : { terminal_reason: stop.terminal },
747
+ ...info.receipt === void 0 ? {} : { receipt: receiptJson(info.receipt) }
627
748
  };
628
749
  }
629
750
 
630
751
  // src/cli/repl.ts
631
752
  import { createInterface } from "readline";
632
- async function runRepl(runtime, approver, renderer, sessionPath, exitNow, io = { input: process.stdin, output: process.stderr }, firstInput, notifier) {
753
+ async function runRepl(runtime, approver, renderer, sessionPath, exitNow, io = { input: process.stdin, output: process.stderr }, firstInput, notifier, tour) {
754
+ let tourTasks = tour;
633
755
  const history = [];
634
756
  const list = rootLister(runtime.root);
635
757
  const args = new CommandArgs(runtime);
@@ -670,7 +792,8 @@ async function runRepl(runtime, approver, renderer, sessionPath, exitNow, io = {
670
792
  raw = `${raw.slice(0, -1)}
671
793
  ${more.text}`;
672
794
  }
673
- const text = raw.trim();
795
+ const text = tourChoice(raw.trim(), tourTasks);
796
+ tourTasks = void 0;
674
797
  if (text === "") continue;
675
798
  history.unshift(raw);
676
799
  if (text.startsWith("!") && text.length > 1) {
@@ -706,8 +829,20 @@ ${more.text}`;
706
829
  renderer,
707
830
  prompt,
708
831
  exitNow,
709
- notifier
832
+ notifier,
833
+ { chat: true }
710
834
  );
835
+ if (outcome.kind === "done" && outcome.result.stopReason === "max_steps") {
836
+ const next = await stopHandoff(
837
+ approver,
838
+ runtime.limits.maxSteps,
839
+ runtime.executor.isolation
840
+ );
841
+ if (next === "stop") break;
842
+ prompt = next === "more" ? CONTINUE_PROMPT : SUMMARY_PROMPT;
843
+ renderer.info(`\u203A ${prompt}`);
844
+ continue;
845
+ }
711
846
  if (!planning || outcome.kind !== "done" || outcome.result.stopReason !== "done") break;
712
847
  if (await planHandoff(runtime, approver) !== "now") break;
713
848
  renderer.info(`\u203A ${BUILD_PROMPT}`);
@@ -832,7 +967,7 @@ async function main() {
832
967
  "--test-command <cmd>",
833
968
  "with --from-git: the test command; {files} takes the test files (default: detected)"
834
969
  ).action(async (options) => {
835
- const { runEvalCommand } = await import("../evalCommand-SKJQ6CW2.js");
970
+ const { runEvalCommand } = await import("../evalCommand-BLJJ4G76.js");
836
971
  process.exitCode = await runEvalCommand({
837
972
  ...options,
838
973
  model: options.model ?? process.env.GARUDA_MODEL,
@@ -849,16 +984,30 @@ async function main() {
849
984
  "stop before a round that would pass this (default 20)",
850
985
  (v) => Number(v)
851
986
  ).option("--seed <n>", "seed for the run order and the intervals (default 1)", (v) => Number(v)).option("--yes", "start without the question").option("--parallel <n>", "runs at the same time in each score (default 4)", (v) => Number(v)).action(async (options) => {
852
- const { runEvalTune } = await import("../evalTune-CZRCPSZ3.js");
987
+ const { runEvalTune } = await import("../evalTune-W53KAD4V.js");
853
988
  process.exitCode = await runEvalTune({
854
989
  ...options,
855
990
  model: options.model ?? process.env.GARUDA_MODEL
856
991
  });
857
992
  });
858
993
  evalCommand.command("compare").description("compare two eval reports of the same tasks (pass rates with a paired interval)").argument("<a>", "report.json, or its run folder (.garuda/evals/<run-id>)").argument("<b>", "the second report").option("--seed <n>", "seed for the bootstrap (default 1)", (v) => Number(v)).action(async (a, b, options) => {
859
- const { runEvalCompare } = await import("../evalCommand-SKJQ6CW2.js");
994
+ const { runEvalCompare } = await import("../evalCommand-BLJJ4G76.js");
860
995
  process.exitCode = await runEvalCompare(a, b, options);
861
996
  });
997
+ program.command("advise").description(
998
+ "which model for this repo: run its own history (garuda eval --from-git) on two models and compare"
999
+ ).option(
1000
+ "--models <a,b>",
1001
+ "two models (default claude-haiku-5-5,claude-sonnet-5-5)",
1002
+ (v) => v.split(",").map((m) => m.trim())
1003
+ ).option("--repeat <n>", "runs of each task (default 2)", (v) => Number(v)).option(
1004
+ "--max-cost <usd>",
1005
+ "stop before a model that would pass this (default 2)",
1006
+ (v) => Number(v)
1007
+ ).option("--seed <n>", "seed for the run order and the intervals (default 1)", (v) => Number(v)).option("--yes", "start without the question").action(async (options) => {
1008
+ const { runAdvise } = await import("../advise-HDKJGNBL.js");
1009
+ process.exitCode = await runAdvise(options);
1010
+ });
862
1011
  program.command("init").description(
863
1012
  "set up this folder (AGENTS.md; commands, MCP servers and rules from Claude Code, OpenCode, Codex, Gemini CLI, Tabnine, Cursor, Copilot), then chat"
864
1013
  ).option("-m, --model <id>", "model id (or set GARUDA_MODEL)").action(async (options) => {
@@ -874,30 +1023,30 @@ async function main() {
874
1023
  program.command("night").description(
875
1024
  "run this project's night queue (jobs from /schedule), up to 3 at a time, then write one digest"
876
1025
  ).option("--at <HH:MM>", "wait until this local time first (keep the terminal open)").option("--parallel <n>", "jobs at the same time (1 to 10, default 3)").addOption(new Option("--from-launchd").hideHelp()).action(async (options) => {
877
- const { nightCommand } = await import("../nightCommand-WJU6VZA6.js");
1026
+ const { nightCommand } = await import("../nightCommand-XPWT6CQZ.js");
878
1027
  process.exitCode = await nightCommand(options, new PlainRenderer());
879
1028
  });
880
1029
  program.command("setup").description(
881
1030
  "choose a provider and model and store its key (~/.garuda/credentials, only you can read it); editors run it to sign in"
882
1031
  ).option("--show", "show the model and where each key comes from (keys masked)").option("--forget [key-name]", "remove a stored key, or all of them").action(async (options) => {
883
- const { setupCommand, terminalIO } = await import("../setupCommand-YMF6I3MD.js");
1032
+ const { setupCommand, terminalIO } = await import("../setupCommand-OSOMFHDQ.js");
884
1033
  process.exitCode = await setupCommand(options, { io: await terminalIO() });
885
1034
  });
886
1035
  program.command("acp").description(
887
1036
  "run as an agent for an editor over the Agent Client Protocol (VS Code with an extension, Zed, JetBrains, Neovim, Emacs); the editor starts it"
888
1037
  ).argument("[action]", "setup: run garuda setup (the editor's sign-in, ACP Terminal Auth)").option("-m, --model <id>", "model id (or set GARUDA_MODEL)").action(async (action, options) => {
889
- const { acpCommand } = await import("../acpCommand-IUZPLPLI.js");
1038
+ const { acpCommand } = await import("../acpCommand-JAYNMIMP.js");
890
1039
  process.exitCode = await acpCommand({
891
1040
  ...options,
892
1041
  ...action === void 0 ? {} : { action }
893
1042
  });
894
1043
  });
895
1044
  const lsp = program.command("lsp").description("show the language servers for diagnostics (TS/JS, Python, Java)").action(async () => {
896
- const { lspStatusCommand } = await import("../lspCommand-ZZ6R4PA2.js");
1045
+ const { lspStatusCommand } = await import("../lspCommand-X4FTTONR.js");
897
1046
  process.exitCode = await lspStatusCommand();
898
1047
  });
899
1048
  lsp.command("install").description("install a pinned language server into ~/.garuda/lsp (needs the network)").argument("<language>", "typescript, python or java").action(async (language) => {
900
- const { lspInstallCommand } = await import("../lspCommand-ZZ6R4PA2.js");
1049
+ const { lspInstallCommand } = await import("../lspCommand-X4FTTONR.js");
901
1050
  process.exitCode = await lspInstallCommand(language);
902
1051
  });
903
1052
  await program.parseAsync();
@@ -909,7 +1058,7 @@ async function start(options, program) {
909
1058
  let job;
910
1059
  let jobGuard;
911
1060
  if (options.job !== void 0) {
912
- const { prepareJob } = await import("../jobCommand-2ODQLHB3.js");
1061
+ const { prepareJob } = await import("../jobCommand-ILOTYOX3.js");
913
1062
  const prepared = await prepareJob(
914
1063
  mainRoot,
915
1064
  options.job,
@@ -1017,6 +1166,8 @@ async function start(options, program) {
1017
1166
  // The project's settings that loosen safety: asked at startup when there is a terminal,
1018
1167
  // pinned in ~/.garuda/trust.json (a job passes its own settings).
1019
1168
  projectSettings: { home: homedir2(), ask: process.stdin.isTTY === true },
1169
+ // UX U2: a chat watches the network, so a command that needs a host asks for it.
1170
+ ...job === void 0 && prompt === void 0 && process.stdin.isTTY === true ? { network: { watch: true } } : {},
1020
1171
  // Web search (0.5) and Claude's own search (0.6): only the user's search.json and environment.
1021
1172
  ...searchConfig.config === void 0 && searchConfig.claude === void 0 ? {} : {
1022
1173
  search: {
@@ -1069,7 +1220,7 @@ async function start(options, program) {
1069
1220
  job.job.status = "failed";
1070
1221
  await saveJob(job.job);
1071
1222
  if (options.fromLaunchd === true || job.job.launchd !== void 0) {
1072
- const { removeAgent, defaultAgentEnv } = await import("../launchd-3A3ONEW5.js");
1223
+ const { removeAgent, defaultAgentEnv } = await import("../launchd-QG6R5RAK.js");
1073
1224
  await removeAgent(runtime.executor, job.job, defaultAgentEnv());
1074
1225
  }
1075
1226
  return 1;
@@ -1134,7 +1285,8 @@ async function start(options, program) {
1134
1285
  ...runIncomplete ? { runCostIncomplete: true } : {},
1135
1286
  contextWindow: runtime.limits.contextWindow,
1136
1287
  maxOutputTokens: resolved.maxTokens ?? DEFAULT_MAX_TOKENS,
1137
- ...outcome2.kind === "done" ? { stopMessage: stopMessage(outcome2.result.stopReason, runtime.limits) } : {}
1288
+ ...outcome2.kind === "done" ? { stopMessage: stopMessage(outcome2.result.stopReason, runtime.limits) } : {},
1289
+ ...outcome2.kind === "done" && runtime.lastReceipt !== void 0 ? { receipt: runtime.lastReceipt } : {}
1138
1290
  });
1139
1291
  };
1140
1292
  if (prompt.startsWith("/")) {
@@ -1148,7 +1300,7 @@ async function start(options, program) {
1148
1300
  if (resolved2.kind === "prompt") prompt = resolved2.prompt;
1149
1301
  }
1150
1302
  if (job !== void 0) {
1151
- const { testsBefore } = await import("../jobCommand-2ODQLHB3.js");
1303
+ const { testsBefore } = await import("../jobCommand-ILOTYOX3.js");
1152
1304
  await testsBefore(job, runtime, renderer);
1153
1305
  }
1154
1306
  const outcome = await runTurnInTerminal(
@@ -1161,7 +1313,7 @@ async function start(options, program) {
1161
1313
  await runtime.close();
1162
1314
  finish(outcome);
1163
1315
  if (job !== void 0) {
1164
- const { finishJob } = await import("../jobCommand-2ODQLHB3.js");
1316
+ const { finishJob } = await import("../jobCommand-ILOTYOX3.js");
1165
1317
  await finishJob(job, outcome, runtime, renderer, void 0, {
1166
1318
  fromLaunchd: options.fromLaunchd === true
1167
1319
  });
@@ -1183,15 +1335,48 @@ async function start(options, program) {
1183
1335
  tools: runtime.toolsSummary(),
1184
1336
  ink: ink !== void 0
1185
1337
  };
1338
+ const { screenReaderMode } = await import("../receiptView-YFDHV253.js");
1186
1339
  let startBanner = banner(bannerInfo, {
1187
1340
  columns: process.stdout.columns || 80,
1188
- color: colorLevel(process.stdout)
1341
+ color: colorLevel(process.stdout),
1342
+ // 0.18.1: the Ink chat centres the banner; a screen reader gets it as it is.
1343
+ center: ink !== void 0 && !screenReaderMode(),
1344
+ ...process.stdout.rows ? { rows: process.stdout.rows } : {},
1345
+ screenReader: screenReaderMode()
1189
1346
  });
1347
+ {
1348
+ const { BUILD_COMMIT } = await import("../buildInfo-K73FFI5S.js");
1349
+ const { CHAT_STALE, garudaCommit, staleBuildNote } = await import("../buildCheck-HB46NWLX.js");
1350
+ const stale = staleBuildNote(BUILD_COMMIT, await garudaCommit(), CHAT_STALE);
1351
+ if (stale !== void 0) {
1352
+ startBanner += `
1353
+ ${colorLevel(process.stdout) === "none" ? stale : styleText("yellow", stale)}`;
1354
+ }
1355
+ }
1356
+ let tour;
1190
1357
  if (options.firstInput === void 0) {
1358
+ const colored = colorLevel(process.stdout) !== "none";
1359
+ const { morningBrief } = await import("../brief-RWKESOPT.js");
1360
+ const brief = await morningBrief(
1361
+ root,
1362
+ (style, text) => colored ? styleText(style, text) : text
1363
+ ).catch(() => void 0);
1364
+ if (brief !== void 0) startBanner += `
1365
+ ${brief}
1366
+ `;
1191
1367
  const { initTip } = await import("../detect-LARDSLLZ.js");
1192
1368
  const tip = initTip(root);
1193
- if (tip !== void 0) startBanner += `
1194
- ${tip}`;
1369
+ const { firstRunTour } = await import("../tour-CEVMAC5S.js");
1370
+ const first = await firstRunTour(root, homedir2(), runtime.profiles).catch(() => void 0);
1371
+ if (first !== void 0) {
1372
+ tour = first.prompts;
1373
+ startBanner += `
1374
+ ${first.text}${tip === void 0 ? "" : " /init sets up AGENTS.md for this project."}`;
1375
+ } else if (tip !== void 0) {
1376
+ const shown = ink !== void 0 && !screenReaderMode() ? centerLines([tip], process.stdout.columns || 80)[0] : tip;
1377
+ startBanner += `
1378
+ ${shown}`;
1379
+ }
1195
1380
  }
1196
1381
  const sessionPath = (id2) => join(store.dir, `${id2}.jsonl`);
1197
1382
  const notify = runtime.notificationSettings;
@@ -1209,6 +1394,8 @@ ${tip}`;
1209
1394
  const setEventTarget = (target) => {
1210
1395
  events = target;
1211
1396
  };
1397
+ const { countChat, KEY_HINT_CHATS } = await import("../uiState-YFJQ43D7.js");
1398
+ const chats = await countChat(homedir2());
1212
1399
  await ink.runInkChat(
1213
1400
  runtime,
1214
1401
  approver,
@@ -1218,7 +1405,10 @@ ${tip}`;
1218
1405
  exitNow,
1219
1406
  options.firstInput,
1220
1407
  notifier,
1221
- focus
1408
+ focus,
1409
+ chats <= KEY_HINT_CHATS,
1410
+ runtime.uiSettings?.clearOnStart !== false,
1411
+ tour
1222
1412
  );
1223
1413
  } else {
1224
1414
  process.stderr.write(`${startBanner}
@@ -1231,7 +1421,8 @@ ${tip}`;
1231
1421
  exitNow,
1232
1422
  void 0,
1233
1423
  options.firstInput,
1234
- notifier
1424
+ notifier,
1425
+ tour
1235
1426
  );
1236
1427
  }
1237
1428
  await runtime.close();
@@ -1247,7 +1438,7 @@ function wantsInk() {
1247
1438
  }
1248
1439
  async function loadInk(renderer) {
1249
1440
  try {
1250
- return await import("../inkChat-WYYAFZXD.js");
1441
+ return await import("../inkChat-EVLYDC3K.js");
1251
1442
  } catch (error) {
1252
1443
  renderer.info(`Plain chat (Ink is not available: ${error.message.split("\n")[0]}).`);
1253
1444
  return void 0;
@@ -1279,8 +1470,8 @@ function recordJobDenial(job, tool, target) {
1279
1470
  }
1280
1471
  async function jobBatchClient(job, resolved, renderer) {
1281
1472
  const { DeadlineClient } = await import("../deadline-TP7ZGLT2.js");
1282
- const { nextTime } = await import("../launchd-3A3ONEW5.js");
1283
- const { DEFAULT_FINISH_BY, DEFAULT_STEP_LIMIT_MINUTES, SWITCH_BEFORE_MS } = await import("../create-W6BV75QX.js");
1473
+ const { nextTime } = await import("../launchd-QG6R5RAK.js");
1474
+ const { DEFAULT_FINISH_BY, DEFAULT_STEP_LIMIT_MINUTES, SWITCH_BEFORE_MS } = await import("../create-OACSGJ37.js");
1284
1475
  const finishBy = job.job.finishBy ?? DEFAULT_FINISH_BY;
1285
1476
  const stepLimit = job.job.stepLimitMinutes ?? DEFAULT_STEP_LIMIT_MINUTES;
1286
1477
  const switchAt = new Date(nextTime(finishBy).getTime() - SWITCH_BEFORE_MS);
@@ -3,7 +3,7 @@ import {
3
3
  jobBase,
4
4
  linkCandidates,
5
5
  worktreeDir
6
- } from "./chunk-55CFEEIN.js";
6
+ } from "./chunk-WK5NE6RY.js";
7
7
  import {
8
8
  agentLabel,
9
9
  defaultAgentEnv,
@@ -12,15 +12,15 @@ import {
12
12
  nextTime,
13
13
  nightAgentTime,
14
14
  nightSpec
15
- } from "./chunk-5B5HDTUR.js";
15
+ } from "./chunk-TWQ7V2L6.js";
16
16
  import {
17
17
  jobPrompt
18
18
  } from "./chunk-3MRQJKUO.js";
19
19
  import "./chunk-AOGFYUKG.js";
20
20
  import {
21
21
  JobGitError
22
- } from "./chunk-6XHON3Q6.js";
23
- import "./chunk-B4SJY7KT.js";
22
+ } from "./chunk-QXTHEFKP.js";
23
+ import "./chunk-LMKGSYJC.js";
24
24
  import "./chunk-BHZ6G65V.js";
25
25
  import "./chunk-P6XWWIEK.js";
26
26
  import {
@@ -227,4 +227,4 @@ export {
227
227
  createJob,
228
228
  switchTime
229
229
  };
230
- //# sourceMappingURL=create-W6BV75QX.js.map
230
+ //# sourceMappingURL=create-OACSGJ37.js.map