@aragon-agent/cli 0.6.3 → 0.6.7

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 (138) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/README.md +203 -13
  3. package/dist/agent/controller.d.ts +158 -2
  4. package/dist/agent/controller.js +400 -1
  5. package/dist/agent/reducer.d.ts +102 -19
  6. package/dist/agent/reducer.js +162 -71
  7. package/dist/agent/system-prompt.d.ts +14 -0
  8. package/dist/agent/system-prompt.js +2 -0
  9. package/dist/agent/usage.d.ts +34 -0
  10. package/dist/agent/usage.js +43 -0
  11. package/dist/cli.js +132 -23
  12. package/dist/commands/builtins.js +101 -1
  13. package/dist/compaction/child.js +5 -0
  14. package/dist/compaction/command.js +14 -1
  15. package/dist/compaction/compactor.d.ts +94 -24
  16. package/dist/compaction/compactor.js +247 -98
  17. package/dist/compaction/context-command.d.ts +33 -0
  18. package/dist/compaction/context-command.js +166 -0
  19. package/dist/compaction/meter.d.ts +251 -0
  20. package/dist/compaction/meter.js +428 -0
  21. package/dist/compaction/pressure.d.ts +6 -0
  22. package/dist/compaction/pressure.js +4 -0
  23. package/dist/compaction/types.d.ts +77 -0
  24. package/dist/compaction/wiring.d.ts +56 -0
  25. package/dist/compaction/wiring.js +107 -25
  26. package/dist/config/cli-commands.js +5 -0
  27. package/dist/config/env.d.ts +1 -1
  28. package/dist/config/env.js +63 -2
  29. package/dist/config/load.d.ts +28 -0
  30. package/dist/config/load.js +83 -1
  31. package/dist/config/schema.d.ts +129 -0
  32. package/dist/config/schema.js +69 -0
  33. package/dist/config/store.js +47 -1
  34. package/dist/exec/events.d.ts +138 -1
  35. package/dist/exec/events.js +42 -0
  36. package/dist/exec/index.js +43 -6
  37. package/dist/exec/progress-reporter.d.ts +23 -0
  38. package/dist/exec/progress-reporter.js +88 -0
  39. package/dist/exec/runner.d.ts +34 -0
  40. package/dist/exec/runner.js +137 -25
  41. package/dist/fast/reviewer.d.ts +19 -1
  42. package/dist/fast/reviewer.js +22 -0
  43. package/dist/fast/types.d.ts +15 -0
  44. package/dist/fast/wiring.d.ts +10 -1
  45. package/dist/fast/wiring.js +18 -1
  46. package/dist/input/limits.d.ts +72 -0
  47. package/dist/input/limits.js +63 -0
  48. package/dist/input/paste-parse.d.ts +71 -0
  49. package/dist/input/paste-parse.js +95 -0
  50. package/dist/input/stdin-filter.d.ts +81 -0
  51. package/dist/input/stdin-filter.js +379 -0
  52. package/dist/logging/install.d.ts +2 -0
  53. package/dist/logging/install.js +53 -1
  54. package/dist/proc/classify.d.ts +52 -0
  55. package/dist/proc/classify.js +143 -0
  56. package/dist/proc/kill-tree.d.ts +42 -0
  57. package/dist/proc/kill-tree.js +119 -0
  58. package/dist/proc/limits.d.ts +84 -0
  59. package/dist/proc/limits.js +84 -0
  60. package/dist/proc/log-ring.d.ts +68 -0
  61. package/dist/proc/log-ring.js +102 -0
  62. package/dist/proc/prompt.d.ts +24 -0
  63. package/dist/proc/prompt.js +49 -0
  64. package/dist/proc/readiness.d.ts +102 -0
  65. package/dist/proc/readiness.js +219 -0
  66. package/dist/proc/supervisor.d.ts +103 -0
  67. package/dist/proc/supervisor.js +465 -0
  68. package/dist/proc/types.d.ts +175 -0
  69. package/dist/proc/types.js +15 -0
  70. package/dist/session/persist.js +36 -1
  71. package/dist/todo/limits.d.ts +4 -17
  72. package/dist/todo/limits.js +4 -17
  73. package/dist/todo/panel-rows.d.ts +8 -6
  74. package/dist/todo/panel-rows.js +19 -6
  75. package/dist/tools/bash-tool.d.ts +51 -2
  76. package/dist/tools/bash-tool.js +321 -51
  77. package/dist/tools/fs-tools.d.ts +17 -0
  78. package/dist/tools/index.d.ts +55 -2
  79. package/dist/tools/index.js +39 -1
  80. package/dist/tools/proc-tools.d.ts +25 -0
  81. package/dist/tools/proc-tools.js +102 -0
  82. package/dist/ui/App.d.ts +15 -2
  83. package/dist/ui/App.js +330 -69
  84. package/dist/ui/AutocompletePopup.d.ts +3 -1
  85. package/dist/ui/AutocompletePopup.js +9 -11
  86. package/dist/ui/BottomStatusRow.d.ts +1 -1
  87. package/dist/ui/Composer.d.ts +56 -1
  88. package/dist/ui/Composer.js +50 -6
  89. package/dist/ui/PromptInput.d.ts +52 -3
  90. package/dist/ui/PromptInput.js +201 -55
  91. package/dist/ui/StatusBar.d.ts +40 -15
  92. package/dist/ui/StatusBar.js +51 -9
  93. package/dist/ui/TeamPanel.d.ts +3 -1
  94. package/dist/ui/TeamPanel.js +13 -9
  95. package/dist/ui/TodoPanel.d.ts +5 -5
  96. package/dist/ui/TodoPanel.js +56 -24
  97. package/dist/ui/Transcript.js +29 -1
  98. package/dist/ui/UpdateLine.d.ts +1 -1
  99. package/dist/ui/capabilities.js +5 -5
  100. package/dist/ui/composer-limits.d.ts +31 -0
  101. package/dist/ui/composer-limits.js +50 -0
  102. package/dist/ui/composer-rows.d.ts +73 -0
  103. package/dist/ui/composer-rows.js +201 -0
  104. package/dist/ui/editor-reducer.d.ts +37 -0
  105. package/dist/ui/editor-reducer.js +88 -12
  106. package/dist/ui/entries/ServiceCard.d.ts +66 -0
  107. package/dist/ui/entries/ServiceCard.js +116 -0
  108. package/dist/ui/entries/UserEntry.d.ts +17 -3
  109. package/dist/ui/entries/UserEntry.js +34 -5
  110. package/dist/ui/exit-snapshot.d.ts +9 -0
  111. package/dist/ui/layout/ScrollViewport.d.ts +1 -1
  112. package/dist/ui/layout/autocomplete.d.ts +18 -0
  113. package/dist/ui/layout/autocomplete.js +26 -0
  114. package/dist/ui/layout/budget.d.ts +34 -6
  115. package/dist/ui/layout/budget.js +32 -7
  116. package/dist/ui/layout/rail.d.ts +4 -53
  117. package/dist/ui/layout/rail.js +10 -62
  118. package/dist/ui/layout/team-panel.d.ts +18 -0
  119. package/dist/ui/layout/team-panel.js +22 -0
  120. package/dist/ui/layout/todo-layout.d.ts +24 -0
  121. package/dist/ui/layout/todo-layout.js +27 -0
  122. package/dist/ui/layout/virtual-window.js +51 -1
  123. package/dist/ui/overlays/HelpOverlay.js +3 -0
  124. package/dist/ui/overlays/PlanReviewOverlay.js +10 -2
  125. package/dist/ui/overlays/QuestionOverlay.js +5 -1
  126. package/dist/ui/overlays/SettingsScreen.js +14 -1
  127. package/dist/ui/paste-frames.d.ts +87 -0
  128. package/dist/ui/paste-frames.js +112 -0
  129. package/dist/ui/paste-tokens.d.ts +90 -0
  130. package/dist/ui/paste-tokens.js +147 -0
  131. package/dist/ui/screen.d.ts +16 -0
  132. package/dist/ui/screen.js +45 -2
  133. package/dist/ui/selection/selection-controller.d.ts +1 -1
  134. package/dist/ui/transcript-text.js +55 -2
  135. package/dist/ui/use-wheel-routing.d.ts +1 -1
  136. package/package.json +2 -2
  137. package/dist/input/stdin-mouse-filter.d.ts +0 -47
  138. package/dist/input/stdin-mouse-filter.js +0 -153
