travel-agent-cli 0.3.6 → 0.4.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/bin/cli.js CHANGED
@@ -5,22 +5,43 @@
5
5
  * 该脚本作为 npm 包的入口,调用 Python 实现的 main.py
6
6
  */
7
7
 
8
- const { spawn } = require('child_process');
9
- const path = require('path');
10
- const fs = require('fs');
8
+ import { spawn } from 'child_process';
9
+ import path from 'path';
10
+ import fs from 'fs';
11
+ import { fileURLToPath } from 'url';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = path.dirname(__filename);
11
15
 
12
16
  // 获取包的安装路径
13
17
  const packagePath = path.join(__dirname, '..');
14
18
  const pythonDir = path.join(packagePath, 'python');
15
19
  const mainPy = path.join(pythonDir, 'main.py');
16
20
 
21
+ // 检查虚拟环境是否存在
22
+ function getVenvPython() {
23
+ const venvPaths = [
24
+ path.join(pythonDir, 'venv', 'bin', 'python'),
25
+ path.join(pythonDir, '.venv', 'bin', 'python'),
26
+ path.join(pythonDir, 'venv', 'Scripts', 'python.exe'),
27
+ ];
28
+
29
+ for (const venvPath of venvPaths) {
30
+ if (fs.existsSync(venvPath)) {
31
+ return venvPath;
32
+ }
33
+ }
34
+
35
+ return null;
36
+ }
37
+
17
38
  // 检查 Python 是否可用
