@baimingtao/lbs-agent 1.2.0 → 1.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/lbs.js CHANGED
@@ -46,17 +46,21 @@ const INIT_SCRIPT = path.join(PKG_ROOT, 'scripts', 'init.js');
46
46
 
47
47
  // ── 颜色与图标 (对标 Hermes banner/colors) ─────────────────────
48
48
 
49
+ // ── Aurora Pink 配色 ───────────────────────────────────────────
50
+
49
51
  const C = {
50
- reset: '\x1b[0m',
51
- bold: '\x1b[1m',
52
- dim: '\x1b[2m',
53
- red: '\x1b[31m',
54
- green: '\x1b[32m',
55
- yellow: '\x1b[33m',
56
- blue: '\x1b[34m',
57
- magenta: '\x1b[35m',
58
- cyan: '\x1b[36m',
59
- gold: '\x1b[1;38;2;255;191;0m',
52
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', italic: '\x1b[3m',
53
+ pink: '\x1b[38;2;255;79;164m', // #FF4FA4
54
+ pinkL: '\x1b[38;2;255;167;213m', // #FFA7D5
55
+ purple: '\x1b[38;2;194;107;255m', // #C26BFF
56
+ blue: '\x1b[38;2;110;139;255m', // #6E8BFF
57
+ mint: '\x1b[38;2;152;216;200m', // #98D8C8
58
+ mintD: '\x1b[38;2;111;196;176m', // #6FC4B0
59
+ ok: '\x1b[38;2;62;229;138m', // #3EE58A
60
+ warn: '\x1b[38;2;255;179;71m', // #FFB347
61
+ err: '\x1b[38;2;255;107;129m', // #FF6B81
62
+ subtle: '\x1b[38;2;138;138;150m', // #8A8A96
63
+ faint: '\x1b[38;2;90;90;102m', // #5A5A66
60
64
  };
61
65
 
62
66
  function supportsColor() {
@@ -70,25 +74,38 @@ function paint(text, ...colors) {
70
74
  return colors.join('') + text + C.reset;
71
75
  }
72
76
 
73
- // ── ASCII Logo ─────────────────────────────────────────────────
77
+ // 逐字符渐变
78
+ function gradient(text) {
79
+ if (!supportsColor()) return text;
80
+ const stops = [
81
+ '\x1b[38;2;255;79;164m', // pink
82
+ '\x1b[38;2;255;127;184m', // pink-pu
83
+ '\x1b[38;2;224;119;220m', // mid
84
+ '\x1b[38;2;194;107;255m', // purple
85
+ '\x1b[38;2;160;123;240m', // pu-blue
86
+ '\x1b[38;2;130;131;248m', // blue-ish
87
+ '\x1b[38;2;110;139;255m', // blue
88
+ ];
89
+ const n = text.length;
90
+ let out = '';
91
+ for (let i = 0; i < n; i++) {
92
+ if (text[i] === ' ') { out += ' '; continue; }
93
+ const idx = Math.min(Math.floor(i / Math.max(n, 1) * stops.length), stops.length - 1);
94
+ out += stops[idx] + text[i] + C.reset;
95
+ }
96
+ return out;
97
+ }
74
98
 
75
- const LOGO = [
76
- '',
77
- ' ' + paint('╔══╗', C.gold) + ' ' + paint('╔═══╗', C.cyan) + ' ' + paint('╔═════╗', C.cyan),
78
- ' ' + paint('║ ║', C.gold) + ' ' + paint('║ ║', C.cyan) + ' ' + paint('║ ╔═╝', C.cyan),
79
- ' ' + paint('╠══╣', C.gold) + ' ' + paint('╠═══╣', C.cyan) + ' ' + paint('║ ╚═╗', C.cyan),
80
- ' ' + paint('║ ║', C.gold) + ' ' + paint('║ ║', C.cyan) + ' ' + paint('╚═════╝', C.cyan),
81
- ' ' + paint('╚══╝', C.gold) + ' ' + paint('╚═══╝', C.cyan) + ' ' + paint('AGENT', C.dim),
82
- '',
83
- ].join('\n');
99
+ // ── Banner — 极简留白 ─────────────────────────────────────────
84
100
 
85
101
  function printBanner() {
86
- const pkg = JSON.parse(fs.readFileSync(path.join(PKG_ROOT, 'package.json'), 'utf-8'));
87
- console.log(LOGO);
88
- console.log(paint(' v' + pkg.version, C.bold, C.gold) + paint(' Leaving Blank Space Agent', C.dim));
102
+ console.log();
103
+ console.log(' ' + paint('✦', C.pink));
104
+ console.log();
105
+ console.log(' ' + gradient('LBS Agent'));
106
+ console.log(' ' + paint('Autonomous AI Runtime', C.subtle));
89
107
  console.log();
90
108
  }
91
-
92
109
  // ── 初始化检查 ─────────────────────────────────────────────────
93
110
 
94
111
  function isInitialized() {
@@ -98,13 +115,13 @@ function isInitialized() {
98
115
  function ensureInitialized() {
99
116
  if (isInitialized()) return true;
100
117
 
101
- console.log(paint('⚙ ', C.gold) + paint('首次运行,正在初始化 LBS Agent...', C.bold));
102
- console.log(paint(' 状态目录: ', C.dim) + paint(STATE_ROOT, C.cyan));
118
+ console.log(paint('⚙ ', C.pink) + paint('首次运行,正在初始化 LBS Agent...', C.bold));
119
+ console.log(paint(' 状态目录: ', C.dim) + paint(STATE_ROOT, C.mint));
103
120
  console.log(paint(' 创建 Python 虚拟环境 + 安装依赖(约 1-2 分钟)', C.dim));
104
121
  console.log();
105
122
 
106
123
  if (!fs.existsSync(INIT_SCRIPT)) {
107
- console.error(paint('✖ ', C.red) + '初始化脚本不存在: ' + INIT_SCRIPT);
124
+ console.error(paint('✖ ', C.err) + '初始化脚本不存在: ' + INIT_SCRIPT);
108
125
  return false;
109
126
  }
110
127
 
@@ -115,11 +132,11 @@ function ensureInitialized() {
115
132
  });
116
133
 
117
134
  if (result.status !== 0) {
118
- console.error(paint('\n✖ ', C.red) + '初始化失败');
135
+ console.error(paint('\n✖ ', C.err) + '初始化失败');
119
136
  return false;
120
137
  }
121
138
 
122
- console.log(paint('\n✓ ', C.green) + paint('初始化完成!', C.bold, C.green));
139
+ console.log(paint('\n✓ ', C.ok) + paint('初始化完成!', C.bold, C.ok));
123
140
  console.log();
124
141
  return true;
125
142
  }
@@ -140,7 +157,7 @@ if (subcmd === 'init' || subcmd === '--init') {
140
157
  });
141
158
  process.exit(result.status || 0);
142
159
  }
143
- console.error(paint('✖ ', C.red) + '初始化脚本不存在');
160
+ console.error(paint('✖ ', C.err) + '初始化脚本不存在');
144
161
  process.exit(1);
145
162
  }
