skyloom 1.10.0 → 1.12.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.
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ /**
3
+ * 天空织机 TUI — Full-screen terminal interface
4
+ *
5
+ * Layout:
6
+ * ┌─────────────────────────────────────────┐
7
+ * │ ≋ 雾 Fog · deepseek-chat · $0.02 · ⏻ │ ← header bar
8
+ * ├──────────┬──────────────────────────────┤
9
+ * │ ☼ 晴 Fair│ ✦ 你好!有什么可以帮你的? │
10
+ * │ ✱ 霜 │ │ ← messages
11
+ * │ ≋ 雾 ▸ │ 用户消息右对齐 │
12
+ * │ ❉ 雪 │ │
13
+ * │ ∘ 露 │ │
14
+ * │ ⸽ 雨 │ │
15
+ * ├──────────┴──────────────────────────────┤
16
+ * │ ┌─ /fog /rain /frost /snow ───────┐│ ← command palette (popup)
17
+ * │ ▶ /fog Switch to Fog ││
18
+ * │ /rain Switch to Rain ││
19
+ * │ └──────────────────────────────────────┘│
20
+ * │ > hello world [send] │ ← input bar
21
+ * └─────────────────────────────────────────┘
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
36
+ }) : function(o, v) {
37
+ o["default"] = v;
38
+ });
39
+ var __importStar = (this && this.__importStar) || (function () {
40
+ var ownKeys = function(o) {
41
+ ownKeys = Object.getOwnPropertyNames || function (o) {
42
+ var ar = [];
43
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
44
+ return ar;
45
+ };
46
+ return ownKeys(o);
47
+ };
48
+ return function (mod) {
49
+ if (mod && mod.__esModule) return mod;
50
+ var result = {};
51
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
52
+ __setModuleDefault(result, mod);
53
+ return result;
54
+ };
55
+ })();
56
+ var __importDefault = (this && this.__importDefault) || function (mod) {
57
+ return (mod && mod.__esModule) ? mod : { "default": mod };
58
+ };
59
+ Object.defineProperty(exports, "__esModule", { value: true });
60
+ exports.readInput = readInput;
61
+ const readline = __importStar(require("readline"));
62
+ const chalk_1 = __importDefault(require("chalk"));
63
+ /* ── Slash commands with icons ── */
64
+ const AGENT_CMDS = [
65
+ ["≋", "/fog", "雾 Fog · 松烟墨"],
66
+ ["⸽", "/rain", "雨 Rain · 石青"],
67
+ ["✱", "/frost", "霜 Frost · 石绿"],
68
+ ["❉", "/snow", "雪 Snow · 铅白"],
69
+ ["∘", "/dew", "露 Dew · 赭石"],
70
+ ["☼", "/fair", "晴 Fair · 朱砂"],
71
+ ];
72
+ const ACTION_CMDS = [
73
+ ["/help", "所有命令"],
74
+ ["/clear", "清屏"],
75
+ ["/status", "状态总览"],
76
+ ["/cost", "费用统计"],
77
+ ["/cost reset", "费用归零"],
78
+ ["/compact", "压缩上下文"],
79
+ ["/retry", "重发上条"],
80
+ ["/setup", "配置向导"],
81
+ ["/apikey set <p> <k>", "保存API Key"],
82
+ ["/apikey", "查看API Key"],
83
+ ["/model", "模型管理"],
84
+ ["/task <goal>", "多Agent编排"],
85
+ ["/memory", "记忆状态"],
86
+ ["/memory clear", "清除记忆"],
87
+ ["/sessions", "会话列表"],
88
+ ["/workspace", "工作空间"],
89
+ ["/mcp", "MCP服务器"],
90
+ ["/version", "版本信息"],
91
+ ["/quit", "退出"],
92
+ ];
93
+ /* ── Box drawing characters ── */
94
+ const B = { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│", l: "├", r: "┤", cross: "┼", t: "┬", b: "┴", L: "░", o: "●" };
95
+ function bar(start, fill, end, width) {
96
+ return start + fill.repeat(Math.max(0, width)) + end;
97
+ }
98
+ /* ── Render sidebar ── */
99
+ function renderSidebar(agent, agents, h) {
100
+ const lines = [];
101
+ const W = 14; // sidebar width in chars
102
+ // Header
103
+ lines.push(chalk_1.default.cyan(bar(B.L + " 天空织机 ".padEnd(W - 2, B.L) + B.r, "", "", 0)));
104
+ lines.push(chalk_1.default.dim(B.v + " Skyloom " + B.v));
105
+ for (const n of ["fog", "rain", "frost", "snow", "dew", "fair"]) {
106
+ const isActive = agent.name === n;
107
+ const display = { fog: "≋ 雾 Fog", rain: "⸽ 雨 Rain", frost: "✱ 霜 Frost", snow: "❉ 雪 Snow", dew: "∘ 露 Dew", fair: "☼ 晴 Fair" };
108
+ const line = isActive
109
+ ? chalk_1.default.cyan(B.v + " " + B.o + " " + display[n].padEnd(W - 5) + B.v)
110
+ : chalk_1.default.dim(B.v + " " + display[n].padEnd(W - 5) + B.v);
111
+ lines.push(line);
112
+ }
113
+ // Fill remaining space
114
+ for (let i = lines.length; i < h; i++) {
115
+ lines.push(chalk_1.default.dim(B.v + " ".repeat(W - 2) + B.v));
116
+ }
117
+ // Footer
118
+ try {
119
+ const cu = agent.contextUsage();
120
+ const pct = cu.pct || 0;
121
+ lines.push(chalk_1.default.dim(B.v + " ctx " + String(pct).padStart(3) + "%" + " ".repeat(W - 10) + B.v));
122
+ }
123
+ catch {
124
+ lines.push(chalk_1.default.dim(B.v + " ".repeat(W - 2) + B.v));
125
+ }
126
+ lines.push(chalk_1.default.dim(bar(B.bl, B.h, B.br, W - 2)));
127
+ return lines;
128
+ }
129
+ /* ── Render command palette ── */
130
+ function renderPalette(filter, selIdx, width) {
131
+ const lines = [];
132
+ const W = Math.min(width - 4, 56);
133
+ // Agent section first
134
+ const agentMatches = AGENT_CMDS.filter(([, cmd]) => cmd.includes(filter) || filter === "/");
135
+ const actionMatches = ACTION_CMDS.filter(([cmd]) => cmd.includes(filter));
136
+ const allItems = [];
137
+ for (const [icon, cmd, desc] of agentMatches)
138
+ allItems.push(`${icon} ${cmd.padEnd(16)} ${desc}`);
139
+ for (const [cmd, desc] of actionMatches)
140
+ allItems.push(` ${cmd.padEnd(18)} ${desc}`);
141
+ if (allItems.length === 0 && filter.length > 1) {
142
+ // No matches — show message
143
+ lines.push(chalk_1.default.dim(bar(B.tl, B.h, B.tr, W)));
144
+ lines.push(chalk_1.default.dim(B.v + " 未找到匹配命令 (esc 关闭)".padEnd(W) + B.v));
145
+ lines.push(chalk_1.default.dim(bar(B.bl, B.h, B.br, W)));
146
+ return lines;
147
+ }
148
+ if (allItems.length === 0)
149
+ return lines;
150
+ const start = Math.max(0, Math.min(selIdx - 5, allItems.length - 10));
151
+ const end = Math.min(allItems.length, start + 10);
152
+ lines.push(chalk_1.default.dim(bar(B.tl, B.h, B.tr, W - 5)) + " ".padEnd(5));
153
+ for (let i = start; i < end; i++) {
154
+ const item = allItems[i];
155
+ const isSelected = i === selIdx;
156
+ const pad = W - item.replace(/\x1b\[[0-9;]*m/g, "").length + 2; // account for ANSI codes
157
+ lines.push(isSelected
158
+ ? chalk_1.default.cyan(B.v + " ▶ " + item).padEnd(W + 10) + chalk_1.default.cyan(B.v)
159
+ : chalk_1.default.dim(B.v + " " + item).padEnd(W + 10) + chalk_1.default.dim(B.v));
160
+ }
161
+ lines.push(chalk_1.default.dim(bar(B.bl, B.h, B.br, W - 5)) + " ".padEnd(5));
162
+ return lines;
163
+ }
164
+ /* ── Render message ── */
165
+ function renderMessage(role, text, width) {
166
+ const lines = [];
167
+ const maxW = Math.min(width - 24, 60);
168
+ const prefix = role === "user" ? " " : " ";
169
+ const suffix = role === "user" ? "" : "";
170
+ for (const para of text.split("\n")) {
171
+ let remaining = para;
172
+ while (remaining.length > 0) {
173
+ const cut = remaining.length > maxW ? remaining.lastIndexOf(" ", maxW) : remaining.length;
174
+ const idx = cut > 0 ? cut : maxW;
175
+ const line = remaining.slice(0, idx).trimEnd();
176
+ if (role === "user") {
177
+ lines.push(chalk_1.default.dim(" ".repeat(Math.max(0, width - line.length - 4))) + chalk_1.default.cyan(line) + " ");
178
+ }
179
+ else if (role === "assistant") {
180
+ lines.push(prefix + line + suffix);
181
+ }
182
+ else {
183
+ lines.push(chalk_1.default.dim(" " + line));
184
+ }
185
+ remaining = remaining.slice(idx).trimStart();
186
+ }
187
+ }
188
+ return lines;
189
+ }
190
+ /* ── Read input with command palette ── */
191
+ function readInput(stdin, stdout, ctx) {
192
+ return new Promise(resolve => {
193
+ let buf = "";
194
+ let cursor = 0;
195
+ let palette = false;
196
+ let selIdx = 0;
197
+ function render() {
198
+ // Clear screen and render full TUI
199
+ readline.cursorTo(stdout, 0, 0);
200
+ readline.clearScreenDown(stdout);
201
+ const w = stdout.columns || 80;
202
+ const h = stdout.rows || 24;
203
+ const sidebarW = 16;
204
+ // Header
205
+ stdout.write(chalk_1.default.bgBlack.cyan(" 天空织机 Skyloom v1.10 ".padEnd(w - 20, " ")) + chalk_1.default.bgBlack.dim(" deepseek".padEnd(10)) + chalk_1.default.bgBlack("\n"));
206
+ stdout.write(chalk_1.default.dim(bar("", B.h, "", w)) + "\n");
207
+ // Sidebar
208
+ const sidebar = renderSidebar(ctx.agent, ctx.agents, h - 5);
209
+ for (let i = 0; i < sidebar.length && i < h - 5; i++) {
210
+ stdout.write(sidebar[i] + "\n");
211
+ }
212
+ // Command palette (overlaid)
213
+ if (palette) {
214
+ const paletteLines = renderPalette(buf, selIdx, w);
215
+ // Move cursor up to position palette below header
216
+ const paletteY = 2;
217
+ for (let i = 0; i < paletteLines.length; i++) {
218
+ stdout.write(`\x1b[${paletteY + i};${sidebarW}H`); // position cursor
219
+ stdout.write(paletteLines[i]);
220
+ }
221
+ }
222
+ // Input bar at bottom
223
+ readline.cursorTo(stdout, sidebarW, h - 1);
224
+ stdout.write(chalk_1.default.dim(B.l + B.h.repeat(w - sidebarW - 2) + B.r));
225
+ readline.cursorTo(stdout, sidebarW, h);
226
+ stdout.write(chalk_1.default.cyan(" > ") + buf.slice(0, cursor) + chalk_1.default.inverse(buf[cursor] || " ") + buf.slice(cursor + 1));
227
+ }
228
+ if (!stdin.isTTY) {
229
+ const rl = readline.createInterface({ input: stdin });
230
+ rl.on("line", (line) => { rl.close(); resolve(line.trim()); });
231
+ return;
232
+ }
233
+ stdin.setRawMode(true);
234
+ stdin.resume();
235
+ render();
236
+ let escBuf = "";
237
+ stdin.on("data", (data) => {
238
+ const str = data.toString();
239
+ escBuf += str;
240
+ if (escBuf.startsWith("\x1b[") && escBuf.length >= 3) {
241
+ const code = escBuf[2];
242
+ escBuf = "";
243
+ if (code === "A") {
244
+ if (palette)
245
+ selIdx = Math.max(0, selIdx - 1);
246
+ render();
247
+ return;
248
+ }
249
+ if (code === "B") {
250
+ if (palette) {
251
+ const all = [...AGENT_CMDS.map(c => c[1]), ...ACTION_CMDS.map(c => c[0])];
252
+ selIdx = Math.min(all.filter(a => a.includes(buf)).length - 1, selIdx + 1);
253
+ }
254
+ render();
255
+ return;
256
+ }
257
+ if (code === "C") {
258
+ if (cursor < buf.length)
259
+ cursor++;
260
+ render();
261
+ return;
262
+ }
263
+ if (code === "D") {
264
+ if (cursor > 0)
265
+ cursor--;
266
+ render();
267
+ return;
268
+ }
269
+ }
270
+ for (const ch of escBuf) {
271
+ escBuf = "";
272
+ if (ch === "\x1b") {
273
+ palette = false;
274
+ render();
275
+ return;
276
+ }
277
+ if (ch === "\r" || ch === "\n") {
278
+ if (palette) {
279
+ const all = [...AGENT_CMDS.map(c => c[1]), ...ACTION_CMDS.map(c => c[0])];
280
+ const filtered = all.filter(a => a.includes(buf));
281
+ if (filtered[selIdx])
282
+ buf = filtered[selIdx];
283
+ palette = false;
284
+ render();
285
+ stdin.setRawMode(false);
286
+ stdin.pause();
287
+ resolve(buf.trim());
288
+ return;
289
+ }
290
+ stdin.setRawMode(false);
291
+ stdin.pause();
292
+ resolve(buf.trim());
293
+ return;
294
+ }
295
+ if (ch === "\t") { /* ignore */
296
+ return;
297
+ }
298
+ if (ch === "\x7f" || ch === "\b") {
299
+ if (cursor > 0) {
300
+ buf = buf.slice(0, cursor - 1) + buf.slice(cursor);
301
+ cursor--;
302
+ }
303
+ if (!buf)
304
+ palette = false;
305
+ render();
306
+ return;
307
+ }
308
+ if (ch === "\x03") {
309
+ stdin.setRawMode(false);
310
+ stdin.pause();
311
+ resolve("/quit");
312
+ return;
313
+ }
314
+ if (ch >= " ") {
315
+ buf = buf.slice(0, cursor) + ch + buf.slice(cursor);
316
+ cursor++;
317
+ if (ch === "/") {
318
+ palette = true;
319
+ selIdx = 0;
320
+ }
321
+ else if (palette)
322
+ selIdx = 0;
323
+ render();
324
+ return;
325
+ }
326
+ }
327
+ });
328
+ });
329
+ }
330
+ //# sourceMappingURL=tui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui.js","sourceRoot":"","sources":["../../src/cli/tui.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skyloom",
3
- "version": "1.10.0",
3
+ "version": "1.12.0",
4
4
  "description": "天空织机 Skyloom — 6 weather-themed AI agents: Fog, Rain, Frost, Snow, Dew, Fair",
5
5
  "preferGlobal": true,
6
6
  "type": "commonjs",
package/src/cli/main.ts CHANGED
@@ -10,6 +10,7 @@ import { createSystemContext, orchestrateTask } from "../core/factory";
10
10
  import { loadConfig, USER_CONFIG_DIR } from "../core/config";
11
11
  import { classify } from "../core/router";
12
12
  import { InteractiveMode, ModeController } from "./mode";
13
+ import { readInput, type TUIContext } from "./tui";
13
14
 
14
15
  const MODE = new ModeController();
15
16
  const VERSION = (() => { try { return require("../../package.json").version; } catch { return "1.5.2"; } })();
@@ -180,15 +181,70 @@ function saveApiKey(provider: string, key: string): void {
180
181
  fs.writeFileSync(cfgPath, yaml.stringify(cfg), "utf-8");
181
182
  }
182
183
 
184
+ /* ═══════════════════════════════════════
185
+ Interactive setup wizard
186
+ ═══════════════════════════════════════ */
187
+ async function setupWizard(): Promise<{ provider: string; key: string; model: string } | null> {
188
+ const providers = [
189
+ { id: "deepseek", name: "DeepSeek", models: ["deepseek-chat","deepseek-v4-flash","deepseek-v4-pro","deepseek-reasoner"] },
190
+ { id: "openai", name: "OpenAI", models: ["gpt-4.1","gpt-4o","gpt-4o-mini","o4-mini"] },
191
+ { id: "anthropic", name: "Anthropic", models: ["claude-sonnet-4-6","claude-opus-4-7","claude-haiku-4-5"] },
192
+ { id: "google", name: "Google Gemini", models: ["gemini-2.5-pro","gemini-2.5-flash"] },
193
+ { id: "groq", name: "Groq", models: ["llama-3.3-70b","mixtral-8x7b"] },
194
+ { id: "openrouter", name: "OpenRouter (多模型)", models: ["openai/gpt-4.1","anthropic/claude-sonnet-4-6","google/gemini-2.5-flash","meta-llama/llama-4-maverick"] },
195
+ { id: "mistral", name: "Mistral", models: ["mistral-large","mistral-small"] },
196
+ { id: "xai", name: "xAI (Grok)", models: ["grok-4"] },
197
+ { id: "ollama", name: "Ollama 本地", models: ["llama3","qwen2.5","deepseek-r1"] },
198
+ ];
199
+
200
+ process.stdout.write("\n" + chalk.cyan(" ✦ API Key 设置向导 ✦\n\n"));
201
+ process.stdout.write(chalk.dim(" 选择 Provider(Key 保存在 ~/.skyloom/config.yaml):\n\n"));
202
+
203
+ for (let i = 0; i < providers.length; i++) {
204
+ process.stdout.write(chalk.dim(` ${String(i+1).padStart(2)}. ${providers[i].name.padEnd(22)} ${providers[i].models.slice(0,3).join(", ")}\n`));
205
+ }
206
+
207
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
208
+ const ask = (q: string): Promise<string> => new Promise(r => rl.question(q, r));
209
+
210
+ const choice = await ask(chalk.cyan("\n 编号 (1-"+providers.length+", q退出): "));
211
+ if (choice === "q") { rl.close(); return null; }
212
+ const idx = parseInt(choice) - 1;
213
+ if (isNaN(idx) || idx < 0 || idx >= providers.length) { rl.close(); process.stdout.write(chalk.dim(" 已取消\n")); return null; }
214
+
215
+ const prov = providers[idx];
216
+ const key = await ask(chalk.cyan(` ${prov.name} API Key: `));
217
+ if (!key.trim()) { rl.close(); return null; }
218
+
219
+ saveApiKey(prov.id, key.trim());
220
+
221
+ process.stdout.write(chalk.dim("\n 可用模型:\n"));
222
+ for (let i = 0; i < prov.models.length; i++) process.stdout.write(chalk.dim(` ${i+1}. ${prov.models[i]}\n`));
223
+
224
+ const mc = await ask(chalk.cyan("\n 选择模型 (1-"+prov.models.length+", 默认1): ")) || "1";
225
+ const mi = (parseInt(mc) || 1) - 1;
226
+ const model = prov.models[Math.max(0, Math.min(mi, prov.models.length - 1))];
227
+
228
+ // Save to config
229
+ const path = require("path"); const fs = require("fs"); const yaml = require("yaml");
230
+ const cfgPath = path.join(require("os").homedir(), ".skyloom", "config.yaml");
231
+ let cfg: any = {}; if (fs.existsSync(cfgPath)) { try { cfg = yaml.parse(fs.readFileSync(cfgPath, "utf-8")) || {}; } catch { } }
232
+ cfg.default_model = model; cfg.default_provider = prov.id;
233
+ fs.writeFileSync(cfgPath, yaml.stringify(cfg), "utf-8");
234
+
235
+ rl.close();
236
+ process.stdout.write(chalk.green(`\n ✓ ${prov.name} · ${model} · 就绪!\n\n`));
237
+ return { provider: prov.id, key: key.trim(), model };
238
+ }
239
+
183
240
  async function chat(agentName: string, modelOverride?: string): Promise<void> {
184
241
  const haveKey = checkApiKeys();
185
242
  if (!haveKey) {
186
- process.stdout.write("\n" + chalk.yellow(" No API key configured.\n"));
187
- process.stdout.write(chalk.dim(" Quick setup:\n"));
188
- process.stdout.write(chalk.dim(" sky apikey set deepseek sk-your-key-here\n"));
189
- process.stdout.write(chalk.dim(" Or env var:\n"));
190
- process.stdout.write(chalk.dim(" $env:DEEPSEEK_API_KEY = \"sk-your-key\"\n\n"));
191
- process.exit(1);
243
+ process.stdout.write("\n" + chalk.cyan(" 天空织机 Skyloom ✦\n"));
244
+ process.stdout.write(chalk.dim(" 检测到未配置 API Key,进入设置向导...\n\n"));
245
+ const result = await setupWizard();
246
+ if (!result) { process.stdout.write(chalk.red(" 设置未完成,请重新运行 sky 配置。\n")); process.exit(0); }
247
+ process.stdout.write(chalk.green(` ✓ ${result.provider} 已就绪 · 模型: ${result.model}\n\n`));
192
248
  }
193
249
 
194
250
  const ctx = createSystemContext();
@@ -217,54 +273,57 @@ async function chat(agentName: string, modelOverride?: string): Promise<void> {
217
273
 
218
274
  process.stdout.write(chalk.dim(" Key: " + haveKey + "\n\n"));
219
275
 
220
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
276
+ // ── TUI loop ──
277
+ const ctx_: TUIContext = { agent: currentAgent, agents: ctx.agentMap, model: "default", cost: "$0", width: 80, height: 24 };
221
278
 
222
- function ask() { rl.question(chalk.cyan(" " + currentAgent.displayName + " ❯ "), handler); }
223
- async function handler(inp: string) {
224
- inp = inp.trim();
225
- if (!inp) { ask(); return; }
279
+ while (true) {
280
+ const inp = await readInput(process.stdin, process.stdout, ctx_);
281
+ if (!inp) continue;
226
282
 
227
283
  const cmdL = inp.toLowerCase();
228
284
 
229
285
  // Agent switch
286
+ let switched = false;
230
287
  for (const n of AGENT_NAMES) {
231
- if (cmdL === "/" + n) { const a = ctx.agentMap.get(n); if (a) { await a.init(); currentAgent = a; } process.stdout.write(chalk.dim(" ⟳ " + AGENT_DISPLAY[n] + "\n")); ask(); return; }
288
+ if (cmdL === "/" + n) { const a = ctx.agentMap.get(n); if (a) { await a.init(); currentAgent = a; ctx_.agent = a; } switched = true; break; }
232
289
  }
233
-
234
- if (cmdL === "/quit" || cmdL === "/exit") { process.stdout.write(chalk.dim("\n Session ended\n")); rl.close(); await ctx.closeAll(); process.exit(0); return; }
235
- if (cmdL === "/help") { process.stdout.write(helpText()); ask(); return; }
236
- if (cmdL === "/clear") { console.clear(); welcome(agent); process.stdout.write(chalk.dim(" Key: " + haveKey + "\n\n")); ask(); return; }
237
- if (cmdL === "/status") { process.stdout.write(chalk.bold("\n " + currentAgent.displayName + " (" + currentAgent.name + ")\n") + chalk.dim(" State: " + currentAgent.state + " · Memory: " + currentAgent.memory.shortTerm.length + " msgs\n\n")); ask(); return; }
238
- if (cmdL === "/cost") { process.stdout.write(chalk.bold("\n Total: " + formatCost(ctx.llm.getTotalCost()) + "\n\n")); ask(); return; }
239
- if (cmdL === "/compact") { const r = await currentAgent.compact(); process.stdout.write(chalk.green(" " + r + "\n\n")); ask(); return; }
240
- if (cmdL === "/version") { process.stdout.write(" Skyloom v" + VERSION + "\n"); ask(); return; }
241
- if (cmdL.startsWith("/task ")) { const g = inp.slice(6); process.stdout.write(chalk.cyan("\n " + g + "\n\n")); await runTask(g); ask(); return; }
242
- if (cmdL.startsWith("/apikey set ")) { const parts = inp.split(/\s+/); if (parts.length >= 4) { saveApiKey(parts[2], parts[3]); process.stdout.write(chalk.green(" Saved " + parts[2] + " API key to ~/.skyloom/config.yaml\n\n")); } else { process.stdout.write(chalk.yellow(" Usage: /apikey set <provider> <key>\n\n")); } ask(); return; }
243
- if (cmdL === "/apikey") {
244
- const providers = ["openai","deepseek","anthropic","groq","openrouter"];
245
- process.stdout.write(chalk.bold("\n API Keys:\n"));
246
- for (const p of providers) { const envVar = p.toUpperCase() + "_API_KEY"; const hasEnv = !!process.env[envVar]; process.stdout.write(chalk.dim(" " + p.padEnd(14) + (hasEnv ? chalk.green("env") : chalk.dim("")) + "\n")); }
247
- process.stdout.write(chalk.dim("\n Save: /apikey set <provider> <key>\n\n"));
248
- ask(); return;
249
- }
250
- if (inp.startsWith("/")) { process.stdout.write(helpText()); ask(); return; }
290
+ if (switched) continue;
291
+ if (cmdL === "/quit" || cmdL === "/exit") break;
292
+ if (cmdL === "/clear") { console.clear(); continue; }
293
+ if (cmdL === "/help") { process.stdout.write(helpText()); continue; }
294
+ if (cmdL === "/version") { process.stdout.write(" Skyloom v" + VERSION + "\n"); continue; }
295
+ if (cmdL === "/status") { process.stdout.write(chalk.bold("\n " + currentAgent.displayName + " (" + currentAgent.name + ")\n") + chalk.dim(" State: " + currentAgent.state + " · Memory: " + currentAgent.memory.shortTerm.length + " msgs\n\n")); continue; }
296
+ if (cmdL === "/cost") { process.stdout.write(chalk.bold("\n Total: " + formatCost(ctx.llm.getTotalCost()) + "\n\n")); continue; }
297
+ if (cmdL === "/cost reset") { (ctx.llm as any).resetUsageStats?.(); process.stdout.write(chalk.dim(" Stats reset\n")); continue; }
298
+ if (cmdL === "/compact") { const r = await currentAgent.compact(); process.stdout.write(chalk.green(" " + r + "\n\n")); continue; }
299
+ if (cmdL === "/memory") { process.stdout.write(chalk.dim(" Short-term: " + currentAgent.memory.shortTerm.length + " msgs · Working: " + Object.keys(currentAgent.memory.working).length + " keys\n")); continue; }
300
+ if (cmdL === "/memory clear") { await currentAgent.memory.clearShortTerm(); process.stdout.write(chalk.dim(" Memory cleared\n")); continue; }
301
+ if (cmdL === "/workspace") { process.stdout.write(chalk.dim(" " + (ctx.workspacePath || "default") + "\n")); continue; }
302
+ if (cmdL === "/sessions") { const ss = await currentAgent.memory.listSessions(); process.stdout.write(chalk.bold("\n Sessions:\n")); for (const s of ss.slice(0, 10)) process.stdout.write(chalk.dim(" " + s.id?.slice(0, 10) + "... " + s.preview + " (" + s.messageCount + " msgs)\n")); continue; }
303
+ if (cmdL === "/mcp") { process.stdout.write(chalk.dim(" " + (ctx.mcpStatus?.join(", ") || "none") + "\n")); continue; }
304
+ if (cmdL.startsWith("/apikey set ")) { const p = inp.split(/\s+/); if (p.length >= 4) { saveApiKey(p[2], p[3]); process.stdout.write(chalk.green(" ✓ Saved " + p[2] + " API key\n")); } else { process.stdout.write(chalk.yellow(" Usage: /apikey set <provider> <key>\n")); } continue; }
305
+ if (cmdL === "/apikey") { process.stdout.write(chalk.bold("\n API Keys:\n")); for (const p of ["openai","deepseek","anthropic","groq","openrouter"]) { process.stdout.write(chalk.dim(" " + p.padEnd(14) + (!!process.env[p.toUpperCase() + "_API_KEY"] ? chalk.green("env") : chalk.dim("—")) + "\n")); } process.stdout.write("\n"); continue; }
306
+ if (cmdL.startsWith("/task ")) { const g = inp.slice(6); process.stdout.write(chalk.cyan("\n ✦ " + g + "\n\n")); await runTask(g); continue; }
307
+ if (cmdL === "/setup") { const r = await setupWizard(); if (r) process.stdout.write(chalk.green(` ${r.provider} · ${r.model} — Ready!\n`)); continue; }
308
+ if (cmdL.startsWith("/model")) { process.stdout.write(chalk.dim(" Run /setup to reconfigure models\n")); continue; }
309
+ if (inp.startsWith("/")) { process.stdout.write(helpText()); continue; }
251
310
 
252
311
  // ── Chat ──
253
312
  process.stdout.write(chalk.dim(" " + currentAgent.displayName + " thinking...\r"));
254
313
  try {
255
314
  const response = await currentAgent.chat(inp);
256
315
  process.stdout.write("\r" + " ".repeat(40) + "\r\n");
257
- const lines = render(response);
258
- for (const l of lines) process.stdout.write(l + "\n");
316
+ for (const l of render(response)) process.stdout.write(l + "\n");
259
317
  process.stdout.write("\n");
260
318
  } catch (e: any) {
261
319
  process.stdout.write("\r" + " ".repeat(40) + "\r");
262
320
  process.stdout.write(chalk.red(" ✗ " + (e.message || e) + "\n\n"));
263
321
  }
264
- ask();
265
322
  }
266
323
 
267
- ask();
324
+ process.stdout.write(chalk.dim("\n Session ended\n"));
325
+ await ctx.closeAll();
326
+ process.exit(0);
268
327
  }
269
328
 
270
329
  /* ═══════════════════════════════════════