18
39
  function findPython() {
19
40
  const candidates = ['python3', 'python'];
20
41
 
21
42
  for (const cmd of candidates) {
22
43
  try {
23
- const { execSync } = require('child_process');
44
+ const { execSync } = await import('child_process');
24
45
  execSync(`${cmd} --version`, { stdio: 'ignore' });
25
46
  return cmd;
26
47
  } catch (e) {
@@ -31,21 +52,29 @@ function findPython() {
31
52
  return null;
32
53
  }
33
54
 
34
- // 检查虚拟环境是否存在
35
- function getVenvPython() {
36
- const venvPaths = [
37
- path.join(pythonDir, 'venv', 'bin', 'python'),
38
- path.join(pythonDir, '.venv', 'bin', 'python'),
39
- path.join(pythonDir, 'venv', 'Scripts', 'python.exe'),
40
- ];
55
+ // 启动 Ink 交互式 CLI
56
+ function runInteractive() {
57
+ const interactiveJs = path.join(packagePath, 'interactive.jsx');
41
58
 
42
- for (const venvPath of venvPaths) {
43
- if (fs.existsSync(venvPath)) {
44
- return venvPath;
45
- }
59
+ if (!fs.existsSync(interactiveJs)) {
60
+ console.error(`错误:未找到 interactive.jsx 文件:${interactiveJs}`);
61
+ process.exit(1);
46
62
  }
47
63
 
48
- return null;
64
+ // 使用 tsx 运行 JSX
65
+ const child = spawn('node', ['--import', 'tsx', interactiveJs], {
66
+ stdio: 'inherit',
67
+ cwd: packagePath
68
+ });
69
+
70
+ child.on('error', (err) => {
71
+ console.error('执行失败:', err.message);
72
+ process.exit(1);
73
+ });
74
+
75
+ child.on('exit', (code) => {
76
+ process.exit(code || 0);
77
+ });
49
78
  }
50
79
 
51
80
  // 主函数
@@ -64,24 +93,21 @@ function run() {
64
93
  travel-agent <command> [options]
65
94
 
66
95
  可用命令:
67
- run 运行完整工作流(数据采集 → 分析评分 → 路线规划 → 报告生成)
68
- analyze 分析旅行产品可行性(市场调研 → 资源评估 → 生成报告)
96
+ run 运行完整工作流
97
+ analyze 产品可行性分析
69
98
  agents 查看 Agent 团队信息
70
- status 显示系统状态(版本、模型、API 配置)
71
- model 管理 LLM 模型配置(list/status/use)
72
- config 管理配置(--show/--init)
73
- flyai FlyAI 旅行搜索(航班/酒店/景点)
99
+ status 显示系统状态
100
+ model 管理 LLM 模型配置
101
+ config 管理配置
102
+ flyai FlyAI 旅行搜索
74
103
  interactive 启动交互式 CLI(推荐)
75
104
  help 显示帮助信息
76
105
 
77
106
  示例:
78
- travel-agent interactive # 启动交互式 CLI(推荐)
79
- travel-agent run -k "海岛游" # 搜索海岛游推荐
80
- travel-agent analyze "北欧极光" # 分析极光旅行产品
81
- travel-agent flyai "5 天日本行程规划" # FlyAI 旅行搜索
82
- travel-agent agents # 查看 Agent 团队
83
- travel-agent model list # 查看支持的模型
84
- travel-agent --help # 显示帮助
107
+ travel-agent interactive # 启动交互式 CLI
108
+ travel-agent run -k "海岛游"
109
+ travel-agent analyze "北欧极光"
110
+ travel-agent flyai "5 天日本行程规划"
85
111
 
86
112
  选项:
87
113
  -h, --help 显示帮助信息
@@ -93,17 +119,23 @@ function run() {
93
119
 
94
120
  // 版本信息
95
121
  if (args.includes('-v') || args.includes('--version')) {
96
- const pkg = require(path.join(__dirname, '..', 'package.json'));
122
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
97
123
  console.log(`travel-agent-cli v${pkg.version}`);
98
124
  process.exit(0);
99
125
  }
100
126
 
127
+ // 检查 interactive 命令
128
+ if (args[0] === 'interactive') {
129
+ runInteractive();
130
+ return;
131
+ }
132
+
101
133
  // 优先使用虚拟环境的 Python
102
134
  let pythonCmd = getVenvPython();
103
135
 
104
136
  // 如果没有虚拟环境,使用系统 Python
105
137
  if (!pythonCmd) {
106
- pythonCmd = findPython();
138
+ pythonCmd = await findPython();
107
139
  }
108
140
 
109
141
  if (!pythonCmd) {
@@ -112,30 +144,6 @@ function run() {
112
144
  process.exit(1);
113
145
  }
114
146
 
115
- // 检查 interactive 命令
116
- const interactivePy = path.join(pythonDir, 'interactive.py');
117
- if (args[0] === 'interactive') {
118
- if (!fs.existsSync(interactivePy)) {
119
- console.error(`错误:未找到 interactive.py 文件:${interactivePy}`);
120
- process.exit(1);
121
- }
122
- const pyArgs = [interactivePy, ...args.slice(1)];
123
- const child = spawn(pythonCmd, pyArgs, {
124
- stdio: 'inherit',
125
- cwd: pythonDir
126
- });
127
-
128
- child.on('error', (err) => {
129
- console.error('执行失败:', err.message);
130
- process.exit(1);
131
- });
132
-
133
- child.on('exit', (code) => {
134
- process.exit(code || 0);
135
- });
136
- return;
137
- }
138
-
139
147
  // 检查主文件是否存在
140
148
  if (!fs.existsSync(mainPy)) {
141
149
  console.error(`错误:未找到 main.py 文件:${mainPy}`);
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * travel-agent 交互式 CLI - Ink 版本
4
+ * 基于 React/Ink 实现,类似 Claude Code 的交互方式
5
+ */
6
+ import React, { useState, useEffect } from 'react';
7
+ import { render, Box, Text, useApp, useInput } from 'ink';
8
+ import TextInput from 'ink-text-input';
9
+ import chalk from 'chalk';
10
+
11
+ // 命令选项
12
+ const commands = [
13
+ { label: 'run - 运行完整工作流', value: 'run' },
14
+ { label: 'flyai - FlyAI 旅行搜索', value: 'flyai' },
15
+ { label: 'analyze - 产品可行性分析', value: 'analyze' },
16
+ { label: 'model - 模型管理', value: 'model' },
17
+ { label: 'config - 配置管理', value: 'config' },
18
+ { label: 'status - 系统状态', value: 'status' },
19
+ { label: 'agents - 查看 Agent 团队', value: 'agents' },
20
+ { label: 'help - 帮助信息', value: 'help' },
21
+ ];
22
+
23
+ // 主应用组件
24
+ function App() {
25
+ const { exit } = useApp();
26
+ const [input, setInput] = useState('');
27
+ const [messages, setMessages] = useState([
28
+ { type: 'system', content: '欢迎使用 travel-agent 交互式 CLI' },
29
+ { type: 'system', content: '' },
30
+ { type: 'system', content: '可用命令:' },
31
+ { type: 'info', content: ' /run - 运行完整工作流' },
32
+ { type: 'info', content: ' /flyai - FlyAI 旅行搜索' },
33
+ { type: 'info', content: ' /analyze - 产品可行性分析' },
34
+ { type: 'info', content: ' /model - 模型管理' },
35
+ { type: 'info', content: ' /config - 配置管理' },
36
+ { type: 'info', content: ' /status - 系统状态' },
37
+ { type: 'info', content: ' /agents - 查看 Agent 团队' },
38
+ { type: 'system', content: '' },
39
+ { type: 'system', content: '快捷键:Ctrl+C 退出,Ctrl+L 清屏,/ 打开命令面板' },
40
+ { type: 'system', content: '' },
41
+ ]);
42
+ const [isProcessing, setIsProcessing] = useState(false);
43
+ const [showCommandPalette, setShowCommandPalette] = useState(false);
44
+ const [commandInput, setCommandInput] = useState('');
45
+ const [filteredCommands, setFilteredCommands] = useState(commands);
46
+ const [selectedCommandIndex, setSelectedCommandIndex] = useState(0);
47
+
48
+ // 处理键盘输入
49
+ useInput((inputChar, key) => {
50
+ // Ctrl+C 退出
51
+ if (key.ctrl && inputChar === 'c') {
52
+ exit();
53
+ }
54
+
55
+ // Ctrl+L 清屏
56
+ if (key.ctrl && inputChar === 'l') {
57
+ setMessages([
58
+ { type: 'system', content: '欢迎使用 travel-agent 交互式 CLI' },
59
+ { type: 'system', content: '' },
60
+ ]);
61
+ }
62
+
63
+ // / 打开命令面板
64
+ if (inputChar === '/' && !showCommandPalette) {
65
+ setShowCommandPalette(true);
66
+ setCommandInput('');
67
+ setFilteredCommands(commands);
68
+ setSelectedCommandIndex(0);
69
+ return; // 阻止字符输入到 TextInput
70
+ }
71
+
72
+ // Esc 关闭命令面板
73
+ if (key.escape && showCommandPalette) {
74
+ setShowCommandPalette(false);
75
+ setCommandInput('');
76
+ return;
77
+ }
78
+
79
+ // 命令面板导航
80
+ if (showCommandPalette) {
81
+ if (key.upArrow) {
82
+ setSelectedCommandIndex(prev => Math.max(0, prev - 1));
83
+ return;
84
+ }
85
+ if (key.downArrow) {
86
+ setSelectedCommandIndex(prev => Math.min(filteredCommands.length - 1, prev + 1));
87
+ return;
88
+ }
89
+ // Enter 提交
90
+ if (key.return && filteredCommands.length > 0) {
91
+ const selected = filteredCommands[selectedCommandIndex];
92
+ setInput('/' + selected.value);
93
+ setShowCommandPalette(false);
94
+ setCommandInput('');
95
+ return;
96
+ }
97
+ }
98
+ });
99
+
100
+ // 处理命令提交
101
+ const handleSubmit = async (value) => {
102
+ if (!value.trim()) return;
103
+
104
+ const userMsg = { type: 'user', content: value };
105
+ setMessages(prev => [...prev, userMsg]);
106
+ setInput('');
107
+ setIsProcessing(true);
108
+
109
+ // 模拟处理延迟
110
+ setTimeout(() => {
111
+ setMessages(prev => [...prev, {
112
+ type: 'result',
113
+ content: `命令 "${value}" 执行完成(演示模式)`
114
+ }]);
115
+ setIsProcessing(false);
116
+ }, 1000);
117
+ };
118
+
119
+ // 命令面板过滤
120
+ useEffect(() => {
121
+ if (commandInput) {
122
+ setFilteredCommands(
123
+ commands.filter(cmd =>
124
+ cmd.value.toLowerCase().includes(commandInput.toLowerCase()) ||
125
+ cmd.label.toLowerCase().includes(commandInput.toLowerCase())
126
+ )
127
+ );
128
+ setSelectedCommandIndex(0);
129
+ } else {
130
+ setFilteredCommands(commands);
131
+ }
132
+ }, [commandInput]);
133
+
134
+ return (
135
+ <Box flexDirection="column">
136
+ {/* 头部 */}
137
+ <Box marginBottom={1}>
138
+ <Text bold color="cyan">travel-agent</Text>
139
+ <Text> - AI 驱动的旅行目的地推荐</Text>
140
+ </Box>
141
+
142
+ {/* 消息区域 */}
143
+ <Box flexDirection="column" marginBottom={1}>
144
+ {messages.map((msg, i) => (
145
+ <Box key={i}>
146
+ {msg.type === 'user' && (
147
+ <Text color="blue">{'> '}{msg.content}</Text>
148
+ )}
149
+ {msg.type === 'system' && (
150
+ <Text dimColor>{msg.content}</Text>
151
+ )}
152
+ {msg.type === 'info' && (
153
+ <Text color="gray">{msg.content}</Text>
154
+ )}
155
+ {msg.type === 'result' && (
156
+ <Box borderStyle="round" borderColor="green" paddingX={1}>
157
+ <Text color="green">{msg.content}</Text>
158
+ </Box>
159
+ )}
160
+ {msg.type === 'error' && (
161
+ <Text color="red">错误:{msg.content}</Text>
162
+ )}
163
+ </Box>
164
+ ))}
165
+ {isProcessing && (
166
+ <Text dimColor>正在处理...</Text>
167
+ )}
168
+ </Box>
169
+
170
+ {/* 命令面板 */}
171
+ {showCommandPalette && (
172
+ <Box flexDirection="column" marginBottom={1} borderStyle="single" borderColor="cyan" paddingX={1}>
173
+ <Box>
174
+ <Text>命令:/</Text>
175
+ <Text color="cyan">{commandInput}</Text>
176
+ </Box>
177
+ {filteredCommands.map((cmd, i) => (
178
+ <Box key={cmd.value}>
179
+ {i === selectedCommandIndex && <Text color="cyan">{'>'} </Text>}
180
+ {i !== selectedCommandIndex && <Text> </Text>}
181
+ <Text color={i === selectedCommandIndex ? 'cyan' : 'gray'}>{cmd.label}</Text>
182
+ </Box>
183
+ ))}
184
+ </Box>
185
+ )}
186
+
187
+ {/* 输入区域 */}
188
+ <Box>
189
+ <Text color="blue">{'> '}</Text>
190
+ <TextInput
191
+ value={input}
192
+ onChange={setInput}
193
+ onSubmit={handleSubmit}
194
+ placeholder="输入消息或按 / 打开命令面板..."
195
+ focus={!showCommandPalette}
196
+ />
197
+ </Box>
198
+ </Box>
199
+ );
200
+ }
201
+
202
+ // 渲染应用
203
+ const instance = render(<App />, {
204
+ exitOnCtrlC: false,
205
+ });
206
+
207
+ // 优雅退出
208
+ process.on('SIGINT', () => {
209
+ instance.unmount();
210
+ process.exit(0);
211
+ });
212
+
213
+ process.on('SIGTERM', () => {
214
+ instance.unmount();
215
+ process.exit(0);
216
+ });
package/package.json CHANGED
@@ -1,15 +1,30 @@
1
1
  {
2
2
  "name": "travel-agent-cli",
3
- "version": "0.3.6",
3
+ "version": "0.4.0",
4
4
  "description": "AI 驱动的旅行目的地推荐 Agent - 命令行工具(集成 FlyAI 旅行搜索)",
5
+ "type": "module",
5
6
  "bin": {
6
7
  "travel-agent": "bin/cli.js",
7
8
  "travel-agent-cli": "bin/cli.js"
8
9
  },
10
+ "files": [
11
+ "bin",
12
+ "python",
13
+ "scripts",
14
+ "interactive.jsx"
15
+ ],
9
16
  "scripts": {
10
17
  "postinstall": "node scripts/postinstall.js",
11
18
  "preuninstall": "node scripts/preuninstall.js"
12
19
  },
20
+ "dependencies": {
21
+ "ink": "^5.2.0",
22
+ "react": "^18.3.1",
23
+ "ink-text-input": "^6.0.0",
24
+ "ink-select-input": "^6.0.0",
25
+ "chalk": "^5.4.1",
26
+ "tsx": "^4.19.2"
27
+ },
13
28
  "keywords": [
14
29
  "travel",
15
30
  "agent",
@@ -32,12 +47,11 @@
32
47
  "directory": "npm-package"
33
48
  },
34
49
  "engines": {
35
- "node": ">=14.0.0"
50
+ "node": ">=18.0.0"
36
51
  },
37
52
  "os": [
38
53
  "darwin",
39
- "linux",
40
- "win32"
54
+ "linux"
41
55
  ],
42
56
  "preferGlobal": true
43
57
  }
@@ -20,6 +20,57 @@ from main import run_command
20
20
  from config.settings import get_settings
21
21
 
22
22
 
23
+ class WhiteInput(Input):
24
+ """强制白底黑字的 Input 组件"""
25
+
26
+ DEFAULT_CSS = """
27
+ WhiteInput {
28
+ background: #ffffff !important;
29
+ color: #000000 !important;
30
+ height: 3;
31
+ margin: 1 1 0 1;
32
+ padding: 1;
33
+ border: solid #000000;
34
+ }
35
+
36
+ WhiteInput:focus {
37
+ border: solid #e94560;
38
+ }
39
+
40
+ WhiteInput > .input--cursor {
41
+ background: #000000 !important;
42
+ color: #ffffff !important;
43
+ }
44
+
45
+ WhiteInput > .input--selection {
46
+ background: #cccccc !important;
47
+ color: #000000 !important;
48
+ }
49
+
50
+ WhiteInput > .input--placeholder, WhiteInput > .input--suggestion {
51
+ color: #666666 !important;
52
+ }
53
+
54
+ WhiteInput:ansi {
55
+ background: ansi_white !important;
56
+ color: ansi_black !important;
57
+ }
58
+
59
+ WhiteInput:ansi > .input--cursor {
60
+ background: ansi_black !important;
61
+ color: ansi_white !important;
62
+ }
63
+
64
+ WhiteInput:ansi > .input--selection {
65
+ background: ansi_default !important;
66
+ }
67
+
68
+ WhiteInput:ansi > .input--placeholder, WhiteInput:ansi > .input--suggestion {
69
+ text-style: dim !important;
70
+ }
71
+ """
72
+
73
+
23
74
  class CommandProvider(Provider):
24
75
  """命令提供者 - 用于命令面板"""
25
76
 
@@ -68,8 +119,8 @@ class ChatScreen(Screen):
68
119
  with Vertical():
69
120
  # 聊天输出区域 - 使用 RichLog 支持 Markdown
70
121
  yield RichLog(id="chat-output", highlight=True, markup=True)
71
- # 输入区域
72
- yield Input(
122
+ # 输入区域 - 使用自定义 WhiteInput 强制白底黑字
123
+ yield WhiteInput(
73
124
  placeholder="输入消息或按 / 打开命令面板...",
74
125
  id="chat-input"
75
126
  )
@@ -197,8 +248,15 @@ class TravelAgentApp(App):
197
248
  SUB_TITLE = "AI 驱动的旅行目的地推荐"
198
249
 
199
250
  CSS = """
251
+ /* 强制使用亮色主题 - 白底黑字 */
252
+ App {
253
+ background: #ffffff;
254
+ color: #000000;
255
+ }
256
+
257
+ /* 主屏幕背景 - 白色 */
200
258
  Screen {
201
- background: #1a1a2e;
259
+ background: #ffffff;
202
260
  }
203
261
 
204
262
  Vertical {
@@ -207,7 +265,8 @@ class TravelAgentApp(App):
207
265
 
208
266
  #chat-output {
209
267
  height: 1fr;
210
- background: #1a1a2e;
268
+ background: #ffffff;
269
+ color: #000000;
211
270
  padding: 1;
212
271
  }
213
272
 
@@ -216,56 +275,157 @@ class TravelAgentApp(App):
216
275
  margin: 1 1 0 1;
217
276
  padding: 1;
218
277
  dock: bottom;
219
- background: #16213e;
220
- border: solid #0f3460;
278
+ background: #ffffff;
279
+ color: #000000;
280
+ border: solid #000000;
221
281
  }
222
282
 
223
283
  Input#chat-input:focus {
224
- background: #16213e;
284
+ background: #ffffff;
285
+ color: #000000;
225
286
  border: solid #e94560;
226
287
  }
227
288
 
228
- /* Command Palette Styles */
289
+ /* Command Palette - 强制白底黑字 */
229
290
  CommandPalette {
230
- background: rgba(26, 26, 46, 0.95);
291
+ background: #ffffff !important;
292
+ color: #000000 !important;
231
293
  }
232
294
 
233
- CommandPalette > Vertical {
234
- background: #1a1a2e;
235
- border: solid #0f3460;
295
+ CommandPalette > #--container {
296
+ align: center middle;
297
+ background: #ffffff !important;
236
298
  }
237
299
 
238
- CommandPalette Input {
239
- background: #16213e;
240
- color: #eaeaea;
241
- border: solid #0f3460;
300
+ CommandPalette > #--container > Vertical {
301
+ background: #ffffff !important;
302
+ border: solid #000000 !important;
303
+ width: 80;
304
+ height: auto;
305
+ max-height: 20;
242
306
  }
243
307
 
244
- CommandPalette Input:focus {
245
- background: #16213e;
246
- border: solid #e94560;
308
+ CommandPalette > #--container > Vertical > #--input {
309
+ background: #ffffff !important;
310
+ color: #000000 !important;
311
+ }
312
+
313
+ /* Input 主体 */
314
+ CommandPalette #--input Input {
315
+ background: #ffffff !important;
316
+ color: #000000 !important;
317
+ border: solid #000000 !important;
318
+ }
319
+
320
+ CommandPalette #--input Input:focus {
321
+ background: #ffffff !important;
322
+ color: #000000 !important;
323
+ border: solid #e94560 !important;
324
+ }
325
+
326
+ /* Input 内部子组件 - 使用直接子选择器 */
327
+ CommandPalette #--input > .input--cursor {
328
+ background: #000000 !important;
329
+ color: #ffffff !important;
330
+ }
331
+
332
+ CommandPalette #--input > .input--selection {
333
+ background: #cccccc !important;
334
+ color: #000000 !important;
335
+ }
336
+
337
+ CommandPalette #--input > .input--placeholder {
338
+ color: #666666 !important;
339
+ }
340
+
341
+ CommandPalette #--input > .input--suggestion {
342
+ color: #666666 !important;
343
+ }
344
+
345
+ /* 输入内容的颜色 - 强制覆盖 */
346
+ CommandPalette #--input Input * {
347
+ color: #000000 !important;
348
+ background: #ffffff !important;
349
+ }
350
+
351
+ CommandPalette #--input SearchIcon {
352
+ color: #000000 !important;
353
+ }
354
+
355
+ CommandPalette #--input Button {
356
+ background: #e94560 !important;
357
+ color: #ffffff !important;
358
+ }
359
+
360
+ CommandPalette #--results {
361
+ background: #ffffff !important;
362
+ color: #000000 !important;
363
+ }
364
+
365
+ CommandPalette #--results .option-list {
366
+ background: #ffffff !important;
367
+ color: #000000 !important;
368
+ }
369
+
370
+ CommandPalette .option-list__option,
371
+ CommandPalette .option-list--option {
372
+ color: #000000 !important;
373
+ background: #ffffff !important;
374
+ }
375
+
376
+ CommandPalette .option-list__option--highlighted,
377
+ CommandPalette .option-list--option--highlighted {
378
+ background: #e94560 !important;
379
+ color: #ffffff !important;
247
380
  }
248
381
 
249
382
  CommandPalette .command-palette--help-text {
250
- color: #6c6c8a;
383
+ color: #666666 !important;
251
384
  }
252
385
 
253
386
  CommandPalette .command-palette--highlight {
254
- text-style: bold;
387
+ text-style: bold !important;
388
+ color: #e94560 !important;
389
+ }
390
+
391
+ CommandPalette Static,
392
+ CommandPalette Label {
393
+ color: #000000 !important;
394
+ }
395
+
396
+ CommandPalette LoadingIndicator {
397
+ background: #ffffff;
255
398
  color: #e94560;
256
399
  }
257
400
 
258
- CommandPalette Static {
259
- color: #eaeaea;
401
+ /* ANSI 模式覆盖 */
402
+ CommandPalette:ansi {
403
+ background: ansi_white !important;
404
+ color: ansi_black !important;
405
+ }
406
+
407
+ CommandPalette:ansi #--input Input {
408
+ background: ansi_white !important;
409
+ color: ansi_black !important;
410
+ }
411
+
412
+ CommandPalette:ansi #--input > .input--cursor {
413
+ background: ansi_black !important;
414
+ color: ansi_white !important;
415
+ }
416
+
417
+ CommandPalette:ansi #--input > .input--selection {
418
+ background: ansi_default !important;
260
419
  }
261
420
 
262
- CommandPalette .option-list__option {
263
- color: #eaeaea;
421
+ CommandPalette:ansi #--input > .input--placeholder,
422
+ CommandPalette:ansi #--input > .input--suggestion {
423
+ text-style: dim !important;
264
424
  }
265
425
 
266
- CommandPalette .option-list__option--highlighted {
267
- background: #0f3460;
268
- color: #ffffff;
426
+ CommandPalette:ansi .option-list__option {
427
+ color: ansi_black !important;
428
+ background: ansi_white !important;
269
429
  }
270
430
  """
271
431
 
@@ -4,9 +4,13 @@
4
4
  * 创建虚拟环境并安装 Python 依赖
5
5
  */
6
6
 
7
- const { execSync } = require('child_process');
8
- const fs = require('fs');
9
- const path = require('path');
7
+ import { execSync } from 'child_process';
8
+ import fs from 'fs';
9
+ import path from 'path';
10
+ import { fileURLToPath } from 'url';
11
+
12
+ const __filename = fileURLToPath(import.meta.url);
13
+ const __dirname = path.dirname(__filename);
10
14
 
11
15
  const packagePath = path.join(__dirname, '..');
12
16
  const pythonDir = path.join(packagePath, 'python');