monk-pi 0.2.0 → 0.10.2
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/README.md +71 -8
- package/dist/{chunk-6OMOTI3T.js → chunk-GGAUER4O.js} +203 -254
- package/dist/cli.js +170 -26
- package/dist/index.d.ts +9 -3
- package/dist/index.js +5 -1
- package/dist/monk-extension.ts +853 -0
- package/package.json +1 -1
|
@@ -55,207 +55,8 @@ function getPiMonkExtensionFile() {
|
|
|
55
55
|
|
|
56
56
|
// src/config.ts
|
|
57
57
|
import fs from "fs";
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
58
|
+
import path2 from "path";
|
|
59
|
+
import { fileURLToPath } from "url";
|
|
259
60
|
function loadMonkConfig() {
|
|
260
61
|
const configFile = getMonkConfigFile();
|
|
261
62
|
try {
|
|
@@ -354,19 +155,59 @@ function syncPiModelsJson(apiKey) {
|
|
|
354
155
|
};
|
|
355
156
|
}
|
|
356
157
|
}
|
|
357
|
-
function
|
|
158
|
+
function getMonkExtensionRaw() {
|
|
159
|
+
try {
|
|
160
|
+
const distPath = path2.resolve(
|
|
161
|
+
path2.dirname(fileURLToPath(import.meta.url)),
|
|
162
|
+
"monk-extension.ts"
|
|
163
|
+
);
|
|
164
|
+
if (fs.existsSync(distPath)) {
|
|
165
|
+
return fs.readFileSync(distPath, "utf-8");
|
|
166
|
+
}
|
|
167
|
+
const srcPath = path2.resolve(
|
|
168
|
+
path2.dirname(fileURLToPath(import.meta.url)),
|
|
169
|
+
"../src/extension/monk-extension.ts"
|
|
170
|
+
);
|
|
171
|
+
if (fs.existsSync(srcPath)) {
|
|
172
|
+
return fs.readFileSync(srcPath, "utf-8");
|
|
173
|
+
}
|
|
174
|
+
const cwdPath = path2.resolve(process.cwd(), "src/extension/monk-extension.ts");
|
|
175
|
+
if (fs.existsSync(cwdPath)) {
|
|
176
|
+
return fs.readFileSync(cwdPath, "utf-8");
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
}
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
function syncPiExtension(force = false) {
|
|
358
183
|
const extDir = getPiExtensionsDir();
|
|
359
184
|
const extFile = getPiMonkExtensionFile();
|
|
360
185
|
try {
|
|
361
186
|
if (!fs.existsSync(extDir)) {
|
|
362
187
|
fs.mkdirSync(extDir, { recursive: true });
|
|
363
188
|
}
|
|
364
|
-
|
|
365
|
-
|
|
189
|
+
const targetContent = getMonkExtensionRaw().trim() + "\n";
|
|
190
|
+
if (!targetContent.trim()) {
|
|
191
|
+
return {
|
|
192
|
+
success: false,
|
|
193
|
+
path: extFile,
|
|
194
|
+
updated: false,
|
|
195
|
+
error: "\u672A\u627E\u5230\u6269\u5C55\u6E90\u6587\u4EF6 monk-extension.ts"
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
if (fs.existsSync(extFile)) {
|
|
199
|
+
const existing = fs.readFileSync(extFile, "utf-8");
|
|
200
|
+
if (existing === targetContent && !force) {
|
|
201
|
+
return { success: true, path: extFile, updated: false };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
fs.writeFileSync(extFile, targetContent, "utf-8");
|
|
205
|
+
return { success: true, path: extFile, updated: true };
|
|
366
206
|
} catch (err) {
|
|
367
207
|
return {
|
|
368
208
|
success: false,
|
|
369
209
|
path: extFile,
|
|
210
|
+
updated: false,
|
|
370
211
|
error: err instanceof Error ? err.message : String(err)
|
|
371
212
|
};
|
|
372
213
|
}
|
|
@@ -443,12 +284,27 @@ async function validateApiKey(apiKey, baseUrl = MONK_BASE_URL) {
|
|
|
443
284
|
};
|
|
444
285
|
}
|
|
445
286
|
}
|
|
287
|
+
function extractFirstJson(text) {
|
|
288
|
+
try {
|
|
289
|
+
return JSON.parse(text);
|
|
290
|
+
} catch {
|
|
291
|
+
const cleaned = text.replace(/^data:\s*/gm, "");
|
|
292
|
+
const start = cleaned.indexOf("{");
|
|
293
|
+
const end = cleaned.lastIndexOf("}");
|
|
294
|
+
if (start === -1 || end <= start) return {};
|
|
295
|
+
try {
|
|
296
|
+
return JSON.parse(cleaned.slice(start, end + 1));
|
|
297
|
+
} catch {
|
|
298
|
+
return {};
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
446
302
|
async function testChatCompletion(apiKey, model = "monk-fast", baseUrl = MONK_BASE_URL) {
|
|
447
303
|
const endpoint = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
|
|
448
304
|
const startTime = Date.now();
|
|
449
305
|
try {
|
|
450
306
|
const controller = new AbortController();
|
|
451
|
-
const timeoutId = setTimeout(() => controller.abort(),
|
|
307
|
+
const timeoutId = setTimeout(() => controller.abort(), 3e4);
|
|
452
308
|
const response = await fetch(endpoint, {
|
|
453
309
|
method: "POST",
|
|
454
310
|
headers: {
|
|
@@ -465,16 +321,15 @@ async function testChatCompletion(apiKey, model = "monk-fast", baseUrl = MONK_BA
|
|
|
465
321
|
});
|
|
466
322
|
clearTimeout(timeoutId);
|
|
467
323
|
const latencyMs = Date.now() - startTime;
|
|
324
|
+
const payload = extractFirstJson(await response.text());
|
|
468
325
|
if (!response.ok) {
|
|
469
|
-
const errJson = await response.json().catch(() => ({}));
|
|
470
326
|
return {
|
|
471
327
|
success: false,
|
|
472
328
|
latencyMs,
|
|
473
|
-
error:
|
|
329
|
+
error: payload.error?.message || `HTTP ${response.status}`
|
|
474
330
|
};
|
|
475
331
|
}
|
|
476
|
-
const
|
|
477
|
-
const reply = json.choices?.[0]?.message?.content?.trim() || "";
|
|
332
|
+
const reply = (payload.choices?.[0]?.message?.content ?? "").trim();
|
|
478
333
|
return {
|
|
479
334
|
success: true,
|
|
480
335
|
latencyMs,
|
|
@@ -491,8 +346,25 @@ async function testChatCompletion(apiKey, model = "monk-fast", baseUrl = MONK_BA
|
|
|
491
346
|
}
|
|
492
347
|
|
|
493
348
|
// src/ui.ts
|
|
349
|
+
import spawn from "cross-spawn";
|
|
494
350
|
import pc from "picocolors";
|
|
495
351
|
import { password, select, confirm } from "@inquirer/prompts";
|
|
352
|
+
function openBrowser(url) {
|
|
353
|
+
try {
|
|
354
|
+
if (process.platform === "darwin") {
|
|
355
|
+
spawn("open", [url], { stdio: "ignore", detached: true });
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
if (process.platform === "win32") {
|
|
359
|
+
spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true });
|
|
360
|
+
return true;
|
|
361
|
+
}
|
|
362
|
+
spawn("xdg-open", [url], { stdio: "ignore", detached: true });
|
|
363
|
+
return true;
|
|
364
|
+
} catch {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
496
368
|
function printBanner() {
|
|
497
369
|
const line = pc.dim("\u2500".repeat(54));
|
|
498
370
|
console.log();
|
|
@@ -526,11 +398,62 @@ function logStep(step, total, msg) {
|
|
|
526
398
|
async function promptForApiKey(currentKey) {
|
|
527
399
|
console.log();
|
|
528
400
|
console.log(` ${pc.bold("\u6B22\u8FCE\u4F7F\u7528 Monk \xD7 Pi \u7F16\u7801\u4F34\u4FA3\uFF01")}`);
|
|
529
|
-
console.log(
|
|
530
|
-
|
|
401
|
+
console.log(
|
|
402
|
+
` ${pc.dim("Monk \u4E13\u4E3A Agent \u63D0\u4F9B\u6781\u901F\u9AD8\u541E\u5410\u878D\u5408\u6A21\u578B (\u6708\u5361 \xA530 / 100\u4E07 Token \u4E0A\u4E0B\u6587)")}`
|
|
403
|
+
);
|
|
531
404
|
console.log();
|
|
405
|
+
if (!currentKey) {
|
|
406
|
+
const action = await select({
|
|
407
|
+
message: "\u8BF7\u9009\u62E9\u914D\u7F6E\u6216\u83B7\u53D6 Monk API Key \u7684\u65B9\u5F0F:",
|
|
408
|
+
choices: [
|
|
409
|
+
{
|
|
410
|
+
name: `1. \u6211\u5DF2\u6709 API Key\uFF0C\u76F4\u63A5\u7C98\u8D34\u8F93\u5165 ${pc.dim("(sk-monk-...)")}`,
|
|
411
|
+
value: "input"
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: `2. \u6211\u8FD8\u6CA1\u6709 Key\uFF0C\u7ACB\u5373\u6253\u5F00 monk.party \u8BA2\u9605 ${pc.green("(\u63A8\u8350 \xB7 \u56DE\u8F66\u6D4F\u89C8\u5668\u626B\u7801)")}`,
|
|
415
|
+
value: "open_browser"
|
|
416
|
+
}
|
|
417
|
+
]
|
|
418
|
+
});
|
|
419
|
+
if (action === "open_browser") {
|
|
420
|
+
logInfo(`\u6B63\u5728\u4E3A\u60A8\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u6253\u5F00\u5B98\u7F51: ${pc.cyan(MONK_WEBSITE)} ...`);
|
|
421
|
+
openBrowser(MONK_WEBSITE);
|
|
422
|
+
console.log();
|
|
423
|
+
logSuccess("\u5DF2\u5524\u8D77\u6D4F\u89C8\u5668\uFF01\u8BF7\u5728\u7F51\u9875\u5B8C\u6210\u8BA2\u9605\u540E\uFF0C\u5C06\u751F\u6210\u7684 sk-monk-... Key \u590D\u5236\u5E76\u7C98\u8D34\u5230\u4E0B\u65B9\uFF1A");
|
|
424
|
+
console.log();
|
|
425
|
+
}
|
|
426
|
+
} else {
|
|
427
|
+
const action = await select({
|
|
428
|
+
message: `\u68C0\u6D4B\u5230\u5DF2\u914D\u7F6E Key (${maskKey(currentKey)})\uFF0C\u8BF7\u9009\u62E9\u64CD\u4F5C:`,
|
|
429
|
+
choices: [
|
|
430
|
+
{
|
|
431
|
+
name: "1. \u4FDD\u6301\u5E76\u6D4B\u8BD5\u5F53\u524D Key",
|
|
432
|
+
value: "keep"
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
name: "2. \u66F4\u6362\u4E3A\u65B0\u7684 API Key",
|
|
436
|
+
value: "replace"
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
name: `3. \u5728\u6D4F\u89C8\u5668\u6253\u5F00 monk.party \u5B98\u7F51 (\u67E5\u8BE2/\u7EED\u8D39)`,
|
|
440
|
+
value: "open_browser"
|
|
441
|
+
}
|
|
442
|
+
]
|
|
443
|
+
});
|
|
444
|
+
if (action === "keep") {
|
|
445
|
+
return currentKey;
|
|
446
|
+
}
|
|
447
|
+
if (action === "open_browser") {
|
|
448
|
+
logInfo(`\u6B63\u5728\u4E3A\u60A8\u5728\u6D4F\u89C8\u5668\u6253\u5F00\u5B98\u7F51: ${pc.cyan(MONK_ACCOUNT_URL)} ...`);
|
|
449
|
+
openBrowser(MONK_ACCOUNT_URL);
|
|
450
|
+
console.log();
|
|
451
|
+
logInfo("\u5DF2\u6253\u5F00\u67E5\u8BE2\u9875\u9762\u3002\u5982\u9700\u66F4\u6362 Key \u8BF7\u5728\u4E0B\u65B9\u7C98\u8D34\uFF0C\u76F4\u63A5\u56DE\u8F66\u4FDD\u6301\u5F53\u524D Key\uFF1A");
|
|
452
|
+
console.log();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
532
455
|
const key = await password({
|
|
533
|
-
message: currentKey ? `\u8BF7\u8F93\u5165 Monk API Key (\u76F4\u63A5\u56DE\u8F66\u4FDD\u6301\u5F53\u524D: ${maskKey(currentKey)}):` : "\u8BF7\
|
|
456
|
+
message: currentKey ? `\u8BF7\u8F93\u5165 Monk API Key (\u76F4\u63A5\u56DE\u8F66\u4FDD\u6301\u5F53\u524D: ${maskKey(currentKey)}):` : "\u8BF7\u7C98\u8D34\u60A8\u7684 Monk API Key (sk-monk-...):",
|
|
534
457
|
mask: "*",
|
|
535
458
|
validate: (val) => {
|
|
536
459
|
const trimmed = val.trim();
|
|
@@ -574,13 +497,13 @@ function maskKey(key) {
|
|
|
574
497
|
|
|
575
498
|
// src/pi-runner.ts
|
|
576
499
|
import fs2 from "fs";
|
|
577
|
-
import
|
|
578
|
-
import { fileURLToPath } from "url";
|
|
579
|
-
import
|
|
500
|
+
import path3 from "path";
|
|
501
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
502
|
+
import spawn2 from "cross-spawn";
|
|
580
503
|
import pc2 from "picocolors";
|
|
581
504
|
function resolvePiBinary() {
|
|
582
505
|
try {
|
|
583
|
-
const globalCheck =
|
|
506
|
+
const globalCheck = spawn2.sync("pi", ["--version"], {
|
|
584
507
|
encoding: "utf-8",
|
|
585
508
|
stdio: ["ignore", "pipe", "ignore"]
|
|
586
509
|
});
|
|
@@ -596,13 +519,13 @@ function resolvePiBinary() {
|
|
|
596
519
|
} catch {
|
|
597
520
|
}
|
|
598
521
|
const candidateBinDirs = [
|
|
599
|
-
|
|
600
|
-
|
|
522
|
+
path3.resolve(path3.dirname(fileURLToPath2(import.meta.url)), "../node_modules/.bin/pi"),
|
|
523
|
+
path3.resolve(process.cwd(), "node_modules/.bin/pi")
|
|
601
524
|
];
|
|
602
525
|
for (const binPath of candidateBinDirs) {
|
|
603
526
|
if (fs2.existsSync(binPath)) {
|
|
604
527
|
try {
|
|
605
|
-
const localCheck =
|
|
528
|
+
const localCheck = spawn2.sync(binPath, ["--version"], {
|
|
606
529
|
encoding: "utf-8",
|
|
607
530
|
stdio: ["ignore", "pipe", "ignore"]
|
|
608
531
|
});
|
|
@@ -612,7 +535,7 @@ function resolvePiBinary() {
|
|
|
612
535
|
command: binPath,
|
|
613
536
|
argsPrefix: [],
|
|
614
537
|
version: localCheck.stdout.trim(),
|
|
615
|
-
sourceDescription: `\u672C\u5730\u4F9D\u8D56 (${
|
|
538
|
+
sourceDescription: `\u672C\u5730\u4F9D\u8D56 (${path3.basename(path3.dirname(binPath))})`
|
|
616
539
|
};
|
|
617
540
|
}
|
|
618
541
|
} catch {
|
|
@@ -620,10 +543,10 @@ function resolvePiBinary() {
|
|
|
620
543
|
}
|
|
621
544
|
}
|
|
622
545
|
try {
|
|
623
|
-
const mainEntry =
|
|
624
|
-
const cliEntry =
|
|
546
|
+
const mainEntry = fileURLToPath2(import.meta.resolve("@earendil-works/pi-coding-agent"));
|
|
547
|
+
const cliEntry = path3.join(path3.dirname(mainEntry), "bundle", "cli.js");
|
|
625
548
|
if (fs2.existsSync(cliEntry)) {
|
|
626
|
-
const moduleCheck =
|
|
549
|
+
const moduleCheck = spawn2.sync(process.execPath, [cliEntry, "--version"], {
|
|
627
550
|
encoding: "utf-8",
|
|
628
551
|
stdio: ["ignore", "pipe", "ignore"]
|
|
629
552
|
});
|
|
@@ -657,12 +580,12 @@ function detectPi() {
|
|
|
657
580
|
}
|
|
658
581
|
function detectPackageManager() {
|
|
659
582
|
try {
|
|
660
|
-
const bunCheck =
|
|
583
|
+
const bunCheck = spawn2.sync("bun", ["--version"], { stdio: "ignore" });
|
|
661
584
|
if (bunCheck.status === 0) return "bun";
|
|
662
585
|
} catch {
|
|
663
586
|
}
|
|
664
587
|
try {
|
|
665
|
-
const pnpmCheck =
|
|
588
|
+
const pnpmCheck = spawn2.sync("pnpm", ["--version"], { stdio: "ignore" });
|
|
666
589
|
if (pnpmCheck.status === 0) return "pnpm";
|
|
667
590
|
} catch {
|
|
668
591
|
}
|
|
@@ -681,7 +604,7 @@ async function installPi() {
|
|
|
681
604
|
}
|
|
682
605
|
logInfo(`\u68C0\u6D4B\u5230\u5305\u7BA1\u7406\u5668: ${pc2.bold(pm)}\uFF0C\u6B63\u5728\u6267\u884C: ${pc2.yellow(`${cmd} ${args.join(" ")}`)} ...`);
|
|
683
606
|
try {
|
|
684
|
-
const child =
|
|
607
|
+
const child = spawn2.sync(cmd, args, {
|
|
685
608
|
stdio: "inherit"
|
|
686
609
|
});
|
|
687
610
|
if (child.status === 0) {
|
|
@@ -720,7 +643,7 @@ function launchPi(options) {
|
|
|
720
643
|
...process.env,
|
|
721
644
|
MONK_API_KEY: apiKey
|
|
722
645
|
};
|
|
723
|
-
const child =
|
|
646
|
+
const child = spawn2(resolved.command, fullArgs, {
|
|
724
647
|
stdio: "inherit",
|
|
725
648
|
env
|
|
726
649
|
});
|
|
@@ -807,17 +730,19 @@ async function doctorCommand() {
|
|
|
807
730
|
syncPiModelsJson(key);
|
|
808
731
|
logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u521B\u5EFA\u5B8C\u6210`);
|
|
809
732
|
}
|
|
810
|
-
const
|
|
811
|
-
if (
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
if (extRes.success) {
|
|
817
|
-
logSuccess(`Pi \u539F\u751F\u6269\u5C55: \u90E8\u7F72\u5B8C\u6210`);
|
|
733
|
+
const extRes = syncPiExtension();
|
|
734
|
+
if (extRes.success) {
|
|
735
|
+
if (extRes.updated) {
|
|
736
|
+
logSuccess(
|
|
737
|
+
`Pi \u539F\u751F\u6269\u5C55: ${pc3.bold("\u5DF2\u81EA\u52A8\u66F4\u65B0\u81F3\u6700\u65B0\u7248")} (\u4E2D\u6587\u5DE5\u7A0B\u63D0\u793A\u8BCD\u3001/monk \u6307\u4EE4\u4E0E\u81EA\u52A8\u91CD\u8BD5\u5C31\u7EEA)`
|
|
738
|
+
);
|
|
818
739
|
} else {
|
|
819
|
-
|
|
740
|
+
logSuccess(
|
|
741
|
+
`Pi \u539F\u751F\u6269\u5C55: ${pc3.bold("\u5DF2\u5C31\u7EEA")} (\u4E2D\u6587\u5DE5\u7A0B\u63D0\u793A\u8BCD\u3001/monk \u6307\u4EE4\u4E0E\u81EA\u52A8\u91CD\u8BD5\u5C31\u7EEA)`
|
|
742
|
+
);
|
|
820
743
|
}
|
|
744
|
+
} else {
|
|
745
|
+
logError(`Pi \u539F\u751F\u6269\u5C55\u90E8\u7F72\u5931\u8D25: ${extRes.error}`);
|
|
821
746
|
}
|
|
822
747
|
if (key) {
|
|
823
748
|
process.stdout.write(` ${pc3.dim("\u23F3 \u6B63\u5728\u63A2\u6D4B\u4E0E monk.party \u63A5\u53E3\u7684\u8FDE\u901A\u6027...")} `);
|
|
@@ -908,6 +833,23 @@ async function modelCommand(targetModel) {
|
|
|
908
833
|
console.log();
|
|
909
834
|
}
|
|
910
835
|
|
|
836
|
+
// src/commands/run.ts
|
|
837
|
+
import pc6 from "picocolors";
|
|
838
|
+
|
|
839
|
+
// src/extension/monk-extension.ts
|
|
840
|
+
import fs4 from "fs";
|
|
841
|
+
import path4 from "path";
|
|
842
|
+
var PRO_TIPS = [
|
|
843
|
+
"\u5728\u8F93\u5165\u6846\u8F93\u5165 @diff \u5373\u53EF\u79D2\u7EA7\u628A\u5F53\u524D\u672A\u63D0\u4EA4\u6539\u52A8\u5E26\u5165\u5206\u6790",
|
|
844
|
+
"\u8F93\u5165 /commit \u53EF\u6309 Conventional Commits \u89C4\u8303\u81EA\u52A8\u751F\u6210\u4E2D\u6587\u63D0\u4EA4",
|
|
845
|
+
"AI \u6539\u4E71\u4E86\u4EE3\u7801\u4E0D\u7528\u614C\uFF0C\u968F\u65F6\u8F93\u5165 /undo \u6216 /\u56DE\u9000 \u77AC\u95F4\u4E00\u952E\u590D\u539F",
|
|
846
|
+
"\u8F93\u5165 /review \u53EF\u4ECE\u7F3A\u9677\u3001\u6027\u80FD\u3001\u67B6\u6784\u56DB\u4E2A\u7EF4\u5EA6\u5BF9\u4EE3\u7801\u8FDB\u884C\u6DF1\u5EA6\u5BA1\u67E5",
|
|
847
|
+
"\u8F93\u5165 /monk \u53EF\u547C\u51FA\u56FE\u5F62\u5316\u63A7\u5236\u53F0\uFF0C\u79D2\u7EA7\u514D\u91CD\u542F\u5207\u6362\u4E3B\u529B\u6A21\u578B",
|
|
848
|
+
"\u8F93\u5165 @recent \u5FEB\u901F\u63D0\u53D6\u6700\u8FD1\u53D8\u52A8\u7684\u9879\u76EE\u6838\u5FC3\u6E90\u6587\u4EF6\u5217\u8868",
|
|
849
|
+
"\u8F93\u5165 /monk cn \u968F\u65F6\u5207\u6362\u4E2D\u6587\u5DE5\u7A0B\u7CBE\u70BC\u6A21\u5F0F\uFF08\u96F6\u5BA2\u5957\xB7\u884C\u52A8\u4F18\u5148\uFF09",
|
|
850
|
+
"\u7EC8\u7AEF\u8F93\u5165 monk-pi -r \u53EF\u89C6\u5316\u6062\u590D\u4EE5\u5F80\u4EFB\u610F\u5386\u53F2\u4EFB\u52A1\u65AD\u70B9\u7EED\u5199"
|
|
851
|
+
];
|
|
852
|
+
|
|
911
853
|
// src/commands/run.ts
|
|
912
854
|
async function runCommand(passthroughArgs) {
|
|
913
855
|
const piCheck = detectPi();
|
|
@@ -941,6 +883,11 @@ async function runCommand(passthroughArgs) {
|
|
|
941
883
|
syncPiModelsJson(key);
|
|
942
884
|
syncPiExtension();
|
|
943
885
|
const defaultModel = getDefaultModel();
|
|
886
|
+
if (!passthroughArgs.includes("-p") && !passthroughArgs.includes("--print")) {
|
|
887
|
+
const tip = PRO_TIPS[Math.floor(Math.random() * PRO_TIPS.length)];
|
|
888
|
+
console.log(` ${pc6.yellow("\u{1F4A1} \u6781\u5BA2\u5C0F\u8D34\u58EB:")} ${pc6.dim(tip)}`);
|
|
889
|
+
console.log();
|
|
890
|
+
}
|
|
944
891
|
return launchPi({
|
|
945
892
|
apiKey: key,
|
|
946
893
|
defaultModel,
|
|
@@ -949,25 +896,25 @@ async function runCommand(passthroughArgs) {
|
|
|
949
896
|
}
|
|
950
897
|
|
|
951
898
|
// src/commands/status.ts
|
|
952
|
-
import
|
|
899
|
+
import pc7 from "picocolors";
|
|
953
900
|
async function statusCommand() {
|
|
954
901
|
printBanner();
|
|
955
|
-
console.log(` ${
|
|
902
|
+
console.log(` ${pc7.bold("\u3010\u670D\u52A1\u4E0E\u73AF\u5883\u72B6\u6001\u68C0\u6D4B\u3011")}`);
|
|
956
903
|
console.log();
|
|
957
904
|
const piDetect = detectPi();
|
|
958
905
|
if (piDetect.installed) {
|
|
959
906
|
logSuccess(
|
|
960
|
-
`Pi \u8FD0\u884C\u73AF\u5883: ${
|
|
907
|
+
`Pi \u8FD0\u884C\u73AF\u5883: ${pc7.bold("\u5DF2\u5C31\u7EEA")} (v${piDetect.version}) \xB7 ${pc7.dim(`[\u6765\u6E90: ${piDetect.description}]`)}`
|
|
961
908
|
);
|
|
962
909
|
} else {
|
|
963
|
-
logWarn(`Pi \u8FD0\u884C\u73AF\u5883: ${
|
|
964
|
-
console.log(` ${
|
|
910
|
+
logWarn(`Pi \u8FD0\u884C\u73AF\u5883: ${pc7.red("\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u8FD0\u884C\u65F6")}`);
|
|
911
|
+
console.log(` ${pc7.dim("\u8BF7\u8FD0\u884C npm install -g @earendil-works/pi-coding-agent")}`);
|
|
965
912
|
}
|
|
966
913
|
const { key, source } = resolveApiKey();
|
|
967
914
|
const defaultModel = getDefaultModel();
|
|
968
915
|
if (!key) {
|
|
969
|
-
logError(`Monk API Key: ${
|
|
970
|
-
console.log(` ${
|
|
916
|
+
logError(`Monk API Key: ${pc7.red("\u672A\u914D\u7F6E")}`);
|
|
917
|
+
console.log(` ${pc7.dim("\u8BF7\u8FD0\u884C `monk-pi login` \u8F93\u5165\u60A8\u7684 Key")}`);
|
|
971
918
|
return;
|
|
972
919
|
}
|
|
973
920
|
const sourceLabels = {
|
|
@@ -976,39 +923,39 @@ async function statusCommand() {
|
|
|
976
923
|
pi: `Pi \u914D\u7F6E\u6587\u4EF6 (${getPiModelsFile()})`,
|
|
977
924
|
none: "\u65E0"
|
|
978
925
|
};
|
|
979
|
-
logSuccess(`Monk API Key: ${
|
|
980
|
-
logInfo(`\u5F53\u524D\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B: ${
|
|
981
|
-
logInfo(`Monk \u57FA\u7840\u5730\u5740: ${
|
|
982
|
-
process.stdout.write(` ${
|
|
926
|
+
logSuccess(`Monk API Key: ${pc7.bold(maskKey(key))} ${pc7.dim(`[\u6765\u6E90: ${sourceLabels[source]}]`)}`);
|
|
927
|
+
logInfo(`\u5F53\u524D\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B: ${pc7.yellow(defaultModel)}`);
|
|
928
|
+
logInfo(`Monk \u57FA\u7840\u5730\u5740: ${pc7.dim(MONK_BASE_URL)}`);
|
|
929
|
+
process.stdout.write(` ${pc7.dim("\u23F3 \u6B63\u5728\u6D4B\u8BD5 Monk API \u8FDE\u63A5\u4E0E\u8BA4\u8BC1...")} `);
|
|
983
930
|
const valResult = await validateApiKey(key);
|
|
984
931
|
if (valResult.valid) {
|
|
985
932
|
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
986
933
|
logSuccess(
|
|
987
|
-
`Monk API \u8FDE\u63A5\u6B63\u5E38 ${
|
|
934
|
+
`Monk API \u8FDE\u63A5\u6B63\u5E38 ${pc7.dim("\xB7")} \u8BA4\u8BC1\u6709\u6548 ${pc7.dim("\xB7")} \u5EF6\u8FDF: ${pc7.green(`${valResult.latencyMs}ms`)}`
|
|
988
935
|
);
|
|
989
936
|
if (valResult.models.length > 0) {
|
|
990
|
-
logInfo(`\u652F\u6301\u7684\u6A21\u578B\u7AEF\u70B9: ${
|
|
937
|
+
logInfo(`\u652F\u6301\u7684\u6A21\u578B\u7AEF\u70B9: ${pc7.dim(valResult.models.join(" \xB7 "))}`);
|
|
991
938
|
}
|
|
992
939
|
} else {
|
|
993
940
|
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
994
941
|
logError(`Monk API \u9A8C\u8BC1\u5F02\u5E38: ${valResult.error}`);
|
|
995
942
|
return;
|
|
996
943
|
}
|
|
997
|
-
process.stdout.write(` ${
|
|
944
|
+
process.stdout.write(` ${pc7.dim(`\u23F3 \u6B63\u5728\u5BF9 ${defaultModel} \u53D1\u8D77\u6781\u7B80\u63E1\u624B\u63A8\u6F14...`)} `);
|
|
998
945
|
const testRes = await testChatCompletion(key, defaultModel);
|
|
999
946
|
if (testRes.success) {
|
|
1000
947
|
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
1001
948
|
logSuccess(
|
|
1002
|
-
`\u63A8\u7406\u901A\u9053\u63E1\u624B\u6210\u529F ${
|
|
949
|
+
`\u63A8\u7406\u901A\u9053\u63E1\u624B\u6210\u529F ${pc7.dim("\xB7")} \u54CD\u5E94\u5EF6\u8FDF: ${pc7.green(`${testRes.latencyMs}ms`)}`
|
|
1003
950
|
);
|
|
1004
951
|
} else {
|
|
1005
952
|
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
1006
953
|
logWarn(`\u63A8\u7406\u901A\u9053\u63E1\u624B\u8F7B\u5FAE\u544A\u8B66: ${testRes.error || "\u672A\u8FD4\u56DE\u5E38\u89C4\u5185\u5BB9"}`);
|
|
1007
954
|
}
|
|
1008
955
|
console.log();
|
|
1009
|
-
console.log(
|
|
1010
|
-
console.log(` ${
|
|
1011
|
-
console.log(` ${
|
|
956
|
+
console.log(pc7.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"));
|
|
957
|
+
console.log(` ${pc7.dim("\u5B98\u65B9\u7F51\u7AD9:")} ${pc7.cyan(MONK_WEBSITE)}`);
|
|
958
|
+
console.log(` ${pc7.dim("\u7528\u91CF\u4E0E\u5230\u671F\u67E5\u8BE2:")} ${pc7.cyan(MONK_ACCOUNT_URL)}`);
|
|
1012
959
|
console.log();
|
|
1013
960
|
}
|
|
1014
961
|
|
|
@@ -1029,10 +976,12 @@ export {
|
|
|
1029
976
|
saveMonkConfig,
|
|
1030
977
|
resolveApiKey,
|
|
1031
978
|
syncPiModelsJson,
|
|
979
|
+
getMonkExtensionRaw,
|
|
1032
980
|
syncPiExtension,
|
|
1033
981
|
getDefaultModel,
|
|
1034
982
|
validateApiKey,
|
|
1035
983
|
testChatCompletion,
|
|
984
|
+
openBrowser,
|
|
1036
985
|
printBanner,
|
|
1037
986
|
logSuccess,
|
|
1038
987
|
logInfo,
|