monk-pi 0.1.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.
- package/README.md +85 -6
- package/dist/chunk-37UZNIY3.js +1772 -0
- package/dist/cli.js +6 -2
- package/dist/index.d.ts +14 -2
- package/dist/index.js +9 -1
- package/package.json +10 -2
- package/dist/chunk-DHF5QVTM.js +0 -812
package/dist/chunk-DHF5QVTM.js
DELETED
|
@@ -1,812 +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
|
-
|
|
50
|
-
// src/config.ts
|
|
51
|
-
import fs from "fs";
|
|
52
|
-
function loadMonkConfig() {
|
|
53
|
-
const configFile = getMonkConfigFile();
|
|
54
|
-
try {
|
|
55
|
-
if (fs.existsSync(configFile)) {
|
|
56
|
-
const content = fs.readFileSync(configFile, "utf-8");
|
|
57
|
-
return JSON.parse(content);
|
|
58
|
-
}
|
|
59
|
-
} catch {
|
|
60
|
-
}
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
function saveMonkConfig(config) {
|
|
64
|
-
const homeDir = getMonkHomeDir();
|
|
65
|
-
if (!fs.existsSync(homeDir)) {
|
|
66
|
-
fs.mkdirSync(homeDir, { recursive: true });
|
|
67
|
-
}
|
|
68
|
-
const configFile = getMonkConfigFile();
|
|
69
|
-
const existing = loadMonkConfig();
|
|
70
|
-
const merged = { ...existing, ...config };
|
|
71
|
-
fs.writeFileSync(configFile, JSON.stringify(merged, null, 2), "utf-8");
|
|
72
|
-
}
|
|
73
|
-
function resolveApiKey() {
|
|
74
|
-
const envKey = process.env.MONK_API_KEY?.trim();
|
|
75
|
-
if (envKey) {
|
|
76
|
-
return { key: envKey, source: "env" };
|
|
77
|
-
}
|
|
78
|
-
const localConfig = loadMonkConfig();
|
|
79
|
-
if (localConfig.apiKey?.trim()) {
|
|
80
|
-
return { key: localConfig.apiKey.trim(), source: "local" };
|
|
81
|
-
}
|
|
82
|
-
const piModelsFile = getPiModelsFile();
|
|
83
|
-
try {
|
|
84
|
-
if (fs.existsSync(piModelsFile)) {
|
|
85
|
-
const data = JSON.parse(fs.readFileSync(piModelsFile, "utf-8"));
|
|
86
|
-
const key = data?.providers?.monk?.apiKey;
|
|
87
|
-
if (typeof key === "string" && key.trim() && !key.startsWith("$")) {
|
|
88
|
-
return { key: key.trim(), source: "pi" };
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
} catch {
|
|
92
|
-
}
|
|
93
|
-
return { key: "", source: "none" };
|
|
94
|
-
}
|
|
95
|
-
function syncPiModelsJson(apiKey) {
|
|
96
|
-
const piDir = getPiHomeDir();
|
|
97
|
-
const piModelsFile = getPiModelsFile();
|
|
98
|
-
try {
|
|
99
|
-
if (!fs.existsSync(piDir)) {
|
|
100
|
-
fs.mkdirSync(piDir, { recursive: true });
|
|
101
|
-
}
|
|
102
|
-
let modelsData = { providers: {} };
|
|
103
|
-
if (fs.existsSync(piModelsFile)) {
|
|
104
|
-
const raw = fs.readFileSync(piModelsFile, "utf-8");
|
|
105
|
-
try {
|
|
106
|
-
modelsData = JSON.parse(raw);
|
|
107
|
-
if (!modelsData.providers) {
|
|
108
|
-
modelsData.providers = {};
|
|
109
|
-
}
|
|
110
|
-
} catch {
|
|
111
|
-
modelsData = { providers: {} };
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
const monkProviderConfig = {
|
|
115
|
-
name: "Monk",
|
|
116
|
-
baseUrl: MONK_BASE_URL,
|
|
117
|
-
api: "openai-completions",
|
|
118
|
-
apiKey: apiKey && !apiKey.startsWith("$") ? apiKey : "$MONK_API_KEY",
|
|
119
|
-
compat: {
|
|
120
|
-
supportsDeveloperRole: false,
|
|
121
|
-
maxTokensField: "max_tokens",
|
|
122
|
-
requiresToolResultName: true
|
|
123
|
-
},
|
|
124
|
-
models: MONK_MODELS.map((m) => ({
|
|
125
|
-
id: m.id,
|
|
126
|
-
name: m.name,
|
|
127
|
-
reasoning: m.reasoning,
|
|
128
|
-
input: ["text"],
|
|
129
|
-
contextWindow: m.contextWindow,
|
|
130
|
-
maxTokens: m.maxTokens,
|
|
131
|
-
cost: {
|
|
132
|
-
input: 0,
|
|
133
|
-
output: 0,
|
|
134
|
-
cacheRead: 0,
|
|
135
|
-
cacheWrite: 0
|
|
136
|
-
}
|
|
137
|
-
}))
|
|
138
|
-
};
|
|
139
|
-
modelsData.providers.monk = monkProviderConfig;
|
|
140
|
-
fs.writeFileSync(piModelsFile, JSON.stringify(modelsData, null, 2), "utf-8");
|
|
141
|
-
return { success: true, path: piModelsFile };
|
|
142
|
-
} catch (err) {
|
|
143
|
-
return {
|
|
144
|
-
success: false,
|
|
145
|
-
path: piModelsFile,
|
|
146
|
-
error: err instanceof Error ? err.message : String(err)
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function getDefaultModel() {
|
|
151
|
-
const config = loadMonkConfig();
|
|
152
|
-
if (config.defaultModel && MONK_MODELS.some((m) => m.id === config.defaultModel)) {
|
|
153
|
-
return config.defaultModel;
|
|
154
|
-
}
|
|
155
|
-
return DEFAULT_MONK_MODEL;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// src/monk-api.ts
|
|
159
|
-
async function validateApiKey(apiKey, baseUrl = MONK_BASE_URL) {
|
|
160
|
-
const trimmedKey = apiKey.trim();
|
|
161
|
-
if (!trimmedKey) {
|
|
162
|
-
return {
|
|
163
|
-
valid: false,
|
|
164
|
-
latencyMs: 0,
|
|
165
|
-
models: [],
|
|
166
|
-
error: "API Key \u4E0D\u80FD\u4E3A\u7A7A"
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
const endpoint = `${baseUrl.replace(/\/+$/, "")}/models`;
|
|
170
|
-
const startTime = Date.now();
|
|
171
|
-
try {
|
|
172
|
-
const controller = new AbortController();
|
|
173
|
-
const timeoutId = setTimeout(() => controller.abort(), 8e3);
|
|
174
|
-
const response = await fetch(endpoint, {
|
|
175
|
-
method: "GET",
|
|
176
|
-
headers: {
|
|
177
|
-
Authorization: `Bearer ${trimmedKey}`,
|
|
178
|
-
Accept: "application/json"
|
|
179
|
-
},
|
|
180
|
-
signal: controller.signal
|
|
181
|
-
});
|
|
182
|
-
clearTimeout(timeoutId);
|
|
183
|
-
const latencyMs = Date.now() - startTime;
|
|
184
|
-
if (response.status === 401 || response.status === 403) {
|
|
185
|
-
const body = await response.json().catch(() => ({}));
|
|
186
|
-
return {
|
|
187
|
-
valid: false,
|
|
188
|
-
latencyMs,
|
|
189
|
-
models: [],
|
|
190
|
-
statusCode: response.status,
|
|
191
|
-
error: body.error?.message || "API Key \u65E0\u6548\u6216\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u68C0\u67E5 monk.party \u7684\u8BA2\u9605\u51ED\u8BC1"
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
if (!response.ok) {
|
|
195
|
-
return {
|
|
196
|
-
valid: false,
|
|
197
|
-
latencyMs,
|
|
198
|
-
models: [],
|
|
199
|
-
statusCode: response.status,
|
|
200
|
-
error: `Monk API \u54CD\u5E94\u5F02\u5E38 (HTTP ${response.status})`
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
const data = await response.json().catch(() => ({}));
|
|
204
|
-
const models = Array.isArray(data.data) ? data.data.map((m) => m.id) : [];
|
|
205
|
-
return {
|
|
206
|
-
valid: true,
|
|
207
|
-
latencyMs,
|
|
208
|
-
models,
|
|
209
|
-
statusCode: response.status
|
|
210
|
-
};
|
|
211
|
-
} catch (err) {
|
|
212
|
-
const latencyMs = Date.now() - startTime;
|
|
213
|
-
const isAbort = err instanceof Error && err.name === "AbortError";
|
|
214
|
-
return {
|
|
215
|
-
valid: false,
|
|
216
|
-
latencyMs,
|
|
217
|
-
models: [],
|
|
218
|
-
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)}`
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
async function testChatCompletion(apiKey, model = "monk-fast", baseUrl = MONK_BASE_URL) {
|
|
223
|
-
const endpoint = `${baseUrl.replace(/\/+$/, "")}/chat/completions`;
|
|
224
|
-
const startTime = Date.now();
|
|
225
|
-
try {
|
|
226
|
-
const controller = new AbortController();
|
|
227
|
-
const timeoutId = setTimeout(() => controller.abort(), 12e3);
|
|
228
|
-
const response = await fetch(endpoint, {
|
|
229
|
-
method: "POST",
|
|
230
|
-
headers: {
|
|
231
|
-
"Content-Type": "application/json",
|
|
232
|
-
Authorization: `Bearer ${apiKey.trim()}`
|
|
233
|
-
},
|
|
234
|
-
body: JSON.stringify({
|
|
235
|
-
model,
|
|
236
|
-
messages: [{ role: "user", content: "pong" }],
|
|
237
|
-
max_tokens: 10,
|
|
238
|
-
temperature: 0.1
|
|
239
|
-
}),
|
|
240
|
-
signal: controller.signal
|
|
241
|
-
});
|
|
242
|
-
clearTimeout(timeoutId);
|
|
243
|
-
const latencyMs = Date.now() - startTime;
|
|
244
|
-
if (!response.ok) {
|
|
245
|
-
const errJson = await response.json().catch(() => ({}));
|
|
246
|
-
return {
|
|
247
|
-
success: false,
|
|
248
|
-
latencyMs,
|
|
249
|
-
error: errJson.error?.message || `HTTP ${response.status}`
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
const json = await response.json().catch(() => ({}));
|
|
253
|
-
const reply = json.choices?.[0]?.message?.content?.trim() || "";
|
|
254
|
-
return {
|
|
255
|
-
success: true,
|
|
256
|
-
latencyMs,
|
|
257
|
-
reply
|
|
258
|
-
};
|
|
259
|
-
} catch (err) {
|
|
260
|
-
const latencyMs = Date.now() - startTime;
|
|
261
|
-
return {
|
|
262
|
-
success: false,
|
|
263
|
-
latencyMs,
|
|
264
|
-
error: err instanceof Error ? err.message : String(err)
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
// src/ui.ts
|
|
270
|
-
import pc from "picocolors";
|
|
271
|
-
import { password, select, confirm } from "@inquirer/prompts";
|
|
272
|
-
function printBanner() {
|
|
273
|
-
const line = pc.dim("\u2500".repeat(54));
|
|
274
|
-
console.log();
|
|
275
|
-
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")));
|
|
276
|
-
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")));
|
|
277
|
-
console.log(line);
|
|
278
|
-
console.log(
|
|
279
|
-
` ${pc.bold("Monk \xD7 Pi Harness")} ${pc.dim("\xB7")} ${pc.green("OpenAI-Compatible Fusion Agent")}`
|
|
280
|
-
);
|
|
281
|
-
console.log(
|
|
282
|
-
` ${pc.dim("\u6A21\u578B:")} ${pc.yellow("monk-coding")} ${pc.dim("|")} ${pc.cyan("monk-fast")} ${pc.dim("|")} ${pc.magenta("monk")}`
|
|
283
|
-
);
|
|
284
|
-
console.log(line);
|
|
285
|
-
console.log();
|
|
286
|
-
}
|
|
287
|
-
function logSuccess(msg) {
|
|
288
|
-
console.log(` ${pc.green("\u2714")} ${msg}`);
|
|
289
|
-
}
|
|
290
|
-
function logInfo(msg) {
|
|
291
|
-
console.log(` ${pc.cyan("\u2139")} ${msg}`);
|
|
292
|
-
}
|
|
293
|
-
function logWarn(msg) {
|
|
294
|
-
console.log(` ${pc.yellow("\u25B2")} ${msg}`);
|
|
295
|
-
}
|
|
296
|
-
function logError(msg) {
|
|
297
|
-
console.log(` ${pc.red("\u2716")} ${msg}`);
|
|
298
|
-
}
|
|
299
|
-
function logStep(step, total, msg) {
|
|
300
|
-
console.log(` ${pc.dim(`[${step}/${total}]`)} ${pc.bold(msg)}`);
|
|
301
|
-
}
|
|
302
|
-
async function promptForApiKey(currentKey) {
|
|
303
|
-
console.log();
|
|
304
|
-
console.log(` ${pc.bold("\u6B22\u8FCE\u4F7F\u7528 Monk \xD7 Pi \u7F16\u7801\u4F34\u4FA3\uFF01")}`);
|
|
305
|
-
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")}`);
|
|
306
|
-
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)")}`);
|
|
307
|
-
console.log();
|
|
308
|
-
const key = await password({
|
|
309
|
-
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-...):",
|
|
310
|
-
mask: "*",
|
|
311
|
-
validate: (val) => {
|
|
312
|
-
const trimmed = val.trim();
|
|
313
|
-
if (!trimmed && currentKey) return true;
|
|
314
|
-
if (!trimmed) return "API Key \u4E0D\u80FD\u4E3A\u7A7A";
|
|
315
|
-
if (!trimmed.startsWith("sk-")) {
|
|
316
|
-
return "Key \u683C\u5F0F\u901A\u5E38\u4EE5 sk- \u5F00\u5934\uFF0C\u8BF7\u786E\u8BA4\u590D\u5236\u5B8C\u6574";
|
|
317
|
-
}
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
});
|
|
321
|
-
const finalKey = key.trim() || currentKey || "";
|
|
322
|
-
return finalKey;
|
|
323
|
-
}
|
|
324
|
-
async function promptSelectModel(currentModel) {
|
|
325
|
-
const choices = MONK_MODELS.map((m) => ({
|
|
326
|
-
name: `${m.name.padEnd(28)} ${pc.dim(m.description)}`,
|
|
327
|
-
value: m.id,
|
|
328
|
-
description: m.description
|
|
329
|
-
}));
|
|
330
|
-
const selected = await select({
|
|
331
|
-
message: "\u8BF7\u9009\u62E9\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B:",
|
|
332
|
-
choices,
|
|
333
|
-
default: currentModel || "monk-coding"
|
|
334
|
-
});
|
|
335
|
-
return selected;
|
|
336
|
-
}
|
|
337
|
-
async function promptInstallPi() {
|
|
338
|
-
logWarn("\u672A\u68C0\u6D4B\u5230\u5168\u5C40\u5B89\u88C5\u7684 pi \u7F16\u7801\u52A9\u624B (@earendil-works/pi-coding-agent)\u3002");
|
|
339
|
-
console.log(` ${pc.dim("Monk Harness \u4F9D\u8D56 Pi \u4F5C\u4E3A\u5E95\u5C42 TUI/Agent \u8FD0\u884C\u65F6\u3002")}`);
|
|
340
|
-
console.log();
|
|
341
|
-
return await confirm({
|
|
342
|
-
message: "\u662F\u5426\u7ACB\u5373\u4F7F\u7528 npm \u5168\u5C40\u5B89\u88C5 @earendil-works/pi-coding-agent\uFF1F",
|
|
343
|
-
default: true
|
|
344
|
-
});
|
|
345
|
-
}
|
|
346
|
-
function maskKey(key) {
|
|
347
|
-
if (!key || key.length < 10) return "******";
|
|
348
|
-
return `${key.slice(0, 7)}...${key.slice(-4)}`;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// src/pi-runner.ts
|
|
352
|
-
import fs2 from "fs";
|
|
353
|
-
import path2 from "path";
|
|
354
|
-
import { fileURLToPath } from "url";
|
|
355
|
-
import spawn from "cross-spawn";
|
|
356
|
-
import pc2 from "picocolors";
|
|
357
|
-
function resolvePiBinary() {
|
|
358
|
-
try {
|
|
359
|
-
const globalCheck = spawn.sync("pi", ["--version"], {
|
|
360
|
-
encoding: "utf-8",
|
|
361
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
362
|
-
});
|
|
363
|
-
if (globalCheck.status === 0 && globalCheck.stdout) {
|
|
364
|
-
return {
|
|
365
|
-
type: "global",
|
|
366
|
-
command: "pi",
|
|
367
|
-
argsPrefix: [],
|
|
368
|
-
version: globalCheck.stdout.trim(),
|
|
369
|
-
sourceDescription: "\u7CFB\u7EDF\u5168\u5C40\u547D\u4EE4 (PATH)"
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
} catch {
|
|
373
|
-
}
|
|
374
|
-
const candidateBinDirs = [
|
|
375
|
-
path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "../node_modules/.bin/pi"),
|
|
376
|
-
path2.resolve(process.cwd(), "node_modules/.bin/pi")
|
|
377
|
-
];
|
|
378
|
-
for (const binPath of candidateBinDirs) {
|
|
379
|
-
if (fs2.existsSync(binPath)) {
|
|
380
|
-
try {
|
|
381
|
-
const localCheck = spawn.sync(binPath, ["--version"], {
|
|
382
|
-
encoding: "utf-8",
|
|
383
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
384
|
-
});
|
|
385
|
-
if (localCheck.status === 0 && localCheck.stdout) {
|
|
386
|
-
return {
|
|
387
|
-
type: "local",
|
|
388
|
-
command: binPath,
|
|
389
|
-
argsPrefix: [],
|
|
390
|
-
version: localCheck.stdout.trim(),
|
|
391
|
-
sourceDescription: `\u672C\u5730\u4F9D\u8D56 (${path2.basename(path2.dirname(binPath))})`
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
} catch {
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
}
|
|
398
|
-
try {
|
|
399
|
-
const mainEntry = fileURLToPath(import.meta.resolve("@earendil-works/pi-coding-agent"));
|
|
400
|
-
const cliEntry = path2.join(path2.dirname(mainEntry), "bundle", "cli.js");
|
|
401
|
-
if (fs2.existsSync(cliEntry)) {
|
|
402
|
-
const moduleCheck = spawn.sync(process.execPath, [cliEntry, "--version"], {
|
|
403
|
-
encoding: "utf-8",
|
|
404
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
405
|
-
});
|
|
406
|
-
if (moduleCheck.status === 0 && moduleCheck.stdout) {
|
|
407
|
-
return {
|
|
408
|
-
type: "bundled",
|
|
409
|
-
command: process.execPath,
|
|
410
|
-
argsPrefix: [cliEntry],
|
|
411
|
-
version: moduleCheck.stdout.trim(),
|
|
412
|
-
sourceDescription: "Monk-Pi \u5185\u5D4C\u6838\u5FC3 (\u514D\u5B89\u88C5\u8FD0\u884C)"
|
|
413
|
-
};
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
} catch {
|
|
417
|
-
}
|
|
418
|
-
return {
|
|
419
|
-
type: "missing",
|
|
420
|
-
command: "",
|
|
421
|
-
argsPrefix: [],
|
|
422
|
-
sourceDescription: "\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u7684 Pi \u6838\u5FC3"
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
function detectPi() {
|
|
426
|
-
const resolved = resolvePiBinary();
|
|
427
|
-
return {
|
|
428
|
-
installed: resolved.type !== "missing",
|
|
429
|
-
version: resolved.version,
|
|
430
|
-
type: resolved.type,
|
|
431
|
-
description: resolved.sourceDescription
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
function detectPackageManager() {
|
|
435
|
-
try {
|
|
436
|
-
const bunCheck = spawn.sync("bun", ["--version"], { stdio: "ignore" });
|
|
437
|
-
if (bunCheck.status === 0) return "bun";
|
|
438
|
-
} catch {
|
|
439
|
-
}
|
|
440
|
-
try {
|
|
441
|
-
const pnpmCheck = spawn.sync("pnpm", ["--version"], { stdio: "ignore" });
|
|
442
|
-
if (pnpmCheck.status === 0) return "pnpm";
|
|
443
|
-
} catch {
|
|
444
|
-
}
|
|
445
|
-
return "npm";
|
|
446
|
-
}
|
|
447
|
-
async function installPi() {
|
|
448
|
-
const pm = detectPackageManager();
|
|
449
|
-
let cmd = "npm";
|
|
450
|
-
let args = ["install", "-g", "@earendil-works/pi-coding-agent"];
|
|
451
|
-
if (pm === "bun") {
|
|
452
|
-
cmd = "bun";
|
|
453
|
-
args = ["add", "-g", "@earendil-works/pi-coding-agent"];
|
|
454
|
-
} else if (pm === "pnpm") {
|
|
455
|
-
cmd = "pnpm";
|
|
456
|
-
args = ["add", "-g", "@earendil-works/pi-coding-agent"];
|
|
457
|
-
}
|
|
458
|
-
logInfo(`\u68C0\u6D4B\u5230\u5305\u7BA1\u7406\u5668: ${pc2.bold(pm)}\uFF0C\u6B63\u5728\u6267\u884C: ${pc2.yellow(`${cmd} ${args.join(" ")}`)} ...`);
|
|
459
|
-
try {
|
|
460
|
-
const child = spawn.sync(cmd, args, {
|
|
461
|
-
stdio: "inherit"
|
|
462
|
-
});
|
|
463
|
-
if (child.status === 0) {
|
|
464
|
-
logSuccess("Pi \u6838\u5FC3\u5957\u4EF6\u5B89\u88C5\u6210\u529F\uFF01");
|
|
465
|
-
return true;
|
|
466
|
-
}
|
|
467
|
-
logError(`\u5B89\u88C5\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${child.status}`);
|
|
468
|
-
logWarn(`\u82E5\u56E0\u6743\u9650\u95EE\u9898 (EACCES) \u5931\u8D25\uFF0C\u8BF7\u5C1D\u8BD5:`);
|
|
469
|
-
console.log(` ${pc2.cyan(`sudo ${cmd} ${args.join(" ")}`)}`);
|
|
470
|
-
console.log(` \u6216\u76F4\u63A5\u4F7F\u7528\u514D\u5B89\u88C5\u65B9\u6848: ${pc2.cyan("npx monk-pi")}`);
|
|
471
|
-
return false;
|
|
472
|
-
} catch (err) {
|
|
473
|
-
logError(`\u6267\u884C\u5B89\u88C5\u5F02\u5E38: ${err instanceof Error ? err.message : String(err)}`);
|
|
474
|
-
return false;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
function launchPi(options) {
|
|
478
|
-
const resolved = resolvePiBinary();
|
|
479
|
-
if (resolved.type === "missing") {
|
|
480
|
-
logError("\u672A\u627E\u5230\u53EF\u7528\u7684 Pi \u6838\u5FC3\u8FD0\u884C\u73AF\u5883\u3002");
|
|
481
|
-
return 1;
|
|
482
|
-
}
|
|
483
|
-
const { apiKey, defaultModel, passthroughArgs } = options;
|
|
484
|
-
const extraArgs = [];
|
|
485
|
-
const hasProvider = passthroughArgs.includes("--provider");
|
|
486
|
-
const hasModel = passthroughArgs.some((arg, idx) => {
|
|
487
|
-
return arg === "--model" || arg === "-m" || passthroughArgs[idx - 1] === "--model";
|
|
488
|
-
});
|
|
489
|
-
if (!hasProvider && !hasModel) {
|
|
490
|
-
extraArgs.push("--provider", "monk", "--model", defaultModel);
|
|
491
|
-
} else if (!hasProvider && hasModel) {
|
|
492
|
-
extraArgs.push("--provider", "monk");
|
|
493
|
-
}
|
|
494
|
-
const fullArgs = [...resolved.argsPrefix, ...extraArgs, ...passthroughArgs];
|
|
495
|
-
const env = {
|
|
496
|
-
...process.env,
|
|
497
|
-
MONK_API_KEY: apiKey
|
|
498
|
-
};
|
|
499
|
-
const child = spawn(resolved.command, fullArgs, {
|
|
500
|
-
stdio: "inherit",
|
|
501
|
-
env
|
|
502
|
-
});
|
|
503
|
-
const forwardSignal = (signal) => {
|
|
504
|
-
try {
|
|
505
|
-
child.kill(signal);
|
|
506
|
-
} catch {
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
process.on("SIGINT", () => forwardSignal("SIGINT"));
|
|
510
|
-
process.on("SIGTERM", () => forwardSignal("SIGTERM"));
|
|
511
|
-
return new Promise((resolve) => {
|
|
512
|
-
child.on("close", (code) => {
|
|
513
|
-
resolve(code ?? 0);
|
|
514
|
-
});
|
|
515
|
-
child.on("error", (err) => {
|
|
516
|
-
logError(`\u542F\u52A8 Pi \u53D1\u751F\u9519\u8BEF: ${err.message}`);
|
|
517
|
-
resolve(1);
|
|
518
|
-
});
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
// src/commands/doctor.ts
|
|
523
|
-
import fs3 from "fs";
|
|
524
|
-
import os2 from "os";
|
|
525
|
-
import pc3 from "picocolors";
|
|
526
|
-
async function doctorCommand() {
|
|
527
|
-
printBanner();
|
|
528
|
-
console.log(` ${pc3.bold("\u3010Monk \xD7 Pi \u73AF\u5883\u8BCA\u65AD (Doctor)\u3011")}`);
|
|
529
|
-
console.log();
|
|
530
|
-
let hasIssue = false;
|
|
531
|
-
const nodeVersion = process.version;
|
|
532
|
-
const major = parseInt(nodeVersion.slice(1).split(".")[0], 10);
|
|
533
|
-
if (major >= 18) {
|
|
534
|
-
logSuccess(`Node.js \u7248\u672C: ${pc3.bold(nodeVersion)} (\u6EE1\u8DB3 >= 18 \u8981\u6C42)`);
|
|
535
|
-
} else {
|
|
536
|
-
hasIssue = true;
|
|
537
|
-
logError(`Node.js \u7248\u672C: ${pc3.bold(nodeVersion)} (\u8FC7\u4F4E\uFF0C\u8BF7\u5347\u7EA7\u5230 Node 18+)`);
|
|
538
|
-
}
|
|
539
|
-
logInfo(`\u64CD\u4F5C\u7CFB\u7EDF: ${os2.type()} ${os2.release()} (${os2.arch()})`);
|
|
540
|
-
const pi = detectPi();
|
|
541
|
-
if (pi.installed) {
|
|
542
|
-
logSuccess(
|
|
543
|
-
`Pi \u6838\u5FC3\u5957\u4EF6: ${pc3.bold(`\u5DF2\u5C31\u7EEA (v${pi.version})`)} \xB7 ${pc3.dim(`[\u6765\u6E90: ${pi.description}]`)}`
|
|
544
|
-
);
|
|
545
|
-
} else {
|
|
546
|
-
hasIssue = true;
|
|
547
|
-
logError(`Pi \u6838\u5FC3\u5957\u4EF6: ${pc3.bold("\u672A\u627E\u5230\u53EF\u7528\u8FD0\u884C\u65F6")}`);
|
|
548
|
-
console.log(` ${pc3.dim("\u89E3\u51B3\u529E\u6CD5: \u8FD0\u884C npm install -g @earendil-works/pi-coding-agent")}`);
|
|
549
|
-
}
|
|
550
|
-
const { key, source } = resolveApiKey();
|
|
551
|
-
if (key) {
|
|
552
|
-
logSuccess(`Monk API Key: ${pc3.bold(maskKey(key))} (\u6765\u6E90: ${source})`);
|
|
553
|
-
} else {
|
|
554
|
-
hasIssue = true;
|
|
555
|
-
logError(`Monk API Key: \u672A\u914D\u7F6E`);
|
|
556
|
-
console.log(` ${pc3.dim("\u89E3\u51B3\u529E\u6CD5: \u8FD0\u884C monk-pi login")}`);
|
|
557
|
-
}
|
|
558
|
-
const modelsFile = getPiModelsFile();
|
|
559
|
-
if (fs3.existsSync(modelsFile)) {
|
|
560
|
-
try {
|
|
561
|
-
const data = JSON.parse(fs3.readFileSync(modelsFile, "utf-8"));
|
|
562
|
-
const monk = data?.providers?.monk;
|
|
563
|
-
if (monk) {
|
|
564
|
-
const hasCompat = monk.compat?.supportsDeveloperRole === false && monk.compat?.maxTokensField === "max_tokens";
|
|
565
|
-
if (hasCompat) {
|
|
566
|
-
logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: ${pc3.bold("\u5DF2\u914D\u7F6E Monk \u4E13\u5C5E\u4F18\u5316\u517C\u5BB9\u53C2\u6570")}`);
|
|
567
|
-
} else {
|
|
568
|
-
logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5B58\u5728 Monk \u914D\u7F6E\uFF0C\u4F46\u7F3A\u5C11\u6700\u4F73 compat \u53C2\u6570`);
|
|
569
|
-
console.log(` ${pc3.dim("\u6B63\u5728\u4E3A\u60A8\u81EA\u52A8\u7EA0\u6B63...")}`);
|
|
570
|
-
syncPiModelsJson(key);
|
|
571
|
-
logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u5DF2\u81EA\u52A8\u4FEE\u590D\u4F18\u5316`);
|
|
572
|
-
}
|
|
573
|
-
} else {
|
|
574
|
-
logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5C1A\u672A\u6CE8\u5165 Monk \u4F9B\u5E94\u5546`);
|
|
575
|
-
syncPiModelsJson(key);
|
|
576
|
-
logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u5DF2\u6210\u529F\u81EA\u52A8\u6CE8\u5165`);
|
|
577
|
-
}
|
|
578
|
-
} catch {
|
|
579
|
-
logError(`Pi \u914D\u7F6E\u6587\u4EF6: ${modelsFile} \u5B58\u5728\u8BED\u6CD5\u9519\u8BEF`);
|
|
580
|
-
}
|
|
581
|
-
} else {
|
|
582
|
-
logWarn(`Pi \u914D\u7F6E\u6587\u4EF6: \u5C1A\u672A\u521B\u5EFA\uFF0C\u6B63\u5728\u4E3A\u60A8\u81EA\u52A8\u521B\u5EFA...`);
|
|
583
|
-
syncPiModelsJson(key);
|
|
584
|
-
logSuccess(`Pi \u914D\u7F6E\u6587\u4EF6: \u521B\u5EFA\u5B8C\u6210`);
|
|
585
|
-
}
|
|
586
|
-
if (key) {
|
|
587
|
-
process.stdout.write(` ${pc3.dim("\u23F3 \u6B63\u5728\u63A2\u6D4B\u4E0E monk.party \u63A5\u53E3\u7684\u8FDE\u901A\u6027...")} `);
|
|
588
|
-
const val = await validateApiKey(key);
|
|
589
|
-
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
590
|
-
if (val.valid) {
|
|
591
|
-
logSuccess(`Monk \u8FDE\u901A\u6027: ${pc3.green("\u4F18\u79C0")} \xB7 \u5EF6\u8FDF ${val.latencyMs}ms`);
|
|
592
|
-
} else {
|
|
593
|
-
hasIssue = true;
|
|
594
|
-
logError(`Monk \u8FDE\u901A\u6027\u5F02\u5E38: ${val.error}`);
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
console.log();
|
|
598
|
-
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"));
|
|
599
|
-
if (hasIssue) {
|
|
600
|
-
logWarn("\u68C0\u6D4B\u5230\u73AF\u5883\u5B58\u5728\u90E8\u5206\u95EE\u9898\uFF0C\u8BF7\u53C2\u8003\u4E0A\u65B9\u63D0\u793A\u5904\u7406\u3002");
|
|
601
|
-
} else {
|
|
602
|
-
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"));
|
|
603
|
-
}
|
|
604
|
-
console.log();
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
// src/commands/login.ts
|
|
608
|
-
import pc4 from "picocolors";
|
|
609
|
-
async function loginCommand() {
|
|
610
|
-
printBanner();
|
|
611
|
-
const current = resolveApiKey();
|
|
612
|
-
const apiKey = await promptForApiKey(current.key || void 0);
|
|
613
|
-
if (!apiKey) {
|
|
614
|
-
logWarn("\u672A\u8F93\u5165 API Key\uFF0C\u64CD\u4F5C\u5DF2\u53D6\u6D88\u3002");
|
|
615
|
-
return false;
|
|
616
|
-
}
|
|
617
|
-
logInfo("\u6B63\u5728\u8FDE\u63A5 Monk API \u9A8C\u8BC1\u5BC6\u94A5...");
|
|
618
|
-
const result = await validateApiKey(apiKey);
|
|
619
|
-
if (!result.valid) {
|
|
620
|
-
logError(`\u9A8C\u8BC1\u5931\u8D25: ${result.error || "\u672A\u77E5\u9519\u8BEF"}`);
|
|
621
|
-
logWarn("\u8BF7\u6838\u5BF9\u540E\u91CD\u65B0\u8FD0\u884C `monk-pi login`\u3002");
|
|
622
|
-
return false;
|
|
623
|
-
}
|
|
624
|
-
logSuccess(`\u9A8C\u8BC1\u901A\u8FC7\uFF01\u7F51\u7EDC\u5EF6\u8FDF: ${pc4.green(`${result.latencyMs}ms`)}`);
|
|
625
|
-
if (result.models.length > 0) {
|
|
626
|
-
logInfo(`\u53EF\u7528\u6A21\u578B: ${pc4.yellow(result.models.join(", "))}`);
|
|
627
|
-
}
|
|
628
|
-
saveMonkConfig({
|
|
629
|
-
apiKey,
|
|
630
|
-
lastVerified: (/* @__PURE__ */ new Date()).toISOString()
|
|
631
|
-
});
|
|
632
|
-
logSuccess(`\u51ED\u8BC1\u5DF2\u4FDD\u5B58\u81F3\u672C\u5730\u914D\u7F6E`);
|
|
633
|
-
const syncResult = syncPiModelsJson(apiKey);
|
|
634
|
-
if (syncResult.success) {
|
|
635
|
-
logSuccess(`\u5DF2\u6210\u529F\u540C\u6B65\u5E76\u4F18\u5316 Pi \u914D\u7F6E\u6587\u4EF6: ${pc4.dim(syncResult.path)}`);
|
|
636
|
-
} else {
|
|
637
|
-
logWarn(`\u540C\u6B65 Pi \u914D\u7F6E\u6587\u4EF6\u5931\u8D25: ${syncResult.error}`);
|
|
638
|
-
}
|
|
639
|
-
console.log();
|
|
640
|
-
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`);
|
|
641
|
-
console.log();
|
|
642
|
-
return true;
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// src/commands/model.ts
|
|
646
|
-
import pc5 from "picocolors";
|
|
647
|
-
async function modelCommand(targetModel) {
|
|
648
|
-
printBanner();
|
|
649
|
-
const currentModel = getDefaultModel();
|
|
650
|
-
if (targetModel) {
|
|
651
|
-
const matched2 = MONK_MODELS.find(
|
|
652
|
-
(m) => m.id === targetModel || m.id.endsWith(targetModel)
|
|
653
|
-
);
|
|
654
|
-
if (!matched2) {
|
|
655
|
-
logWarn(`\u672A\u77E5\u6A21\u578B: "${targetModel}"`);
|
|
656
|
-
logInfo(`\u652F\u6301\u7684\u6A21\u578B\u5217\u8868: ${MONK_MODELS.map((m) => m.id).join(", ")}`);
|
|
657
|
-
return;
|
|
658
|
-
}
|
|
659
|
-
saveMonkConfig({ defaultModel: matched2.id });
|
|
660
|
-
logSuccess(`\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B\u5DF2\u5207\u6362\u4E3A: ${pc5.bold(pc5.yellow(matched2.name))}`);
|
|
661
|
-
return;
|
|
662
|
-
}
|
|
663
|
-
const selected = await promptSelectModel(currentModel);
|
|
664
|
-
saveMonkConfig({ defaultModel: selected });
|
|
665
|
-
const matched = MONK_MODELS.find((m) => m.id === selected);
|
|
666
|
-
console.log();
|
|
667
|
-
logSuccess(`\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B\u5DF2\u6210\u529F\u8BBE\u5B9A\u4E3A: ${pc5.bold(pc5.yellow(matched?.name || selected))}`);
|
|
668
|
-
console.log();
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
// src/commands/run.ts
|
|
672
|
-
async function runCommand(passthroughArgs) {
|
|
673
|
-
const piCheck = detectPi();
|
|
674
|
-
if (!piCheck.installed) {
|
|
675
|
-
const shouldInstall = await promptInstallPi();
|
|
676
|
-
if (shouldInstall) {
|
|
677
|
-
const installed = await installPi();
|
|
678
|
-
if (!installed) {
|
|
679
|
-
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");
|
|
680
|
-
return 1;
|
|
681
|
-
}
|
|
682
|
-
} else {
|
|
683
|
-
logWarn("\u5DF2\u53D6\u6D88\u8FD0\u884C\u3002Monk Harness \u9700\u8981 Pi \u4F5C\u4E3A\u8FD0\u884C\u5E95\u5EA7\u3002");
|
|
684
|
-
return 1;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
let { key } = resolveApiKey();
|
|
688
|
-
if (!key) {
|
|
689
|
-
logWarn("\u672A\u68C0\u6D4B\u5230 Monk API Key\uFF0C\u6B63\u5728\u4E3A\u60A8\u542F\u52A8\u9996\u6B21\u914D\u7F6E\u5F15\u5BFC...");
|
|
690
|
-
const ok = await loginCommand();
|
|
691
|
-
if (!ok) {
|
|
692
|
-
return 1;
|
|
693
|
-
}
|
|
694
|
-
const resolved = resolveApiKey();
|
|
695
|
-
key = resolved.key;
|
|
696
|
-
}
|
|
697
|
-
if (!key) {
|
|
698
|
-
logError("\u672A\u627E\u5230\u6709\u6548\u7684 Monk API Key\uFF0C\u9000\u51FA\u8FD0\u884C\u3002");
|
|
699
|
-
return 1;
|
|
700
|
-
}
|
|
701
|
-
syncPiModelsJson(key);
|
|
702
|
-
const defaultModel = getDefaultModel();
|
|
703
|
-
return launchPi({
|
|
704
|
-
apiKey: key,
|
|
705
|
-
defaultModel,
|
|
706
|
-
passthroughArgs
|
|
707
|
-
});
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
// src/commands/status.ts
|
|
711
|
-
import pc6 from "picocolors";
|
|
712
|
-
async function statusCommand() {
|
|
713
|
-
printBanner();
|
|
714
|
-
console.log(` ${pc6.bold("\u3010\u670D\u52A1\u4E0E\u73AF\u5883\u72B6\u6001\u68C0\u6D4B\u3011")}`);
|
|
715
|
-
console.log();
|
|
716
|
-
const piDetect = detectPi();
|
|
717
|
-
if (piDetect.installed) {
|
|
718
|
-
logSuccess(
|
|
719
|
-
`Pi \u8FD0\u884C\u73AF\u5883: ${pc6.bold("\u5DF2\u5C31\u7EEA")} (v${piDetect.version}) \xB7 ${pc6.dim(`[\u6765\u6E90: ${piDetect.description}]`)}`
|
|
720
|
-
);
|
|
721
|
-
} else {
|
|
722
|
-
logWarn(`Pi \u8FD0\u884C\u73AF\u5883: ${pc6.red("\u672A\u68C0\u6D4B\u5230\u53EF\u7528\u8FD0\u884C\u65F6")}`);
|
|
723
|
-
console.log(` ${pc6.dim("\u8BF7\u8FD0\u884C npm install -g @earendil-works/pi-coding-agent")}`);
|
|
724
|
-
}
|
|
725
|
-
const { key, source } = resolveApiKey();
|
|
726
|
-
const defaultModel = getDefaultModel();
|
|
727
|
-
if (!key) {
|
|
728
|
-
logError(`Monk API Key: ${pc6.red("\u672A\u914D\u7F6E")}`);
|
|
729
|
-
console.log(` ${pc6.dim("\u8BF7\u8FD0\u884C `monk-pi login` \u8F93\u5165\u60A8\u7684 Key")}`);
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
const sourceLabels = {
|
|
733
|
-
env: "\u73AF\u5883\u53D8\u91CF ($MONK_API_KEY)",
|
|
734
|
-
local: `\u672C\u5730\u914D\u7F6E (${getMonkConfigFile()})`,
|
|
735
|
-
pi: `Pi \u914D\u7F6E\u6587\u4EF6 (${getPiModelsFile()})`,
|
|
736
|
-
none: "\u65E0"
|
|
737
|
-
};
|
|
738
|
-
logSuccess(`Monk API Key: ${pc6.bold(maskKey(key))} ${pc6.dim(`[\u6765\u6E90: ${sourceLabels[source]}]`)}`);
|
|
739
|
-
logInfo(`\u5F53\u524D\u9ED8\u8BA4\u4E3B\u529B\u6A21\u578B: ${pc6.yellow(defaultModel)}`);
|
|
740
|
-
logInfo(`Monk \u57FA\u7840\u5730\u5740: ${pc6.dim(MONK_BASE_URL)}`);
|
|
741
|
-
process.stdout.write(` ${pc6.dim("\u23F3 \u6B63\u5728\u6D4B\u8BD5 Monk API \u8FDE\u63A5\u4E0E\u8BA4\u8BC1...")} `);
|
|
742
|
-
const valResult = await validateApiKey(key);
|
|
743
|
-
if (valResult.valid) {
|
|
744
|
-
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
745
|
-
logSuccess(
|
|
746
|
-
`Monk API \u8FDE\u63A5\u6B63\u5E38 ${pc6.dim("\xB7")} \u8BA4\u8BC1\u6709\u6548 ${pc6.dim("\xB7")} \u5EF6\u8FDF: ${pc6.green(`${valResult.latencyMs}ms`)}`
|
|
747
|
-
);
|
|
748
|
-
if (valResult.models.length > 0) {
|
|
749
|
-
logInfo(`\u652F\u6301\u7684\u6A21\u578B\u7AEF\u70B9: ${pc6.dim(valResult.models.join(" \xB7 "))}`);
|
|
750
|
-
}
|
|
751
|
-
} else {
|
|
752
|
-
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
753
|
-
logError(`Monk API \u9A8C\u8BC1\u5F02\u5E38: ${valResult.error}`);
|
|
754
|
-
return;
|
|
755
|
-
}
|
|
756
|
-
process.stdout.write(` ${pc6.dim(`\u23F3 \u6B63\u5728\u5BF9 ${defaultModel} \u53D1\u8D77\u6781\u7B80\u63E1\u624B\u63A8\u6F14...`)} `);
|
|
757
|
-
const testRes = await testChatCompletion(key, defaultModel);
|
|
758
|
-
if (testRes.success) {
|
|
759
|
-
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
760
|
-
logSuccess(
|
|
761
|
-
`\u63A8\u7406\u901A\u9053\u63E1\u624B\u6210\u529F ${pc6.dim("\xB7")} \u54CD\u5E94\u5EF6\u8FDF: ${pc6.green(`${testRes.latencyMs}ms`)}`
|
|
762
|
-
);
|
|
763
|
-
} else {
|
|
764
|
-
process.stdout.write("\r" + " ".repeat(50) + "\r");
|
|
765
|
-
logWarn(`\u63A8\u7406\u901A\u9053\u63E1\u624B\u8F7B\u5FAE\u544A\u8B66: ${testRes.error || "\u672A\u8FD4\u56DE\u5E38\u89C4\u5185\u5BB9"}`);
|
|
766
|
-
}
|
|
767
|
-
console.log();
|
|
768
|
-
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"));
|
|
769
|
-
console.log(` ${pc6.dim("\u5B98\u65B9\u7F51\u7AD9:")} ${pc6.cyan(MONK_WEBSITE)}`);
|
|
770
|
-
console.log(` ${pc6.dim("\u7528\u91CF\u4E0E\u5230\u671F\u67E5\u8BE2:")} ${pc6.cyan(MONK_ACCOUNT_URL)}`);
|
|
771
|
-
console.log();
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
export {
|
|
775
|
-
MONK_BASE_URL,
|
|
776
|
-
MONK_WEBSITE,
|
|
777
|
-
MONK_ACCOUNT_URL,
|
|
778
|
-
MONK_MODELS,
|
|
779
|
-
DEFAULT_MONK_MODEL,
|
|
780
|
-
getMonkHomeDir,
|
|
781
|
-
getMonkConfigFile,
|
|
782
|
-
getPiHomeDir,
|
|
783
|
-
getPiModelsFile,
|
|
784
|
-
getPiSettingsFile,
|
|
785
|
-
loadMonkConfig,
|
|
786
|
-
saveMonkConfig,
|
|
787
|
-
resolveApiKey,
|
|
788
|
-
syncPiModelsJson,
|
|
789
|
-
getDefaultModel,
|
|
790
|
-
validateApiKey,
|
|
791
|
-
testChatCompletion,
|
|
792
|
-
printBanner,
|
|
793
|
-
logSuccess,
|
|
794
|
-
logInfo,
|
|
795
|
-
logWarn,
|
|
796
|
-
logError,
|
|
797
|
-
logStep,
|
|
798
|
-
promptForApiKey,
|
|
799
|
-
promptSelectModel,
|
|
800
|
-
promptInstallPi,
|
|
801
|
-
maskKey,
|
|
802
|
-
resolvePiBinary,
|
|
803
|
-
detectPi,
|
|
804
|
-
detectPackageManager,
|
|
805
|
-
installPi,
|
|
806
|
-
launchPi,
|
|
807
|
-
doctorCommand,
|
|
808
|
-
loginCommand,
|
|
809
|
-
modelCommand,
|
|
810
|
-
runCommand,
|
|
811
|
-
statusCommand
|
|
812
|
-
};
|