146
163
 
@@ -0,0 +1,233 @@
1
+ """LBS CLI Theme — Aurora Pink 现代终端设计系统。
2
+
3
+ 设计原则:
4
+ 留白 > 密集
5
+ 符号 > 字符画
6
+ 渐变 > 纯色
7
+
8
+ 对标: Claude Code, Gemini CLI, Warp Terminal, Charm BubbleTea
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import os
14
+ import sys
15
+
16
+
17
+ # ── 色彩 ───────────────────────────────────────────────────────
18
+
19
+ class C:
20
+ RESET = "\033[0m"
21
+ BOLD = "\033[1m"
22
+ DIM = "\033[2m"
23
+ ITALIC = "\033[3m"
24
+
25
+ # Aurora Pink 渐变 (Pink → Purple → Blue)
26
+ PINK = "\033[38;2;255;79;164m" # #FF4FA4
27
+ PINK_L = "\033[38;2;255;167;213m" # #FFA7D5
28
+ PURPLE = "\033[38;2;194;107;255m" # #C26BFF
29
+ BLUE = "\033[38;2;110;139;255m" # #6E8BFF
30
+
31
+ # Mint (Web 端品牌色)
32
+ MINT = "\033[38;2;152;216;200m" # #98D8C8
33
+ MINT_D = "\033[38;2;111;196;176m" # #6FC4B0
34
+
35
+ # 状态
36
+ OK = "\033[38;2;62;229;138m" # #3EE58A
37
+ WARN = "\033[38;2;255;179;71m" # #FFB347
38
+ ERR = "\033[38;2;255;107;129m" # #FF6B81
39
+ INFO = "\033[38;2;101;168;255m" # #65A8FF
40
+
41
+ # 文字
42
+ TEXT = "\033[38;2;235;235;245m" # #EBEBF5 (正文)
43
+ SUBTLE = "\033[38;2;138;138;150m" # #8A8A96 (辅助)
44
+ FAINT = "\033[38;2;90;90;102m" # #5A5A66 (最弱)
45
+
46
+
47
+ def _ok() -> bool:
48
+ if os.environ.get("NO_COLOR"):
49
+ return False
50
+ if os.environ.get("TERM") == "dumb":
51
+ return False
52
+ return sys.stdout.isatty()
53
+
54
+
55
+ def p(text: str, *codes: str) -> str:
56
+ """上色"""
57
+ if not _ok():
58
+ return text
59
+ return "".join(codes) + text + C.RESET
60
+
61
+
62
+ def dim(text: str) -> str:
63
+ return p(text, C.SUBTLE)
64
+
65
+
66
+ def faint(text: str) -> str:
67
+ return p(text, C.FAINT)
68
+
69
+
70
+ def pink(text: str) -> str:
71
+ return p(text, C.PINK)
72
+
73
+
74
+ def purple(text: str) -> str:
75
+ return p(text, C.PURPLE)
76
+
77
+
78
+ def mint(text: str) -> str:
79
+ return p(text, C.MINT_D)
80
+
81
+
82
+ def ok(text: str) -> str:
83
+ return p(text, C.OK)
84
+
85
+
86
+ def err(text: str) -> str:
87
+ return p(text, C.ERR)
88
+
89
+
90
+ # ── 组件 ───────────────────────────────────────────────────────
91
+
92
+ def gradient_text(text: str) -> str:
93
+ """Pink → Purple → Blue 逐字符渐变。"""
94
+ if not _ok():
95
+ return text
96
+ colors = [C.PINK, C.PINK_L, "\033[38;2;255;127;184m",
97
+ "\033[38;2;224;119;220m", C.PURPLE,
98
+ "\033[38;2;160;123;240m", C.BLUE]
99
+ n = len(text)
100
+ result = []
101
+ for i, ch in enumerate(text):
102
+ if ch == " ":
103
+ result.append(ch)
104
+ continue
105
+ idx = min(int(i / max(n, 1) * len(colors)), len(colors) - 1)
106
+ result.append(colors[idx] + ch + C.RESET)
107
+ return "".join(result)
108
+
109
+
110
+ def header() -> str:
111
+ """启动 header — 极简留白风格。"""
112
+ lines = [
113
+ "",
114
+ f" {p('✦', C.PINK)}",
115
+ "",
116
+ f" {gradient_text('LBS Agent')}",
117
+ f" {dim('Autonomous AI Runtime')}",
118
+ "",
119
+ ]
120
+ return "\n".join(lines)
121
+
122
+
123
+ def session_card(rows: list[tuple[str, str]]) -> str:
124
+ """Session 信息卡 — 上下布局,图标 + label + value。"""
125
+ icons = {
126
+ "session": "◇",
127
+ "workspace": "▸",
128
+ "agent": "◐",
129
+ "model": "✦",
130
+ "provider": "☁",
131
+ "memory": "◈",
132
+ "runtime": "⚙",
133
+ "turns": "⟩",
134
+ "elapsed": "⏱",
135
+ }
136
+ lines = []
137
+ for label, value in rows:
138
+ icon = icons.get(label, "·")
139
+ lines.append(f" {p(icon, C.PURPLE)} {dim(f'{label:11}')} {value}")
140
+ return "\n".join(lines)
141
+
142
+
143
+ def separator(width: int = 52) -> str:
144
+ """分隔线 — 最弱色"""
145
+ return p("─" * width, C.FAINT)
146
+
147
+
148
+ def prompt_symbol() -> str:
149
+ """输入提示符"""
150
+ return p("❯", C.PINK)
151
+
152
+
153
+ def footer() -> str:
154
+ """底部快捷键栏"""
155
+ keys = [
156
+ ("↵", "Send"),
157
+ ("↑↓", "History"),
158
+ ("Tab", "Complete"),
159
+ ("/help", "Commands"),
160
+ ("Ctrl+C", "Exit"),
161
+ ]
162
+ parts = []
163
+ for key, label in keys:
164
+ parts.append(f"{p(key, C.PURPLE)} {faint(label)}")
165
+ return faint(" ") + faint(" · ".join(parts))
166
+
167
+
168
+ def usage_line(seconds: float, iterations: int, tools: int) -> str:
169
+ """用量条"""
170
+ parts = [
171
+ p(f"{seconds:.1f}s", C.MINT_D),
172
+ faint(f"iter {iterations}"),
173
+ faint(f"tools {tools}"),
174
+ ]
175
+ return " " + faint(" · ").join(parts)
176
+
177
+
178
+ def result_text(content: str) -> str:
179
+ """最终结果"""
180
+ return p(content, C.TEXT)
181
+
182
+
183
+ def error_text(content: str) -> str:
184
+ """错误"""
185
+ return p(f"✕ {content}", C.ERR)
186
+
187
+
188
+ def agent_tag(name: str) -> str:
189
+ """Agent 标签"""
190
+ return p(f"◐ {name}", C.PURPLE)
191
+
192
+
193
+ def model_tag(model: str) -> str:
194
+ """模型标签"""
195
+ return p(f"✦ {model}", C.PINK)
196
+
197
+
198
+ def react_header(agent_display: str, model_chain: list[str], tools: list[str]) -> str:
199
+ """ReAct 任务头 — 极简留白"""
200
+ model_str = faint(" → ").join(pink(m) for m in model_chain)
201
+ tools_str = faint(", ").join(mint(t) for t in tools)
202
+ return "\n".join([
203
+ separator(),
204
+ f" {agent_tag(agent_display)}",
205
+ f" {model_str}",
206
+ f" {faint('tools')} {tools_str}" if tools_str else "",
207
+ separator(),
208
+ ])
209
+
210
+
211
+ def react_iter(iteration: int) -> str:
212
+ """迭代标记"""
213
+ return f"\n {p('⟡', C.PINK)} {p(f'iter {iteration}', C.BOLD, C.PINK)}"
214
+
215
+
216
+ def thinking_block(content: str) -> str:
217
+ """思考块"""
218
+ return p(content, C.ITALIC, C.MINT_D)
219
+
220
+
221
+ def tool_card(name: str, status: str, duration: str = "") -> str:
222
+ """工具调用卡片"""
223
+ status_color = C.OK if status == "ok" else C.ERR
224
+ icon = "✓" if status == "ok" else "✕"
225
+ dur = f" {faint(duration)}" if duration else ""
226
+ return f" {p(icon, status_color)} {faint(name)}{dur}"
227
+
228
+
229
+ def timeline_item(timestamp: str, label: str, success: bool = True) -> str:
230
+ """时间线条目"""
231
+ icon = "✓" if success else "✕"
232
+ color = C.OK if success else C.ERR
233
+ return f" {faint(timestamp)} {p(icon, color)} {dim(label)}"
@@ -1,17 +1,6 @@
1
- """LBS Agent REPL 交互模式(最小可工作版本)。
2
-
3
- 设计:
4
- - 用户进入交互循环,每次输入一行
5
- - 内建命令以 `/` 开头(/help, /exit, /model, /agent, /session, /status, /clear, /new)
6
- - 其他输入走 Orchestrator.run_agent_sync()
7
- - 每次 turn 自动保存到 session(持久化)
8
-
9
- 用法:
10
- lbs chat # 默认 agent
11
- lbs chat --agent code
12
- lbs chat --agent code --provider minmax --model MiniMax-M3
13
- lbs chat --session <id> # 恢复已有 session
14
- lbs chat --query "single query" # 非交互(等价于 lbs run)
1
+ """LBS Agent REPL — Aurora Terminal v2。
2
+
3
+ 极简留白,符号驱动,渐变品牌。
15
4
  """
