atom-lite 0.0.0-stage → 0.4.1
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 +72 -0
- package/LICENSE +21 -0
- package/README.md +313 -2
- package/dist/agent/loop.d.ts +32 -0
- package/dist/agent/loop.js +204 -0
- package/dist/agent/loop.js.map +1 -0
- package/dist/agent/types.d.ts +85 -0
- package/dist/agent/types.js +2 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/activity.d.ts +45 -0
- package/dist/cli/activity.js +141 -0
- package/dist/cli/activity.js.map +1 -0
- package/dist/cli/app.d.ts +1 -0
- package/dist/cli/app.js +1576 -0
- package/dist/cli/app.js.map +1 -0
- package/dist/cli/approval-prompt.d.ts +24 -0
- package/dist/cli/approval-prompt.js +82 -0
- package/dist/cli/approval-prompt.js.map +1 -0
- package/dist/cli/approvals.d.ts +1 -0
- package/dist/cli/approvals.js +2 -0
- package/dist/cli/approvals.js.map +1 -0
- package/dist/cli/banner.d.ts +12 -0
- package/dist/cli/banner.js +35 -0
- package/dist/cli/banner.js.map +1 -0
- package/dist/cli/commands.d.ts +94 -0
- package/dist/cli/commands.js +324 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/diff.d.ts +1 -0
- package/dist/cli/diff.js +28 -0
- package/dist/cli/diff.js.map +1 -0
- package/dist/cli/input.d.ts +2 -0
- package/dist/cli/input.js +10 -0
- package/dist/cli/input.js.map +1 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +22 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/mouse.d.ts +54 -0
- package/dist/cli/mouse.js +83 -0
- package/dist/cli/mouse.js.map +1 -0
- package/dist/cli/palette.d.ts +41 -0
- package/dist/cli/palette.js +212 -0
- package/dist/cli/palette.js.map +1 -0
- package/dist/cli/panel.d.ts +29 -0
- package/dist/cli/panel.js +48 -0
- package/dist/cli/panel.js.map +1 -0
- package/dist/cli/picker.d.ts +34 -0
- package/dist/cli/picker.js +173 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/renderer.d.ts +1 -0
- package/dist/cli/renderer.js +5 -0
- package/dist/cli/renderer.js.map +1 -0
- package/dist/cli/secret-input.d.ts +21 -0
- package/dist/cli/secret-input.js +101 -0
- package/dist/cli/secret-input.js.map +1 -0
- package/dist/cli/status-line.d.ts +24 -0
- package/dist/cli/status-line.js +49 -0
- package/dist/cli/status-line.js.map +1 -0
- package/dist/cli/stream-text.d.ts +18 -0
- package/dist/cli/stream-text.js +63 -0
- package/dist/cli/stream-text.js.map +1 -0
- package/dist/cli/theme.d.ts +48 -0
- package/dist/cli/theme.js +158 -0
- package/dist/cli/theme.js.map +1 -0
- package/dist/cli/tool-box.d.ts +41 -0
- package/dist/cli/tool-box.js +177 -0
- package/dist/cli/tool-box.js.map +1 -0
- package/dist/cli/transcript.d.ts +26 -0
- package/dist/cli/transcript.js +64 -0
- package/dist/cli/transcript.js.map +1 -0
- package/dist/config/credentials.d.ts +26 -0
- package/dist/config/credentials.js +79 -0
- package/dist/config/credentials.js.map +1 -0
- package/dist/config/defaults.d.ts +34 -0
- package/dist/config/defaults.js +35 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/load.d.ts +9 -0
- package/dist/config/load.js +137 -0
- package/dist/config/load.js.map +1 -0
- package/dist/config/paths.d.ts +4 -0
- package/dist/config/paths.js +14 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/schema.d.ts +132 -0
- package/dist/config/schema.js +83 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/write.d.ts +20 -0
- package/dist/config/write.js +70 -0
- package/dist/config/write.js.map +1 -0
- package/dist/context/budget.d.ts +2 -0
- package/dist/context/budget.js +13 -0
- package/dist/context/budget.js.map +1 -0
- package/dist/context/builder.d.ts +7 -0
- package/dist/context/builder.js +11 -0
- package/dist/context/builder.js.map +1 -0
- package/dist/context/compaction.d.ts +1 -0
- package/dist/context/compaction.js +5 -0
- package/dist/context/compaction.js.map +1 -0
- package/dist/context/instructions.d.ts +3 -0
- package/dist/context/instructions.js +30 -0
- package/dist/context/instructions.js.map +1 -0
- package/dist/context/manager.d.ts +29 -0
- package/dist/context/manager.js +122 -0
- package/dist/context/manager.js.map +1 -0
- package/dist/extensions/api.d.ts +51 -0
- package/dist/extensions/api.js +101 -0
- package/dist/extensions/api.js.map +1 -0
- package/dist/extensions/discovery.d.ts +26 -0
- package/dist/extensions/discovery.js +243 -0
- package/dist/extensions/discovery.js.map +1 -0
- package/dist/extensions/loader.d.ts +27 -0
- package/dist/extensions/loader.js +113 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/trust.d.ts +4 -0
- package/dist/extensions/trust.js +40 -0
- package/dist/extensions/trust.js.map +1 -0
- package/dist/extensions/types.d.ts +52 -0
- package/dist/extensions/types.js +2 -0
- package/dist/extensions/types.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +73 -0
- package/dist/mcp/client.js +363 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/format.d.ts +3 -0
- package/dist/mcp/format.js +37 -0
- package/dist/mcp/format.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +7 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +53 -0
- package/dist/mcp/manager.js +349 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/stdio-transport.d.ts +26 -0
- package/dist/mcp/stdio-transport.js +191 -0
- package/dist/mcp/stdio-transport.js.map +1 -0
- package/dist/mcp/tools.d.ts +22 -0
- package/dist/mcp/tools.js +162 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/types.d.ts +92 -0
- package/dist/mcp/types.js +2 -0
- package/dist/mcp/types.js.map +1 -0
- package/dist/providers/catalog.d.ts +60 -0
- package/dist/providers/catalog.js +289 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/context-window.d.ts +11 -0
- package/dist/providers/context-window.js +87 -0
- package/dist/providers/context-window.js.map +1 -0
- package/dist/providers/factory.d.ts +2 -0
- package/dist/providers/factory.js +55 -0
- package/dist/providers/factory.js.map +1 -0
- package/dist/providers/fake.d.ts +14 -0
- package/dist/providers/fake.js +23 -0
- package/dist/providers/fake.js.map +1 -0
- package/dist/providers/gemini.d.ts +24 -0
- package/dist/providers/gemini.js +228 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +4 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/ollama.d.ts +64 -0
- package/dist/providers/ollama.js +433 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +27 -0
- package/dist/providers/openai-compatible.js +282 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/providers/registry.d.ts +7 -0
- package/dist/providers/registry.js +13 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/tool-calls.d.ts +18 -0
- package/dist/providers/tool-calls.js +42 -0
- package/dist/providers/tool-calls.js.map +1 -0
- package/dist/providers/types.d.ts +16 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/runtime/approvals.d.ts +20 -0
- package/dist/runtime/approvals.js +20 -0
- package/dist/runtime/approvals.js.map +1 -0
- package/dist/runtime/executor.d.ts +2 -0
- package/dist/runtime/executor.js +4 -0
- package/dist/runtime/executor.js.map +1 -0
- package/dist/runtime/locks.d.ts +13 -0
- package/dist/runtime/locks.js +180 -0
- package/dist/runtime/locks.js.map +1 -0
- package/dist/runtime/scheduler.d.ts +7 -0
- package/dist/runtime/scheduler.js +110 -0
- package/dist/runtime/scheduler.js.map +1 -0
- package/dist/security/paths.d.ts +1 -0
- package/dist/security/paths.js +35 -0
- package/dist/security/paths.js.map +1 -0
- package/dist/security/process.d.ts +1 -0
- package/dist/security/process.js +8 -0
- package/dist/security/process.js.map +1 -0
- package/dist/security/redaction.d.ts +1 -0
- package/dist/security/redaction.js +4 -0
- package/dist/security/redaction.js.map +1 -0
- package/dist/sessions/events.d.ts +30 -0
- package/dist/sessions/events.js +92 -0
- package/dist/sessions/events.js.map +1 -0
- package/dist/sessions/history.d.ts +18 -0
- package/dist/sessions/history.js +76 -0
- package/dist/sessions/history.js.map +1 -0
- package/dist/sessions/index.d.ts +5 -0
- package/dist/sessions/index.js +6 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/recovery.d.ts +6 -0
- package/dist/sessions/recovery.js +35 -0
- package/dist/sessions/recovery.js.map +1 -0
- package/dist/sessions/search.d.ts +16 -0
- package/dist/sessions/search.js +136 -0
- package/dist/sessions/search.js.map +1 -0
- package/dist/sessions/store.d.ts +91 -0
- package/dist/sessions/store.js +360 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/skills/registry.d.ts +23 -0
- package/dist/skills/registry.js +129 -0
- package/dist/skills/registry.js.map +1 -0
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.js +159 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/diff.d.ts +7 -0
- package/dist/tools/diff.js +40 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.js +118 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +8 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/read.d.ts +2 -0
- package/dist/tools/read.js +138 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/registry.d.ts +7 -0
- package/dist/tools/registry.js +13 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +27 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/tools/webfetch.d.ts +2 -0
- package/dist/tools/webfetch.js +97 -0
- package/dist/tools/webfetch.js.map +1 -0
- package/dist/tools/websearch.d.ts +2 -0
- package/dist/tools/websearch.js +88 -0
- package/dist/tools/websearch.js.map +1 -0
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.js +91 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/types.d.ts +84 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +74 -4
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { Container, decodeKittyPrintable, fuzzyFilter, isKeyRelease, isKeyRepeat, Key, matchesKey, Text, } from "@earendil-works/pi-tui";
|
|
2
|
+
import { extractPaste } from "./input.js";
|
|
3
|
+
import { darkTheme } from "./theme.js";
|
|
4
|
+
/** Fuzzy-filter palette items on label, description, category and keywords. */
|
|
5
|
+
export function filterPaletteItems(items, query) {
|
|
6
|
+
const q = query.trim();
|
|
7
|
+
if (!q)
|
|
8
|
+
return items;
|
|
9
|
+
return fuzzyFilter(items, q, (item) => [
|
|
10
|
+
item.label,
|
|
11
|
+
item.description ?? "",
|
|
12
|
+
item.category,
|
|
13
|
+
...(item.keywords ?? []),
|
|
14
|
+
].join(" "));
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Group items by category, keeping the category order of first appearance.
|
|
18
|
+
* Filtering happens first, so groups only contain matching items.
|
|
19
|
+
*/
|
|
20
|
+
export function groupPaletteItems(items) {
|
|
21
|
+
const groups = new Map();
|
|
22
|
+
for (const item of items) {
|
|
23
|
+
const list = groups.get(item.category) ?? [];
|
|
24
|
+
list.push(item);
|
|
25
|
+
groups.set(item.category, list);
|
|
26
|
+
}
|
|
27
|
+
return [...groups].map(([category, grouped]) => ({
|
|
28
|
+
category,
|
|
29
|
+
items: grouped,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
function flatten(groups) {
|
|
33
|
+
return groups.flatMap((group) => group.items);
|
|
34
|
+
}
|
|
35
|
+
/** Open the ctrl+p command palette overlay. */
|
|
36
|
+
export function openCommandPalette(options) {
|
|
37
|
+
const { tui, container, items: initialItems, maxVisible = 12, title = "Command palette", onCancel, onSelect, onError, restoreFocus, } = options;
|
|
38
|
+
let allItems = initialItems;
|
|
39
|
+
let query = "";
|
|
40
|
+
let closed = false;
|
|
41
|
+
let selectedId;
|
|
42
|
+
let flat = [];
|
|
43
|
+
const theme = options.theme ?? darkTheme;
|
|
44
|
+
const wrapper = new Container();
|
|
45
|
+
const titleText = new Text(theme.tokens.accent(title));
|
|
46
|
+
const filterText = new Text("");
|
|
47
|
+
const listText = new Text("");
|
|
48
|
+
wrapper.addChild(titleText);
|
|
49
|
+
wrapper.addChild(filterText);
|
|
50
|
+
wrapper.addChild(listText);
|
|
51
|
+
container.addChild(wrapper);
|
|
52
|
+
function renderFilter() {
|
|
53
|
+
filterText.setText(query
|
|
54
|
+
? `${theme.tokens.dim("search:")} ${query}${theme.tokens.accent("▏")}`
|
|
55
|
+
: theme.tokens.dim("type to search…"));
|
|
56
|
+
}
|
|
57
|
+
function renderList() {
|
|
58
|
+
const filtered = filterPaletteItems(allItems, query);
|
|
59
|
+
const groups = groupPaletteItems(filtered);
|
|
60
|
+
flat = flatten(groups);
|
|
61
|
+
if (flat.length === 0) {
|
|
62
|
+
selectedId = undefined;
|
|
63
|
+
listText.setText(theme.tokens.dim(" no commands match"));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (!selectedId || !flat.some((item) => item.id === selectedId)) {
|
|
67
|
+
selectedId = flat[0].id;
|
|
68
|
+
}
|
|
69
|
+
const selectedIndex = Math.max(0, flat.findIndex((item) => item.id === selectedId));
|
|
70
|
+
const windowSize = Math.max(1, maxVisible);
|
|
71
|
+
const start = Math.min(Math.max(0, selectedIndex - Math.floor(windowSize / 2)), Math.max(0, flat.length - windowSize));
|
|
72
|
+
const end = start + windowSize;
|
|
73
|
+
const lines = [];
|
|
74
|
+
for (const group of groups) {
|
|
75
|
+
const visible = group.items.filter((item) => {
|
|
76
|
+
const index = flat.indexOf(item);
|
|
77
|
+
return index >= start && index < end;
|
|
78
|
+
});
|
|
79
|
+
if (visible.length === 0)
|
|
80
|
+
continue;
|
|
81
|
+
lines.push(theme.tokens.dim(`── ${group.category} ──`));
|
|
82
|
+
for (const item of visible) {
|
|
83
|
+
const selected = item.id === selectedId;
|
|
84
|
+
const hint = item.description
|
|
85
|
+
? theme.tokens.dim(` ${item.description}`)
|
|
86
|
+
: "";
|
|
87
|
+
const label = `${selected ? "▸ " : " "}${item.label}`;
|
|
88
|
+
lines.push(selected ? theme.tokens.selection(label) + hint : label + hint);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (flat.length > windowSize) {
|
|
92
|
+
lines.push(theme.tokens.dim(` ${selectedIndex + 1}/${flat.length} · ↑/↓ to move · Esc to cancel`));
|
|
93
|
+
}
|
|
94
|
+
listText.setText(lines.join("\n"));
|
|
95
|
+
}
|
|
96
|
+
function rebuild() {
|
|
97
|
+
renderFilter();
|
|
98
|
+
renderList();
|
|
99
|
+
tui.requestRender();
|
|
100
|
+
}
|
|
101
|
+
function move(delta) {
|
|
102
|
+
if (flat.length === 0)
|
|
103
|
+
return;
|
|
104
|
+
const current = Math.max(0, flat.findIndex((item) => item.id === selectedId));
|
|
105
|
+
const next = Math.min(flat.length - 1, Math.max(0, current + delta));
|
|
106
|
+
selectedId = flat[next].id;
|
|
107
|
+
renderList();
|
|
108
|
+
tui.requestRender();
|
|
109
|
+
}
|
|
110
|
+
function onKey(data) {
|
|
111
|
+
if (closed)
|
|
112
|
+
return { consume: true };
|
|
113
|
+
if (isKeyRelease(data))
|
|
114
|
+
return { consume: true };
|
|
115
|
+
if (matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.escape)) {
|
|
116
|
+
close();
|
|
117
|
+
onCancel?.();
|
|
118
|
+
return { consume: true };
|
|
119
|
+
}
|
|
120
|
+
// ctrl+p toggles the palette closed, matching the key that opened it.
|
|
121
|
+
if (matchesKey(data, Key.ctrl("p")) && !isKeyRepeat(data)) {
|
|
122
|
+
close();
|
|
123
|
+
onCancel?.();
|
|
124
|
+
return { consume: true };
|
|
125
|
+
}
|
|
126
|
+
if (matchesKey(data, Key.enter)) {
|
|
127
|
+
const item = flat.find((entry) => entry.id === selectedId);
|
|
128
|
+
if (item)
|
|
129
|
+
void run(item);
|
|
130
|
+
return { consume: true };
|
|
131
|
+
}
|
|
132
|
+
if (matchesKey(data, Key.up)) {
|
|
133
|
+
move(-1);
|
|
134
|
+
return { consume: true };
|
|
135
|
+
}
|
|
136
|
+
if (matchesKey(data, Key.down)) {
|
|
137
|
+
move(1);
|
|
138
|
+
return { consume: true };
|
|
139
|
+
}
|
|
140
|
+
if (matchesKey(data, Key.pageUp)) {
|
|
141
|
+
move(-10);
|
|
142
|
+
return { consume: true };
|
|
143
|
+
}
|
|
144
|
+
if (matchesKey(data, Key.pageDown)) {
|
|
145
|
+
move(10);
|
|
146
|
+
return { consume: true };
|
|
147
|
+
}
|
|
148
|
+
if (matchesKey(data, Key.backspace)) {
|
|
149
|
+
query = query.slice(0, -1);
|
|
150
|
+
rebuild();
|
|
151
|
+
return { consume: true };
|
|
152
|
+
}
|
|
153
|
+
if (matchesKey(data, Key.ctrl("u"))) {
|
|
154
|
+
query = "";
|
|
155
|
+
rebuild();
|
|
156
|
+
return { consume: true };
|
|
157
|
+
}
|
|
158
|
+
const paste = extractPaste(data);
|
|
159
|
+
if (paste !== null) {
|
|
160
|
+
query += paste;
|
|
161
|
+
rebuild();
|
|
162
|
+
return { consume: true };
|
|
163
|
+
}
|
|
164
|
+
const kittyChar = decodeKittyPrintable(data);
|
|
165
|
+
if (kittyChar !== undefined) {
|
|
166
|
+
query += kittyChar;
|
|
167
|
+
rebuild();
|
|
168
|
+
return { consume: true };
|
|
169
|
+
}
|
|
170
|
+
if (/^[\x20-\x7e]+$/.test(data)) {
|
|
171
|
+
query += data;
|
|
172
|
+
rebuild();
|
|
173
|
+
return { consume: true };
|
|
174
|
+
}
|
|
175
|
+
return { consume: true };
|
|
176
|
+
}
|
|
177
|
+
async function run(item) {
|
|
178
|
+
close();
|
|
179
|
+
onSelect?.(item);
|
|
180
|
+
try {
|
|
181
|
+
await item.action();
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
onError?.(error);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const removeListener = tui.addInputListener(onKey);
|
|
188
|
+
function close() {
|
|
189
|
+
if (closed)
|
|
190
|
+
return;
|
|
191
|
+
closed = true;
|
|
192
|
+
removeListener();
|
|
193
|
+
container.removeChild(wrapper);
|
|
194
|
+
wrapper.clear();
|
|
195
|
+
restoreFocus?.();
|
|
196
|
+
tui.requestRender();
|
|
197
|
+
}
|
|
198
|
+
rebuild();
|
|
199
|
+
return {
|
|
200
|
+
updateItems(next) {
|
|
201
|
+
if (closed)
|
|
202
|
+
return;
|
|
203
|
+
allItems = next;
|
|
204
|
+
rebuild();
|
|
205
|
+
},
|
|
206
|
+
close,
|
|
207
|
+
get isOpen() {
|
|
208
|
+
return !closed;
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=palette.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"palette.js","sourceRoot":"","sources":["../../src/cli/palette.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** Shared ANSI helpers for the small hand-drawn panels in the TUI. */
|
|
2
|
+
export declare const RESET = "\u001B[0m";
|
|
3
|
+
export declare const BOLD = "\u001B[1m";
|
|
4
|
+
export declare const DIM = "\u001B[2m";
|
|
5
|
+
export declare const RED = "\u001B[31m";
|
|
6
|
+
export declare const GREEN = "\u001B[32m";
|
|
7
|
+
export declare const YELLOW = "\u001B[33m";
|
|
8
|
+
export declare const BLUE = "\u001B[34m";
|
|
9
|
+
export declare const MAGENTA = "\u001B[35m";
|
|
10
|
+
export declare const CYAN = "\u001B[36m";
|
|
11
|
+
export declare const GRAY = "\u001B[90m";
|
|
12
|
+
export type Color = (text: string) => string;
|
|
13
|
+
export declare const dim: Color;
|
|
14
|
+
export declare const bold: Color;
|
|
15
|
+
export declare const red: Color;
|
|
16
|
+
export declare const green: Color;
|
|
17
|
+
export declare const yellow: Color;
|
|
18
|
+
export declare const blue: Color;
|
|
19
|
+
export declare const magenta: Color;
|
|
20
|
+
export declare const cyan: Color;
|
|
21
|
+
export declare const gray: Color;
|
|
22
|
+
/** Draw the top edge of a panel, embedding a title in the border. */
|
|
23
|
+
export declare function panelTop(label: string, width: number, color: Color): string;
|
|
24
|
+
/** Draw the bottom edge of a panel. */
|
|
25
|
+
export declare function panelBottom(width: number, color: Color): string;
|
|
26
|
+
/** Draw one body row, padding it to the panel's inner width. */
|
|
27
|
+
export declare function panelRow(content: string, width: number, color: Color): string;
|
|
28
|
+
/** Wrap plain or ANSI-styled text for a panel's inner width. */
|
|
29
|
+
export declare function wrapPanelText(text: string, width: number): string[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@earendil-works/pi-tui";
|
|
2
|
+
/** Shared ANSI helpers for the small hand-drawn panels in the TUI. */
|
|
3
|
+
export const RESET = "\x1b[0m";
|
|
4
|
+
export const BOLD = "\x1b[1m";
|
|
5
|
+
export const DIM = "\x1b[2m";
|
|
6
|
+
export const RED = "\x1b[31m";
|
|
7
|
+
export const GREEN = "\x1b[32m";
|
|
8
|
+
export const YELLOW = "\x1b[33m";
|
|
9
|
+
export const BLUE = "\x1b[34m";
|
|
10
|
+
export const MAGENTA = "\x1b[35m";
|
|
11
|
+
export const CYAN = "\x1b[36m";
|
|
12
|
+
export const GRAY = "\x1b[90m";
|
|
13
|
+
export const dim = (text) => `${DIM}${text}${RESET}`;
|
|
14
|
+
export const bold = (text) => `${BOLD}${text}${RESET}`;
|
|
15
|
+
export const red = (text) => `${RED}${text}${RESET}`;
|
|
16
|
+
export const green = (text) => `${GREEN}${text}${RESET}`;
|
|
17
|
+
export const yellow = (text) => `${YELLOW}${text}${RESET}`;
|
|
18
|
+
export const blue = (text) => `${BLUE}${text}${RESET}`;
|
|
19
|
+
export const magenta = (text) => `${MAGENTA}${text}${RESET}`;
|
|
20
|
+
export const cyan = (text) => `${CYAN}${text}${RESET}`;
|
|
21
|
+
export const gray = (text) => `${GRAY}${text}${RESET}`;
|
|
22
|
+
/** Draw the top edge of a panel, embedding a title in the border. */
|
|
23
|
+
export function panelTop(label, width, color) {
|
|
24
|
+
const inner = Math.max(0, Math.floor(width) - 2);
|
|
25
|
+
const title = truncateToWidth(` ${label} `, inner, "…");
|
|
26
|
+
const fill = Math.max(0, inner - visibleWidth(title));
|
|
27
|
+
return color(`╭${title}${"─".repeat(fill)}╮`);
|
|
28
|
+
}
|
|
29
|
+
/** Draw the bottom edge of a panel. */
|
|
30
|
+
export function panelBottom(width, color) {
|
|
31
|
+
const inner = Math.max(0, Math.floor(width) - 2);
|
|
32
|
+
return color(`╰${"─".repeat(inner)}╯`);
|
|
33
|
+
}
|
|
34
|
+
/** Draw one body row, padding it to the panel's inner width. */
|
|
35
|
+
export function panelRow(content, width, color) {
|
|
36
|
+
const inner = Math.max(0, Math.floor(width) - 2);
|
|
37
|
+
const text = truncateToWidth(content, inner, "…", true);
|
|
38
|
+
return `${color("│")}${text}${color("│")}`;
|
|
39
|
+
}
|
|
40
|
+
/** Wrap plain or ANSI-styled text for a panel's inner width. */
|
|
41
|
+
export function wrapPanelText(text, width) {
|
|
42
|
+
const inner = Math.max(1, Math.floor(width) - 2);
|
|
43
|
+
return text
|
|
44
|
+
.replace(/\t/g, " ")
|
|
45
|
+
.split("\n")
|
|
46
|
+
.flatMap((line) => line.length === 0 ? [""] : wrapTextWithAnsi(line, inner));
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../../src/cli/panel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type Theme } from "./theme.js";
|
|
2
|
+
export interface PickerItem {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface SearchablePickerOptions {
|
|
8
|
+
tui: any;
|
|
9
|
+
container: any;
|
|
10
|
+
title: string;
|
|
11
|
+
items: PickerItem[];
|
|
12
|
+
maxVisible?: number;
|
|
13
|
+
initialQuery?: string;
|
|
14
|
+
/** Value to highlight when the picker opens. */
|
|
15
|
+
initialValue?: string;
|
|
16
|
+
onSelect: (item: PickerItem) => void;
|
|
17
|
+
onCancel: () => void;
|
|
18
|
+
/** Close before onSelect (default true). Set false for toggle items. */
|
|
19
|
+
closeOnSelect?: boolean;
|
|
20
|
+
/** Called as the highlighted item changes, for live previews. */
|
|
21
|
+
onPreview?: (item: PickerItem) => void;
|
|
22
|
+
restoreFocus?: () => void;
|
|
23
|
+
theme?: Theme;
|
|
24
|
+
}
|
|
25
|
+
export interface SearchablePicker {
|
|
26
|
+
/** Replace the full item set (e.g. after live model discovery). */
|
|
27
|
+
updateItems(items: PickerItem[]): void;
|
|
28
|
+
/** Update the dim status line under the title. */
|
|
29
|
+
setStatus(status: string): void;
|
|
30
|
+
close(): void;
|
|
31
|
+
}
|
|
32
|
+
/** Fuzzy-filter picker items on label, description and value. */
|
|
33
|
+
export declare function filterPickerItems(items: PickerItem[], query: string): PickerItem[];
|
|
34
|
+
export declare function openSearchablePicker(options: SearchablePickerOptions): SearchablePicker;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { Container, decodeKittyPrintable, fuzzyFilter, isKeyRelease, Key, matchesKey, SelectList, Text, } from "@earendil-works/pi-tui";
|
|
2
|
+
import { extractPaste } from "./input.js";
|
|
3
|
+
import { darkTheme } from "./theme.js";
|
|
4
|
+
/** Fuzzy-filter picker items on label, description and value. */
|
|
5
|
+
export function filterPickerItems(items, query) {
|
|
6
|
+
const q = query.trim();
|
|
7
|
+
if (!q)
|
|
8
|
+
return items;
|
|
9
|
+
return fuzzyFilter(items, q, (item) => `${item.label} ${item.description ?? ""} ${item.value}`);
|
|
10
|
+
}
|
|
11
|
+
export function openSearchablePicker(options) {
|
|
12
|
+
const { tui, container, title, items: initialItems, maxVisible = 15, initialQuery = "", initialValue, onSelect, onCancel, onPreview, restoreFocus, } = options;
|
|
13
|
+
const closeOnSelect = options.closeOnSelect ?? true;
|
|
14
|
+
const theme = options.theme ?? darkTheme;
|
|
15
|
+
const selectListTheme = {
|
|
16
|
+
selectedPrefix: (s) => theme.tokens.accent(s),
|
|
17
|
+
selectedText: (s) => theme.tokens.selection(s),
|
|
18
|
+
description: (s) => theme.tokens.dim(s),
|
|
19
|
+
scrollInfo: (s) => theme.tokens.dim(s),
|
|
20
|
+
noMatch: (s) => theme.tokens.dim(s),
|
|
21
|
+
};
|
|
22
|
+
let allItems = initialItems;
|
|
23
|
+
let query = initialQuery;
|
|
24
|
+
let closed = false;
|
|
25
|
+
let selectedValue = initialValue;
|
|
26
|
+
const wrapper = new Container();
|
|
27
|
+
const titleText = new Text(theme.tokens.accent(title));
|
|
28
|
+
const filterText = new Text("");
|
|
29
|
+
const statusText = new Text("");
|
|
30
|
+
const listHost = new Container();
|
|
31
|
+
wrapper.addChild(titleText);
|
|
32
|
+
wrapper.addChild(filterText);
|
|
33
|
+
wrapper.addChild(listHost);
|
|
34
|
+
wrapper.addChild(statusText);
|
|
35
|
+
container.addChild(wrapper);
|
|
36
|
+
let list = null;
|
|
37
|
+
function renderFilter() {
|
|
38
|
+
filterText.setText(query
|
|
39
|
+
? `${theme.tokens.dim("search:")} ${query}${theme.tokens.accent("▏")}`
|
|
40
|
+
: theme.tokens.dim("type to search…"));
|
|
41
|
+
}
|
|
42
|
+
function rebuild() {
|
|
43
|
+
const filtered = filterPickerItems(allItems, query);
|
|
44
|
+
listHost.clear();
|
|
45
|
+
if (filtered.length === 0) {
|
|
46
|
+
list = null;
|
|
47
|
+
listHost.addChild(new Text(theme.tokens.dim(` no models match “${query}”`)));
|
|
48
|
+
renderFilter();
|
|
49
|
+
tui.requestRender();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
list = new SelectList(filtered, Math.max(1, Math.min(maxVisible, filtered.length)), selectListTheme, { minPrimaryColumnWidth: 20, maxPrimaryColumnWidth: 56 });
|
|
53
|
+
const idx = selectedValue
|
|
54
|
+
? filtered.findIndex((i) => i.value === selectedValue)
|
|
55
|
+
: 0;
|
|
56
|
+
if (idx > 0)
|
|
57
|
+
list.setSelectedIndex(idx);
|
|
58
|
+
list.onSelect = (item) => {
|
|
59
|
+
selectedValue = item.value;
|
|
60
|
+
if (closeOnSelect)
|
|
61
|
+
close();
|
|
62
|
+
onSelect(item);
|
|
63
|
+
};
|
|
64
|
+
list.onCancel = () => {
|
|
65
|
+
close();
|
|
66
|
+
onCancel();
|
|
67
|
+
};
|
|
68
|
+
if (onPreview) {
|
|
69
|
+
list.onSelectionChange = (item) => onPreview(item);
|
|
70
|
+
}
|
|
71
|
+
listHost.addChild(list);
|
|
72
|
+
renderFilter();
|
|
73
|
+
tui.requestRender();
|
|
74
|
+
}
|
|
75
|
+
function onKey(data) {
|
|
76
|
+
if (closed)
|
|
77
|
+
return { consume: true };
|
|
78
|
+
// Kitty reports key releases (and, with some terminals, repeats). Releases
|
|
79
|
+
// must never trigger an action, or every keystroke fires twice.
|
|
80
|
+
if (isKeyRelease(data))
|
|
81
|
+
return { consume: true };
|
|
82
|
+
if (matchesKey(data, Key.ctrl("c")) || matchesKey(data, Key.escape)) {
|
|
83
|
+
close();
|
|
84
|
+
onCancel();
|
|
85
|
+
return { consume: true };
|
|
86
|
+
}
|
|
87
|
+
if (matchesKey(data, Key.enter)) {
|
|
88
|
+
const item = list?.getSelectedItem?.();
|
|
89
|
+
if (item) {
|
|
90
|
+
selectedValue = item.value;
|
|
91
|
+
if (closeOnSelect)
|
|
92
|
+
close();
|
|
93
|
+
onSelect(item);
|
|
94
|
+
}
|
|
95
|
+
return { consume: true };
|
|
96
|
+
}
|
|
97
|
+
if (matchesKey(data, Key.backspace)) {
|
|
98
|
+
query = query.slice(0, -1);
|
|
99
|
+
rebuild();
|
|
100
|
+
return { consume: true };
|
|
101
|
+
}
|
|
102
|
+
if (matchesKey(data, Key.ctrl("u"))) {
|
|
103
|
+
query = "";
|
|
104
|
+
rebuild();
|
|
105
|
+
return { consume: true };
|
|
106
|
+
}
|
|
107
|
+
// Navigation keys are delegated to SelectList, which understands both
|
|
108
|
+
// legacy sequences and Kitty CSI-u / event-type encodings.
|
|
109
|
+
if (matchesKey(data, Key.up) ||
|
|
110
|
+
matchesKey(data, Key.down) ||
|
|
111
|
+
matchesKey(data, Key.pageUp) ||
|
|
112
|
+
matchesKey(data, Key.pageDown)) {
|
|
113
|
+
const before = list?.getSelectedItem?.()?.value;
|
|
114
|
+
list?.handleInput?.(data);
|
|
115
|
+
const after = list?.getSelectedItem?.()?.value;
|
|
116
|
+
if (before !== after)
|
|
117
|
+
selectedValue = after;
|
|
118
|
+
tui.requestRender();
|
|
119
|
+
return { consume: true };
|
|
120
|
+
}
|
|
121
|
+
const paste = extractPaste(data);
|
|
122
|
+
if (paste !== null) {
|
|
123
|
+
query += paste;
|
|
124
|
+
rebuild();
|
|
125
|
+
return { consume: true };
|
|
126
|
+
}
|
|
127
|
+
// Kitty flag 1 sends printable keys as CSI-u sequences; decode those
|
|
128
|
+
// before falling back to plain printable text and pastes.
|
|
129
|
+
const kittyChar = decodeKittyPrintable(data);
|
|
130
|
+
if (kittyChar !== undefined) {
|
|
131
|
+
query += kittyChar;
|
|
132
|
+
rebuild();
|
|
133
|
+
return { consume: true };
|
|
134
|
+
}
|
|
135
|
+
if (/^[\x20-\x7e]+$/.test(data)) {
|
|
136
|
+
query += data;
|
|
137
|
+
rebuild();
|
|
138
|
+
return { consume: true };
|
|
139
|
+
}
|
|
140
|
+
return { consume: true };
|
|
141
|
+
}
|
|
142
|
+
const removeListener = tui.addInputListener(onKey);
|
|
143
|
+
function close() {
|
|
144
|
+
if (closed)
|
|
145
|
+
return;
|
|
146
|
+
closed = true;
|
|
147
|
+
removeListener();
|
|
148
|
+
container.removeChild(wrapper);
|
|
149
|
+
wrapper.clear();
|
|
150
|
+
restoreFocus?.();
|
|
151
|
+
tui.requestRender();
|
|
152
|
+
}
|
|
153
|
+
renderFilter();
|
|
154
|
+
rebuild();
|
|
155
|
+
return {
|
|
156
|
+
updateItems(next) {
|
|
157
|
+
if (closed)
|
|
158
|
+
return;
|
|
159
|
+
allItems = next;
|
|
160
|
+
// Keep the highlighted item stable across a live model refresh.
|
|
161
|
+
selectedValue = list?.getSelectedItem?.()?.value ?? selectedValue;
|
|
162
|
+
rebuild();
|
|
163
|
+
},
|
|
164
|
+
setStatus(status) {
|
|
165
|
+
if (closed)
|
|
166
|
+
return;
|
|
167
|
+
statusText.setText(status ? theme.tokens.dim(status) : "");
|
|
168
|
+
tui.requestRender();
|
|
169
|
+
},
|
|
170
|
+
close,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
//# sourceMappingURL=picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"picker.js","sourceRoot":"","sources":["../../src/cli/picker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function print(text: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/cli/renderer.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,MAAM,UAAU,KAAK,CAAC,IAAY;IAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Component, type Focusable } from "@earendil-works/pi-tui";
|
|
2
|
+
/**
|
|
3
|
+
* Single-line input that never echoes its value. Used for API keys so secrets
|
|
4
|
+
* do not land in terminal scrollback or TUI transcripts.
|
|
5
|
+
*/
|
|
6
|
+
export declare class SecretInput implements Component, Focusable {
|
|
7
|
+
private readonly label;
|
|
8
|
+
private readonly placeholder;
|
|
9
|
+
focused: boolean;
|
|
10
|
+
private value;
|
|
11
|
+
private pasteBuffer;
|
|
12
|
+
onSubmit?: (value: string) => void;
|
|
13
|
+
onCancel?: () => void;
|
|
14
|
+
constructor(label?: string, placeholder?: string);
|
|
15
|
+
getValue(): string;
|
|
16
|
+
setValue(value: string): void;
|
|
17
|
+
reset(): void;
|
|
18
|
+
invalidate(): void;
|
|
19
|
+
handleInput(data: string): void;
|
|
20
|
+
render(width: number): string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { CURSOR_MARKER, decodeKittyPrintable, isKeyRelease, Key, matchesKey, } from "@earendil-works/pi-tui";
|
|
2
|
+
const RESET = "\x1b[0m";
|
|
3
|
+
const DIM = "\x1b[2m";
|
|
4
|
+
const CYAN = "\x1b[36m";
|
|
5
|
+
/**
|
|
6
|
+
* Single-line input that never echoes its value. Used for API keys so secrets
|
|
7
|
+
* do not land in terminal scrollback or TUI transcripts.
|
|
8
|
+
*/
|
|
9
|
+
export class SecretInput {
|
|
10
|
+
label;
|
|
11
|
+
placeholder;
|
|
12
|
+
focused = false;
|
|
13
|
+
value = "";
|
|
14
|
+
pasteBuffer = null;
|
|
15
|
+
onSubmit;
|
|
16
|
+
onCancel;
|
|
17
|
+
constructor(label = "API key", placeholder = "paste key (input hidden)") {
|
|
18
|
+
this.label = label;
|
|
19
|
+
this.placeholder = placeholder;
|
|
20
|
+
}
|
|
21
|
+
getValue() {
|
|
22
|
+
return this.value;
|
|
23
|
+
}
|
|
24
|
+
setValue(value) {
|
|
25
|
+
this.value = value;
|
|
26
|
+
}
|
|
27
|
+
reset() {
|
|
28
|
+
this.value = "";
|
|
29
|
+
this.pasteBuffer = null;
|
|
30
|
+
}
|
|
31
|
+
invalidate() {
|
|
32
|
+
// No cached render state.
|
|
33
|
+
}
|
|
34
|
+
handleInput(data) {
|
|
35
|
+
if (this.pasteBuffer !== null) {
|
|
36
|
+
const end = data.indexOf("\x1b[201~");
|
|
37
|
+
if (end === -1) {
|
|
38
|
+
this.pasteBuffer += data;
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.pasteBuffer += data.slice(0, end);
|
|
42
|
+
this.value += this.pasteBuffer.replace(/[\x00-\x1f]/g, "");
|
|
43
|
+
this.pasteBuffer = null;
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const pasteStart = data.indexOf("\x1b[200~");
|
|
47
|
+
if (pasteStart !== -1) {
|
|
48
|
+
const after = data.slice(pasteStart + 6);
|
|
49
|
+
const end = after.indexOf("\x1b[201~");
|
|
50
|
+
if (end === -1) {
|
|
51
|
+
this.pasteBuffer = after;
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
this.value += after.slice(0, end).replace(/[\x00-\x1f]/g, "");
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (isKeyRelease(data))
|
|
59
|
+
return;
|
|
60
|
+
if (matchesKey(data, Key.enter)) {
|
|
61
|
+
this.onSubmit?.(this.value.trim());
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (matchesKey(data, Key.escape) || matchesKey(data, Key.ctrl("c"))) {
|
|
65
|
+
this.onCancel?.();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (matchesKey(data, Key.ctrl("u"))) {
|
|
69
|
+
this.value = "";
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (matchesKey(data, Key.ctrl("w"))) {
|
|
73
|
+
this.value = this.value.replace(/\s*\S+\s*$/, "");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (matchesKey(data, Key.backspace)) {
|
|
77
|
+
this.value = this.value.slice(0, -1);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
// Kitty flag 1 sends printable keys as CSI-u sequences.
|
|
81
|
+
const kittyChar = decodeKittyPrintable(data);
|
|
82
|
+
if (kittyChar !== undefined) {
|
|
83
|
+
this.value += kittyChar;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
// Drop escape sequences (arrow keys, kitty key events) and control chars.
|
|
87
|
+
const cleaned = data
|
|
88
|
+
.replace(/\x1b\[[0-9;:?]*[A-Za-z~]/g, "")
|
|
89
|
+
.replace(/\x1bO[A-Za-z]/g, "")
|
|
90
|
+
.replace(/[\x00-\x1f\x7f]/g, "");
|
|
91
|
+
if (cleaned)
|
|
92
|
+
this.value += cleaned;
|
|
93
|
+
}
|
|
94
|
+
render(width) {
|
|
95
|
+
const masked = "•".repeat(Math.min(this.value.length, Math.max(0, width - 20)));
|
|
96
|
+
const shown = this.value ? masked : `${DIM}${this.placeholder}${RESET}`;
|
|
97
|
+
const marker = this.focused ? CURSOR_MARKER : "";
|
|
98
|
+
return [` ${CYAN}${this.label}:${RESET} ${shown}${marker}`];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=secret-input.js.map
|