zerg-ztc 0.1.3 → 0.1.5
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/dist/App.d.ts.map +1 -1
- package/dist/App.js +183 -19
- package/dist/App.js.map +1 -1
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +3 -1
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/commands/config.d.ts.map +1 -1
- package/dist/agent/commands/config.js +68 -2
- package/dist/agent/commands/config.js.map +1 -1
- package/dist/agent/commands/index.d.ts.map +1 -1
- package/dist/agent/commands/index.js +4 -1
- package/dist/agent/commands/index.js.map +1 -1
- package/dist/agent/commands/input_mode.d.ts +3 -0
- package/dist/agent/commands/input_mode.d.ts.map +1 -0
- package/dist/agent/commands/input_mode.js +21 -0
- package/dist/agent/commands/input_mode.js.map +1 -0
- package/dist/agent/commands/keybindings.d.ts +3 -0
- package/dist/agent/commands/keybindings.d.ts.map +1 -0
- package/dist/agent/commands/keybindings.js +38 -0
- package/dist/agent/commands/keybindings.js.map +1 -0
- package/dist/agent/commands/types.d.ts +2 -0
- package/dist/agent/commands/types.d.ts.map +1 -1
- package/dist/agent/commands/update.d.ts +3 -0
- package/dist/agent/commands/update.d.ts.map +1 -0
- package/dist/agent/commands/update.js +33 -0
- package/dist/agent/commands/update.js.map +1 -0
- package/dist/cli.js +68 -16
- package/dist/cli.js.map +1 -1
- package/dist/components/ActivityLine.d.ts +11 -0
- package/dist/components/ActivityLine.d.ts.map +1 -0
- package/dist/components/ActivityLine.js +9 -0
- package/dist/components/ActivityLine.js.map +1 -0
- package/dist/components/FullScreen.d.ts +1 -0
- package/dist/components/FullScreen.d.ts.map +1 -1
- package/dist/components/FullScreen.js +30 -30
- package/dist/components/FullScreen.js.map +1 -1
- package/dist/components/InputArea.d.ts.map +1 -1
- package/dist/components/InputArea.js +476 -19
- package/dist/components/InputArea.js.map +1 -1
- package/dist/components/MessageList.d.ts +2 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js +41 -2
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/SingleMessage.d.ts +9 -0
- package/dist/components/SingleMessage.d.ts.map +1 -0
- package/dist/components/SingleMessage.js +27 -0
- package/dist/components/SingleMessage.js.map +1 -0
- package/dist/components/StatusBar.d.ts +2 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +3 -1
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/config/types.d.ts +1 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -0
- package/dist/config.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/core/input_segments.d.ts +1 -0
- package/dist/ui/core/input_segments.d.ts.map +1 -1
- package/dist/ui/core/input_segments.js +46 -14
- package/dist/ui/core/input_segments.js.map +1 -1
- package/dist/ui/core/types.d.ts +1 -0
- package/dist/ui/core/types.d.ts.map +1 -1
- package/dist/ui/ink/render.d.ts +3 -1
- package/dist/ui/ink/render.d.ts.map +1 -1
- package/dist/ui/ink/render.js +7 -5
- package/dist/ui/ink/render.js.map +1 -1
- package/dist/ui/views/activity_line.d.ts +11 -0
- package/dist/ui/views/activity_line.d.ts.map +1 -0
- package/dist/ui/views/activity_line.js +20 -0
- package/dist/ui/views/activity_line.js.map +1 -0
- package/dist/ui/views/app.d.ts +5 -1
- package/dist/ui/views/app.d.ts.map +1 -1
- package/dist/ui/views/app.js +18 -14
- package/dist/ui/views/app.js.map +1 -1
- package/dist/ui/views/header.d.ts.map +1 -1
- package/dist/ui/views/header.js +7 -5
- package/dist/ui/views/header.js.map +1 -1
- package/dist/ui/views/input_area.d.ts.map +1 -1
- package/dist/ui/views/input_area.js +25 -12
- package/dist/ui/views/input_area.js.map +1 -1
- package/dist/ui/views/message_list.d.ts +3 -2
- package/dist/ui/views/message_list.d.ts.map +1 -1
- package/dist/ui/views/message_list.js +33 -19
- package/dist/ui/views/message_list.js.map +1 -1
- package/dist/ui/views/status_bar.d.ts +3 -1
- package/dist/ui/views/status_bar.d.ts.map +1 -1
- package/dist/ui/views/status_bar.js +8 -2
- package/dist/ui/views/status_bar.js.map +1 -1
- package/dist/utils/spinner_frames.d.ts +2 -0
- package/dist/utils/spinner_frames.d.ts.map +1 -0
- package/dist/utils/spinner_frames.js +2 -0
- package/dist/utils/spinner_frames.js.map +1 -0
- package/dist/utils/spinner_verbs.d.ts +4 -0
- package/dist/utils/spinner_verbs.d.ts.map +1 -0
- package/dist/utils/spinner_verbs.js +22 -0
- package/dist/utils/spinner_verbs.js.map +1 -0
- package/dist/utils/tool_trace.d.ts.map +1 -1
- package/dist/utils/tool_trace.js +12 -2
- package/dist/utils/tool_trace.js.map +1 -1
- package/dist/utils/update.d.ts +9 -0
- package/dist/utils/update.d.ts.map +1 -0
- package/dist/utils/update.js +37 -0
- package/dist/utils/update.js.map +1 -0
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +16 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +1 -1
- package/src/App.tsx +226 -32
- package/src/agent/agent.ts +3 -1
- package/src/agent/commands/config.ts +76 -2
- package/src/agent/commands/index.ts +6 -0
- package/src/agent/commands/input_mode.ts +22 -0
- package/src/agent/commands/keybindings.ts +40 -0
- package/src/agent/commands/types.ts +2 -0
- package/src/agent/commands/update.ts +32 -0
- package/src/cli.tsx +77 -15
- package/src/components/ActivityLine.tsx +23 -0
- package/src/components/FullScreen.tsx +41 -35
- package/src/components/InputArea.tsx +489 -19
- package/src/components/MessageList.tsx +52 -6
- package/src/components/SingleMessage.tsx +59 -0
- package/src/components/StatusBar.tsx +6 -0
- package/src/components/index.tsx +3 -1
- package/src/config/types.ts +1 -0
- package/src/config.ts +8 -0
- package/src/types.ts +1 -0
- package/src/ui/core/input_segments.ts +49 -14
- package/src/ui/core/types.ts +1 -0
- package/src/ui/ink/render.tsx +16 -5
- package/src/ui/views/activity_line.ts +33 -0
- package/src/ui/views/app.ts +25 -13
- package/src/ui/views/header.ts +7 -5
- package/src/ui/views/input_area.ts +28 -17
- package/src/ui/views/message_list.ts +36 -20
- package/src/ui/views/status_bar.ts +11 -1
- package/src/utils/spinner_frames.ts +1 -0
- package/src/utils/spinner_verbs.ts +23 -0
- package/src/utils/tool_trace.ts +12 -2
- package/src/utils/update.ts +44 -0
- package/src/utils/version.ts +15 -0
|
@@ -278,7 +278,17 @@ function renderTable(lines: string[]): LayoutNode[] {
|
|
|
278
278
|
|
|
279
279
|
function renderMarkdownLines(lines: string[]): LayoutNode[] {
|
|
280
280
|
const normalized: string[] = [];
|
|
281
|
+
let inCodeBlock = false;
|
|
281
282
|
lines.forEach(line => {
|
|
283
|
+
if (line.trim().startsWith('```')) {
|
|
284
|
+
inCodeBlock = !inCodeBlock;
|
|
285
|
+
normalized.push(line);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (inCodeBlock) {
|
|
289
|
+
normalized.push(line);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
282
292
|
if (line.includes('||') && line.includes('|')) {
|
|
283
293
|
const segments = line.split('||').map(segment => segment.trim()).filter(Boolean);
|
|
284
294
|
segments.forEach(segment => {
|
|
@@ -288,6 +298,7 @@ function renderMarkdownLines(lines: string[]): LayoutNode[] {
|
|
|
288
298
|
normalized.push(out);
|
|
289
299
|
});
|
|
290
300
|
} else {
|
|
301
|
+
// Preserve the original line - don't collapse whitespace as it breaks formatting
|
|
291
302
|
normalized.push(line);
|
|
292
303
|
}
|
|
293
304
|
});
|
|
@@ -373,10 +384,11 @@ function clipMessage(message: Message, available: number): Message | null {
|
|
|
373
384
|
|
|
374
385
|
interface MessageListProps {
|
|
375
386
|
messages: Message[];
|
|
376
|
-
height
|
|
387
|
+
height?: number;
|
|
377
388
|
maxMessages?: number;
|
|
378
389
|
debug?: boolean;
|
|
379
390
|
expandToolOutputs?: boolean;
|
|
391
|
+
scrollback?: boolean;
|
|
380
392
|
}
|
|
381
393
|
|
|
382
394
|
export function buildMessageListView({
|
|
@@ -384,30 +396,34 @@ export function buildMessageListView({
|
|
|
384
396
|
height,
|
|
385
397
|
maxMessages = 50,
|
|
386
398
|
debug = false,
|
|
387
|
-
expandToolOutputs = false
|
|
399
|
+
expandToolOutputs = false,
|
|
400
|
+
scrollback = false
|
|
388
401
|
}: MessageListProps): LayoutNode {
|
|
389
402
|
const recentMessages = messages.slice(-maxMessages);
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
remaining
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
const clipped = clipMessage(msg, remaining);
|
|
402
|
-
if (clipped) {
|
|
403
|
-
visibleMessages.unshift(clipped);
|
|
403
|
+
let visibleMessages: Message[] = recentMessages;
|
|
404
|
+
if (!scrollback && typeof height === 'number') {
|
|
405
|
+
visibleMessages = [];
|
|
406
|
+
let remaining = height;
|
|
407
|
+
for (let i = recentMessages.length - 1; i >= 0; i -= 1) {
|
|
408
|
+
const msg = recentMessages[i];
|
|
409
|
+
const estimate = estimateMessageLines(msg);
|
|
410
|
+
if (estimate <= remaining) {
|
|
411
|
+
visibleMessages.unshift(msg);
|
|
412
|
+
remaining -= estimate;
|
|
413
|
+
continue;
|
|
404
414
|
}
|
|
415
|
+
if (visibleMessages.length === 0) {
|
|
416
|
+
const clipped = clipMessage(msg, remaining);
|
|
417
|
+
if (clipped) {
|
|
418
|
+
visibleMessages.unshift(clipped);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
break;
|
|
405
422
|
}
|
|
406
|
-
break;
|
|
407
423
|
}
|
|
408
424
|
|
|
409
425
|
return box([
|
|
410
|
-
box([], { flexGrow: 1 }),
|
|
426
|
+
!scrollback ? box([], { flexGrow: 1 }) : box([], {}),
|
|
411
427
|
box(visibleMessages.map(msg => messageView(msg, expandToolOutputs)), { flexDirection: 'column' }),
|
|
412
428
|
messages.length === 0
|
|
413
429
|
? box([text('No messages yet. Type something to begin.', { color: 'gray', dimColor: true })], {
|
|
@@ -418,9 +434,9 @@ export function buildMessageListView({
|
|
|
418
434
|
: box([], {})
|
|
419
435
|
], {
|
|
420
436
|
flexDirection: 'column',
|
|
421
|
-
height,
|
|
437
|
+
height: scrollback ? undefined : height,
|
|
422
438
|
paddingX: 1,
|
|
423
|
-
flexGrow: 1,
|
|
439
|
+
flexGrow: scrollback ? undefined : 1,
|
|
424
440
|
borderStyle: debug ? 'single' : undefined,
|
|
425
441
|
borderColor: debug ? 'gray' : undefined
|
|
426
442
|
});
|
|
@@ -11,7 +11,9 @@ interface StatusBarProps {
|
|
|
11
11
|
provider?: string;
|
|
12
12
|
model?: string;
|
|
13
13
|
emulationId?: string;
|
|
14
|
+
inputMode?: 'queue' | 'interrupt';
|
|
14
15
|
toast?: string | null;
|
|
16
|
+
spinnerLabel?: string | null;
|
|
15
17
|
debug?: boolean;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -36,11 +38,15 @@ export function buildStatusBarView({
|
|
|
36
38
|
provider,
|
|
37
39
|
model,
|
|
38
40
|
emulationId,
|
|
41
|
+
inputMode,
|
|
39
42
|
toast,
|
|
43
|
+
spinnerLabel,
|
|
40
44
|
debug = false
|
|
41
45
|
}: StatusBarProps): LayoutNode {
|
|
42
46
|
const config = getStatusConfig(state);
|
|
43
47
|
const isActive = state.status !== 'idle' && state.status !== 'error';
|
|
48
|
+
const useSpinnerLabel = spinnerLabel && (state.status === 'thinking' || state.status === 'streaming');
|
|
49
|
+
const label = useSpinnerLabel ? spinnerLabel : config.label;
|
|
44
50
|
|
|
45
51
|
const connectionColors = {
|
|
46
52
|
connected: 'green',
|
|
@@ -62,7 +68,7 @@ export function buildStatusBarView({
|
|
|
62
68
|
return box([
|
|
63
69
|
box([
|
|
64
70
|
text(isActive ? '⠋ ' : `${config.icon} `, { color: config.color }),
|
|
65
|
-
text(
|
|
71
|
+
text(label, { color: config.color }),
|
|
66
72
|
state.error ? text(` - ${state.error}`, { color: 'red' }) : text('', {}),
|
|
67
73
|
toastLabel ? text(' • ', { color: 'gray', dimColor: true }) : text('', {}),
|
|
68
74
|
toastLabel ? text(toastLabel, { color: 'yellow' }) : text('', {})
|
|
@@ -78,6 +84,8 @@ export function buildStatusBarView({
|
|
|
78
84
|
(provider || model) ? text(' • ', { color: 'gray', dimColor: true }) : text('', {}),
|
|
79
85
|
emulationId ? text(`emu:${emulationId}`, { color: 'gray', dimColor: true }) : text('', {}),
|
|
80
86
|
emulationId ? text(' • ', { color: 'gray', dimColor: true }) : text('', {}),
|
|
87
|
+
inputMode ? text(`mode:${inputMode}`, { color: 'gray', dimColor: true }) : text('', {}),
|
|
88
|
+
inputMode ? text(' • ', { color: 'gray', dimColor: true }) : text('', {}),
|
|
81
89
|
state.tokensUsed !== undefined && state.tokensUsed > 0
|
|
82
90
|
? text(`${state.tokensUsed.toLocaleString()} tok`, { color: 'gray', dimColor: true })
|
|
83
91
|
: text('', {}),
|
|
@@ -98,6 +106,8 @@ export function buildStatusBarView({
|
|
|
98
106
|
flexDirection: 'row',
|
|
99
107
|
justifyContent: 'space-between',
|
|
100
108
|
paddingX: 1,
|
|
109
|
+
height: 1,
|
|
110
|
+
flexShrink: 0,
|
|
101
111
|
borderStyle: debug ? 'single' : undefined,
|
|
102
112
|
borderColor: debug ? 'gray' : undefined
|
|
103
113
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SPINNER_FRAMES = ['-', '\\', '|', '/'];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const DEFAULT_SPINNER_VERBS = [
|
|
2
|
+
'Thinking',
|
|
3
|
+
'Reticulating splines',
|
|
4
|
+
'Allocating time slices',
|
|
5
|
+
'Negotiating with entropy',
|
|
6
|
+
'Consulting the archives',
|
|
7
|
+
'Organizing thoughts',
|
|
8
|
+
'Compiling context',
|
|
9
|
+
'Assembling response',
|
|
10
|
+
'Tracing dependencies',
|
|
11
|
+
'Resolving intent'
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export function parseSpinnerVerbs(input: string): string[] {
|
|
15
|
+
return input
|
|
16
|
+
.split(/[,|;\n]+/g)
|
|
17
|
+
.map(part => part.trim())
|
|
18
|
+
.filter(Boolean);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function formatSpinnerVerbs(verbs: string[]): string {
|
|
22
|
+
return verbs.length === 0 ? '(none)' : verbs.join(', ');
|
|
23
|
+
}
|
package/src/utils/tool_trace.ts
CHANGED
|
@@ -138,7 +138,11 @@ export function formatToolStart(tool: string, args: Record<string, unknown>, emu
|
|
|
138
138
|
return `⏺ ${label}${argsText}`;
|
|
139
139
|
}
|
|
140
140
|
if (style === 'codex') {
|
|
141
|
-
|
|
141
|
+
if (tool === 'run_command') {
|
|
142
|
+
const command = args.command ? String(args.command) : '';
|
|
143
|
+
return `! ${command}`;
|
|
144
|
+
}
|
|
145
|
+
return `⏺ ${label}${argsText}`;
|
|
142
146
|
}
|
|
143
147
|
return `> ${label}${argsText}`;
|
|
144
148
|
}
|
|
@@ -150,7 +154,13 @@ export function formatToolEnd(tool: string, result: string, durationMs?: number,
|
|
|
150
154
|
return `⎿ ${summary}`;
|
|
151
155
|
}
|
|
152
156
|
if (style === 'codex') {
|
|
153
|
-
|
|
157
|
+
if (tool === 'run_command') {
|
|
158
|
+
const { lines } = buildOutputLines(tool, result);
|
|
159
|
+
if (lines.length === 0) {
|
|
160
|
+
return ` ⎿ (No content)`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return ` ⎿ ${summary}`;
|
|
154
164
|
}
|
|
155
165
|
return `< ${summary}`;
|
|
156
166
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const PACKAGE_NAME = 'zerg-ztc';
|
|
2
|
+
|
|
3
|
+
export interface UpdateCheck {
|
|
4
|
+
current: string;
|
|
5
|
+
latest: string;
|
|
6
|
+
hasUpdate: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function parseVersion(value: string): number[] {
|
|
10
|
+
return value.split('.').map(part => Number(part.replace(/[^0-9]/g, '')) || 0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function compareVersions(a: string, b: string): number {
|
|
14
|
+
const pa = parseVersion(a);
|
|
15
|
+
const pb = parseVersion(b);
|
|
16
|
+
const len = Math.max(pa.length, pb.length);
|
|
17
|
+
for (let i = 0; i < len; i += 1) {
|
|
18
|
+
const av = pa[i] ?? 0;
|
|
19
|
+
const bv = pb[i] ?? 0;
|
|
20
|
+
if (av > bv) return 1;
|
|
21
|
+
if (av < bv) return -1;
|
|
22
|
+
}
|
|
23
|
+
return 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function fetchLatestVersion(): Promise<string> {
|
|
27
|
+
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}/latest`, {
|
|
28
|
+
headers: { 'Accept': 'application/json' }
|
|
29
|
+
});
|
|
30
|
+
if (!res.ok) {
|
|
31
|
+
throw new Error(`Version check failed (${res.status})`);
|
|
32
|
+
}
|
|
33
|
+
const data = await res.json() as { version?: string };
|
|
34
|
+
return data.version || '0.0.0';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function checkForUpdate(current: string): Promise<UpdateCheck> {
|
|
38
|
+
const latest = await fetchLatestVersion();
|
|
39
|
+
return {
|
|
40
|
+
current,
|
|
41
|
+
latest,
|
|
42
|
+
hasUpdate: compareVersions(latest, current) > 0
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { dirname, resolve } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
export function getVersion(): string {
|
|
6
|
+
try {
|
|
7
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
8
|
+
const pkgPath = resolve(here, '../../package.json');
|
|
9
|
+
const raw = readFileSync(pkgPath, 'utf-8');
|
|
10
|
+
const parsed = JSON.parse(raw) as { version?: string };
|
|
11
|
+
return parsed.version || '0.0.0';
|
|
12
|
+
} catch {
|
|
13
|
+
return '0.0.0';
|
|
14
|
+
}
|
|
15
|
+
}
|