@@ -59,6 +59,24 @@ function stripLiveToolOutput(entries) {
59
59
  ? { ...e, live: undefined, liveSeq: undefined, lastOutputAt: undefined }
60
60
  : e);
61
61
  }
62
+ /**
63
+ * Drop the service tail on the way to disk, beside `stripLiveToolOutput` and for
64
+ * the same three reasons (background-service-supervision §6).
65
+ *
66
+ * A resumed card's tail describes a PROCESS THAT NO LONGER EXISTS - it died with
67
+ * the session, because nothing in this package outlives the CLI by design. The
68
+ * tail is also the only unbounded field a service entry carries, and dropping it
69
+ * keeps a saved session's size a function of how many services ran rather than
70
+ * of how chatty they were.
71
+ *
72
+ * `rowsSeen` IS KEPT. It is the revision cursor, not display data, and a
73
+ * restored card that reported 0 rows seen while `normalizeLoadedEntries` was
74
+ * flipping its status would produce a revision collision with a live card that
75
+ * genuinely has none.
76
+ */
77
+ function stripServiceTail(entries) {
78
+ return entries.map((e) => (e.kind === 'service' && e.rows.length > 0 ? { ...e, rows: [] } : e));
79
+ }
62
80
  /**
63
81
  * `data` GAINS `todos`, AND WIDENING `SavedSession` ALONE IS NOT ENOUGH (P0-2):
64
82
  * the writer below builds its payload from THIS parameter, not from the type, so
@@ -81,7 +99,7 @@ export function saveSession(filePath, data) {
81
99
  savedAt: Date.now(),
82
100
  model: data.model,
83
101
  messages: data.messages,
84
- entries: stripLiveToolOutput(data.entries),
102
+ entries: stripServiceTail(stripLiveToolOutput(data.entries)),
85
103
  todos: data.todos,
86
104
  ...(data.meta ? { meta: data.meta } : {}),
87
105
  };
@@ -158,6 +176,23 @@ export function normalizeLoadedEntries(entries) {
158
176
  reason: 'interrupted (session resumed)',
159
177
  };
160
178
  }
179
+ // THE SIXTH CLAUSE (background-service-supervision §6 / R-7). A card saved
180
+ // while its service was up resumes claiming to be running while nothing is -
181
+ // the process died with the session, because nothing here outlives the CLI.
182
+ //
183
+ // AND `starting` IS THE ONE THAT ACTUALLY COSTS: it is the single service
184
+ // status that blocks `Transcript`'s MONOTONIC settled boundary (D-11), so a
185
+ // restored `starting` card would never settle and every frame for the rest of
186
+ // the session would re-render the whole tail. `ready` / `running` would
187
+ // "only" be a lie; this one is a lie that gets slower.
188
+ //
189
+ // `stopped` rather than `exited`: we did not observe an exit code, and
190
+ // claiming one would be inventing a number. The terminal record the session
191
+ // may also carry is already terminal and is left alone.
192
+ if (entry.kind === 'service' &&
193
+ (entry.status === 'starting' || entry.status === 'ready' || entry.status === 'running')) {
194
+ return { ...entry, status: 'stopped', rows: [] };
195
+ }
161
196
  return entry;
162
197
  });
163
198
  }
@@ -32,13 +32,10 @@ export declare const TODO_LIMITS: {
32
32
  * there (§3.3 step 2).
33
33
  */