16
5
  from __future__ import annotations
17
6
 
@@ -23,27 +12,22 @@ from typing import Optional
23
12
  from application.container import AgentSystemContainer
24
13
  from config.config import AppConfig
25
14
  from interfaces.cli._impl.commands.common import project_root
26
-
27
-
28
- BANNER = """\033[1;38;2;255;191;0m
29
- \033[1;36m╔══╗\033[0m \033[1;36m╔═══╗\033[0m \033[1;36m╔═════╗\033[0m
30
- \033[1;36m║ ║\033[0m \033[1;36m║ ║\033[0m \033[1;36m║ ╔═╝\033[0m
31
- \033[1;36m╠══╣\033[0m \033[1;36m╠═══╣\033[0m \033[1;36m║ ╚═╗\033[0m
32
- \033[1;36m║ ║\033[0m \033[1;36m║ ║\033[0m \033[1;36m╚═════╝\033[0m
33
- \033[1;36m╚══╝\033[0m \033[1;36m╚═══╝\033[0m \033[2mAGENT\033[0m
34
- \033[0m
35
- \033[2mInteractive Chat · /help for commands · /exit to quit\033[0m
36
- """
15
+ from interfaces.cli._impl.cli_theme import (
16
+ C, p, dim, faint, pink, purple, mint, ok, err,
17
+ gradient_text, header, session_card, separator,
18
+ prompt_symbol, footer, usage_line, result_text,
19
+ error_text, agent_tag, model_tag, react_header,
20
+ react_iter, thinking_block, tool_card, timeline_item,
21
+ )
37
22
 
38
23
 
39
24
  @dataclass
40
25
  class ChatState:
41
- """REPL 运行时状态。"""
42
26
  container: object = None
43
27
  orchestrator: object = None
44
28
  session_service: object = None
45
29
  session_id: str = ""
46
- agent_name: str = "code"
30
+ agent_name: str = "chat"
47
31
  provider_name: str = ""
48
32
  model_name: str = ""
49
33
  turn_count: int = 0
@@ -51,11 +35,9 @@ class ChatState:
51
35
 
52
36
 
53
37
  def _resolve_agent(config: AppConfig) -> str:
54
- """选默认 agent:chat 优先(REPL 专用),其次 main/第一个。"""
55
38
  names = list(config.agents.agents.keys()) if config.agents else []
56
39
  if not names:
57
40
  raise RuntimeError("没有配置任何 agent")
58
- # chat 是 REPL 专用(无 evidence 强制,纯对话)
59
41
  if "chat" in names:
60
42
  return "chat"
61
43
  if "main" in names:
@@ -63,90 +45,114 @@ def _resolve_agent(config: AppConfig) -> str:
63
45
  return names[0]
64
46
 
65
47
 
48
+ def _print_banner(state: ChatState) -> None:
49
+ """启动 — 极简留白"""
50
+ print()
51
+ print(header())
52
+
53
+ rows = [
54
+ ("session", faint(state.session_id) if state.session_id else faint("(unsaved)")),
55
+ ("agent", agent_tag(state.agent_name)),
56
+ ("model", model_tag(state.model_name) if state.model_name else faint("(default)")),
57
+ ("provider", purple(state.provider_name) if state.provider_name else faint("(default)")),
58
+ ("turns", faint(str(state.turn_count))),
59
+ ]
60
+ print(session_card(rows))
61
+ print()
62
+ print(separator())
63
+ print(f" {faint('Ask anything...')}")
64
+ print(separator())
65
+ print()
66
+
67
+
66
68
  def _print_turn_header(state: ChatState) -> None:
