@ocis/myagent-cli 0.2.0
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/README.md +357 -0
- package/dist/agent/context.d.ts +33 -0
- package/dist/agent/context.js +169 -0
- package/dist/agent/modes.d.ts +21 -0
- package/dist/agent/modes.js +84 -0
- package/dist/agent/prompt-builder.d.ts +9 -0
- package/dist/agent/prompt-builder.js +31 -0
- package/dist/agent/sessions.d.ts +38 -0
- package/dist/agent/sessions.js +130 -0
- package/dist/agent/todo.d.ts +18 -0
- package/dist/agent/todo.js +61 -0
- package/dist/agent/turn.d.ts +309 -0
- package/dist/agent/turn.js +1253 -0
- package/dist/approval/policy.d.ts +81 -0
- package/dist/approval/policy.js +157 -0
- package/dist/config.d.ts +49 -0
- package/dist/config.js +156 -0
- package/dist/git/status.d.ts +89 -0
- package/dist/git/status.js +226 -0
- package/dist/headless.d.ts +72 -0
- package/dist/headless.js +330 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +511 -0
- package/dist/protocol/client.d.ts +123 -0
- package/dist/protocol/client.js +250 -0
- package/dist/protocol/sse-frames.d.ts +6 -0
- package/dist/protocol/sse-frames.js +75 -0
- package/dist/protocol/types.d.ts +200 -0
- package/dist/protocol/types.js +8 -0
- package/dist/runtime.d.ts +38 -0
- package/dist/runtime.js +166 -0
- package/dist/sanitize.d.ts +1 -0
- package/dist/sanitize.js +21 -0
- package/dist/skills/discovery.d.ts +24 -0
- package/dist/skills/discovery.js +109 -0
- package/dist/tools/binary.d.ts +2 -0
- package/dist/tools/binary.js +22 -0
- package/dist/tools/diff.d.ts +1 -0
- package/dist/tools/diff.js +49 -0
- package/dist/tools/find.d.ts +2 -0
- package/dist/tools/find.js +61 -0
- package/dist/tools/fs.d.ts +2 -0
- package/dist/tools/fs.js +276 -0
- package/dist/tools/glob.d.ts +6 -0
- package/dist/tools/glob.js +131 -0
- package/dist/tools/grep.d.ts +3 -0
- package/dist/tools/grep.js +228 -0
- package/dist/tools/paths.d.ts +27 -0
- package/dist/tools/paths.js +124 -0
- package/dist/tools/registry.d.ts +13 -0
- package/dist/tools/registry.js +38 -0
- package/dist/tools/shell.d.ts +2 -0
- package/dist/tools/shell.js +136 -0
- package/dist/tools/skills.d.ts +2 -0
- package/dist/tools/skills.js +36 -0
- package/dist/tools/todo.d.ts +2 -0
- package/dist/tools/todo.js +43 -0
- package/dist/tools/transfer.d.ts +2 -0
- package/dist/tools/transfer.js +145 -0
- package/dist/tools/truncate.d.ts +12 -0
- package/dist/tools/truncate.js +46 -0
- package/dist/tools/types.d.ts +85 -0
- package/dist/tools/types.js +63 -0
- package/dist/ui/app.d.ts +39 -0
- package/dist/ui/app.js +1061 -0
- package/dist/ui/colors.d.ts +100 -0
- package/dist/ui/colors.js +169 -0
- package/dist/ui/components.d.ts +267 -0
- package/dist/ui/components.js +811 -0
- package/dist/ui/diff.d.ts +37 -0
- package/dist/ui/diff.js +143 -0
- package/dist/ui/format.d.ts +28 -0
- package/dist/ui/format.js +76 -0
- package/dist/ui/help.d.ts +6 -0
- package/dist/ui/help.js +45 -0
- package/dist/ui/highlight.d.ts +20 -0
- package/dist/ui/highlight.js +210 -0
- package/dist/ui/logo.d.ts +24 -0
- package/dist/ui/logo.js +106 -0
- package/dist/ui/model-list.d.ts +10 -0
- package/dist/ui/model-list.js +33 -0
- package/dist/ui/quit-confirm.d.ts +8 -0
- package/dist/ui/quit-confirm.js +40 -0
- package/dist/ui/select-popup.d.ts +30 -0
- package/dist/ui/select-popup.js +54 -0
- package/dist/ui/theme.d.ts +4 -0
- package/dist/ui/theme.js +41 -0
- package/dist/ui/tool-view.d.ts +20 -0
- package/dist/ui/tool-view.js +326 -0
- package/package.json +44 -0
- package/skills/git-commit/SKILL.md +27 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { RgbColor } from "@earendil-works/pi-tui";
|
|
2
|
+
export declare function isColorEnabled(): boolean;
|
|
3
|
+
export declare function rgb(r: number, g: number, b: number, text: string): string;
|
|
4
|
+
export declare const style: {
|
|
5
|
+
bold: (s: string) => string;
|
|
6
|
+
dim: (s: string) => string;
|
|
7
|
+
italic: (s: string) => string;
|
|
8
|
+
underline: (s: string) => string;
|
|
9
|
+
red: (s: string) => string;
|
|
10
|
+
green: (s: string) => string;
|
|
11
|
+
yellow: (s: string) => string;
|
|
12
|
+
cyan: (s: string) => string;
|
|
13
|
+
};
|
|
14
|
+
/** Plan mode — orange (clearly separate hue from coding's green). */
|
|
15
|
+
export declare const PLAN_COLOR: (s: string) => string;
|
|
16
|
+
/** Coding mode — green, muted so the prompt frame doesn't glare. */
|
|
17
|
+
export declare const CODING_COLOR: (s: string) => string;
|
|
18
|
+
/** Cowork mode (general tasks) — purple. */
|
|
19
|
+
export declare const COWORK_COLOR: (s: string) => string;
|
|
20
|
+
/** Muted gray for panel content — kept low-contrast on the tinted panel. */
|
|
21
|
+
export declare const GRAY_COLOR: (s: string) => string;
|
|
22
|
+
/** Panel title gray — just a step brighter than the content gray. */
|
|
23
|
+
export declare const TITLE_COLOR: (s: string) => string;
|
|
24
|
+
/** Session title (the sidebar's headline) — the panel's brightest text, a
|
|
25
|
+
* step above the section-title gray so the current session reads at a glance. */
|
|
26
|
+
export declare const SESSION_TITLE_COLOR: (s: string) => string;
|
|
27
|
+
/** Markdown headings — bright light-blue (the CONTEXT section hue), clearly
|
|
28
|
+
* brighter than bold prose so headings read as headings. */
|
|
29
|
+
export declare const headingColor: (s: string) => string;
|
|
30
|
+
/** Dimmer gray for secondary/status text. */
|
|
31
|
+
export declare const GRAY_DIM_COLOR: (s: string) => string;
|
|
32
|
+
/** Border color for the editor, by mode. */
|
|
33
|
+
export declare function modeBorder(mode: "plan" | "coding" | "cowork"): (s: string) => string;
|
|
34
|
+
/** AUTO badge — amber so "running unattended" reads at a glance (ASK stays gray). */
|
|
35
|
+
export declare const AUTO_COLOR: (s: string) => string;
|
|
36
|
+
/** Diff line colors (rgb() no-ops when color is disabled). */
|
|
37
|
+
export declare const diffAdd: (s: string) => string;
|
|
38
|
+
export declare const diffDel: (s: string) => string;
|
|
39
|
+
/** Section hues — title text + the tint of the full-width header band. */
|
|
40
|
+
declare const SECTION_HUES: {
|
|
41
|
+
readonly context: {
|
|
42
|
+
readonly r: 125;
|
|
43
|
+
readonly g: 211;
|
|
44
|
+
readonly b: 252;
|
|
45
|
+
};
|
|
46
|
+
readonly todo: {
|
|
47
|
+
readonly r: 196;
|
|
48
|
+
readonly g: 181;
|
|
49
|
+
readonly b: 253;
|
|
50
|
+
};
|
|
51
|
+
readonly changes: {
|
|
52
|
+
readonly r: 253;
|
|
53
|
+
readonly g: 186;
|
|
54
|
+
readonly b: 116;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
export type SectionName = keyof typeof SECTION_HUES;
|
|
58
|
+
/** Panel tint used when the terminal background cannot be detected. */
|
|
59
|
+
export declare const DEFAULT_PANEL_BG: RgbColor;
|
|
60
|
+
/**
|
|
61
|
+
* Panel background: a few percent lighter than a dark terminal background,
|
|
62
|
+
* a few percent darker than a light one (so it stays visible either way).
|
|
63
|
+
*/
|
|
64
|
+
export declare function panelBackgroundRgb(terminalBg?: RgbColor): RgbColor;
|
|
65
|
+
/**
|
|
66
|
+
* Popup background: a stronger tint than the panel so a floating card reads
|
|
67
|
+
* above the transcript. Undefined when the terminal background is unknown —
|
|
68
|
+
* the card then falls back to its border alone (never assumes dark or light).
|
|
69
|
+
*/
|
|
70
|
+
export declare function overlayBackgroundRgb(terminalBg?: RgbColor): RgbColor | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* User-message band: a subtle tint so the prompt reads as its own block.
|
|
73
|
+
* Undefined without a terminal background — the message then renders untinted.
|
|
74
|
+
*/
|
|
75
|
+
export declare function userMessageBackgroundRgb(terminalBg?: RgbColor): RgbColor | undefined;
|
|
76
|
+
/** User-message text — softer than the terminal default so prompts don't glare. */
|
|
77
|
+
export declare const userMessageColor: (s: string) => string;
|
|
78
|
+
/** User-message accent bar (violet, matching the logo gradient). */
|
|
79
|
+
export declare const userMessageAccent: (s: string) => string;
|
|
80
|
+
/** Tool output content — one step darker than the shared content gray. */
|
|
81
|
+
export declare const toolOutputColor: (s: string) => string;
|
|
82
|
+
/** Apply a background color to `text` (no-op when color is disabled). */
|
|
83
|
+
export declare function bgRgb(color: RgbColor, text: string): string;
|
|
84
|
+
export declare function paintLine(text: string, width: number, bg?: RgbColor): string;
|
|
85
|
+
/** Assistant prose tone — one step grayer than the terminal's default foreground. */
|
|
86
|
+
export declare const assistantColor: (s: string) => string;
|
|
87
|
+
/** Keyword hue (declarations, control flow). */
|
|
88
|
+
export declare const syntaxKeyword: (s: string) => string;
|
|
89
|
+
/** String / template literal hue. */
|
|
90
|
+
export declare const syntaxString: (s: string) => string;
|
|
91
|
+
/** Numeric literal hue. */
|
|
92
|
+
export declare const syntaxNumber: (s: string) => string;
|
|
93
|
+
/** Comment hue — muted and italic so it recedes. */
|
|
94
|
+
export declare const syntaxComment: (s: string) => string;
|
|
95
|
+
/**
|
|
96
|
+
* Foreground style for the section's accent bar — the hue muted toward the
|
|
97
|
+
* panel tint so it reads as an accent, not a highlight.
|
|
98
|
+
*/
|
|
99
|
+
export declare function sectionFg(name: SectionName, panel?: RgbColor): (s: string) => string;
|
|
100
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// ANSI styling for the TUI.
|
|
3
|
+
//
|
|
4
|
+
// pi-tui components take style callbacks, so this module is the single place
|
|
5
|
+
// that decides whether color is available (TTY + NO_COLOR + TERM) and how the
|
|
6
|
+
// mode/approval palettes map to SGR sequences.
|
|
7
|
+
// -------------------------------------------------------------------
|
|
8
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
9
|
+
const colorEnabled = Boolean(process.stdout.isTTY) &&
|
|
10
|
+
!process.env.NO_COLOR &&
|
|
11
|
+
process.env.TERM !== "dumb";
|
|
12
|
+
export function isColorEnabled() {
|
|
13
|
+
return colorEnabled;
|
|
14
|
+
}
|
|
15
|
+
function sgr(open, close, text) {
|
|
16
|
+
if (!colorEnabled)
|
|
17
|
+
return text;
|
|
18
|
+
return `\u001b[${open}m${text}\u001b[${close}m`;
|
|
19
|
+
}
|
|
20
|
+
export function rgb(r, g, b, text) {
|
|
21
|
+
return sgr(`38;2;${r};${g};${b}`, "39", text);
|
|
22
|
+
}
|
|
23
|
+
export const style = {
|
|
24
|
+
bold: (s) => sgr("1", "22", s),
|
|
25
|
+
dim: (s) => sgr("2", "22", s),
|
|
26
|
+
italic: (s) => sgr("3", "23", s),
|
|
27
|
+
underline: (s) => sgr("4", "24", s),
|
|
28
|
+
red: (s) => sgr("31", "39", s),
|
|
29
|
+
green: (s) => sgr("32", "39", s),
|
|
30
|
+
yellow: (s) => sgr("33", "39", s),
|
|
31
|
+
cyan: (s) => sgr("36", "39", s),
|
|
32
|
+
};
|
|
33
|
+
// ---------------------------------------------------------------------------
|
|
34
|
+
// Semantic palettes
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
/** Plan mode — orange (clearly separate hue from coding's green). */
|
|
37
|
+
export const PLAN_COLOR = (s) => rgb(0xf9, 0x73, 0x16, s);
|
|
38
|
+
/** Coding mode — green, muted so the prompt frame doesn't glare. */
|
|
39
|
+
export const CODING_COLOR = (s) => rgb(0x5f, 0xbe, 0x82, s);
|
|
40
|
+
/** Cowork mode (general tasks) — purple. */
|
|
41
|
+
export const COWORK_COLOR = (s) => rgb(0xa7, 0x8b, 0xfa, s);
|
|
42
|
+
/** Muted gray for panel content — kept low-contrast on the tinted panel. */
|
|
43
|
+
export const GRAY_COLOR = (s) => rgb(0x7f, 0x87, 0x94, s);
|
|
44
|
+
/** Panel title gray — just a step brighter than the content gray. */
|
|
45
|
+
export const TITLE_COLOR = (s) => rgb(0x9a, 0xa2, 0xae, s);
|
|
46
|
+
/** Session title (the sidebar's headline) — the panel's brightest text, a
|
|
47
|
+
* step above the section-title gray so the current session reads at a glance. */
|
|
48
|
+
export const SESSION_TITLE_COLOR = (s) => rgb(0xc2, 0xc8, 0xd2, s);
|
|
49
|
+
/** Markdown headings — bright light-blue (the CONTEXT section hue), clearly
|
|
50
|
+
* brighter than bold prose so headings read as headings. */
|
|
51
|
+
export const headingColor = (s) => rgb(0x7d, 0xd3, 0xfc, s);
|
|
52
|
+
/** Dimmer gray for secondary/status text. */
|
|
53
|
+
export const GRAY_DIM_COLOR = (s) => rgb(0x59, 0x61, 0x6e, s);
|
|
54
|
+
/** Border color for the editor, by mode. */
|
|
55
|
+
export function modeBorder(mode) {
|
|
56
|
+
if (mode === "plan")
|
|
57
|
+
return PLAN_COLOR;
|
|
58
|
+
return mode === "coding" ? CODING_COLOR : COWORK_COLOR;
|
|
59
|
+
}
|
|
60
|
+
/** AUTO badge — amber so "running unattended" reads at a glance (ASK stays gray). */
|
|
61
|
+
export const AUTO_COLOR = (s) => rgb(0xf9, 0xc7, 0x4a, s);
|
|
62
|
+
/** Diff line colors (rgb() no-ops when color is disabled). */
|
|
63
|
+
export const diffAdd = (s) => rgb(0x4a, 0xde, 0x80, s);
|
|
64
|
+
export const diffDel = (s) => rgb(0xf8, 0x71, 0x71, s);
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Panel + sidebar sections
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
/** Section hues — title text + the tint of the full-width header band. */
|
|
69
|
+
const SECTION_HUES = {
|
|
70
|
+
context: { r: 0x7d, g: 0xd3, b: 0xfc },
|
|
71
|
+
todo: { r: 0xc4, g: 0xb5, b: 0xfd },
|
|
72
|
+
changes: { r: 0xfd, g: 0xba, b: 0x74 },
|
|
73
|
+
};
|
|
74
|
+
/** Panel tint used when the terminal background cannot be detected. */
|
|
75
|
+
export const DEFAULT_PANEL_BG = { r: 0x22, g: 0x26, b: 0x2e };
|
|
76
|
+
function clamp255(n) {
|
|
77
|
+
return Math.max(0, Math.min(255, Math.round(n)));
|
|
78
|
+
}
|
|
79
|
+
function mix(a, b, weight) {
|
|
80
|
+
return {
|
|
81
|
+
r: clamp255(a.r + (b.r - a.r) * weight),
|
|
82
|
+
g: clamp255(a.g + (b.g - a.g) * weight),
|
|
83
|
+
b: clamp255(a.b + (b.b - a.b) * weight),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function luminance(color) {
|
|
87
|
+
return (0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b) / 255;
|
|
88
|
+
}
|
|
89
|
+
/** Whichever end of the scale a terminal background tints toward. */
|
|
90
|
+
function contrastTarget(terminalBg) {
|
|
91
|
+
return luminance(terminalBg) < 0.5
|
|
92
|
+
? { r: 0xff, g: 0xff, b: 0xff }
|
|
93
|
+
: { r: 0x00, g: 0x00, b: 0x00 };
|
|
94
|
+
}
|
|
95
|
+
/** Mix the terminal background toward its contrast target by `ratio`. */
|
|
96
|
+
function tint(terminalBg, ratio) {
|
|
97
|
+
return terminalBg ? mix(terminalBg, contrastTarget(terminalBg), ratio) : undefined;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Panel background: a few percent lighter than a dark terminal background,
|
|
101
|
+
* a few percent darker than a light one (so it stays visible either way).
|
|
102
|
+
*/
|
|
103
|
+
export function panelBackgroundRgb(terminalBg) {
|
|
104
|
+
return tint(terminalBg, 0.06) ?? DEFAULT_PANEL_BG;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Popup background: a stronger tint than the panel so a floating card reads
|
|
108
|
+
* above the transcript. Undefined when the terminal background is unknown —
|
|
109
|
+
* the card then falls back to its border alone (never assumes dark or light).
|
|
110
|
+
*/
|
|
111
|
+
export function overlayBackgroundRgb(terminalBg) {
|
|
112
|
+
return tint(terminalBg, 0.12);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* User-message band: a subtle tint so the prompt reads as its own block.
|
|
116
|
+
* Undefined without a terminal background — the message then renders untinted.
|
|
117
|
+
*/
|
|
118
|
+
export function userMessageBackgroundRgb(terminalBg) {
|
|
119
|
+
return tint(terminalBg, 0.06);
|
|
120
|
+
}
|
|
121
|
+
/** User-message text — softer than the terminal default so prompts don't glare. */
|
|
122
|
+
export const userMessageColor = (s) => rgb(0xc2, 0xc8, 0xd2, s);
|
|
123
|
+
/** User-message accent bar (violet, matching the logo gradient). */
|
|
124
|
+
export const userMessageAccent = (s) => rgb(0xc0, 0x84, 0xfc, s);
|
|
125
|
+
/** Tool output content — one step darker than the shared content gray. */
|
|
126
|
+
export const toolOutputColor = (s) => rgb(0x6b, 0x73, 0x80, s);
|
|
127
|
+
/** Apply a background color to `text` (no-op when color is disabled). */
|
|
128
|
+
export function bgRgb(color, text) {
|
|
129
|
+
return sgr(`48;2;${color.r};${color.g};${color.b}`, "49", text);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Clamp `text` to `width` and, when `bg` is set, tint the full line —
|
|
133
|
+
* re-opening the tint after any inner reset so the band stays solid.
|
|
134
|
+
*
|
|
135
|
+
* Inner resets come in two forms: the generic `\u001b[0m` (pasted content)
|
|
136
|
+
* and the paired `\u001b[49m` this module's own bgRgb emits as its close
|
|
137
|
+
* code (nested paintLine output). Splitting on both keeps the band solid
|
|
138
|
+
* either way; the join normalizes to the generic reset.
|
|
139
|
+
*/
|
|
140
|
+
const INNER_RESET = /\u001b\[(?:0|49)m/g;
|
|
141
|
+
export function paintLine(text, width, bg) {
|
|
142
|
+
const safeWidth = Math.max(1, width);
|
|
143
|
+
const clipped = truncateToWidth(text, safeWidth, "…", true);
|
|
144
|
+
const padded = clipped + " ".repeat(Math.max(0, safeWidth - visibleWidth(clipped)));
|
|
145
|
+
if (!bg)
|
|
146
|
+
return padded;
|
|
147
|
+
return padded.split(INNER_RESET).map((segment) => bgRgb(bg, segment)).join("\u001b[0m");
|
|
148
|
+
}
|
|
149
|
+
/** Assistant prose tone — one step grayer than the terminal's default foreground. */
|
|
150
|
+
export const assistantColor = (s) => rgb(0xb1, 0xb8, 0xc4, s);
|
|
151
|
+
// ---------------------------------------------------------------------------
|
|
152
|
+
// Syntax highlighting (tool output)
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
/** Keyword hue (declarations, control flow). */
|
|
155
|
+
export const syntaxKeyword = (s) => rgb(0xc6, 0x78, 0xdd, s);
|
|
156
|
+
/** String / template literal hue. */
|
|
157
|
+
export const syntaxString = (s) => rgb(0x98, 0xc3, 0x79, s);
|
|
158
|
+
/** Numeric literal hue. */
|
|
159
|
+
export const syntaxNumber = (s) => rgb(0xd1, 0x9a, 0x66, s);
|
|
160
|
+
/** Comment hue — muted and italic so it recedes. */
|
|
161
|
+
export const syntaxComment = (s) => style.italic(rgb(0x5c, 0x63, 0x70, s));
|
|
162
|
+
/**
|
|
163
|
+
* Foreground style for the section's accent bar — the hue muted toward the
|
|
164
|
+
* panel tint so it reads as an accent, not a highlight.
|
|
165
|
+
*/
|
|
166
|
+
export function sectionFg(name, panel = DEFAULT_PANEL_BG) {
|
|
167
|
+
const color = mix(SECTION_HUES[name], panel, 0.25);
|
|
168
|
+
return (s) => rgb(color.r, color.g, color.b, s);
|
|
169
|
+
}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import type { Component, EditorTheme, RgbColor, SelectList, TUI, TuiMouseEvent, TuiMouseEventResult } from "@earendil-works/pi-tui";
|
|
2
|
+
import { Editor } from "@earendil-works/pi-tui";
|
|
3
|
+
import type { AgentMode } from "../agent/modes.js";
|
|
4
|
+
import type { ApprovalMode } from "../approval/policy.js";
|
|
5
|
+
import type { TodoStore } from "../agent/todo.js";
|
|
6
|
+
import type { GitFileChange, GitStatus } from "../git/status.js";
|
|
7
|
+
import type { AgentUsage } from "../protocol/types.js";
|
|
8
|
+
import type { ApprovalRequest } from "../tools/types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Messages submitted while a run is active, floating between the transcript
|
|
11
|
+
* and the prompt editor. A steered message is NOT part of the conversation
|
|
12
|
+
* until the server takes it — until then it stays here, one dim preview line
|
|
13
|
+
* per pending message, and is released (into the transcript) on acceptance
|
|
14
|
+
* or when a re-queued follow-up turn actually starts.
|
|
15
|
+
*/
|
|
16
|
+
export declare class QueuedMessagesComponent implements Component {
|
|
17
|
+
private entries;
|
|
18
|
+
invalidate(): void;
|
|
19
|
+
add(text: string): void;
|
|
20
|
+
/** Release the oldest entry with exactly this text (FIFO — steering the
|
|
21
|
+
* same text twice releases one float per acceptance). */
|
|
22
|
+
release(text: string): void;
|
|
23
|
+
render(width: number): string[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A submitted prompt: a leading blank row (margin from the previous message),
|
|
27
|
+
* a violet block bar down the left edge, and a content-sized tinted bubble
|
|
28
|
+
* (with one row of vertical padding) when the terminal background is known.
|
|
29
|
+
*/
|
|
30
|
+
export declare class UserMessageComponent implements Component {
|
|
31
|
+
private readonly text;
|
|
32
|
+
private readonly queued;
|
|
33
|
+
private readonly options;
|
|
34
|
+
constructor(text: string, queued: boolean, options?: {
|
|
35
|
+
bg?: () => RgbColor | undefined;
|
|
36
|
+
});
|
|
37
|
+
invalidate(): void;
|
|
38
|
+
render(width: number): string[];
|
|
39
|
+
}
|
|
40
|
+
export declare class AssistantMessageComponent implements Component {
|
|
41
|
+
private readonly md;
|
|
42
|
+
/** Raw stream (unsanitized) — the sanitizing pass needs the whole text. */
|
|
43
|
+
private raw;
|
|
44
|
+
private text;
|
|
45
|
+
constructor();
|
|
46
|
+
append(delta: string): void;
|
|
47
|
+
get content(): string;
|
|
48
|
+
render(width: number): string[];
|
|
49
|
+
invalidate(): void;
|
|
50
|
+
}
|
|
51
|
+
export declare class ReasoningBlockComponent implements Component {
|
|
52
|
+
private raw;
|
|
53
|
+
private text;
|
|
54
|
+
expanded: boolean;
|
|
55
|
+
append(delta: string): void;
|
|
56
|
+
toggle(): void;
|
|
57
|
+
get hasContent(): boolean;
|
|
58
|
+
invalidate(): void;
|
|
59
|
+
render(width: number): string[];
|
|
60
|
+
}
|
|
61
|
+
export declare class ToolCallComponent implements Component {
|
|
62
|
+
readonly name: string;
|
|
63
|
+
private readonly args;
|
|
64
|
+
status: "running" | "done" | "error";
|
|
65
|
+
expanded: boolean;
|
|
66
|
+
private output;
|
|
67
|
+
private bodyCache?;
|
|
68
|
+
constructor(name: string, args: Record<string, unknown>);
|
|
69
|
+
setResult(output: string, isError: boolean): void;
|
|
70
|
+
toggle(): void;
|
|
71
|
+
/** The whole row is the button: press is consumed, the release click toggles. */
|
|
72
|
+
handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
|
|
73
|
+
invalidate(): void;
|
|
74
|
+
/** Tool-specific expanded body, cached per width/result (renders on spinner ticks). */
|
|
75
|
+
private body;
|
|
76
|
+
render(width: number): string[];
|
|
77
|
+
}
|
|
78
|
+
export declare class NoticeComponent implements Component {
|
|
79
|
+
private readonly text;
|
|
80
|
+
private readonly level;
|
|
81
|
+
constructor(text: string, level: "info" | "error" | "warn");
|
|
82
|
+
invalidate(): void;
|
|
83
|
+
render(width: number): string[];
|
|
84
|
+
}
|
|
85
|
+
export interface SidebarState {
|
|
86
|
+
title: string | null;
|
|
87
|
+
usage: AgentUsage | null;
|
|
88
|
+
git: GitStatus;
|
|
89
|
+
}
|
|
90
|
+
/** A clickable row in the panel (content-space line index). */
|
|
91
|
+
export type SidebarTarget = {
|
|
92
|
+
type: "file";
|
|
93
|
+
file: GitFileChange;
|
|
94
|
+
} | {
|
|
95
|
+
type: "toggle-changes";
|
|
96
|
+
};
|
|
97
|
+
export interface SidebarOptions {
|
|
98
|
+
todos: TodoStore;
|
|
99
|
+
/**
|
|
100
|
+
* Viewport height of the enclosing ScrollView. Short content is padded to it
|
|
101
|
+
* so the panel background reaches the bottom of the column (never padded
|
|
102
|
+
* beyond it, which would break scrolling for long content).
|
|
103
|
+
*/
|
|
104
|
+
viewportHeight?: () => number;
|
|
105
|
+
/**
|
|
106
|
+
* Panel background, resolved asynchronously from the terminal's OSC 11
|
|
107
|
+
* reply. Until it exists (or when color is unavailable) no background is
|
|
108
|
+
* painted.
|
|
109
|
+
*/
|
|
110
|
+
panelBg?: () => RgbColor | undefined;
|
|
111
|
+
}
|
|
112
|
+
export declare class SidebarComponent implements Component {
|
|
113
|
+
state: SidebarState;
|
|
114
|
+
private readonly opts;
|
|
115
|
+
private expanded;
|
|
116
|
+
private readonly targets;
|
|
117
|
+
constructor(state: SidebarState, opts: SidebarOptions);
|
|
118
|
+
invalidate(): void;
|
|
119
|
+
toggleChanges(): void;
|
|
120
|
+
/** What a click at content line `y` hits (coordinates include scrollTop). */
|
|
121
|
+
targetAt(y: number): SidebarTarget | undefined;
|
|
122
|
+
render(width: number): string[];
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Editor wrapped in a rounded four-sided frame whose bottom edge carries the
|
|
126
|
+
* mode badge (bold, same color as the frame) followed by the model and
|
|
127
|
+
* thinking level. The content is inset by `paddingX`; the frame has no
|
|
128
|
+
* background of its own.
|
|
129
|
+
*/
|
|
130
|
+
/** Clickable status chips on the prompt frame's bottom edge. */
|
|
131
|
+
export type EditorChip = "mode" | "model" | "thinking";
|
|
132
|
+
export declare class PromptEditor extends Editor {
|
|
133
|
+
mode: AgentMode;
|
|
134
|
+
model: string | null;
|
|
135
|
+
thinking: string | undefined;
|
|
136
|
+
/** Fired when a bottom-edge chip (mode / model / thinking) is clicked. */
|
|
137
|
+
onChipClick?: (chip: EditorChip) => void;
|
|
138
|
+
/** Chip column extents from the last bottom-edge render, for hit-testing. */
|
|
139
|
+
private chipRanges;
|
|
140
|
+
/** Bottom-edge row in this component's coordinates (-1 = no bottom edge). */
|
|
141
|
+
private bottomBorderRow;
|
|
142
|
+
/**
|
|
143
|
+
* The exact bottom-edge line rendered this frame. render() locates the
|
|
144
|
+
* edge by identity against it — scanning for a "╰" substring would misfire
|
|
145
|
+
* on user content that happens to contain the border glyph.
|
|
146
|
+
*/
|
|
147
|
+
private lastBottomBorder;
|
|
148
|
+
constructor(tui: TUI, theme: EditorTheme, mode: AgentMode, thinking?: string);
|
|
149
|
+
protected renderTopBorder(width: number, _hiddenLineCount: number): string;
|
|
150
|
+
/**
|
|
151
|
+
* Alt+Enter inserts a newline exactly like Shift+Enter — the base editor
|
|
152
|
+
* only knows Shift+Enter/Ctrl+J, but terminals send Alt+Enter as ESC+CR
|
|
153
|
+
* (legacy) or a Kitty/modifyOtherKeys sequence.
|
|
154
|
+
*/
|
|
155
|
+
handleInput(data: string): void;
|
|
156
|
+
protected renderBottomBorder(width: number, hiddenLineCount: number): string;
|
|
157
|
+
/**
|
|
158
|
+
* Mouse dispatch for the framed editor. The bottom edge carries the
|
|
159
|
+
* mode/model/thinking chips; every other event is translated into the base
|
|
160
|
+
* editor's coordinate system — our frame inserts a padding row below the
|
|
161
|
+
* top edge and above the bottom edge, and the side borders shift text rows
|
|
162
|
+
* one column right, so without the shift the base's cursor/autocomplete
|
|
163
|
+
* hit-testing lands one row and one column off.
|
|
164
|
+
*/
|
|
165
|
+
handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
|
|
166
|
+
render(width: number): string[];
|
|
167
|
+
}
|
|
168
|
+
export interface FooterState {
|
|
169
|
+
approval: ApprovalMode;
|
|
170
|
+
workspace: string;
|
|
171
|
+
branch: string | null;
|
|
172
|
+
usage: AgentUsage | null;
|
|
173
|
+
runState: "idle" | "running" | "stopping";
|
|
174
|
+
spinnerFrame: number;
|
|
175
|
+
/** Set after the first idle Ctrl+C: the next one inside the window exits. */
|
|
176
|
+
pendingQuit?: boolean;
|
|
177
|
+
}
|
|
178
|
+
export declare class FooterComponent implements Component {
|
|
179
|
+
state: FooterState;
|
|
180
|
+
private readonly onApprovalClick?;
|
|
181
|
+
/** Fired when the ASK/AUTO badge is clicked. */
|
|
182
|
+
constructor(state: FooterState, onApprovalClick?: (() => void) | undefined);
|
|
183
|
+
invalidate(): void;
|
|
184
|
+
handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
|
|
185
|
+
render(width: number): string[];
|
|
186
|
+
private compactPath;
|
|
187
|
+
}
|
|
188
|
+
/** Chrome shared by the popup cards: background tint + bottom-edge hint. */
|
|
189
|
+
export interface PopupCardOptions {
|
|
190
|
+
/** Live background tint; undefined leaves the card unfilled. */
|
|
191
|
+
bg?: () => RgbColor | undefined;
|
|
192
|
+
/** Dim hint rendered in the bottom edge. */
|
|
193
|
+
hint?: string;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* A pending approval, floating between the transcript and the prompt (NOT a
|
|
197
|
+
* modal overlay — the editor keeps focus, so typing stays possible while the
|
|
198
|
+
* user decides). Answered with ctrl+y / ctrl+n from the app's global key
|
|
199
|
+
* listener; the card itself is render-only.
|
|
200
|
+
*/
|
|
201
|
+
export declare class ApprovalFloatComponent implements Component {
|
|
202
|
+
private request;
|
|
203
|
+
invalidate(): void;
|
|
204
|
+
/** Show (or clear) the approval being decided. */
|
|
205
|
+
set(request: ApprovalRequest | null): void;
|
|
206
|
+
render(width: number): string[];
|
|
207
|
+
}
|
|
208
|
+
export declare class InfoOverlay implements Component {
|
|
209
|
+
private readonly title;
|
|
210
|
+
private readonly body;
|
|
211
|
+
private readonly close;
|
|
212
|
+
private readonly options;
|
|
213
|
+
constructor(title: string, body: string[], close: () => void, options?: PopupCardOptions);
|
|
214
|
+
handleInput(data: string): void;
|
|
215
|
+
invalidate(): void;
|
|
216
|
+
render(width: number): string[];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Scrollable popup for a single file's unified diff. Overlays are clipped, not
|
|
220
|
+
* scrolled by the framework, so the window is managed here: the popup renders
|
|
221
|
+
* exactly `viewportHeight() + 2` lines (top edge, body, bottom edge) and moves the
|
|
222
|
+
* window with the arrow/page keys.
|
|
223
|
+
*/
|
|
224
|
+
export declare class DiffOverlay implements Component {
|
|
225
|
+
private readonly title;
|
|
226
|
+
private readonly options;
|
|
227
|
+
private scrollTop;
|
|
228
|
+
private mode;
|
|
229
|
+
private rowCount;
|
|
230
|
+
/** Content rows shown in the viewer (file headers and hunk headers hidden). */
|
|
231
|
+
private readonly visible;
|
|
232
|
+
private cache?;
|
|
233
|
+
constructor(title: string, diff: string, options: {
|
|
234
|
+
/** Live body-row budget, re-read every render so the card refits on resize. */
|
|
235
|
+
viewportHeight: () => number;
|
|
236
|
+
truncated: boolean;
|
|
237
|
+
close: () => void;
|
|
238
|
+
});
|
|
239
|
+
private viewHeight;
|
|
240
|
+
private get maxTop();
|
|
241
|
+
private scrollBy;
|
|
242
|
+
/** Paint one diff line, using the same palette as the transcript. */
|
|
243
|
+
private paint;
|
|
244
|
+
private buildRows;
|
|
245
|
+
private rows;
|
|
246
|
+
handleInput(data: string): void;
|
|
247
|
+
/** The mouse wheel scrolls the diff like the arrow keys do. */
|
|
248
|
+
handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
|
|
249
|
+
invalidate(): void;
|
|
250
|
+
render(width: number): string[];
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Select list inside a popup card, usable as a focused overlay: input and
|
|
254
|
+
* mouse events are forwarded to the inner SelectList (a bare Container would
|
|
255
|
+
* swallow them), with the card's top edge and padding row skipped in the
|
|
256
|
+
* mouse coordinates (renderCard: edge, blank, then list rows).
|
|
257
|
+
*/
|
|
258
|
+
export declare class SelectOverlay implements Component {
|
|
259
|
+
private readonly title;
|
|
260
|
+
private readonly list;
|
|
261
|
+
private readonly options;
|
|
262
|
+
constructor(title: string, list: SelectList, options?: PopupCardOptions);
|
|
263
|
+
handleInput(data: string): void;
|
|
264
|
+
handleMouse(event: TuiMouseEvent): TuiMouseEventResult | undefined;
|
|
265
|
+
invalidate(): void;
|
|
266
|
+
render(width: number): string[];
|
|
267
|
+
}
|