34
34
  readonly minFreshItems: 2;
35
- /** Rows the in-progress row may wrap to. Every other row truncates. */
36
- readonly activeWrapRows: 2;
37
- /**
38
- * Below this many AVAILABLE rail rows (`todoRailRows`, NOT `viewportBudget`)
39
- * the rail is not mounted at all.
40
- */
41
- readonly panelMinRows: 6;
35
+ /** Minimum shared middle rows for the compact rail. */
36
+ readonly panelMinRows: 3;
37
+ /** Full rail includes a blank separator and separate overflow markers. */
38
+ readonly panelFullRows: 6;
42
39
  /** Below this many terminal columns the status-bar counter degrades to `[3/7]`. */
43
40
  readonly statusCompactCols: 100;
44
41
  /**
@@ -51,16 +48,6 @@ export declare const TODO_LIMITS: {
51
48
  * component was a third policy or a typo for one of them.
52
49
  */
53
50
  readonly stripDoneCols: 80;
54
- /**
55
- * Rows `todoRailRows()` subtracts while a team dispatch is live (§3.9 / P1-3).
56
- *
57
- * `TEAM_LIMITS.panelMaxRows` (5) + header + `+N more` + the mail line = 8, and
58
- * this is deliberately the FULL worst case rather than a measurement: an
59
- * over-subtraction costs one item row, an under-subtraction eats the `+N
60
- * below` marker - the one row whose absence is indistinguishable from "the
61
- * list is short" - and those two mistakes are not equally bad.
62
- */
63
- readonly railReservedRows: 8;
64
51
  /**
65
52
  * Consecutive user turns an UNFINISHED list survives without a `todo_write`
66
53
  * before `beginUserTurn()` drops it (§3.2 / P1-7). Three keeps the common
@@ -32,13 +32,10 @@ export const TODO_LIMITS = {
32
32
  * there (§3.3 step 2).
33
33
  */