67
- """每次 turn header(agent + turn 编号)。"""
68
- agent_label = f"\033[1;36m{state.agent_name}\033[0m"
69
- turn_label = f"\033[2mturn {state.turn_count}\033[0m"
70
- print(f"\n{agent_label} {turn_label} \033[2m›\033[0m ", end="", flush=True)
69
+ """输入提示符 只有 """
70
+ print()
71
+ print(f" {prompt_symbol()} ", end="", flush=True)
71
72
 
72
73
 
73
74
  def _print_help() -> None:
74
- print("""
75
- \033[1;36m内建命令:\033[0m
76
- /help 显示本帮助
77
- /exit /quit 退出 chat(自动保存 session)
78
- /new 开始新 session
79
- /session [id] 查看或切换 session(不带参数显示当前)
80
- /status 显示 session 状态
81
- /agent 列出可用 agents
82
- /agent <name> 切换到指定 agent
83
- /model 列出当前 provider/models
84
- /model <model> 切换 model(当前 provider 内)
85
- /clear 清屏
86
- /history [n] 显示最近 n 轮对话(默认 5)
87
- /save 手动保存当前 session
88
- """)
75
+ print()
76
+ print(f" {gradient_text('Commands')}")
77
+ print()
78
+ cmds = [
79
+ ("/help", "显示帮助"),
80
+ ("/exit", "退出"),
81
+ ("/new", "新 session"),
82
+ ("/status", "状态"),
83
+ ("/agent", "切换 agent"),
84
+ ("/model", "切换 model"),
85
+ ("/history", "历史"),
86
+ ("/clear", "清屏"),
87
+ ]
88
+ for cmd, desc in cmds:
89
+ print(f" {pink(cmd.ljust(12))} {faint(desc)}")
90
+ print()
89
91
 
90
92
 
91
93
  def _cmd_list_agents(state: ChatState) -> None:
92
94
  agents = state.container.config.agents.agents
93
- print("\n\033[1;36m可用 agents:\033[0m")
95
+ print()
94
96
  for name, a in agents.items():
95
- marker = " \033[1;32m<-- 当前\033[0m" if name == state.agent_name else ""
96
- print(f" {name:25} {a.display_name}{marker}")
97
+ current = f" {ok('← current')}" if name == state.agent_name else ""
98
+ print(f" {agent_tag(name)} {faint(a.display_name)}{current}")
99
+ print()
97
100
 
98
101
 
99
102
  def _cmd_list_models(state: ChatState) -> None:
100
103
  config = state.container.config
101
104
  provider_name = state.provider_name or config.models.default_provider
102
105
  if provider_name not in config.models.providers:
103
- print(f" 无 provider '{provider_name}'")
106
+ msg = f"无 provider '{provider_name}'"
107
+ print(f" {error_text(msg)}")
104
108
  return
105
- p = config.models.providers[provider_name]
106
- print(f"\n\033[1;36m当前 provider: {provider_name} ({p.display_name or provider_name})\033[0m")
107
- for m in p.models:
108
- marker = " \033[1;32m<-- 当前\033[0m" if m == state.model_name else ""
109
- print(f" {m}{marker}")
109
+ prov = config.models.providers[provider_name]
110
+ print()
111
+ print(f" {faint('provider')} {purple(provider_name)}")
112
+ for m in prov.models:
113
+ marker = f" {ok('←')}" if m == state.model_name else ""
114
+ print(f" {model_tag(m)}{marker}")
115
+ print()
110
116
 
111
117
 
112
118
  def _cmd_history(state: ChatState, n: int = 5) -> None:
113
119
  if not state.session_id:
114
- print(" 无 session")
120
+ print(f" {faint('无 session')}")
115
121
  return
116
122
  try:
117
123
  messages = list(state.session_service.session_store.load_session_messages(state.session_id))
118
- # 显示 user/assistant 配对
119
124
  recent = []
120
125
  for msg in messages[-n*2:]:
121
126
  role = getattr(msg, "role", "?")
122
127
  content = getattr(msg, "content", "")[:120]
123
128
  if role in ("user", "assistant"):
124
129
  recent.append((role, content))
125
- print(f"\n\033[1;36m最近 {len(recent)} 条消息\033[0m")
130
+ print()
126
131
  for role, content in recent:
127
- print(f" {role:11} {content}")
132
+ rc = C.PINK if role == "user" else C.MINT_D
133
+ print(f" {p(role.ljust(9), rc)} {faint(content)}")
134
+ print()
128
135
  except Exception as e:
129
- print(f" 读取失败:{e}")
136
+ msg = f"读取失败: {e}"
137
+ print(f" {error_text(msg)}")
130
138
 
131
139
 
132
140
  def _cmd_status(state: ChatState) -> None:
133
141
  elapsed = int(time.time() - state.started_at)
134
142
  rows = [
135
- ("session", state.session_id or "\033[2m(unsaved)\033[0m"),
136
- ("agent", state.agent_name),
137
- ("provider", state.provider_name or "\033[2m(default)\033[0m"),
138
- ("model", state.model_name or "\033[2m(default)\033[0m"),
139
- ("turns", str(state.turn_count)),
140
- ("elapsed", f"{elapsed}s"),
143
+ ("session", faint(state.session_id) if state.session_id else faint("(unsaved)")),
144
+ ("agent", agent_tag(state.agent_name)),
145
+ ("model", model_tag(state.model_name) if state.model_name else faint("(default)")),
146
+ ("provider", purple(state.provider_name) if state.provider_name else faint("(default)")),
147
+ ("turns", faint(str(state.turn_count))),
148
+ ("elapsed", faint(f"{elapsed}s")),
141
149
  ]
142
150
  print()
143
- for label, val in rows:
144
- print(f" \033[2m{label:9}\033[0m │ {val}")
151
+ print(session_card(rows))
145
152
  print()
146
153
 
147
154
 
148
155
  def _handle_command(state: ChatState, line: str) -> bool:
149
- """处理 / 命令。返回 True 表示继续循环,False 表示退出。"""
150
156
  parts = line.strip().split(maxsplit=1)
151
157
  cmd = parts[0].lower()
152
158
  arg = parts[1] if len(parts) > 1 else ""
@@ -159,13 +165,14 @@ def _handle_command(state: ChatState, line: str) -> bool:
159
165
  state.session_id = ""
160
166
  state.turn_count = 0
161
167
  state.started_at = time.time()
