@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
package/dist/ui/logo.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// The original MyAgent block-letter logo, preserved verbatim, wrapped as a
|
|
3
|
+
// pi-tui component. The gradient shimmer runs once on launch (22 frames ×
|
|
4
|
+
// 38ms) and settles on the static gradient; non-TTY / NO_COLOR prints the
|
|
5
|
+
// plain art once.
|
|
6
|
+
// -------------------------------------------------------------------
|
|
7
|
+
import { truncateToWidth } from "@earendil-works/pi-tui";
|
|
8
|
+
import { isColorEnabled, rgb, style } from "./colors.js";
|
|
9
|
+
// Block-letter "MYAGENT" logo for the welcome screen (5 rows, 41 cols).
|
|
10
|
+
export const LOGO = [
|
|
11
|
+
"█ █ █ █ ███ ████ █████ █ █ █████",
|
|
12
|
+
"██ ██ █ █ █ █ █ █ ██ █ █ ",
|
|
13
|
+
"█ █ █ █ █████ █ ██ ████ █ █ █ █ ",
|
|
14
|
+
"█ █ █ █ █ █ █ █ █ ██ █ ",
|
|
15
|
+
"█ █ █ █ █ ████ █████ █ █ █ ",
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* Left inset shared by the art and the tagline — the component adds the
|
|
19
|
+
* transcript's 2-space margin, so the block starts at column 8 and the art
|
|
20
|
+
* lines up with the words below it.
|
|
21
|
+
*/
|
|
22
|
+
const LOGO_INSET = " ";
|
|
23
|
+
export const TAGLINE = `${LOGO_INSET}✦ your machine, in the hands of the agent ✦`;
|
|
24
|
+
// Gradient stops the logo sweeps through (cyan → indigo → violet → pink).
|
|
25
|
+
const GRADIENT = [
|
|
26
|
+
[0x22, 0xd3, 0xee],
|
|
27
|
+
[0x81, 0x8c, 0xf8],
|
|
28
|
+
[0xc0, 0x84, 0xfc],
|
|
29
|
+
[0xf4, 0x72, 0xb6],
|
|
30
|
+
];
|
|
31
|
+
function gradientAt(t) {
|
|
32
|
+
const clamped = Math.max(0, Math.min(1, t));
|
|
33
|
+
const span = GRADIENT.length - 1;
|
|
34
|
+
const x = clamped * span;
|
|
35
|
+
const i = Math.min(span - 1, Math.floor(x));
|
|
36
|
+
const f = x - i;
|
|
37
|
+
const a = GRADIENT[i];
|
|
38
|
+
const b = GRADIENT[i + 1];
|
|
39
|
+
const mix = (j) => Math.round(a[j] + (b[j] - a[j]) * f);
|
|
40
|
+
return [mix(0), mix(1), mix(2)];
|
|
41
|
+
}
|
|
42
|
+
/** Triangle wave, period 2, mapping any x → [0,1] — seamless shimmer. */
|
|
43
|
+
function triangle(x) {
|
|
44
|
+
const m = ((x % 2) + 2) % 2;
|
|
45
|
+
return m <= 1 ? m : 2 - m;
|
|
46
|
+
}
|
|
47
|
+
/** Paint the logo for a given gradient phase; returns the 5 colored rows. */
|
|
48
|
+
export function paintLogo(phase) {
|
|
49
|
+
const width = LOGO[0].length;
|
|
50
|
+
return LOGO.map((line, row) => {
|
|
51
|
+
let painted = "";
|
|
52
|
+
for (let col = 0; col < line.length; col++) {
|
|
53
|
+
const ch = line[col];
|
|
54
|
+
if (ch === " ") {
|
|
55
|
+
painted += " ";
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
const [r, g, b] = gradientAt(triangle((col + row * 2) / (width + 8) + phase));
|
|
59
|
+
painted += rgb(r, g, b, ch);
|
|
60
|
+
}
|
|
61
|
+
return painted;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Transcript component rendering the logo. `start()` kicks off the one-shot
|
|
66
|
+
* shimmer; the component stops animating after the final frame.
|
|
67
|
+
*/
|
|
68
|
+
export class LogoComponent {
|
|
69
|
+
options;
|
|
70
|
+
phase = 0;
|
|
71
|
+
timer = null;
|
|
72
|
+
frame = 0;
|
|
73
|
+
frames = 22;
|
|
74
|
+
constructor(options = { animate: true }) {
|
|
75
|
+
this.options = options;
|
|
76
|
+
}
|
|
77
|
+
start(tui) {
|
|
78
|
+
if (!this.options.animate || !isColorEnabled() || !process.stdout.isTTY)
|
|
79
|
+
return;
|
|
80
|
+
this.timer = setInterval(() => {
|
|
81
|
+
this.frame++;
|
|
82
|
+
this.phase = (this.frame / this.frames) * 2;
|
|
83
|
+
if (this.frame >= this.frames)
|
|
84
|
+
this.stop();
|
|
85
|
+
tui.requestRender();
|
|
86
|
+
}, 38);
|
|
87
|
+
this.timer.unref?.();
|
|
88
|
+
}
|
|
89
|
+
stop() {
|
|
90
|
+
if (this.timer) {
|
|
91
|
+
clearInterval(this.timer);
|
|
92
|
+
this.timer = null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
invalidate() { }
|
|
96
|
+
render(width) {
|
|
97
|
+
const lines = [""];
|
|
98
|
+
for (const line of paintLogo(this.phase)) {
|
|
99
|
+
lines.push(truncateToWidth(` ${LOGO_INSET}${line}`, width));
|
|
100
|
+
}
|
|
101
|
+
if (this.options.tagline !== false)
|
|
102
|
+
lines.push(truncateToWidth(style.dim(` ${TAGLINE}`), width));
|
|
103
|
+
lines.push("");
|
|
104
|
+
return lines;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { SelectItem } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { ModelInfo } from "../protocol/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* The id the picker marks as current: the model in use (a thread's model or a
|
|
5
|
+
* fresh selection), otherwise the user's pending selection, otherwise the
|
|
6
|
+
* server default (the entry flagged `default`, falling back to the first).
|
|
7
|
+
*/
|
|
8
|
+
export declare function currentModelId(models: ModelInfo[], activeModel: string | null, selectedModel: string | null): string | undefined;
|
|
9
|
+
/** Build the `/model` picker rows for a model list. */
|
|
10
|
+
export declare function buildModelItems(models: ModelInfo[], currentId: string | undefined): SelectItem[];
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Model picker helpers — turn GET /v1/models entries into `/model` rows.
|
|
3
|
+
//
|
|
4
|
+
// The picker marks the model in use as "current" and myagent's default as
|
|
5
|
+
// "default". Current wins when both apply, so the row the user is actually
|
|
6
|
+
// running carries exactly one marker.
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
/**
|
|
9
|
+
* The id the picker marks as current: the model in use (a thread's model or a
|
|
10
|
+
* fresh selection), otherwise the user's pending selection, otherwise the
|
|
11
|
+
* server default (the entry flagged `default`, falling back to the first).
|
|
12
|
+
*/
|
|
13
|
+
export function currentModelId(models, activeModel, selectedModel) {
|
|
14
|
+
if (activeModel)
|
|
15
|
+
return activeModel;
|
|
16
|
+
if (selectedModel)
|
|
17
|
+
return selectedModel;
|
|
18
|
+
return models.find((m) => m.default)?.id ?? models[0]?.id;
|
|
19
|
+
}
|
|
20
|
+
/** Build the `/model` picker rows for a model list. */
|
|
21
|
+
export function buildModelItems(models, currentId) {
|
|
22
|
+
// The server flags exactly one entry; older servers only order the list.
|
|
23
|
+
const hasDefaultFlag = models.some((m) => m.default === true);
|
|
24
|
+
return models.map((m, index) => {
|
|
25
|
+
const isCurrent = m.id === currentId;
|
|
26
|
+
const isDefault = m.default === true || (!hasDefaultFlag && index === 0);
|
|
27
|
+
return {
|
|
28
|
+
value: m.id,
|
|
29
|
+
label: m.label ? `${m.label} (${m.id})` : m.id,
|
|
30
|
+
description: isCurrent ? "current" : isDefault ? "default" : "",
|
|
31
|
+
};
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface QuitConfirm {
|
|
2
|
+
readonly armed: boolean;
|
|
3
|
+
/** Arm, or extend the window when already armed. */
|
|
4
|
+
arm(): void;
|
|
5
|
+
/** Clear the pending confirmation (expired window, quit, or a new run). */
|
|
6
|
+
disarm(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function createQuitConfirm(onChange: (armed: boolean) => void, windowMs?: number): QuitConfirm;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// Two-press quit gate for idle Ctrl+C.
|
|
3
|
+
//
|
|
4
|
+
// The first idle Ctrl+C arms the gate (the caller shows the hint), a second
|
|
5
|
+
// press inside the window quits, and expiry disarms it back to idle.
|
|
6
|
+
// -------------------------------------------------------------------
|
|
7
|
+
/** How long the second Ctrl+C stays valid. */
|
|
8
|
+
const QUIT_CONFIRM_MS = 2000;
|
|
9
|
+
export function createQuitConfirm(onChange, windowMs = QUIT_CONFIRM_MS) {
|
|
10
|
+
let timer = null;
|
|
11
|
+
let armed = false;
|
|
12
|
+
const set = (next) => {
|
|
13
|
+
if (armed === next)
|
|
14
|
+
return;
|
|
15
|
+
armed = next;
|
|
16
|
+
onChange(armed);
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
get armed() {
|
|
20
|
+
return armed;
|
|
21
|
+
},
|
|
22
|
+
arm() {
|
|
23
|
+
if (timer)
|
|
24
|
+
clearTimeout(timer);
|
|
25
|
+
set(true);
|
|
26
|
+
timer = setTimeout(() => {
|
|
27
|
+
timer = null;
|
|
28
|
+
set(false);
|
|
29
|
+
}, windowMs);
|
|
30
|
+
timer.unref?.();
|
|
31
|
+
},
|
|
32
|
+
disarm() {
|
|
33
|
+
if (timer) {
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
timer = null;
|
|
36
|
+
}
|
|
37
|
+
set(false);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type SelectList } from "@earendil-works/pi-tui";
|
|
2
|
+
/** Width ceiling so long session descriptions never span an ultrawide terminal. */
|
|
3
|
+
export declare const MAX_SELECT_CARD_WIDTH = 96;
|
|
4
|
+
/** Columns added around the measured content: borders (2), padding (2), slack (2). */
|
|
5
|
+
export declare const SELECT_CARD_CHROME = 6;
|
|
6
|
+
/**
|
|
7
|
+
* Rows the list may render inside a card on a `termHeight`-row terminal —
|
|
8
|
+
* leaves room for the two card edges, the top/bottom padding rows and a
|
|
9
|
+
* possible scroll indicator row.
|
|
10
|
+
*/
|
|
11
|
+
export declare function selectVisibleRows(termHeight: number, requested?: number): number;
|
|
12
|
+
/** Widest label column SelectList should use, clamped to a readable range. */
|
|
13
|
+
export declare function selectLabelColumn(items: readonly {
|
|
14
|
+
label: string;
|
|
15
|
+
}[]): number;
|
|
16
|
+
/**
|
|
17
|
+
* Card width floor that keeps SelectList from silently dropping one-line
|
|
18
|
+
* descriptions: its inner width must clear the label column plus a 10-char
|
|
19
|
+
* description minimum and a 4-column safety gap, and the card adds 4 chrome
|
|
20
|
+
* columns — `labelColumn + 19`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function selectDescriptionMinWidth(labelColumn: number): number;
|
|
23
|
+
/**
|
|
24
|
+
* Content-adaptive card width. `minWidth` should come from
|
|
25
|
+
* {@link selectDescriptionMinWidth} whenever the list has descriptions.
|
|
26
|
+
*/
|
|
27
|
+
export declare function selectCardWidth(title: string, list: SelectList, options: {
|
|
28
|
+
termWidth: number;
|
|
29
|
+
minWidth?: number;
|
|
30
|
+
}): number;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// Popup geometry for the select overlays.
|
|
3
|
+
//
|
|
4
|
+
// pi-tui resolves an overlay's width from the options passed to showOverlay,
|
|
5
|
+
// so the card cannot resize itself at render time. The list is dry-rendered at
|
|
6
|
+
// a wide probe width to measure its intrinsic line widths, and the card is
|
|
7
|
+
// sized from that measurement, clamped to the terminal and a readability
|
|
8
|
+
// ceiling.
|
|
9
|
+
// -------------------------------------------------------------------
|
|
10
|
+
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
11
|
+
/** Width ceiling so long session descriptions never span an ultrawide terminal. */
|
|
12
|
+
export const MAX_SELECT_CARD_WIDTH = 96;
|
|
13
|
+
/** Columns added around the measured content: borders (2), padding (2), slack (2). */
|
|
14
|
+
export const SELECT_CARD_CHROME = 6;
|
|
15
|
+
/** Narrowest unfilled card. */
|
|
16
|
+
const SELECT_CARD_MIN_WIDTH = 30;
|
|
17
|
+
/** Widest probe passed to a dry render when measuring content. */
|
|
18
|
+
const MAX_PROBE_WIDTH = 160;
|
|
19
|
+
/** Fraction of the terminal height a select popup may occupy. */
|
|
20
|
+
const POPUP_HEIGHT_RATIO = 0.6;
|
|
21
|
+
/**
|
|
22
|
+
* Rows the list may render inside a card on a `termHeight`-row terminal —
|
|
23
|
+
* leaves room for the two card edges, the top/bottom padding rows and a
|
|
24
|
+
* possible scroll indicator row.
|
|
25
|
+
*/
|
|
26
|
+
export function selectVisibleRows(termHeight, requested = 12) {
|
|
27
|
+
return Math.max(3, Math.min(requested, Math.floor(termHeight * POPUP_HEIGHT_RATIO) - 5));
|
|
28
|
+
}
|
|
29
|
+
/** Widest label column SelectList should use, clamped to a readable range. */
|
|
30
|
+
export function selectLabelColumn(items) {
|
|
31
|
+
const widest = items.reduce((max, item) => Math.max(max, visibleWidth(item.label)), 0);
|
|
32
|
+
return Math.max(6, Math.min(40, widest + 2));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Card width floor that keeps SelectList from silently dropping one-line
|
|
36
|
+
* descriptions: its inner width must clear the label column plus a 10-char
|
|
37
|
+
* description minimum and a 4-column safety gap, and the card adds 4 chrome
|
|
38
|
+
* columns — `labelColumn + 19`.
|
|
39
|
+
*/
|
|
40
|
+
export function selectDescriptionMinWidth(labelColumn) {
|
|
41
|
+
return labelColumn + 19;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Content-adaptive card width. `minWidth` should come from
|
|
45
|
+
* {@link selectDescriptionMinWidth} whenever the list has descriptions.
|
|
46
|
+
*/
|
|
47
|
+
export function selectCardWidth(title, list, options) {
|
|
48
|
+
const termWidth = Math.max(12, options.termWidth);
|
|
49
|
+
const probeWidth = Math.max(1, Math.min(termWidth - 4, MAX_PROBE_WIDTH));
|
|
50
|
+
const lines = list.render(probeWidth);
|
|
51
|
+
const contentWidth = lines.reduce((widest, line) => Math.max(widest, visibleWidth(line)), visibleWidth(title) + 5);
|
|
52
|
+
const width = Math.max(contentWidth + SELECT_CARD_CHROME, options.minWidth ?? SELECT_CARD_MIN_WIDTH);
|
|
53
|
+
return Math.max(8, Math.min(width, MAX_SELECT_CARD_WIDTH, termWidth - 2));
|
|
54
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { EditorTheme, MarkdownTheme, SelectListTheme } from "@earendil-works/pi-tui";
|
|
2
|
+
export declare const markdownTheme: MarkdownTheme;
|
|
3
|
+
export declare const selectListTheme: SelectListTheme;
|
|
4
|
+
export declare function editorTheme(borderColor: (s: string) => string): EditorTheme;
|
package/dist/ui/theme.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// -------------------------------------------------------------------
|
|
2
|
+
// pi-tui themes: markdown, select lists, editor border.
|
|
3
|
+
// -------------------------------------------------------------------
|
|
4
|
+
import { headingColor, style } from "./colors.js";
|
|
5
|
+
import { highlightCodeBlock } from "./highlight.js";
|
|
6
|
+
export const markdownTheme = {
|
|
7
|
+
// Bright light-blue + bold so headings read as headings, not bold prose
|
|
8
|
+
// (h1 is additionally underlined by pi-tui; h2+ render bare — the color
|
|
9
|
+
// is the only level cue left once the "###" prefixes are stripped).
|
|
10
|
+
heading: (t) => style.bold(headingColor(t)),
|
|
11
|
+
link: (t) => style.underline(style.cyan(t)),
|
|
12
|
+
linkUrl: (t) => style.dim(t),
|
|
13
|
+
code: (t) => style.yellow(t),
|
|
14
|
+
codeBlock: (t) => t,
|
|
15
|
+
codeBlockBorder: (t) => style.dim(t),
|
|
16
|
+
// Pinned: AssistantMessageComponent swaps this 2-cell indent for the code
|
|
17
|
+
// bar, so its slice(2) must match whatever lands here.
|
|
18
|
+
codeBlockIndent: " ",
|
|
19
|
+
highlightCode: (code, language) => highlightCodeBlock(code, language),
|
|
20
|
+
quote: (t) => style.italic(t),
|
|
21
|
+
quoteBorder: (t) => style.dim(t),
|
|
22
|
+
hr: (t) => style.dim(t),
|
|
23
|
+
// Unordered items read as a dot rather than a hyphen flush with prose. The
|
|
24
|
+
// replacement must stay width-preserving: pi-tui pads wrapped continuation
|
|
25
|
+
// lines with the ORIGINAL marker's width, so a wider prefix misaligns them.
|
|
26
|
+
listBullet: (marker) => style.cyan(marker.replace(/^- /, "• ")),
|
|
27
|
+
bold: (t) => style.bold(t),
|
|
28
|
+
italic: (t) => style.italic(t),
|
|
29
|
+
strikethrough: (t) => style.dim(t),
|
|
30
|
+
underline: (t) => style.underline(t),
|
|
31
|
+
};
|
|
32
|
+
export const selectListTheme = {
|
|
33
|
+
selectedPrefix: (t) => style.cyan(t),
|
|
34
|
+
selectedText: (t) => style.bold(style.cyan(t)),
|
|
35
|
+
description: (t) => style.dim(t),
|
|
36
|
+
scrollInfo: (t) => style.dim(t),
|
|
37
|
+
noMatch: (t) => style.dim(t),
|
|
38
|
+
};
|
|
39
|
+
export function editorTheme(borderColor) {
|
|
40
|
+
return { borderColor, selectList: selectListTheme };
|
|
41
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Bash output lines kept in the expanded body (older lines collapse). */
|
|
2
|
+
export declare const SHELL_TAIL_LINES = 30;
|
|
3
|
+
/** Parse tool arguments whether they arrived as a JSON string or an object. */
|
|
4
|
+
export declare function parseToolArgs(raw: unknown): Record<string, unknown>;
|
|
5
|
+
/** `local_read` → `read`, `load_local_skill` → `load_skill`. */
|
|
6
|
+
export declare function displayToolName(name: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* One-line argument summary shown after the tool name — important parameters
|
|
9
|
+
* only, never raw JSON. Tools without a curated summary fall back to a single
|
|
10
|
+
* parameter shown inline; a call with several parameters shows no summary.
|
|
11
|
+
*
|
|
12
|
+
* The result is sanitized: the summary is always visible (collapsed header)
|
|
13
|
+
* and its values come from model-generated arguments.
|
|
14
|
+
*/
|
|
15
|
+
export declare function toolSummary(name: string, args: Record<string, unknown>): string;
|
|
16
|
+
/**
|
|
17
|
+
* Expanded body lines for a tool call, rendered for the available `width`
|
|
18
|
+
* (pair diffs use it for their columns). Callers add the transcript indent.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toolBody(name: string, args: Record<string, unknown>, output: string, isError: boolean, width: number): string[];
|