34
34
  minFreshItems: 2,
35
- /** Rows the in-progress row may wrap to. Every other row truncates. */
36
- activeWrapRows: 2,
37
- /**
38
- * Below this many AVAILABLE rail rows (`todoRailRows`, NOT `viewportBudget`)
39
- * the rail is not mounted at all.
40
- */
41
- panelMinRows: 6,
35
+ /** Minimum shared middle rows for the compact rail. */
36
+ panelMinRows: 3,
37
+ /** Full rail includes a blank separator and separate overflow markers. */
38
+ panelFullRows: 6,
42
39
  /** Below this many terminal columns the status-bar counter degrades to `[3/7]`. */
43
40
  statusCompactCols: 100,
44
41
  /**
@@ -51,16 +48,6 @@ export const TODO_LIMITS = {
51
48
  * component was a third policy or a typo for one of them.
52
49
  */
53
50
  stripDoneCols: 80,
54
- /**
55
- * Rows `todoRailRows()` subtracts while a team dispatch is live (§3.9 / P1-3).
56
- *
57
- * `TEAM_LIMITS.panelMaxRows` (5) + header + `+N more` + the mail line = 8, and
58
- * this is deliberately the FULL worst case rather than a measurement: an
59
- * over-subtraction costs one item row, an under-subtraction eats the `+N
60
- * below` marker - the one row whose absence is indistinguishable from "the
61
- * list is short" - and those two mistakes are not equally bad.
62
- */
63
- railReservedRows: 8,
64
51
  /**
65
52
  * Consecutive user turns an UNFINISHED list survives without a `todo_write`
66
53
  * before `beginUserTurn()` drops it (§3.2 / P1-7). Three keeps the common
@@ -37,17 +37,19 @@ export interface TodoRowSelection {
37
37
  export declare function todoAnchorIndex(items: TodoItem[]): number;
38
38
  /**
39
39
  * @param maxRows Rows available for the item rows AND the two overflow markers
40
- * together. `todoRailRows()` upstream is what makes this number
41
- * honest while a team dispatch is live (I-10 / P1-3).
40
+ * together. The shared layout subtracts actual team/menu rows.
42
41
  *
43
42
  * THE ANCHOR IS ALWAYS VISIBLE, and that beats the row bound when the two
44
43
  * conflict. They can only conflict below `maxRows` 3 with overflow on BOTH
45
44
  * sides — one item plus two markers is three rows — where this returns the
46
45
  * anchor and lets the caller's `overflow="hidden"` clip a marker. Hiding the
47
46
  * one row the user is watching in order to keep a `+N above` would be the wrong
48
- * trade. `TODO_LIMITS.panelMinRows` (6) gates the mount and leaves `TodoPanel`
49
- * at least 4 item rows, so the case is unreachable from the rail; a future
50
- * caller with a smaller budget should read this paragraph before assuming
51
- * otherwise.
47
+ * trade. The full rail has at least four item rows. The compact rail uses
48
+ * `selectCompactTodoRows` with a single merged footer instead.
52
49
  */
