monk-pi 0.2.0 → 0.10.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.
@@ -1,1056 +0,0 @@
1
- // src/constants.ts
2
- import os from "os";
3
- import path from "path";
4
- var MONK_BASE_URL = "https://monk.party/v1";
5
- var MONK_WEBSITE = "https://monk.party";
6
- var MONK_ACCOUNT_URL = "https://monk.party/account/";
7
- var MONK_MODELS = [
8
- {
9
- id: "monk-coding",
10
- name: "Monk Coding (\u4EE3\u7801\u4E3B\u529B - \u63A8\u8350)",
11
- description: "\u4E13\u4E3A Agent \u6DF1\u5EA6\u4F18\u5316\uFF0C\u517C\u5907\u9AD8\u541E\u5410\u903B\u8F91\u63A8\u6F14\u4E0E\u5DE5\u5177\u8C03\u7528\u80FD\u529B",
12
- reasoning: true,
13
- contextWindow: 1e6,
14
- maxTokens: 64e3
15
- },
16
- {
17
- id: "monk-fast",
18
- name: "Monk Fast (\u6781\u901F\u63A8\u7406)",
19
- description: "\u6781\u901F\u54CD\u5E94\uFF0C\u9002\u5408\u65E5\u5E38\u95EE\u7B54\u3001\u5FEB\u901F\u4EE3\u7801\u63A2\u7D22\u4E0E\u5355\u6587\u4EF6\u9605\u8BFB",
20
- reasoning: true,
21
- contextWindow: 1e6,
22
- maxTokens: 64e3
23
- },
24
- {
25
- id: "monk",
26
- name: "Monk (\u878D\u5408\u6A21\u578B)",
27
- description: "\u96C6\u4E09\u5927 Flash \u4E4B\u6240\u957F\uFF0C\u7EFC\u5408\u8D28\u91CF\u4E0E\u601D\u8003\u80FD\u529B\u4F18\u5148",
28
- reasoning: true,
29
- contextWindow: 1e6,
30
- maxTokens: 64e3
31
- }
32
- ];
33
- var DEFAULT_MONK_MODEL = "monk-coding";
34
- function getMonkHomeDir() {
35
- return path.join(os.homedir(), ".monk-pi");
36
- }
37
- function getMonkConfigFile() {
38
- return path.join(getMonkHomeDir(), "config.json");
39
- }
40
- function getPiHomeDir() {
41
- return process.env.PI_CODING_AGENT_DIR || path.join(os.homedir(), ".pi", "agent");
42
- }
43
- function getPiModelsFile() {
44
- return path.join(getPiHomeDir(), "models.json");
45
- }
46
- function getPiSettingsFile() {
47
- return path.join(getPiHomeDir(), "settings.json");
48
- }
49
- function getPiExtensionsDir() {
50
- return path.join(getPiHomeDir(), "extensions");
51
- }
52
- function getPiMonkExtensionFile() {
53
- return path.join(getPiExtensionsDir(), "monk.ts");
54
- }
55
-
56
- // src/config.ts
57
- import fs from "fs";
58
-
59
- // src/extension/code.ts
60
- var MONK_EXTENSION_CODE = `// @monk-managed-pi-extension
61
- // Monk \xD7 Pi Native Extension
62
- // Features: Footer status, /monk slash command, and context overflow auto-compaction
63
-
64
- const MONK_MODELS = [
65
- { id: "monk-coding", label: "monk-coding (\u4EE3\u7801\u4E3B\u529B - \u63A8\u8350 \xB7 \u6DF1\u5EA6\u5DE5\u5177\u8C03\u7528)" },
66
- { id: "monk-fast", label: "monk-fast (\u6781\u901F\u63A8\u7406 \xB7 \u5FEB\u901F\u95EE\u7B54\u4E0E\u8F7B\u91CF\u4EFB\u52A1)" },
67
- { id: "monk", label: "monk (\u878D\u5408\u65D7\u8230 \xB7 \u8D28\u91CF\u4F18\u5148\u4E0E\u7EFC\u5408\u63A8\u7406)" },
68
- ];
69
-
70
- const OVERFLOW_PATTERNS = [
71
- /context.*length/i,
72
- /maximum.*tokens/i,
73
- /token.*limit/i,
74
- /too many tokens/i,
75
- /prompt.*too long/i,
76
- /request.*too large/i,
77
- /context_window_exceeded/i,
78
- /exceed.*context/i,
79
- ];
80
-
81
- export default function monkExtension(pi) {
82
- let turnCount = 0;
83
-
84
- function updateStatus(ctx) {
85
- if (!ctx.ui) return;
86
- const model = ctx.model;
87
- const isMonk = model && model.provider === "monk";
88
-
89
- if (!isMonk) {
90
- ctx.ui.setStatus("monk", undefined);
91
- return;
92
- }
93
-
94
- const theme = ctx.ui.theme;
95
- const indicator = theme.fg("success", "\u25CF");
96
- const label = theme.fg("accent", \`Monk: \${model.id}\`);
97
- const meta = theme.fg("dim", " (1M ctx)");
98
- ctx.ui.setStatus("monk", \`\${indicator} \${label}\${meta}\`);
99
- }
100
-
101
- // 1. Lifecycle Events: update footer status
102
- pi.on("session_start", async (_event, ctx) => {
103
- updateStatus(ctx);
104
- });
105
-
106
- pi.on("model_select", async (_event, ctx) => {
107
- updateStatus(ctx);
108
- });
109
-
110
- pi.on("turn_start", async (_event, ctx) => {
111
- turnCount++;
112
- if (!ctx.ui) return;
113
- const model = ctx.model;
114
- if (model && model.provider === "monk") {
115
- const theme = ctx.ui.theme;
116
- const spinner = theme.fg("warning", "\u25B2");
117
- const label = theme.fg("accent", \`Monk: \${model.id}\`);
118
- const text = theme.fg("dim", \` [Turn \${turnCount}]\`);
119
- ctx.ui.setStatus("monk", \`\${spinner} \${label}\${text}\`);
120
- }
121
- });
122
-
123
- pi.on("turn_end", async (_event, ctx) => {
124
- updateStatus(ctx);
125
- });
126
-
127
- // 2. Intelligent Context Overflow & Compaction Recovery
128
- pi.on("message_end", async (event, ctx) => {
129
- const message = event.message;
130
- if (!message || message.role !== "assistant") return;
131
- if (message.stopReason !== "error") return;
132
-
133
- const isMonk = message.provider === "monk" || (ctx.model && ctx.model.provider === "monk");
134
- if (!isMonk) return;
135
-
136
- const errorMsg = message.errorMessage || "";
137
- if (errorMsg.includes("context_length_exceeded")) return;
138
-
139
- const isOverflow = OVERFLOW_PATTERNS.some((p) => p.test(errorMsg));
140
- if (isOverflow) {
141
- ctx.ui && ctx.ui.notify(
142
- "Monk: \u68C0\u6D4B\u5230\u4E0A\u4E0B\u6587\u8D85\u957F\uFF0C\u5DF2\u81EA\u52A8\u91CD\u5199\u9519\u8BEF\u5E76\u89E6\u53D1\u667A\u80FD\u538B\u7F29 (Compaction) \u91CD\u8BD5...",
143
- "warning"
144
- );
145
- return {
146
- message: {
147
- ...message,
148
- errorMessage: \`context_length_exceeded: \${errorMsg}\`,
149
- },
150
- };
151
- }
152
- });
153
-
154
- // 3. Custom Slash Command: /monk
155
- pi.registerCommand("monk", {
156
- description: "Monk \u4E13\u5C5E\u63A7\u5236\u53F0 (/monk [model|ping|status|account])",
157
- handler: async (args, ctx) => {
158
- const sub = (args || "").trim().toLowerCase();
159
-
160
- if (sub === "model" || sub === "switch") {
161
- await handleModelSwitch(pi, ctx);
162
- return;
163
- }
164
-
165
- if (sub === "ping" || sub === "status") {
166
- await handlePing(ctx);
167
- return;
168
- }
169
-
170
- if (sub === "account" || sub === "quota") {
171
- ctx.ui && ctx.ui.notify("Monk \u7528\u91CF\u4E0E\u5230\u671F\u67E5\u8BE2: https://monk.party/account/", "info");
172
- return;
173
- }
174
-
175
- // Default: interactive menu
176
- await handleMenu(pi, ctx);
177
- },
178
- });
179
- }
180
-
181
- async function handleModelSwitch(pi, ctx) {
182
- if (!ctx.ui) return;
183
-
184
- const choices = MONK_MODELS.map((m) => m.label);
185
- const selectedLabel = await ctx.ui.select("\u9009\u62E9\u5F53\u524D\u4F1A\u8BDD\u7684 Monk \u6A21\u578B:", choices);
186
-
187
- if (!selectedLabel) return;
188
-
189
- const matched = MONK_MODELS.find((m) => m.label === selectedLabel);
190
- if (!matched) return;
191
-
192
- const model = ctx.modelRegistry.find("monk", matched.id);
193
- if (!model) {
194
- ctx.ui.notify(\`\u672A\u5728\u914D\u7F6E\u4E2D\u627E\u5230\u6A21\u578B: monk/\${matched.id}\`, "error");
195
- return;
196
- }
197
-
198
- const success = await pi.setModel(model);
199
- if (success) {
200
- ctx.ui.notify(\`\u4E3B\u529B\u6A21\u578B\u5DF2\u5207\u6362\u81F3: \${matched.id}\`, "info");
201
- } else {
202
- ctx.ui.notify(\`\u5207\u6362\u5931\u8D25\uFF0C\u672A\u80FD\u8BBE\u7F6E\u6A21\u578B: \${matched.id}\`, "error");
203
- }
204
- }
205
-
206
- async function handlePing(ctx) {
207
- if (!ctx.ui) return;
208
-
209
- const startTime = Date.now();
210
- const apiKey = process.env.MONK_API_KEY || "";
211
-
212
- try {
213
- const controller = new AbortController();
214
- const timeout = setTimeout(() => controller.abort(), 6000);
215
-
216
- const res = await fetch("https://monk.party/v1/models", {
217
- headers: { Authorization: \`Bearer \${apiKey}\` },
218
- signal: controller.signal,
219
- });
220
-
221
- clearTimeout(timeout);
222
- const latency = Date.now() - startTime;
223
-
224
- if (res.ok) {
225
- ctx.ui.notify(\`Monk API \u8FDE\u901A\u6B63\u5E38 \xB7 \u5EF6\u8FDF \${latency}ms\`, "info");
226
- } else {
227
- ctx.ui.notify(\`Monk API \u54CD\u5E94\u5F02\u5E38 (HTTP \${res.status})\`, "warning");
228
- }
229
- } catch (err) {
230
- ctx.ui.notify(
231
- \`Monk API \u8FDE\u63A5\u5931\u8D25: \${err instanceof Error ? err.message : String(err)}\`,
232
- "error"
233
- );
234
- }
235
- }
236
-
237
- async function handleMenu(pi, ctx) {
238
- if (!ctx.ui) return;
239
-
240
- const choice = await ctx.ui.select("Monk API \u63A7\u5236\u53F0", [
241
- "1. \u5207\u6362\u4F1A\u8BDD\u6A21\u578B (Switch Model)",
242
- "2. \u63A2\u6D4B\u7F51\u7EDC\u5EF6\u8FDF (Ping API)",
243
- "3. \u67E5\u8BE2\u7528\u91CF\u4E0E\u5230\u671F\u65F6\u95F4 (Account Info)",
244
- ]);
245
-
246
- if (!choice) return;
247
-
248
- if (choice.startsWith("1")) {
249
- await handleModelSwitch(pi, ctx);
250
- } else if (choice.startsWith("2")) {
251
- await handlePing(ctx);
252
- } else if (choice.startsWith("3")) {
253
- ctx.ui.notify("\u8BF7\u5728\u6D4F\u89C8\u5668\u6253\u5F00 https://monk.party/account/ \u67E5\u770B\u7528\u91CF\u4E0E\u5269\u4F59\u5929\u6570", "info");
254
- }
255
- }
256
- `;
257
-
258
- // src/config.ts
259
- function loadMonkConfig() {
260
- const configFile = getMonkConfigFile();
261
- try {
262
- if (fs.existsSync(configFile)) {
263
- const content = fs.readFileSync(configFile, "utf-8");
264
- return JSON.parse(content);
265
- }
266
- } catch {
267
- }
268
- return {};
269
- }
270
- function saveMonkConfig(config) {
271
- const homeDir = getMonkHomeDir();
272
- if (!fs.existsSync(homeDir)) {
273
- fs.mkdirSync(homeDir, { recursive: true });
274
- }
275
- const configFile = getMonkConfigFile();
276
- const existing = loadMonkConfig();
277
- const merged = { ...existing, ...config };
278
- fs.writeFileSync(configFile, JSON.stringify(merged, null, 2), "utf-8");
279
- }
280
- function resolveApiKey() {
281
- const envKey = process.env.MONK_API_KEY?.trim();
282
- if (envKey) {
283
- return { key: envKey, source: "env" };
284
- }
285
- const localConfig = loadMonkConfig();
286
- if (localConfig.apiKey?.trim()) {
287
- return { key: localConfig.apiKey.trim(), source: "local" };
288
- }
289
- const piModelsFile = getPiModelsFile();
290
- try {
291
- if (fs.existsSync(piModelsFile)) {
292
- const data = JSON.parse(fs.readFileSync(piModelsFile, "utf-8"));
293
- const key = data?.providers?.monk?.apiKey;
294
- if (typeof key === "string" && key.trim() && !key.startsWith("$")) {
295
- return { key: key.trim(), source: "pi" };
296
- }
297
- }
298
- } catch {
299
- }
300
- return { key: "", source: "none" };
301
- }
302
- function syncPiModelsJson(apiKey) {
303
- const piDir = getPiHomeDir();
304
- const piModelsFile = getPiModelsFile();
305
- try {
306
- if (!fs.existsSync(piDir)) {
307
- fs.mkdirSync(piDir, { recursive: true });
308
- }
309
- let modelsData = { providers: {} };
310
- if (fs.existsSync(piModelsFile)) {
311
- const raw = fs.readFileSync(piModelsFile, "utf-8");
312
- try {
313
- modelsData = JSON.parse(raw);
314
- if (!modelsData.providers) {
315
- modelsData.providers = {};
316
- }
317
- } catch {
318
- modelsData = { providers: {} };
319
- }
320
- }
321
- const monkProviderConfig = {
322
- name: "Monk",
323
- baseUrl: MONK_BASE_URL,
324
- api: "openai-completions",
325
- apiKey: apiKey && !apiKey.startsWith("$") ? apiKey : "$MONK_API_KEY",
326
- compat: {
327
- supportsDeveloperRole: false,
328
- maxTokensField: "max_tokens",
329
- requiresToolResultName: true
330
- },
331
- models: MONK_MODELS.map((m) => ({
332
- id: m.id,
333
- name: m.name,
334
- reasoning: m.reasoning,
335
- input: ["text"],
336
- contextWindow: m.contextWindow,
337
- maxTokens: m.maxTokens,
338
- cost: {
339
- input: 0,
340
- output: 0,
341
- cacheRead: 0,
342
- cacheWrite: 0
343
- }
344
- }))
345
- };
346
- modelsData.providers.monk = monkProviderConfig;
347
- fs.writeFileSync(piModelsFile, JSON.stringify(modelsData, null, 2), "utf-8");
348
- return { success: true, path: piModelsFile };
349
- } catch (err) {
350
- return {
351
- success: false,
352
- path: piModelsFile,
353
- error: err instanceof Error ? err.message : String(err)
354
- };
355
- }
356
- }
357
- function syncPiExtension() {
358
- const extDir = getPiExtensionsDir();
359
- const extFile = getPiMonkExtensionFile();
360
- try {
361
- if (!fs.existsSync(extDir)) {
362
- fs.mkdirSync(extDir, { recursive: true });
363
- }
364
- fs.writeFileSync(extFile, MONK_EXTENSION_CODE.trim() + "\n", "utf-8");
365
- return { success: true, path: extFile };
366
- } catch (err) {
367
- return {
368
- success: false,
369
- path: extFile,
370
- error: err instanceof Error ? err.message : String(err)
371
- };
372
- }
373
- }
374
- function getDefaultModel() {
375
- const config = loadMonkConfig();
376
- if (config.defaultModel && MONK_MODELS.some((m) => m.id === config.defaultModel)) {
377
- return config.defaultModel;
378
- }
379
- return DEFAULT_MONK_MODEL;
380
- }
381
-
382
- // src/monk-api.ts
383
- async function validateApiKey(apiKey, baseUrl = MONK_BASE_URL) {
384
- const trimmedKey = apiKey.trim();
385
- if (!trimmedKey) {
386
- return {
387
- valid: false,
388
- latencyMs: 0,
389
- models: [],
390
- error: "API Key \u4E0D\u80FD\u4E3A\u7A7A"
391
- };
392
- }
393
- const endpoint = `${baseUrl.replace(/\/+$/, "")}/models`;
394
- const startTime = Date.now();
395
- try {
396
- const controller = new AbortController();
397
- const timeoutId = setTimeout(() => controller.abort(), 8e3);
398
- const response = await fetch(endpoint, {
399
- method: "GET",
400
- headers: {
401
- Authorization: `Bearer ${trimmedKey}`,
402
- Accept: "application/json"
403
- },
404
- signal: controller.signal
405
- });
406
- clearTimeout(timeoutId);
407
- const latencyMs = Date.now() - startTime;
408
- if (response.status === 401 || response.status === 403) {
409
- const body = await response.json().catch(() => ({}));
410
- return {
411
- valid: false,
412
- latencyMs,
413
- models: [],
414
- statusCode: response.status,
415
- error: body.error?.message || "API Key \u65E0\u6548\u6216\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u68C0\u67E5 monk.party \u7684\u8BA2\u9605\u51ED\u8BC1"
416
- };
417
- }
418
- if (!response.ok) {
419
- return {
420
- valid: false,
421
- latencyMs,
422
- models: [],
423
- statusCode: response.status,
424
- error: `Monk API \u54CD\u5E94\u5F02\u5E38 (HTTP ${response.status})`
425
- };
426
- }
427
- const data = await response.json().catch(() => ({}));
428
- const models = Array.isArray(data.data) ? data.data.map((m) => m.id) : [];
429
- return {
430
- valid: true,
431
- latencyMs,
432
- models,
433
- statusCode: response.status
434
- };
435
- } catch (err) {
436
- const latencyMs = Date.now() - startTime;
437
- const isAbort = err instanceof Error && err.name === "AbortError";
438
- return {
439
- valid: false,
440
- latencyMs,
441
- models: [],
442
- error: isAbort ? "\u8FDE\u63A5 Monk \u670D\u52A1\u8D85\u65F6\uFF08\u8D85\u8FC7 8 \u79D2\uFF09\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u8FDE\u63A5" : `\u7F51\u7EDC\u8FDE\u63A5\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`
443
- };
444
- }
445
- }
446
- async function testChatCompletion(apiKey, model = "monk-fast", baseUrl = MONK_BASE_URL) {
447
- const endpoint = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
448
- const startTime = Date.now();
449
- try {
450
- const controller = new AbortController();
451
- const timeoutId = setTimeout(() => controller.abort(), 12e3);
452
- const response = await fetch(endpoint, {
453
- method: "POST",
454
- headers: {
455
- "Content-Type": "application/json",
456
- Authorization: `Bearer ${apiKey.trim()}`
457
- },
458
- body: JSON.stringify({
459
- model,
460
- messages: [{ role: "user", content: "pong" }],
461
- max_tokens: 10,
462
- temperature: 0.1
463
- }),
464
- signal: controller.signal
465
- });
466
- clearTimeout(timeoutId);
467
- const latencyMs = Date.now() - startTime;
468
- if (!response.ok) {
469
- const errJson = await response.json().catch(() => ({}));
470
- return {
471
- success: false,
472
- latencyMs,
473
- error: errJson.error?.message || `HTTP ${response.status}`
474
- };
475
- }
476
- const json = await response.json().catch(() => ({}));
477
- const reply = json.choices?.[0]?.message?.content?.trim() || "";
478
- return {
479
- success: true,
480
- latencyMs,
481
- reply
482
- };
483
- } catch (err) {
484
- const latencyMs = Date.now() - startTime;
485
- return {
486
- success: false,
487
- latencyMs,
488
- error: err instanceof Error ? err.message : String(err)
489
- };
490
- }
491
- }
492
-
493
- // src/ui.ts
494
- import pc from "picocolors";
495
- import { password, select, confirm } from "@inquirer/prompts";
496
- function printBanner() {
497
- const line = pc.dim("\u2500".repeat(54));
498
- console.log();
499
- console.log(pc.bold(pc.yellow(" \u2588\u2580\u2584\u2580\u2588 \u2588\u2580\u2588 \u2588\u2584\u2591\u2588 \u2588\u2584\u2580") + " \u2715 " + pc.cyan("\u2588\u2580\u2588 \u2588")));
500
- console.log(pc.bold(pc.yellow(" \u2588\u2591\u2580\u2591\u2588 \u2588\u2584\u2588 \u2588\u2591\u2580\u2588 \u2588\u2591\u2588") + " " + pc.cyan("\u2588\u2580\u2580 \u2588")));
501
- console.log(line);
502
- console.log(
503
- ` ${pc.bold("Monk \xD7 Pi Harness")} ${pc.dim("\xB7")} ${pc.green("OpenAI-Compatible Fusion Agent")}`
504
- );
505
- console.log(
506
- ` ${pc.dim("\u6A21\u578B:")} ${pc.yellow("monk-coding")} ${pc.dim("|")} ${pc.cyan("monk-fast")} ${pc.dim("|")} ${pc.magenta("monk")}`
507
- );
508
- console.log(line);
509
- console.log();
510
- }
511
- function logSuccess(msg) {
512
- console.log(` ${pc.green("\u2714")} ${msg}`);
513
- }
514
- function logInfo(msg) {
515
- console.log(` ${pc.cyan("\u2139")} ${msg}`);
516
- }
517
- function logWarn(msg) {
518
- console.log(` ${pc.yellow("\u25B2")} ${msg}`);
519
- }
520
- function logError(msg) {
521
- console.log(` ${pc.red("\u2716")} ${msg}`);
522
- }
523
- function logStep(step, total, msg) {
524
- console.log(` ${pc.dim(`[${step}/${total}]`)} ${pc.bold(msg)}`);
525
- }
526
- async function promptForApiKey(currentKey) {
527
- console.log();
528
- console.log(` ${pc.bold("\u6B22\u8FCE\u4F7F\u7528 Monk \xD7 Pi \u7F16\u7801\u4F34\u4FA3\uFF01")}`);
529
- console.log(` ${pc.dim("Monk \u4E13\u4E3A Agent \u63D0\u4F9B\u9AD8\u5E76\u53D1\u6781\u901F\u878D\u5408\u6A21\u578B\u3002\u8BF7\u914D\u7F6E\u60A8\u7684 API Key\u3002")}`);
530
- console.log(` ${pc.dim("\u8FD8\u6CA1\u6709 Key\uFF1F\u53EF\u4EE5\u5728")} ${pc.underline(pc.yellow(MONK_WEBSITE))} ${pc.dim("\u8BA2\u9605\u6708\u5361 (\xA530/\u6708)")}`);
531
- console.log();
532
- const key = await password({
533
- message: currentKey ? `\u8BF7\u8F93\u5165 Monk API Key (\u76F4\u63A5\u56DE\u8F66\u4FDD\u6301\u5F53\u524D: ${maskKey(currentKey)}):` : "\u8BF7\u8F93\u5165 Monk API Key (\u683C\u5F0F sk-monk-...):",
534
- mask: "*",
535
- validate: (val) => {
536
- const trimmed = val.trim();
537
- if (!trimmed && currentKey) return true;
538
- if (!trimmed) return "API Key \u4E0D\u80FD\u4E3A\u7A7A";
539
- if (!trimmed.startsWith("sk-")) {
540
- return "Key \u683C\u5F0F\u901A\u5E38\u4EE5 sk- \u5F00\u5934\uFF0C\u8BF7\u786E\u8BA4\u590D\u5236\u5B8C\u6574";
541
- }
542
- return true;
543
- }
544
- });
545
- const finalKey = key.trim() || currentKey || "";
546
- return finalKey;
547
- }
548
- async function promptSelectModel(currentModel) {
549
- const choices = MONK_MODELS.map((m) => ({
550
- name: `${m.name.padEnd(28)} ${pc.dim(m.description)}`,
551
- value: m.id,
552
- description: m.description
553
- }));
554
- const selected = await select({
555
- message: "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B:",
556
- choices,
557
- default: currentModel || "monk-coding"
558
- });
559
- return selected;
560
- }
561
- async function promptInstallPi() {
562
- logWarn("\u672A\u68C0\u6D4B\u5230\u5168\u5C40\u5B89\u88C5\u7684 pi \u7F16\u7801\u52A9\u624B (@earendil-works/pi-coding-agent)\u3002");
563
- console.log(` ${pc.dim("Monk Harness \u4F9D\u8D56 Pi \u4F5C\u4E3A\u5E95\u5C42 TUI/Agent \u8FD0\u884C\u65F6\u3002")}`);
564
- console.log();
565
- return await confirm({
566
- message: "\u662F\u5426\u7ACB\u5373\u4F7F\u7528 npm \u5168\u5C40\u5B89\u88C5 @earendil-works/pi-coding-agent\uFF1F",
567
- default: true
568
- });
569
- }
570
- function maskKey(key) {
571
- if (!key || key.length < 10) return "******";
572
- return `${key.slice(0, 7)}...${key.slice(-4)}`;
573
- }
574
-
575
- // src/pi-runner.ts
576
- import fs2 from "fs";
577
- import path2 from "path";
578
- import { fileURLToPath } from "url";
579
- import spawn from "cross-spawn";
580
- import pc2 from "picocolors";
581
- function resolvePiBinary() {
582
- try {
583
- const globalCheck = spawn.sync("pi", ["--version"], {
584
- encoding: "utf-8",
585
- stdio: ["ignore", "pipe", "ignore"]
586
- });
587
- if (globalCheck.status === 0 && globalCheck.stdout) {
588
- return {
589
- type: "global",
590
- command: "pi",
591
- argsPrefix: [],
592
- version: globalCheck.stdout.trim(),
593
- sourceDescription: "\u7CFB\u7EDF\u5168\u5C40\u547D\u4EE4 (PATH)"
594
- };
595
- }
596
- } catch {
597
- }
598
- const candidateBinDirs = [
599
- path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "../node_modules/.bin/pi"),
600
- path2.resolve(process.cwd(), "node_modules/.bin/pi")
601
- ];
602
- for (const binPath of candidateBinDirs) {
603
- if (fs2.existsSync(binPath)) {
604
- try {
605
- const localCheck = spawn.sync(binPath, ["--version"], {
606
- encoding: "utf-8",
607
- stdio: ["ignore", "pipe", "ignore"]
608
- });
609
- if (localCheck.status === 0 && localCheck.stdout) {
610
- return {
611
- type: "local",
612
- command: binPath,
613
- argsPrefix: [],
614
- version: localCheck.stdout.trim(),
615
- sourceDescription: `\u672C\u5730\u4F9D\u8D56 (${path2.basename(path2.dirname(binPath))})`
616
- };
617
- }
618
- } catch {
619
- }
620
- }
621
- }
622
- try {
623
- const mainEntry = fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent"));
624
- const cliEntry = path2.join(path2.dirname(mainEntry), "bundle", "cli.js");
625
- if (fs2.existsSync(cliEntry)) {
626
- const moduleCheck = spawn.sync(process.execPath, [cliEntry, "--version"], {
627
- encoding: "utf-8",
628
- stdio: ["ignore", "pipe", "ignore"]
629
- });
630
- if (moduleCheck.status === 0 && moduleCheck.stdout) {
631
- return {
632
- type: "bundled",
633
- command: process.execPath,
634
- argsPrefix: [cliEntry],
635
- version: moduleCheck.stdout.trim(),
636
- sourceDescription: "Monk-Pi \u5185\u5D4C\u6838\u5FC3 (\u514D\u5B89\u88C5\u8FD0\u884C)"
637
- };
638
- }
639
- }
640
- } catch {
641
- }
642
- return {
643
- type: "missing",
644
- command: "",
645
- argsPrefix: [],
646
- sourceDescription: "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Pi \u6838\u5FC3"
647
- };
648
- }
649
- function detectPi() {
650
- const resolved = resolvePiBinary();
651
- return {
652
- installed: resolved.type !== "missing",
653
- version: resolved.version,
654
- type: resolved.type,
655
- description: resolved.sourceDescription
656
- };
657
- }
658
- function detectPackageManager() {
659
- try {
660
- const bunCheck = spawn.sync("bun", ["--version"], { stdio: "ignore" });
661
- if (bunCheck.status === 0) return "bun";
662
- } catch {
663
- }
664
- try {
665
- const pnpmCheck = spawn.sync("pnpm", ["--version"], { stdio: "ignore" });
666
- if (pnpmCheck.status === 0) return "pnpm";
667
- } catch {
668
- }
669
- return "npm";
670
- }
671
- async function installPi() {
672
- const pm = detectPackageManager();
673
- let cmd = "npm";
674
- let args = ["install", "-g", "@earendil-works/pi-coding-agent"];
675
- if (pm === "bun") {
676
- cmd = "bun";
677
- args = ["add", "-g", "@earendil-works/pi-coding-agent"];
678
- } else if (pm === "pnpm") {
679
- cmd = "pnpm";
680
- args = ["add", "-g", "@earendil-works/pi-coding-agent"];
681
- }
682
- logInfo(`\u68C0\u6D4B\u5230\u5305\u7BA1\u7406\u5668: ${pc2.bold(pm)}\uFF0C\u6B63\u5728\u6267\u884C: ${pc2.yellow(`${cmd} ${args.join(" ")}`)} ...`);
683
- try {
684
- const child = spawn.sync(cmd, args, {
685
- stdio: "inherit"
686
- });
687
- if (child.status === 0) {
688
- logSuccess("Pi \u6838\u5FC3\u5957\u4EF6\u5B89\u88C5\u6210\u529F\uFF01");
689
- return true;
690
- }
691
- logError(`\u5B89\u88C5\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${child.status}`);
692
- logWarn(`\u82E5\u56E0\u6743\u9650\u95EE\u9898 (EACCES) \u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5:`);
693
- console.log(` ${pc2.cyan(`sudo ${cmd} ${args.join(" ")}`)}`);
694
- console.log(` \u6216\u76F4\u63A5\u4F7F\u7528\u514D\u5B89\u88C5\u65B9\u6848: ${pc2.cyan("npx monk-pi")}`);
695
- return false;
696
- } catch (err) {
697
- logError(`\u6267\u884C\u5B89\u88C5\u5F02\u5E38: ${err instanceof Error ? err.message : String(err)}`);
698
- return false;
699
- }
700
- }
701
- function launchPi(options) {
702
- const resolved = resolvePiBinary();
703
- if (resolved.type === "missing") {
704
- logError("\u672A\u627E\u5230\u53EF\u7528\u7684 Pi \u6838\u5FC3\u8FD0\u884C\u73AF\u5883\u3002");
705
- return 1;
706
- }
707
- const { apiKey, defaultModel, passthroughArgs } = options;
708
- const extraArgs = [];
709
- const hasProvider = passthroughArgs.includes("--provider");
710
- const hasModel = passthroughArgs.some((arg, idx) => {
711
- return arg === "--model" || arg === "-m" || passthroughArgs[idx - 1] === "--model";
712
- });
713
- if (!hasProvider && !hasModel) {
714
- extraArgs.push("--provider", "monk", "--model", defaultModel);
715
- } else if (!hasProvider && hasModel) {
716
- extraArgs.push("--provider", "monk");
717
- }
718
- const fullArgs = [...resolved.argsPrefix, ...extraArgs, ...passthroughArgs];
719
- const env = {
720
- ...process.env,
721
- MONK_API_KEY: apiKey
722
- };
723
- const child = spawn(resolved.command, fullArgs, {
724
- stdio: "inherit",
725
- env
726
- });
727
- const forwardSignal = (signal) => {
728
- try {
729
- child.kill(signal);
730
- } catch {
731
- }
732
- };
733
- process.on("SIGINT", () => forwardSignal("SIGINT"));
734
- process.on("SIGTERM", () => forwardSignal("SIGTERM"));
735
- return new Promise((resolve) => {
736
- child.on("close", (code) => {
737
- resolve(code ?? 0);
738
- });
739
- child.on("error", (err) => {
740
- logError(`\u542F\u52A8 Pi \u53D1\u751F\u9519\u8BEF: ${err.message}`);
741
- resolve(1);
742
- });
743
- });
744
- }
745
-
746
- // src/commands/doctor.ts
747
- import fs3 from "fs";
748
- import os2 from "os";
749
- import pc3 from "picocolors";
750
- async function doctorCommand() {
751
- printBanner();
752
- console.log(` ${pc3.bold("\u3010Monk \xD7 Pi \u73AF\u5883\u8BCA\u65AD (Doctor)\u3011")}`);
753
- console.log();
754
- let hasIssue = false;
755
- const nodeVersion = process.version;
756
- const major = parseInt(nodeVersion.slice(1).split(".")[0], 10);
757
- if (major >= 18) {
758
- logSuccess(`Node.js \u7248\u672C: ${pc3.bold(nodeVersion)} (\u6EE1\u8DB3 >= 18 \u8981\u6C42)`);
759
- } else {
760
- hasIssue = true;
761
- logError(`Node.js \u7248\u672C: ${pc3.bold(nodeVersion)} (\u8FC7\u4F4E\uFF0C\u8BF7\u5347\u7EA7\u5230 Node 18+)`);
762
- }
763
- logInfo(`\u64CD\u4F5C\u7CFB\u7EDF: ${os2.type()} ${os2.release()} (${os2.arch()})`);
764
- const pi = detectPi();
765
- if (pi.installed) {
766
- logSuccess(
767
- `Pi \u6838\u5FC3\u5957\u4EF6: ${pc3.bold(`\u5DF2\u5C31\u7EEA (v${pi.version})`)} \xB7 ${pc3.dim(`[\u6765\u6E90: ${pi.description}]`)}`
768
- );
769
- } else {
770
- hasIssue = true;
771
- logError(`Pi \u6838\u5FC3\u5957\u4EF6: ${pc3.bold("\u672A\u627E\u5230\u53EF\u7528\u8FD0\u884C\u65F6")}`);
772
- console.log(` ${pc3.dim("\u89E3\u51B3\u529E\u6CD5: \u8FD0\u884C npm install -g @earendil-works/pi-coding-agent")}`);
773
- }
774
- const { key, source } = resolveApiKey();
775
- if (key) {
776
- logSuccess(`Monk API Key: ${pc3.bold(maskKey(key))} (\u6765\u6E90: ${source})`);
777
- } else {
778
- hasIssue = true;
779
- logError(`Monk API Key: \u672A\u914D\u7F6E`);
780
- console.log(` ${pc3.dim("\u89E3\u51B3\u529E\u6CD5: \u8FD0\u884C monk-pi login")}`);
781
- }
782
- const modelsFile = getPiModelsFile();
783
- if (fs3.existsSync(modelsFile)) {
784
- try {
785
- const data = JSON.parse(fs3.readFileSync(modelsFile, "utf-8"));
786
- const monk = data?.providers?.monk;
787
- if (monk) {
788
- const hasCompat = monk.compat?.supportsDeveloperRole === false && monk.compat?.maxTokensField === "max_tokens";
789
- if (hasCompat) {
790
- logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: ${pc3.bold("\u5DF2\u914D\u7F6E Monk \u4E13\u5C5E\u4F18\u5316\u517C\u5BB9\u53C2\u6570")}`);
791
- } else {
792
- logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5B58\u5728 Monk \u914D\u7F6E\uFF0C\u4F46\u7F3A\u5C11\u6700\u4F73 compat \u53C2\u6570`);
793
- console.log(` ${pc3.dim("\u6B63\u5728\u4E3A\u60A8\u81EA\u52A8\u7EA0\u6B63...")}`);
794
- syncPiModelsJson(key);
795
- logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u5DF2\u81EA\u52A8\u4FEE\u590D\u4F18\u5316`);
796
- }
797
- } else {
798
- logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5C1A\u672A\u6CE8\u5165 Monk \u4F9B\u5E94\u5546`);
799
- syncPiModelsJson(key);
800
- logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u5DF2\u6210\u529F\u81EA\u52A8\u6CE8\u5165`);
801
- }
802
- } catch {
803
- logError(`Pi \u914D\u7F6E\u6587\u4EF6: ${modelsFile} \u5B58\u5728\u8BED\u6CD5\u9519\u8BEF`);
804
- }
805
- } else {
806
- logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5C1A\u672A\u521B\u5EFA\uFF0C\u6B63\u5728\u4E3A\u60A8\u81EA\u52A8\u521B\u5EFA...`);
807
- syncPiModelsJson(key);
808
- logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u521B\u5EFA\u5B8C\u6210`);
809
- }
810
- const extFile = getPiMonkExtensionFile();
811
- if (fs3.existsSync(extFile)) {
812
- logSuccess(`Pi \u539F\u751F\u6269\u5C55: ${pc3.bold("\u5DF2\u5B89\u88C5")} (/monk \u6307\u4EE4\u3001\u72B6\u6001\u680F\u4E0E\u6EA2\u51FA\u81EA\u52A8\u91CD\u8BD5\u5C31\u7EEA)`);
813
- } else {
814
- logWarn(`Pi \u539F\u751F\u6269\u5C55: \u672A\u5B89\u88C5\uFF0C\u6B63\u5728\u4E3A\u60A8\u81EA\u52A8\u90E8\u7F72...`);
815
- const extRes = syncPiExtension();
816
- if (extRes.success) {
817
- logSuccess(`Pi \u539F\u751F\u6269\u5C55: \u90E8\u7F72\u5B8C\u6210`);
818
- } else {
819
- logError(`Pi \u539F\u751F\u6269\u5C55\u90E8\u7F72\u5931\u8D25: ${extRes.error}`);
820
- }
821
- }
822
- if (key) {
823
- process.stdout.write(` ${pc3.dim("\u23F3 \u6B63\u5728\u63A2\u6D4B\u4E0E monk.party \u63A5\u53E3\u7684\u8FDE\u901A\u6027...")} `);
824
- const val = await validateApiKey(key);
825
- process.stdout.write("\r" + " ".repeat(50) + "\r");
826
- if (val.valid) {
827
- logSuccess(`Monk \u8FDE\u901A\u6027: ${pc3.green("\u4F18\u79C0")} \xB7 \u5EF6\u8FDF ${val.latencyMs}ms`);
828
- } else {
829
- hasIssue = true;
830
- logError(`Monk \u8FDE\u901A\u6027\u5F02\u5E38: ${val.error}`);
831
- }
832
- }
833
- console.log();
834
- console.log(pc3.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
835
- if (hasIssue) {
836
- logWarn("\u68C0\u6D4B\u5230\u73AF\u5883\u5B58\u5728\u90E8\u5206\u95EE\u9898\uFF0C\u8BF7\u53C2\u8003\u4E0A\u65B9\u63D0\u793A\u5904\u7406\u3002");
837
- } else {
838
- logSuccess(pc3.bold("\u592A\u68D2\u4E86\uFF01\u6240\u6709\u68C0\u67E5\u9879\u5168\u90E8\u901A\u8FC7\uFF0C\u73AF\u5883\u5904\u4E8E\u6700\u4F73\u72B6\u6001\u3002"));
839
- }
840
- console.log();
841
- }
842
-
843
- // src/commands/login.ts
844
- import pc4 from "picocolors";
845
- async function loginCommand() {
846
- printBanner();
847
- const current = resolveApiKey();
848
- const apiKey = await promptForApiKey(current.key || void 0);
849
- if (!apiKey) {
850
- logWarn("\u672A\u8F93\u5165 API Key\uFF0C\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002");
851
- return false;
852
- }
853
- logInfo("\u6B63\u5728\u8FDE\u63A5 Monk API \u9A8C\u8BC1\u5BC6\u94A5...");
854
- const result = await validateApiKey(apiKey);
855
- if (!result.valid) {
856
- logError(`\u9A8C\u8BC1\u5931\u8D25: ${result.error || "\u672A\u77E5\u9519\u8BEF"}`);
857
- logWarn("\u8BF7\u6838\u5BF9\u540E\u91CD\u65B0\u8FD0\u884C `monk-pi login`\u3002");
858
- return false;
859
- }
860
- logSuccess(`\u9A8C\u8BC1\u901A\u8FC7\uFF01\u7F51\u7EDC\u5EF6\u8FDF: ${pc4.green(`${result.latencyMs}ms`)}`);
861
- if (result.models.length > 0) {
862
- logInfo(`\u53EF\u7528\u6A21\u578B: ${pc4.yellow(result.models.join(", "))}`);
863
- }
864
- saveMonkConfig({
865
- apiKey,
866
- lastVerified: (/* @__PURE__ */ new Date()).toISOString()
867
- });
868
- logSuccess(`\u51ED\u8BC1\u5DF2\u4FDD\u5B58\u81F3\u672C\u5730\u914D\u7F6E`);
869
- const syncResult = syncPiModelsJson(apiKey);
870
- const extResult = syncPiExtension();
871
- if (syncResult.success) {
872
- logSuccess(`\u5DF2\u6210\u529F\u540C\u6B65\u5E76\u4F18\u5316 Pi \u914D\u7F6E\u6587\u4EF6: ${pc4.dim(syncResult.path)}`);
873
- } else {
874
- logWarn(`\u540C\u6B65 Pi \u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${syncResult.error}`);
875
- }
876
- if (extResult.success) {
877
- logSuccess(`\u5DF2\u5B89\u88C5 Monk \u539F\u751F TUI \u6269\u5C55: ${pc4.dim(extResult.path)}`);
878
- }
879
- console.log();
880
- logSuccess(`Monk \xD7 Pi \u5C31\u7EEA\uFF01\u73B0\u5728\u60A8\u53EF\u4EE5\u76F4\u63A5\u8F93\u5165 ${pc4.bold(pc4.yellow("monk-pi"))} \u5F00\u59CB\u7F16\u7801\u3002`);
881
- console.log();
882
- return true;
883
- }
884
-
885
- // src/commands/model.ts
886
- import pc5 from "picocolors";
887
- async function modelCommand(targetModel) {
888
- printBanner();
889
- const currentModel = getDefaultModel();
890
- if (targetModel) {
891
- const matched2 = MONK_MODELS.find(
892
- (m) => m.id === targetModel || m.id.endsWith(targetModel)
893
- );
894
- if (!matched2) {
895
- logWarn(`\u672A\u77E5\u6A21\u578B: "${targetModel}"`);
896
- logInfo(`\u652F\u6301\u7684\u6A21\u578B\u5217\u8868: ${MONK_MODELS.map((m) => m.id).join(", ")}`);
897
- return;
898
- }
899
- saveMonkConfig({ defaultModel: matched2.id });
900
- logSuccess(`\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B\u5DF2\u5207\u6362\u4E3A: ${pc5.bold(pc5.yellow(matched2.name))}`);
901
- return;
902
- }
903
- const selected = await promptSelectModel(currentModel);
904
- saveMonkConfig({ defaultModel: selected });
905
- const matched = MONK_MODELS.find((m) => m.id === selected);
906
- console.log();
907
- logSuccess(`\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B\u5DF2\u6210\u529F\u8BBE\u5B9A\u4E3A: ${pc5.bold(pc5.yellow(matched?.name || selected))}`);
908
- console.log();
909
- }
910
-
911
- // src/commands/run.ts
912
- async function runCommand(passthroughArgs) {
913
- const piCheck = detectPi();
914
- if (!piCheck.installed) {
915
- const shouldInstall = await promptInstallPi();
916
- if (shouldInstall) {
917
- const installed = await installPi();
918
- if (!installed) {
919
- logError("\u65E0\u6CD5\u81EA\u52A8\u5B89\u88C5 Pi\uFF0C\u8BF7\u624B\u52A8\u8FD0\u884C `npm install -g @earendil-works/pi-coding-agent` \u540E\u91CD\u8BD5\u3002");
920
- return 1;
921
- }
922
- } else {
923
- logWarn("\u5DF2\u53D6\u6D88\u8FD0\u884C\u3002Monk Harness \u9700\u8981 Pi \u4F5C\u4E3A\u8FD0\u884C\u5E95\u5EA7\u3002");
924
- return 1;
925
- }
926
- }
927
- let { key } = resolveApiKey();
928
- if (!key) {
929
- logWarn("\u672A\u68C0\u6D4B\u5230 Monk API Key\uFF0C\u6B63\u5728\u4E3A\u60A8\u542F\u52A8\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC...");
930
- const ok = await loginCommand();
931
- if (!ok) {
932
- return 1;
933
- }
934
- const resolved = resolveApiKey();
935
- key = resolved.key;
936
- }
937
- if (!key) {
938
- logError("\u672A\u627E\u5230\u6709\u6548\u7684 Monk API Key\uFF0C\u9000\u51FA\u8FD0\u884C\u3002");
939
- return 1;
940
- }
941
- syncPiModelsJson(key);
942
- syncPiExtension();
943
- const defaultModel = getDefaultModel();
944
- return launchPi({
945
- apiKey: key,
946
- defaultModel,
947
- passthroughArgs
948
- });
949
- }
950
-
951
- // src/commands/status.ts
952
- import pc6 from "picocolors";
953
- async function statusCommand() {
954
- printBanner();
955
- console.log(` ${pc6.bold("\u3010\u670D\u52A1\u4E0E\u73AF\u5883\u72B6\u6001\u68C0\u6D4B\u3011")}`);
956
- console.log();
957
- const piDetect = detectPi();
958
- if (piDetect.installed) {
959
- logSuccess(
960
- `Pi \u8FD0\u884C\u73AF\u5883: ${pc6.bold("\u5DF2\u5C31\u7EEA")} (v${piDetect.version}) \xB7 ${pc6.dim(`[\u6765\u6E90: ${piDetect.description}]`)}`
961
- );
962
- } else {
963
- logWarn(`Pi \u8FD0\u884C\u73AF\u5883: ${pc6.red("\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u8FD0\u884C\u65F6")}`);
964
- console.log(` ${pc6.dim("\u8BF7\u8FD0\u884C npm install -g @earendil-works/pi-coding-agent")}`);
965
- }
966
- const { key, source } = resolveApiKey();
967
- const defaultModel = getDefaultModel();
968
- if (!key) {
969
- logError(`Monk API Key: ${pc6.red("\u672A\u914D\u7F6E")}`);
970
- console.log(` ${pc6.dim("\u8BF7\u8FD0\u884C `monk-pi login` \u8F93\u5165\u60A8\u7684 Key")}`);
971
- return;
972
- }
973
- const sourceLabels = {
974
- env: "\u73AF\u5883\u53D8\u91CF ($MONK_API_KEY)",
975
- local: `\u672C\u5730\u914D\u7F6E (${getMonkConfigFile()})`,
976
- pi: `Pi \u914D\u7F6E\u6587\u4EF6 (${getPiModelsFile()})`,
977
- none: "\u65E0"
978
- };
979
- logSuccess(`Monk API Key: ${pc6.bold(maskKey(key))} ${pc6.dim(`[\u6765\u6E90: ${sourceLabels[source]}]`)}`);
980
- logInfo(`\u5F53\u524D\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B: ${pc6.yellow(defaultModel)}`);
981
- logInfo(`Monk \u57FA\u7840\u5730\u5740: ${pc6.dim(MONK_BASE_URL)}`);
982
- process.stdout.write(` ${pc6.dim("\u23F3 \u6B63\u5728\u6D4B\u8BD5 Monk API \u8FDE\u63A5\u4E0E\u8BA4\u8BC1...")} `);
983
- const valResult = await validateApiKey(key);
984
- if (valResult.valid) {
985
- process.stdout.write("\r" + " ".repeat(50) + "\r");
986
- logSuccess(
987
- `Monk API \u8FDE\u63A5\u6B63\u5E38 ${pc6.dim("\xB7")} \u8BA4\u8BC1\u6709\u6548 ${pc6.dim("\xB7")} \u5EF6\u8FDF: ${pc6.green(`${valResult.latencyMs}ms`)}`
988
- );
989
- if (valResult.models.length > 0) {
990
- logInfo(`\u652F\u6301\u7684\u6A21\u578B\u7AEF\u70B9: ${pc6.dim(valResult.models.join(" \xB7 "))}`);
991
- }
992
- } else {
993
- process.stdout.write("\r" + " ".repeat(50) + "\r");
994
- logError(`Monk API \u9A8C\u8BC1\u5F02\u5E38: ${valResult.error}`);
995
- return;
996
- }
997
- process.stdout.write(` ${pc6.dim(`\u23F3 \u6B63\u5728\u5BF9 ${defaultModel} \u53D1\u8D77\u6781\u7B80\u63E1\u624B\u63A8\u6F14...`)} `);
998
- const testRes = await testChatCompletion(key, defaultModel);
999
- if (testRes.success) {
1000
- process.stdout.write("\r" + " ".repeat(50) + "\r");
1001
- logSuccess(
1002
- `\u63A8\u7406\u901A\u9053\u63E1\u624B\u6210\u529F ${pc6.dim("\xB7")} \u54CD\u5E94\u5EF6\u8FDF: ${pc6.green(`${testRes.latencyMs}ms`)}`
1003
- );
1004
- } else {
1005
- process.stdout.write("\r" + " ".repeat(50) + "\r");
1006
- logWarn(`\u63A8\u7406\u901A\u9053\u63E1\u624B\u8F7B\u5FAE\u544A\u8B66: ${testRes.error || "\u672A\u8FD4\u56DE\u5E38\u89C4\u5185\u5BB9"}`);
1007
- }
1008
- console.log();
1009
- console.log(pc6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1010
- console.log(` ${pc6.dim("\u5B98\u65B9\u7F51\u7AD9:")} ${pc6.cyan(MONK_WEBSITE)}`);
1011
- console.log(` ${pc6.dim("\u7528\u91CF\u4E0E\u5230\u671F\u67E5\u8BE2:")} ${pc6.cyan(MONK_ACCOUNT_URL)}`);
1012
- console.log();
1013
- }
1014
-
1015
- export {
1016
- MONK_BASE_URL,
1017
- MONK_WEBSITE,
1018
- MONK_ACCOUNT_URL,
1019
- MONK_MODELS,
1020
- DEFAULT_MONK_MODEL,
1021
- getMonkHomeDir,
1022
- getMonkConfigFile,
1023
- getPiHomeDir,
1024
- getPiModelsFile,
1025
- getPiSettingsFile,
1026
- getPiExtensionsDir,
1027
- getPiMonkExtensionFile,
1028
- loadMonkConfig,
1029
- saveMonkConfig,
1030
- resolveApiKey,
1031
- syncPiModelsJson,
1032
- syncPiExtension,
1033
- getDefaultModel,
1034
- validateApiKey,
1035
- testChatCompletion,
1036
- printBanner,
1037
- logSuccess,
1038
- logInfo,
1039
- logWarn,
1040
- logError,
1041
- logStep,
1042
- promptForApiKey,
1043
- promptSelectModel,
1044
- promptInstallPi,
1045
- maskKey,
1046
- resolvePiBinary,
1047
- detectPi,
1048
- detectPackageManager,
1049
- installPi,
1050
- launchPi,
1051
- doctorCommand,
1052
- loginCommand,
1053
- modelCommand,
1054
- runCommand,
1055
- statusCommand
1056
- };