162
- print("\033[1;32m→ session 已开始\033[0m")
168
+ print(f" {ok('◇')} {faint('new session')}")
163
169
  elif cmd == "/session":
164
170
  if arg:
165
171
  state.session_id = arg
166
- print(f"\033[1;32m→ 切换到 session: {arg}\033[0m")
172
+ print(f" {ok('◇')} {faint('switched to')} {pink(arg)}")
167
173
  else:
168
- print(f" 当前 session: {state.session_id or '()'}")
174
+ sid = state.session_id or "(none)"
175
+ print(f" {faint('session:')} {sid}")
169
176
  elif cmd == "/status":
170
177
  _cmd_status(state)
171
178
  elif cmd == "/agent":
@@ -175,15 +182,16 @@ def _handle_command(state: ChatState, line: str) -> bool:
175
182
  agents = state.container.config.agents.agents
176
183
  if arg in agents:
177
184
  state.agent_name = arg
178
- print(f"\033[1;32m→ 切换到 agent: {arg}\033[0m")
185
+ print(f" {ok('◇')} {faint('agent')} {agent_tag(arg)}")
179
186
  else:
180
- print(f" 无 agent '{arg}'")
187
+ msg = f"无 agent '{arg}'"
188
+ print(f" {error_text(msg)}")
181
189
  elif cmd == "/model":
182
190
  if not arg:
183
191
  _cmd_list_models(state)
184
192
  else:
185
193
  state.model_name = arg
186
- print(f"\033[1;32m→ 切换到 model: {arg}\033[0m")
194
+ print(f" {ok('◇')} {faint('model')} {model_tag(arg)}")
187
195
  elif cmd == "/clear":
188
196
  print("\033[2J\033[H", end="")
189
197
  elif cmd == "/history":
@@ -191,20 +199,18 @@ def _handle_command(state: ChatState, line: str) -> bool:
191
199
  n = int(arg) if arg else 5
192
200
  _cmd_history(state, n)
193
201
  except ValueError:
194
- print(" /history [n]n 必须是整数")
202
+ print(f" {error_text('/history [n]n 须为整数')}")
195
203
  elif cmd == "/save":
196
- # session 自动持久化在每次 turn,无需手动保存
197
- print(" session 已在每次 turn 自动保存")
204
+ print(f" {faint('session 每次 turn 自动保存')}")
198
205
  else:
199
- print(f" 未知命令:{cmd}(输入 /help 查看)")
206
+ print(f" {error_text(f'未知命令: {cmd}')}")
200
207
  return True
201
208
 
202
209
 
203
210
  def _run_turn(state: ChatState, user_input: str) -> None:
204
- """跑一轮对话(同步阻塞)。"""
211
+ """跑一轮对话"""
205
212
  t0 = time.time()
206
213
  try:
207
- # 把 user_input 作为 task
208
214
  result = state.orchestrator.run_agent_sync(
209
215
  state.agent_name,
210
216
  user_input,
@@ -212,24 +218,23 @@ def _run_turn(state: ChatState, user_input: str) -> None:
212
218
  session_id=state.session_id,
213
219
  )
214
220
  elapsed = time.time() - t0
215
- # 显示结果
216
221
  if result.success:
217
222
  content = (result.content or "").strip()
218
- print(f"\n\033[1;37m{content}\033[0m")
223
+ print(f"\n{result_text(content)}")
219
224
  else:
220
- err = result.error or "(无错误信息)"
221
- print(f"\n\033[1;31m✗ {err[:300]}\033[0m")
222
- # 状态行
223
- print(f"\033[2m {elapsed:.1f}s │ iter {result.iterations} │ tools {result.total_tool_calls}\033[0m")
224
- # 保存 session_id(Orchestrator 内部会创建/复用)
225
+ e = result.error or "(无错误信息)"
226
+ print(f"\n {error_text(e[:300])}")
227
+ print(usage_line(elapsed, result.iterations, result.total_tool_calls))
225
228
  if not state.session_id:
226
- state.session_id = result.session_id if hasattr(result, "session_id") and result.session_id else f"chat-{int(state.started_at)}"
229
+ sid = result.session_id if hasattr(result, "session_id") and result.session_id else ""
230
+ state.session_id = sid or f"chat-{int(state.started_at)}"
227
231
  except KeyboardInterrupt:
228
- print("\n\033[1;33m 已中断\033[0m")
232
+ print(f"\n {p('', C.WARN)} {faint('已中断')}")
229
233
  except Exception as e:
230
234
  elapsed = time.time() - t0
231
- print(f"\n\033[1;31m ✗ {type(e).__name__}: {str(e)[:200]}\033[0m")
232
- print(f"\033[2m {elapsed:.1f}s\033[0m")
235
+ msg = f"{type(e).__name__}: {str(e)[:200]}"
236
+ print(f"\n {error_text(msg)}")
237
+ print(f" {faint(f'{elapsed:.1f}s')}")
233
238
 
234
239
 
