sharkcode 0.3.4 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +178 -71
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -33,6 +33,7 @@ function serializeConfig(mc) {
|
|
|
33
33
|
"",
|
|
34
34
|
"[default]",
|
|
35
35
|
`provider = "${mc.activeProvider}"`,
|
|
36
|
+
`permission_mode = "${mc.permissionMode}"`,
|
|
36
37
|
"",
|
|
37
38
|
"[providers.deepseek]",
|
|
38
39
|
"# API key from https://platform.deepseek.com",
|
|
@@ -53,6 +54,7 @@ function ensureConfig() {
|
|
|
53
54
|
if (!existsSync(CONFIG_FILE)) {
|
|
54
55
|
const initial = {
|
|
55
56
|
activeProvider: "deepseek",
|
|
57
|
+
permissionMode: "prompt",
|
|
56
58
|
providers: {
|
|
57
59
|
deepseek: { key: "", model: PROVIDERS.deepseek.defaultModel },
|
|
58
60
|
ark: { key: "", model: PROVIDERS.ark.defaultModel }
|
|
@@ -75,8 +77,10 @@ function readMultiConfig() {
|
|
|
75
77
|
const deepseekKey = process.env.DEEPSEEK_API_KEY || providersRaw.deepseek?.key || legacy?.key || "";
|
|
76
78
|
const arkKey = process.env.ARK_API_KEY || providersRaw.ark?.key || "";
|
|
77
79
|
const activeProvider = defaultSection.provider || (legacy ? "deepseek" : "deepseek");
|
|
80
|
+
const permissionMode = defaultSection.permission_mode === "full-access" ? "full-access" : "prompt";
|
|
78
81
|
return {
|
|
79
82
|
activeProvider,
|
|
83
|
+
permissionMode,
|
|
80
84
|
providers: {
|
|
81
85
|
deepseek: {
|
|
82
86
|
key: deepseekKey,
|
|
@@ -200,19 +204,57 @@ import { exec } from "child_process";
|
|
|
200
204
|
|
|
201
205
|
// src/permission.ts
|
|
202
206
|
import chalk from "chalk";
|
|
207
|
+
var PURPLE = chalk.hex("#a855f7");
|
|
208
|
+
var GRAY = chalk.gray;
|
|
209
|
+
var GREEN = chalk.green;
|
|
210
|
+
var RED = chalk.red;
|
|
211
|
+
var YELLOW = chalk.yellow;
|
|
212
|
+
var DIM = chalk.dim;
|
|
213
|
+
var _permissionMode = "prompt";
|
|
214
|
+
function setPermissionMode(mode) {
|
|
215
|
+
_permissionMode = mode;
|
|
216
|
+
}
|
|
217
|
+
function getPermissionMode() {
|
|
218
|
+
return _permissionMode;
|
|
219
|
+
}
|
|
203
220
|
async function askPermission(command) {
|
|
221
|
+
if (_permissionMode === "full-access") {
|
|
222
|
+
process.stdout.write(
|
|
223
|
+
PURPLE(" \u25C6 ") + DIM("auto-approved") + GRAY(" \u203A ") + chalk.white(command) + "\n"
|
|
224
|
+
);
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
const width = Math.min(72, process.stdout.columns ?? 80);
|
|
228
|
+
const innerWidth = width - 4;
|
|
229
|
+
const line = (s) => ` ${s}
|
|
230
|
+
`;
|
|
231
|
+
const bar = PURPLE("\u2500".repeat(width));
|
|
232
|
+
const label = YELLOW(" \u26A1 \u6267\u884C\u547D\u4EE4");
|
|
233
|
+
const cmd = chalk.white.bold(command.length > innerWidth ? command.slice(0, innerWidth - 1) + "\u2026" : command);
|
|
234
|
+
process.stderr.write("\n");
|
|
235
|
+
process.stderr.write(bar + "\n");
|
|
236
|
+
process.stderr.write(line(label));
|
|
237
|
+
process.stderr.write(line(" " + cmd));
|
|
238
|
+
process.stderr.write(bar + "\n");
|
|
204
239
|
process.stderr.write(
|
|
205
|
-
|
|
206
|
-
\u26A0\uFE0F Will execute: `) + chalk.white(command) + "\n"
|
|
240
|
+
" " + GREEN("[ y ] \u5141\u8BB8") + " " + RED("[ n ] \u62D2\u7EDD") + " " + DIM("[ a ] \u672C\u6B21\u5168\u90E8\u5141\u8BB8") + "\n\n"
|
|
207
241
|
);
|
|
208
|
-
process.stderr.write(
|
|
242
|
+
process.stderr.write(PURPLE(" \u25C6 ") + GRAY("\u6309\u952E\u51B3\u5B9A \u203A "));
|
|
209
243
|
return new Promise((resolve4) => {
|
|
210
244
|
const onData = (chunk) => {
|
|
211
|
-
const ch = chunk.toString("utf8")[0] ?? "";
|
|
245
|
+
const ch = chunk.toString("utf8")[0]?.toLowerCase() ?? "";
|
|
212
246
|
process.stdin.removeListener("data", onData);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
247
|
+
if (ch === "y") {
|
|
248
|
+
process.stderr.write(GREEN("y \u5141\u8BB8\n\n"));
|
|
249
|
+
resolve4(true);
|
|
250
|
+
} else if (ch === "a") {
|
|
251
|
+
process.stderr.write(YELLOW("a \u5DF2\u5207\u6362\u4E3A Full Access\uFF08\u672C\u6B21\u4F1A\u8BDD\uFF09\n\n"));
|
|
252
|
+
_permissionMode = "full-access";
|
|
253
|
+
resolve4(true);
|
|
254
|
+
} else {
|
|
255
|
+
process.stderr.write(RED("n \u62D2\u7EDD\n\n"));
|
|
256
|
+
resolve4(false);
|
|
257
|
+
}
|
|
216
258
|
};
|
|
217
259
|
process.stdin.once("data", onData);
|
|
218
260
|
});
|
|
@@ -272,8 +314,14 @@ function createProvider(config) {
|
|
|
272
314
|
}
|
|
273
315
|
|
|
274
316
|
// src/agent.ts
|
|
275
|
-
var
|
|
276
|
-
|
|
317
|
+
var PURPLE2 = chalk2.hex("#a855f7");
|
|
318
|
+
var TOOL_LABELS = {
|
|
319
|
+
read_file: { icon: "\u{1F4D6}", verb: "reading file" },
|
|
320
|
+
write_file: { icon: "\u270D\uFE0F ", verb: "writing file" },
|
|
321
|
+
edit_file: { icon: "\u270F\uFE0F ", verb: "editing file" },
|
|
322
|
+
bash: { icon: "\u2699\uFE0F ", verb: "running command" }
|
|
323
|
+
};
|
|
324
|
+
function createSpinner(label) {
|
|
277
325
|
const frames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
278
326
|
let i = 0;
|
|
279
327
|
let timer = null;
|
|
@@ -282,10 +330,13 @@ function createSpinner() {
|
|
|
282
330
|
process.stdout.write("\n");
|
|
283
331
|
timer = setInterval(() => {
|
|
284
332
|
process.stdout.write(
|
|
285
|
-
`\r${
|
|
333
|
+
`\r${PURPLE2(frames[i++ % frames.length])} ${chalk2.gray(label)}`
|
|
286
334
|
);
|
|
287
335
|
}, 80);
|
|
288
336
|
},
|
|
337
|
+
update(newLabel) {
|
|
338
|
+
label = newLabel;
|
|
339
|
+
},
|
|
289
340
|
stop() {
|
|
290
341
|
if (timer) {
|
|
291
342
|
clearInterval(timer);
|
|
@@ -325,36 +376,54 @@ async function runAgent(messages, config) {
|
|
|
325
376
|
stopWhen: stepCountIs(30)
|
|
326
377
|
});
|
|
327
378
|
let currentStep = 0;
|
|
328
|
-
const
|
|
329
|
-
let
|
|
330
|
-
|
|
379
|
+
const thinkingSpinner = createSpinner("thinking...");
|
|
380
|
+
let thinkingDone = false;
|
|
381
|
+
let toolSpinner = null;
|
|
382
|
+
let currentToolName = "";
|
|
383
|
+
let currentToolArgs = null;
|
|
384
|
+
thinkingSpinner.start();
|
|
331
385
|
for await (const event of result.fullStream) {
|
|
332
|
-
if (!
|
|
333
|
-
|
|
334
|
-
|
|
386
|
+
if (!thinkingDone && (event.type === "text-delta" || event.type === "tool-call" || event.type === "error")) {
|
|
387
|
+
thinkingSpinner.stop();
|
|
388
|
+
thinkingDone = true;
|
|
335
389
|
}
|
|
336
390
|
switch (event.type) {
|
|
337
391
|
case "text-delta":
|
|
338
392
|
process.stdout.write(event.text);
|
|
339
393
|
break;
|
|
340
|
-
case "tool-call":
|
|
394
|
+
case "tool-call": {
|
|
395
|
+
const meta = TOOL_LABELS[event.toolName] ?? { icon: "\u{1F527}", verb: "running" };
|
|
396
|
+
currentToolName = event.toolName;
|
|
397
|
+
currentToolArgs = event.input;
|
|
398
|
+
const argHint = getArgHint(event.toolName, event.input);
|
|
399
|
+
const spinLabel = `${meta.verb}${argHint ? ` \u203A ${argHint}` : ""}`;
|
|
341
400
|
process.stdout.write(
|
|
342
|
-
chalk2.cyan(`
|
|
343
|
-
\u{1F527} ${event.toolName}`) + chalk2.gray(`(${formatArgs(event.input)})
|
|
344
|
-
`)
|
|
401
|
+
"\n" + chalk2.cyan(`${meta.icon} ${event.toolName}`) + chalk2.gray(argHint ? ` ${argHint}` : "") + "\n"
|
|
345
402
|
);
|
|
403
|
+
toolSpinner = createSpinner(spinLabel);
|
|
404
|
+
toolSpinner.start();
|
|
346
405
|
break;
|
|
347
|
-
|
|
406
|
+
}
|
|
407
|
+
case "tool-result": {
|
|
408
|
+
if (toolSpinner) {
|
|
409
|
+
toolSpinner.stop();
|
|
410
|
+
toolSpinner = null;
|
|
411
|
+
}
|
|
412
|
+
const meta = TOOL_LABELS[currentToolName] ?? { icon: "\u{1F527}", verb: "done" };
|
|
413
|
+
const summary = truncate(String(event.output), 100);
|
|
348
414
|
process.stdout.write(
|
|
349
|
-
chalk2.green(
|
|
350
|
-
|
|
351
|
-
`)
|
|
415
|
+
chalk2.green(` \u2713 done`) + chalk2.gray(` ${summary}`) + "\n\n"
|
|
352
416
|
);
|
|
353
417
|
break;
|
|
418
|
+
}
|
|
354
419
|
case "tool-error":
|
|
420
|
+
if (toolSpinner) {
|
|
421
|
+
toolSpinner.stop();
|
|
422
|
+
toolSpinner = null;
|
|
423
|
+
}
|
|
355
424
|
process.stderr.write(
|
|
356
425
|
chalk2.red(`
|
|
357
|
-
\
|
|
426
|
+
\u2717 Tool error [${event.toolName}]: ${String(event.error)}
|
|
358
427
|
`)
|
|
359
428
|
);
|
|
360
429
|
break;
|
|
@@ -362,22 +431,25 @@ async function runAgent(messages, config) {
|
|
|
362
431
|
currentStep++;
|
|
363
432
|
break;
|
|
364
433
|
case "error":
|
|
434
|
+
if (toolSpinner) {
|
|
435
|
+
toolSpinner.stop();
|
|
436
|
+
toolSpinner = null;
|
|
437
|
+
}
|
|
438
|
+
thinkingSpinner.stop();
|
|
365
439
|
process.stderr.write(chalk2.red(`
|
|
366
440
|
\u274C Error: ${String(event.error)}
|
|
367
441
|
`));
|
|
368
442
|
break;
|
|
369
443
|
}
|
|
370
444
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
}
|
|
445
|
+
thinkingSpinner.stop();
|
|
446
|
+
if (toolSpinner) toolSpinner.stop();
|
|
374
447
|
process.stdout.write("\n");
|
|
375
448
|
const usage = await result.totalUsage;
|
|
376
449
|
if (usage) {
|
|
377
450
|
process.stderr.write(
|
|
378
451
|
chalk2.gray(
|
|
379
|
-
|
|
380
|
-
\u{1F4CA} Tokens: ${usage.inputTokens} in / ${usage.outputTokens} out | Steps: ${currentStep}
|
|
452
|
+
`\u{1F4CA} ${usage.inputTokens} in / ${usage.outputTokens} out | steps: ${currentStep}
|
|
381
453
|
`
|
|
382
454
|
)
|
|
383
455
|
);
|
|
@@ -389,25 +461,33 @@ async function runAgent(messages, config) {
|
|
|
389
461
|
return messages;
|
|
390
462
|
}
|
|
391
463
|
}
|
|
392
|
-
function
|
|
393
|
-
if (typeof args !== "object" || args === null) return
|
|
464
|
+
function getArgHint(toolName, args) {
|
|
465
|
+
if (typeof args !== "object" || args === null) return "";
|
|
394
466
|
const obj = args;
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
467
|
+
switch (toolName) {
|
|
468
|
+
case "read_file":
|
|
469
|
+
case "write_file":
|
|
470
|
+
case "edit_file":
|
|
471
|
+
return truncate(String(obj.path ?? obj.file_path ?? ""), 50);
|
|
472
|
+
case "bash":
|
|
473
|
+
return truncate(String(obj.command ?? ""), 50);
|
|
474
|
+
default: {
|
|
475
|
+
const first = Object.values(obj).find((v) => typeof v === "string");
|
|
476
|
+
return first ? truncate(first, 50) : "";
|
|
477
|
+
}
|
|
478
|
+
}
|
|
399
479
|
}
|
|
400
480
|
function truncate(str, max) {
|
|
401
|
-
const oneLine = str.replace(/\n/g, "
|
|
481
|
+
const oneLine = str.replace(/\n/g, "\u21B5");
|
|
402
482
|
return oneLine.length > max ? oneLine.slice(0, max) + "\u2026" : oneLine;
|
|
403
483
|
}
|
|
404
484
|
|
|
405
485
|
// src/cli.ts
|
|
406
|
-
var
|
|
407
|
-
var
|
|
408
|
-
var
|
|
409
|
-
var
|
|
410
|
-
var
|
|
486
|
+
var PURPLE3 = chalk3.hex("#a855f7");
|
|
487
|
+
var GRAY2 = chalk3.gray;
|
|
488
|
+
var YELLOW2 = chalk3.yellow;
|
|
489
|
+
var GREEN2 = chalk3.green;
|
|
490
|
+
var RED2 = chalk3.red;
|
|
411
491
|
var CYAN = chalk3.cyan;
|
|
412
492
|
var GLYPHS = {
|
|
413
493
|
S: [[0, 1, 1, 1, 1], [1, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 1], [1, 1, 1, 1, 0]],
|
|
@@ -422,28 +502,33 @@ var GLYPHS = {
|
|
|
422
502
|
};
|
|
423
503
|
function renderWord(word, padLeft = 2) {
|
|
424
504
|
const letters = word.toUpperCase().split("").map((c) => GLYPHS[c]);
|
|
505
|
+
const ON = chalk3.bgHex("#a855f7")(" ");
|
|
506
|
+
const OFF = " ";
|
|
425
507
|
const rows = [];
|
|
426
508
|
for (let row = 0; row < 5; row++) {
|
|
427
509
|
let line = " ".repeat(padLeft);
|
|
428
510
|
for (let i = 0; i < letters.length; i++) {
|
|
429
511
|
const letter = letters[i];
|
|
430
512
|
for (let col = 0; col < letter[row].length; col++) {
|
|
431
|
-
line += letter[row][col] ?
|
|
513
|
+
line += letter[row][col] ? ON : OFF;
|
|
432
514
|
}
|
|
433
|
-
if (i < letters.length - 1) line +=
|
|
515
|
+
if (i < letters.length - 1) line += OFF;
|
|
434
516
|
}
|
|
435
|
-
rows.push(
|
|
517
|
+
rows.push(line);
|
|
436
518
|
}
|
|
437
519
|
return rows;
|
|
438
520
|
}
|
|
439
521
|
var BANNER = ["", ...renderWord("shark", 2), "", ...renderWord("code", 8), ""].join("\n");
|
|
440
522
|
async function showCommandMenu(multiConfig) {
|
|
441
523
|
console.log();
|
|
524
|
+
const permMode = getPermissionMode();
|
|
525
|
+
const permLabel = permMode === "full-access" ? "\u26A1 \u6743\u9650\u6A21\u5F0F\uFF1AFull Access " + chalk3.dim("(\u70B9\u51FB\u5207\u6362\u56DE\u9ED8\u8BA4)") : "\u{1F510} \u6743\u9650\u6A21\u5F0F\uFF1A\u9ED8\u8BA4 " + chalk3.dim("(\u70B9\u51FB\u5F00\u542F Full Access)");
|
|
442
526
|
try {
|
|
443
527
|
const action = await select({
|
|
444
|
-
message:
|
|
528
|
+
message: PURPLE3("\u25C6 \u9009\u62E9\u64CD\u4F5C"),
|
|
445
529
|
choices: [
|
|
446
530
|
{ name: "\u{1F50C} \u5207\u6362 / \u914D\u7F6E Provider", value: "provider" },
|
|
531
|
+
{ name: permLabel, value: "permission" },
|
|
447
532
|
{ name: "\u{1F5D1}\uFE0F \u6E05\u7A7A\u5BF9\u8BDD\u5386\u53F2", value: "clear" },
|
|
448
533
|
{ name: "\u{1F6AA} \u9000\u51FA", value: "exit" }
|
|
449
534
|
]
|
|
@@ -451,35 +536,54 @@ async function showCommandMenu(multiConfig) {
|
|
|
451
536
|
switch (action) {
|
|
452
537
|
case "provider":
|
|
453
538
|
return showSetupFlow(multiConfig);
|
|
539
|
+
case "permission":
|
|
540
|
+
return togglePermissionMode(multiConfig);
|
|
454
541
|
case "clear":
|
|
455
|
-
console.log(
|
|
542
|
+
console.log(GRAY2("\n \u2713 \u5BF9\u8BDD\u5DF2\u6E05\u7A7A\n"));
|
|
456
543
|
return { multiConfig, config: resolveConfig(multiConfig), clearHistory: true };
|
|
457
544
|
case "exit":
|
|
458
|
-
console.log(
|
|
545
|
+
console.log(GRAY2("\nBye! \u{1F988}"));
|
|
459
546
|
return { multiConfig, config: resolveConfig(multiConfig), exit: true };
|
|
460
547
|
}
|
|
461
548
|
} catch {
|
|
462
|
-
console.log(
|
|
549
|
+
console.log(GRAY2("\n \u53D6\u6D88\n"));
|
|
463
550
|
}
|
|
464
551
|
return { multiConfig, config: resolveConfig(multiConfig) };
|
|
465
552
|
}
|
|
553
|
+
async function togglePermissionMode(multiConfig) {
|
|
554
|
+
const current = getPermissionMode();
|
|
555
|
+
const next = current === "full-access" ? "prompt" : "full-access";
|
|
556
|
+
setPermissionMode(next);
|
|
557
|
+
const updated = { ...multiConfig, permissionMode: next };
|
|
558
|
+
saveMultiConfig(updated);
|
|
559
|
+
if (next === "full-access") {
|
|
560
|
+
console.log(
|
|
561
|
+
chalk3.yellow("\n \u26A1 Full Access \u5DF2\u5F00\u542F") + GRAY2(" \u2014 agent \u5C06\u81EA\u52A8\u6279\u51C6\u6240\u6709\u5DE5\u5177\u64CD\u4F5C\n")
|
|
562
|
+
);
|
|
563
|
+
} else {
|
|
564
|
+
console.log(
|
|
565
|
+
chalk3.green("\n \u{1F510} \u5DF2\u6062\u590D\u9ED8\u8BA4\u6743\u9650") + GRAY2(" \u2014 \u6BCF\u6B21\u5DE5\u5177\u8C03\u7528\u524D\u4F1A\u8BE2\u95EE\n")
|
|
566
|
+
);
|
|
567
|
+
}
|
|
568
|
+
return { multiConfig: updated, config: resolveConfig(updated) };
|
|
569
|
+
}
|
|
466
570
|
async function showSetupFlow(multiConfig) {
|
|
467
571
|
console.log();
|
|
468
572
|
try {
|
|
469
573
|
const providerChoices = Object.entries(PROVIDERS).map(([id, meta]) => {
|
|
470
574
|
const hasKey = !!multiConfig.providers[id]?.key;
|
|
471
|
-
const badge = hasKey ?
|
|
575
|
+
const badge = hasKey ? GREEN2("\u2713 \u5DF2\u914D\u7F6E") : YELLOW2("\u2717 \u672A\u914D\u7F6E");
|
|
472
576
|
return { name: `${meta.label} ${badge}`, value: id };
|
|
473
577
|
});
|
|
474
578
|
const selectedProvider = await select({
|
|
475
|
-
message:
|
|
579
|
+
message: PURPLE3("\u25C6 \u9009\u62E9 Provider"),
|
|
476
580
|
choices: providerChoices,
|
|
477
581
|
default: multiConfig.activeProvider
|
|
478
582
|
});
|
|
479
583
|
const currentKey = multiConfig.providers[selectedProvider]?.key ?? "";
|
|
480
|
-
const hint = currentKey ?
|
|
584
|
+
const hint = currentKey ? GRAY2("(\u56DE\u8F66\u4FDD\u7559 " + currentKey.slice(0, 6) + "\u2022\u2022\u2022)") : GRAY2("(\u5FC5\u586B)");
|
|
481
585
|
const rawKey = await input({
|
|
482
|
-
message:
|
|
586
|
+
message: PURPLE3("\u25C6 API Key ") + hint,
|
|
483
587
|
default: currentKey || void 0
|
|
484
588
|
});
|
|
485
589
|
const newKey = rawKey.trim() || currentKey;
|
|
@@ -500,14 +604,14 @@ async function showSetupFlow(multiConfig) {
|
|
|
500
604
|
saveMultiConfig(updated);
|
|
501
605
|
const newConfig = resolveConfig(updated);
|
|
502
606
|
const keyMsg = newKey && newKey !== currentKey ? "\uFF0CAPI Key \u5DF2\u4FDD\u5B58" : "";
|
|
503
|
-
console.log(
|
|
607
|
+
console.log(GREEN2(`
|
|
504
608
|
\u2713 \u5DF2\u5207\u6362\u5230 ${PROVIDERS[selectedProvider].label}${keyMsg}`) + "\n");
|
|
505
609
|
if (!newConfig.apiKey) {
|
|
506
|
-
console.log(
|
|
610
|
+
console.log(YELLOW2(" \u26A0 \u8FD8\u672A\u586B\u5199 API Key\uFF0C\u65E0\u6CD5\u53D1\u9001\u6D88\u606F\n"));
|
|
507
611
|
}
|
|
508
612
|
return { multiConfig: updated, config: newConfig };
|
|
509
613
|
} catch {
|
|
510
|
-
console.log(
|
|
614
|
+
console.log(GRAY2("\n \u53D6\u6D88\n"));
|
|
511
615
|
return { multiConfig, config: resolveConfig(multiConfig) };
|
|
512
616
|
}
|
|
513
617
|
}
|
|
@@ -574,31 +678,33 @@ async function readLineRaw(promptStr) {
|
|
|
574
678
|
}
|
|
575
679
|
function statusLine(config) {
|
|
576
680
|
const label = PROVIDERS[config.providerName]?.label ?? config.providerName;
|
|
577
|
-
|
|
681
|
+
const permMode = getPermissionMode();
|
|
682
|
+
const permBadge = permMode === "full-access" ? chalk3.yellow(" \u26A1 Full Access") : GRAY2(" \u{1F510} \u9ED8\u8BA4\u6743\u9650");
|
|
683
|
+
return PURPLE3(" \u25C6") + GRAY2(` ${label}`) + CYAN(` [${config.model}]`) + permBadge + GRAY2(" \u8F93\u5165 / \u8C03\u51FA\u6307\u4EE4\u83DC\u5355\n");
|
|
578
684
|
}
|
|
579
685
|
async function main() {
|
|
580
686
|
const args = process.argv.slice(2);
|
|
581
687
|
if (args[0] === "--help" || args[0] === "-h") {
|
|
582
688
|
console.log(BANNER);
|
|
583
|
-
console.log(
|
|
584
|
-
console.log(" " +
|
|
585
|
-
console.log(" " +
|
|
586
|
-
console.log(
|
|
689
|
+
console.log(PURPLE3(" Usage:"));
|
|
690
|
+
console.log(" " + PURPLE3("sharkcode") + GRAY2(" \u2014 \u4EA4\u4E92\u6A21\u5F0F\uFF08\u76F4\u63A5\u542F\u52A8\uFF09"));
|
|
691
|
+
console.log(" " + PURPLE3("sharkcode") + YELLOW2(' "prompt"') + GRAY2(" \u2014 \u5355\u6B21\u6267\u884C"));
|
|
692
|
+
console.log(GRAY2("\n \u4EA4\u4E92\u6A21\u5F0F\u5185\u8F93\u5165 / \u8C03\u51FA\u6307\u4EE4\u83DC\u5355\n"));
|
|
587
693
|
return;
|
|
588
694
|
}
|
|
589
695
|
if (args[0] === "--version" || args[0] === "-v") {
|
|
590
|
-
console.log("sharkcode v0.3.
|
|
696
|
+
console.log("sharkcode v0.3.6");
|
|
591
697
|
return;
|
|
592
698
|
}
|
|
593
699
|
if (args.length > 0) {
|
|
594
700
|
const mc = readMultiConfig();
|
|
595
701
|
const config2 = resolveConfig(mc);
|
|
596
702
|
if (!config2.apiKey) {
|
|
597
|
-
console.error(
|
|
703
|
+
console.error(RED2("\u274C \u672A\u914D\u7F6E API Key\u3002\u8BF7\u5148\u8FD0\u884C sharkcode \u5E76\u8F93\u5165 / \u914D\u7F6E Provider\u3002"));
|
|
598
704
|
process.exit(1);
|
|
599
705
|
}
|
|
600
706
|
console.log(
|
|
601
|
-
|
|
707
|
+
PURPLE3("\n\u{1F988} SharkCode") + GRAY2(` | ${PROVIDERS[config2.providerName]?.label ?? config2.providerName} | ${config2.model}
|
|
602
708
|
`)
|
|
603
709
|
);
|
|
604
710
|
await runAgent([{ role: "user", content: args.join(" ") }], config2);
|
|
@@ -607,6 +713,7 @@ async function main() {
|
|
|
607
713
|
console.log(BANNER);
|
|
608
714
|
let multiConfig = readMultiConfig();
|
|
609
715
|
let config = resolveConfig(multiConfig);
|
|
716
|
+
setPermissionMode(multiConfig.permissionMode ?? "prompt");
|
|
610
717
|
try {
|
|
611
718
|
process.stdin.setRawMode(true);
|
|
612
719
|
process.stdin.resume();
|
|
@@ -615,20 +722,20 @@ async function main() {
|
|
|
615
722
|
console.log(statusLine(config));
|
|
616
723
|
if (!config.apiKey) {
|
|
617
724
|
console.log(
|
|
618
|
-
|
|
725
|
+
YELLOW2(" \u26A0 \u5C1A\u672A\u914D\u7F6E API Key\u3002") + GRAY2("\u8F93\u5165 / \u7136\u540E\u9009\u62E9\u300C\u5207\u6362 / \u914D\u7F6E Provider\u300D\n")
|
|
619
726
|
);
|
|
620
727
|
}
|
|
621
728
|
let messages = [];
|
|
622
729
|
while (true) {
|
|
623
|
-
const raw = await readLineRaw(
|
|
730
|
+
const raw = await readLineRaw(PURPLE3("\n\u25C6 "));
|
|
624
731
|
if (raw === null) {
|
|
625
|
-
console.log(
|
|
732
|
+
console.log(GRAY2("\nBye! \u{1F988}"));
|
|
626
733
|
break;
|
|
627
734
|
}
|
|
628
735
|
const trimmed = raw.trim();
|
|
629
736
|
if (!trimmed) continue;
|
|
630
737
|
if (trimmed === "exit" || trimmed === "quit") {
|
|
631
|
-
console.log(
|
|
738
|
+
console.log(GRAY2("Bye! \u{1F988}"));
|
|
632
739
|
break;
|
|
633
740
|
}
|
|
634
741
|
if (trimmed === "/") {
|
|
@@ -659,11 +766,11 @@ async function main() {
|
|
|
659
766
|
continue;
|
|
660
767
|
}
|
|
661
768
|
if (trimmed.startsWith("/")) {
|
|
662
|
-
console.log(
|
|
769
|
+
console.log(GRAY2(" \u672A\u77E5\u547D\u4EE4\u3002\u8F93\u5165 / \u8C03\u51FA\u6307\u4EE4\u83DC\u5355\n"));
|
|
663
770
|
continue;
|
|
664
771
|
}
|
|
665
772
|
if (!config.apiKey) {
|
|
666
|
-
console.log(
|
|
773
|
+
console.log(YELLOW2(" \u26A0 \u8FD8\u672A\u586B\u5199 API Key\u3002\u8F93\u5165 / \u2192 \u5207\u6362 / \u914D\u7F6E Provider\n"));
|
|
667
774
|
continue;
|
|
668
775
|
}
|
|
669
776
|
messages.push({ role: "user", content: trimmed });
|
|
@@ -675,7 +782,7 @@ async function main() {
|
|
|
675
782
|
} catch {
|
|
676
783
|
}
|
|
677
784
|
} catch (err) {
|
|
678
|
-
console.error(
|
|
785
|
+
console.error(RED2(`
|
|
679
786
|
\u274C ${String(err)}
|
|
680
787
|
`));
|
|
681
788
|
messages.pop();
|