zerg-ztc 0.1.11 → 0.1.13

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.
Files changed (122) hide show
  1. package/bin/ztc-audio-darwin-arm64 +0 -0
  2. package/dist/utils/dictation_native.d.ts.map +1 -1
  3. package/dist/utils/dictation_native.js +43 -23
  4. package/dist/utils/dictation_native.js.map +1 -1
  5. package/package.json +5 -4
  6. package/packages/ztc-dictation/Cargo.toml +0 -43
  7. package/packages/ztc-dictation/README.md +0 -65
  8. package/packages/ztc-dictation/index.d.ts +0 -16
  9. package/packages/ztc-dictation/index.js +0 -74
  10. package/packages/ztc-dictation/package.json +0 -41
  11. package/packages/ztc-dictation/src/main.rs +0 -430
  12. package/src/App.tsx +0 -910
  13. package/src/agent/agent.ts +0 -534
  14. package/src/agent/backends/anthropic.ts +0 -86
  15. package/src/agent/backends/gemini.ts +0 -119
  16. package/src/agent/backends/inception.ts +0 -23
  17. package/src/agent/backends/index.ts +0 -17
  18. package/src/agent/backends/openai.ts +0 -23
  19. package/src/agent/backends/openai_compatible.ts +0 -143
  20. package/src/agent/backends/types.ts +0 -83
  21. package/src/agent/commands/clipboard.ts +0 -77
  22. package/src/agent/commands/config.ts +0 -204
  23. package/src/agent/commands/debug.ts +0 -23
  24. package/src/agent/commands/dictation.ts +0 -11
  25. package/src/agent/commands/emulation.ts +0 -80
  26. package/src/agent/commands/execution.ts +0 -9
  27. package/src/agent/commands/help.ts +0 -20
  28. package/src/agent/commands/history.ts +0 -13
  29. package/src/agent/commands/index.ts +0 -48
  30. package/src/agent/commands/input_mode.ts +0 -22
  31. package/src/agent/commands/keybindings.ts +0 -40
  32. package/src/agent/commands/model.ts +0 -11
  33. package/src/agent/commands/models.ts +0 -116
  34. package/src/agent/commands/permissions.ts +0 -64
  35. package/src/agent/commands/retry.ts +0 -9
  36. package/src/agent/commands/shell.ts +0 -68
  37. package/src/agent/commands/skills.ts +0 -54
  38. package/src/agent/commands/status.ts +0 -19
  39. package/src/agent/commands/types.ts +0 -88
  40. package/src/agent/commands/update.ts +0 -32
  41. package/src/agent/factory.ts +0 -60
  42. package/src/agent/index.ts +0 -20
  43. package/src/agent/runtime/capabilities.ts +0 -7
  44. package/src/agent/runtime/memory.ts +0 -23
  45. package/src/agent/runtime/policy.ts +0 -48
  46. package/src/agent/runtime/session.ts +0 -18
  47. package/src/agent/runtime/tracing.ts +0 -23
  48. package/src/agent/tools/file.ts +0 -178
  49. package/src/agent/tools/index.ts +0 -52
  50. package/src/agent/tools/screenshot.ts +0 -821
  51. package/src/agent/tools/search.ts +0 -138
  52. package/src/agent/tools/shell.ts +0 -69
  53. package/src/agent/tools/skills.ts +0 -28
  54. package/src/agent/tools/types.ts +0 -14
  55. package/src/agent/tools/zerg.ts +0 -50
  56. package/src/cli.tsx +0 -163
  57. package/src/components/ActivityLine.tsx +0 -23
  58. package/src/components/FullScreen.tsx +0 -79
  59. package/src/components/Header.tsx +0 -27
  60. package/src/components/InputArea.tsx +0 -1660
  61. package/src/components/MessageList.tsx +0 -71
  62. package/src/components/SingleMessage.tsx +0 -298
  63. package/src/components/StatusBar.tsx +0 -55
  64. package/src/components/index.tsx +0 -8
  65. package/src/config/types.ts +0 -19
  66. package/src/config.ts +0 -186
  67. package/src/debug/logger.ts +0 -14
  68. package/src/emulation/README.md +0 -24
  69. package/src/emulation/catalog.ts +0 -82
  70. package/src/emulation/trace_style.ts +0 -8
  71. package/src/emulation/types.ts +0 -7
  72. package/src/skills/index.ts +0 -36
  73. package/src/skills/loader.ts +0 -135
  74. package/src/skills/registry.ts +0 -6
  75. package/src/skills/types.ts +0 -10
  76. package/src/types.ts +0 -84
  77. package/src/ui/README.md +0 -44
  78. package/src/ui/core/factory.ts +0 -9
  79. package/src/ui/core/index.ts +0 -4
  80. package/src/ui/core/input.ts +0 -38
  81. package/src/ui/core/input_segments.ts +0 -410
  82. package/src/ui/core/input_state.ts +0 -17
  83. package/src/ui/core/layout_yoga.ts +0 -122
  84. package/src/ui/core/style.ts +0 -38
  85. package/src/ui/core/types.ts +0 -54
  86. package/src/ui/ink/index.tsx +0 -1
  87. package/src/ui/ink/render.tsx +0 -60
  88. package/src/ui/views/activity_line.ts +0 -33
  89. package/src/ui/views/app.ts +0 -111
  90. package/src/ui/views/header.ts +0 -44
  91. package/src/ui/views/input_area.ts +0 -255
  92. package/src/ui/views/message_list.ts +0 -443
  93. package/src/ui/views/status_bar.ts +0 -114
  94. package/src/ui/vue/index.ts +0 -53
  95. package/src/ui/web/frame_render.tsx +0 -148
  96. package/src/ui/web/index.tsx +0 -1
  97. package/src/ui/web/render.tsx +0 -41
  98. package/src/utils/clipboard.ts +0 -39
  99. package/src/utils/clipboard_image.ts +0 -40
  100. package/src/utils/dictation.ts +0 -467
  101. package/src/utils/dictation_native.ts +0 -258
  102. package/src/utils/diff.ts +0 -52
  103. package/src/utils/image_preview.ts +0 -36
  104. package/src/utils/models.ts +0 -98
  105. package/src/utils/path_complete.ts +0 -173
  106. package/src/utils/path_format.ts +0 -99
  107. package/src/utils/shell.ts +0 -72
  108. package/src/utils/spinner_frames.ts +0 -1
  109. package/src/utils/spinner_verbs.ts +0 -23
  110. package/src/utils/table.ts +0 -171
  111. package/src/utils/tool_summary.ts +0 -56
  112. package/src/utils/tool_trace.ts +0 -346
  113. package/src/utils/update.ts +0 -44
  114. package/src/utils/version.ts +0 -15
  115. package/src/web/index.html +0 -352
  116. package/src/web/mirror-favicon.svg +0 -4
  117. package/src/web/mirror.html +0 -641
  118. package/src/web/mirror_hook.ts +0 -25
  119. package/src/web/mirror_server.ts +0 -204
  120. package/tsconfig.json +0 -22
  121. package/vite.config.ts +0 -363
  122. /package/{packages/ztc-dictation/bin → bin}/.gitkeep +0 -0
