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