235
240
  def cmd_chat(
@@ -243,13 +248,12 @@ def cmd_chat(
243
248
  """进入 chat REPL 或单次 query。"""
244
249
  container = AgentSystemContainer(config=config, project_root=project_root)
245
250
 
246
- # 选 agent
247
251
  if not agent_name:
248
252
  agent_name = _resolve_agent(config)
249
253
 
250
- # 验证 agent 存在
251
254
  if agent_name not in config.agents.agents:
252
- print(f"Agent '{agent_name}' 不存在")
255
+ msg = f"Agent '{agent_name}' 不存在"
256
+ print(f" {error_text(msg)}")
253
257
  return 1
254
258
 
255
259
  state = ChatState(
@@ -262,7 +266,6 @@ def cmd_chat(
262
266
  session_id=session_id,
263
267
  )
264
268
 
265
- # 单次 query 模式(--query,非交互)
266
269
  if query:
267
270
  state.turn_count = 1
268
271
  _print_turn_header(state)
@@ -270,10 +273,10 @@ def cmd_chat(
270
273
  _run_turn(state, query)
271
274
  return 0
272
275
 
273
- # REPL 模式
274
- print(BANNER)
275
- _cmd_status(state)
276
- print("\n输入 /help 查看命令。Ctrl+C 中断当前 turn,/exit 退出。\n")
276
+ # REPL
277
+ _print_banner(state)
278
+ print(footer())
279
+ print()
277
280
 
278
281
  while True:
279
282
  try:
@@ -283,7 +286,7 @@ def cmd_chat(
283
286
  print("\n")
284
287
  break
285
288
  except KeyboardInterrupt:
286
- print("\n\033[1;33m(用 /exit 退出)\033[0m")
289
+ print(f"\n {p('用 /exit 退出', C.WARN)}")
287
290
  continue
288
291
 
289
292
  line = line.strip()
@@ -296,5 +299,5 @@ def cmd_chat(
296
299
  state.turn_count += 1
297
300
  _run_turn(state, line)
298
301
 
299
- print("\n\033[1;36m→ Session 已保存。退出 chat。\033[0m")
302
+ print(f"\n {ok('◇')} {faint('Session saved. Bye.')}")
300
303
  return 0
@@ -73,34 +73,34 @@ def _paint(text: str, *codes: str) -> str:
73
73
  def _header(title: str) -> None:
74
74
  """打印章节标题 (带边框)。"""
75
75
  print()
76
- print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.MAGENTA))
77
- print(_paint(" │ ", _C.MAGENTA) + _paint(f"⚙ LBS Setup — {title}", _C.BOLD, _C.GOLD)
78
- + _paint(" " * max(0, 47 - len(title) - 14) + "│", _C.MAGENTA))
79
- print(_paint(" └─────────────────────────────────────────────────────────┘", _C.MAGENTA))
76
+ print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.PINK))
77
+ print(_paint(" │ ", _C.PINK) + _paint(f"⚙ LBS Setup — {title}", _C.BOLD, _C.PINK)
78
+ + _paint(" " * max(0, 47 - len(title) - 14) + "│", _C.PINK))
79
+ print(_paint(" └─────────────────────────────────────────────────────────┘", _C.PINK))
80
80
  print()
81
81
 
82
82
 
83
83
  def _info(msg: str) -> None:
84
- print(_paint(" ℹ ", _C.BLUE) + msg)
84
+ print(_paint(" ℹ ", _C.VIOLET) + msg)
85
85
 
86
86
 
87
87
  def _success(msg: str) -> None:
88
- print(_paint(" ✓ ", _C.GREEN) + _paint(msg, _C.GREEN))
88
+ print(_paint(" ✓ ", _C.OK) + _paint(msg, _C.OK))
89
89
 
90
90
 
91
91
  def _warn(msg: str) -> None:
92
- print(_paint(" ⚠ ", _C.YELLOW) + _paint(msg, _C.YELLOW))
92
+ print(_paint(" ⚠ ", _C.HONEY) + _paint(msg, _C.HONEY))
93
93
 
94
94
 
95
95
  def _error(msg: str) -> None:
96
- print(_paint(" ✖ ", _C.RED) + _paint(msg, _C.RED))
96
+ print(_paint(" ✖ ", _C.ERR) + _paint(msg, _C.ERR))
97
97
 
98
98
 
99
99
  def _prompt(label: str, default: str = "") -> str:
100
100
  """带默认值的输入提示。"""
101
101
  suffix = f" [{default}]" if default else ""
102
102
  try:
103
- val = input(_paint(f" ▸ {label}{suffix}: ", _C.CYAN)).strip()
103
+ val = input(_paint(f" ▸ {label}{suffix}: ", _C.MINT)).strip()
104
104
  except (EOFError, KeyboardInterrupt):
105
105
  print()
106
106
  return default
@@ -109,9 +109,9 @@ def _prompt(label: str, default: str = "") -> str:
109
109
 
110
110
  def _prompt_choice(label: str, options: list[str], default: str = "") -> str:
111
111
  """带选项列表的输入提示。"""
112
- print(_paint(f" ▸ {label}", _C.CYAN))
112
+ print(_paint(f" ▸ {label}", _C.MINT))
113
113
  for i, opt in enumerate(options, 1):
114
- marker = _paint("→", _C.GREEN) if opt == default else " "
114
+ marker = _paint("→", _C.OK) if opt == default else " "
115
115
  print(f" {marker} {i}. {opt}")
116
116
  val = _prompt("选择编号或直接输入", default)
117
117
  if val.isdigit():
@@ -125,7 +125,7 @@ def _prompt_password(label: str) -> str:
125
125
  """密码输入(不回显)。"""
126
126
  import getpass
127
127
  try:
128
- val = getpass.getpass(_paint(f" ▸ {label}: ", _C.CYAN))
128
+ val = getpass.getpass(_paint(f" ▸ {label}: ", _C.MINT))
129
129
  except (EOFError, KeyboardInterrupt):
130
130
  print()
131
131
  return ""
@@ -467,10 +467,10 @@ def run_setup(section: str | None = None) -> int:
467
467
  root.mkdir(parents=True, exist_ok=True)
468
468
 
469
469
  print()
470
- print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.GOLD))
471
- print(_paint(" │ ", _C.GOLD) + _paint("⚙ LBS Agent Setup Wizard", _C.BOLD, _C.GOLD)
472
- + _paint(" │", _C.GOLD))
473
- print(_paint(" └─────────────────────────────────────────────────────────┘", _C.GOLD))
470
+ print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.PINK))
471
+ print(_paint(" │ ", _C.PINK) + _paint("⚙ LBS Agent Setup Wizard", _C.BOLD, _C.PINK)
472
+ + _paint(" │", _C.PINK))
473
+ print(_paint(" └─────────────────────────────────────────────────────────┘", _C.PINK))
474
474
  print()
475
475
  _info(f"配置目录: {root}")
476
476
  print()
@@ -496,15 +496,15 @@ def run_setup(section: str | None = None) -> int:
496
496
 
497
497
  def _print_done() -> None:
498
498
  print()
499
- print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.GREEN))
500
- print(_paint(" │ ", _C.GREEN) + _paint("✅ 配置完成!", _C.BOLD, _C.GREEN)
501
- + _paint(" │", _C.GREEN))
502
- print(_paint(" │ │", _C.GREEN))
503
- print(_paint(" │ ", _C.GREEN) + _paint("配置文件:", _C.BOLD) + paint_path(_models_yaml_path()) + _paint(" │", _C.GREEN))
504
- print(_paint(" │ ", _C.GREEN) + _paint("密钥文件:", _C.BOLD) + paint_path(_env_path()) + _paint(" │", _C.GREEN))
505
- print(_paint(" │ │", _C.GREEN))
506
- print(_paint(" │ ", _C.GREEN) + _paint("现在可以运行:", _C.BOLD) + paint_cmd(" lbs status") + _paint(" │", _C.GREEN))
507
- print(_paint(" └─────────────────────────────────────────────────────────┘", _C.GREEN))
499
+ print(_paint(" ┌─────────────────────────────────────────────────────────┐", _C.OK))
500
+ print(_paint(" │ ", _C.OK) + _paint("✅ 配置完成!", _C.BOLD, _C.OK)
501
+ + _paint(" │", _C.OK))
502
+ print(_paint(" │ │", _C.OK))
503
+ print(_paint(" │ ", _C.OK) + _paint("配置文件:", _C.BOLD) + paint_path(_models_yaml_path()) + _paint(" │", _C.OK))
504
+ print(_paint(" │ ", _C.OK) + _paint("密钥文件:", _C.BOLD) + paint_path(_env_path()) + _paint(" │", _C.OK))
505
+ print(_paint(" │ │", _C.OK))
506
+ print(_paint(" │ ", _C.OK) + _paint("现在可以运行:", _C.BOLD) + paint_cmd(" lbs status") + _paint(" │", _C.OK))
507
+ print(_paint(" └─────────────────────────────────────────────────────────┘", _C.OK))
508
508
  print()
