travel-agent-cli 0.3.5 → 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.5",
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
  )
@@ -168,7 +219,9 @@ class ChatScreen(Screen):
168
219
  def action_submit(self) -> None:
169
220
  """提交输入"""
170
221
  input_widget = self.query_one("#chat-input", Input)
171
- input_widget._submit()
222
+ # 手动触发提交事件
223
+ from textual.events import InputSubmitted
224
+ input_widget.post_message(InputSubmitted(input_widget))
172
225
 
173
226
  def action_clear(self) -> None:
174
227
  """清屏"""
@@ -195,8 +248,15 @@ class TravelAgentApp(App):
195
248
  SUB_TITLE = "AI 驱动的旅行目的地推荐"
196
249
 
197
250
  CSS = """
251
+ /* 强制使用亮色主题 - 白底黑字 */
252
+ App {
253
+ background: #ffffff;
254
+ color: #000000;
255
+ }
256
+
257
+ /* 主屏幕背景 - 白色 */
198
258
  Screen {
199
- background: #1a1a2e;
259
+ background: #ffffff;
200
260
  }
201
261
 
202
262
  Vertical {
@@ -205,7 +265,8 @@ class TravelAgentApp(App):
205
265
 
206
266
  #chat-output {
207
267
  height: 1fr;
208
- background: #1a1a2e;
268
+ background: #ffffff;
269
+ color: #000000;
209
270
  padding: 1;
210
271
  }
211
272
 
@@ -214,56 +275,157 @@ class TravelAgentApp(App):
214
275
  margin: 1 1 0 1;
215
276
  padding: 1;
216
277
  dock: bottom;
217
- background: #16213e;
218
- border: solid #0f3460;
278
+ background: #ffffff;
279
+ color: #000000;
280
+ border: solid #000000;
219
281
  }
220
282
 
221
283
  Input#chat-input:focus {
222
- background: #16213e;
284
+ background: #ffffff;
285
+ color: #000000;
223
286
  border: solid #e94560;
224
287
  }
225
288
 
226
- /* Command Palette Styles */
289
+ /* Command Palette - 强制白底黑字 */
227
290
  CommandPalette {
228
- background: rgba(26, 26, 46, 0.95);
291
+ background: #ffffff !important;
292
+ color: #000000 !important;
229
293
  }
230
294
 
231
- CommandPalette > Vertical {
232
- background: #1a1a2e;
233
- border: solid #0f3460;
295
+ CommandPalette > #--container {
296
+ align: center middle;
297
+ background: #ffffff !important;
234
298
  }
235
299
 
236
- CommandPalette Input {
237
- background: #16213e;
238
- color: #eaeaea;
239
- 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;
240
306
  }
241
307
 
242
- CommandPalette Input:focus {
243
- background: #16213e;
244
- 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;
245
380
  }
246
381
 
247
382
  CommandPalette .command-palette--help-text {
248
- color: #6c6c8a;
383
+ color: #666666 !important;
249
384
  }
250
385
 
251
386
  CommandPalette .command-palette--highlight {
252
- 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;
253
398
  color: #e94560;
254
399
  }
255
400
 
256
- CommandPalette Static {
257
- 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;
258
419
  }
259
420
 
260
- CommandPalette .option-list__option {
261
- color: #eaeaea;
421
+ CommandPalette:ansi #--input > .input--placeholder,
422
+ CommandPalette:ansi #--input > .input--suggestion {
423
+ text-style: dim !important;
262
424
  }
263
425
 
264
- CommandPalette .option-list__option--highlighted {
265
- background: #0f3460;
266
- color: #ffffff;
426
+ CommandPalette:ansi .option-list__option {
427
+ color: ansi_black !important;
428
+ background: ansi_white !important;
267
429
  }
268
430
  """
269
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');