@aragon-agent/cli 0.6.7 → 0.6.9

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 (117) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +107 -77
  3. package/dist/agent/controller.d.ts +11 -7
  4. package/dist/agent/controller.js +35 -48
  5. package/dist/agent/headless.d.ts +2 -1
  6. package/dist/agent/prompt-options.d.ts +15 -0
  7. package/dist/agent/prompt-options.js +1 -0
  8. package/dist/agent/reducer.d.ts +7 -113
  9. package/dist/agent/reducer.js +0 -62
  10. package/dist/cli.js +111 -182
  11. package/dist/commands/builtins.js +3 -1
  12. package/dist/commands/perf.d.ts +32 -2
  13. package/dist/commands/perf.js +32 -2
  14. package/dist/commands/registry.d.ts +4 -5
  15. package/dist/config/env.js +0 -130
  16. package/dist/config/load.d.ts +0 -2
  17. package/dist/config/load.js +2 -31
  18. package/dist/config/schema.d.ts +1 -14
  19. package/dist/config/schema.js +0 -1
  20. package/dist/config/store.js +2 -0
  21. package/dist/input/interrupt-gesture.d.ts +18 -0
  22. package/dist/input/interrupt-gesture.js +19 -0
  23. package/dist/input/pointer-router.d.ts +11 -0
  24. package/dist/input/pointer-router.js +14 -0
  25. package/dist/logging/install.d.ts +2 -2
  26. package/dist/logging/install.js +2 -2
  27. package/dist/todo/follow-through.d.ts +0 -4
  28. package/dist/todo/follow-through.js +0 -4
  29. package/dist/todo/limits.d.ts +0 -10
  30. package/dist/todo/limits.js +0 -10
  31. package/dist/todo/prompt.d.ts +0 -15
  32. package/dist/todo/store.d.ts +8 -13
  33. package/dist/todo/store.js +13 -14
  34. package/dist/todo/types.d.ts +2 -1
  35. package/dist/ui/ActivityLine.d.ts +26 -34
  36. package/dist/ui/ActivityLine.js +30 -19
  37. package/dist/ui/App.d.ts +3 -41
  38. package/dist/ui/App.js +223 -247
  39. package/dist/ui/BottomStatusRow.d.ts +1 -3
  40. package/dist/ui/BottomStatusRow.js +4 -8
  41. package/dist/ui/Composer.d.ts +38 -5
  42. package/dist/ui/Composer.js +45 -23
  43. package/dist/ui/Header.d.ts +2 -16
  44. package/dist/ui/Header.js +3 -18
  45. package/dist/ui/Logo.d.ts +1 -17
  46. package/dist/ui/Logo.js +0 -16
  47. package/dist/ui/ModeChip.d.ts +7 -18
  48. package/dist/ui/ModeChip.js +9 -0
  49. package/dist/ui/PromptCaret.d.ts +11 -0
  50. package/dist/ui/PromptCaret.js +31 -0
  51. package/dist/ui/PromptInput.d.ts +10 -33
  52. package/dist/ui/PromptInput.js +37 -20
  53. package/dist/ui/StatusBar.d.ts +1 -11
  54. package/dist/ui/StatusBar.js +14 -8
  55. package/dist/ui/ToastStack.d.ts +2 -18
  56. package/dist/ui/ToastStack.js +4 -11
  57. package/dist/ui/Transcript.d.ts +5 -71
  58. package/dist/ui/Transcript.js +10 -199
  59. package/dist/ui/composer-rows.js +50 -9
  60. package/dist/ui/entries/AssistantEntry.d.ts +0 -23
  61. package/dist/ui/entries/AssistantEntry.js +3 -4
  62. package/dist/ui/entries/DiffView.d.ts +1 -7
  63. package/dist/ui/entries/DiffView.js +2 -2
  64. package/dist/ui/entries/ToolCard.d.ts +0 -6
  65. package/dist/ui/entries/ToolCard.js +4 -13
  66. package/dist/ui/frame-differ.d.ts +13 -0
  67. package/dist/ui/frame-differ.js +37 -24
  68. package/dist/ui/frame-observer.d.ts +17 -0
  69. package/dist/ui/frame-observer.js +81 -0
  70. package/dist/ui/frame-parser.d.ts +7 -0
  71. package/dist/ui/frame-parser.js +18 -0
  72. package/dist/ui/ink-runtime.d.ts +1 -0
  73. package/dist/ui/ink-runtime.js +21 -0
  74. package/dist/ui/layout/AppShell.d.ts +4 -58
  75. package/dist/ui/layout/AppShell.js +3 -6
  76. package/dist/ui/layout/OverlayFrame.d.ts +1 -25
  77. package/dist/ui/layout/OverlayFrame.js +0 -24
  78. package/dist/ui/layout/ScrollIndicator.d.ts +4 -3
  79. package/dist/ui/layout/ScrollIndicator.js +4 -4
  80. package/dist/ui/layout/ScrollViewport.d.ts +16 -66
  81. package/dist/ui/layout/ScrollViewport.js +195 -185
  82. package/dist/ui/layout/budget.d.ts +3 -51
  83. package/dist/ui/layout/budget.js +4 -53
  84. package/dist/ui/layout/document-layout.d.ts +13 -0
  85. package/dist/ui/layout/document-layout.js +11 -0
  86. package/dist/ui/layout/follow-state.d.ts +1 -0
  87. package/dist/ui/layout/follow-state.js +1 -3
  88. package/dist/ui/layout/frame.d.ts +0 -22
  89. package/dist/ui/layout/frame.js +0 -36
  90. package/dist/ui/layout/scroll-indicator.d.ts +1 -1
  91. package/dist/ui/layout/scroll-indicator.js +3 -2
  92. package/dist/ui/layout/scrollbar-geometry.d.ts +17 -0
  93. package/dist/ui/layout/scrollbar-geometry.js +13 -0
  94. package/dist/ui/layout/todo-layout.d.ts +2 -3
  95. package/dist/ui/layout/todo-layout.js +9 -9
  96. package/dist/ui/layout/viewport-geometry.d.ts +2 -1
  97. package/dist/ui/layout/viewport-geometry.js +2 -1
  98. package/dist/ui/layout/virtual-window.d.ts +1 -0
  99. package/dist/ui/layout/virtual-window.js +1 -1
  100. package/dist/ui/live-clamp.d.ts +1 -29
  101. package/dist/ui/live-clamp.js +1 -29
  102. package/dist/ui/overlays/HelpOverlay.js +6 -2
  103. package/dist/ui/run-status-row.d.ts +61 -0
  104. package/dist/ui/run-status-row.js +70 -0
  105. package/dist/ui/screen.d.ts +1 -1
  106. package/dist/ui/screen.js +4 -6
  107. package/dist/ui/scrollbar-controller.d.ts +30 -0
  108. package/dist/ui/scrollbar-controller.js +124 -0
  109. package/dist/ui/transcript-text.d.ts +0 -8
  110. package/dist/ui/transcript-text.js +0 -8
  111. package/dist/ui/use-startup-notices.d.ts +1 -57
  112. package/dist/ui/use-startup-notices.js +3 -54
  113. package/dist/ui/use-wheel-routing.d.ts +3 -1
  114. package/dist/ui/use-wheel-routing.js +6 -0
  115. package/package.json +2 -2
  116. package/dist/ui/TodoStrip.d.ts +0 -36
  117. package/dist/ui/TodoStrip.js +0 -32
