@aragon-agent/cli 0.6.8 → 0.6.10
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.
- package/CHANGELOG.md +27 -0
- package/README.md +89 -44
- package/dist/agent/controller.d.ts +1 -1
- package/dist/agent/reducer.d.ts +31 -113
- package/dist/agent/reducer.js +41 -63
- package/dist/cli.js +53 -155
- package/dist/commands/builtins.d.ts +2 -1
- package/dist/commands/builtins.js +47 -2
- package/dist/commands/perf.d.ts +32 -2
- package/dist/commands/perf.js +32 -2
- package/dist/commands/registry.d.ts +2 -2
- package/dist/config/env.js +0 -130
- package/dist/config/load.d.ts +0 -2
- package/dist/config/load.js +2 -31
- package/dist/config/schema.d.ts +1 -14
- package/dist/config/schema.js +0 -1
- package/dist/config/store.js +2 -0
- package/dist/input/enter-sequences.d.ts +63 -0
- package/dist/input/enter-sequences.js +151 -0
- package/dist/input/limits.d.ts +11 -0
- package/dist/input/limits.js +11 -0
- package/dist/input/stdin-filter.js +19 -1
- package/dist/logging/install.d.ts +2 -2
- package/dist/logging/install.js +2 -2
- package/dist/session/persist.js +20 -0
- package/dist/todo/follow-through.d.ts +0 -4
- package/dist/todo/follow-through.js +0 -4
- package/dist/todo/limits.d.ts +0 -10
- package/dist/todo/limits.js +0 -10
- package/dist/todo/prompt.d.ts +0 -15
- package/dist/ui/ActivityLine.d.ts +26 -34
- package/dist/ui/ActivityLine.js +30 -19
- package/dist/ui/App.d.ts +1 -41
- package/dist/ui/App.js +94 -129
- package/dist/ui/BottomStatusRow.d.ts +1 -3
- package/dist/ui/BottomStatusRow.js +4 -8
- package/dist/ui/Composer.d.ts +28 -1
- package/dist/ui/Composer.js +46 -17
- package/dist/ui/Header.d.ts +2 -16
- package/dist/ui/Header.js +3 -18
- package/dist/ui/Logo.d.ts +1 -17
- package/dist/ui/Logo.js +0 -16
- package/dist/ui/ModeChip.d.ts +7 -18
- package/dist/ui/ModeChip.js +9 -0
- package/dist/ui/PromptInput.d.ts +2 -28
- package/dist/ui/PromptInput.js +38 -9
- package/dist/ui/StatusBar.d.ts +0 -11
- package/dist/ui/ToastStack.d.ts +2 -18
- package/dist/ui/ToastStack.js +4 -11
- package/dist/ui/Transcript.d.ts +5 -71
- package/dist/ui/Transcript.js +15 -199
- package/dist/ui/enter-frames.d.ts +63 -0
- package/dist/ui/enter-frames.js +136 -0
- package/dist/ui/entries/AssistantEntry.d.ts +0 -23
- package/dist/ui/entries/AssistantEntry.js +3 -4
- package/dist/ui/entries/DiffView.d.ts +1 -7
- package/dist/ui/entries/DiffView.js +2 -2
- package/dist/ui/entries/QueuedEntry.d.ts +27 -0
- package/dist/ui/entries/QueuedEntry.js +30 -0
- package/dist/ui/entries/ToolCard.d.ts +0 -6
- package/dist/ui/entries/ToolCard.js +4 -13
- package/dist/ui/frame-differ.d.ts +13 -0
- package/dist/ui/frame-differ.js +36 -6
- package/dist/ui/glyphs.d.ts +9 -0
- package/dist/ui/glyphs.js +2 -0
- package/dist/ui/ink-runtime.d.ts +1 -0
- package/dist/ui/ink-runtime.js +21 -0
- package/dist/ui/layout/AppShell.d.ts +1 -10
- package/dist/ui/layout/AppShell.js +2 -5
- package/dist/ui/layout/OverlayFrame.d.ts +1 -25
- package/dist/ui/layout/OverlayFrame.js +0 -24
- package/dist/ui/layout/ScrollViewport.d.ts +3 -0
- package/dist/ui/layout/ScrollViewport.js +17 -5
- package/dist/ui/layout/frame.d.ts +0 -22
- package/dist/ui/layout/frame.js +0 -36
- package/dist/ui/layout/todo-layout.d.ts +1 -3
- package/dist/ui/layout/todo-layout.js +7 -8
- package/dist/ui/layout/viewport-geometry.d.ts +1 -1
- package/dist/ui/layout/viewport-geometry.js +1 -1
- package/dist/ui/live-clamp.d.ts +1 -29
- package/dist/ui/live-clamp.js +1 -29
- package/dist/ui/overlays/HelpOverlay.js +3 -1
- package/dist/ui/overlays/PlanReviewOverlay.js +5 -1
- package/dist/ui/overlays/QuestionOverlay.js +7 -2
- package/dist/ui/overlays/SettingsScreen.js +8 -1
- package/dist/ui/run-status-row.d.ts +61 -0
- package/dist/ui/run-status-row.js +70 -0
- package/dist/ui/selection/selection-controller.d.ts +23 -7
- package/dist/ui/selection/selection-controller.js +68 -16
- package/dist/ui/transcript-text.d.ts +0 -8
- package/dist/ui/transcript-text.js +0 -8
- package/dist/ui/use-startup-notices.d.ts +6 -58
- package/dist/ui/use-startup-notices.js +10 -57
- package/dist/ui/use-wheel-routing.d.ts +1 -1
- package/package.json +2 -2
- package/dist/ui/TodoStrip.d.ts +0 -36
- package/dist/ui/TodoStrip.js +0 -32
|
@@ -20,6 +20,7 @@ import { Box, Text, useInput } from 'ink';
|
|
|
20
20
|
import { pickGlyphs } from '../glyphs.js';
|
|
21
21
|
import { OverlayFrame } from '../layout/OverlayFrame.js';
|
|
22
22
|
import { stripPasteFrames } from '../paste-frames.js';
|
|
23
|
+
import { stripEnterFrames } from '../enter-frames.js';
|
|
23
24
|
/** Which option index each question starts on: the recommended one. */
|
|
24
25
|
function initialCursors(questions) {
|
|
25
26
|
return questions.map((q) => Math.max(0, q.options.findIndex((o) => o.recommended)));
|
|
@@ -125,8 +126,12 @@ export function QuestionOverlay({ questions, maxRows, cols, theme, caps, onSubmi
|
|
|
125
126
|
// `stripPasteFrames`, NOT `input` (I-12 / P0-2) -- the same broadcast
|
|
126
127
|
// hazard `SettingsScreen` documents at length: a framed paste appended
|
|
127
128
|
// verbatim stores NULs that render as nothing.
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
// `stripEnterFrames` rides inside it for the newline frame a
|
|
130
|
+
// Shift+Enter broadcasts (tui-shift-enter-copy-queue 3.5): same hazard,
|
|
131
|
+
// same fix, and this order is the one that leaves no NUL in the draft.
|
|
132
|
+
if (input && !key.ctrl && !key.meta && !key.tab) {
|
|
133
|
+
setDraft(draft + stripPasteFrames(stripEnterFrames(input)));
|
|
134
|
+
}
|
|
130
135
|
return;
|
|
131
136
|
}
|
|
132
137
|
// phase === 'choosing'
|
|
@@ -16,6 +16,7 @@ import { LOG_LEVEL_NAMES } from '../../logging/levels.js';
|
|
|
16
16
|
import { pickGlyphs } from '../glyphs.js';
|
|
17
17
|
import { OverlayFrame } from '../layout/OverlayFrame.js';
|
|
18
18
|
import { stripPasteFrames } from '../paste-frames.js';
|
|
19
|
+
import { stripEnterFrames } from '../enter-frames.js';
|
|
19
20
|
const SHOW_THINKING_OPTIONS = ['off', 'on'];
|
|
20
21
|
const LIVE_OUTPUT_OPTIONS = ['off', 'on'];
|
|
21
22
|
const FAST_ENABLED_OPTIONS = ['off', 'on'];
|
|
@@ -302,7 +303,13 @@ export function SettingsScreen({ initial, apiKeys, maxRows, cols, scrollOffset,
|
|
|
302
303
|
// `controller.setApiKey()`. The user is told the settings were saved and
|
|
303
304
|
// every request afterwards fails to authenticate with nothing on screen to
|
|
304
305
|
// explain it. Pasting IS how a key enters this process.
|
|
305
|
-
|
|
306
|
+
// `stripEnterFrames` INSIDE (tui-shift-enter-copy-queue 3.5): the same
|
|
307
|
+
// broadcast carries the newline frame a Shift+Enter produced, and this
|
|
308
|
+
// composition order is the one that leaves no NUL in the field -- the
|
|
309
|
+
// outer paste strip removes the frame's newline for a single-line field
|
|
310
|
+
// exactly as it removes a bare Ctrl+J today, while the reverse order
|
|
311
|
+
// would leak the frame's letter as visible text.
|
|
312
|
+
const text = stripPasteFrames(stripEnterFrames(input));
|
|
306
313
|
if (text.length === 0)
|
|
307
314
|
return;
|
|
308
315
|
setValues((prev) => ({ ...prev, [field.key]: String(prev[field.key]) + text }));
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run status row's width plan (tui-scrollbar-edge-and-run-row §3.3.3).
|
|
3
|
+
*
|
|
4
|
+
* While a run is in flight, ONE row above the input box carries the spinner, the
|
|
5
|
+
* phrase and the `steer / interrupt / exit` hint clauses, and `planRunRow` decides
|
|
6
|
+
* what survives when the line is too narrow. It is a pure function with no React
|
|
7
|
+
* and no I/O so the whole ladder can be tested as arithmetic.
|
|
8
|
+
*
|
|
9
|
+
* THE ALLOCATION IS PER CLAUSE, NOT PER STRING, and that is the whole point.
|
|
10
|
+
* The idle hint row this one replaces owned the full line width and ended in
|
|
11
|
+
* `wrap="truncate"`; handing the label half the line and truncating the joined
|
|
12
|
+
* hint would cut `interrupt` to `inter...` at 38 columns - a regression of the
|
|
13
|
+
* "running hint is NEVER abbreviated" rule `Composer.hintText` documents. So:
|
|
14
|
+
*
|
|
15
|
+
* - clauses are dropped WHOLE, from the tail (`exit`, then `stop N`), and
|
|
16
|
+
* - `steer` and `interrupt` (REQUIRED_CLAUSES) are never dropped or cut mid-word
|
|
17
|
+
* while the row is enabled, and
|
|
18
|
+
* - the only thing allowed to end in an ellipsis is the label.
|
|
19
|
+
*/
|
|
20
|
+
/** Everything the label needs, kept in one shape so there is one place that names it. */
|
|
21
|
+
export interface RunActivity {
|
|
22
|
+
/** Epoch ms the current run began - the phrase sequence's seed. */
|
|
23
|
+
startedAt: number;
|
|
24
|
+
/** `Date.now() - startedAt`, already computed by App's 200 ms ticker. */
|
|
25
|
+
elapsedMs: number;
|
|
26
|
+
/** The RAW config flag, never the widened one (single-spinner D-5). */
|
|
27
|
+
reducedMotion: boolean;
|
|
28
|
+
/** The tool currently in flight, if any. */
|
|
29
|
+
runningTool?: string;
|
|
30
|
+
/** A context compaction is in flight; outranks the tool name and the phrase. */
|
|
31
|
+
compacting?: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface RunRowPlanInput {
|
|
34
|
+
/** Width of the row's container (the composer's content columns). */
|
|
35
|
+
cols: number;
|
|
36
|
+
/** Spinner + space + label, in display columns (the label's natural width). */
|
|
37
|
+
labelCols: number;
|
|
38
|
+
/** Display width of each hint clause, most urgent first. */
|
|
39
|
+
hintClauseCols: readonly number[];
|
|
40
|
+
/** Display width of the separator between clauses (` · ` or ` - `). */
|
|
41
|
+
separatorCols: number;
|
|
42
|
+
/** Display width of the right-aligned mode chip; 0 = no chip. */
|
|
43
|
+
chipCols: number;
|
|
44
|
+
}
|
|
45
|
+
export interface RunRowPlan {
|
|
46
|
+
/** Columns the label may occupy; below its natural width it is ellipsized. */
|
|
47
|
+
labelCols: number;
|
|
48
|
+
/** How many leading clauses to show; 0 = none (defensive tier only). */
|
|
49
|
+
hintClauses: number;
|
|
50
|
+
/** Whether the chip fits after everything else. */
|
|
51
|
+
chip: boolean;
|
|
52
|
+
}
|
|
53
|
+
/** One leading space, matching the idle hint row's `' '` indent. */
|
|
54
|
+
export declare const RUN_ROW_LEAD = 1;
|
|
55
|
+
/** Narrowest the label may be squeezed before a clause is dropped instead. */
|
|
56
|
+
export declare const RUN_ROW_MIN_LABEL_COLS = 10;
|
|
57
|
+
/** `steer` and `interrupt`: always whole while the row is enabled. */
|
|
58
|
+
export declare const RUN_ROW_REQUIRED_CLAUSES = 2;
|
|
59
|
+
/** Space kept between the last clause and the chip. */
|
|
60
|
+
export declare const RUN_ROW_CHIP_GAP = 2;
|
|
61
|
+
export declare function planRunRow(input: RunRowPlanInput): RunRowPlan;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run status row's width plan (tui-scrollbar-edge-and-run-row §3.3.3).
|
|
3
|
+
*
|
|
4
|
+
* While a run is in flight, ONE row above the input box carries the spinner, the
|
|
5
|
+
* phrase and the `steer / interrupt / exit` hint clauses, and `planRunRow` decides
|
|
6
|
+
* what survives when the line is too narrow. It is a pure function with no React
|
|
7
|
+
* and no I/O so the whole ladder can be tested as arithmetic.
|
|
8
|
+
*
|
|
9
|
+
* THE ALLOCATION IS PER CLAUSE, NOT PER STRING, and that is the whole point.
|
|
10
|
+
* The idle hint row this one replaces owned the full line width and ended in
|
|
11
|
+
* `wrap="truncate"`; handing the label half the line and truncating the joined
|
|
12
|
+
* hint would cut `interrupt` to `inter...` at 38 columns - a regression of the
|
|
13
|
+
* "running hint is NEVER abbreviated" rule `Composer.hintText` documents. So:
|
|
14
|
+
*
|
|
15
|
+
* - clauses are dropped WHOLE, from the tail (`exit`, then `stop N`), and
|
|
16
|
+
* - `steer` and `interrupt` (REQUIRED_CLAUSES) are never dropped or cut mid-word
|
|
17
|
+
* while the row is enabled, and
|
|
18
|
+
* - the only thing allowed to end in an ellipsis is the label.
|
|
19
|
+
*/
|
|
20
|
+
/** One leading space, matching the idle hint row's `' '` indent. */
|
|
21
|
+
export const RUN_ROW_LEAD = 1;
|
|
22
|
+
/** Narrowest the label may be squeezed before a clause is dropped instead. */
|
|
23
|
+
export const RUN_ROW_MIN_LABEL_COLS = 10;
|
|
24
|
+
/** `steer` and `interrupt`: always whole while the row is enabled. */
|
|
25
|
+
export const RUN_ROW_REQUIRED_CLAUSES = 2;
|
|
26
|
+
/** Space kept between the last clause and the chip. */
|
|
27
|
+
export const RUN_ROW_CHIP_GAP = 2;
|
|
28
|
+
/** Non-finite or negative widths collapse to 0 so no input can make the plan throw. */
|
|
29
|
+
function width(value) {
|
|
30
|
+
return Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
|
|
31
|
+
}
|
|
32
|
+
/** Width of the first `count` clauses joined by `separator`. */
|
|
33
|
+
function clausesWidth(clauses, count, separator) {
|
|
34
|
+
if (count <= 0)
|
|
35
|
+
return 0;
|
|
36
|
+
let total = separator * (count - 1);
|
|
37
|
+
for (let i = 0; i < count; i += 1)
|
|
38
|
+
total += clauses[i] ?? 0;
|
|
39
|
+
return total;
|
|
40
|
+
}
|
|
41
|
+
export function planRunRow(input) {
|
|
42
|
+
const inner = Math.max(0, width(input.cols) - RUN_ROW_LEAD);
|
|
43
|
+
const natural = width(input.labelCols);
|
|
44
|
+
const separator = width(input.separatorCols);
|
|
45
|
+
const chipCols = width(input.chipCols);
|
|
46
|
+
const clauses = input.hintClauseCols.map(width);
|
|
47
|
+
const total = clauses.length;
|
|
48
|
+
const labelOnly = {
|
|
49
|
+
labelCols: Math.min(natural, inner), hintClauses: 0, chip: false,
|
|
50
|
+
};
|
|
51
|
+
if (total < RUN_ROW_REQUIRED_CLAUSES)
|
|
52
|
+
return labelOnly;
|
|
53
|
+
// Tier 1: everything fits; the chip is the first thing to go.
|
|
54
|
+
const everything = natural + separator + clausesWidth(clauses, total, separator);
|
|
55
|
+
if (everything <= inner) {
|
|
56
|
+
const chip = chipCols > 0 && everything + RUN_ROW_CHIP_GAP + chipCols <= inner;
|
|
57
|
+
return { labelCols: natural, hintClauses: total, chip };
|
|
58
|
+
}
|
|
59
|
+
// Tier 2: drop clauses from the tail, but never below the required two; only the
|
|
60
|
+
// label may be squeezed (down to its minimum) to make the remaining clauses fit.
|
|
61
|
+
for (let kept = total - 1; kept >= RUN_ROW_REQUIRED_CLAUSES; kept -= 1) {
|
|
62
|
+
const available = inner - separator - clausesWidth(clauses, kept, separator);
|
|
63
|
+
if (available >= RUN_ROW_MIN_LABEL_COLS) {
|
|
64
|
+
return { labelCols: Math.min(natural, available), hintClauses: kept, chip: false };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Tier 3 (defensive, below ~40 columns): the label alone. The status bar's own
|
|
68
|
+
// `Esc x2 interrupt` carries the urgent hint at this width.
|
|
69
|
+
return labelOnly;
|
|
70
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The selection controller (tui-selection-and-scroll-follow §4.4). NON-REACT: it
|
|
3
|
-
* owns the mouse lifecycle, the 16 ms drag coalescer, the `decorate` hook and
|
|
4
|
-
*
|
|
5
|
-
* `App` registers on mount.
|
|
3
|
+
* owns the mouse lifecycle, the 16 ms drag coalescer, the `decorate` hook and
|
|
4
|
+
* the released-selection state Ctrl+C consumes, and it reaches the React tree
|
|
5
|
+
* only through the callbacks `App` registers on mount.
|
|
6
6
|
*
|
|
7
7
|
* WHY IT IS NOT A COMPONENT (D-6). A React re-render per motion report goes
|
|
8
8
|
* through the render governor and the whole component tree; the frame pipeline
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
* than by a staleness check that can be wrong.
|
|
29
29
|
*/
|
|
30
30
|
import type { MouseSource } from '../../input/stdin-filter.js';
|
|
31
|
+
import type { CopyVia } from '../clipboard.js';
|
|
31
32
|
import type { Theme } from '../theme.js';
|
|
32
33
|
import type { TermCapabilities } from '../capabilities.js';
|
|
33
|
-
import type { CopyVia } from '../clipboard.js';
|
|
34
34
|
/**
|
|
35
35
|
* How long a nominally-held button may sit MOTIONLESS before the watchdog lets
|
|
36
36
|
* go of it (I-11). Reset by every motion report, so it only fires when the
|
|
@@ -49,9 +49,6 @@ export interface SelectionControllerOptions {
|
|
|
49
49
|
repaint: () => boolean;
|
|
50
50
|
/** `App`'s `redrawNonce`, for the invalidated case (§4.4.3). */
|
|
51
51
|
requestRedraw: () => void;
|
|
52
|
-
copy: (text: string) => CopyVia;
|
|
53
|
-
/** Toast sink, registered by `App` on mount (§6.3). */
|
|
54
|
-
onCopied: (via: CopyVia, lines: number, chars: number) => void;
|
|
55
52
|
theme: () => Theme;
|
|
56
53
|
caps: TermCapabilities;
|
|
57
54
|
/** Terminal width, for the right edge of a multi-row highlight. */
|
|
@@ -64,6 +61,25 @@ export interface SelectionControllerOptions {
|
|
|
64
61
|
export interface SelectionController {
|
|
65
62
|
/** Feed to `createFrameDiffer({ decorate })`. Mirrors, then paints. */
|
|
66
63
|
decorate(lines: string[]): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Whether a RELEASED, non-empty selection is waiting for Ctrl+C
|
|
66
|
+
* (tui-shift-enter-copy-queue 4.2). Dragging does not count: the gesture
|
|
67
|
+
* is not finished, and a copy key pressed mid-drag must fall through to
|
|
68
|
+
* whatever it meant before this feature.
|
|
69
|
+
*/
|
|
70
|
+
hasPendingSelection(): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Take the pending selection: returns its text and line count, and clears
|
|
73
|
+
* the highlight, the settled state and the hold. `null` when nothing is
|
|
74
|
+
* pending. The caller owns the copy itself (`copyText` is the single
|
|
75
|
+
* clipboard path) and MUST take BEFORE copying: OSC 52 writes through
|
|
76
|
+
* `writeForeign`, the differ invalidates, and its `onInvalidate` clears
|
|
77
|
+
* this controller -- taking first makes that clear a no-op (4.3 / R7).
|
|
78
|
+
*/
|
|
79
|
+
takeSelection(): {
|
|
80
|
+
text: string;
|
|
81
|
+
lines: number;
|
|
82
|
+
} | null;
|
|
67
83
|
/** Subscribe to `hold` transitions; `App` mirrors this into React state. */
|
|
68
84
|
onHoldChange(listener: (hold: boolean) => void): () => void;
|
|
69
85
|
/** Called by `App` for key / resize / overlay / clear, and by `onInvalidate`. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The selection controller (tui-selection-and-scroll-follow §4.4). NON-REACT: it
|
|
3
|
-
* owns the mouse lifecycle, the 16 ms drag coalescer, the `decorate` hook and
|
|
4
|
-
*
|
|
5
|
-
* `App` registers on mount.
|
|
3
|
+
* owns the mouse lifecycle, the 16 ms drag coalescer, the `decorate` hook and
|
|
4
|
+
* the released-selection state Ctrl+C consumes, and it reaches the React tree
|
|
5
|
+
* only through the callbacks `App` registers on mount.
|
|
6
6
|
*
|
|
7
7
|
* WHY IT IS NOT A COMPONENT (D-6). A React re-render per motion report goes
|
|
8
8
|
* through the render governor and the whole component tree; the frame pipeline
|
|
@@ -57,6 +57,10 @@ export function createSelectionController(options) {
|
|
|
57
57
|
let enabled = true;
|
|
58
58
|
let sel = null;
|
|
59
59
|
let dragging = false;
|
|
60
|
+
/** A released, non-empty selection is waiting for Ctrl+C (4.2.1). */
|
|
61
|
+
let settled = false;
|
|
62
|
+
/** Mirror of the last `hold` emitted, so exits can be conditional. */
|
|
63
|
+
let holdActive = false;
|
|
60
64
|
let pendingFocus = null;
|
|
61
65
|
let flushTimer = null;
|
|
62
66
|
let holdWatchdog = null;
|
|
@@ -64,6 +68,7 @@ export function createSelectionController(options) {
|
|
|
64
68
|
/** Guards `decorate` against being re-entered from inside a repaint. */
|
|
65
69
|
let painting = false;
|
|
66
70
|
const emitHold = (hold) => {
|
|
71
|
+
holdActive = hold;
|
|
67
72
|
for (const listener of [...holdListeners])
|
|
68
73
|
listener(hold);
|
|
69
74
|
};
|
|
@@ -121,15 +126,18 @@ export function createSelectionController(options) {
|
|
|
121
126
|
// Nothing to undo: no timers, no repaint, no redraw. This is what keeps
|
|
122
127
|
// `onInvalidate` — which fires on every resize and every foreign write —
|
|
123
128
|
// free for a session that has never selected anything.
|
|
124
|
-
if (sel === null && !dragging && pendingFocus === null)
|
|
129
|
+
if (sel === null && !dragging && pendingFocus === null && !settled)
|
|
125
130
|
return;
|
|
126
|
-
const wasDragging = dragging;
|
|
127
131
|
sel = null;
|
|
128
132
|
dragging = false;
|
|
133
|
+
settled = false;
|
|
129
134
|
pendingFocus = null;
|
|
130
135
|
clearFlushTimer();
|
|
131
136
|
clearWatchdog();
|
|
132
|
-
|
|
137
|
+
// `holdActive`, not `wasDragging`: since tui-shift-enter-copy-queue a
|
|
138
|
+
// RELEASED selection also holds the viewport (4.2.3), so this is the
|
|
139
|
+
// exit for two states, not one.
|
|
140
|
+
if (holdActive)
|
|
133
141
|
emitHold(false);
|
|
134
142
|
paint(false);
|
|
135
143
|
};
|
|
@@ -150,26 +158,38 @@ export function createSelectionController(options) {
|
|
|
150
158
|
paint(true);
|
|
151
159
|
};
|
|
152
160
|
const finishSelection = () => {
|
|
153
|
-
if (!sel)
|
|
161
|
+
if (!sel) {
|
|
162
|
+
emitHold(false);
|
|
154
163
|
return;
|
|
164
|
+
}
|
|
155
165
|
const normal = normalize(sel);
|
|
156
166
|
if (isEmpty(normal)) {
|
|
157
|
-
// A plain click. It must never leave a one-cell highlight behind, and
|
|
158
|
-
// must never clobber the clipboard.
|
|
167
|
+
// A plain click. It must never leave a one-cell highlight behind, and
|
|
168
|
+
// it must never clobber the clipboard.
|
|
159
169
|
sel = null;
|
|
170
|
+
settled = false;
|
|
171
|
+
emitHold(false);
|
|
160
172
|
paint(false);
|
|
161
173
|
return;
|
|
162
174
|
}
|
|
163
|
-
|
|
164
|
-
|
|
175
|
+
if (selectedText(mirror.plain, normal).length === 0) {
|
|
176
|
+
// Geometry without content (blank cells): nothing honest to promise a
|
|
177
|
+
// later Ctrl+C, so this is the same no-op a click is.
|
|
165
178
|
sel = null;
|
|
179
|
+
settled = false;
|
|
180
|
+
emitHold(false);
|
|
166
181
|
paint(false);
|
|
167
182
|
return;
|
|
168
183
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
//
|
|
172
|
-
//
|
|
184
|
+
// RELEASED AND NON-EMPTY: the highlight STAYS and so does the hold
|
|
185
|
+
// (4.2.1 / 4.2.3). The highlight is the promise of what Ctrl+C will
|
|
186
|
+
// copy -- not a receipt for a copy that already happened -- and the
|
|
187
|
+
// hold keeps the rows under it frozen until that promise resolves,
|
|
188
|
+
// which is what lets "what you see is what you get" survive a
|
|
189
|
+
// streaming run. The watchdog is NOT re-armed: the release already
|
|
190
|
+
// happened, and the frozen state has explicit exits (Ctrl+C, any other
|
|
191
|
+
// key, resize, overlay, /mouse off).
|
|
192
|
+
settled = true;
|
|
173
193
|
paint(true);
|
|
174
194
|
};
|
|
175
195
|
const onMouse = (event) => {
|
|
@@ -222,7 +242,9 @@ export function createSelectionController(options) {
|
|
|
222
242
|
clearFlushTimer();
|
|
223
243
|
clearWatchdog();
|
|
224
244
|
dragging = false;
|
|
225
|
-
|
|
245
|
+
// `finishSelection` decides the hold: a non-empty release KEEPS it
|
|
246
|
+
// (4.2.3) so the pending selection cannot be pushed off screen; every
|
|
247
|
+
// empty path releases it there.
|
|
226
248
|
finishSelection();
|
|
227
249
|
};
|
|
228
250
|
const unsubscribe = options.source.subscribe(onMouse);
|
|
@@ -258,6 +280,32 @@ export function createSelectionController(options) {
|
|
|
258
280
|
holdListeners.add(listener);
|
|
259
281
|
return () => holdListeners.delete(listener);
|
|
260
282
|
},
|
|
283
|
+
hasPendingSelection() {
|
|
284
|
+
return settled && sel !== null;
|
|
285
|
+
},
|
|
286
|
+
takeSelection() {
|
|
287
|
+
if (!settled || sel === null)
|
|
288
|
+
return null;
|
|
289
|
+
const normal = normalize(sel);
|
|
290
|
+
const text = selectedText(mirror.plain, normal);
|
|
291
|
+
// CONSUMED BEFORE THE CALLER COPIES (4.3 / R7). The copy writes OSC
|
|
292
|
+
// 52 through `writeForeign`; the differ treats that as a foreign
|
|
293
|
+
// write and invalidates, and `onInvalidate` clears this controller on
|
|
294
|
+
// the next macrotask. Clearing first makes that callback a no-op;
|
|
295
|
+
// copying first would let it erase the held viewport state a tick
|
|
296
|
+
// after the copy -- the "copy flashes the screen" regression.
|
|
297
|
+
sel = null;
|
|
298
|
+
settled = false;
|
|
299
|
+
pendingFocus = null;
|
|
300
|
+
clearFlushTimer();
|
|
301
|
+
clearWatchdog();
|
|
302
|
+
if (holdActive)
|
|
303
|
+
emitHold(false);
|
|
304
|
+
paint(false);
|
|
305
|
+
if (text.length === 0)
|
|
306
|
+
return null;
|
|
307
|
+
return { text, lines: text.split('\n').length };
|
|
308
|
+
},
|
|
261
309
|
clear,
|
|
262
310
|
setEnabled(next) {
|
|
263
311
|
if (enabled === next)
|
|
@@ -270,6 +318,10 @@ export function createSelectionController(options) {
|
|
|
270
318
|
if (disposed)
|
|
271
319
|
return;
|
|
272
320
|
disposed = true;
|
|
321
|
+
// 4.2.3: a pending selection holds the viewport; teardown must let go
|
|
322
|
+
// of it explicitly, exactly like `clear()` does.
|
|
323
|
+
if (holdActive)
|
|
324
|
+
emitHold(false);
|
|
273
325
|
unsubscribe();
|
|
274
326
|
clearFlushTimer();
|
|
275
327
|
clearWatchdog();
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plain-text session rendering (spec §4.4). Pure, colorless, ANSI-free, so the
|
|
3
|
-
* exit replay can be piped, diffed, or pasted into an issue.
|
|
4
|
-
*
|
|
5
|
-
* Used only by the full-screen exit replay: inline mode already left the real
|
|
6
|
-
* transcript in the terminal's native scrollback, and replaying there would
|
|
7
|
-
* simply print everything twice.
|
|
8
|
-
*/
|
|
9
1
|
import type { Entry, UsageTotal } from '../agent/reducer.js';
|
|
10
2
|
import type { Glyphs } from './glyphs.js';
|
|
11
3
|
export interface TranscriptTextOptions {
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plain-text session rendering (spec §4.4). Pure, colorless, ANSI-free, so the
|
|
3
|
-
* exit replay can be piped, diffed, or pasted into an issue.
|
|
4
|
-
*
|
|
5
|
-
* Used only by the full-screen exit replay: inline mode already left the real
|
|
6
|
-
* transcript in the terminal's native scrollback, and replaying there would
|
|
7
|
-
* simply print everything twice.
|
|
8
|
-
*/
|
|
9
1
|
import { formatCost, formatDuration, formatTokens, promptTokensOf } from '../agent/usage.js';
|
|
10
2
|
import { formatRetryLine } from '../agent/retry-view.js';
|
|
11
3
|
const DEFAULT_MAX_ENTRIES = 200;
|
|
@@ -22,8 +22,12 @@ import type { ViewAction } from '../agent/reducer.js';
|
|
|
22
22
|
*
|
|
23
23
|
* `1` = the first text that names DRAG-SELECT and `/mouse`. `0` = the 0.6.2 text
|
|
24
24
|
* that taught the Shift bypass, recorded back when this was a boolean.
|
|
25
|
+
* `2` = the Ctrl+C-to-copy text (tui-shift-enter-copy-queue 4.4): releasing
|
|
26
|
+
* no longer copies, and every user who learned the old gesture -- which is
|
|
27
|
+
* every user who has a version recorded at all -- has to be told the new
|
|
28
|
+
* one, once.
|
|
25
29
|
*/
|
|
26
|
-
export declare const MOUSE_NOTICE_VERSION =
|
|
30
|
+
export declare const MOUSE_NOTICE_VERSION = 2;
|
|
27
31
|
/**
|
|
28
32
|
* The revision of the text below that a user must have seen for this notice to
|
|
29
33
|
* stay quiet (`state.json::vtInputNoticeVersion`, `0` when absent).
|
|
@@ -40,53 +44,7 @@ export declare const MOUSE_NOTICE_VERSION = 1;
|
|
|
40
44
|
* that offered only `/plan`, recorded back when this was a boolean.
|
|
41
45
|
*/
|
|
42
46
|
export declare const VT_INPUT_NOTICE_VERSION = 1;
|
|
43
|
-
|
|
44
|
-
* The `shift-tab-and-mouse-wheel-dead-on-some-terminals` notice (F1'). Shown at
|
|
45
|
-
* most once per `VT_INPUT_NOTICE_VERSION`, and only on a Windows console that
|
|
46
|
-
* cannot deliver either input — see `ui/win-vt-input.ts` for why that is a
|
|
47
|
-
* property of the Node version rather than of the terminal.
|
|
48
|
-
*
|
|
49
|
-
* IT NAMES WHAT THE KEY DOES NOW, not merely that it is unavailable, and that
|
|
50
|
-
* is the load-bearing half of the text. `Shift+Tab` on these machines is not
|
|
51
|
-
* inert: the modifier is lost inside libuv, so Ink sees an ordinary `Tab` and
|
|
52
|
-
* the `/` palette or an `@` popup completes its selection over the user's
|
|
53
|
-
* draft. A user told only "this key does not work" keeps pressing it and keeps
|
|
54
|
-
* losing text without ever connecting the two.
|
|
55
|
-
*
|
|
56
|
-
* THE FALLBACK KEY COMES BEFORE `/plan` IN BOTH BRANCHES, and it is named from
|
|
57
|
-
* `MODE_TOGGLE_KEYS` rather than spelled out, so the four consumers of that
|
|
58
|
-
* constant cannot drift apart. This notice is the last one of them to be wired
|
|
59
|
-
* up, and it is also the only channel that reaches the affected user without
|
|
60
|
-
* being asked to: the composer hint does not exist at all in inline mode and is
|
|
61
|
-
* switched off by a short terminal or `hints: false` in full-screen, and
|
|
62
|
-
* `/help` has to be typed by someone whose current belief is "the key does
|
|
63
|
-
* nothing" rather than "I should read the help". Ordering follows cost — one
|
|
64
|
-
* keystroke before four and a return.
|
|
65
|
-
*
|
|
66
|
-
* `Shift+Up` / `Shift+Down` is the scroll workaround named here because it is
|
|
67
|
-
* the only one PROVEN to survive: both Node versions emit `\x1b[1;2A` for it,
|
|
68
|
-
* byte for byte, in the probe data. `PgUp` / `PgDn` is expected to work too but
|
|
69
|
-
* was never injected, so it is left out rather than promised.
|
|
70
|
-
*
|
|
71
|
-
* THE WHEEL HALF IS FULL-SCREEN ONLY, and dropping it inline is not a detail.
|
|
72
|
-
* `Shift+Tab` is broken in both modes — the modifier dies inside libuv, well
|
|
73
|
-
* below anything this app chooses — but the wheel is only ours to lose in
|
|
74
|
-
* full-screen: inline never asks the console to report it (`mode` is a conjunct
|
|
75
|
-
* of `cli.tsx::wantMouse`), so the wheel goes on scrolling the terminal's own
|
|
76
|
-
* scrollback exactly as it always has. And `Shift+Up` / `Shift+Down` are handled
|
|
77
|
-
* inside `App`'s `if (fullscreen)` branch, so recommending them inline names a
|
|
78
|
-
* key that does nothing. Telling an inline user their working wheel is dead and
|
|
79
|
-
* then handing them an inert workaround is the same failure this notice exists
|
|
80
|
-
* to end — advice about a mode that is not running — merely pointed the other
|
|
81
|
-
* way.
|
|
82
|
-
*
|
|
83
|
-
* EXPORTED FOR ITS TEST, unlike the two notices above it. Asserting this text
|
|
84
|
-
* through a rendered frame does not work: the transcript wraps a notice at two
|
|
85
|
-
* columns wider than it displays it, so any phrase landing on a wrap boundary
|
|
86
|
-
* loses a character or two on the way to `lastFrame()` and the assertion fails
|
|
87
|
-
* for a reason that has nothing to do with the text.
|
|
88
|
-
*/
|
|
89
|
-
export declare function vtInputDeadNotice(nodeVersion: string, fullscreen: boolean): string;
|
|
47
|
+
export declare function vtInputDeadNotice(nodeVersion: string): string;
|
|
90
48
|
/**
|
|
91
49
|
* `{ requested, resolved }` when the raise happened, `undefined` otherwise —
|
|
92
50
|
* i.e. `cfg.transcriptRetainRequested` and `cfg.transcriptRetain`.
|
|
@@ -132,16 +90,6 @@ export interface MouseNoticeOptions {
|
|
|
132
90
|
export interface VtInputNoticeOptions {
|
|
133
91
|
/** `process.versions.node`, quoted back so the user can act on it. */
|
|
134
92
|
nodeVersion: string;
|
|
135
|
-
/**
|
|
136
|
-
* Whether this run owns the alternate screen, i.e. `App`'s own `fullscreen`.
|
|
137
|
-
*
|
|
138
|
-
* Selects which half of the text applies: inline keeps the wheel and loses the
|
|
139
|
-
* full-screen scroll keys, so it is told about `Shift+Tab` and nothing else
|
|
140
|
-
* (see `vtInputDeadNotice`). Taken from the caller rather than re-derived here
|
|
141
|
-
* for the same reason the version is — one source, no chance of the notice and
|
|
142
|
-
* the renderer disagreeing about which mode is running.
|
|
143
|
-
*/
|
|
144
|
-
fullscreen: boolean;
|
|
145
93
|
/**
|
|
146
94
|
* Record that `VT_INPUT_NOTICE_VERSION` was shown (`state.json`). Called once,
|
|
147
95
|
* after dispatch — and it must write that constant, not `true`: the gate
|
|
@@ -26,8 +26,12 @@ import { getLogger } from '../logging/logger.js';
|
|
|
26
26
|
*
|
|
27
27
|
* `1` = the first text that names DRAG-SELECT and `/mouse`. `0` = the 0.6.2 text
|
|
28
28
|
* that taught the Shift bypass, recorded back when this was a boolean.
|
|
29
|
+
* `2` = the Ctrl+C-to-copy text (tui-shift-enter-copy-queue 4.4): releasing
|
|
30
|
+
* no longer copies, and every user who learned the old gesture -- which is
|
|
31
|
+
* every user who has a version recorded at all -- has to be told the new
|
|
32
|
+
* one, once.
|
|
29
33
|
*/
|
|
30
|
-
export const MOUSE_NOTICE_VERSION =
|
|
34
|
+
export const MOUSE_NOTICE_VERSION = 2;
|
|
31
35
|
/**
|
|
32
36
|
* The one-shot mouse notice (tui-selection-and-scroll-follow §5.2 row 29).
|
|
33
37
|
*
|
|
@@ -47,8 +51,8 @@ function mouseNoticeText(selectEnabled) {
|
|
|
47
51
|
return ('Mouse wheel scrolls the transcript. Drag-select is off (mouseSelect); ' +
|
|
48
52
|
'/mouse off hands the mouse back to your terminal for this session.');
|
|
49
53
|
}
|
|
50
|
-
return ('Mouse wheel scrolls the transcript
|
|
51
|
-
'
|
|
54
|
+
return ('Mouse wheel scrolls the transcript; drag to select, then Ctrl+C to copy. ' +
|
|
55
|
+
'/mouse off hands the mouse back to your terminal for this session.');
|
|
52
56
|
}
|
|
53
57
|
/**
|
|
54
58
|
* The §5.1 notice (tui-render-performance). Shown once per run, and only when
|
|
@@ -80,61 +84,11 @@ function retainRaisedNotice(requested, resolved) {
|
|
|
80
84
|
* that offered only `/plan`, recorded back when this was a boolean.
|
|
81
85
|
*/
|
|
82
86
|
export const VT_INPUT_NOTICE_VERSION = 1;
|
|
83
|
-
|
|
84
|
-
* The `shift-tab-and-mouse-wheel-dead-on-some-terminals` notice (F1'). Shown at
|
|
85
|
-
* most once per `VT_INPUT_NOTICE_VERSION`, and only on a Windows console that
|
|
86
|
-
* cannot deliver either input — see `ui/win-vt-input.ts` for why that is a
|
|
87
|
-
* property of the Node version rather than of the terminal.
|
|
88
|
-
*
|
|
89
|
-
* IT NAMES WHAT THE KEY DOES NOW, not merely that it is unavailable, and that
|
|
90
|
-
* is the load-bearing half of the text. `Shift+Tab` on these machines is not
|
|
91
|
-
* inert: the modifier is lost inside libuv, so Ink sees an ordinary `Tab` and
|
|
92
|
-
* the `/` palette or an `@` popup completes its selection over the user's
|
|
93
|
-
* draft. A user told only "this key does not work" keeps pressing it and keeps
|
|
94
|
-
* losing text without ever connecting the two.
|
|
95
|
-
*
|
|
96
|
-
* THE FALLBACK KEY COMES BEFORE `/plan` IN BOTH BRANCHES, and it is named from
|
|
97
|
-
* `MODE_TOGGLE_KEYS` rather than spelled out, so the four consumers of that
|
|
98
|
-
* constant cannot drift apart. This notice is the last one of them to be wired
|
|
99
|
-
* up, and it is also the only channel that reaches the affected user without
|
|
100
|
-
* being asked to: the composer hint does not exist at all in inline mode and is
|
|
101
|
-
* switched off by a short terminal or `hints: false` in full-screen, and
|
|
102
|
-
* `/help` has to be typed by someone whose current belief is "the key does
|
|
103
|
-
* nothing" rather than "I should read the help". Ordering follows cost — one
|
|
104
|
-
* keystroke before four and a return.
|
|
105
|
-
*
|
|
106
|
-
* `Shift+Up` / `Shift+Down` is the scroll workaround named here because it is
|
|
107
|
-
* the only one PROVEN to survive: both Node versions emit `\x1b[1;2A` for it,
|
|
108
|
-
* byte for byte, in the probe data. `PgUp` / `PgDn` is expected to work too but
|
|
109
|
-
* was never injected, so it is left out rather than promised.
|
|
110
|
-
*
|
|
111
|
-
* THE WHEEL HALF IS FULL-SCREEN ONLY, and dropping it inline is not a detail.
|
|
112
|
-
* `Shift+Tab` is broken in both modes — the modifier dies inside libuv, well
|
|
113
|
-
* below anything this app chooses — but the wheel is only ours to lose in
|
|
114
|
-
* full-screen: inline never asks the console to report it (`mode` is a conjunct
|
|
115
|
-
* of `cli.tsx::wantMouse`), so the wheel goes on scrolling the terminal's own
|
|
116
|
-
* scrollback exactly as it always has. And `Shift+Up` / `Shift+Down` are handled
|
|
117
|
-
* inside `App`'s `if (fullscreen)` branch, so recommending them inline names a
|
|
118
|
-
* key that does nothing. Telling an inline user their working wheel is dead and
|
|
119
|
-
* then handing them an inert workaround is the same failure this notice exists
|
|
120
|
-
* to end — advice about a mode that is not running — merely pointed the other
|
|
121
|
-
* way.
|
|
122
|
-
*
|
|
123
|
-
* EXPORTED FOR ITS TEST, unlike the two notices above it. Asserting this text
|
|
124
|
-
* through a rendered frame does not work: the transcript wraps a notice at two
|
|
125
|
-
* columns wider than it displays it, so any phrase landing on a wrap boundary
|
|
126
|
-
* loses a character or two on the way to `lastFrame()` and the assertion fails
|
|
127
|
-
* for a reason that has nothing to do with the text.
|
|
128
|
-
*/
|
|
129
|
-
export function vtInputDeadNotice(nodeVersion, fullscreen) {
|
|
87
|
+
export function vtInputDeadNotice(nodeVersion) {
|
|
130
88
|
const cause = `Node ${nodeVersion} on Windows does not turn on the console's VT input mode, so `;
|
|
131
89
|
const cost = 'it will not switch mode, and with the / palette or an @ popup open it completes that ' +
|
|
132
90
|
'instead, overwriting your draft. ';
|
|
133
91
|
const toggle = `Press ${MODE_TOGGLE_KEYS.fallback} to switch mode instead (or /plan)`;
|
|
134
|
-
if (!fullscreen) {
|
|
135
|
-
return (`${cause}Shift+Tab never arrives: it comes through as a PLAIN TAB - ${cost}` +
|
|
136
|
-
`${toggle}. Node 22.17.0+ (or 24.2.0+) restores it.`);
|
|
137
|
-
}
|
|
138
92
|
return (`${cause}two keys never arrive: the wheel sends nothing at all, and Shift+Tab arrives ` +
|
|
139
93
|
`as a PLAIN TAB - ${cost}${toggle}, and Shift+Up / Shift+Down to scroll. ` +
|
|
140
94
|
'Node 22.17.0+ (or 24.2.0+) restores both.');
|
|
@@ -199,7 +153,6 @@ export function useStartupNotices(dispatch, mouseNotice, retainNotice, vtInputNo
|
|
|
199
153
|
const vtNoticeRef = useRef(vtInputNotice);
|
|
200
154
|
vtNoticeRef.current = vtInputNotice;
|
|
201
155
|
const vtNodeVersion = vtInputNotice?.nodeVersion;
|
|
202
|
-
const vtFullscreen = vtInputNotice?.fullscreen ?? false;
|
|
203
156
|
const vtNoticeShown = useRef(false);
|
|
204
157
|
useEffect(() => {
|
|
205
158
|
if (vtNodeVersion === undefined || vtNoticeShown.current)
|
|
@@ -210,10 +163,10 @@ export function useStartupNotices(dispatch, mouseNotice, retainNotice, vtInputNo
|
|
|
210
163
|
dispatch({
|
|
211
164
|
type: 'notice',
|
|
212
165
|
level: 'warn',
|
|
213
|
-
text: vtInputDeadNotice(vtNodeVersion
|
|
166
|
+
text: vtInputDeadNotice(vtNodeVersion),
|
|
214
167
|
});
|
|
215
168
|
vtNoticeRef.current?.onSeen();
|
|
216
|
-
}, [vtNodeVersion,
|
|
169
|
+
}, [vtNodeVersion, dispatch]);
|
|
217
170
|
// A `warn` notice rather than a toast: it is about a value the user typed, so
|
|
218
171
|
// it belongs in the transcript where it can be scrolled back to, not in a row
|
|
219
172
|
// that expires. DEPENDS ON THE TWO SCALARS, never on the options object —
|
|
@@ -32,7 +32,7 @@ export declare const OVERLAY_PAGE = 8;
|
|
|
32
32
|
export interface WheelRoutingOptions {
|
|
33
33
|
isPointerCaptured?: () => boolean;
|
|
34
34
|
isActive?: () => boolean;
|
|
35
|
-
/** Absent when mouse support is off,
|
|
35
|
+
/** Absent when mouse support is off, or on a non-TTY. */
|
|
36
36
|
mouseSource?: MouseSource;
|
|
37
37
|
/** Read at EVENT time for the routing branch, and again at FLUSH time (P1-3). */
|
|
38
38
|
getOverlay: () => Overlay | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aragon-agent/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "AragonAgent CLI — a Claude-Code / Codex-style interactive terminal UI (TUI) on top of the @aragon-agent/core engine. Installable and runnable via npm / npx.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "AragonAgent contributors",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"prepublishOnly": "npm run build"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aragon-agent/core": "^0.2.
|
|
59
|
+
"@aragon-agent/core": "^0.2.22",
|
|
60
60
|
"chalk": "^5.6.2",
|
|
61
61
|
"cli-highlight": "^2.0.0",
|
|
62
62
|
"commander": "^12.1.0",
|