@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.
Files changed (71) hide show
  1. package/dist/app.d.ts +6 -0
  2. package/dist/app.d.ts.map +1 -0
  3. package/dist/app.js +36 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/cli.js +180674 -0
  6. package/dist/cli.js.map +7 -0
  7. package/dist/config/index.d.ts +20 -0
  8. package/dist/config/index.d.ts.map +1 -0
  9. package/dist/config/index.js +18 -0
  10. package/dist/config/index.js.map +1 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +190 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/ui/components/App.d.ts +40 -0
  16. package/dist/ui/components/App.d.ts.map +1 -0
  17. package/dist/ui/components/App.js +196 -0
  18. package/dist/ui/components/App.js.map +1 -0
  19. package/dist/ui/components/AppHeader.d.ts +6 -0
  20. package/dist/ui/components/AppHeader.d.ts.map +1 -0
  21. package/dist/ui/components/AppHeader.js +51 -0
  22. package/dist/ui/components/AppHeader.js.map +1 -0
  23. package/dist/ui/components/ChatInput.d.ts +12 -0
  24. package/dist/ui/components/ChatInput.d.ts.map +1 -0
  25. package/dist/ui/components/ChatInput.js +107 -0
  26. package/dist/ui/components/ChatInput.js.map +1 -0
  27. package/dist/ui/components/MessageList.d.ts +7 -0
  28. package/dist/ui/components/MessageList.d.ts.map +1 -0
  29. package/dist/ui/components/MessageList.js +8 -0
  30. package/dist/ui/components/MessageList.js.map +1 -0
  31. package/dist/ui/components/Permission.d.ts +8 -0
  32. package/dist/ui/components/Permission.d.ts.map +1 -0
  33. package/dist/ui/components/Permission.js +104 -0
  34. package/dist/ui/components/Permission.js.map +1 -0
  35. package/dist/ui/components/SelectOptions.d.ts +12 -0
  36. package/dist/ui/components/SelectOptions.d.ts.map +1 -0
  37. package/dist/ui/components/SelectOptions.js +49 -0
  38. package/dist/ui/components/SelectOptions.js.map +1 -0
  39. package/dist/ui/components/ShellOutput.d.ts +6 -0
  40. package/dist/ui/components/ShellOutput.d.ts.map +1 -0
  41. package/dist/ui/components/ShellOutput.js +13 -0
  42. package/dist/ui/components/ShellOutput.js.map +1 -0
  43. package/dist/ui/components/Spinner.d.ts +6 -0
  44. package/dist/ui/components/Spinner.d.ts.map +1 -0
  45. package/dist/ui/components/Spinner.js +17 -0
  46. package/dist/ui/components/Spinner.js.map +1 -0
  47. package/dist/ui/components/StatusBar.d.ts +8 -0
  48. package/dist/ui/components/StatusBar.d.ts.map +1 -0
  49. package/dist/ui/components/StatusBar.js +8 -0
  50. package/dist/ui/components/StatusBar.js.map +1 -0
  51. package/dist/ui/components/StreamingText.d.ts +6 -0
  52. package/dist/ui/components/StreamingText.d.ts.map +1 -0
  53. package/dist/ui/components/StreamingText.js +46 -0
  54. package/dist/ui/components/StreamingText.js.map +1 -0
  55. package/dist/ui/components/ToolCall.d.ts +9 -0
  56. package/dist/ui/components/ToolCall.d.ts.map +1 -0
  57. package/dist/ui/components/ToolCall.js +29 -0
  58. package/dist/ui/components/ToolCall.js.map +1 -0
  59. package/dist/ui/hooks/use-agent.d.ts +46 -0
  60. package/dist/ui/hooks/use-agent.d.ts.map +1 -0
  61. package/dist/ui/hooks/use-agent.js +277 -0
  62. package/dist/ui/hooks/use-agent.js.map +1 -0
  63. package/dist/ui/render-markdown.d.ts +8 -0
  64. package/dist/ui/render-markdown.d.ts.map +1 -0
  65. package/dist/ui/render-markdown.js +230 -0
  66. package/dist/ui/render-markdown.js.map +1 -0
  67. package/dist/ui/theme.d.ts +13 -0
  68. package/dist/ui/theme.d.ts.map +1 -0
  69. package/dist/ui/theme.js +19 -0
  70. package/dist/ui/theme.js.map +1 -0
  71. 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"}
@@ -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
+ }