509
509
 
510
510
 
@@ -512,8 +512,8 @@ def paint_path(p: Path) -> str:
512
512
  s = str(p)
513
513
  if len(s) > 40:
514
514
  s = "..." + s[-37:]
515
- return _paint(s, _C.CYAN)
515
+ return _paint(s, _C.MINT)
516
516
 
517
517
 
518
518
  def paint_cmd(cmd: str) -> str:
519
- return _paint(cmd, _C.CYAN, _C.BOLD)
519
+ return _paint(cmd, _C.MINT, _C.BOLD)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baimingtao/lbs-agent",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/scripts/init.js CHANGED
@@ -29,10 +29,15 @@ const PIP = isWin ? path.join(VENV_DIR, 'Scripts', 'pip.exe') : path.join(VENV_D
29
29
  // ── 颜色 ───────────────────────────────────────────────────────
30
30
 
31
31
  const C = {
32
- reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m',
33
- red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m',
34
- blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m',
35
- gold: '\x1b[1;38;2;255;191;0m',
32
+ reset: '\x1b[0m', bold: '\x1b[1m', dim: '\x1b[2m', italic: '\x1b[3m',
33
+ sakura: '\x1b[38;2;255;183;197m', // #FFB7C5
34
+ sakuraDark: '\x1b[38;2;232;154;168m', // #E89AA8
35
+ mint: '\x1b[38;2;152;216;200m', // #98D8C8
36
+ mintDark: '\x1b[38;2;111;196;176m', // #6FC4B0
37
+ violet: '\x1b[38;2;110;90;168m', // #6E5AA8
38
+ honey: '\x1b[38;2;255;184;107m', // #FFB86B
39
+ green: '\x1b[38;2;69;214;163m', // #45D6A3
40
+ red: '\x1b[38;2;255;107;129m', // #FF6B81
36
41
  };
37
42
 
38
43
  function paint(text, ...colors) {
@@ -58,7 +63,7 @@ function ensureDir(dir) {
58
63
  // ── Step 1: 检测系统 Python ────────────────────────────────────
59
64
 
60
65
  function findSystemPython() {
61
- console.log(paint(' 🔍 ', C.gold) + '检测系统 Python...');
66
+ console.log(paint(' 🔍 ', C.pink) + '检测系统 Python...');
62
67
 
63
68
  const candidates = isWin
64
69
  ? ['python', 'python3', 'py -3']
@@ -68,7 +73,7 @@ function findSystemPython() {
68
73
  const result = run(cmd, ['--version'], { silent: true, shell: isWin });
69
74
  if (result.status === 0) {
70
75
  const version = (result.stdout || result.stderr || '').trim();
71
- console.log(paint(' ✓ ', C.green) + `${cmd}: ${version}`);
76
+ console.log(paint(' ✓ ', C.ok) + `${cmd}: ${version}`);
72
77
 
73
78
  const match = version.match(/(\d+)\.(\d+)/);
74
79
  if (match) {
@@ -76,11 +81,11 @@ function findSystemPython() {
76
81
  const minor = parseInt(match[2]);
77
82
  if (major >= 3 && minor >= 10) return cmd;
78
83
  }
79
- console.log(paint(' ⚠ ', C.yellow) + '版本低于 3.10,继续寻找...');
84
+ console.log(paint(' ⚠ ', C.warn) + '版本低于 3.10,继续寻找...');
80
85
  }
81
86
  }
82
87
 
83
- console.error(paint('\n ✖ ', C.red) + '未找到 Python 3.10+');
88
+ console.error(paint('\n ✖ ', C.err) + '未找到 Python 3.10+');
84
89
  console.error(paint(' ', C.dim) + 'Windows: https://www.python.org/downloads/');
85
90
  console.error(paint(' ', C.dim) + 'macOS: brew install python@3.12');
86
91
  console.error(paint(' ', C.dim) + 'Linux: sudo apt install python3 python3-venv');
@@ -91,20 +96,20 @@ function findSystemPython() {
91
96
 
92
97
  function createVenv(sysPython) {
93
98
  if (fs.existsSync(PYTHON)) {
94
- console.log(paint(' ✓ ', C.green) + '虚拟环境已存在,跳过创建');
99
+ console.log(paint(' ✓ ', C.ok) + '虚拟环境已存在,跳过创建');
95
100
  return true;
96
101
  }
97
102
 
98
103
  // 确保 state root 存在
99
104
  ensureDir(STATE_ROOT);
100
- console.log(paint(' 📦 ', C.gold) + `创建 Python 虚拟环境 → ${paint(STATE_ROOT + '/venv', C.cyan)}`);
105
+ console.log(paint(' 📦 ', C.pink) + `创建 Python 虚拟环境 → ${paint(STATE_ROOT + '/venv', C.mint)}`);
101
106
 
102
107
  const result = run(sysPython, ['-m', 'venv', VENV_DIR]);
103
108
  if (result.status !== 0 || !fs.existsSync(PYTHON)) {
104
- console.error(paint(' ✖ ', C.red) + '创建虚拟环境失败');
109
+ console.error(paint(' ✖ ', C.err) + '创建虚拟环境失败');
105
110
  return false;
106
111
  }
107
- console.log(paint(' ✓ ', C.green) + 'venv 已创建');
112
+ console.log(paint(' ✓ ', C.ok) + 'venv 已创建');
108
113
  return true;
109
114
  }
110
115
 
@@ -112,17 +117,17 @@ function createVenv(sysPython) {
112
117
 
113
118
  function installDeps() {
114
119
  if (!fs.existsSync(REQUIREMENTS)) {
115
- console.error(paint(' ✖ ', C.red) + 'requirements.txt 不存在: ' + REQUIREMENTS);
120
+ console.error(paint(' ✖ ', C.err) + 'requirements.txt 不存在: ' + REQUIREMENTS);
116
121
  return false;
117
122
  }
118
123
 
119
- console.log(paint(' 📥 ', C.gold) + '安装 Python 依赖 (可能需要 1-2 分钟)...');
124
+ console.log(paint(' 📥 ', C.pink) + '安装 Python 依赖 (可能需要 1-2 分钟)...');
120
125
  const result = run(PIP, ['install', '-r', REQUIREMENTS, '--disable-pip-version-check']);
121
126
  if (result.status !== 0) {
122
- console.error(paint(' ✖ ', C.red) + '依赖安装失败');
127
+ console.error(paint(' ✖ ', C.err) + '依赖安装失败');
123
128
  return false;
124
129
  }
125
- console.log(paint(' ✓ ', C.green) + '依赖安装完成');
130
+ console.log(paint(' ✓ ', C.ok) + '依赖安装完成');
126
131
  return true;
127
132
  }
128
133
 
@@ -156,22 +161,22 @@ function createDefaultDirs() {
156
161
  fs.writeFileSync(configPath, defaultConfig, 'utf-8');
157
162
  }
158
163
 
159
- console.log(paint(' ✓ ', C.green) + '目录结构已创建');
164
+ console.log(paint(' ✓ ', C.ok) + '目录结构已创建');
160
165
  }
161
166
 
162
167
  // ── Step 5: 验证 ───────────────────────────────────────────────
163
168
 
164
169
  function verifyInstall() {
165
- console.log(paint(' 🔍 ', C.gold) + '验证安装...');
170
+ console.log(paint(' 🔍 ', C.pink) + '验证安装...');
166
171
  const result = run(PYTHON, [path.join(PKG_ROOT, 'lbs.py'), 'status'], {
167
172
  silent: true,
168
173
  cwd: PKG_ROOT,
169
174
  env: { ...process.env, LBS_HOME: STATE_ROOT },
170
175
  });
171
176
  if (result.status === 0) {
172
- console.log(paint(' ✓ ', C.green) + 'lbs status 运行正常');
177
+ console.log(paint(' ✓ ', C.ok) + 'lbs status 运行正常');
173
178
  } else {
174
- console.log(paint(' ⚠ ', C.yellow) + 'lbs status 运行异常(可能是配置问题,不影响初始化)');
179
+ console.log(paint(' ⚠ ', C.warn) + 'lbs status 运行异常(可能是配置问题,不影响初始化)');
175
180
  }
176
181
  return true;
177
182
  }
@@ -186,19 +191,19 @@ function writeFlag() {
186
191
  platform: os.platform(),
187
192
  node_version: process.version,
188
193
  }, null, 2));
189
- console.log(paint(' ✓ ', C.green) + '.lbs-initialized 已创建');
194
+ console.log(paint(' ✓ ', C.ok) + '.lbs-initialized 已创建');
190
195
  }
191
196
 
192
197
  // ── 主流程 ─────────────────────────────────────────────────────
193
198
 
194
199
  function main() {
195
200
  console.log();
196
- console.log(paint(' ┌─────────────────────────────────────────────────────────┐', C.gold));
197
- console.log(paint(' │ ', C.gold) + paint('⚙ LBS Agent — 初始化', C.bold, C.gold) + paint(' │', C.gold));
198
- console.log(paint(' └─────────────────────────────────────────────────────────┘', C.gold));
201
+ console.log(paint(' ┌─────────────────────────────────────────────────────────┐', C.pink));
202
+ console.log(paint(' │ ', C.pink) + paint('⚙ LBS Agent — 初始化', C.bold, C.pink) + paint(' │', C.pink));
203
+ console.log(paint(' └─────────────────────────────────────────────────────────┘', C.pink));
199
204
  console.log();
200
- console.log(paint(' 包目录 (只读): ', C.dim) + paint(PKG_ROOT, C.cyan));
201
- console.log(paint(' 状态目录 (可写): ', C.dim) + paint(STATE_ROOT, C.cyan));
205
+ console.log(paint(' 包目录 (只读): ', C.dim) + paint(PKG_ROOT, C.mint));
206
+ console.log(paint(' 状态目录 (可写): ', C.dim) + paint(STATE_ROOT, C.mint));
202
207
  console.log();
203
208
 
204
209
  // Step 1: Python
@@ -221,17 +226,17 @@ function main() {
221
226
  writeFlag();
222
227
 
223
228
  console.log();
224
- console.log(paint(' ┌─────────────────────────────────────────────────────────┐', C.green));
225
- console.log(paint(' │ ', C.green) + paint('✅ 初始化完成!', C.bold, C.green) + paint(' │', C.green));
226
- console.log(paint(' │ │', C.green));
227
- console.log(paint(' │ ', C.green) + paint('下一步:', C.bold) + paint(' │', C.green));
228
- console.log(paint(' │ ', C.green) + paint(' lbs setup 配置模型/供应商/Agent', C.cyan) + paint(' │', C.green));
229
- console.log(paint(' │ ', C.green) + paint(' lbs status 查看系统状态', C.cyan) + paint(' │', C.green));
230
- console.log(paint(' │ ', C.green) + paint(' lbs help 查看所有命令', C.cyan) + paint(' │', C.green));
231
- console.log(paint(' │ ', C.green) + paint(' lbs web 启动 Web 界面', C.cyan) + paint(' │', C.green));
232
- console.log(paint(' │ │', C.green));
233
- console.log(paint(' │ ', C.green) + paint('状态目录: ', C.dim) + paint(STATE_ROOT, C.cyan) + paint(' │', C.green));
234
- console.log(paint(' └─────────────────────────────────────────────────────────┘', C.green));
229
+ console.log(paint(' ┌─────────────────────────────────────────────────────────┐', C.ok));
230
+ console.log(paint(' │ ', C.ok) + paint('✅ 初始化完成!', C.bold, C.ok) + paint(' │', C.ok));
231
+ console.log(paint(' │ │', C.ok));
232
+ console.log(paint(' │ ', C.ok) + paint('下一步:', C.bold) + paint(' │', C.ok));
233
+ console.log(paint(' │ ', C.ok) + paint(' lbs setup 配置模型/供应商/Agent', C.mint) + paint(' │', C.ok));
234
+ console.log(paint(' │ ', C.ok) + paint(' lbs status 查看系统状态', C.mint) + paint(' │', C.ok));
235
+ console.log(paint(' │ ', C.ok) + paint(' lbs help 查看所有命令', C.mint) + paint(' │', C.ok));
236
+ console.log(paint(' │ ', C.ok) + paint(' lbs web 启动 Web 界面', C.mint) + paint(' │', C.ok));
237
+ console.log(paint(' │ │', C.ok));
238
+ console.log(paint(' │ ', C.ok) + paint('状态目录: ', C.dim) + paint(STATE_ROOT, C.mint) + paint(' │', C.ok));
239
+ console.log(paint(' └─────────────────────────────────────────────────────────┘', C.ok));
235
240
  console.log();
236
241
  }
237
242