@@ -41,6 +41,8 @@
41
41
  import React from 'react';
42
42
  import type { Theme } from './theme.js';
43
43
  import type { TermCapabilities } from './capabilities.js';
44
+ import { pickGlyphs } from './glyphs.js';
45
+ import type { RunActivity } from './run-status-row.js';
44
46
  /**
45
47
  * The animated spinner this row draws while it is live, or `null` when it would
46
48
  * be STATIC — an ASCII terminal, or a user who asked for stillness.
@@ -57,42 +59,32 @@ import type { TermCapabilities } from './capabilities.js';
57
59
  * reader has to reason about; one more caller of this function is not.
58
60
  */
59
61
  export declare function liveSpinner(reducedMotion: boolean, caps: TermCapabilities): React.ReactElement | null;
60
- export interface ActivityLineProps {
61
- /** Epoch ms the current run began — the phrase sequence's seed. */
62
- startedAt: number;
63
- /** `Date.now() - startedAt`, already computed by App's 200 ms ticker. */
64
- elapsedMs: number;
65
- reducedMotion: boolean;
66
- /**
67
- * The name of the tool currently in flight, or `undefined`
68
- * (agent-activity-presentation-live L4 / D-31).
69
- *
70
- * `status === 'running'` covers the WHOLE turn, including the minutes the
71
- * model is idle and a child process is doing the work. Round 1 chose the
72
- * thinking vocabulary deliberately for the gap before the first token, and it
73
- * is right for that gap; a UI that says "Pondering" while `npm test` runs is
74
- * not calm, it is wrong.
75
- */
76
- runningTool?: string;
62
+ /**
63
+ * The label ladder, MOST SPECIFIC FIRST: `Compacting context` outranks a tool name
64
+ * because compaction can be the only thing happening, and the tool name outranks
65
+ * the rotating phrase for the reason `runningTool` exists at all. One
66
+ * implementation, because the fixed bottom row and the run status row above the
67
+ * input must never disagree about what the agent is doing.
68
+ *
69
+ * `Running ${name}` rather than a per-tool verb table: a table would be a SECOND
70
+ * registry of tool names, and `toolGlyph` is already the one place that knows
71
+ * them. ASCII only, and the ellipsis comes from `pickGlyphs` like every other one.
72
+ */
73
+ export declare function resolveActivityLabel(activity: RunActivity, glyphs: ReturnType<typeof pickGlyphs>): string;
74
+ export interface ActivityLabelProps extends RunActivity {
77
75
  /**
78
- * A context compaction is in flight (context-auto-compaction §6.1).
79
- *
80
- * HIGHEST PRECEDENCE IN THE LABEL LADDER, above `runningTool` and above the
81
- * rotating phrase. Compaction happens BEFORE `turn_start`, i.e. at a moment
82
- * when `status` is `'running'` but no tool is in flight — precisely the window
83
- * in which the phrase rotation would say something false, and it can last
84
- * tens of seconds. `runningTool` already established the principle one step
85
- * back: a UI that says "Pondering" while `npm test` runs is not calm, it is
86
- * wrong, and one that says it while a 30 k-token summarization runs is the same
87
- * error.
88
- *
89
- * STILL NO SECOND SPINNER. `single-spinner-while-running`'s D-1 stands: this
90
- * row owns the only animation while it is mounted, and the compaction card
91
- * follows `FastCard` in taking a `reducedMotion` that `App` has already
92
- * widened.
76
+ * False draws the STATIC glyph even when motion is allowed. The run status row
77
+ * uses it when it has scrolled out of the viewport (the fixed bottom row owns
78
+ * the animation then) or an overlay covers the chat. The phrase still rotates
79
+ * from the RAW `reducedMotion`, so a still icon never freezes the wording.
93
80
  */
94
- compacting?: boolean;
81
+ spinnerLive?: boolean;
82
+ /** Prefix one space (the fixed bottom row's indent); the run row indents itself. */
83
+ leadingSpace?: boolean;
95
84
  theme: Theme;
96
85
  caps: TermCapabilities;
97
86
  }
98
- export declare function ActivityLine({ startedAt, elapsedMs, reducedMotion, runningTool, compacting, theme, caps, }: ActivityLineProps): React.ReactElement;
87
+ /** `<spinner> <label>` as ONE truncating `<Text>`; the only place that composes them. */
88
+ export declare function ActivityLabel({ spinnerLive, leadingSpace, theme, caps, ...activity }: ActivityLabelProps): React.ReactElement;
89
+ export type ActivityLineProps = Omit<ActivityLabelProps, 'spinnerLive' | 'leadingSpace'>;
90
+ export declare function ActivityLine(props: ActivityLineProps): React.ReactElement;
@@ -21,32 +21,43 @@ import { pickActivityPhrase } from './activity-phrases.js';
21
21
  export function liveSpinner(reducedMotion, caps) {
22
22
  return caps.unicode && !reducedMotion ? _jsx(Spinner, { type: "dots" }) : null;
23
23
  }
24
- export function ActivityLine({ startedAt, elapsedMs, reducedMotion, runningTool, compacting, theme, caps, }) {
25
- const glyphs = pickGlyphs(caps);
24
+ /**
25
+ * The label ladder, MOST SPECIFIC FIRST: `Compacting context` outranks a tool name
26
+ * because compaction can be the only thing happening, and the tool name outranks
27
+ * the rotating phrase for the reason `runningTool` exists at all. One
28
+ * implementation, because the fixed bottom row and the run status row above the
29
+ * input must never disagree about what the agent is doing.
30
+ *
31
+ * `Running ${name}` rather than a per-tool verb table: a table would be a SECOND
32
+ * registry of tool names, and `toolGlyph` is already the one place that knows
33
+ * them. ASCII only, and the ellipsis comes from `pickGlyphs` like every other one.
34
+ */
35
+ export function resolveActivityLabel(activity, glyphs) {
36
+ if (activity.compacting)
37
+ return `Compacting context${glyphs.ellipsis}`;
38
+ if (activity.runningTool)
39
+ return `Running ${activity.runningTool}`;
26
40
  // PURE AND DERIVED FROM `(startedAt, now)`, so the sequence does not need to
27
41
  // keep rotating underneath the tool label: when the tool settles the phrase
28
42
  // resumes at the position the clock implies, with no state anywhere.
29
- const phrase = pickActivityPhrase(startedAt, startedAt + elapsedMs, !reducedMotion);
30
- // `Running ${name}` rather than a per-tool verb table: a table would be a
31
- // SECOND registry of tool names, and `toolGlyph` is already the one place that
32
- // knows them. Everything round 1 legislated for this row survives — one row,
33
- // no digits, no `esc abort`, no width ladder, ASCII only.
34
- // THREE RUNGS, MOST SPECIFIC FIRST. `Compacting context` outranks a tool name
35
- // because compaction can be the only thing happening, and it outranks the
36
- // phrase for the reason `runningTool` does. ASCII only, and the ellipsis comes
37
- // from `pickGlyphs` like every other one on this row.
38
- const label = compacting
39
- ? `Compacting context${glyphs.ellipsis}`
40
- : runningTool
41
- ? `Running ${runningTool}`
42
- : `${phrase}${glyphs.ellipsis}`;
43
+ const phrase = pickActivityPhrase(activity.startedAt, activity.startedAt + activity.elapsedMs, !activity.reducedMotion);
44
+ return `${phrase}${glyphs.ellipsis}`;
45
+ }
46
+ /** `<spinner> <label>` as ONE truncating `<Text>`; the only place that composes them. */
47
+ export function ActivityLabel({ spinnerLive = true, leadingSpace = false, theme, caps, ...activity }) {
48
+ const glyphs = pickGlyphs(caps);
49
+ const label = resolveActivityLabel(activity, glyphs);
43
50
  // The IDENTICAL branch `Transcript.tsx` uses for the assistant role marker, and
44
51
  // it must stay identical: braille dots are both an animation AND a Unicode-only
45
52
  // glyph, so reduced motion and an ASCII terminal fall back to the same marker.
46
53
  //
47
54
  // Through `liveSpinner` rather than inline, so this row and the glyph
48
55
  // `BottomStatusRow` composes beside a toast can never disagree about WHEN the
49
- // spinner is live — the same reason `App` names its mount condition once.
50
- const spinner = liveSpinner(reducedMotion, caps) ?? glyphs.spinnerStill;
51
- return (_jsx(Box, { flexShrink: 0, children: _jsxs(Text, { wrap: "truncate", color: theme.thinking, children: [' ', spinner, " ", label] }) }));
56
+ // spinner is live - the same reason `App` names its mount condition once.
57
+ const spinner = (spinnerLive ? liveSpinner(activity.reducedMotion, caps) : null) ??
58
+ glyphs.spinnerStill;
59
+ return (_jsxs(Text, { wrap: "truncate", color: theme.thinking, children: [leadingSpace ? ' ' : '', spinner, " ", label] }));
60
+ }
61
+ export function ActivityLine(props) {
62
+ return (_jsx(Box, { flexShrink: 0, children: _jsx(ActivityLabel, { ...props, leadingSpace: true }) }));
52
63
  }
package/dist/ui/App.d.ts CHANGED
@@ -5,11 +5,11 @@
5
5
  * input / toast stack / status bar / overlays.
6
6
  */
7
7
  import React from 'react';
8
+ import type { ScrollbarBridge } from './scrollbar-controller.js';
8
9
  import type { AgentController } from '../agent/controller.js';
9
10
  import type { ConfirmRequest } from '../tools/index.js';
10
11
  import { type Overlay, type ToastLevel } from '../agent/reducer.js';
11
12
  import type { UpdateBridge } from '../update/types.js';
12
- import { type RenderMode } from './layout/frame.js';
13
13
  import type { MouseSource } from '../input/stdin-filter.js';
14
14
  import type { PasteBridge } from '../input/limits.js';
15
15
  import type { SelectionBridge } from './selection/selection-controller.js';
@@ -42,15 +42,11 @@ export interface AppProps {
42
42
  controller: AgentController;
43
43
  version: string;
44
44
  /** Decided once in `cli.tsx::runInteractive()`; never switched at run time. */
45
- mode: RenderMode;
46
45
  initialOverlay?: Overlay;
47
46
  initialPrompt?: string;
48
47
  confirmBridge?: ConfirmBridge;
49
48
  /** The plan-mode human channel; absent in tests that do not exercise it. */
50
49
  humanInputBridge?: HumanInputBridge;
51
- /** Wheel events, already stripped out of stdin. Absent whenever mouse support
52
- * is off: inline mode, `--no-mouse`, a non-TTY, or a filter that failed to
53
- * build (mouse-wheel-region-routing §4.2). */
54
50
  mouseSource?: MouseSource;
55
51
  /**
56
52
  * Present ONLY on a console that can deliver neither `CSI Z` nor a mouse
@@ -86,51 +82,17 @@ export interface AppProps {
86
82
  * on a non-TTY, and in every test that does not exercise it.
87
83
  */
88
84
  pasteBridge?: PasteBridge;
89
- /**
90
- * The terminal-facing services `cli.tsx` owns and this component cannot build
91
- * (tui-selection-and-scroll-follow §4.4).
92
- *
93
- * ONE PROP RATHER THAN FOUR, and every FIELD of it is independently optional,
94
- * so `--no-mouse`, `--no-diff-render` and inline mode each drop exactly the
95
- * services they do not have. Absent altogether on a non-TTY and in every test
96
- * that does not exercise selection, which is what keeps those trees
97
- * byte-identical.
98
- */
99
85
  terminal?: TerminalBridge;
100
86
  }
101
- /**
102
- * Terminal-level services, almost all of which exist only in a full-screen TTY
103
- * session — `writeForeign` is the exception, because `/copy` is available in
104
- * inline mode too and OSC 52 is what makes it work over SSH (§4.4.5).
105
- *
106
- * `selection` is a LATE-BOUND BRIDGE for the reason `updateBridge` above is one:
107
- * the controller is constructed before `render()` and must not hold React state,
108
- * while the toast sink and the redraw nonce only exist once this component has
109
- * mounted. The effect below assigns both and clears them on unmount.
110
- */
111
87
  export interface TerminalBridge {
88
+ scrollbar?: ScrollbarBridge;
112
89
  /** Whether drag-select is on for this session (`mouseSelect` + a filter). */
113
90
  mouseSelect: boolean;
114
91
  /** Release the mouse to the terminal, or take it back (`/mouse`, G3). */
115
92
  setMouseCapture?: (on: boolean) => void;
116
93
  /** Whether the mouse is captured right now — read at command time. */
117
94
  isMouseCaptured?: () => boolean;
118
- /**
119
- * Write bytes that are ours but are not a frame (OSC 52).
120
- *
121
- * IT MUST NOT BE `stdout.write` WITH THE DIFFER IN FRONT OF STDOUT (P1-6):
122
- * that goes through the frame-writer proxy, which does not recognise an OSC 52
123
- * chunk, counts it as a foreign write and prints `FRAME_FALLBACK_NOTICE` at
124
- * the user the first time they copy anything. Without a differ — inline mode,
125
- * `--no-diff-render` — stdout IS the real stream and `cli.tsx` supplies a
126
- * direct write instead.
127
- *
128
- * Absent only when there is no terminal to accept it at all. It is never a
129
- * function that writes nowhere: `copyText` reports `'osc52'` whenever its door
130
- * took the text, so a no-op door would make the toast name a mechanism that
131
- * was never attempted.
132
- */
133
95
  writeForeign?: (text: string) => void;
134
96
  selection?: SelectionBridge;
135
97
  }
136
- export declare function App({ controller, version, mode, initialOverlay, initialPrompt, confirmBridge, humanInputBridge, mouseSource, vtInputWarning, updateBridge, pasteBridge, terminal, }: AppProps): React.ReactElement;
98
+ export declare function App({ controller, version, initialOverlay, initialPrompt, confirmBridge, humanInputBridge, mouseSource, vtInputWarning, updateBridge, pasteBridge, terminal, }: AppProps): React.ReactElement;