53
50
  export declare function selectTodoRows(items: TodoItem[], maxRows: number): TodoRowSelection;
51
+ /** Select an anchored contiguous window without reserving overflow-marker rows.
52
+ * maxItemRows is a row count; invalid/nonpositive values return an empty window
53
+ * with every item counted below it. Does not mutate the list or throw.
54
+ */
55
+ export declare function selectCompactTodoRows(items: TodoItem[], maxItemRows: number): TodoRowSelection;
@@ -58,18 +58,15 @@ function windowFor(count, anchor, slots) {
58
58
  }
59
59
  /**
60
60
  * @param maxRows Rows available for the item rows AND the two overflow markers
61
- * together. `todoRailRows()` upstream is what makes this number
62
- * honest while a team dispatch is live (I-10 / P1-3).
61
+ * together. The shared layout subtracts actual team/menu rows.
63
62
  *
64
63
  * THE ANCHOR IS ALWAYS VISIBLE, and that beats the row bound when the two
65
64
  * conflict. They can only conflict below `maxRows` 3 with overflow on BOTH
66
65
  * sides — one item plus two markers is three rows — where this returns the
67
66
  * anchor and lets the caller's `overflow="hidden"` clip a marker. Hiding the
68
67
  * one row the user is watching in order to keep a `+N above` would be the wrong
69
- * trade. `TODO_LIMITS.panelMinRows` (6) gates the mount and leaves `TodoPanel`
70
- * at least 4 item rows, so the case is unreachable from the rail; a future
71
- * caller with a smaller budget should read this paragraph before assuming
72
- * otherwise.
68
+ * trade. The full rail has at least four item rows. The compact rail uses
69
+ * `selectCompactTodoRows` with a single merged footer instead.
73
70
  */
