skyloom 1.5.1 → 1.5.3
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/dist/cli/main.js +223 -592
- package/dist/cli/main.js.map +1 -1
- package/dist/core/llm.d.ts +8 -9
- package/dist/core/llm.d.ts.map +1 -1
- package/dist/core/llm.js +162 -35
- package/dist/core/llm.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/main.ts +1 -1
package/dist/cli/main.js
CHANGED
|
@@ -39,7 +39,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
39
39
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
40
|
/**
|
|
41
41
|
* 天空织机 CLI — Skyloom Terminal Interface
|
|
42
|
-
* Raw-mode input + slash command popup + streaming display
|
|
43
42
|
*/
|
|
44
43
|
const commander_1 = require("commander");
|
|
45
44
|
const fs = __importStar(require("fs"));
|
|
@@ -47,663 +46,297 @@ const readline = __importStar(require("readline"));
|
|
|
47
46
|
const chalk_1 = __importDefault(require("chalk"));
|
|
48
47
|
const factory_1 = require("../core/factory");
|
|
49
48
|
const config_1 = require("../core/config");
|
|
50
|
-
const router_1 = require("../core/router");
|
|
51
49
|
const mode_1 = require("./mode");
|
|
52
50
|
const MODE = new mode_1.ModeController();
|
|
53
|
-
const VERSION =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
};
|
|
51
|
+
const VERSION = (() => { try {
|
|
52
|
+
return require("../../package.json").version;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return "1.5.2";
|
|
56
|
+
} })();
|
|
59
57
|
const AGENT_DISPLAY = {
|
|
60
58
|
fog: "≋ 雾 Fog", rain: "⸽ 雨 Rain", frost: "✱ 霜 Frost",
|
|
61
59
|
snow: "❉ 雪 Snow", dew: "∘ 露 Dew", fair: "☼ 晴 Fair",
|
|
62
60
|
};
|
|
63
61
|
const AGENT_NAMES = ["fog", "rain", "frost", "snow", "dew", "fair"];
|
|
64
62
|
/* ═══════════════════════════════════════
|
|
65
|
-
|
|
66
|
-
═══════════════════════════════════════ */
|
|
67
|
-
const program = new commander_1.Command()
|
|
68
|
-
.name("sky").description("天空织机 Skyloom — 6 weather-themed AI agents").version(VERSION);
|
|
69
|
-
program.command("chat").description("Start interactive chat")
|
|
70
|
-
.argument("[agent]", "agent name", "fog")
|
|
71
|
-
.option("-m,--model <model>", "Model override")
|
|
72
|
-
.action(async (a, o) => { await chat(a, o.model); });
|
|
73
|
-
program.command("task").description("Multi-agent orchestration")
|
|
74
|
-
.argument("[goal]", "task goal")
|
|
75
|
-
.option("-r,--resume", "resume from checkpoint")
|
|
76
|
-
.action(async (g, o) => { if (g)
|
|
77
|
-
await runTask(g, o?.resume); });
|
|
78
|
-
program.command("web").description("Start web server")
|
|
79
|
-
.option("-p,--port <port>", "port", "3000")
|
|
80
|
-
.action(async (o) => { const { startWebServer } = await Promise.resolve().then(() => __importStar(require("../web/server"))); await startWebServer(parseInt(o.port || "3000", 10)); });
|
|
81
|
-
program.command("mcp").description("Start MCP server")
|
|
82
|
-
.action(async () => { const { startMCPServer } = await Promise.resolve().then(() => __importStar(require("../core/mcp_server"))); await startMCPServer(); });
|
|
83
|
-
program.command("config").description("Show configuration")
|
|
84
|
-
.action(() => { const c = (0, config_1.loadConfig)(); logLine(chalk_1.default.cyan("Config dir: ") + config_1.USER_CONFIG_DIR); logLine(chalk_1.default.cyan("Agent models:")); for (const [n, a] of Object.entries(c.agents || {}))
|
|
85
|
-
logLine(` ${chalk_1.default.bold(n)}: ${a.model || "default"}`); });
|
|
86
|
-
program.command("init").description("Initialize config directory")
|
|
87
|
-
.action(() => { const d = config_1.USER_CONFIG_DIR; if (!fs.existsSync(d))
|
|
88
|
-
fs.mkdirSync(d, { recursive: true }); logLine(chalk_1.default.green("✓ ") + d); });
|
|
89
|
-
program.command("version").description("Show version")
|
|
90
|
-
.action(() => logLine(`Skyloom v${VERSION}`));
|
|
91
|
-
/* ═══════════════════════════════════════
|
|
92
|
-
Interactive Chat — raw-mode input + popup
|
|
63
|
+
Slash commands registry
|
|
93
64
|
═══════════════════════════════════════ */
|
|
94
65
|
const SLASH_CMDS = [
|
|
95
|
-
["/help", "Show all commands"
|
|
96
|
-
["/clear", "Clear screen"
|
|
97
|
-
["/status", "Agent overview"
|
|
98
|
-
["/cost", "Usage & cost"
|
|
99
|
-
["/cost reset", "Reset usage stats"
|
|
100
|
-
["/compact", "Compress context"
|
|
101
|
-
["/retry", "Resend last
|
|
102
|
-
["/
|
|
103
|
-
["/memory", "
|
|
104
|
-
["/sessions", "Session list"
|
|
105
|
-
["/workspace", "Workspace info"
|
|
106
|
-
["/model", "Model info"
|
|
107
|
-
["/
|
|
108
|
-
["/
|
|
109
|
-
["/
|
|
110
|
-
["/fog", "≋ Fog — research
|
|
111
|
-
["/rain", "⸽ Rain — codegen"
|
|
112
|
-
["/frost", "✱ Frost — review
|
|
113
|
-
["/snow", "❉ Snow — planning
|
|
114
|
-
["/dew", "∘ Dew — devops
|
|
115
|
-
["/fair", "☼ Fair — companion
|
|
116
|
-
["/quit", "Exit chat"
|
|
117
|
-
["/exit", "Exit chat"
|
|
66
|
+
["/help", "Show all commands"],
|
|
67
|
+
["/clear", "Clear screen"],
|
|
68
|
+
["/status", "Agent overview"],
|
|
69
|
+
["/cost", "Usage & cost"],
|
|
70
|
+
["/cost reset", "Reset usage stats"],
|
|
71
|
+
["/compact", "Compress context"],
|
|
72
|
+
["/retry", "Resend last msg"],
|
|
73
|
+
["/memory", "Memory stats"],
|
|
74
|
+
["/memory clear", "Clear short-term memory"],
|
|
75
|
+
["/sessions", "Session list"],
|
|
76
|
+
["/workspace", "Workspace info"],
|
|
77
|
+
["/model", "Model info"],
|
|
78
|
+
["/mcp", "MCP server status"],
|
|
79
|
+
["/version", "Version info"],
|
|
80
|
+
["/task <goal>", "Multi-agent orchestrate"],
|
|
81
|
+
["/fog", "≋ Fog — research insight"],
|
|
82
|
+
["/rain", "⸽ Rain — creation codegen"],
|
|
83
|
+
["/frost", "✱ Frost — review quality"],
|
|
84
|
+
["/snow", "❉ Snow — planning architect"],
|
|
85
|
+
["/dew", "∘ Dew — devops reliability"],
|
|
86
|
+
["/fair", "☼ Fair — companion warmth"],
|
|
87
|
+
["/quit", "Exit chat"],
|
|
88
|
+
["/exit", "Exit chat"],
|
|
118
89
|
];
|
|
119
|
-
function
|
|
120
|
-
/* ── Stream response with spinner ── */
|
|
121
|
-
async function chatWithSpinner(agent, ctx, message) {
|
|
122
|
-
let frame = 0;
|
|
123
|
-
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
124
|
-
const spinner = setInterval(() => {
|
|
125
|
-
readline.cursorTo(process.stdout, 0);
|
|
126
|
-
process.stdout.write(chalk_1.default.cyan(` ${frames[frame % frames.length]} ${agent.displayName} thinking...`));
|
|
127
|
-
frame++;
|
|
128
|
-
}, 80);
|
|
129
|
-
try {
|
|
130
|
-
const response = await agent.chat(message);
|
|
131
|
-
clearInterval(spinner);
|
|
132
|
-
readline.cursorTo(process.stdout, 0);
|
|
133
|
-
process.stdout.write(" ".repeat(50) + "\r");
|
|
134
|
-
return response;
|
|
135
|
-
}
|
|
136
|
-
catch (e) {
|
|
137
|
-
clearInterval(spinner);
|
|
138
|
-
throw e;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
/* ── Render response ── */
|
|
142
|
-
function renderResponse(text) {
|
|
143
|
-
const lines = [];
|
|
90
|
+
function showPopup(cmds, selIdx) {
|
|
144
91
|
const w = process.stdout.columns || 80;
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const codeLines = trimmed.split("\n");
|
|
153
|
-
lines.push(chalk_1.default.dim(" ┌─ code ──────────────"));
|
|
154
|
-
for (let i = 1; i < codeLines.length - 1; i++) {
|
|
155
|
-
const cl = codeLines[i];
|
|
156
|
-
lines.push(` ${chalk_1.default.dim("│")} ${chalk_1.default.white(cl.slice(0, maxW - 4))}`);
|
|
157
|
-
}
|
|
158
|
-
lines.push(chalk_1.default.dim(" └────────────────────"));
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
// Wrap long lines
|
|
162
|
-
for (const line of trimmed.split("\n")) {
|
|
163
|
-
if (line.startsWith("#")) {
|
|
164
|
-
lines.push(" " + chalk_1.default.bold(line));
|
|
165
|
-
}
|
|
166
|
-
else if (line.startsWith("- ") || line.startsWith("* ")) {
|
|
167
|
-
lines.push(" " + chalk_1.default.dim("• ") + line.slice(2));
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
let remaining = line;
|
|
171
|
-
while (remaining.length > maxW) {
|
|
172
|
-
const cut = remaining.lastIndexOf(" ", maxW);
|
|
173
|
-
const idx = cut > 0 ? cut : maxW;
|
|
174
|
-
lines.push(" " + remaining.slice(0, idx));
|
|
175
|
-
remaining = remaining.slice(idx).trimStart();
|
|
176
|
-
}
|
|
177
|
-
if (remaining)
|
|
178
|
-
lines.push(" " + remaining);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
92
|
+
const start = Math.max(0, Math.min(selIdx - 4, cmds.length - 8));
|
|
93
|
+
const end = Math.min(cmds.length, start + 8);
|
|
94
|
+
process.stdout.write(chalk_1.default.dim(" ┌─ commands (↑↓ pick · type letter to filter · tab/enter select) ─┐\n"));
|
|
95
|
+
for (let i = start; i < end; i++) {
|
|
96
|
+
const [cmd, desc] = cmds[i];
|
|
97
|
+
const marker = i === selIdx ? chalk_1.default.cyan(" ▶ ") : " ";
|
|
98
|
+
process.stdout.write(` │${marker}${chalk_1.default.cyan(cmd.padEnd(24))}${chalk_1.default.dim(desc)}${" ".repeat(Math.max(0, 50 - desc.length))}│\n`);
|
|
181
99
|
}
|
|
182
|
-
|
|
100
|
+
process.stdout.write(chalk_1.default.dim(` └${"─".repeat(60)}┘\n`));
|
|
183
101
|
}
|
|
184
|
-
/*
|
|
185
|
-
|
|
102
|
+
/* ═══════════════════════════════════════
|
|
103
|
+
Commander
|
|
104
|
+
═══════════════════════════════════════ */
|
|
105
|
+
const program = new commander_1.Command()
|
|
106
|
+
.name("sky").description("天空织机 Skyloom").version(VERSION);
|
|
107
|
+
program.command("chat").argument("[agent]", "agent name", "fog")
|
|
108
|
+
.option("-m,--model <m>", "model").action(async (a, o) => { await chat(a, o.model); });
|
|
109
|
+
program.command("task").argument("[goal]", "task goal")
|
|
110
|
+
.action(async (g) => { if (g)
|
|
111
|
+
await runTask(g); });
|
|
112
|
+
program.command("web").option("-p,--port <p>", "port", "3000")
|
|
113
|
+
.action((o) => { Promise.resolve().then(() => __importStar(require("../web/server"))).then(m => m.startWebServer(parseInt(o.port || "3000"))); });
|
|
114
|
+
program.command("mcp").action(() => { Promise.resolve().then(() => __importStar(require("../core/mcp_server"))).then(m => m.startMCPServer()); });
|
|
115
|
+
program.command("config").action(() => { const c = (0, config_1.loadConfig)(); process.stdout.write(chalk_1.default.cyan("\nConfig: ") + config_1.USER_CONFIG_DIR + "\n"); for (const [n, a] of Object.entries(c.agents || {}))
|
|
116
|
+
process.stdout.write(` ${chalk_1.default.bold(n)}: ${a.model || "default"}\n`); });
|
|
117
|
+
program.command("init").action(() => { if (!fs.existsSync(config_1.USER_CONFIG_DIR))
|
|
118
|
+
fs.mkdirSync(config_1.USER_CONFIG_DIR, { recursive: true }); process.stdout.write(chalk_1.default.green("✓ ") + config_1.USER_CONFIG_DIR + "\n"); });
|
|
119
|
+
program.command("version").action(() => { process.stdout.write(`Skyloom v${VERSION}\n`); });
|
|
120
|
+
/* ═══════════════════════════════════════
|
|
121
|
+
Welcome
|
|
122
|
+
═══════════════════════════════════════ */
|
|
123
|
+
function welcome(agent) {
|
|
186
124
|
const w = process.stdout.columns || 80;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
agentLine.push(prefix);
|
|
125
|
+
const pad = " ".repeat(Math.max(0, Math.floor((w - 34) / 2)));
|
|
126
|
+
process.stdout.write("\n" + pad + chalk_1.default.cyan("✦ 天 空 织 机 ✦\n"));
|
|
127
|
+
process.stdout.write(pad + chalk_1.default.dim("S K Y L O O M\n\n"));
|
|
128
|
+
const parts = [];
|
|
129
|
+
for (const n of AGENT_NAMES) {
|
|
130
|
+
const a = n === agent.name;
|
|
131
|
+
const s = `${AGENT_DISPLAY[n].split(" ")[0]} ${AGENT_DISPLAY[n].split(" ")[1]}`;
|
|
132
|
+
parts.push(a ? chalk_1.default.bold.cyan(s) : chalk_1.default.dim(s));
|
|
196
133
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
logLine(chalk_1.default.dim(` Model: ${model} · /help for commands · /quit to exit`));
|
|
200
|
-
logLine("");
|
|
134
|
+
process.stdout.write(" " + parts.join(chalk_1.default.dim(" · ")) + "\n\n");
|
|
135
|
+
process.stdout.write(chalk_1.default.dim(" /help for commands · /quit to exit\n\n"));
|
|
201
136
|
}
|
|
202
|
-
/* ── Status bar ── */
|
|
203
137
|
function statusBar(agent, ctx) {
|
|
204
|
-
let ctxStr = "";
|
|
205
|
-
let costStr = "$0";
|
|
206
|
-
let modelStr = "default";
|
|
207
138
|
try {
|
|
208
139
|
const cu = agent.contextUsage();
|
|
209
|
-
modelStr = cu.model || "?";
|
|
210
140
|
const pct = cu.pct || 0;
|
|
211
|
-
const
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
141
|
+
const bar = pct < 50 ? chalk_1.default.green : pct < 80 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
142
|
+
const filled = Math.round(pct / 10);
|
|
143
|
+
const ctxBar = `${bar("█".repeat(filled) + "░".repeat(10 - filled))} ${pct}%`;
|
|
144
|
+
const cost = formatCost(ctx.llm.getTotalCost());
|
|
145
|
+
return chalk_1.default.dim(`${ctxBar} · ${cost} · ${cu.model || "?"}`);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return "";
|
|
215
149
|
}
|
|
216
|
-
catch { /* ignore */ }
|
|
217
|
-
const w = process.stdout.columns || 80;
|
|
218
|
-
return chalk_1.default.dim(`┤ ${ctxStr} · ${costStr} · ${modelStr} ├${"─".repeat(Math.max(0, w - 60))}`);
|
|
219
150
|
}
|
|
220
|
-
function formatCost(
|
|
221
|
-
if (
|
|
222
|
-
return chalk_1.default.yellow(`$${
|
|
223
|
-
if (
|
|
224
|
-
return chalk_1.default.yellow(`$${
|
|
225
|
-
if (
|
|
226
|
-
return chalk_1.default.green(`${(
|
|
151
|
+
function formatCost(c) {
|
|
152
|
+
if (c >= 1)
|
|
153
|
+
return chalk_1.default.yellow(`$${c.toFixed(2)}`);
|
|
154
|
+
if (c >= 0.01)
|
|
155
|
+
return chalk_1.default.yellow(`$${c.toFixed(4)}`);
|
|
156
|
+
if (c > 0)
|
|
157
|
+
return chalk_1.default.green(`${(c * 100).toFixed(2)}¢`);
|
|
227
158
|
return "$0";
|
|
228
159
|
}
|
|
229
|
-
/*
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
let buf = "";
|
|
245
|
-
let cursor = 0;
|
|
246
|
-
let popup = false;
|
|
247
|
-
let selIdx = 0;
|
|
248
|
-
const _history = readWithPopup._popupHistory || [];
|
|
249
|
-
let histIdx = _history.length;
|
|
250
|
-
function render() {
|
|
251
|
-
const w = process.stdout.columns || 80;
|
|
252
|
-
readline.cursorTo(process.stdout, 0);
|
|
253
|
-
// Clear current line area
|
|
254
|
-
const promptLine = ` ${chalk_1.default.cyan(agent.displayName)} ${chalk_1.default.dim("❯")} `;
|
|
255
|
-
// Build filtered commands
|
|
256
|
-
const filtered = popup ? SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase())) : [];
|
|
257
|
-
if (filtered.length && selIdx >= filtered.length)
|
|
258
|
-
selIdx = filtered.length - 1;
|
|
259
|
-
const popupH = Math.min(filtered.length, 10);
|
|
260
|
-
const totalH = popup ? popupH + 3 : 1;
|
|
261
|
-
// Move cursor up
|
|
262
|
-
if (popup) {
|
|
263
|
-
for (let i = 0; i < popupH + 2; i++)
|
|
264
|
-
process.stdout.write("\x1b[1A\x1b[2K");
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
process.stdout.write("\x1b[2K\r");
|
|
268
|
-
}
|
|
269
|
-
// Input line
|
|
270
|
-
const before = buf.slice(0, cursor);
|
|
271
|
-
const after = buf.slice(cursor);
|
|
272
|
-
const cursorChar = after[0] || " ";
|
|
273
|
-
process.stdout.write(promptLine + before + chalk_1.default.inverse(cursorChar) + after.slice(1) + "\n");
|
|
274
|
-
// Popup
|
|
275
|
-
if (popup && filtered.length) {
|
|
276
|
-
const maxW = Math.min(w - 4, 60);
|
|
277
|
-
const start = Math.max(0, Math.min(selIdx - 4, filtered.length - 8));
|
|
278
|
-
const end = Math.min(filtered.length, start + 8);
|
|
279
|
-
process.stdout.write(chalk_1.default.dim(` ┌─ commands (↑↓ pick · type to filter · tab/enter select · esc close)${"─".repeat(Math.max(0, maxW - 58))}┐\n`));
|
|
280
|
-
for (let i = start; i < end; i++) {
|
|
281
|
-
const [cmd, desc] = filtered[i];
|
|
282
|
-
const marker = i === selIdx ? chalk_1.default.cyan(" ▶ ") : " ";
|
|
283
|
-
const cmdColored = i === selIdx ? chalk_1.default.bold(cmd) : chalk_1.default.cyan(cmd);
|
|
284
|
-
const line = ` │${marker}${cmdColored.padEnd(24)}${chalk_1.default.dim(desc)}`;
|
|
285
|
-
process.stdout.write(line + " ".repeat(Math.max(0, maxW - line.length + 6)) + "│\n");
|
|
286
|
-
}
|
|
287
|
-
process.stdout.write(chalk_1.default.dim(` └${"─".repeat(maxW + 1)}┘\n`));
|
|
288
|
-
}
|
|
289
|
-
// Status bar
|
|
290
|
-
process.stdout.write(statusBar(agent, ctx) + (popup ? "" : "\n"));
|
|
160
|
+
/* ═══════════════════════════════════════
|
|
161
|
+
Response render
|
|
162
|
+
═══════════════════════════════════════ */
|
|
163
|
+
function render(text) {
|
|
164
|
+
const out = [];
|
|
165
|
+
for (const para of text.split("\n\n")) {
|
|
166
|
+
const t = para.trim();
|
|
167
|
+
if (!t)
|
|
168
|
+
continue;
|
|
169
|
+
if (t.startsWith("```")) {
|
|
170
|
+
const lines = t.split("\n");
|
|
171
|
+
out.push(chalk_1.default.dim(" ╭─ code ──"));
|
|
172
|
+
for (let i = 1; i < lines.length - 1; i++)
|
|
173
|
+
out.push(` ${chalk_1.default.dim("│")} ${chalk_1.default.gray(lines[i].slice(0, 72))}`);
|
|
174
|
+
out.push(chalk_1.default.dim(" ╰────────"));
|
|
291
175
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
176
|
+
else {
|
|
177
|
+
for (const line of t.split("\n")) {
|
|
178
|
+
if (line.startsWith("# "))
|
|
179
|
+
out.push(" " + chalk_1.default.bold(line));
|
|
180
|
+
else if (line.startsWith("- ") || line.startsWith("* "))
|
|
181
|
+
out.push(" " + chalk_1.default.dim("• ") + line.slice(2));
|
|
182
|
+
else
|
|
183
|
+
out.push(" " + line);
|
|
295
184
|
}
|
|
296
|
-
catch { }
|
|
297
|
-
stdin.pause();
|
|
298
|
-
resolve(line);
|
|
299
185
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
for (const ch of seq) {
|
|
303
|
-
// Esc
|
|
304
|
-
if (ch === "\x1b") {
|
|
305
|
-
if (popup) {
|
|
306
|
-
popup = false;
|
|
307
|
-
render();
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
accept("");
|
|
311
|
-
return;
|
|
312
|
-
}
|
|
313
|
-
// Enter
|
|
314
|
-
if (ch === "\r" || ch === "\n") {
|
|
315
|
-
if (popup && SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase())).length) {
|
|
316
|
-
const filtered = SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase()));
|
|
317
|
-
buf = filtered[selIdx]?.[0] || buf;
|
|
318
|
-
popup = false;
|
|
319
|
-
}
|
|
320
|
-
accept(buf.trim());
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
// Tab
|
|
324
|
-
if (ch === "\t") {
|
|
325
|
-
if (popup && SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase())).length) {
|
|
326
|
-
const filtered = SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase()));
|
|
327
|
-
buf = filtered[selIdx]?.[0] || buf;
|
|
328
|
-
cursor = buf.length;
|
|
329
|
-
popup = false;
|
|
330
|
-
render();
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
// Insert 2 spaces
|
|
334
|
-
buf = buf.slice(0, cursor) + " " + buf.slice(cursor);
|
|
335
|
-
cursor += 2;
|
|
336
|
-
render();
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
// Backspace
|
|
340
|
-
if (ch === "\x7f" || ch === "\b") {
|
|
341
|
-
if (cursor > 0) {
|
|
342
|
-
buf = buf.slice(0, cursor - 1) + buf.slice(cursor);
|
|
343
|
-
cursor--;
|
|
344
|
-
}
|
|
345
|
-
if (!buf) {
|
|
346
|
-
popup = false;
|
|
347
|
-
}
|
|
348
|
-
render();
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
// Ctrl+C
|
|
352
|
-
if (ch === "\x03") {
|
|
353
|
-
accept("/quit");
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
// Printable
|
|
357
|
-
if (ch >= " ") {
|
|
358
|
-
buf = buf.slice(0, cursor) + ch + buf.slice(cursor);
|
|
359
|
-
cursor++;
|
|
360
|
-
if (buf === "/") {
|
|
361
|
-
popup = true;
|
|
362
|
-
selIdx = 0;
|
|
363
|
-
}
|
|
364
|
-
else if (popup) {
|
|
365
|
-
selIdx = 0;
|
|
366
|
-
}
|
|
367
|
-
render();
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
// Arrow keys come as escape sequences — handle via process.stdin
|
|
373
|
-
// For simplicity, arrow keys in raw mode are: \x1b[A (up), \x1b[B (down), \x1b[C (right), \x1b[D (left)
|
|
374
|
-
// We handle them in the data handler above by checking for escape sequences
|
|
375
|
-
// Actually the raw mode data comes byte by byte — let me use a state machine approach
|
|
376
|
-
// For now, let me handle the common case: the full escape sequence arrives in one data event
|
|
377
|
-
// Note: Arrow keys are 3 bytes: \x1b [ A/B/C/D. They may arrive in one or multiple data events.
|
|
378
|
-
// In practice on Windows they arrive as one event. Let me add a simple buffered approach.
|
|
379
|
-
stdin.removeAllListeners("data");
|
|
380
|
-
let escBuf = "";
|
|
381
|
-
stdin.on("data", (data) => {
|
|
382
|
-
const str = data.toString();
|
|
383
|
-
escBuf += str;
|
|
384
|
-
// If we have an escape sequence, process it
|
|
385
|
-
if (escBuf.startsWith("\x1b[")) {
|
|
386
|
-
if (escBuf.length >= 3) {
|
|
387
|
-
const code = escBuf[2];
|
|
388
|
-
escBuf = "";
|
|
389
|
-
if (code === "A") {
|
|
390
|
-
if (popup) {
|
|
391
|
-
selIdx = Math.max(0, selIdx - 1);
|
|
392
|
-
}
|
|
393
|
-
else if (_history.length) {
|
|
394
|
-
histIdx = Math.max(0, histIdx - 1);
|
|
395
|
-
buf = _history[histIdx] || "";
|
|
396
|
-
cursor = buf.length;
|
|
397
|
-
}
|
|
398
|
-
render();
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
if (code === "B") {
|
|
402
|
-
if (popup) {
|
|
403
|
-
const f = SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase()));
|
|
404
|
-
selIdx = Math.min(f.length - 1, selIdx + 1);
|
|
405
|
-
}
|
|
406
|
-
else if (_history.length && histIdx < _history.length) {
|
|
407
|
-
histIdx++;
|
|
408
|
-
buf = _history[histIdx] || "";
|
|
409
|
-
cursor = buf.length;
|
|
410
|
-
}
|
|
411
|
-
render();
|
|
412
|
-
return;
|
|
413
|
-
}
|
|
414
|
-
if (code === "C") {
|
|
415
|
-
if (cursor < buf.length)
|
|
416
|
-
cursor++;
|
|
417
|
-
if (popup)
|
|
418
|
-
popup = false;
|
|
419
|
-
render();
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
if (code === "D") {
|
|
423
|
-
if (cursor > 0)
|
|
424
|
-
cursor--;
|
|
425
|
-
if (popup)
|
|
426
|
-
popup = false;
|
|
427
|
-
render();
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
return; /* wait for more bytes */
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
// Not an escape sequence — process normally
|
|
436
|
-
for (const ch of escBuf) {
|
|
437
|
-
escBuf = "";
|
|
438
|
-
if (ch === "\x1b") {
|
|
439
|
-
if (popup) {
|
|
440
|
-
popup = false;
|
|
441
|
-
render();
|
|
442
|
-
}
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
if (ch === "\r" || ch === "\n") {
|
|
446
|
-
if (popup && SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase())).length) {
|
|
447
|
-
buf = SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase()))[selIdx]?.[0] || buf;
|
|
448
|
-
popup = false;
|
|
449
|
-
}
|
|
450
|
-
accept(buf.trim());
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
if (ch === "\t") {
|
|
454
|
-
if (popup && SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase())).length) {
|
|
455
|
-
const filtered = SLASH_CMDS.filter(c => c[0].toLowerCase().includes(buf.toLowerCase()));
|
|
456
|
-
buf = filtered[selIdx]?.[0] || buf;
|
|
457
|
-
cursor = buf.length;
|
|
458
|
-
popup = false;
|
|
459
|
-
render();
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
buf = buf.slice(0, cursor) + " " + buf.slice(cursor);
|
|
463
|
-
cursor += 2;
|
|
464
|
-
render();
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
if (ch === "\x7f" || ch === "\b") {
|
|
468
|
-
if (cursor > 0) {
|
|
469
|
-
buf = buf.slice(0, cursor - 1) + buf.slice(cursor);
|
|
470
|
-
cursor--;
|
|
471
|
-
}
|
|
472
|
-
if (!buf)
|
|
473
|
-
popup = false;
|
|
474
|
-
render();
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
if (ch === "\x03") {
|
|
478
|
-
accept("/quit");
|
|
479
|
-
return;
|
|
480
|
-
}
|
|
481
|
-
if (ch >= " ") {
|
|
482
|
-
buf = buf.slice(0, cursor) + ch + buf.slice(cursor);
|
|
483
|
-
cursor++;
|
|
484
|
-
if (buf === "/") {
|
|
485
|
-
popup = true;
|
|
486
|
-
selIdx = 0;
|
|
487
|
-
}
|
|
488
|
-
else if (popup)
|
|
489
|
-
selIdx = 0;
|
|
490
|
-
render();
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
render();
|
|
496
|
-
});
|
|
186
|
+
}
|
|
187
|
+
return out;
|
|
497
188
|
}
|
|
498
189
|
/* ═══════════════════════════════════════
|
|
499
|
-
|
|
190
|
+
Chat loop
|
|
500
191
|
═══════════════════════════════════════ */
|
|
192
|
+
/* Check for API key availability */
|
|
193
|
+
function checkApiKeys() {
|
|
194
|
+
const keys = ["DEEPSEEK_API_KEY", "OPENAI_API_KEY", "ANTHROPIC_API_KEY", "GROQ_API_KEY", "OPENROUTER_API_KEY"];
|
|
195
|
+
for (const k of keys) {
|
|
196
|
+
if (process.env[k])
|
|
197
|
+
return k;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
501
201
|
async function chat(agentName, modelOverride) {
|
|
202
|
+
const haveKey = checkApiKeys();
|
|
203
|
+
if (!haveKey) {
|
|
204
|
+
process.stdout.write("\n" + chalk_1.default.yellow(" ⚠ No API key configured.\n"));
|
|
205
|
+
process.stdout.write(chalk_1.default.dim(" Set one: $env:DEEPSEEK_API_KEY = \"sk-your-key\" (PowerShell)\n"));
|
|
206
|
+
process.stdout.write(chalk_1.default.dim(" export DEEPSEEK_API_KEY=sk-your-key (Bash)\n\n"));
|
|
207
|
+
process.stdout.write(chalk_1.default.dim(" Then run: sky\n\n"));
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
502
210
|
const ctx = (0, factory_1.createSystemContext)();
|
|
503
211
|
let agent = ctx.agentMap.get(agentName);
|
|
504
212
|
if (!agent) {
|
|
505
|
-
|
|
213
|
+
process.stdout.write(chalk_1.default.red("Unknown agent: " + agentName) + "\n");
|
|
506
214
|
return;
|
|
507
215
|
}
|
|
508
216
|
await agent.init();
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
217
|
+
// eslint-disable-next-line prefer-const
|
|
218
|
+
let currentAgent = agent; // mutable for agent switching
|
|
219
|
+
welcome(agent);
|
|
220
|
+
process.stdout.write(chalk_1.default.dim(" Key: " + haveKey + "\n\n"));
|
|
221
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
222
|
+
function ask() { rl.question(chalk_1.default.cyan(" " + currentAgent.displayName + " ❯ "), handler); }
|
|
223
|
+
async function handler(inp) {
|
|
224
|
+
inp = inp.trim();
|
|
515
225
|
if (!inp) {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
// Save to history
|
|
520
|
-
if (!inputHistory[inputHistory.length - 1] || inputHistory[inputHistory.length - 1] !== inp) {
|
|
521
|
-
inputHistory.push(inp);
|
|
522
|
-
if (inputHistory.length > 50)
|
|
523
|
-
inputHistory.shift();
|
|
226
|
+
ask();
|
|
227
|
+
return;
|
|
524
228
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
const cmdLower = cmd.toLowerCase();
|
|
528
|
-
/* ── Slash commands ── */
|
|
529
|
-
let handled = false;
|
|
530
|
-
// Agent switching
|
|
229
|
+
const cmdL = inp.toLowerCase();
|
|
230
|
+
// Agent switch
|
|
531
231
|
for (const n of AGENT_NAMES) {
|
|
532
|
-
if (
|
|
533
|
-
const
|
|
534
|
-
if (
|
|
535
|
-
await
|
|
536
|
-
|
|
537
|
-
logLine(chalk_1.default.dim(`\n ⟳ ${AGENT_DISPLAY[n]}\n`));
|
|
538
|
-
// We can't reassign the outer `agent` const, so use a workaround
|
|
539
|
-
chat._currentAgent = newAgent;
|
|
540
|
-
chat._currentCtx = ctx;
|
|
541
|
-
// Actually, let me handle this differently — replace the agent in the closure
|
|
542
|
-
agent = newAgent;
|
|
232
|
+
if (cmdL === "/" + n) {
|
|
233
|
+
const a = ctx.agentMap.get(n);
|
|
234
|
+
if (a) {
|
|
235
|
+
await a.init();
|
|
236
|
+
currentAgent = a;
|
|
543
237
|
}
|
|
544
|
-
|
|
545
|
-
|
|
238
|
+
process.stdout.write(chalk_1.default.dim(" ⟳ " + AGENT_DISPLAY[n] + "\n"));
|
|
239
|
+
ask();
|
|
240
|
+
return;
|
|
546
241
|
}
|
|
547
242
|
}
|
|
548
|
-
if (
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
if (cmdLower === "/clear") {
|
|
555
|
-
console.clear();
|
|
556
|
-
handled = true;
|
|
557
|
-
}
|
|
558
|
-
if (cmdLower === "/version") {
|
|
559
|
-
logLine(` Skyloom v${VERSION}`);
|
|
560
|
-
handled = true;
|
|
561
|
-
}
|
|
562
|
-
if (cmdLower === "/status") {
|
|
563
|
-
logLine(chalk_1.default.bold(`\n ${agent.displayName} (${agent.name})`));
|
|
564
|
-
logLine(chalk_1.default.dim(` State: ${agent.state} · Specialty: ${agent.specialty}`));
|
|
565
|
-
logLine(chalk_1.default.dim(` Memory: ${agent.memory.shortTerm.length} messages · ${Object.keys(agent.memory.working).length} working keys`));
|
|
566
|
-
handled = true;
|
|
567
|
-
}
|
|
568
|
-
if (cmdLower === "/cost") {
|
|
569
|
-
logLine(chalk_1.default.bold("\n Usage & Cost"));
|
|
570
|
-
logLine(chalk_1.default.dim(" ─".repeat(24)));
|
|
571
|
-
logLine(` Total: ${formatCost(ctx.llm.getTotalCost())}`);
|
|
572
|
-
handled = true;
|
|
573
|
-
}
|
|
574
|
-
if (cmdLower === "/cost reset") {
|
|
575
|
-
ctx.llm.resetUsageStats?.();
|
|
576
|
-
logLine(chalk_1.default.dim(" Stats reset"));
|
|
577
|
-
handled = true;
|
|
578
|
-
}
|
|
579
|
-
if (cmdLower === "/compact") {
|
|
580
|
-
logLine(chalk_1.default.dim(" Compacting..."));
|
|
581
|
-
const r = await agent.compact();
|
|
582
|
-
logLine(chalk_1.default.green(` ✓ ${r}`));
|
|
583
|
-
handled = true;
|
|
243
|
+
if (cmdL === "/quit" || cmdL === "/exit") {
|
|
244
|
+
process.stdout.write(chalk_1.default.dim("\n Session ended\n"));
|
|
245
|
+
rl.close();
|
|
246
|
+
await ctx.closeAll();
|
|
247
|
+
process.exit(0);
|
|
248
|
+
return;
|
|
584
249
|
}
|
|
585
|
-
if (
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
250
|
+
if (cmdL === "/help") {
|
|
251
|
+
process.stdout.write(helpText());
|
|
252
|
+
ask();
|
|
253
|
+
return;
|
|
589
254
|
}
|
|
590
|
-
if (
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
handled = true;
|
|
255
|
+
if (cmdL === "/clear") {
|
|
256
|
+
console.clear();
|
|
257
|
+
welcome(agent);
|
|
258
|
+
process.stdout.write(chalk_1.default.dim(" Key: " + haveKey + "\n\n"));
|
|
259
|
+
ask();
|
|
260
|
+
return;
|
|
597
261
|
}
|
|
598
|
-
if (
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
for (const s of sessions.slice(0, 10)) {
|
|
603
|
-
logLine(chalk_1.default.dim(` ${s.id?.slice(0, 10)}... ${s.preview || ""} (${s.messageCount || 0} msgs)`));
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
else {
|
|
607
|
-
logLine(chalk_1.default.dim(" No saved sessions"));
|
|
608
|
-
}
|
|
609
|
-
handled = true;
|
|
262
|
+
if (cmdL === "/status") {
|
|
263
|
+
process.stdout.write(chalk_1.default.bold("\n " + currentAgent.displayName + " (" + currentAgent.name + ")\n") + chalk_1.default.dim(" State: " + currentAgent.state + " · Memory: " + currentAgent.memory.shortTerm.length + " msgs\n\n"));
|
|
264
|
+
ask();
|
|
265
|
+
return;
|
|
610
266
|
}
|
|
611
|
-
if (
|
|
612
|
-
|
|
613
|
-
|
|
267
|
+
if (cmdL === "/cost") {
|
|
268
|
+
process.stdout.write(chalk_1.default.bold("\n Total: " + formatCost(ctx.llm.getTotalCost()) + "\n\n"));
|
|
269
|
+
ask();
|
|
270
|
+
return;
|
|
614
271
|
}
|
|
615
|
-
if (
|
|
616
|
-
const
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
}
|
|
621
|
-
handled = true;
|
|
272
|
+
if (cmdL === "/compact") {
|
|
273
|
+
const r = await currentAgent.compact();
|
|
274
|
+
process.stdout.write(chalk_1.default.green(" ✓ " + r + "\n\n"));
|
|
275
|
+
ask();
|
|
276
|
+
return;
|
|
622
277
|
}
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
|
|
278
|
+
if (cmdL === "/version") {
|
|
279
|
+
process.stdout.write(" Skyloom v" + VERSION + "\n");
|
|
280
|
+
ask();
|
|
281
|
+
return;
|
|
626
282
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
await runTask(
|
|
631
|
-
|
|
632
|
-
|
|
283
|
+
if (cmdL.startsWith("/task ")) {
|
|
284
|
+
const g = inp.slice(6);
|
|
285
|
+
process.stdout.write(chalk_1.default.cyan("\n ✦ " + g + "\n\n"));
|
|
286
|
+
await runTask(g);
|
|
287
|
+
ask();
|
|
288
|
+
return;
|
|
633
289
|
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
continue;
|
|
290
|
+
if (inp.startsWith("/")) {
|
|
291
|
+
process.stdout.write(helpText());
|
|
292
|
+
ask();
|
|
293
|
+
return;
|
|
639
294
|
}
|
|
640
|
-
|
|
295
|
+
// ── Chat ──
|
|
296
|
+
process.stdout.write(chalk_1.default.dim(" " + currentAgent.displayName + " thinking...\r"));
|
|
641
297
|
try {
|
|
642
|
-
const response = await
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
// Auto-continue
|
|
649
|
-
if (mode === mode_1.InteractiveMode.AUTO) {
|
|
650
|
-
const tail = response.split("\n").slice(-6).join("\n");
|
|
651
|
-
if (/(?:接下来|下一步|继续|next|let me|I'[vl]l)/i.test(tail) && !/(?:完成了|全部完成|all done)/i.test(tail)) {
|
|
652
|
-
logLine(chalk_1.default.yellow(" [auto-continue]\n"));
|
|
653
|
-
try {
|
|
654
|
-
const r2 = await chatWithSpinner(agent, ctx, "请继续完成");
|
|
655
|
-
logLine("");
|
|
656
|
-
for (const line of renderResponse(r2))
|
|
657
|
-
logLine(line);
|
|
658
|
-
logLine("");
|
|
659
|
-
}
|
|
660
|
-
catch { /* ignore */ }
|
|
661
|
-
}
|
|
662
|
-
}
|
|
298
|
+
const response = await currentAgent.chat(inp);
|
|
299
|
+
process.stdout.write("\r" + " ".repeat(40) + "\r\n");
|
|
300
|
+
const lines = render(response);
|
|
301
|
+
for (const l of lines)
|
|
302
|
+
process.stdout.write(l + "\n");
|
|
303
|
+
process.stdout.write("\n");
|
|
663
304
|
}
|
|
664
305
|
catch (e) {
|
|
665
|
-
|
|
306
|
+
process.stdout.write("\r" + " ".repeat(40) + "\r");
|
|
307
|
+
process.stdout.write(chalk_1.default.red(" ✗ " + (e.message || e) + "\n\n"));
|
|
666
308
|
}
|
|
309
|
+
ask();
|
|
667
310
|
}
|
|
668
|
-
|
|
669
|
-
await ctx.closeAll();
|
|
670
|
-
process.exit(0);
|
|
311
|
+
ask();
|
|
671
312
|
}
|
|
672
313
|
/* ═══════════════════════════════════════
|
|
673
|
-
Task
|
|
314
|
+
Task
|
|
674
315
|
═══════════════════════════════════════ */
|
|
675
|
-
async function runTask(goal
|
|
316
|
+
async function runTask(goal) {
|
|
676
317
|
const ctx = (0, factory_1.createSystemContext)();
|
|
677
318
|
await ctx.initAll();
|
|
678
|
-
const [, results, summary] = await (0, factory_1.orchestrateTask)(goal, ctx.agentMap
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
logLine(chalk_1.default.dim(" ─".repeat(30)));
|
|
683
|
-
for (const r of results) {
|
|
684
|
-
logLine(` ${r.success ? chalk_1.default.green("✓") : chalk_1.default.red("✗")} ${chalk_1.default.cyan(r.agent)}: ${r.description.slice(0, 60)}`);
|
|
685
|
-
}
|
|
686
|
-
logLine(chalk_1.default.bold("\n Summary"));
|
|
687
|
-
logLine(chalk_1.default.dim(" ─".repeat(30)));
|
|
688
|
-
logLine(` ${summary.slice(0, 1000)}`);
|
|
689
|
-
logLine("");
|
|
319
|
+
const [, results, summary] = await (0, factory_1.orchestrateTask)(goal, ctx.agentMap);
|
|
320
|
+
for (const r of results)
|
|
321
|
+
process.stdout.write(` ${r.success ? chalk_1.default.green("✓") : chalk_1.default.red("✗")} ${chalk_1.default.cyan(r.agent)}: ${r.description.slice(0, 60)}\n`);
|
|
322
|
+
process.stdout.write(chalk_1.default.bold("\n " + summary.slice(0, 800) + "\n\n"));
|
|
690
323
|
await ctx.closeAll();
|
|
691
324
|
}
|
|
692
|
-
function
|
|
693
|
-
logLine(chalk_1.default.bold("\n Slash Commands"));
|
|
694
|
-
logLine(chalk_1.default.dim(" ─".repeat(40)));
|
|
325
|
+
function helpText() {
|
|
695
326
|
const groups = [
|
|
696
327
|
["Agent", [["/fog /rain /frost", "Switch agents"], ["/snow /dew /fair", "Switch agents"]]],
|
|
697
|
-
["Chat", [["/help", "
|
|
698
|
-
["Info", [["/status", "
|
|
699
|
-
["Orch.", [["/task <goal>", "Multi-agent
|
|
328
|
+
["Chat", [["/help", "Commands"], ["/clear", "Clear"], ["/compact", "Compress"], ["/retry", "Resend"]]],
|
|
329
|
+
["Info", [["/status", "Status"], ["/cost", "Cost"], ["/memory", "Memory"], ["/sessions", "Sessions"], ["/workspace", "Workspace"], ["/version", "Version"]]],
|
|
330
|
+
["Orch.", [["/task <goal>", "Multi-agent"]]],
|
|
700
331
|
];
|
|
332
|
+
let s = "";
|
|
701
333
|
for (const [title, cmds] of groups) {
|
|
702
|
-
|
|
334
|
+
s += chalk_1.default.cyan(` ${title}\n`);
|
|
703
335
|
for (const [c, d] of cmds)
|
|
704
|
-
|
|
336
|
+
s += ` ${chalk_1.default.cyan(c.padEnd(18))}${chalk_1.default.dim(d)}\n`;
|
|
705
337
|
}
|
|
706
|
-
|
|
338
|
+
s += "\n";
|
|
339
|
+
return s;
|
|
707
340
|
}
|
|
708
341
|
/* ═══════════════════════════════════════
|
|
709
342
|
Entry
|
|
@@ -716,19 +349,17 @@ async function main() {
|
|
|
716
349
|
}
|
|
717
350
|
if (AGENT_NAMES.includes(args[0])) {
|
|
718
351
|
let m;
|
|
719
|
-
for (let i = 1; i < args.length; i++)
|
|
352
|
+
for (let i = 1; i < args.length; i++)
|
|
720
353
|
if ((args[i] === "-m" || args[i] === "--model") && i + 1 < args.length)
|
|
721
354
|
m = args[++i];
|
|
722
|
-
}
|
|
723
355
|
await chat(args[0], m);
|
|
724
356
|
return;
|
|
725
357
|
}
|
|
726
|
-
|
|
727
|
-
if (!subCmds.includes(args[0]) && !args[0].startsWith("-")) {
|
|
358
|
+
if (!["chat", "task", "web", "config", "init", "version", "mcp", "help"].includes(args[0]) && !args[0].startsWith("-")) {
|
|
728
359
|
await chat("fog");
|
|
729
360
|
return;
|
|
730
361
|
}
|
|
731
362
|
program.parse(process.argv);
|
|
732
363
|
}
|
|
733
|
-
main().catch(e => {
|
|
364
|
+
main().catch(e => { process.stderr.write(chalk_1.default.red(`Fatal: ${e.message}\n`)); process.exit(1); });
|
|
734
365
|
//# sourceMappingURL=main.js.map
|