@x-code-cli/cli 0.1.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/dist/app.d.ts +6 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +36 -0
- package/dist/app.js.map +1 -0
- package/dist/cli.js +180674 -0
- package/dist/cli.js.map +7 -0
- package/dist/config/index.d.ts +20 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +18 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/components/App.d.ts +40 -0
- package/dist/ui/components/App.d.ts.map +1 -0
- package/dist/ui/components/App.js +196 -0
- package/dist/ui/components/App.js.map +1 -0
- package/dist/ui/components/AppHeader.d.ts +6 -0
- package/dist/ui/components/AppHeader.d.ts.map +1 -0
- package/dist/ui/components/AppHeader.js +51 -0
- package/dist/ui/components/AppHeader.js.map +1 -0
- package/dist/ui/components/ChatInput.d.ts +12 -0
- package/dist/ui/components/ChatInput.d.ts.map +1 -0
- package/dist/ui/components/ChatInput.js +107 -0
- package/dist/ui/components/ChatInput.js.map +1 -0
- package/dist/ui/components/MessageList.d.ts +7 -0
- package/dist/ui/components/MessageList.d.ts.map +1 -0
- package/dist/ui/components/MessageList.js +8 -0
- package/dist/ui/components/MessageList.js.map +1 -0
- package/dist/ui/components/Permission.d.ts +8 -0
- package/dist/ui/components/Permission.d.ts.map +1 -0
- package/dist/ui/components/Permission.js +104 -0
- package/dist/ui/components/Permission.js.map +1 -0
- package/dist/ui/components/SelectOptions.d.ts +12 -0
- package/dist/ui/components/SelectOptions.d.ts.map +1 -0
- package/dist/ui/components/SelectOptions.js +49 -0
- package/dist/ui/components/SelectOptions.js.map +1 -0
- package/dist/ui/components/ShellOutput.d.ts +6 -0
- package/dist/ui/components/ShellOutput.d.ts.map +1 -0
- package/dist/ui/components/ShellOutput.js +13 -0
- package/dist/ui/components/ShellOutput.js.map +1 -0
- package/dist/ui/components/Spinner.d.ts +6 -0
- package/dist/ui/components/Spinner.d.ts.map +1 -0
- package/dist/ui/components/Spinner.js +17 -0
- package/dist/ui/components/Spinner.js.map +1 -0
- package/dist/ui/components/StatusBar.d.ts +8 -0
- package/dist/ui/components/StatusBar.d.ts.map +1 -0
- package/dist/ui/components/StatusBar.js +8 -0
- package/dist/ui/components/StatusBar.js.map +1 -0
- package/dist/ui/components/StreamingText.d.ts +6 -0
- package/dist/ui/components/StreamingText.d.ts.map +1 -0
- package/dist/ui/components/StreamingText.js +46 -0
- package/dist/ui/components/StreamingText.js.map +1 -0
- package/dist/ui/components/ToolCall.d.ts +9 -0
- package/dist/ui/components/ToolCall.d.ts.map +1 -0
- package/dist/ui/components/ToolCall.js +29 -0
- package/dist/ui/components/ToolCall.js.map +1 -0
- package/dist/ui/hooks/use-agent.d.ts +46 -0
- package/dist/ui/hooks/use-agent.d.ts.map +1 -0
- package/dist/ui/hooks/use-agent.js +277 -0
- package/dist/ui/hooks/use-agent.js.map +1 -0
- package/dist/ui/render-markdown.d.ts +8 -0
- package/dist/ui/render-markdown.d.ts.map +1 -0
- package/dist/ui/render-markdown.js +230 -0
- package/dist/ui/render-markdown.js.map +1 -0
- package/dist/ui/theme.d.ts +13 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +19 -0
- package/dist/ui/theme.js.map +1 -0
- package/package.json +28 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// @x-code/cli — Agent state management hook
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { agentLoop, compressMessages, initMemories, loadLatestSession, saveSession, scanProject } from '@x-code/core';
|
|
4
|
+
export function useAgent(initialModel, options) {
|
|
5
|
+
const [state, setState] = useState({
|
|
6
|
+
messages: [],
|
|
7
|
+
streamingText: '',
|
|
8
|
+
isLoading: false,
|
|
9
|
+
currentToolCall: null,
|
|
10
|
+
shellOutput: '',
|
|
11
|
+
pendingPermission: null,
|
|
12
|
+
pendingQuestion: null,
|
|
13
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0, estimatedCost: 0, costCurrency: 'USD' },
|
|
14
|
+
error: null,
|
|
15
|
+
latestSession: null,
|
|
16
|
+
});
|
|
17
|
+
const modelRef = useRef(initialModel);
|
|
18
|
+
const modelIdRef = useRef(options.modelId);
|
|
19
|
+
const loopStateRef = useRef(null);
|
|
20
|
+
const abortControllerRef = useRef(null);
|
|
21
|
+
const initializedRef = useRef(false);
|
|
22
|
+
// ── Throttled streaming text buffer ──
|
|
23
|
+
// Accumulate text deltas in a ref and flush to state at a fixed interval
|
|
24
|
+
// to avoid triggering a React re-render on every single token delta.
|
|
25
|
+
const streamingBufferRef = useRef('');
|
|
26
|
+
const flushTimerRef = useRef(null);
|
|
27
|
+
const startStreamingFlush = useCallback(() => {
|
|
28
|
+
if (flushTimerRef.current)
|
|
29
|
+
return;
|
|
30
|
+
flushTimerRef.current = setInterval(() => {
|
|
31
|
+
if (streamingBufferRef.current) {
|
|
32
|
+
const buffered = streamingBufferRef.current;
|
|
33
|
+
streamingBufferRef.current = '';
|
|
34
|
+
setState((prev) => ({ ...prev, streamingText: prev.streamingText + buffered }));
|
|
35
|
+
}
|
|
36
|
+
}, 50);
|
|
37
|
+
}, []);
|
|
38
|
+
const stopStreamingFlush = useCallback(() => {
|
|
39
|
+
if (flushTimerRef.current) {
|
|
40
|
+
clearInterval(flushTimerRef.current);
|
|
41
|
+
flushTimerRef.current = null;
|
|
42
|
+
}
|
|
43
|
+
// Flush any remaining buffered text
|
|
44
|
+
if (streamingBufferRef.current) {
|
|
45
|
+
const buffered = streamingBufferRef.current;
|
|
46
|
+
streamingBufferRef.current = '';
|
|
47
|
+
setState((prev) => ({ ...prev, streamingText: prev.streamingText + buffered }));
|
|
48
|
+
}
|
|
49
|
+
}, []);
|
|
50
|
+
// Cleanup flush timer on unmount
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
return () => {
|
|
53
|
+
if (flushTimerRef.current)
|
|
54
|
+
clearInterval(flushTimerRef.current);
|
|
55
|
+
};
|
|
56
|
+
}, []);
|
|
57
|
+
/** Initialize memories and scan project (once) */
|
|
58
|
+
const initialize = useCallback(async () => {
|
|
59
|
+
if (initializedRef.current)
|
|
60
|
+
return;
|
|
61
|
+
initializedRef.current = true;
|
|
62
|
+
await initMemories();
|
|
63
|
+
await scanProject(process.cwd());
|
|
64
|
+
// Check for latest session to offer continuation
|
|
65
|
+
const session = await loadLatestSession();
|
|
66
|
+
if (session && (session.status === 'in_progress' || session.pendingWork.length > 0)) {
|
|
67
|
+
setState((prev) => ({ ...prev, latestSession: session }));
|
|
68
|
+
}
|
|
69
|
+
}, []);
|
|
70
|
+
/** Submit a user message */
|
|
71
|
+
const submit = useCallback(async (text) => {
|
|
72
|
+
await initialize();
|
|
73
|
+
setState((prev) => ({
|
|
74
|
+
...prev,
|
|
75
|
+
isLoading: true,
|
|
76
|
+
streamingText: '',
|
|
77
|
+
shellOutput: '',
|
|
78
|
+
error: null,
|
|
79
|
+
messages: [
|
|
80
|
+
...prev.messages,
|
|
81
|
+
{
|
|
82
|
+
id: Date.now().toString(),
|
|
83
|
+
role: 'user',
|
|
84
|
+
content: text,
|
|
85
|
+
timestamp: Date.now(),
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
}));
|
|
89
|
+
const controller = new AbortController();
|
|
90
|
+
abortControllerRef.current = controller;
|
|
91
|
+
startStreamingFlush();
|
|
92
|
+
const callbacks = {
|
|
93
|
+
onTextDelta: (delta) => {
|
|
94
|
+
streamingBufferRef.current += delta;
|
|
95
|
+
},
|
|
96
|
+
onToolCall: (toolName, input) => {
|
|
97
|
+
setState((prev) => ({ ...prev, currentToolCall: { toolName, input } }));
|
|
98
|
+
},
|
|
99
|
+
onToolResult: (_toolCallId, _result) => {
|
|
100
|
+
setState((prev) => ({ ...prev, currentToolCall: null, shellOutput: '' }));
|
|
101
|
+
},
|
|
102
|
+
onAskPermission: (toolCall) => {
|
|
103
|
+
return new Promise((resolve) => {
|
|
104
|
+
setState((prev) => ({
|
|
105
|
+
...prev,
|
|
106
|
+
pendingPermission: { ...toolCall, resolve },
|
|
107
|
+
}));
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
onAskUser: (question, opts) => {
|
|
111
|
+
return new Promise((resolve) => {
|
|
112
|
+
setState((prev) => ({
|
|
113
|
+
...prev,
|
|
114
|
+
pendingQuestion: { question, options: opts, resolve },
|
|
115
|
+
}));
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
onShellOutput: (chunk) => {
|
|
119
|
+
setState((prev) => ({ ...prev, shellOutput: prev.shellOutput + chunk }));
|
|
120
|
+
},
|
|
121
|
+
onUsageUpdate: (usage) => {
|
|
122
|
+
setState((prev) => ({ ...prev, usage }));
|
|
123
|
+
},
|
|
124
|
+
onContextCompressed: () => {
|
|
125
|
+
// Could show a notification
|
|
126
|
+
},
|
|
127
|
+
onError: (error) => {
|
|
128
|
+
setState((prev) => ({ ...prev, error: error.message }));
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
loopStateRef.current = await agentLoop(text, modelRef.current, { ...options, modelId: modelIdRef.current, abortSignal: controller.signal }, callbacks, loopStateRef.current ?? undefined);
|
|
133
|
+
// Flush any remaining buffered text before finalizing
|
|
134
|
+
stopStreamingFlush();
|
|
135
|
+
// Add assistant message from streaming text
|
|
136
|
+
setState((prev) => {
|
|
137
|
+
const assistantMsg = {
|
|
138
|
+
id: Date.now().toString(),
|
|
139
|
+
role: 'assistant',
|
|
140
|
+
content: prev.streamingText,
|
|
141
|
+
timestamp: Date.now(),
|
|
142
|
+
};
|
|
143
|
+
return {
|
|
144
|
+
...prev,
|
|
145
|
+
messages: prev.streamingText ? [...prev.messages, assistantMsg] : prev.messages,
|
|
146
|
+
streamingText: '',
|
|
147
|
+
isLoading: false,
|
|
148
|
+
currentToolCall: null,
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
stopStreamingFlush();
|
|
154
|
+
setState((prev) => ({
|
|
155
|
+
...prev,
|
|
156
|
+
isLoading: false,
|
|
157
|
+
error: err instanceof Error ? err.message : String(err),
|
|
158
|
+
}));
|
|
159
|
+
}
|
|
160
|
+
}, [options, initialize, startStreamingFlush, stopStreamingFlush]);
|
|
161
|
+
/** Resolve a pending permission request */
|
|
162
|
+
const resolvePermission = useCallback((approved) => {
|
|
163
|
+
setState((prev) => {
|
|
164
|
+
if (prev.pendingPermission) {
|
|
165
|
+
// Defer the side-effect outside the setState updater to avoid
|
|
166
|
+
// double-invocation under React 18 Strict Mode.
|
|
167
|
+
queueMicrotask(() => prev.pendingPermission.resolve(approved));
|
|
168
|
+
}
|
|
169
|
+
return { ...prev, pendingPermission: null };
|
|
170
|
+
});
|
|
171
|
+
}, []);
|
|
172
|
+
/** Resolve a pending question */
|
|
173
|
+
const resolveQuestion = useCallback((answer) => {
|
|
174
|
+
setState((prev) => {
|
|
175
|
+
if (prev.pendingQuestion) {
|
|
176
|
+
queueMicrotask(() => prev.pendingQuestion.resolve(answer));
|
|
177
|
+
}
|
|
178
|
+
return { ...prev, pendingQuestion: null };
|
|
179
|
+
});
|
|
180
|
+
}, []);
|
|
181
|
+
/** Abort current operation */
|
|
182
|
+
const abort = useCallback(() => {
|
|
183
|
+
abortControllerRef.current?.abort();
|
|
184
|
+
setState((prev) => ({ ...prev, isLoading: false }));
|
|
185
|
+
}, []);
|
|
186
|
+
/** Save session and cleanup */
|
|
187
|
+
const cleanup = useCallback(async () => {
|
|
188
|
+
if (loopStateRef.current) {
|
|
189
|
+
await saveSession(loopStateRef.current, modelRef.current);
|
|
190
|
+
}
|
|
191
|
+
}, []);
|
|
192
|
+
/** Save session without exiting */
|
|
193
|
+
const saveCurrentSession = useCallback(async () => {
|
|
194
|
+
if (loopStateRef.current) {
|
|
195
|
+
await saveSession(loopStateRef.current, modelRef.current);
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
}, []);
|
|
200
|
+
/** Clear conversation */
|
|
201
|
+
const clear = useCallback(() => {
|
|
202
|
+
loopStateRef.current = null;
|
|
203
|
+
setState({
|
|
204
|
+
messages: [],
|
|
205
|
+
streamingText: '',
|
|
206
|
+
isLoading: false,
|
|
207
|
+
currentToolCall: null,
|
|
208
|
+
shellOutput: '',
|
|
209
|
+
pendingPermission: null,
|
|
210
|
+
pendingQuestion: null,
|
|
211
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0, estimatedCost: 0, costCurrency: 'USD' },
|
|
212
|
+
error: null,
|
|
213
|
+
latestSession: null,
|
|
214
|
+
});
|
|
215
|
+
}, []);
|
|
216
|
+
/** Manual context compression */
|
|
217
|
+
const compact = useCallback(async () => {
|
|
218
|
+
if (!loopStateRef.current)
|
|
219
|
+
return;
|
|
220
|
+
loopStateRef.current.messages = await compressMessages(loopStateRef.current.messages, modelRef.current);
|
|
221
|
+
}, []);
|
|
222
|
+
/** Switch model at runtime */
|
|
223
|
+
const switchModel = useCallback((newModelId, newModel) => {
|
|
224
|
+
modelRef.current = newModel;
|
|
225
|
+
modelIdRef.current = newModelId;
|
|
226
|
+
}, []);
|
|
227
|
+
/** Dismiss session continuation prompt */
|
|
228
|
+
const dismissSession = useCallback(() => {
|
|
229
|
+
setState((prev) => ({ ...prev, latestSession: null }));
|
|
230
|
+
}, []);
|
|
231
|
+
/** Add a system/info message (for slash command output) */
|
|
232
|
+
const addInfoMessage = useCallback((content) => {
|
|
233
|
+
setState((prev) => ({
|
|
234
|
+
...prev,
|
|
235
|
+
messages: [
|
|
236
|
+
...prev.messages,
|
|
237
|
+
{
|
|
238
|
+
id: Date.now().toString(),
|
|
239
|
+
role: 'assistant',
|
|
240
|
+
content,
|
|
241
|
+
timestamp: Date.now(),
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
}));
|
|
245
|
+
}, []);
|
|
246
|
+
/** Add a user message to the history (for echoing slash commands) */
|
|
247
|
+
const addUserMessage = useCallback((content) => {
|
|
248
|
+
setState((prev) => ({
|
|
249
|
+
...prev,
|
|
250
|
+
messages: [
|
|
251
|
+
...prev.messages,
|
|
252
|
+
{
|
|
253
|
+
id: Date.now().toString(),
|
|
254
|
+
role: 'user',
|
|
255
|
+
content,
|
|
256
|
+
timestamp: Date.now(),
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
}));
|
|
260
|
+
}, []);
|
|
261
|
+
return {
|
|
262
|
+
state,
|
|
263
|
+
submit,
|
|
264
|
+
resolvePermission,
|
|
265
|
+
resolveQuestion,
|
|
266
|
+
abort,
|
|
267
|
+
cleanup,
|
|
268
|
+
clear,
|
|
269
|
+
compact,
|
|
270
|
+
switchModel,
|
|
271
|
+
saveCurrentSession,
|
|
272
|
+
dismissSession,
|
|
273
|
+
addInfoMessage,
|
|
274
|
+
addUserMessage,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=use-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-agent.js","sourceRoot":"","sources":["../../../src/ui/hooks/use-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert a Markdown string into ANSI-styled terminal text.
|
|
3
|
+
*
|
|
4
|
+
* Uses `marked.lexer()` to parse the Markdown into tokens, then renders
|
|
5
|
+
* each token recursively.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderMarkdown(text: string): string;
|
|
8
|
+
//# sourceMappingURL=render-markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-markdown.d.ts","sourceRoot":"","sources":["../../src/ui/render-markdown.ts"],"names":[],"mappings":"AA6OA;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAanD"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// @x-code/cli — Markdown-to-ANSI renderer (token-based)
|
|
2
|
+
//
|
|
3
|
+
// Uses `marked.lexer()` to parse Markdown into an AST (token tree), then
|
|
4
|
+
// recursively renders each token to ANSI-styled terminal text using chalk.
|
|
5
|
+
//
|
|
6
|
+
// This approach (identical to what Claude Code uses internally) is far more
|
|
7
|
+
// reliable than regex-based rendering because:
|
|
8
|
+
// 1. The parser correctly handles nested structures
|
|
9
|
+
// (e.g. bold **inside** a list item inside a blockquote).
|
|
10
|
+
// 2. Code spans are protected — their content is never re-interpreted.
|
|
11
|
+
// 3. Streaming partial text degrades gracefully (unclosed tokens are
|
|
12
|
+
// simply treated as plain text by the lexer).
|
|
13
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
14
|
+
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
16
|
+
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
17
|
+
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
18
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
19
|
+
import { Chalk } from 'chalk';
|
|
20
|
+
import { marked } from 'marked';
|
|
21
|
+
// ── chalk instance with 24-bit colour ──
|
|
22
|
+
const c = new Chalk({ level: 3 });
|
|
23
|
+
// Disable del (strikethrough) extension to avoid conflicts with file paths
|
|
24
|
+
// containing tildes — same approach Claude Code uses.
|
|
25
|
+
marked.use({
|
|
26
|
+
tokenizer: {
|
|
27
|
+
del() {
|
|
28
|
+
return undefined;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
// ── Theme colours (keep in sync with theme.ts) ──
|
|
33
|
+
const ACCENT = '#89b4fa';
|
|
34
|
+
const WARNING = '#f9e2af';
|
|
35
|
+
// Newline constant for joining blocks
|
|
36
|
+
const NL = '\n';
|
|
37
|
+
// ── Recursive token renderer ──────────────────────────────────────────
|
|
38
|
+
//
|
|
39
|
+
// Mirrors the approach from Claude Code's minified `CM` function:
|
|
40
|
+
// - Each token type has a dedicated case
|
|
41
|
+
// - Inline tokens (bold, italic, code, etc.) recurse into child tokens
|
|
42
|
+
// - Block tokens (heading, list, code block, etc.) append newlines
|
|
43
|
+
function renderToken(token, depth = 0, orderedStart = null, _parentToken = null) {
|
|
44
|
+
switch (token.type) {
|
|
45
|
+
// ── Block elements ──
|
|
46
|
+
case 'heading': {
|
|
47
|
+
const content = renderTokens(token.tokens ?? [], depth);
|
|
48
|
+
switch (token.depth) {
|
|
49
|
+
case 1:
|
|
50
|
+
return c.hex(ACCENT).bold.underline(content) + NL;
|
|
51
|
+
case 2:
|
|
52
|
+
return c.bold(content) + NL;
|
|
53
|
+
default:
|
|
54
|
+
return c.bold(content) + NL;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
case 'paragraph': {
|
|
58
|
+
const content = renderTokens(token.tokens ?? [], depth);
|
|
59
|
+
return content + NL;
|
|
60
|
+
}
|
|
61
|
+
case 'blockquote': {
|
|
62
|
+
const content = renderTokens(token.tokens ?? [], depth);
|
|
63
|
+
// Indent each line with a dim vertical bar
|
|
64
|
+
return (content
|
|
65
|
+
.split(NL)
|
|
66
|
+
.map((line) => (line.trim() ? c.dim.italic(` │ ${line}`) : ''))
|
|
67
|
+
.filter(Boolean)
|
|
68
|
+
.join(NL) + NL);
|
|
69
|
+
}
|
|
70
|
+
case 'code': {
|
|
71
|
+
const langLabel = token.lang ? c.dim(` [${token.lang}]`) : '';
|
|
72
|
+
const codeLines = (token.text ?? '')
|
|
73
|
+
.split(NL)
|
|
74
|
+
.map((line) => ` ${c.hex(WARNING)(line)}`)
|
|
75
|
+
.join(NL);
|
|
76
|
+
return (langLabel ? langLabel + NL : '') + codeLines + NL;
|
|
77
|
+
}
|
|
78
|
+
case 'list': {
|
|
79
|
+
return token.items
|
|
80
|
+
.map((item, idx) => renderToken(item, depth, token.ordered ? (token.start ?? 1) + idx : null, token))
|
|
81
|
+
.join('');
|
|
82
|
+
}
|
|
83
|
+
case 'list_item': {
|
|
84
|
+
// Each list_item contains child tokens (paragraph, text, sub-lists…).
|
|
85
|
+
// We render them, prepending a bullet/number to the first line.
|
|
86
|
+
const inner = (token.tokens ?? [])
|
|
87
|
+
.map((child) => {
|
|
88
|
+
// If the child is a 'text' token at list-item level, render its
|
|
89
|
+
// inline children directly (without adding an extra newline that
|
|
90
|
+
// 'paragraph' would add).
|
|
91
|
+
if (child.type === 'text') {
|
|
92
|
+
const prefix = orderedStart !== null ? `${orderedStart}.` : '•';
|
|
93
|
+
const indent = ' '.repeat(depth);
|
|
94
|
+
const inlineContent = child.tokens ? renderTokens(child.tokens, depth) : (child.text ?? '');
|
|
95
|
+
return `${indent}${prefix} ${inlineContent}${NL}`;
|
|
96
|
+
}
|
|
97
|
+
if (child.type === 'list') {
|
|
98
|
+
// Nested list — increase depth
|
|
99
|
+
return renderToken(child, depth + 1);
|
|
100
|
+
}
|
|
101
|
+
// Other block elements inside a list item (e.g. paragraph)
|
|
102
|
+
if (child.type === 'paragraph') {
|
|
103
|
+
const prefix = orderedStart !== null ? `${orderedStart}.` : '•';
|
|
104
|
+
const indent = ' '.repeat(depth);
|
|
105
|
+
const inlineContent = renderTokens(child.tokens ?? [], depth);
|
|
106
|
+
return `${indent}${prefix} ${inlineContent}${NL}`;
|
|
107
|
+
}
|
|
108
|
+
return renderToken(child, depth);
|
|
109
|
+
})
|
|
110
|
+
.join('');
|
|
111
|
+
return inner;
|
|
112
|
+
}
|
|
113
|
+
case 'hr':
|
|
114
|
+
return c.dim('─'.repeat(40)) + NL;
|
|
115
|
+
case 'space':
|
|
116
|
+
return NL;
|
|
117
|
+
case 'html':
|
|
118
|
+
// Pass HTML through as-is (rare in LLM output)
|
|
119
|
+
return (token.text ?? '') + NL;
|
|
120
|
+
case 'table': {
|
|
121
|
+
// Simple table rendering
|
|
122
|
+
const header = token.header;
|
|
123
|
+
const rows = token.rows;
|
|
124
|
+
// Compute column widths
|
|
125
|
+
const colWidths = header.map((cell, i) => {
|
|
126
|
+
let max = stripAnsi(renderTokens(cell.tokens ?? [], 0)).length;
|
|
127
|
+
for (const row of rows) {
|
|
128
|
+
if (row[i]) {
|
|
129
|
+
const len = stripAnsi(renderTokens(row[i].tokens ?? [], 0)).length;
|
|
130
|
+
max = Math.max(max, len);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return Math.max(max, 3);
|
|
134
|
+
});
|
|
135
|
+
// Header
|
|
136
|
+
const headerLine = header
|
|
137
|
+
.map((cell, i) => {
|
|
138
|
+
const text = renderTokens(cell.tokens ?? [], 0);
|
|
139
|
+
return padVisual(text, colWidths[i]);
|
|
140
|
+
})
|
|
141
|
+
.join(' │ ');
|
|
142
|
+
// Separator
|
|
143
|
+
const sepLine = colWidths.map((w) => '─'.repeat(w)).join('─┼─');
|
|
144
|
+
// Rows
|
|
145
|
+
const rowLines = rows
|
|
146
|
+
.map((row) => row
|
|
147
|
+
.map((cell, i) => {
|
|
148
|
+
const text = renderTokens(cell?.tokens ?? [], 0);
|
|
149
|
+
return padVisual(text, colWidths[i]);
|
|
150
|
+
})
|
|
151
|
+
.join(' │ '))
|
|
152
|
+
.join(NL);
|
|
153
|
+
return [c.bold(headerLine), c.dim(sepLine), rowLines].join(NL) + NL;
|
|
154
|
+
}
|
|
155
|
+
// ── Inline elements ──
|
|
156
|
+
case 'strong':
|
|
157
|
+
return c.bold(renderTokens(token.tokens ?? [], depth));
|
|
158
|
+
case 'em':
|
|
159
|
+
return c.italic(renderTokens(token.tokens ?? [], depth));
|
|
160
|
+
case 'codespan':
|
|
161
|
+
return c.hex(ACCENT)(token.text ?? '');
|
|
162
|
+
case 'br':
|
|
163
|
+
return NL;
|
|
164
|
+
case 'del':
|
|
165
|
+
return c.strikethrough.dim(renderTokens(token.tokens ?? [], depth));
|
|
166
|
+
case 'link':
|
|
167
|
+
if (token.href?.startsWith('mailto:')) {
|
|
168
|
+
return token.href.replace(/^mailto:/, '');
|
|
169
|
+
}
|
|
170
|
+
return `${c.hex(ACCENT).underline(renderTokens(token.tokens ?? [], depth))} (${c.dim(token.href ?? '')})`;
|
|
171
|
+
case 'image':
|
|
172
|
+
return token.text || token.href || '[image]';
|
|
173
|
+
case 'text': {
|
|
174
|
+
// Text tokens may have inline sub-tokens (e.g. inside a paragraph)
|
|
175
|
+
if (token.tokens && token.tokens.length > 0) {
|
|
176
|
+
return renderTokens(token.tokens, depth);
|
|
177
|
+
}
|
|
178
|
+
return token.text ?? '';
|
|
179
|
+
}
|
|
180
|
+
case 'escape':
|
|
181
|
+
return token.text ?? '';
|
|
182
|
+
default:
|
|
183
|
+
// Fallback — return raw text if available
|
|
184
|
+
return token.text ?? token.raw ?? '';
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Render an array of tokens into a single ANSI string.
|
|
189
|
+
*/
|
|
190
|
+
function renderTokens(tokens, depth = 0) {
|
|
191
|
+
return tokens.map((t) => renderToken(t, depth)).join('');
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Convert a Markdown string into ANSI-styled terminal text.
|
|
195
|
+
*
|
|
196
|
+
* Uses `marked.lexer()` to parse the Markdown into tokens, then renders
|
|
197
|
+
* each token recursively.
|
|
198
|
+
*/
|
|
199
|
+
export function renderMarkdown(text) {
|
|
200
|
+
if (!text)
|
|
201
|
+
return '';
|
|
202
|
+
try {
|
|
203
|
+
const tokens = marked.lexer(text);
|
|
204
|
+
const result = renderTokens(tokens);
|
|
205
|
+
// Trim trailing newlines but keep at most one
|
|
206
|
+
return result.replace(/\n{2,}$/g, '\n').trimEnd();
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
// If parsing fails (e.g. during streaming with very partial text),
|
|
210
|
+
// return the original text so the user at least sees something.
|
|
211
|
+
return text;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// ── Utility helpers ───────────────────────────────────────────────────
|
|
215
|
+
/**
|
|
216
|
+
* Strip ANSI escape codes from a string (for width calculation).
|
|
217
|
+
*/
|
|
218
|
+
function stripAnsi(str) {
|
|
219
|
+
return str.replace(/\x1B\[[0-9;]*m/g, '');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Pad a string to a visual width, accounting for ANSI codes.
|
|
223
|
+
*/
|
|
224
|
+
function padVisual(str, width) {
|
|
225
|
+
const visible = stripAnsi(str).length;
|
|
226
|
+
if (visible >= width)
|
|
227
|
+
return str;
|
|
228
|
+
return str + ' '.repeat(width - visible);
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=render-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-markdown.js","sourceRoot":"","sources":["../../src/ui/render-markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Primary accent — soft sky-blue */
|
|
2
|
+
export declare const ACCENT = "#89b4fa";
|
|
3
|
+
/** Muted / dimmed accent — for unselected or less prominent items */
|
|
4
|
+
export declare const ACCENT_DIM = "#6a8fc7";
|
|
5
|
+
/** Success / completed / diff-added — soft green */
|
|
6
|
+
export declare const SUCCESS = "#a6e3a1";
|
|
7
|
+
/** Warning / permission prompt / pending — warm yellow */
|
|
8
|
+
export declare const WARNING = "#f9e2af";
|
|
9
|
+
/** Error / denied / diff-removed — soft red-pink */
|
|
10
|
+
export declare const ERROR = "#f38ba8";
|
|
11
|
+
/** Muted elements — uses named ANSI gray for broad compatibility */
|
|
12
|
+
export declare const DIM = "gray";
|
|
13
|
+
//# sourceMappingURL=theme.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAOA,qCAAqC;AACrC,eAAO,MAAM,MAAM,YAAY,CAAA;AAE/B,qEAAqE;AACrE,eAAO,MAAM,UAAU,YAAY,CAAA;AAEnC,oDAAoD;AACpD,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,0DAA0D;AAC1D,eAAO,MAAM,OAAO,YAAY,CAAA;AAEhC,oDAAoD;AACpD,eAAO,MAAM,KAAK,YAAY,CAAA;AAE9B,oEAAoE;AACpE,eAAO,MAAM,GAAG,SAAS,CAAA"}
|
package/dist/ui/theme.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// @x-code/cli — Shared UI colour tokens
|
|
2
|
+
//
|
|
3
|
+
// Soft colour palette inspired by Claude Code's dark theme.
|
|
4
|
+
// All colours are hex values so they render consistently across terminals
|
|
5
|
+
// that support 24-bit colour (most modern terminals).
|
|
6
|
+
// Ink <Text color={...}> accepts hex strings natively.
|
|
7
|
+
/** Primary accent — soft sky-blue */
|
|
8
|
+
export const ACCENT = '#89b4fa';
|
|
9
|
+
/** Muted / dimmed accent — for unselected or less prominent items */
|
|
10
|
+
export const ACCENT_DIM = '#6a8fc7';
|
|
11
|
+
/** Success / completed / diff-added — soft green */
|
|
12
|
+
export const SUCCESS = '#a6e3a1';
|
|
13
|
+
/** Warning / permission prompt / pending — warm yellow */
|
|
14
|
+
export const WARNING = '#f9e2af';
|
|
15
|
+
/** Error / denied / diff-removed — soft red-pink */
|
|
16
|
+
export const ERROR = '#f38ba8';
|
|
17
|
+
/** Muted elements — uses named ANSI gray for broad compatibility */
|
|
18
|
+
export const DIM = 'gray';
|
|
19
|
+
//# sourceMappingURL=theme.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/ui/theme.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,EAAE;AACF,4DAA4D;AAC5D,0EAA0E;AAC1E,sDAAsD;AACtD,uDAAuD;AAEvD,qCAAqC;AACrC,MAAM,CAAC,MAAM,MAAM,GAAG,SAAS,CAAA;AAE/B,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAA;AAEnC,oDAAoD;AACpD,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,0DAA0D;AAC1D,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAA;AAEhC,oDAAoD;AACpD,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAA;AAE9B,oEAAoE;AACpE,MAAM,CAAC,MAAM,GAAG,GAAG,MAAM,CAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@x-code-cli/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"x-code": "dist/cli.js",
|
|
7
|
+
"xc": "dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"node": ">=20.19.0"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "node esbuild.config.js",
|
|
17
|
+
"dev": "tsx src/index.ts"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@x-code-cli/core": "workspace:*",
|
|
21
|
+
"chalk": "^5.4.0",
|
|
22
|
+
"diff": "^8.0.0",
|
|
23
|
+
"ink": "^6.6.0",
|
|
24
|
+
"marked": "^17.0.1",
|
|
25
|
+
"react": "^19.1.0",
|
|
26
|
+
"yargs": "^18.0.0"
|
|
27
|
+
}
|
|
28
|
+
}
|