74
71
  export function selectTodoRows(items, maxRows) {
75
72
  const count = items.length;
@@ -101,3 +98,19 @@ export function selectTodoRows(items, maxRows) {
101
98
  visible.push({ item: items[i], index: i });
102
99
  return { visible, hiddenAbove: start, hiddenBelow: count - end };
103
100
  }
101
+ /** Select an anchored contiguous window without reserving overflow-marker rows.
102
+ * maxItemRows is a row count; invalid/nonpositive values return an empty window
103
+ * with every item counted below it. Does not mutate the list or throw.
104
+ */
105
+ export function selectCompactTodoRows(items, maxItemRows) {
106
+ const slots = Number.isFinite(maxItemRows) ? Math.max(0, Math.floor(maxItemRows)) : 0;
107
+ if (slots === 0 || items.length === 0) {
108
+ return { visible: [], hiddenAbove: 0, hiddenBelow: items.length };
109
+ }
110
+ const { start, end } = windowFor(items.length, todoAnchorIndex(items), slots);
111
+ return {
112
+ visible: items.slice(start, end).map((item, offset) => ({ item, index: start + offset })),
113
+ hiddenAbove: start,
114
+ hiddenBelow: items.length - end,
115
+ };
116
+ }
@@ -1,12 +1,61 @@
1
1
  /**
2
- * bash tool — run a shell command at full permission (spec §3.6).
2
+ * bash tool — run a shell command at full permission (spec §3.6), and, since
3
+ * background-service-supervision, supervise the ones that do not exit.
3
4
  *
4
5
  * Shell selection: Windows uses `process.env.ComSpec` (cmd.exe by default);
5
6
  * POSIX uses `/bin/sh -c`. The command's stdout+stderr and exit code are
6
7
  * captured. The `timeout?` param can only SHRINK within the executor ceiling
7
8
  * (the core ToolExecutor owns the real timeout + 100 KB truncation — R4), so
8
9
  * this tool does not re-implement an output cap.
10
+ *
11
+ * I-1 — THIS TOOL NEVER LEAVES ITS PROMISE PENDING. Every exit path goes through
12
+ * `settle`, and `settle` is reachable from FIVE places: `'error'`, `'close'`,
13
+ * `'exit'` plus a drain timer, an abort plus a kill grace, and the `timeout`
14
+ * param plus the same grace. That is the whole of W1, and each of the five
15
+ * closes a way the old implementation could hang:
16
+ *
17
+ * 1. It settled on `'close'`, which fires only when the process has exited AND
18
+ * every stdio stream is closed. A child that spawns a detached grandchild
19
+ * inheriting the pipe — `Start-Process`, `&`, `nohup`, and every
20
+ * `npm run dev` that re-execs — keeps that pipe open after the shell is
21
+ * long gone. The shell exited; the promise did not.
22
+ * 2. `stdio` defaulted to `'pipe'` for stdin, so a command that PROMPTS —
23
+ * `npm init`, a package manager asking to install something, `sudo`, a git
24
+ * credential prompt — blocked on a read that could never be satisfied.
25
+ * 3. An abort killed the tree and then went on waiting for a `'close'` that a
26
+ * detached grandchild was still holding.
27
+ *
28
+ * The happy path is BYTE-IDENTICAL to the pre-change build: `$ cmd\n<output>\n
29
+ * [exit code N]`, same truncation, same footer. That is what keeps the existing
30
+ * `bash` assertions meaningful rather than rewritten.
9
31
  */
10
32
  import { type AgentTool } from '@aragon-agent/core';
33
+ import type { ProcSupervisorPort } from '../proc/types.js';
11
34
  import type { ToolDeps } from './fs-tools.js';
12
- export declare function makeBash(deps: ToolDeps): AgentTool;
35
+ export interface BashToolOptions {
36
+ /**
37
+ * Present only when background launches are on for this session.
38
+ *
39
+ * ITS ABSENCE IS WHAT MAKES I-2 CHECKABLE: no `background` property in the
40
+ * schema, no supervisor call, no readiness timer, and a description string
41
+ * identical to the pre-feature one.
42
+ */
43
+ supervisor?: ProcSupervisorPort;
44
+ /** `cfg.bash.autoBackground`, read LIVE. */
45
+ autoBackground?: () => boolean;
46
+ /** `cfg.bash.startupSettleMs`, read LIVE. */
47
+ startupSettleMs?: () => number;
48
+ /**
49
+ * Whether a card can be rendered and a user can keep a service alive (D-15 /
50
+ * P1-8).
51
+ *
52
+ * FALSE IN `aragon exec` AND `-p`. It suppresses only the CLASSIFIER: an
53
+ * explicit `background: true` is still honoured — the model asked for it —
54
+ * and the result then carries one extra line saying the service dies with the
55
+ * run. Without this rule `aragon -p "npm run dev"` would background a server,
56
+ * return in `startupSettleMs`, and reap it at process exit with no card, no
57
+ * `/bg`, no event and nothing in the result saying so.
58
+ */
59
+ interactive?: boolean;
60
+ }
61
+ export declare function makeBash(deps: ToolDeps, options?: BashToolOptions): AgentTool;