deeper-cli 1.0.6 → 1.2.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/dist/cli/index.js +581 -156
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/chat-repl.ts +1251 -961
- package/src/model/DeepSeekClient.ts +35 -37
- package/src/model/RetryManager.ts +54 -7
- package/src/model/StreamHandler.ts +111 -17
- package/src/model/types.ts +25 -6
package/dist/cli/index.js
CHANGED
|
@@ -3285,7 +3285,7 @@ var init_RetryManager = __esm({
|
|
|
3285
3285
|
this.baseDelayMs = baseDelayMs;
|
|
3286
3286
|
this.maxDelayMs = maxDelayMs;
|
|
3287
3287
|
}
|
|
3288
|
-
async execute(fn, shouldRetry) {
|
|
3288
|
+
async execute(fn, shouldRetry, options) {
|
|
3289
3289
|
let lastError;
|
|
3290
3290
|
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
|
|
3291
3291
|
try {
|
|
@@ -3298,27 +3298,34 @@ var init_RetryManager = __esm({
|
|
|
3298
3298
|
if (shouldRetry && !shouldRetry(lastError, attempt)) {
|
|
3299
3299
|
break;
|
|
3300
3300
|
}
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
);
|
|
3301
|
+
if (!shouldRetry && this.isDefaultNonRetryable(lastError)) {
|
|
3302
|
+
break;
|
|
3303
|
+
}
|
|
3304
|
+
const delay = this.calculateDelay(attempt);
|
|
3305
|
+
if (options?.onRetry) {
|
|
3306
|
+
options.onRetry(lastError, attempt, delay);
|
|
3307
|
+
}
|
|
3305
3308
|
await this.sleep(delay);
|
|
3306
3309
|
}
|
|
3307
3310
|
}
|
|
3308
3311
|
throw lastError ?? new Error("Max retries exceeded");
|
|
3309
3312
|
}
|
|
3310
3313
|
withTimeout(fn, timeoutMs, signal) {
|
|
3314
|
+
const controller = new AbortController();
|
|
3311
3315
|
return new Promise((resolve48, reject) => {
|
|
3312
3316
|
const timer = setTimeout(() => {
|
|
3317
|
+
controller.abort();
|
|
3313
3318
|
reject(new Error(`Request timed out after ${timeoutMs}ms`));
|
|
3314
3319
|
}, timeoutMs);
|
|
3315
3320
|
const onAbort = () => {
|
|
3316
3321
|
clearTimeout(timer);
|
|
3322
|
+
controller.abort();
|
|
3317
3323
|
reject(new Error("Request was aborted"));
|
|
3318
3324
|
};
|
|
3319
3325
|
if (signal) {
|
|
3320
3326
|
if (signal.aborted) {
|
|
3321
3327
|
clearTimeout(timer);
|
|
3328
|
+
controller.abort();
|
|
3322
3329
|
reject(new Error("Request was aborted"));
|
|
3323
3330
|
return;
|
|
3324
3331
|
}
|
|
@@ -3339,8 +3346,35 @@ var init_RetryManager = __esm({
|
|
|
3339
3346
|
});
|
|
3340
3347
|
});
|
|
3341
3348
|
}
|
|
3342
|
-
|
|
3343
|
-
|
|
3349
|
+
calculateDelay(attempt) {
|
|
3350
|
+
const exponentialDelay = this.baseDelayMs * Math.pow(2, attempt);
|
|
3351
|
+
const jitter = Math.random() * exponentialDelay;
|
|
3352
|
+
return Math.min(exponentialDelay + jitter, this.maxDelayMs);
|
|
3353
|
+
}
|
|
3354
|
+
isDefaultNonRetryable(error) {
|
|
3355
|
+
const msg = error.message.toLowerCase();
|
|
3356
|
+
if (msg.includes("400") && !msg.includes("429")) return true;
|
|
3357
|
+
if (msg.includes("401") || msg.includes("unauthorized")) return true;
|
|
3358
|
+
if (msg.includes("403") || msg.includes("forbidden")) return true;
|
|
3359
|
+
if (msg.includes("404") || msg.includes("not found")) return true;
|
|
3360
|
+
return false;
|
|
3361
|
+
}
|
|
3362
|
+
sleep(ms, signal) {
|
|
3363
|
+
return new Promise((resolve48, reject) => {
|
|
3364
|
+
const timer = setTimeout(resolve48, ms);
|
|
3365
|
+
if (signal) {
|
|
3366
|
+
const onAbort = () => {
|
|
3367
|
+
clearTimeout(timer);
|
|
3368
|
+
reject(new Error("Retry sleep was aborted"));
|
|
3369
|
+
};
|
|
3370
|
+
if (signal.aborted) {
|
|
3371
|
+
clearTimeout(timer);
|
|
3372
|
+
reject(new Error("Retry sleep was aborted"));
|
|
3373
|
+
return;
|
|
3374
|
+
}
|
|
3375
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3376
|
+
}
|
|
3377
|
+
});
|
|
3344
3378
|
}
|
|
3345
3379
|
};
|
|
3346
3380
|
}
|
|
@@ -3356,21 +3390,31 @@ var init_StreamHandler = __esm({
|
|
|
3356
3390
|
thinkingBuffer;
|
|
3357
3391
|
toolCallBuffer;
|
|
3358
3392
|
finished;
|
|
3393
|
+
lastYieldedIndex;
|
|
3359
3394
|
constructor() {
|
|
3360
3395
|
this.textBuffer = "";
|
|
3361
3396
|
this.thinkingBuffer = "";
|
|
3362
3397
|
this.toolCallBuffer = /* @__PURE__ */ new Map();
|
|
3363
3398
|
this.finished = false;
|
|
3399
|
+
this.lastYieldedIndex = -1;
|
|
3364
3400
|
}
|
|
3365
3401
|
reset() {
|
|
3366
3402
|
this.textBuffer = "";
|
|
3367
3403
|
this.thinkingBuffer = "";
|
|
3368
3404
|
this.toolCallBuffer.clear();
|
|
3369
3405
|
this.finished = false;
|
|
3406
|
+
this.lastYieldedIndex = -1;
|
|
3370
3407
|
}
|
|
3371
3408
|
handleEvent(event, data) {
|
|
3409
|
+
if (event === "error") {
|
|
3410
|
+
return { type: "error", error: data || "SSE error event" };
|
|
3411
|
+
}
|
|
3372
3412
|
if (event === "[DONE]" || data === "[DONE]") {
|
|
3413
|
+
const results = this.finalizePendingToolCalls();
|
|
3373
3414
|
this.finished = true;
|
|
3415
|
+
if (results.length > 0) {
|
|
3416
|
+
return [...results, { type: "done" }];
|
|
3417
|
+
}
|
|
3374
3418
|
return { type: "done" };
|
|
3375
3419
|
}
|
|
3376
3420
|
if (!data) {
|
|
@@ -3385,11 +3429,23 @@ var init_StreamHandler = __esm({
|
|
|
3385
3429
|
const choice = choices[0];
|
|
3386
3430
|
const delta = choice.delta;
|
|
3387
3431
|
if (!delta) {
|
|
3432
|
+
const finishReason2 = choice.finish_reason;
|
|
3433
|
+
if (finishReason2 === "stop" || finishReason2 === "length" || finishReason2 === "tool_calls") {
|
|
3434
|
+
const results = this.finalizePendingToolCalls();
|
|
3435
|
+
this.finished = true;
|
|
3436
|
+
if (results.length > 0) {
|
|
3437
|
+
return [...results, { type: "done" }];
|
|
3438
|
+
}
|
|
3439
|
+
return { type: "done" };
|
|
3440
|
+
}
|
|
3388
3441
|
return null;
|
|
3389
3442
|
}
|
|
3390
3443
|
if (delta.reasoning_content) {
|
|
3391
3444
|
const thinkingChunk = delta.reasoning_content;
|
|
3392
3445
|
this.thinkingBuffer += thinkingChunk;
|
|
3446
|
+
if (this.thinkingBuffer.length > 1e5) {
|
|
3447
|
+
this.thinkingBuffer = this.thinkingBuffer.slice(-8e4);
|
|
3448
|
+
}
|
|
3393
3449
|
return {
|
|
3394
3450
|
type: "thinking",
|
|
3395
3451
|
content: thinkingChunk
|
|
@@ -3401,6 +3457,9 @@ var init_StreamHandler = __esm({
|
|
|
3401
3457
|
if (delta.content) {
|
|
3402
3458
|
const textChunk = delta.content;
|
|
3403
3459
|
this.textBuffer += textChunk;
|
|
3460
|
+
if (this.textBuffer.length > 5e5) {
|
|
3461
|
+
this.textBuffer = this.textBuffer.slice(-4e5);
|
|
3462
|
+
}
|
|
3404
3463
|
return {
|
|
3405
3464
|
type: "text",
|
|
3406
3465
|
content: textChunk
|
|
@@ -3408,7 +3467,11 @@ var init_StreamHandler = __esm({
|
|
|
3408
3467
|
}
|
|
3409
3468
|
const finishReason = choice.finish_reason;
|
|
3410
3469
|
if (finishReason === "stop" || finishReason === "length" || finishReason === "tool_calls") {
|
|
3470
|
+
const results = this.finalizePendingToolCalls();
|
|
3411
3471
|
this.finished = true;
|
|
3472
|
+
if (results.length > 0) {
|
|
3473
|
+
return [...results, { type: "done" }];
|
|
3474
|
+
}
|
|
3412
3475
|
return { type: "done" };
|
|
3413
3476
|
}
|
|
3414
3477
|
} catch {
|
|
@@ -3427,10 +3490,16 @@ var init_StreamHandler = __esm({
|
|
|
3427
3490
|
}
|
|
3428
3491
|
getToolCalls() {
|
|
3429
3492
|
const result = [];
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3493
|
+
const indices = [...this.toolCallBuffer.keys()].sort((a, b2) => a - b2);
|
|
3494
|
+
for (const idx of indices) {
|
|
3495
|
+
const pending = this.toolCallBuffer.get(idx);
|
|
3496
|
+
if (pending) {
|
|
3497
|
+
result.push({
|
|
3498
|
+
id: pending.id,
|
|
3499
|
+
name: pending.name,
|
|
3500
|
+
arguments: this.parseArgsStr(pending.argsStr),
|
|
3501
|
+
index: pending.index
|
|
3502
|
+
});
|
|
3434
3503
|
}
|
|
3435
3504
|
}
|
|
3436
3505
|
return result;
|
|
@@ -3448,8 +3517,9 @@ var init_StreamHandler = __esm({
|
|
|
3448
3517
|
this.toolCallBuffer.set(index, {
|
|
3449
3518
|
id: id ?? "",
|
|
3450
3519
|
name: fn?.name ?? "",
|
|
3451
|
-
|
|
3452
|
-
index
|
|
3520
|
+
argsStr: "",
|
|
3521
|
+
index,
|
|
3522
|
+
started: false
|
|
3453
3523
|
});
|
|
3454
3524
|
}
|
|
3455
3525
|
const existing = this.toolCallBuffer.get(index);
|
|
@@ -3460,24 +3530,71 @@ var init_StreamHandler = __esm({
|
|
|
3460
3530
|
existing.name = fn.name;
|
|
3461
3531
|
}
|
|
3462
3532
|
if (fn?.arguments) {
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3533
|
+
existing.argsStr += fn.arguments;
|
|
3534
|
+
}
|
|
3535
|
+
if (!existing.started) {
|
|
3536
|
+
existing.started = true;
|
|
3537
|
+
if (this.lastYieldedIndex >= 0) {
|
|
3538
|
+
const prev = this.toolCallBuffer.get(this.lastYieldedIndex);
|
|
3539
|
+
if (prev && prev !== existing) {
|
|
3540
|
+
results.push({
|
|
3541
|
+
type: "tool_call_end",
|
|
3542
|
+
tool_call: {
|
|
3543
|
+
id: prev.id,
|
|
3544
|
+
name: prev.name,
|
|
3545
|
+
arguments: this.parseArgsStr(prev.argsStr),
|
|
3546
|
+
index: prev.index
|
|
3547
|
+
}
|
|
3548
|
+
});
|
|
3549
|
+
}
|
|
3469
3550
|
}
|
|
3551
|
+
this.lastYieldedIndex = index;
|
|
3552
|
+
results.push({
|
|
3553
|
+
type: "tool_call_start",
|
|
3554
|
+
tool_call: { id: existing.id, name: existing.name, index: existing.index }
|
|
3555
|
+
});
|
|
3470
3556
|
}
|
|
3471
|
-
|
|
3472
|
-
|
|
3557
|
+
}
|
|
3558
|
+
return results;
|
|
3559
|
+
}
|
|
3560
|
+
finalizePendingToolCalls() {
|
|
3561
|
+
const results = [];
|
|
3562
|
+
if (this.lastYieldedIndex >= 0) {
|
|
3563
|
+
const last = this.toolCallBuffer.get(this.lastYieldedIndex);
|
|
3564
|
+
if (last) {
|
|
3473
3565
|
results.push({
|
|
3474
|
-
type: "
|
|
3475
|
-
tool_call: {
|
|
3566
|
+
type: "tool_call_end",
|
|
3567
|
+
tool_call: {
|
|
3568
|
+
id: last.id,
|
|
3569
|
+
name: last.name,
|
|
3570
|
+
arguments: this.parseArgsStr(last.argsStr),
|
|
3571
|
+
index: last.index
|
|
3572
|
+
}
|
|
3476
3573
|
});
|
|
3477
3574
|
}
|
|
3575
|
+
this.lastYieldedIndex = -1;
|
|
3478
3576
|
}
|
|
3479
3577
|
return results;
|
|
3480
3578
|
}
|
|
3579
|
+
parseArgsStr(argsStr) {
|
|
3580
|
+
if (!argsStr) return {};
|
|
3581
|
+
try {
|
|
3582
|
+
return JSON.parse(argsStr);
|
|
3583
|
+
} catch {
|
|
3584
|
+
const trimmed = argsStr.trim();
|
|
3585
|
+
if (trimmed.startsWith("{") && !trimmed.endsWith("}")) {
|
|
3586
|
+
try {
|
|
3587
|
+
return JSON.parse(trimmed + "}");
|
|
3588
|
+
} catch {
|
|
3589
|
+
try {
|
|
3590
|
+
return JSON.parse(trimmed + "}}");
|
|
3591
|
+
} catch {
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
return {};
|
|
3596
|
+
}
|
|
3597
|
+
}
|
|
3481
3598
|
};
|
|
3482
3599
|
}
|
|
3483
3600
|
});
|
|
@@ -3582,7 +3699,7 @@ ${data.stack ?? ""}`;
|
|
|
3582
3699
|
});
|
|
3583
3700
|
|
|
3584
3701
|
// src/model/DeepSeekClient.ts
|
|
3585
|
-
var DEFAULT_TIMEOUT_MS, MAX_RETRIES, DeepSeekClient;
|
|
3702
|
+
var DEFAULT_TIMEOUT_MS, MAX_RETRIES, isRetryable, DeepSeekClient;
|
|
3586
3703
|
var init_DeepSeekClient = __esm({
|
|
3587
3704
|
"src/model/DeepSeekClient.ts"() {
|
|
3588
3705
|
"use strict";
|
|
@@ -3591,23 +3708,31 @@ var init_DeepSeekClient = __esm({
|
|
|
3591
3708
|
init_logger();
|
|
3592
3709
|
DEFAULT_TIMEOUT_MS = 12e4;
|
|
3593
3710
|
MAX_RETRIES = 3;
|
|
3711
|
+
isRetryable = (error, _attempt) => {
|
|
3712
|
+
const msg = error.message.toLowerCase();
|
|
3713
|
+
if (msg.includes("429") || msg.includes("rate limit")) return true;
|
|
3714
|
+
if (msg.includes("500") || msg.includes("502") || msg.includes("503") || msg.includes("504")) return true;
|
|
3715
|
+
if (msg.includes("timeout") || msg.includes("abort")) return _attempt < 2;
|
|
3716
|
+
if (msg.includes("econnreset") || msg.includes("econnrefused")) return true;
|
|
3717
|
+
return false;
|
|
3718
|
+
};
|
|
3594
3719
|
DeepSeekClient = class {
|
|
3595
3720
|
config;
|
|
3596
3721
|
retryManager;
|
|
3597
3722
|
constructor(config) {
|
|
3598
3723
|
this.config = config;
|
|
3599
|
-
this.retryManager = new RetryManager(
|
|
3724
|
+
this.retryManager = new RetryManager(MAX_RETRIES);
|
|
3600
3725
|
}
|
|
3601
3726
|
async chat(messages, tools, overrides) {
|
|
3602
3727
|
const cfg = this.mergeConfig(overrides);
|
|
3603
3728
|
const body = this.buildRequestBody(messages, tools, cfg, false);
|
|
3604
3729
|
const response = await this.retryManager.execute(async () => {
|
|
3605
|
-
|
|
3730
|
+
return this.retryManager.withTimeout(
|
|
3606
3731
|
() => this.makeRequest(cfg, body),
|
|
3607
|
-
|
|
3732
|
+
DEFAULT_TIMEOUT_MS,
|
|
3733
|
+
cfg.signal
|
|
3608
3734
|
);
|
|
3609
|
-
|
|
3610
|
-
}, this.shouldRetry);
|
|
3735
|
+
}, isRetryable);
|
|
3611
3736
|
const data = await response.json();
|
|
3612
3737
|
if (!data.choices || data.choices.length === 0) {
|
|
3613
3738
|
throw new Error("No choices returned from API");
|
|
@@ -3626,7 +3751,7 @@ var init_DeepSeekClient = __esm({
|
|
|
3626
3751
|
}));
|
|
3627
3752
|
}
|
|
3628
3753
|
if (message.reasoning_content) {
|
|
3629
|
-
result.
|
|
3754
|
+
result.reasoning_content = message.reasoning_content;
|
|
3630
3755
|
}
|
|
3631
3756
|
return result;
|
|
3632
3757
|
}
|
|
@@ -3634,16 +3759,12 @@ var init_DeepSeekClient = __esm({
|
|
|
3634
3759
|
const cfg = this.mergeConfig(overrides);
|
|
3635
3760
|
const body = this.buildRequestBody(messages, tools, cfg, true);
|
|
3636
3761
|
const response = await this.retryManager.execute(async () => {
|
|
3637
|
-
|
|
3762
|
+
return this.retryManager.withTimeout(
|
|
3638
3763
|
() => this.makeRequest(cfg, body),
|
|
3639
|
-
DEFAULT_TIMEOUT_MS
|
|
3764
|
+
DEFAULT_TIMEOUT_MS,
|
|
3765
|
+
cfg.signal
|
|
3640
3766
|
);
|
|
3641
|
-
|
|
3642
|
-
}, this.shouldRetry);
|
|
3643
|
-
if (!response.ok) {
|
|
3644
|
-
const errorBody = await response.text().catch(() => "");
|
|
3645
|
-
throw new Error(`API request failed: ${response.status} ${response.statusText} - ${errorBody}`);
|
|
3646
|
-
}
|
|
3767
|
+
}, isRetryable);
|
|
3647
3768
|
if (!response.body) {
|
|
3648
3769
|
throw new Error("Response body is empty");
|
|
3649
3770
|
}
|
|
@@ -3725,6 +3846,12 @@ var init_DeepSeekClient = __esm({
|
|
|
3725
3846
|
max_tokens: config.maxTokens,
|
|
3726
3847
|
stream
|
|
3727
3848
|
};
|
|
3849
|
+
if (config.think?.enabled) {
|
|
3850
|
+
body.thinking = {
|
|
3851
|
+
type: "enabled",
|
|
3852
|
+
budget_tokens: config.think.budgetTokens
|
|
3853
|
+
};
|
|
3854
|
+
}
|
|
3728
3855
|
if (tools && tools.length > 0) {
|
|
3729
3856
|
body.tools = tools.map((tool) => ({
|
|
3730
3857
|
type: "function",
|
|
@@ -3741,7 +3868,7 @@ var init_DeepSeekClient = __esm({
|
|
|
3741
3868
|
async makeRequest(config, body) {
|
|
3742
3869
|
const url = `${config.baseUrl}/v1/chat/completions`;
|
|
3743
3870
|
logger.debug("DeepSeek API request", { url, model: config.model });
|
|
3744
|
-
const
|
|
3871
|
+
const fetchOpts = {
|
|
3745
3872
|
method: "POST",
|
|
3746
3873
|
headers: {
|
|
3747
3874
|
"Content-Type": "application/json",
|
|
@@ -3749,7 +3876,11 @@ var init_DeepSeekClient = __esm({
|
|
|
3749
3876
|
"Accept": "application/json"
|
|
3750
3877
|
},
|
|
3751
3878
|
body
|
|
3752
|
-
}
|
|
3879
|
+
};
|
|
3880
|
+
if (config.signal) {
|
|
3881
|
+
fetchOpts.signal = config.signal;
|
|
3882
|
+
}
|
|
3883
|
+
const response = await fetch(url, fetchOpts);
|
|
3753
3884
|
if (!response.ok) {
|
|
3754
3885
|
const errorBody = await response.text().catch(() => "");
|
|
3755
3886
|
logger.error("DeepSeek API error", {
|
|
@@ -3761,22 +3892,6 @@ var init_DeepSeekClient = __esm({
|
|
|
3761
3892
|
}
|
|
3762
3893
|
return response;
|
|
3763
3894
|
}
|
|
3764
|
-
shouldRetry(error, attempt) {
|
|
3765
|
-
const message = error.message.toLowerCase();
|
|
3766
|
-
if (message.includes("429") || message.includes("rate limit")) {
|
|
3767
|
-
return true;
|
|
3768
|
-
}
|
|
3769
|
-
if (message.includes("5") && (message.includes("500") || message.includes("502") || message.includes("503") || message.includes("504"))) {
|
|
3770
|
-
return true;
|
|
3771
|
-
}
|
|
3772
|
-
if (message.includes("timeout") || message.includes("abort")) {
|
|
3773
|
-
return attempt < 2;
|
|
3774
|
-
}
|
|
3775
|
-
if (message.includes("econnreset") || message.includes("econnrefused")) {
|
|
3776
|
-
return true;
|
|
3777
|
-
}
|
|
3778
|
-
return false;
|
|
3779
|
-
}
|
|
3780
3895
|
parseArguments(argsStr) {
|
|
3781
3896
|
try {
|
|
3782
3897
|
return JSON.parse(argsStr);
|
|
@@ -7274,9 +7389,9 @@ var init_format_code = __esm({
|
|
|
7274
7389
|
return { success: false, error: `\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`, output: "" };
|
|
7275
7390
|
}
|
|
7276
7391
|
try {
|
|
7277
|
-
const { execSync:
|
|
7392
|
+
const { execSync: execSync20 } = await import("child_process");
|
|
7278
7393
|
const ext = filePath.split(".").pop() ?? "ts";
|
|
7279
|
-
|
|
7394
|
+
execSync20(`npx prettier --write "${filePath}"`, {
|
|
7280
7395
|
encoding: "utf-8",
|
|
7281
7396
|
timeout: 3e4,
|
|
7282
7397
|
stdio: "pipe"
|
|
@@ -8462,25 +8577,25 @@ var init_db_restore = __esm({
|
|
|
8462
8577
|
try {
|
|
8463
8578
|
const engine = params.engine;
|
|
8464
8579
|
const connection = params.connection;
|
|
8465
|
-
const
|
|
8580
|
+
const backupFile2 = params.backup_file;
|
|
8466
8581
|
let cmd = "";
|
|
8467
8582
|
switch (engine) {
|
|
8468
8583
|
case "sqlite":
|
|
8469
|
-
cmd = `sqlite3 "${connection || "database.db"}" < "${
|
|
8584
|
+
cmd = `sqlite3 "${connection || "database.db"}" < "${backupFile2}"`;
|
|
8470
8585
|
break;
|
|
8471
8586
|
case "mysql":
|
|
8472
|
-
cmd = `mysql ${connection || ""} < "${
|
|
8587
|
+
cmd = `mysql ${connection || ""} < "${backupFile2}"`;
|
|
8473
8588
|
break;
|
|
8474
8589
|
case "postgresql":
|
|
8475
|
-
cmd = `psql ${connection || ""} < "${
|
|
8590
|
+
cmd = `psql ${connection || ""} < "${backupFile2}"`;
|
|
8476
8591
|
break;
|
|
8477
8592
|
default:
|
|
8478
8593
|
return { success: false, error: `\u4E0D\u652F\u6301\u7684\u6570\u636E\u5E93\u5F15\u64CE: ${engine}`, output: "" };
|
|
8479
8594
|
}
|
|
8480
8595
|
try {
|
|
8481
8596
|
const output = execSync9(cmd, { encoding: "utf-8", timeout: 12e4, stdio: "pipe" });
|
|
8482
|
-
return { success: true, output: `\u6062\u590D\u5B8C\u6210: ${
|
|
8483
|
-
${output || ""}`, metadata: { engine, backupFile } };
|
|
8597
|
+
return { success: true, output: `\u6062\u590D\u5B8C\u6210: ${backupFile2}
|
|
8598
|
+
${output || ""}`, metadata: { engine, backupFile: backupFile2 } };
|
|
8484
8599
|
} catch (err) {
|
|
8485
8600
|
const e = err;
|
|
8486
8601
|
return { success: false, error: `\u6062\u590D\u5931\u8D25: ${e.message || String(err)}`, output: "" };
|
|
@@ -10616,8 +10731,8 @@ var init_memory_store = __esm({
|
|
|
10616
10731
|
if (!key) return { success: false, error: "delete \u9700\u8981 key \u53C2\u6570", output: "" };
|
|
10617
10732
|
const memPath = join11(MEMORY_DIR, `${key}.json`);
|
|
10618
10733
|
if (!existsSync51(memPath)) return { success: false, error: `\u8BB0\u5FC6\u4E0D\u5B58\u5728: ${key}`, output: "" };
|
|
10619
|
-
const { unlinkSync:
|
|
10620
|
-
|
|
10734
|
+
const { unlinkSync: unlinkSync3 } = await import("fs");
|
|
10735
|
+
unlinkSync3(memPath);
|
|
10621
10736
|
return { success: true, output: `\u8BB0\u5FC6\u5DF2\u5220\u9664: ${key}` };
|
|
10622
10737
|
}
|
|
10623
10738
|
case "list": {
|
|
@@ -10908,17 +11023,17 @@ var init_notify_user = __esm({
|
|
|
10908
11023
|
const output = `${icons[level] || ""} [${level.toUpperCase()}] ${title}: ${message}`;
|
|
10909
11024
|
try {
|
|
10910
11025
|
if (process.platform === "win32") {
|
|
10911
|
-
const { execSync:
|
|
10912
|
-
|
|
11026
|
+
const { execSync: execSync20 } = await import("child_process");
|
|
11027
|
+
execSync20(`powershell -Command "Add-Type -AssemblyName System.Windows.Forms; $notify = New-Object System.Windows.Forms.NotifyIcon; $notify.Icon = [System.Drawing.SystemIcons]::Information; $notify.Visible = $true; $notify.ShowBalloonTip(5000, '${title}', '${message}', [System.Windows.Forms.ToolTipIcon]::${level === "error" ? "Error" : "Info"}); Start-Sleep -Seconds 6; $notify.Dispose()"`, {
|
|
10913
11028
|
timeout: 1e4,
|
|
10914
11029
|
stdio: "ignore"
|
|
10915
11030
|
});
|
|
10916
11031
|
} else if (process.platform === "darwin") {
|
|
10917
|
-
const { execSync:
|
|
10918
|
-
|
|
11032
|
+
const { execSync: execSync20 } = await import("child_process");
|
|
11033
|
+
execSync20(`osascript -e 'display notification "${message}" with title "${title}"'`, { stdio: "ignore" });
|
|
10919
11034
|
} else {
|
|
10920
|
-
const { execSync:
|
|
10921
|
-
|
|
11035
|
+
const { execSync: execSync20 } = await import("child_process");
|
|
11036
|
+
execSync20(`notify-send "${title}" "${message}"`, { stdio: "ignore" });
|
|
10922
11037
|
}
|
|
10923
11038
|
return { success: true, output, metadata: { title, level, notified: true } };
|
|
10924
11039
|
} catch {
|
|
@@ -11259,8 +11374,28 @@ __export(chat_repl_exports, {
|
|
|
11259
11374
|
});
|
|
11260
11375
|
import readline from "readline";
|
|
11261
11376
|
import process5 from "process";
|
|
11262
|
-
import { existsSync as existsSync53, mkdirSync as mkdirSync15, readFileSync as readFileSync37, writeFileSync as writeFileSync14, readdirSync as readdirSync4, statSync as statSync12 } from "fs";
|
|
11263
|
-
import { join as join12 } from "path";
|
|
11377
|
+
import { existsSync as existsSync53, mkdirSync as mkdirSync15, readFileSync as readFileSync37, writeFileSync as writeFileSync14, readdirSync as readdirSync4, statSync as statSync12, copyFileSync as copyFileSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
11378
|
+
import { join as join12, relative as relative6 } from "path";
|
|
11379
|
+
import { execSync as execSync19 } from "child_process";
|
|
11380
|
+
function backupFile(filePath) {
|
|
11381
|
+
if (!existsSync53(filePath)) return;
|
|
11382
|
+
try {
|
|
11383
|
+
if (!existsSync53(BACKUP_DIR)) mkdirSync15(BACKUP_DIR, { recursive: true });
|
|
11384
|
+
const rel = relative6(process5.cwd(), filePath).replace(/[/\\]/g, "_");
|
|
11385
|
+
const ts = Date.now();
|
|
11386
|
+
const backupPath = join12(BACKUP_DIR, `${ts}_${rel}`);
|
|
11387
|
+
copyFileSync2(filePath, backupPath);
|
|
11388
|
+
fileBackupStack.push({ path: filePath, backupPath, timestamp: ts });
|
|
11389
|
+
if (fileBackupStack.length > MAX_BACKUPS) {
|
|
11390
|
+
const old = fileBackupStack.shift();
|
|
11391
|
+
try {
|
|
11392
|
+
unlinkSync2(old.backupPath);
|
|
11393
|
+
} catch {
|
|
11394
|
+
}
|
|
11395
|
+
}
|
|
11396
|
+
} catch {
|
|
11397
|
+
}
|
|
11398
|
+
}
|
|
11264
11399
|
function getSkillSystemPrompt() {
|
|
11265
11400
|
if (!skillEngine) return "";
|
|
11266
11401
|
return skillEngine.getSystemPrompt();
|
|
@@ -11285,7 +11420,7 @@ async function startRepl(opts) {
|
|
|
11285
11420
|
let curTc = null;
|
|
11286
11421
|
let se = null;
|
|
11287
11422
|
try {
|
|
11288
|
-
const stream = await callApi(opts, msgs, tds,
|
|
11423
|
+
const stream = await callApi(opts, msgs, tds, 131072);
|
|
11289
11424
|
GS.api++;
|
|
11290
11425
|
ce = 0;
|
|
11291
11426
|
for await (const chunk of stream) {
|
|
@@ -11297,10 +11432,11 @@ async function startRepl(opts) {
|
|
|
11297
11432
|
const tc = chunk.tool_call;
|
|
11298
11433
|
if (tc) curTc = { id: tc.id, name: tc.name, argsStr: "" };
|
|
11299
11434
|
}
|
|
11300
|
-
if (chunk.type === "tool_call_args" && curTc) curTc.argsStr += chunk.content || "";
|
|
11301
11435
|
if (chunk.type === "tool_call_end" && curTc) {
|
|
11436
|
+
const tcData = chunk.tool_call;
|
|
11302
11437
|
try {
|
|
11303
|
-
|
|
11438
|
+
const args = tcData?.arguments || JSON.parse(curTc.argsStr || "{}");
|
|
11439
|
+
tcs.push({ id: curTc.id, name: curTc.name, args });
|
|
11304
11440
|
} catch {
|
|
11305
11441
|
tcs.push({ id: curTc.id, name: curTc.name, args: {} });
|
|
11306
11442
|
}
|
|
@@ -11337,7 +11473,11 @@ async function startRepl(opts) {
|
|
|
11337
11473
|
continue;
|
|
11338
11474
|
}
|
|
11339
11475
|
try {
|
|
11340
|
-
const
|
|
11476
|
+
const ac = new AbortController();
|
|
11477
|
+
const timeout = TOOL_TIMEOUT_MAP[tc.name] || DEFAULT_TOOL_TIMEOUT;
|
|
11478
|
+
const timer = setTimeout(() => ac.abort(), timeout);
|
|
11479
|
+
const r2 = await tool.execute(tc.args, ac.signal);
|
|
11480
|
+
clearTimeout(timer);
|
|
11341
11481
|
const txt = sanitize(r2.output || "").slice(0, TOOL_RESULT_MAX);
|
|
11342
11482
|
lh.push({ role: "tool", content: r2.success ? txt : `Error: ${r2.error}`, tool_call_id: tc.id });
|
|
11343
11483
|
GS.tc++;
|
|
@@ -11476,6 +11616,12 @@ ${prevSummary.slice(0, 800)}` });
|
|
|
11476
11616
|
return ok;
|
|
11477
11617
|
};
|
|
11478
11618
|
const onSigint = () => {
|
|
11619
|
+
if (currentAbortController) {
|
|
11620
|
+
currentAbortController.abort();
|
|
11621
|
+
currentAbortController = null;
|
|
11622
|
+
O(y("\n \u26A1 \u5DF2\u4E2D\u65AD\u5F53\u524D\u8BF7\u6C42\n"));
|
|
11623
|
+
return;
|
|
11624
|
+
}
|
|
11479
11625
|
if (resolveLine) {
|
|
11480
11626
|
const cb = resolveLine;
|
|
11481
11627
|
resolveLine = null;
|
|
@@ -11495,7 +11641,7 @@ ${prevSummary.slice(0, 800)}` });
|
|
|
11495
11641
|
};
|
|
11496
11642
|
rl.on("SIGINT", onSigint);
|
|
11497
11643
|
const onUCE = (err) => {
|
|
11498
|
-
if (!err.message?.includes("readline")) O(r(`
|
|
11644
|
+
if (!err.message?.includes("readline") && !err.message?.includes("abort")) O(r(`
|
|
11499
11645
|
\u26A0 ${err.message}`) + "\n");
|
|
11500
11646
|
};
|
|
11501
11647
|
process5.on("uncaughtException", onUCE);
|
|
@@ -11532,6 +11678,12 @@ ${prevSummary.slice(0, 800)}` });
|
|
|
11532
11678
|
O(G(" /mcp") + G(" MCP\u670D\u52A1\u5668") + "\n");
|
|
11533
11679
|
O(G(" /plan") + G(" <\u4EFB\u52A1> \u5148\u51FA\u65B9\u6848") + "\n");
|
|
11534
11680
|
O(G(" /spec") + G(" <\u4EFB\u52A1> \u5148\u51FA\u89C4\u683C") + "\n");
|
|
11681
|
+
O(G(" /review") + G(" <\u8DEF\u5F84> \u4EE3\u7801\u5BA1\u67E5") + "\n");
|
|
11682
|
+
O(G(" /fix") + G(" [\u76EE\u6807] \u81EA\u52A8\u4FEE\u590D") + "\n");
|
|
11683
|
+
O(G(" /commit") + G(" \u667A\u80FD\u63D0\u4EA4") + "\n");
|
|
11684
|
+
O(G(" /analyze") + G(" [\u8DEF\u5F84] \u9879\u76EE\u5206\u6790") + "\n");
|
|
11685
|
+
O(G(" /diff") + G(" <\u6587\u4EF6> \u53D8\u66F4\u9884\u89C8") + "\n");
|
|
11686
|
+
O(G(" /undo") + G(" \u64A4\u9500\u64CD\u4F5C") + "\n");
|
|
11535
11687
|
O(G(" /status") + G(" \u5F53\u524D\u72B6\u6001") + "\n");
|
|
11536
11688
|
O(G(" /model") + G(" \u6A21\u578B\u8BBE\u7F6E") + "\n");
|
|
11537
11689
|
O(G(" /config") + G(" \u914D\u7F6E\u7BA1\u7406") + "\n");
|
|
@@ -11648,7 +11800,8 @@ ${prevSummary.slice(0, 800)}` });
|
|
|
11648
11800
|
if (cmd === "/help") {
|
|
11649
11801
|
O(c(" /help /clear /quit /save [name] /load|resume [name] /sessions\n"));
|
|
11650
11802
|
O(c(" /tools [cat] /stats /memory /tasks /model /config /cwd /export /init /mcp /rules\n"));
|
|
11651
|
-
O(c(" /plan <\u4EFB\u52A1> /spec <\u4EFB\u52A1> /
|
|
11803
|
+
O(c(" /plan <\u4EFB\u52A1> /spec <\u4EFB\u52A1> /review <\u8DEF\u5F84> /fix [\u76EE\u6807]\n"));
|
|
11804
|
+
O(c(" /commit /analyze [\u8DEF\u5F84] /diff <\u6587\u4EF6> /undo /status\n\n"));
|
|
11652
11805
|
continue;
|
|
11653
11806
|
}
|
|
11654
11807
|
if (cmd === "/plan") {
|
|
@@ -11692,6 +11845,178 @@ ${prevSummary.slice(0, 800)}` });
|
|
|
11692
11845
|
await runLoop(opts, history, tools, sfdefs, confirm);
|
|
11693
11846
|
continue;
|
|
11694
11847
|
}
|
|
11848
|
+
if (cmd === "/review") {
|
|
11849
|
+
const target = arg || ".";
|
|
11850
|
+
O(b(c(" Review Mode")) + G(` \u2022 ${target}`) + "\n\n");
|
|
11851
|
+
history.push({ role: "system", content: `[Review Mode]
|
|
11852
|
+
\u4F60\u662F\u4E00\u4F4D\u8D44\u6DF1\u4EE3\u7801\u5BA1\u67E5\u4E13\u5BB6\u3002\u8BF7\u5BF9\u6307\u5B9A\u4EE3\u7801\u8FDB\u884C\u5168\u9762\u5BA1\u67E5\uFF1A
|
|
11853
|
+
|
|
11854
|
+
1. \u5148\u7528 read_file / glob_find / grep_search \u8BFB\u53D6\u76F8\u5173\u4EE3\u7801
|
|
11855
|
+
2. \u4ECE\u4EE5\u4E0B\u7EF4\u5EA6\u9010\u9879\u5BA1\u67E5\u5E76\u8BC4\u5206\uFF081-10\uFF09\uFF1A
|
|
11856
|
+
- \u4EE3\u7801\u8D28\u91CF\uFF1A\u53EF\u8BFB\u6027\u3001\u547D\u540D\u3001\u7ED3\u6784
|
|
11857
|
+
- \u5B89\u5168\u6027\uFF1A\u6CE8\u5165\u3001XSS\u3001\u5BC6\u94A5\u6CC4\u9732\u3001\u6743\u9650\u95EE\u9898
|
|
11858
|
+
- \u6027\u80FD\uFF1AN+1\u67E5\u8BE2\u3001\u5185\u5B58\u6CC4\u6F0F\u3001\u4E0D\u5FC5\u8981\u7684\u8BA1\u7B97
|
|
11859
|
+
- \u53EF\u7EF4\u62A4\u6027\uFF1A\u8026\u5408\u5EA6\u3001\u91CD\u590D\u4EE3\u7801\u3001\u6D4B\u8BD5\u8986\u76D6
|
|
11860
|
+
- \u6700\u4F73\u5B9E\u8DF5\uFF1A\u8BBE\u8BA1\u6A21\u5F0F\u3001SOLID\u539F\u5219\u3001\u9519\u8BEF\u5904\u7406
|
|
11861
|
+
3. \u5BF9\u6BCF\u4E2A\u95EE\u9898\u7ED9\u51FA\uFF1A\u6587\u4EF6\u8DEF\u5F84\u3001\u884C\u53F7\u8303\u56F4\u3001\u95EE\u9898\u63CF\u8FF0\u3001\u4FEE\u590D\u5EFA\u8BAE\u3001\u4E25\u91CD\u7A0B\u5EA6(\u{1F534}\u9AD8/\u{1F7E1}\u4E2D/\u{1F7E2}\u4F4E)
|
|
11862
|
+
4. \u6700\u540E\u7ED9\u51FA\u603B\u4F53\u8BC4\u5206\u548C\u6539\u8FDB\u4F18\u5148\u7EA7\u5217\u8868
|
|
11863
|
+
|
|
11864
|
+
\u5BA1\u67E5\u76EE\u6807\uFF1A${target}` });
|
|
11865
|
+
history.push({ role: "user", content: `\u5BA1\u67E5 ${target} \u7684\u4EE3\u7801\u8D28\u91CF` });
|
|
11866
|
+
const rvdefs = toolsToDefs(tools);
|
|
11867
|
+
await runLoop(opts, history, tools, rvdefs, confirm);
|
|
11868
|
+
continue;
|
|
11869
|
+
}
|
|
11870
|
+
if (cmd === "/commit") {
|
|
11871
|
+
O(b(c(" Commit Mode")) + G(" \u2022 \u667A\u80FD\u63D0\u4EA4") + "\n\n");
|
|
11872
|
+
try {
|
|
11873
|
+
const statusOut = execSync19("git status --porcelain", { encoding: "utf-8", timeout: 1e4, cwd: process5.cwd() });
|
|
11874
|
+
if (!statusOut.trim()) {
|
|
11875
|
+
O(y(" \u6CA1\u6709\u672A\u63D0\u4EA4\u7684\u53D8\u66F4\n\n"));
|
|
11876
|
+
continue;
|
|
11877
|
+
}
|
|
11878
|
+
const diffOut = execSync19("git diff --stat", { encoding: "utf-8", timeout: 15e3, cwd: process5.cwd() });
|
|
11879
|
+
const stagedOut = execSync19("git diff --cached --stat", { encoding: "utf-8", timeout: 15e3, cwd: process5.cwd() });
|
|
11880
|
+
const files = statusOut.trim().split("\n").filter(Boolean);
|
|
11881
|
+
O(G(` ${files.length} \u4E2A\u6587\u4EF6\u53D8\u66F4:
|
|
11882
|
+
`));
|
|
11883
|
+
for (const f of files.slice(0, 20)) {
|
|
11884
|
+
const status = f.slice(0, 2).trim();
|
|
11885
|
+
const path = f.slice(3);
|
|
11886
|
+
const icon = status === "M" ? y("M") : status === "A" ? g("A") : status === "D" ? r("D") : status === "?" ? G("?") : c(status);
|
|
11887
|
+
O(G(` ${icon} ${path.slice(0, 60)}`) + "\n");
|
|
11888
|
+
}
|
|
11889
|
+
if (files.length > 20) O(G(` \u2026\u8FD8\u6709 ${files.length - 20} \u4E2A`) + "\n");
|
|
11890
|
+
O("\n");
|
|
11891
|
+
history.push({ role: "system", content: `[Commit Mode]
|
|
11892
|
+
\u5206\u6790 git \u53D8\u66F4\u5E76\u751F\u6210\u63D0\u4EA4\u4FE1\u606F\uFF1A
|
|
11893
|
+
1. \u5148\u7528 run_command \u6267\u884C git diff \u67E5\u770B\u5177\u4F53\u53D8\u66F4\u5185\u5BB9
|
|
11894
|
+
2. \u5206\u6790\u53D8\u66F4\u7C7B\u578B\u548C\u8303\u56F4\uFF0C\u751F\u6210\u7B26\u5408 Conventional Commits \u89C4\u8303\u7684\u63D0\u4EA4\u4FE1\u606F
|
|
11895
|
+
3. \u683C\u5F0F: type(scope): description
|
|
11896
|
+
- type: feat/fix/refactor/docs/style/test/chore/perf
|
|
11897
|
+
- scope: \u53EF\u9009\uFF0C\u5F71\u54CD\u7684\u6A21\u5757
|
|
11898
|
+
4. \u7528 run_command \u6267\u884C git add \u548C git commit
|
|
11899
|
+
5. \u5982\u679C\u53D8\u66F4\u8F83\u591A\uFF0C\u5EFA\u8BAE\u5206\u591A\u6B21\u63D0\u4EA4
|
|
11900
|
+
|
|
11901
|
+
\u5F53\u524D\u53D8\u66F4\u7EDF\u8BA1\uFF1A
|
|
11902
|
+
${diffOut || stagedOut || "\u65E0staged\u53D8\u66F4"}` });
|
|
11903
|
+
history.push({ role: "user", content: "\u5206\u6790\u53D8\u66F4\u5E76\u63D0\u4EA4" });
|
|
11904
|
+
const cmdefs = toolsToDefs(tools);
|
|
11905
|
+
await runLoop(opts, history, tools, cmdefs, confirm);
|
|
11906
|
+
} catch (e) {
|
|
11907
|
+
O(r(` Git \u64CD\u4F5C\u5931\u8D25: ${e instanceof Error ? e.message.slice(0, 80) : String(e).slice(0, 80)}
|
|
11908
|
+
|
|
11909
|
+
`));
|
|
11910
|
+
}
|
|
11911
|
+
continue;
|
|
11912
|
+
}
|
|
11913
|
+
if (cmd === "/analyze") {
|
|
11914
|
+
const target = arg || process5.cwd();
|
|
11915
|
+
O(b(c(" Analyze Mode")) + G(` \u2022 ${target}`) + "\n\n");
|
|
11916
|
+
history.push({ role: "system", content: `[Analyze Mode]
|
|
11917
|
+
\u4F60\u662F\u4E00\u4F4D\u9879\u76EE\u67B6\u6784\u5206\u6790\u5E08\u3002\u8BF7\u5BF9\u9879\u76EE\u8FDB\u884C\u5168\u9762\u5206\u6790\uFF1A
|
|
11918
|
+
|
|
11919
|
+
1. \u7528 glob_find \u626B\u63CF\u9879\u76EE\u76EE\u5F55\u7ED3\u6784
|
|
11920
|
+
2. \u7528 read_file \u8BFB\u53D6 package.json / tsconfig.json / Cargo.toml \u7B49\u914D\u7F6E
|
|
11921
|
+
3. \u7528 grep_search / codebase_search \u5206\u6790\u4EE3\u7801\u6A21\u5F0F
|
|
11922
|
+
4. \u8F93\u51FA\u4EE5\u4E0B\u5206\u6790\u62A5\u544A\uFF1A
|
|
11923
|
+
- \u{1F4C1} \u9879\u76EE\u7ED3\u6784\u6811\uFF08\u5173\u952E\u76EE\u5F55\u548C\u6587\u4EF6\uFF09
|
|
11924
|
+
- \u{1F6E0} \u6280\u672F\u6808\u8BC6\u522B\uFF08\u8BED\u8A00\u3001\u6846\u67B6\u3001\u5E93\u3001\u5DE5\u5177\u94FE\uFF09
|
|
11925
|
+
- \u{1F4CA} \u4EE3\u7801\u7EDF\u8BA1\uFF08\u6587\u4EF6\u6570\u3001\u4EE3\u7801\u884C\u6570\u4F30\u7B97\u3001\u5404\u8BED\u8A00\u5360\u6BD4\uFF09
|
|
11926
|
+
- \u{1F3D7}\uFE0F \u67B6\u6784\u6A21\u5F0F\uFF08MVC/\u5FAE\u670D\u52A1/\u5355\u4F53/\u63D2\u4EF6\u5F0F\u7B49\uFF09
|
|
11927
|
+
- \u{1F517} \u4F9D\u8D56\u5173\u7CFB\uFF08\u6838\u5FC3\u4F9D\u8D56\u3001\u5F00\u53D1\u4F9D\u8D56\u3001\u7248\u672C\u98CE\u9669\uFF09
|
|
11928
|
+
- \u26A0\uFE0F \u6F5C\u5728\u95EE\u9898\uFF08\u8FC7\u65F6\u4F9D\u8D56\u3001\u5B89\u5168\u98CE\u9669\u3001\u4EE3\u7801\u5F02\u5473\uFF09
|
|
11929
|
+
- \u{1F4A1} \u6539\u8FDB\u5EFA\u8BAE\uFF08\u4F18\u5148\u7EA7\u6392\u5E8F\uFF09
|
|
11930
|
+
|
|
11931
|
+
\u5206\u6790\u76EE\u6807\uFF1A${target}` });
|
|
11932
|
+
history.push({ role: "user", content: `\u5206\u6790\u9879\u76EE ${target}` });
|
|
11933
|
+
const andefs = toolsToDefs(tools);
|
|
11934
|
+
await runLoop(opts, history, tools, andefs, confirm);
|
|
11935
|
+
continue;
|
|
11936
|
+
}
|
|
11937
|
+
if (cmd === "/fix") {
|
|
11938
|
+
const target = arg || "";
|
|
11939
|
+
O(b(c(" Fix Mode")) + G(" \u2022 \u81EA\u52A8\u4FEE\u590D") + "\n\n");
|
|
11940
|
+
history.push({ role: "system", content: `[Fix Mode]
|
|
11941
|
+
\u4F60\u662F\u4E00\u4F4D\u81EA\u52A8\u4FEE\u590D\u5DE5\u7A0B\u5E08\u3002\u8BF7\u6267\u884C\u4EE5\u4E0B\u6D41\u7A0B\uFF1A
|
|
11942
|
+
|
|
11943
|
+
1. \u5148\u7528 run_command \u8FD0\u884C\u6784\u5EFA\u547D\u4EE4\uFF08\u5982 npm run build, tsc --noEmit, cargo check \u7B49\uFF09
|
|
11944
|
+
2. \u5982\u679C\u6784\u5EFA\u6210\u529F\uFF0C\u8FD0\u884C\u6D4B\u8BD5\uFF08npm test, cargo test \u7B49\uFF09
|
|
11945
|
+
3. \u5982\u679C\u6709\u9519\u8BEF\uFF1A
|
|
11946
|
+
a. \u4ED4\u7EC6\u5206\u6790\u9519\u8BEF\u4FE1\u606F\uFF0C\u5B9A\u4F4D\u5230\u5177\u4F53\u6587\u4EF6\u548C\u884C\u53F7
|
|
11947
|
+
b. \u7528 read_file \u8BFB\u53D6\u51FA\u9519\u6587\u4EF6\u7684\u76F8\u5173\u4EE3\u7801
|
|
11948
|
+
c. \u7406\u89E3\u9519\u8BEF\u6839\u56E0\uFF0C\u5236\u5B9A\u4FEE\u590D\u65B9\u6848
|
|
11949
|
+
d. \u7528 edit_file \u7CBE\u786E\u4FEE\u590D\uFF08\u4F18\u5148\u7528 edit \u800C\u975E\u91CD\u5199\u6574\u4E2A\u6587\u4EF6\uFF09
|
|
11950
|
+
e. \u91CD\u65B0\u8FD0\u884C\u6784\u5EFA\u9A8C\u8BC1\u4FEE\u590D
|
|
11951
|
+
f. \u91CD\u590D\u76F4\u5230\u6240\u6709\u9519\u8BEF\u6E05\u9664
|
|
11952
|
+
4. \u5982\u679C\u6D4B\u8BD5\u5931\u8D25\uFF0C\u540C\u6837\u5206\u6790\u5E76\u4FEE\u590D
|
|
11953
|
+
5. \u6700\u591A\u5C1D\u8BD5\u4FEE\u590D 5 \u8F6E\uFF0C\u907F\u514D\u65E0\u9650\u5FAA\u73AF
|
|
11954
|
+
6. \u6BCF\u6B21\u4FEE\u590D\u540E\u90FD\u91CD\u65B0\u9A8C\u8BC1
|
|
11955
|
+
|
|
11956
|
+
${target ? `\u4FEE\u590D\u76EE\u6807\uFF1A${target}
|
|
11957
|
+
` : "\u81EA\u52A8\u68C0\u6D4B\u5E76\u4FEE\u590D\u6240\u6709\u6784\u5EFA/\u6D4B\u8BD5\u9519\u8BEF"}` });
|
|
11958
|
+
history.push({ role: "user", content: target || "\u68C0\u6D4B\u5E76\u4FEE\u590D\u9879\u76EE\u9519\u8BEF" });
|
|
11959
|
+
const fxdefs = toolsToDefs(tools);
|
|
11960
|
+
await runLoop(opts, history, tools, fxdefs, confirm);
|
|
11961
|
+
continue;
|
|
11962
|
+
}
|
|
11963
|
+
if (cmd === "/diff") {
|
|
11964
|
+
if (!arg) {
|
|
11965
|
+
O(y(" \u7528\u6CD5: /diff <\u6587\u4EF6\u8DEF\u5F84>\n \u663E\u793A\u6587\u4EF6\u6700\u8FD1\u7684\u53D8\u66F4\n\n"));
|
|
11966
|
+
continue;
|
|
11967
|
+
}
|
|
11968
|
+
const filePath = arg.startsWith("/") || arg.startsWith("\\") || arg.length > 2 ? arg : join12(process5.cwd(), arg);
|
|
11969
|
+
if (fileBackupStack.length === 0) {
|
|
11970
|
+
O(y(" \u6CA1\u6709\u53EF\u7528\u7684\u5907\u4EFD\u8BB0\u5F55\n\n"));
|
|
11971
|
+
continue;
|
|
11972
|
+
}
|
|
11973
|
+
const backups = fileBackupStack.filter((b2) => b2.path === filePath).reverse();
|
|
11974
|
+
if (backups.length === 0) {
|
|
11975
|
+
const allBackups = [...fileBackupStack].reverse();
|
|
11976
|
+
O(G(" \u6700\u8FD1\u7684\u6587\u4EF6\u53D8\u66F4:\n"));
|
|
11977
|
+
for (const b2 of allBackups.slice(0, 10)) {
|
|
11978
|
+
const rel = relative6(process5.cwd(), b2.path);
|
|
11979
|
+
const time = new Date(b2.timestamp).toLocaleTimeString();
|
|
11980
|
+
O(G(` ${time} ${rel.slice(0, 50)}`) + "\n");
|
|
11981
|
+
}
|
|
11982
|
+
O("\n");
|
|
11983
|
+
continue;
|
|
11984
|
+
}
|
|
11985
|
+
const latest = backups[0];
|
|
11986
|
+
try {
|
|
11987
|
+
const currentContent = existsSync53(filePath) ? readFileSync37(filePath, "utf-8") : "(\u6587\u4EF6\u5DF2\u5220\u9664)";
|
|
11988
|
+
const backupContent = readFileSync37(latest.backupPath, "utf-8");
|
|
11989
|
+
const diffResult = computeSimpleDiff(backupContent, currentContent, filePath);
|
|
11990
|
+
O(b(c(" Diff")) + G(` \u2022 ${relative6(process5.cwd(), filePath)}`) + "\n\n");
|
|
11991
|
+
O(diffResult + "\n\n");
|
|
11992
|
+
} catch {
|
|
11993
|
+
O(y(" \u65E0\u6CD5\u8BFB\u53D6\u6587\u4EF6\u8FDB\u884C\u5BF9\u6BD4\n\n"));
|
|
11994
|
+
}
|
|
11995
|
+
continue;
|
|
11996
|
+
}
|
|
11997
|
+
if (cmd === "/undo") {
|
|
11998
|
+
if (fileBackupStack.length === 0) {
|
|
11999
|
+
O(y(" \u6CA1\u6709\u53EF\u64A4\u9500\u7684\u64CD\u4F5C\n\n"));
|
|
12000
|
+
continue;
|
|
12001
|
+
}
|
|
12002
|
+
const last = fileBackupStack[fileBackupStack.length - 1];
|
|
12003
|
+
try {
|
|
12004
|
+
const rel = relative6(process5.cwd(), last.path);
|
|
12005
|
+
copyFileSync2(last.backupPath, last.path);
|
|
12006
|
+
fileBackupStack.pop();
|
|
12007
|
+
try {
|
|
12008
|
+
unlinkSync2(last.backupPath);
|
|
12009
|
+
} catch {
|
|
12010
|
+
}
|
|
12011
|
+
O(g(" \u2713 \u5DF2\u64A4\u9500") + G(` ${rel}`) + "\n");
|
|
12012
|
+
O(G(" \u63D0\u793A: \u53EF\u7EE7\u7EED /undo \u64A4\u9500\u66F4\u591A\u64CD\u4F5C\n\n"));
|
|
12013
|
+
} catch (e) {
|
|
12014
|
+
O(r(` \u64A4\u9500\u5931\u8D25: ${e instanceof Error ? e.message.slice(0, 60) : String(e).slice(0, 60)}
|
|
12015
|
+
|
|
12016
|
+
`));
|
|
12017
|
+
}
|
|
12018
|
+
continue;
|
|
12019
|
+
}
|
|
11695
12020
|
O(G(` \u672A\u77E5\u547D\u4EE4: ${cmd} (\u8F93\u5165 /help \u67E5\u770B\u5E2E\u52A9)
|
|
11696
12021
|
|
|
11697
12022
|
`));
|
|
@@ -11761,8 +12086,9 @@ async function runLoop(opts, history, tools, toolDefs, confirm) {
|
|
|
11761
12086
|
thinkAnimIv = null;
|
|
11762
12087
|
}
|
|
11763
12088
|
};
|
|
12089
|
+
currentAbortController = new AbortController();
|
|
11764
12090
|
try {
|
|
11765
|
-
const stream = await callApi(opts, msgs, toolDefs,
|
|
12091
|
+
const stream = await callApi(opts, msgs, toolDefs, amax, currentAbortController.signal);
|
|
11766
12092
|
GS.api++;
|
|
11767
12093
|
ce = 0;
|
|
11768
12094
|
const cols = process5.stdout.columns || 80;
|
|
@@ -11801,10 +12127,11 @@ async function runLoop(opts, history, tools, toolDefs, confirm) {
|
|
|
11801
12127
|
const tc = chunk.tool_call;
|
|
11802
12128
|
if (tc) curTc = { id: tc.id, name: tc.name, argsStr: "" };
|
|
11803
12129
|
}
|
|
11804
|
-
if (chunk.type === "tool_call_args" && curTc) curTc.argsStr += chunk.content || "";
|
|
11805
12130
|
if (chunk.type === "tool_call_end" && curTc) {
|
|
12131
|
+
const tcData = chunk.tool_call;
|
|
11806
12132
|
try {
|
|
11807
|
-
|
|
12133
|
+
const args = tcData?.arguments || JSON.parse(curTc.argsStr || "{}");
|
|
12134
|
+
tcs.push({ id: curTc.id, name: curTc.name, args });
|
|
11808
12135
|
} catch {
|
|
11809
12136
|
tcs.push({ id: curTc.id, name: curTc.name, args: {} });
|
|
11810
12137
|
}
|
|
@@ -11818,8 +12145,15 @@ async function runLoop(opts, history, tools, toolDefs, confirm) {
|
|
|
11818
12145
|
}
|
|
11819
12146
|
} catch (e) {
|
|
11820
12147
|
stopStreamAnim();
|
|
11821
|
-
|
|
12148
|
+
const errMsg = e instanceof Error ? e.message : String(e);
|
|
12149
|
+
if (errMsg.includes("abort") || errMsg.includes("cancel")) {
|
|
12150
|
+
se = null;
|
|
12151
|
+
O(y("\n \u26A1 \u8BF7\u6C42\u5DF2\u53D6\u6D88\n"));
|
|
12152
|
+
} else {
|
|
12153
|
+
se = errMsg;
|
|
12154
|
+
}
|
|
11822
12155
|
}
|
|
12156
|
+
currentAbortController = null;
|
|
11823
12157
|
stopStreamAnim();
|
|
11824
12158
|
Oflush();
|
|
11825
12159
|
const remaining = md.flush();
|
|
@@ -11955,14 +12289,19 @@ async function execTool(tc, tools, opts, confirm) {
|
|
|
11955
12289
|
execAnimIv = setInterval(() => {
|
|
11956
12290
|
rawWrite("\r" + thinkingAnimAt(toolName, toolStart));
|
|
11957
12291
|
}, 80);
|
|
11958
|
-
const
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
12292
|
+
const timeout = TOOL_TIMEOUT_MAP[tc.name] || DEFAULT_TOOL_TIMEOUT;
|
|
12293
|
+
const ac = new AbortController();
|
|
12294
|
+
const timer = setTimeout(() => ac.abort(), timeout);
|
|
12295
|
+
if (tc.name === "write_file" || tc.name === "edit_file") {
|
|
12296
|
+
const fp = tc.args.file_path || tc.args.path || tc.args.file || "";
|
|
12297
|
+
if (fp) backupFile(fp);
|
|
12298
|
+
}
|
|
11962
12299
|
let result;
|
|
11963
12300
|
try {
|
|
11964
|
-
result = await
|
|
12301
|
+
result = await tool.execute(tc.args, ac.signal);
|
|
12302
|
+
clearTimeout(timer);
|
|
11965
12303
|
} catch (e) {
|
|
12304
|
+
clearTimeout(timer);
|
|
11966
12305
|
result = { success: false, error: e.message, output: "" };
|
|
11967
12306
|
}
|
|
11968
12307
|
stopToolAnim();
|
|
@@ -12027,24 +12366,57 @@ async function execTool(tc, tools, opts, confirm) {
|
|
|
12027
12366
|
}
|
|
12028
12367
|
function buildMsgs(history) {
|
|
12029
12368
|
const r2 = [];
|
|
12030
|
-
let sysContent = `You are DeeperCode V4-Pro,
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12369
|
+
let sysContent = `You are DeeperCode V4-Pro, an elite full-stack AI coding agent with autonomous execution capability.
|
|
12370
|
+
|
|
12371
|
+
## Core Principles
|
|
12372
|
+
1. READ BEFORE WRITE \u2014 Always inspect project state before making changes.
|
|
12373
|
+
2. COMPLETE CODE \u2014 Write full files. Never use placeholders like "// ..." or "rest of code".
|
|
12374
|
+
3. ONE CALL = ONE FILE \u2014 Each write_file contains exactly one complete file. Batch independent writes.
|
|
12375
|
+
4. PLAN WITH TODOS \u2014 Use todo_manager for multi-step tasks. Update status as you progress.
|
|
12376
|
+
5. ACT OVER EXPLAIN \u2014 Keep reasoning brief. Prefer tool calls over lengthy explanations.
|
|
12377
|
+
6. VERIFY AFTER WRITE \u2014 After writing code, run type checks, linters, or tests to confirm correctness.
|
|
12378
|
+
7. FIX ERRORS PROACTIVELY \u2014 If a tool returns an error, diagnose and fix it immediately.
|
|
12379
|
+
8. PARALLEL WHEN POSSIBLE \u2014 Execute independent tool calls simultaneously for efficiency.
|
|
12380
|
+
|
|
12381
|
+
## Smart Editing Strategy
|
|
12382
|
+
- For EXISTING files, prefer edit_file over write_file to minimize diff size.
|
|
12383
|
+
- For NEW files, use write_file with complete content.
|
|
12384
|
+
- Before editing, read the file first to understand its current state.
|
|
12385
|
+
- Make targeted, minimal edits rather than rewriting entire files.
|
|
12386
|
+
|
|
12387
|
+
## Auto-Verification Loop
|
|
12388
|
+
After writing or editing code files, ALWAYS verify the changes:
|
|
12389
|
+
1. Run the project's build command (npm run build, tsc --noEmit, cargo check, etc.)
|
|
12390
|
+
2. If build fails, read the error output, fix the issues, and re-verify
|
|
12391
|
+
3. If tests exist, run them to confirm nothing is broken
|
|
12392
|
+
4. Repeat until all checks pass \u2014 do NOT leave the user with broken code
|
|
12393
|
+
|
|
12394
|
+
## Error Recovery
|
|
12395
|
+
- When a tool call fails, analyze the error message carefully before retrying
|
|
12396
|
+
- If the same approach fails twice, try a different strategy
|
|
12397
|
+
- For type errors: read the file, understand the types, fix precisely
|
|
12398
|
+
- For runtime errors: add proper error handling and logging
|
|
12399
|
+
- Never give up after one failure \u2014 adapt and overcome
|
|
12400
|
+
|
|
12401
|
+
## Execution Strategy
|
|
12402
|
+
- Start by reading relevant files and understanding the codebase structure.
|
|
12403
|
+
- Break complex tasks into small, verifiable steps.
|
|
12404
|
+
- After each code change, verify it compiles/passes before moving on.
|
|
12405
|
+
- When stuck, try a different approach rather than repeating the same failed action.
|
|
12406
|
+
- Use subagent for independent subtasks that can run in parallel.
|
|
12407
|
+
|
|
12408
|
+
## Context
|
|
12409
|
+
- cwd=${process5.cwd()} plat=${process5.platform} arch=${process5.arch}
|
|
12410
|
+
- Respond in the same language as the user's input.`;
|
|
12039
12411
|
const ts = todoSummary(4);
|
|
12040
|
-
if (ts) sysContent += "\n[Remaining]\n" + ts;
|
|
12412
|
+
if (ts) sysContent += "\n[Remaining Tasks]\n" + ts;
|
|
12041
12413
|
const lastU = history.filter((m) => m.role === "user").pop();
|
|
12042
12414
|
if (lastU?.content) {
|
|
12043
12415
|
const hints = xmemory.getProceduralHints(lastU.content || "", 3);
|
|
12044
12416
|
if (hints) sysContent += "\n" + hints;
|
|
12045
12417
|
}
|
|
12046
12418
|
const workCtx = xmemory.getWorkingContext(400);
|
|
12047
|
-
if (workCtx) sysContent += "\n[
|
|
12419
|
+
if (workCtx) sysContent += "\n[Recent Work]\n" + workCtx;
|
|
12048
12420
|
const skillPrompt = getSkillSystemPrompt();
|
|
12049
12421
|
if (skillPrompt) sysContent += "\n" + skillPrompt;
|
|
12050
12422
|
r2.push({ role: "system", content: sysContent });
|
|
@@ -12094,22 +12466,44 @@ function compressHistory(h) {
|
|
|
12094
12466
|
const keep = 6;
|
|
12095
12467
|
const old = h.slice(0, h.length - keep);
|
|
12096
12468
|
const recent = h.slice(h.length - keep);
|
|
12097
|
-
|
|
12469
|
+
const sections = [];
|
|
12470
|
+
let userParts = [];
|
|
12471
|
+
let assistantParts = [];
|
|
12472
|
+
let toolParts = [];
|
|
12473
|
+
const flushSection = () => {
|
|
12474
|
+
if (userParts.length > 0) sections.push(`[\u7528\u6237] ${userParts.join(" \u2192 ")}`);
|
|
12475
|
+
if (assistantParts.length > 0) sections.push(`[\u52A9\u624B] ${assistantParts.join(" \u2192 ")}`);
|
|
12476
|
+
if (toolParts.length > 0) sections.push(`[\u5DE5\u5177] ${toolParts.join(", ")}`);
|
|
12477
|
+
userParts = [];
|
|
12478
|
+
assistantParts = [];
|
|
12479
|
+
toolParts = [];
|
|
12480
|
+
};
|
|
12098
12481
|
for (const m of old) {
|
|
12482
|
+
if (m.role === "system") {
|
|
12483
|
+
flushSection();
|
|
12484
|
+
continue;
|
|
12485
|
+
}
|
|
12099
12486
|
if (m.role === "user" && m.content) {
|
|
12100
|
-
|
|
12101
|
-
|
|
12102
|
-
} else if (m.role === "assistant"
|
|
12103
|
-
|
|
12104
|
-
|
|
12487
|
+
if (assistantParts.length > 0 || toolParts.length > 0) flushSection();
|
|
12488
|
+
userParts.push(m.content.slice(0, 120));
|
|
12489
|
+
} else if (m.role === "assistant") {
|
|
12490
|
+
if (m.tool_calls && m.tool_calls.length > 0) {
|
|
12491
|
+
const names = m.tool_calls.map((t) => t.name).join(", ");
|
|
12492
|
+
toolParts.push(names);
|
|
12493
|
+
}
|
|
12494
|
+
if (m.content) {
|
|
12495
|
+
assistantParts.push(m.content.slice(0, 150));
|
|
12496
|
+
}
|
|
12105
12497
|
} else if (m.role === "tool" && m.content) {
|
|
12106
|
-
|
|
12107
|
-
|
|
12498
|
+
const isErr = m.content.startsWith("Error:");
|
|
12499
|
+
toolParts.push(isErr ? "\u274C" : "\u2713");
|
|
12108
12500
|
}
|
|
12109
12501
|
}
|
|
12502
|
+
flushSection();
|
|
12503
|
+
const compressed = sections.join("\n").slice(0, 4e3);
|
|
12110
12504
|
h.length = 0;
|
|
12111
12505
|
h.push({ role: "system", content: `[\u4E0A\u4E0B\u6587\u538B\u7F29\xB7${old.length}\u6761\u6458\u8981]
|
|
12112
|
-
${compressed
|
|
12506
|
+
${compressed}` });
|
|
12113
12507
|
h.push(...recent);
|
|
12114
12508
|
}
|
|
12115
12509
|
function sanitize(t) {
|
|
@@ -12119,6 +12513,45 @@ function lastUser(h) {
|
|
|
12119
12513
|
for (let i = h.length - 1; i >= 0; i--) if (h[i].role === "user" && h[i].content) return h[i].content;
|
|
12120
12514
|
return "";
|
|
12121
12515
|
}
|
|
12516
|
+
function computeSimpleDiff(oldText, newText, filePath) {
|
|
12517
|
+
const oldLines = oldText.split("\n");
|
|
12518
|
+
const newLines = newText.split("\n");
|
|
12519
|
+
const maxLines = Math.max(oldLines.length, newLines.length);
|
|
12520
|
+
const result = [];
|
|
12521
|
+
let changeCount = 0;
|
|
12522
|
+
const contextLines = 3;
|
|
12523
|
+
for (let i = 0; i < maxLines; i++) {
|
|
12524
|
+
const oldLine = oldLines[i];
|
|
12525
|
+
const newLine = newLines[i];
|
|
12526
|
+
if (oldLine !== newLine) {
|
|
12527
|
+
changeCount++;
|
|
12528
|
+
const start = Math.max(0, i - contextLines);
|
|
12529
|
+
const end = Math.min(maxLines, i + contextLines + 1);
|
|
12530
|
+
if (result.length === 0 || result[result.length - 1] !== "...") {
|
|
12531
|
+
result.push(G(` @@ line ${i + 1} @@`));
|
|
12532
|
+
}
|
|
12533
|
+
for (let j = start; j < end; j++) {
|
|
12534
|
+
if (j === i) {
|
|
12535
|
+
if (oldLine !== void 0 && newLine !== void 0) {
|
|
12536
|
+
result.push(r(` - ${oldLines[j]}`));
|
|
12537
|
+
result.push(g(` + ${newLines[j]}`));
|
|
12538
|
+
} else if (oldLine !== void 0) {
|
|
12539
|
+
result.push(r(` - ${oldLines[j]}`));
|
|
12540
|
+
} else {
|
|
12541
|
+
result.push(g(` + ${newLines[j]}`));
|
|
12542
|
+
}
|
|
12543
|
+
} else if (j < oldLines.length && j < newLines.length) {
|
|
12544
|
+
result.push(G(` ${oldLines[j]}`));
|
|
12545
|
+
}
|
|
12546
|
+
}
|
|
12547
|
+
result.push(G(" ..."));
|
|
12548
|
+
}
|
|
12549
|
+
}
|
|
12550
|
+
if (changeCount === 0) return G(" (\u65E0\u53D8\u66F4)");
|
|
12551
|
+
const rel = relative6(process5.cwd(), filePath);
|
|
12552
|
+
return `${G(`\u6587\u4EF6: ${rel} (${changeCount} \u5904\u53D8\u66F4)`)}
|
|
12553
|
+
${result.join("\n")}`;
|
|
12554
|
+
}
|
|
12122
12555
|
function toolsToDefs(tools) {
|
|
12123
12556
|
return tools.map((t) => ({ type: "function", function: { name: t.name, description: t.description, parameters: t.parameters } }));
|
|
12124
12557
|
}
|
|
@@ -12145,7 +12578,6 @@ async function listSessions() {
|
|
|
12145
12578
|
const data = JSON.parse(readFileSync37(join12(SESSION_DIR, f), "utf-8"));
|
|
12146
12579
|
const label = f.replace(/^sess_|\.json$/g, "");
|
|
12147
12580
|
const msgCount = data.messages?.length || 0;
|
|
12148
|
-
const cwd = data.cwd || "?";
|
|
12149
12581
|
const savedAt = data.savedAt?.slice(0, 16) || "?";
|
|
12150
12582
|
O(G(` ${i + 1}. `) + c(label) + G(` \xB7 ${msgCount}\u6761 \xB7 ${savedAt}`) + "\n");
|
|
12151
12583
|
} catch {
|
|
@@ -12320,14 +12752,15 @@ async function loadBuiltinTools() {
|
|
|
12320
12752
|
const { builtinTools: builtinTools2 } = await Promise.resolve().then(() => (init_builtin(), builtin_exports));
|
|
12321
12753
|
return builtinTools2;
|
|
12322
12754
|
}
|
|
12323
|
-
async function callApi(opts, msgs, tools,
|
|
12755
|
+
async function callApi(opts, msgs, tools, cmt = 8192, signal) {
|
|
12324
12756
|
const client = new DeepSeekClient({
|
|
12325
12757
|
apiKey: opts.apiKey || "",
|
|
12326
12758
|
model: opts.model || "deepseek-chat",
|
|
12327
12759
|
baseUrl: opts.baseUrl || "https://api.deepseek.com",
|
|
12328
12760
|
temperature: opts.temperature ?? 0,
|
|
12329
12761
|
maxTokens: cmt,
|
|
12330
|
-
think: { enabled: true, budgetTokens: cmt }
|
|
12762
|
+
think: { enabled: true, budgetTokens: cmt },
|
|
12763
|
+
signal
|
|
12331
12764
|
});
|
|
12332
12765
|
const chatMsgs = msgs.map((m) => ({
|
|
12333
12766
|
role: m.role || "user",
|
|
@@ -12338,51 +12771,15 @@ async function callApi(opts, msgs, tools, retry = 0, cmt = 8192) {
|
|
|
12338
12771
|
reasoning_content: m.reasoning_content,
|
|
12339
12772
|
thinking: m.thinking
|
|
12340
12773
|
}));
|
|
12341
|
-
|
|
12342
|
-
|
|
12343
|
-
|
|
12344
|
-
|
|
12345
|
-
|
|
12346
|
-
|
|
12347
|
-
|
|
12348
|
-
await new Promise((r2) => setTimeout(r2, d2));
|
|
12349
|
-
return callApi(opts, msgs, tools, retry + 1, cmt);
|
|
12350
|
-
}
|
|
12351
|
-
throw e;
|
|
12352
|
-
}
|
|
12353
|
-
}
|
|
12354
|
-
async function* adaptStream(stream) {
|
|
12355
|
-
const seen = /* @__PURE__ */ new Set();
|
|
12356
|
-
let hasPending = false;
|
|
12357
|
-
for await (const chunk of stream) {
|
|
12358
|
-
if (chunk.type === "text" || chunk.type === "thinking") {
|
|
12359
|
-
yield { type: chunk.type, content: chunk.content };
|
|
12360
|
-
} else if (chunk.type === "tool_call") {
|
|
12361
|
-
const tc = chunk.tool_call;
|
|
12362
|
-
if (tc) {
|
|
12363
|
-
const key = tc.id || tc.name;
|
|
12364
|
-
const sa = JSON.stringify(tc.arguments || {});
|
|
12365
|
-
if (!seen.has(key)) {
|
|
12366
|
-
if (hasPending) yield { type: "tool_call_end" };
|
|
12367
|
-
seen.add(key);
|
|
12368
|
-
hasPending = true;
|
|
12369
|
-
yield { type: "tool_call_start", tool_call: { id: tc.id, name: tc.name } };
|
|
12370
|
-
yield { type: "tool_call_args", content: sa };
|
|
12371
|
-
} else {
|
|
12372
|
-
yield { type: "tool_call_args", content: sa };
|
|
12373
|
-
}
|
|
12374
|
-
}
|
|
12375
|
-
} else if (chunk.type === "done") {
|
|
12376
|
-
if (hasPending) yield { type: "tool_call_end" };
|
|
12377
|
-
yield { type: "done" };
|
|
12378
|
-
return;
|
|
12379
|
-
} else {
|
|
12380
|
-
yield chunk;
|
|
12381
|
-
}
|
|
12382
|
-
}
|
|
12383
|
-
yield { type: "done" };
|
|
12774
|
+
const stream = await client.chatStream(chatMsgs, tools.map((t) => ({
|
|
12775
|
+
name: t.function.name,
|
|
12776
|
+
description: t.function.description,
|
|
12777
|
+
category: "",
|
|
12778
|
+
parameters: t.function.parameters
|
|
12779
|
+
})));
|
|
12780
|
+
return stream;
|
|
12384
12781
|
}
|
|
12385
|
-
var MAX_HISTORY, CONTEXT_LIMIT, CTX_WARN, TOOL_RESULT_MAX, SESSION_DIR, AUTOSAVE_FILE, GS, skillEngine, mcpClient, validator, _fileCache;
|
|
12782
|
+
var MAX_HISTORY, CONTEXT_LIMIT, CTX_WARN, TOOL_RESULT_MAX, SESSION_DIR, AUTOSAVE_FILE, TOOL_TIMEOUT_MAP, DEFAULT_TOOL_TIMEOUT, GS, skillEngine, mcpClient, validator, currentAbortController, BACKUP_DIR, MAX_BACKUPS, fileBackupStack, _fileCache;
|
|
12386
12783
|
var init_chat_repl = __esm({
|
|
12387
12784
|
"src/cli/chat-repl.ts"() {
|
|
12388
12785
|
"use strict";
|
|
@@ -12403,10 +12800,38 @@ var init_chat_repl = __esm({
|
|
|
12403
12800
|
TOOL_RESULT_MAX = 4e3;
|
|
12404
12801
|
SESSION_DIR = join12(DEEPER_HOME, "sessions");
|
|
12405
12802
|
AUTOSAVE_FILE = join12(SESSION_DIR, "_autosave.json");
|
|
12803
|
+
TOOL_TIMEOUT_MAP = {
|
|
12804
|
+
run_command: 12e4,
|
|
12805
|
+
run_async: 12e4,
|
|
12806
|
+
pipe_commands: 12e4,
|
|
12807
|
+
shell_script: 12e4,
|
|
12808
|
+
build_project: 18e4,
|
|
12809
|
+
run_test: 18e4,
|
|
12810
|
+
npm_manage: 12e4,
|
|
12811
|
+
docker_manage: 12e4,
|
|
12812
|
+
project_init: 12e4,
|
|
12813
|
+
web_fetch: 6e4,
|
|
12814
|
+
web_search: 6e4,
|
|
12815
|
+
http_request: 6e4,
|
|
12816
|
+
browser_action: 6e4,
|
|
12817
|
+
screenshot_page: 6e4,
|
|
12818
|
+
sql_query: 6e4,
|
|
12819
|
+
sql_migrate: 12e4,
|
|
12820
|
+
db_backup: 18e4,
|
|
12821
|
+
db_restore: 18e4,
|
|
12822
|
+
secret_scan: 6e4,
|
|
12823
|
+
vulnerability_check: 6e4,
|
|
12824
|
+
subagent: 18e4
|
|
12825
|
+
};
|
|
12826
|
+
DEFAULT_TOOL_TIMEOUT = 3e4;
|
|
12406
12827
|
GS = { tc: 0, api: 0, ch: 0 };
|
|
12407
12828
|
skillEngine = null;
|
|
12408
12829
|
mcpClient = null;
|
|
12409
12830
|
validator = new ToolValidator();
|
|
12831
|
+
currentAbortController = null;
|
|
12832
|
+
BACKUP_DIR = join12(DEEPER_HOME, "backups");
|
|
12833
|
+
MAX_BACKUPS = 50;
|
|
12834
|
+
fileBackupStack = [];
|
|
12410
12835
|
_fileCache = /* @__PURE__ */ new Map();
|
|
12411
12836
|
}
|
|
12412
12837
|
});
|