@@ -1,33 +0,0 @@
1
- import { AgentState } from '../../types.js';
2
- import { box, text, LayoutNode } from '../core/index.js';
3
-
4
- interface ActivityLineProps {
5
- state: AgentState;
6
- spinnerLabel?: string | null;
7
- spinnerFrame?: string | null;
8
- inputMode?: 'queue' | 'interrupt';
9
- }
10
-
11
- export function buildActivityLineView({
12
- state,
13
- spinnerLabel,
14
- spinnerFrame,
15
- inputMode
16
- }: ActivityLineProps): LayoutNode {
17
- const active = state.status === 'thinking' || state.status === 'streaming';
18
- if (!active || !spinnerLabel) {
19
- return box([], { height: 0 });
20
- }
21
- const frame = spinnerFrame || '✽';
22
- const hint = inputMode === 'interrupt' ? ' (esc to interrupt)' : '';
23
- return box([
24
- text(`${frame} ${spinnerLabel}…${hint}`, { color: 'yellow' })
25
- ], {
26
- flexDirection: 'row',
27
- paddingX: 2,
28
- paddingY: 0,
29
- marginTop: 1,
30
- marginBottom: 1,
31
- height: 1
32
- });
33
- }
@@ -1,111 +0,0 @@
1
- import { Message, AgentState } from '../../types.js';
2
- import { InputState } from '../core/input_state.js';
3
- import { box, LayoutNode } from '../core/index.js';
4
- import { buildHeaderView } from './header.js';
5
- import { buildMessageListView } from './message_list.js';
6
- import { buildInputAreaView, estimateInputLines } from './input_area.js';
7
- import { buildStatusBarView } from './status_bar.js';
8
- import { buildActivityLineView } from './activity_line.js';
9
-
10
- interface AppViewProps {
11
- messages: Message[];
12
- agentState: AgentState;
13
- inputState: InputState;
14
- sessionId: string;
15
- cols: number;
16
- rows: number;
17
- commands: Array<{ name: string; description: string; usage?: string }>;
18
- hasApiKey: boolean;
19
- version?: string;
20
- contextLength?: number;
21
- contextEstimated?: boolean;
22
- provider?: string;
23
- model?: string;
24
- emulationId?: string;
25
- toast?: string | null;
26
- spinnerLabel?: string | null;
27
- spinnerFrame?: string | null;
28
- inputMode?: 'queue' | 'interrupt';
29
- debug?: boolean;
30
- expandToolOutputs?: boolean;
31
- }
32
-
33
- function estimateBadgePreviewLines(state: InputState): number {
34
- const segment = state.segments[state.cursor.index];
35
- if (!segment || segment.type === 'text') return 0;
36
- if (segment.type === 'paste') {
37
- const lines = segment.text.split('\n');
38
- return Math.min(3, lines.length) + (lines.length > 3 ? 1 : 0);
39
- }
40
- if (segment.type === 'image') {
41
- return 16;
42
- }
43
- return 1;
44
- }
45
-
46
- export function buildAppView({
47
- messages,
48
- agentState,
49
- inputState,
50
- sessionId,
51
- cols,
52
- rows,
53
- commands,
54
- hasApiKey,
55
- version = '0.1.0',
56
- contextLength,
57
- contextEstimated,
58
- provider,
59
- model,
60
- emulationId,
61
- inputMode,
62
- toast,
63
- spinnerLabel,
64
- spinnerFrame,
65
- debug = false,
66
- expandToolOutputs = false
67
- }: AppViewProps): LayoutNode {
68
- const suggestionLines = 4;
69
- const headerHeight = 1;
70
- const statusHeight = 1;
71
- const activityHeight = (agentState.status === 'thinking' || agentState.status === 'streaming') && spinnerLabel ? 3 : 0;
72
- const inputLineCount = estimateInputLines(inputState.segments, cols);
73
- const previewLines = estimateBadgePreviewLines(inputState);
74
- const maxInputLines = Math.max(1, rows - (headerHeight + statusHeight + activityHeight + suggestionLines + 5));
75
- const inputHeight = Math.min(Math.max(1, inputLineCount + previewLines), maxInputLines) + suggestionLines;
76
- const contentHeight = Math.max(rows - (headerHeight + inputHeight + statusHeight + activityHeight), 5);
77
-
78
- const placeholder = !hasApiKey ? 'Set API key with /config key <key>' :
79
- agentState.status === 'thinking' ? 'Thinking...' :
80
- agentState.status === 'tool_use' ? `Running ${agentState.currentTool}...` :
81
- agentState.status === 'streaming' ? 'Streaming response...' :
82
- 'Type a message or /help for commands...';
83
-
84
- return box([
85
- buildHeaderView({ version, debug }),
86
- buildMessageListView({ messages, height: contentHeight, debug, expandToolOutputs }),
87
- buildActivityLineView({ state: agentState, spinnerLabel, spinnerFrame, inputMode }),
88
- buildInputAreaView({
89
- state: inputState,
90
- placeholder,
91
- disabled: agentState.status !== 'idle' && agentState.status !== 'error',
92
- commands,
93
- cols,
94
- debug
95
- }),
96
- buildStatusBarView({
97
- state: agentState,
98
- sessionId,
99
- version,
100
- connectionStatus: hasApiKey ? 'connected' : 'disconnected',
101
- contextLength,
102
- contextEstimated,
103
- provider,
104
- model,
105
- emulationId,
106
- inputMode,
107
- toast,
108
- debug
109
- })
110
- ], { flexDirection: 'column' });
111
- }
@@ -1,44 +0,0 @@
1
- import { box, text, LayoutNode } from '../core/index.js';
2
-
3
- interface HeaderProps {
4
- title?: string;
5
- version?: string;
6
- dateLabel?: string;
7
- showHelp?: boolean;
8
- debug?: boolean;
9
- }
10
-
11
- export function buildHeaderView({
12
- title = 'Zerg Terminal Client',
13
- version = '0.1.0',
14
- dateLabel,
15
- showHelp = true,
16
- debug = false
17
- }: HeaderProps): LayoutNode {
18
- return box([
19
- box([
20
- text(title, { bold: true }),
21
- text(' ', {}),
22
- text('ZTC', { color: 'gray', dimColor: true })
23
- ], { flexDirection: 'row' }),
24
- showHelp
25
- ? box([
26
- dateLabel ? text(dateLabel, { color: 'gray', dimColor: true }) : text('', {}),
27
- dateLabel ? text(' • ', { color: 'gray', dimColor: true }) : text('', {}),
28
- text(`v${version}`, { color: 'gray', dimColor: true }),
29
- text(' • ', { color: 'gray', dimColor: true }),
30
- text('Ctrl+C exit', { color: 'gray', dimColor: true }),
31
- text(' • ', { color: 'gray', dimColor: true }),
32
- text('/help', { color: 'gray', dimColor: true })
33
- ], { flexDirection: 'row' })
34
- : box([], { flexDirection: 'row' })
35
- ], {
36
- flexDirection: 'row',
37
- justifyContent: 'space-between',
38
- paddingX: 1,
39
- flexShrink: 0,
40
- borderStyle: 'single',
41
- borderColor: debug ? 'cyan' : 'gray',
42
- marginBottom: 1
43
- });
44
- }
@@ -1,255 +0,0 @@
1
- import { InputState, InputSegment } from '../core/input_state.js';
2
- import { box, text, LayoutNode } from '../core/index.js';
3
-
4
- interface InputAreaViewProps {
5
- state: InputState;
6
- placeholder: string;
7
- disabled?: boolean;
8
- commands?: Array<{
9
- name: string;
10
- description: string;
11
- usage?: string;
12
- }>;
13
- cols?: number;
14
- badgePreview?: string[] | null;
15
- showBadgePreview?: boolean;
16
- debug?: boolean;
17
- renderContent?: boolean;
18
- }
19
-
20
- const suggestionLines = 4;
21
- const promptPrefix = '❯ ';
22
- const promptWidth = promptPrefix.length;
23
-
24
- interface RenderToken {
25
- text: string;
26
- style?: { color?: string; dimColor?: boolean; bold?: boolean; inverse?: boolean; badge?: {
27
- type: 'paste' | 'file' | 'image';
28
- preview: string;
29
- full: string;
30
- path?: string;
31
- } };
32
- }
33
-
34
- function badgeLabel(segment: InputSegment): string {
35
- switch (segment.type) {
36
- case 'paste': {
37
- const lines = segment.text.split('\n').length;
38
- return `[pasted ${lines} line${lines === 1 ? '' : 's'}]`;
39
- }
40
- case 'file':
41
- return `[file ${segment.path}]`;
42
- case 'image':
43
- return `[image ${segment.path}]`;
44
- default:
45
- return '';
46
- }
47
- }
48
-
49
- function badgePreview(segment: InputSegment): { preview: string; full: string; path?: string; type: 'paste' | 'file' | 'image' } {
50
- switch (segment.type) {
51
- case 'paste': {
52
- const lines = segment.text.split('\n');
53
- const previewLines = lines.slice(0, 3).join('\n');
54
- const suffix = lines.length > 3 ? '\n…' : '';
55
- return { type: 'paste', preview: previewLines + suffix, full: segment.text };
56
- }
57
- case 'image':
58
- return { type: 'image', preview: `Image: ${segment.path}`, full: segment.path, path: segment.path };
59
- case 'file':
60
- return { type: 'file', preview: `File: ${segment.path}`, full: segment.path, path: segment.path };
61
- default:
62
- return { type: 'file', preview: 'File: (unknown)', full: '' };
63
- }
64
- }
65
-
66
- export function buildRenderTokens(segments: InputSegment[]): RenderToken[] {
67
- return segments.map(segment => {
68
- if (segment.type === 'text') {
69
- return { text: segment.text };
70
- }
71
- const badge = badgePreview(segment);
72
- return { text: badgeLabel(segment), style: { color: 'yellow', dimColor: true, badge } };
73
- });
74
- }
75
-
76
- export function wrapInputSegments(
77
- segments: InputSegment[],
78
- cursor: { index: number; offset: number },
79
- cols: number,
80
- prefixWidth = promptWidth
81
- ): { lines: RenderToken[][]; cursorLine: number; cursorCol: number } {
82
- const wrapWidth = Math.max(10, cols - prefixWidth - 2);
83
- const tokens = buildRenderTokens(segments);
84
- let cursorPos = 0;
85
- let pos = 0;
86
- for (let i = 0; i < segments.length; i += 1) {
87
- const segment = segments[i];
88
- const tokenText = tokens[i].text;
89
- if (i === cursor.index) {
90
- if (segment.type === 'text') {
91
- cursorPos = pos + cursor.offset;
92
- } else {
93
- cursorPos = pos + (cursor.offset > 0 ? tokenText.length : 0);
94
- }
95
- }
96
- pos += tokenText.length;
97
- }
98
- if (cursor.index === segments.length) {
99
- cursorPos = pos;
100
- }
101
-
102
- const lines: RenderToken[][] = [[]];
103
- let lineIndex = 0;
104
- let col = 0;
105
- let cursorLine = 0;
106
- let cursorCol = 0;
107
- let globalPos = 0;
108
-
109
- for (const token of tokens) {
110
- const textValue = token.text || '';
111
- for (let i = 0; i < textValue.length; i += 1) {
112
- if (globalPos === cursorPos) {
113
- cursorLine = lineIndex;
114
- cursorCol = col;
115
- }
116
- const ch = textValue[i];
117
- if (ch === '\n') {
118
- lineIndex += 1;
119
- lines.push([]);
120
- col = 0;
121
- globalPos += 1;
122
- continue;
123
- }
124
- if (col >= wrapWidth) {
125
- lineIndex += 1;
126
- lines.push([]);
127
- col = 0;
128
- }
129
- lines[lineIndex].push({ text: ch, style: token.style });
130
- col += 1;
131
- globalPos += 1;
132
- }
133
- }
134
-
135
- if (cursorPos === globalPos) {
136
- cursorLine = lineIndex;
137
- cursorCol = col;
138
- }
139
-
140
- return { lines, cursorLine, cursorCol };
141
- }
142
-
143
- export function estimateInputLines(segments: InputSegment[], cols: number): number {
144
- return wrapInputSegments(segments, { index: segments.length, offset: 0 }, cols).lines.length;
145
- }
146
-
147
- export function buildInputAreaView({
148
- state,
149
- placeholder,
150
- disabled = false,
151
- commands = [],
152
- cols = 80,
153
- badgePreview,
154
- showBadgePreview = false,
155
- debug = false,
156
- renderContent = true
157
- }: InputAreaViewProps): LayoutNode {
158
- if (!renderContent) {
159
- return box([text('')], { flexDirection: 'column', flexShrink: 0, height: 5 });
160
- }
161
- const truncate = (value: string, max: number) => (
162
- value.length > max ? `${value.slice(0, max - 1)}…` : value
163
- );
164
- const promptColor = disabled ? 'gray' : 'blue';
165
-
166
- const plainText = state.segments.length === 1 && state.segments[0].type === 'text'
167
- ? state.segments[0].text
168
- : '';
169
- const isCommandMode = plainText.startsWith('/');
170
- const commandQuery = isCommandMode ? plainText.slice(1).trim() : '';
171
- const commandMatches = isCommandMode
172
- ? commands.filter(c => c.name.startsWith(commandQuery)).slice(0, suggestionLines)
173
- : [];
174
-
175
- let inputLines: LayoutNode[] = [];
176
- if (disabled) {
177
- inputLines = [
178
- box([
179
- text(promptPrefix, { color: promptColor, bold: true }),
180
- text(placeholder, { color: 'gray', dimColor: true })
181
- ], { flexDirection: 'row' })
182
- ];
183
- } else if (state.segments.length === 0) {
184
- inputLines = [
185
- box([
186
- text(promptPrefix, { color: promptColor, bold: true }),
187
- box([
188
- text('|', { inverse: true }),
189
- text(placeholder, { color: 'gray', dimColor: true })
190
- ], { flexDirection: 'row' })
191
- ], { flexDirection: 'row' })
192
- ];
193
- } else {
194
- const wrapped = wrapInputSegments(state.segments, state.cursor, cols, promptWidth);
195
- inputLines = wrapped.lines.map((line, index) => {
196
- const prefix = index === 0 ? promptPrefix : ' ';
197
- const segments: LayoutNode[] = [text(prefix, { color: promptColor, bold: index === 0 })];
198
- line.forEach((token, tokenIndex) => {
199
- if (index === wrapped.cursorLine && tokenIndex === wrapped.cursorCol) {
200
- segments.push(text(token.text || ' ', { inverse: true, ...token.style }));
201
- } else {
202
- segments.push(text(token.text, token.style));
203
- }
204
- });
205
- if (index === wrapped.cursorLine && wrapped.cursorCol === line.length) {
206
- segments.push(text(' ', { inverse: true }));
207
- }
208
- return box(segments, { flexDirection: 'row' });
209
- });
210
- }
211
-
212
- const inputLine = box(inputLines, {
213
- flexDirection: 'column',
214
- paddingX: 1,
215
- borderStyle: debug ? 'round' : undefined,
216
- borderColor: debug ? (disabled ? 'gray' : 'blue') : undefined
217
- });
218
-
219
- // Only render suggestion lines if there are actual command matches
220
- const suggestions = commandMatches.length > 0
221
- ? box(
222
- commandMatches.map((cmd) => {
223
- const usage = cmd.usage ? ` ${truncate(cmd.usage, 36)}` : '';
224
- return box([
225
- text(`/${cmd.name}`, { color: 'cyan', bold: true }),
226
- text(usage, { color: 'white' }),
227
- text(` — ${truncate(cmd.description, 48)}`, { color: 'gray', dimColor: true })
228
- ], { flexDirection: 'row' });
229
- }),
230
- { flexDirection: 'column', paddingX: 2 }
231
- )
232
- : null;
233
-
234
- const previewLines = showBadgePreview && badgePreview && badgePreview.length > 0
235
- ? box(badgePreview.map(line => text(line, { color: 'gray', dimColor: true })), {
236
- flexDirection: 'column',
237
- paddingX: 2
238
- })
239
- : null;
240
-
241
- // Horizontal separator lines
242
- const separatorTop = text('─'.repeat(Math.max(10, cols - 2)), { color: 'gray', dimColor: true });
243
- const separatorBottom = text('─'.repeat(Math.max(10, cols - 2)), { color: 'gray', dimColor: true });
244
-
245
- // Build the content array, filtering out nulls
246
- const content: LayoutNode[] = [separatorTop, inputLine];
247
- if (previewLines) content.push(previewLines);
248
- if (suggestions) content.push(suggestions);
249
- content.push(separatorBottom);
250
-
251
- return box(content, {
252
- flexDirection: 'column',
253
- flexShrink: 0
254
- });
255
- }