@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,20 @@
1
+ import type { AppConfig } from '@x-code/core';
2
+ export interface CliOptions {
3
+ model?: string;
4
+ trust: boolean;
5
+ print: boolean;
6
+ maxTurns: number;
7
+ prompt?: string;
8
+ }
9
+ /** Resolve all configuration from CLI args + env + config file */
10
+ export declare function resolveCliConfig(args: CliOptions): Promise<{
11
+ config: AppConfig;
12
+ modelId: string | null;
13
+ availableProviders: string[];
14
+ needsSetup: boolean;
15
+ trustMode: boolean;
16
+ printMode: boolean;
17
+ maxTurns: number;
18
+ }>;
19
+ export type { AppConfig };
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,kEAAkE;AAClE,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,UAAU;;;;;;;;GActD;AAED,YAAY,EAAE,SAAS,EAAE,CAAA"}
@@ -0,0 +1,18 @@
1
+ // @x-code/cli — CLI-level config helpers
2
+ import { getAvailableProviders, loadConfig, resolveModelId } from '@x-code/core';
3
+ /** Resolve all configuration from CLI args + env + config file */
4
+ export async function resolveCliConfig(args) {
5
+ const config = await loadConfig();
6
+ const modelId = resolveModelId(args.model, config);
7
+ const availableProviders = getAvailableProviders();
8
+ return {
9
+ config,
10
+ modelId,
11
+ availableProviders,
12
+ needsSetup: availableProviders.length === 0,
13
+ trustMode: args.trust,
14
+ printMode: args.print,
15
+ maxTurns: args.maxTurns,
16
+ };
17
+ }
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/config/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,OAAO,EAAE,qBAAqB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAWhF,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAgB;IACrD,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAA;IACjC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAClD,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAA;IAElD,OAAO;QACL,MAAM;QACN,OAAO;QACP,kBAAkB;QAClB,UAAU,EAAE,kBAAkB,CAAC,MAAM,KAAK,CAAC;QAC3C,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,SAAS,EAAE,IAAI,CAAC,KAAK;QACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAA;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,190 @@
1
+ // @x-code/cli — CLI entry point
2
+ import yargs from 'yargs';
3
+ import { hideBin } from 'yargs/helpers';
4
+ import fs from 'node:fs';
5
+ import path from 'node:path';
6
+ import { PROVIDER_DETECTION_ORDER, PROVIDER_KEY_URLS, VERSION, createModelRegistry, getAvailableProviders, getEnvVarName, loadConfig, resolveModelId, } from '@x-code/core';
7
+ import { getCleanupFn, printExitSummary, startApp } from './app.js';
8
+ const MIN_NODE_VERSION = [20, 19, 0];
9
+ function checkNodeVersion() {
10
+ const [major, minor, patch] = process.versions.node.split('.').map(Number);
11
+ const [reqMajor, reqMinor, reqPatch] = MIN_NODE_VERSION;
12
+ if (major < reqMajor ||
13
+ (major === reqMajor && minor < reqMinor) ||
14
+ (major === reqMajor && minor === reqMinor && patch < reqPatch)) {
15
+ console.error(`Error: X-Code CLI requires Node.js >= ${MIN_NODE_VERSION.join('.')}, but you are running ${process.versions.node}.\n` +
16
+ 'Please upgrade Node.js: https://nodejs.org/');
17
+ process.exit(1);
18
+ }
19
+ }
20
+ async function main() {
21
+ checkNodeVersion();
22
+ loadEnvFile();
23
+ // Parse CLI arguments
24
+ const argv = await yargs(hideBin(process.argv))
25
+ .scriptName('x-code')
26
+ .usage('$0 [options] [prompt]')
27
+ .option('model', {
28
+ alias: 'm',
29
+ type: 'string',
30
+ describe: 'Model to use (e.g. sonnet, deepseek, openai:gpt-4.1)',
31
+ })
32
+ .option('trust', {
33
+ alias: 't',
34
+ type: 'boolean',
35
+ default: false,
36
+ describe: 'Trust mode: skip write operation confirmations',
37
+ })
38
+ .option('print', {
39
+ alias: 'p',
40
+ type: 'boolean',
41
+ default: false,
42
+ describe: 'Non-interactive mode: output result and exit',
43
+ })
44
+ .option('max-turns', {
45
+ type: 'number',
46
+ default: 100,
47
+ describe: 'Maximum agent loop turns',
48
+ })
49
+ .version(VERSION)
50
+ .alias('v', 'version')
51
+ .help()
52
+ .alias('h', 'help')
53
+ .parse();
54
+ const prompt = argv._.join(' ') || undefined;
55
+ // Check for stdin pipe input
56
+ let stdinContent = '';
57
+ if (!process.stdin.isTTY) {
58
+ stdinContent = await readStdin();
59
+ }
60
+ // Load config (for model preference only; API keys come from env vars)
61
+ const config = await loadConfig();
62
+ const availableProviders = getAvailableProviders();
63
+ // If no providers configured, show helpful message and exit
64
+ if (availableProviders.length === 0) {
65
+ printNoApiKeyMessage();
66
+ process.exit(1);
67
+ }
68
+ // Resolve model
69
+ const modelId = resolveModelId(argv.model, config);
70
+ if (!modelId) {
71
+ // User specified a model whose provider has no key
72
+ const requested = argv.model;
73
+ if (requested) {
74
+ const provider = requested.split(':')[0];
75
+ const envVar = getEnvVarName(provider) ?? `${provider.toUpperCase()}_API_KEY`;
76
+ console.error(`Error: ${envVar} is not set. Please set this environment variable to use ${requested}.`);
77
+ }
78
+ else {
79
+ printNoApiKeyMessage();
80
+ }
81
+ process.exit(1);
82
+ }
83
+ // Create registry and get model
84
+ const registry = createModelRegistry();
85
+ const model = registry.languageModel(modelId);
86
+ const options = {
87
+ modelId,
88
+ trustMode: argv.trust,
89
+ printMode: argv.print,
90
+ maxTurns: argv['max-turns'] ?? 100,
91
+ };
92
+ // Combine prompt with stdin
93
+ const fullPrompt = [stdinContent, prompt].filter(Boolean).join('\n\n');
94
+ // Start the app
95
+ const waitUntilExit = startApp(model, options, fullPrompt || undefined);
96
+ await waitUntilExit();
97
+ // Print session usage summary after Ink unmounts
98
+ printExitSummary();
99
+ }
100
+ /** Load .env file from cwd (walk up to find it, like dotenv convention) */
101
+ function loadEnvFile() {
102
+ let dir = process.cwd();
103
+ while (true) {
104
+ const envPath = path.join(dir, '.env');
105
+ if (fs.existsSync(envPath)) {
106
+ try {
107
+ process.loadEnvFile(envPath);
108
+ }
109
+ catch {
110
+ // Ignore parse errors
111
+ }
112
+ return;
113
+ }
114
+ const parent = path.dirname(dir);
115
+ if (parent === dir)
116
+ break; // reached root
117
+ dir = parent;
118
+ }
119
+ }
120
+ function printNoApiKeyMessage() {
121
+ const isWindows = process.platform === 'win32';
122
+ console.error('Error: No API key found.\n');
123
+ console.error('Option 1: Create a .env file in your project root:\n');
124
+ console.error(' cp .env.example .env');
125
+ console.error(' # Edit .env and fill in your API key\n');
126
+ console.error('Option 2: Set an environment variable:\n');
127
+ for (const { envKey } of PROVIDER_DETECTION_ORDER) {
128
+ const provider = envKey
129
+ .replace(/_API_KEY$/, '')
130
+ .replace('GOOGLE_GENERATIVE_AI', 'google')
131
+ .replace('MOONSHOT', 'moonshotai')
132
+ .toLowerCase();
133
+ const url = PROVIDER_KEY_URLS[provider] ?? '';
134
+ console.error(` ${envKey.padEnd(32)} ${url}`);
135
+ }
136
+ console.error(`\n OPENAI_COMPATIBLE_API_KEY (custom OpenAI-compatible endpoint)`);
137
+ if (isWindows) {
138
+ console.error('\nExample (PowerShell):');
139
+ console.error(' $env:ANTHROPIC_API_KEY="sk-ant-..."');
140
+ console.error(' xc');
141
+ }
142
+ else {
143
+ console.error('\nExample:');
144
+ console.error(' export ANTHROPIC_API_KEY=sk-ant-...');
145
+ console.error(' xc');
146
+ }
147
+ }
148
+ function readStdin() {
149
+ return new Promise((resolve) => {
150
+ let data = '';
151
+ process.stdin.setEncoding('utf-8');
152
+ process.stdin.on('data', (chunk) => {
153
+ data += chunk;
154
+ });
155
+ process.stdin.on('end', () => {
156
+ resolve(data);
157
+ });
158
+ // Timeout for stdin — don't hang forever
159
+ setTimeout(() => resolve(data), 1000);
160
+ });
161
+ }
162
+ // Handle Ctrl+C gracefully — save session before exit
163
+ let sigintCount = 0;
164
+ process.on('SIGINT', () => {
165
+ sigintCount++;
166
+ if (sigintCount >= 2) {
167
+ // Force exit on second Ctrl+C
168
+ process.exit(1);
169
+ }
170
+ const cleanup = getCleanupFn();
171
+ if (cleanup) {
172
+ cleanup()
173
+ .catch(() => {
174
+ // Don't crash on cleanup failure
175
+ })
176
+ .finally(() => {
177
+ printExitSummary();
178
+ process.exit(0);
179
+ });
180
+ }
181
+ else {
182
+ printExitSummary();
183
+ process.exit(0);
184
+ }
185
+ });
186
+ main().catch((err) => {
187
+ console.error('Fatal error:', err);
188
+ process.exit(1);
189
+ });
190
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { AgentOptions, LanguageModel } from '@x-code/core';
2
+ interface AppProps {
3
+ model: LanguageModel;
4
+ options: AgentOptions;
5
+ initialPrompt?: string;
6
+ onCleanupReady?: (fn: () => Promise<void>) => void;
7
+ onUsageUpdate?: (usage: import('@x-code/core').TokenUsage, modelId: string) => void;
8
+ }
9
+ /** Slash commands — used for both help text and tab completion */
10
+ export declare const SLASH_COMMANDS: readonly [{
11
+ readonly name: "/help";
12
+ readonly description: "Show this help message";
13
+ }, {
14
+ readonly name: "/model";
15
+ readonly description: "Switch model or list available models";
16
+ }, {
17
+ readonly name: "/usage";
18
+ readonly description: "Show token usage and cost";
19
+ }, {
20
+ readonly name: "/clear";
21
+ readonly description: "Clear conversation history";
22
+ }, {
23
+ readonly name: "/compact";
24
+ readonly description: "Manually compress context";
25
+ }, {
26
+ readonly name: "/init";
27
+ readonly description: "Initialize project knowledge";
28
+ }, {
29
+ readonly name: "/session save";
30
+ readonly description: "Save current session";
31
+ }, {
32
+ readonly name: "/plan";
33
+ readonly description: "Enter plan mode";
34
+ }, {
35
+ readonly name: "/exit";
36
+ readonly description: "Exit (saves session)";
37
+ }];
38
+ export declare function App({ model, options, initialPrompt, onCleanupReady, onUsageUpdate }: AppProps): import("react/jsx-runtime").JSX.Element;
39
+ export {};
40
+ //# sourceMappingURL=App.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.d.ts","sourceRoot":"","sources":["../../../src/ui/components/App.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAa/D,UAAU,QAAQ;IAChB,KAAK,EAAE,aAAa,CAAA;IACpB,OAAO,EAAE,YAAY,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,CAAA;IAClD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,cAAc,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACpF;AAED,kEAAkE;AAClE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUjB,CAAA;AAQV,wBAAgB,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,EAAE,QAAQ,2CAmR7F"}
@@ -0,0 +1,196 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ // @x-code/cli — Root App component
3
+ import { useEffect } from 'react';
4
+ import { Box, Text, useApp, useInput } from 'ink';
5
+ import { MODEL_ALIASES, VERSION, createModelRegistry, initProject, loadConfig, resolveModelId } from '@x-code/core';
6
+ import { useAgent } from '../hooks/use-agent.js';
7
+ import { ACCENT, ERROR, WARNING } from '../theme.js';
8
+ import { ChatInput } from './ChatInput.js';
9
+ import { MessageList } from './MessageList.js';
10
+ import { Permission } from './Permission.js';
11
+ import { SelectOptions } from './SelectOptions.js';
12
+ import { ShellOutput } from './ShellOutput.js';
13
+ import { Spinner } from './Spinner.js';
14
+ import { StreamingText } from './StreamingText.js';
15
+ import { ToolCall } from './ToolCall.js';
16
+ /** Slash commands — used for both help text and tab completion */
17
+ export const SLASH_COMMANDS = [
18
+ { name: '/help', description: 'Show this help message' },
19
+ { name: '/model', description: 'Switch model or list available models' },
20
+ { name: '/usage', description: 'Show token usage and cost' },
21
+ { name: '/clear', description: 'Clear conversation history' },
22
+ { name: '/compact', description: 'Manually compress context' },
23
+ { name: '/init', description: 'Initialize project knowledge' },
24
+ { name: '/session save', description: 'Save current session' },
25
+ { name: '/plan', description: 'Enter plan mode' },
26
+ { name: '/exit', description: 'Exit (saves session)' },
27
+ ];
28
+ const HELP_TEXT = `X-Code CLI v${VERSION}\n\n` +
29
+ SLASH_COMMANDS.map((c) => ` ${c.name.padEnd(16)} ${c.description}`).join('\n') +
30
+ `\n\nModel aliases: ${Object.keys(MODEL_ALIASES).join(', ')}` +
31
+ `\nKeyboard: Ctrl+C to abort current operation`;
32
+ export function App({ model, options, initialPrompt, onCleanupReady, onUsageUpdate }) {
33
+ const { exit } = useApp();
34
+ const { state, submit, resolvePermission, resolveQuestion, cleanup, clear, compact, switchModel, saveCurrentSession, dismissSession, addInfoMessage, addUserMessage, } = useAgent(model, options);
35
+ // Register cleanup function for graceful exit (SIGINT)
36
+ useEffect(() => {
37
+ onCleanupReady?.(cleanup);
38
+ }, [cleanup]); // eslint-disable-line react-hooks/exhaustive-deps
39
+ // Sync usage to the global ref so exit handler can print it
40
+ useEffect(() => {
41
+ onUsageUpdate?.(state.usage, options.modelId);
42
+ }, [state.usage, options.modelId]); // eslint-disable-line react-hooks/exhaustive-deps
43
+ // Handle initial prompt
44
+ useEffect(() => {
45
+ if (initialPrompt) {
46
+ submit(initialPrompt);
47
+ }
48
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
49
+ // Handle print mode — exit after first response
50
+ useEffect(() => {
51
+ if (options.printMode && !state.isLoading && state.messages.length > 1) {
52
+ cleanup().then(() => exit());
53
+ }
54
+ }, [state.isLoading, state.messages.length, options.printMode]); // eslint-disable-line react-hooks/exhaustive-deps
55
+ // Handle session continuation Y/N
56
+ useInput((input) => {
57
+ if (!state.latestSession)
58
+ return;
59
+ if (input.toLowerCase() === 'y') {
60
+ const session = state.latestSession;
61
+ dismissSession();
62
+ const pendingList = session.pendingWork.map((w) => `- ${w}`).join('\n');
63
+ submit(`Continue from previous session "${session.title}".\nPending work:\n${pendingList}\n\nPlease continue where we left off.`);
64
+ }
65
+ else if (input.toLowerCase() === 'n' || input === '\r') {
66
+ dismissSession();
67
+ }
68
+ }, {
69
+ isActive: !!state.latestSession && !state.isLoading && !state.pendingPermission && !state.pendingQuestion,
70
+ });
71
+ /** Echo a slash command to the message history (so the user can see what they typed) */
72
+ function echoCommand(text) {
73
+ addUserMessage(text);
74
+ }
75
+ /** Handle user input (including slash commands) */
76
+ async function handleSubmit(text) {
77
+ // Slash commands
78
+ if (text.startsWith('/')) {
79
+ const parts = text.slice(1).trim().split(/\s+/);
80
+ const command = parts[0].toLowerCase();
81
+ const arg = parts.slice(1).join(' ');
82
+ switch (command) {
83
+ case 'help':
84
+ echoCommand(text);
85
+ addInfoMessage(HELP_TEXT);
86
+ return;
87
+ case 'model':
88
+ echoCommand(text);
89
+ await handleModelSwitch(arg);
90
+ return;
91
+ case 'usage':
92
+ echoCommand(text);
93
+ handleUsage();
94
+ return;
95
+ case 'clear':
96
+ clear();
97
+ addInfoMessage('Conversation cleared.');
98
+ return;
99
+ case 'compact':
100
+ echoCommand(text);
101
+ await handleCompact();
102
+ return;
103
+ case 'init':
104
+ echoCommand(text);
105
+ await handleInit();
106
+ return;
107
+ case 'session':
108
+ echoCommand(text);
109
+ if (arg.toLowerCase() === 'save') {
110
+ await handleSessionSave();
111
+ }
112
+ else {
113
+ addInfoMessage('Unknown session command. Use `/session save`.');
114
+ }
115
+ return;
116
+ case 'plan':
117
+ await submit('Please enter plan mode to explore the codebase and design an implementation plan before making changes.');
118
+ return;
119
+ case 'exit':
120
+ await cleanup();
121
+ exit();
122
+ return;
123
+ default:
124
+ echoCommand(text);
125
+ addInfoMessage(`Unknown command: /${command}. Type /help for available commands.`);
126
+ return;
127
+ }
128
+ }
129
+ await submit(text);
130
+ }
131
+ async function handleModelSwitch(arg) {
132
+ if (!arg) {
133
+ // List available models
134
+ const _config = await loadConfig();
135
+ const aliases = Object.entries(MODEL_ALIASES)
136
+ .map(([alias, id]) => ` ${alias} → ${id}`)
137
+ .join('\n');
138
+ addInfoMessage(`Current model: ${options.modelId}\n\nAvailable aliases:\n${aliases}`);
139
+ return;
140
+ }
141
+ try {
142
+ const config = await loadConfig();
143
+ const newModelId = resolveModelId(arg, config);
144
+ if (!newModelId) {
145
+ addInfoMessage(`Could not resolve model: ${arg}`);
146
+ return;
147
+ }
148
+ const registry = createModelRegistry();
149
+ const newModel = registry.languageModel(newModelId);
150
+ switchModel(newModelId, newModel);
151
+ addInfoMessage(`Model switched to: ${newModelId}`);
152
+ }
153
+ catch (err) {
154
+ addInfoMessage(`Failed to switch model: ${err instanceof Error ? err.message : String(err)}`);
155
+ }
156
+ }
157
+ function handleUsage() {
158
+ const { usage } = state;
159
+ const symbol = usage.costCurrency === 'CNY' ? '¥' : '$';
160
+ const costStr = usage.estimatedCost > 0 ? `${symbol}${usage.estimatedCost.toFixed(4)}` : 'N/A';
161
+ addInfoMessage(`Token Usage\n` +
162
+ ` Input: ${usage.inputTokens.toLocaleString()} tokens\n` +
163
+ ` Output: ${usage.outputTokens.toLocaleString()} tokens\n` +
164
+ ` Total: ${usage.totalTokens.toLocaleString()} tokens\n` +
165
+ ` Cost: ${costStr}\n` +
166
+ ` Model: ${options.modelId}`);
167
+ }
168
+ async function handleCompact() {
169
+ addInfoMessage('Compressing context...');
170
+ await compact();
171
+ addInfoMessage('Context compressed.');
172
+ }
173
+ async function handleInit() {
174
+ addInfoMessage('Analyzing project structure...');
175
+ try {
176
+ const result = await initProject();
177
+ const factLines = result.detectedFacts.map((f) => ` - ${f}`).join('\n');
178
+ const fileLines = result.createdFiles.map((f) => ` - ${f}`).join('\n');
179
+ addInfoMessage(`**Project initialized**\n\nDetected:\n${factLines}\n\nCreated:\n${fileLines || ' (no new files)'}`);
180
+ }
181
+ catch (err) {
182
+ addInfoMessage(`Init failed: ${err instanceof Error ? err.message : String(err)}`);
183
+ }
184
+ }
185
+ async function handleSessionSave() {
186
+ const saved = await saveCurrentSession();
187
+ if (saved) {
188
+ addInfoMessage('Session saved.');
189
+ }
190
+ else {
191
+ addInfoMessage('No active session to save.');
192
+ }
193
+ }
194
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [state.latestSession && !state.isLoading && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: ACCENT, paddingX: 1, marginBottom: 1, children: [_jsxs(Text, { color: ACCENT, bold: true, children: ["Previous session: \"", state.latestSession.title, "\" (", state.latestSession.status, ")"] }), state.latestSession.pendingWork.length > 0 && (_jsxs(Box, { flexDirection: "column", marginLeft: 2, children: [_jsx(Text, { dimColor: true, children: "Pending work:" }), state.latestSession.pendingWork.map((w, i) => (_jsxs(Text, { dimColor: true, children: ["- ", w] }, i)))] })), _jsx(Text, { color: WARNING, children: "Continue previous session? (y/n)" })] })), _jsx(MessageList, { messages: state.messages }), state.streamingText && _jsx(StreamingText, { text: state.streamingText }), state.currentToolCall && !state.pendingPermission && (_jsx(ToolCall, { toolName: state.currentToolCall.toolName, input: state.currentToolCall.input, status: "running" })), state.shellOutput && _jsx(ShellOutput, { output: state.shellOutput }), state.pendingPermission && (_jsx(Permission, { toolName: state.pendingPermission.toolName, input: state.pendingPermission.input, onResolve: resolvePermission })), state.pendingQuestion && (_jsx(SelectOptions, { question: state.pendingQuestion.question, options: state.pendingQuestion.options, onSelect: resolveQuestion })), state.isLoading && !state.streamingText && !state.currentToolCall && _jsx(Spinner, {}), state.error && _jsxs(Text, { color: ERROR, children: ["Error: ", state.error] }), !state.latestSession && (_jsx(ChatInput, { onSubmit: handleSubmit, disabled: state.isLoading || !!state.pendingPermission || !!state.pendingQuestion, commands: SLASH_COMMANDS }))] }));
195
+ }
196
+ //# sourceMappingURL=App.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"App.js","sourceRoot":"","sources":["../../../src/ui/components/App.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Print the startup header banner directly to stdout.
3
+ * Call this ONCE before Ink's render() so it is never re-drawn.
4
+ */
5
+ export declare function printHeader(modelId: string): void;
6
+ //# sourceMappingURL=AppHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../../src/ui/components/AppHeader.tsx"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAyBjD"}
@@ -0,0 +1,51 @@
1
+ // @x-code/cli — Startup header banner
2
+ //
3
+ // printHeader() writes the banner directly to stdout BEFORE Ink starts.
4
+ // This avoids the Ink <Static> re-render bug where the header would
5
+ // appear multiple times as the dynamic area changes height.
6
+ import { Chalk } from 'chalk';
7
+ import { VERSION } from '@x-code/core';
8
+ import { ACCENT } from '../theme.js';
9
+ const c = new Chalk({ level: 3 });
10
+ // ── ASCII logos for different terminal widths ──
11
+ const LOGO_WIDE = `
12
+ ██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗
13
+ ╚██╗██╔╝ ██╔════╝██╔═══██╗██╔══██╗██╔════╝
14
+ ╚███╔╝ █████╗██║ ██║ ██║██║ ██║█████╗
15
+ ██╔██╗ ╚════╝██║ ██║ ██║██║ ██║██╔══╝
16
+ ██╔╝ ██╗ ╚██████╗╚██████╔╝██████╔╝███████╗
17
+ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝`;
18
+ const LOGO_COMPACT = `
19
+ ╔═╗ ╔═╗╔═╗╔╦╗╔═╗
20
+ ╔╩╦╝ ───── ║ ║ ║ ║║║╣
21
+ ╩ ╚═ ╚═╝╚═╝═╩╝╚═╝`;
22
+ const LOGO_TINY = ' X-Code';
23
+ /**
24
+ * Print the startup header banner directly to stdout.
25
+ * Call this ONCE before Ink's render() so it is never re-drawn.
26
+ */
27
+ export function printHeader(modelId) {
28
+ const cols = process.stdout.columns ?? 80;
29
+ // Pick logo based on terminal width
30
+ let logo;
31
+ if (cols >= 52) {
32
+ logo = LOGO_WIDE;
33
+ }
34
+ else if (cols >= 30) {
35
+ logo = LOGO_COMPACT;
36
+ }
37
+ else {
38
+ logo = LOGO_TINY;
39
+ }
40
+ // Extract provider and model from "provider:model-name"
41
+ const [provider, ...modelParts] = modelId.split(':');
42
+ const modelName = modelParts.join(':') || modelId;
43
+ const lines = [
44
+ c.hex(ACCENT).bold(logo),
45
+ ` ${c.dim(`v${VERSION}`)} ${c.dim('│')} ${c.hex(ACCENT)(provider)} ${c.dim('/')} ${c.hex(ACCENT).bold(modelName)}`,
46
+ ` ${c.dim('Type /help for commands, Ctrl+C to abort')}`,
47
+ '', // blank line after header
48
+ ];
49
+ process.stdout.write(lines.join('\n') + '\n');
50
+ }
51
+ //# sourceMappingURL=AppHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppHeader.js","sourceRoot":"","sources":["../../../src/ui/components/AppHeader.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,wEAAwE;AACxE,oEAAoE;AACpE,4DAA4D;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEpC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;AAEjC,kDAAkD;AAElD,MAAM,SAAS,GAAG;;;;;;kDAMgC,CAAA;AAElD,MAAM,YAAY,GAAG;;;0BAGK,CAAA;AAE1B,MAAM,SAAS,GAAG,UAAU,CAAA;AAE5B;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAA;IAEzC,oCAAoC;IACpC,IAAI,IAAY,CAAA;IAChB,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QACf,IAAI,GAAG,SAAS,CAAA;IAClB,CAAC;SAAM,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,CAAA;IACrB,CAAC;SAAM,CAAC;QACN,IAAI,GAAG,SAAS,CAAA;IAClB,CAAC;IAED,wDAAwD;IACxD,MAAM,CAAC,QAAQ,EAAE,GAAG,UAAU,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACpD,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,OAAO,CAAA;IAEjD,MAAM,KAAK,GAAG;QACZ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;QAClH,IAAI,CAAC,CAAC,GAAG,CAAC,0CAA0C,CAAC,EAAE;QACvD,EAAE,EAAE,0BAA0B;KAC/B,CAAA;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface SlashCommand {
2
+ name: string;
3
+ description: string;
4
+ }
5
+ interface ChatInputProps {
6
+ onSubmit: (text: string) => void;
7
+ disabled?: boolean;
8
+ commands?: readonly SlashCommand[];
9
+ }
10
+ export declare function ChatInput({ onSubmit, disabled, commands }: ChatInputProps): import("react/jsx-runtime").JSX.Element | null;
11
+ export {};
12
+ //# sourceMappingURL=ChatInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../src/ui/components/ChatInput.tsx"],"names":[],"mappings":"AAeA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,UAAU,cAAc;IACtB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;CACnC;AAED,wBAAgB,SAAS,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAa,EAAE,EAAE,cAAc,kDAgI9E"}