jinzd-ai-cli 0.4.318 → 0.4.320
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/{batch-Y7IG5WTY.js → batch-LRYDPB6F.js} +2 -2
- package/dist/{chunk-VXQSMWXN.js → chunk-46M65JDN.js} +99 -62
- package/dist/{chunk-SPSFCJLM.js → chunk-4S2XD3M2.js} +4 -4
- package/dist/{chunk-ZXNQ37FB.js → chunk-5VZHSSLW.js} +1 -1
- package/dist/{chunk-DAWPHJSS.js → chunk-DB4HVUPI.js} +1 -1
- package/dist/{chunk-6VBW3L57.js → chunk-E2W2MI6H.js} +76 -6
- package/dist/{chunk-KPCXZJW2.js → chunk-J7IPNING.js} +1 -1
- package/dist/{chunk-IODFI5GY.js → chunk-N6YFBRQV.js} +28 -16
- package/dist/{chunk-TNEGZIP6.js → chunk-NOAWUEJJ.js} +28 -16
- package/dist/{chunk-BVEEA5BS.js → chunk-P4FJBD2H.js} +1 -1
- package/dist/{chunk-RB6FKHNZ.js → chunk-QB3MECZJ.js} +8 -8
- package/dist/{chunk-ZGIMXWXZ.js → chunk-SKQUWDRM.js} +1 -1
- package/dist/{chunk-7HX3FC67.js → chunk-TKBWA3XJ.js} +4 -4
- package/dist/{chunk-4MLOMT3W.js → chunk-WW2LFOWE.js} +1 -1
- package/dist/{chunk-APGWL4CQ.js → chunk-WY4IWCQ5.js} +1 -1
- package/dist/{chunk-MBI4RPRN.js → chunk-YAMPLTYO.js} +1 -1
- package/dist/{ci-XE42OB7U.js → ci-7TSOMDHV.js} +6 -6
- package/dist/{ci-format-IHLVLQ6B.js → ci-format-6A2RFYZS.js} +2 -2
- package/dist/{constants-HVWL645G.js → constants-EHYM2NS5.js} +1 -1
- package/dist/{constants-XUNVLHWI.js → constants-P33UDQVS.js} +1 -1
- package/dist/{doctor-cli-R3WQP5FD.js → doctor-cli-2B72UMZO.js} +6 -6
- package/dist/electron-server.js +180 -73
- package/dist/{hub-34YQNQF3.js → hub-JACLTKYY.js} +1 -1
- package/dist/index.js +45 -24
- package/dist/{persistent-memory-IUALAZ5K.js → persistent-memory-5ICLP275.js} +2 -2
- package/dist/{persistent-memory-VBVGH3P5.js → persistent-memory-ZIM6ICIR.js} +2 -2
- package/dist/{pr-QEQH3TAH.js → pr-UBGLNROK.js} +6 -6
- package/dist/{run-tests-OBX5CEPQ.js → run-tests-HCID73KE.js} +2 -2
- package/dist/{run-tests-L7FHOQAD.js → run-tests-SYJG4S3N.js} +2 -2
- package/dist/{server-ESLQPXVI.js → server-3UEEPEUD.js} +15 -15
- package/dist/{server-NBAC226K.js → server-BVTFIPB2.js} +6 -6
- package/dist/{task-orchestrator-2IKNOOMG.js → task-orchestrator-6NRCGF5V.js} +9 -7
- package/dist/{usage-B7TQHRIN.js → usage-6V64TTRE.js} +2 -2
- package/package.json +1 -1
package/dist/electron-server.js
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
touchMemoryReferences,
|
|
56
56
|
updateMemoryApproval,
|
|
57
57
|
updateMemoryEntry
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-WW2LFOWE.js";
|
|
59
59
|
import {
|
|
60
60
|
DEFAULT_PATTERNS,
|
|
61
61
|
redactJson,
|
|
@@ -77,10 +77,11 @@ import {
|
|
|
77
77
|
decodeWindowsBuffer,
|
|
78
78
|
killProcessTree,
|
|
79
79
|
looksLikeGbkMojibake,
|
|
80
|
+
posixShell,
|
|
80
81
|
recoverGbkMojibake,
|
|
81
82
|
runTestsTool,
|
|
82
83
|
shellInvocation
|
|
83
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-N6YFBRQV.js";
|
|
84
85
|
import {
|
|
85
86
|
getCurrentSessionKey,
|
|
86
87
|
getExecutionConfigDir,
|
|
@@ -122,7 +123,7 @@ import {
|
|
|
122
123
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
123
124
|
VERSION,
|
|
124
125
|
buildUserIdentityPrompt
|
|
125
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-SKQUWDRM.js";
|
|
126
127
|
|
|
127
128
|
// src/web/access.ts
|
|
128
129
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -1391,7 +1392,8 @@ function getDangerLevel(toolName, args) {
|
|
|
1391
1392
|
if (/\bgit\s+(?:clean\b|reset\s+--hard\b|push\b[^\n]*(?:--force\b|\s-f\b))/i.test(cmd)) return "destructive";
|
|
1392
1393
|
if (/\brm\s+[^\n]*(?:-\w*[rRfF]\w*|--recursive|--force)\b/.test(cmd)) return "destructive";
|
|
1393
1394
|
if (/\brm\s+\S/.test(cmd)) return "destructive";
|
|
1394
|
-
if (/\brmdir\b|\
|
|
1395
|
+
if (/\brmdir\b|\bmkfs\b|\bdd\s+if=|\bshred\b|\bfdisk\b|\bparted\b/.test(cmd)) return "destructive";
|
|
1396
|
+
if (/(?:^|[;&|(\n]\s*)format(?:\.com)?\s+[A-Za-z]:/im.test(cmd)) return "destructive";
|
|
1395
1397
|
if (/\bshutdown\b|\breboot\b|\bhalt\b|\bpoweroff\b/.test(cmd)) return "destructive";
|
|
1396
1398
|
if (/\bkill\s+-9\b|\bkillall\b/.test(cmd)) return "destructive";
|
|
1397
1399
|
if (/\bRemove-Item\b|\bri\s+\S/i.test(cmd)) return "destructive";
|
|
@@ -2431,6 +2433,14 @@ var HALLUCINATION_PATTERNS = [
|
|
|
2431
2433
|
// 已创建!
|
|
2432
2434
|
/File\s+(?:written|saved|created)\s+(?:to|as|at)/i,
|
|
2433
2435
|
// File written to / saved as(要求介词)
|
|
2436
|
+
// 2026-10-07 审计 B-02:中英文判据不对称。中文「已保存到」要求引号、英文只认 `File saved to`,
|
|
2437
|
+
// 于是「已保存到 report.md。」「I saved the changes to src/index.ts.」双双漏检。
|
|
2438
|
+
// 改为「后面跟一个带扩展名的文件名」——同样挡得住「已保存到数据库」「saved my time」这类误报。
|
|
2439
|
+
/已(?:保存|写入)到?\s*[^\s,,。;;::]{1,120}\.\w{1,6}(?![\w/])/,
|
|
2440
|
+
// 动词后直接跟文件名(中间只许冠词 / both / the file 之类),或「动词 … to/into 文件名」。
|
|
2441
|
+
// 刻意不放宽成「同句任意文件名」:「I saved you some time by checking README.md」不是写入声明。
|
|
2442
|
+
/\b(?:I|We)(?:'ve| have)?\s+(?:now\s+|just\s+|also\s+|successfully\s+)?(?:created|written|wrote|saved|generated)\s+(?:(?:the|a|an|both|all|two|three|new|following)\s+)*(?:(?:files?|documents?|reports?|scripts?)\s+)?[`'"]?[\w./-]+\.(?:md|txt|json|ya?ml|csv|html?|css|[jt]sx?|py|sh|go|rs|java|sql|xml|toml|ini|cfg|pdf|docx?|xlsx?|pptx?)\b/i,
|
|
2443
|
+
/\b(?:I|We)(?:'ve| have)?\s+(?:now\s+|just\s+|also\s+|successfully\s+)?(?:created|written|wrote|saved|generated)\b[^.\n]{0,40}?\b(?:to|into)\s+[`'"]?[\w./-]+\.(?:md|txt|json|ya?ml|csv|html?|css|[jt]sx?|py|sh|go|rs|java|sql|xml|toml|ini|cfg|pdf|docx?|xlsx?|pptx?)\b/i,
|
|
2434
2444
|
/生成完成[!!]/,
|
|
2435
2445
|
// 生成完成!
|
|
2436
2446
|
/✅\s*(?:文件|已[生保写创]|第)\S*\.\w{1,5}/,
|
|
@@ -2481,6 +2491,8 @@ var QUICK_WRITE_KEYWORDS = [
|
|
|
2481
2491
|
"saved",
|
|
2482
2492
|
"written",
|
|
2483
2493
|
"created",
|
|
2494
|
+
"wrote",
|
|
2495
|
+
"generated",
|
|
2484
2496
|
"File",
|
|
2485
2497
|
"file",
|
|
2486
2498
|
// emoji 勾选标记
|
|
@@ -2597,8 +2609,13 @@ function extractClaimedFilePaths(content) {
|
|
|
2597
2609
|
}
|
|
2598
2610
|
const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+\.\w{1,6})/g;
|
|
2599
2611
|
while ((m = zhRe.exec(content)) !== null) add(m[1]);
|
|
2600
|
-
const enRe =
|
|
2612
|
+
const enRe = /\b(?:saved|written|wrote|created)\b[^.\n]{0,40}?\b(?:to|as|at|into)\s+[`'”]?([^\s`'”\n,]+\.\w{1,6})/gi;
|
|
2601
2613
|
while ((m = enRe.exec(content)) !== null) add(m[1]);
|
|
2614
|
+
const enClaimRe = /\b(?:I|We)(?:'ve| have)?\s+(?:now\s+|just\s+|also\s+|successfully\s+)?(?:created|written|wrote|saved|generated)\b([^\n;]*)/gi;
|
|
2615
|
+
while ((m = enClaimRe.exec(content)) !== null) {
|
|
2616
|
+
const clause = m[1].split(/[.!?](?:\s|$)|\b(?:based on|from|using|per|according to|referencing|following|after|by|while|when|checking|reading|reviewing)\b/i)[0] ?? "";
|
|
2617
|
+
for (const f of clause.matchAll(/[`'"]?([\w./-]+\.\w{1,6})\b/g)) add(f[1]);
|
|
2618
|
+
}
|
|
2602
2619
|
const checkRe = /✅[^\n`]*?[`'”]?([^\s`'”\n,,。]+?\.\w{1,6})/g;
|
|
2603
2620
|
while ((m = checkRe.exec(content)) !== null) {
|
|
2604
2621
|
const pathStart = m.index + m[0].lastIndexOf(m[1]);
|
|
@@ -2873,8 +2890,27 @@ var META_NARRATION_HEURISTICS = [
|
|
|
2873
2890
|
/(?:我来|让我|容我)\s*(?:整理|梳理|归纳|想想|看看|重新|检查|核实)/u,
|
|
2874
2891
|
// 过渡语(需要 2+ hits):"以下是:" / "如下:" 作为独立行。文档中可作小节标题,
|
|
2875
2892
|
// 但配合另一个对话模式(如"好的")时是典型的 AI 内容包装。
|
|
2876
|
-
/^.{0,60}(?:以下是|下面是|如下)\s*[::,,]\s*$/mu
|
|
2893
|
+
/^.{0,60}(?:以下是|下面是|如下)\s*[::,,]\s*$/mu,
|
|
2894
|
+
// 叙述自己要调用工具(2026-10-07 审计 B-05):文档正文不会这样写自己。
|
|
2895
|
+
/(?:让我|我来|我将|我会|接下来)\s*(?:调用|使用|用)\s*`?\w+`?\s*工具/u,
|
|
2896
|
+
/\bI(?:'ll| will| am going to)\s+(?:now\s+)?(?:use|call|invoke)\s+the\s+`?\w+`?\s+tool\b/i
|
|
2897
|
+
];
|
|
2898
|
+
var ANNOUNCEMENT_PATTERNS = [
|
|
2899
|
+
/^\s*(?:好的|好|收到|明白|了解|嗯|OK|Okay|Sure|Certainly)[,,。.!!\s]/iu,
|
|
2900
|
+
/(?:我(?:这就|马上|现在|立即|立刻|来|将|会)|让我|下面我|接下来我)\s*(?:为[您你])?\s*(?:开始|着手|撰写|写|生成|整理|输出|编写|准备|调用|使用)/u,
|
|
2901
|
+
/(?:请稍[候等]|稍等|马上就好|这就开始)/u,
|
|
2902
|
+
/\b(?:let me|I(?:'ll| will| am going to)|I'm going to)\s+(?:now\s+)?(?:write|draft|generate|create|start|prepare|produce|compose|use|call)\b/i,
|
|
2903
|
+
/\b(?:please wait|one moment|stand by)\b/i
|
|
2877
2904
|
];
|
|
2905
|
+
function looksLikeAnnouncementOnly(content) {
|
|
2906
|
+
const text = content.trim();
|
|
2907
|
+
if (!text || text.length > 300 || text.split("\n").length > 4) return null;
|
|
2908
|
+
if (/^#{1,6}\s+\S/m.test(text)) return null;
|
|
2909
|
+
for (const re of ANNOUNCEMENT_PATTERNS) {
|
|
2910
|
+
if (re.test(text)) return re.source;
|
|
2911
|
+
}
|
|
2912
|
+
return null;
|
|
2913
|
+
}
|
|
2878
2914
|
var CHINESE_TAIL_CLOSING_MARKERS = [
|
|
2879
2915
|
/(?:需要你|请你|麻烦你|你看)\s*(?:确认|决定|选择|帮忙|看[一看下]|过目|觉得|认为)/u,
|
|
2880
2916
|
/(?:随时|有问题|有需要|需要调整|需要修改)\s*(?:联系|找我|告诉|沟通|调整|修改)/u,
|
|
@@ -3011,6 +3047,15 @@ This fresh stream has NO tools \u2014 output is captured verbatim. STOP emitting
|
|
|
3011
3047
|
summary: `[save_last_response REJECTED] The content-only stream produced NO text at all (output budget likely spent on reasoning). ${saveToFile} was NOT saved.`
|
|
3012
3048
|
};
|
|
3013
3049
|
}
|
|
3050
|
+
const announced = looksLikeAnnouncementOnly(rawContent);
|
|
3051
|
+
if (announced) {
|
|
3052
|
+
return fallback(`announcement only: ${announced}`) ?? {
|
|
3053
|
+
kind: "reject",
|
|
3054
|
+
reason: "not-a-document",
|
|
3055
|
+
matched: announced,
|
|
3056
|
+
summary: `[save_last_response REJECTED] The content-only stream produced only an announcement (e.g. "OK, I'll write the report now\u2026"), not the document itself. ${saveToFile} was NOT saved.`
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3014
3059
|
const { lines, bytes } = teeFileStats(rawContent);
|
|
3015
3060
|
return {
|
|
3016
3061
|
kind: "ok",
|
|
@@ -3032,6 +3077,7 @@ function teeStreamErrorSummary(saveToFile, errMsg) {
|
|
|
3032
3077
|
// src/core/stalled-intent.ts
|
|
3033
3078
|
var WAITING_FOR_USER_RE = /[??]\s*$|是否|要不要|需不需要|需要我|要我|可以吗|好吗|行吗|您看|你看看|请确认|确认后|同意后|如果(?:你|您)|若(?:你|您)|如(?:你|您)需要|等你|等待(?:你|您)|待(?:你|您)|我可以|我也可以|还可以|(?:你|您)可以|告诉我|或者(?:让我|我)|可以为(?:你|您)|可以帮|随时|\bwould you\b|\bshall i\b|\bshould i\b|\bdo you want\b|\blet me know\b|\bif you(?:'d| would)? like\b|\bonce you confirm\b|\byour (?:approval|confirmation)\b|\bif you want\b|\bi can also\b/i;
|
|
3034
3079
|
var COMPLETED_RE = /已|完成|好了|完毕|写好|搞定|\b(?:done|finished|completed|have (?:written|created|generated))\b/i;
|
|
3080
|
+
var NEGATION_RE = /没有?|未|无法|不(?:会|能|再|打算|需要|用|必|要)|n't\b|\b(?:not|never|no longer|cannot)\b/i;
|
|
3035
3081
|
var CN_VERBS = "\u5F00\u5199|\u52A8\u624B|\u7F16\u5199|\u5199\u5165|\u5199|\u751F\u6210|\u521B\u5EFA|\u5236\u4F5C|\u6267\u884C|\u8FD0\u884C|\u5B89\u88C5|\u4FEE\u6539|\u66F4\u65B0|\u4FEE\u590D|\u5B9E\u73B0|\u6784\u5EFA|\u8F93\u51FA|\u4FDD\u5B58|\u8BFB\u53D6|\u67E5\u770B|\u68C0\u67E5|\u8C03\u7528|\u5904\u7406|\u6574\u7406|\u8865\u5145|\u5B8C\u5584|\u91CD\u5199|\u6539\u5199|\u843D\u76D8";
|
|
3036
3082
|
var CN_FIRST_PERSON_INTENT_RE = new RegExp(
|
|
3037
3083
|
`(?:\u6211|\u54B1\u4EEC|\u6211\u4EEC|\u8BA9\u6211)(?:\u73B0\u5728|\u8FD9\u5C31|\u9A6C\u4E0A|\u7ACB\u5373|\u7ACB\u523B|\u76F4\u63A5|\u63A5\u4E0B\u6765|\u4E0B\u9762|\u5148|\u518D|\u968F\u540E|\u7136\u540E|\u5C31)*(?:\u5C06|\u4F1A|\u8981|\u6765|\u53BB|\u5F00\u59CB|\u7740\u624B|\u51C6\u5907)?(?:[^\uFF0C,\u3002\uFF01!\uFF1B;\uFF1A:\\n]{0,4})?(?:${CN_VERBS})`
|
|
@@ -3053,11 +3099,11 @@ function detectStalledIntent(content) {
|
|
|
3053
3099
|
if (WAITING_FOR_USER_RE.test(tail)) return null;
|
|
3054
3100
|
const clauses = tail.split(/[,,;;。!!::\n]/).map((c) => c.trim()).filter(Boolean);
|
|
3055
3101
|
for (const clause of clauses) {
|
|
3056
|
-
if (COMPLETED_RE.test(clause)) continue;
|
|
3102
|
+
if (COMPLETED_RE.test(clause) || NEGATION_RE.test(clause)) continue;
|
|
3057
3103
|
if (CN_FIRST_PERSON_INTENT_RE.test(clause) || CN_BARE_INTENT_RE.test(clause)) return clause;
|
|
3058
3104
|
}
|
|
3059
3105
|
for (const sentence of tail.split(/(?<=[.!])\s+|\n/)) {
|
|
3060
|
-
if (COMPLETED_RE.test(sentence)) continue;
|
|
3106
|
+
if (COMPLETED_RE.test(sentence) || NEGATION_RE.test(sentence)) continue;
|
|
3061
3107
|
const m = EN_INTENT_RE.exec(sentence);
|
|
3062
3108
|
if (m) return sentence.trim();
|
|
3063
3109
|
}
|
|
@@ -3505,7 +3551,12 @@ async function runAgentLoop(host) {
|
|
|
3505
3551
|
if (tc.name.startsWith("mcp__")) host.onMcpToolUsed?.(tc.name);
|
|
3506
3552
|
}
|
|
3507
3553
|
host.persistRound?.(toolCalls, toolResults, {
|
|
3508
|
-
|
|
3554
|
+
// 工具调用前模型说的话("A 方向汇报:…"、"先看一下配置")挂在 _streamedText 上:
|
|
3555
|
+
// 本轮上下文里有(buildToolResultMessages 会带上),但此前存档只取 outcome.content,
|
|
3556
|
+
// 而工具调用轮次的 outcome 没有 content——2026-10-07 审计会话 157 条带工具调用的
|
|
3557
|
+
// assistant 消息正文**全部为空**:下一条用户消息时模型看不到自己之前的阶段性汇报,
|
|
3558
|
+
// /session show、导出、回放也全缺这部分(审计 X-01)。
|
|
3559
|
+
assistantContent: outcome.content ?? toolCalls._streamedText,
|
|
3509
3560
|
reasoningContent: outcome.reasoningContent
|
|
3510
3561
|
});
|
|
3511
3562
|
host.afterToolRoundPersist?.(toolCalls, toolResults, extraMessages);
|
|
@@ -3560,6 +3611,7 @@ async function runLeanAgentLoop(opts) {
|
|
|
3560
3611
|
let roundsUsed = 0;
|
|
3561
3612
|
let toolCallCount = 0;
|
|
3562
3613
|
let stalledIntentNudges = 0;
|
|
3614
|
+
let hallucinationRetries = 0;
|
|
3563
3615
|
try {
|
|
3564
3616
|
for (let round = 0; round < opts.maxRounds; round++) {
|
|
3565
3617
|
roundsUsed = round + 1;
|
|
@@ -3575,6 +3627,7 @@ async function runLeanAgentLoop(opts) {
|
|
|
3575
3627
|
timeout: opts.chatParams?.timeout,
|
|
3576
3628
|
thinking: opts.chatParams?.thinking,
|
|
3577
3629
|
thinkingEffort: opts.chatParams?.thinkingEffort,
|
|
3630
|
+
thinkingBudget: opts.chatParams?.thinkingBudget,
|
|
3578
3631
|
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
3579
3632
|
},
|
|
3580
3633
|
opts.toolDefsForRound(round)
|
|
@@ -3594,6 +3647,24 @@ async function runLeanAgentLoop(opts) {
|
|
|
3594
3647
|
);
|
|
3595
3648
|
continue;
|
|
3596
3649
|
}
|
|
3650
|
+
const nextTools = round < opts.maxRounds - 1 ? opts.toolDefsForRound(round + 1) : [];
|
|
3651
|
+
const canWrite = nextTools.some((t) => t.name === "write_file" || t.name === "edit_file");
|
|
3652
|
+
if (canWrite && hallucinationRetries < 1 && result.content) {
|
|
3653
|
+
const alreadyWrote = hadPreviousWriteToolCalls(extraMessages);
|
|
3654
|
+
const coarse = !alreadyWrote && detectsHallucinatedFileOp(result.content) && extractBashCommands(extraMessages).length === 0;
|
|
3655
|
+
const phantom = coarse || alreadyWrote ? findPhantomClaims(result.content, extraMessages) : [];
|
|
3656
|
+
if (phantom.length > 0 || coarse) {
|
|
3657
|
+
hallucinationRetries++;
|
|
3658
|
+
extraMessages.push(
|
|
3659
|
+
{ role: "assistant", content: result.content },
|
|
3660
|
+
{
|
|
3661
|
+
role: "user",
|
|
3662
|
+
content: phantom.length > 0 ? buildPhantomCorrectionMessage(phantom) : HALLUCINATION_CORRECTION_MESSAGE
|
|
3663
|
+
}
|
|
3664
|
+
);
|
|
3665
|
+
continue;
|
|
3666
|
+
}
|
|
3667
|
+
}
|
|
3597
3668
|
content = result.content;
|
|
3598
3669
|
break;
|
|
3599
3670
|
}
|
|
@@ -6082,7 +6153,7 @@ var undoStack = new UndoStack();
|
|
|
6082
6153
|
import { spawn } from "child_process";
|
|
6083
6154
|
import { platform } from "os";
|
|
6084
6155
|
var IS_WINDOWS2 = platform() === "win32";
|
|
6085
|
-
var SHELL = IS_WINDOWS2 ? "powershell.exe" :
|
|
6156
|
+
var SHELL = IS_WINDOWS2 ? "powershell.exe" : posixShell();
|
|
6086
6157
|
var pool = /* @__PURE__ */ new Map();
|
|
6087
6158
|
var IDLE_EVICT_MS = 5 * 6e4;
|
|
6088
6159
|
var evictionTimer = null;
|
|
@@ -6091,7 +6162,11 @@ function spawnShell(cwd) {
|
|
|
6091
6162
|
const proc = spawn(SHELL, shellArgs, {
|
|
6092
6163
|
cwd,
|
|
6093
6164
|
windowsHide: true,
|
|
6094
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
6165
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
6166
|
+
// POSIX: own process group, so a timeout / Ctrl+C can kill the whole tree
|
|
6167
|
+
// (killProcessTree with processGroup=true). Without it only the shell host
|
|
6168
|
+
// died and grandchildren were orphaned (2026-10-07 audit A-01).
|
|
6169
|
+
detached: !IS_WINDOWS2
|
|
6095
6170
|
});
|
|
6096
6171
|
proc.on("exit", () => {
|
|
6097
6172
|
for (const [key, entry] of pool) {
|
|
@@ -6118,13 +6193,17 @@ function startEvictionTimer() {
|
|
|
6118
6193
|
}
|
|
6119
6194
|
}, 6e4).unref();
|
|
6120
6195
|
}
|
|
6196
|
+
function stderrMarker(id) {
|
|
6197
|
+
return `AICLI_MARKER_ERR:${id}`;
|
|
6198
|
+
}
|
|
6121
6199
|
function buildWrappedCommand(command, id, isWindows) {
|
|
6122
6200
|
const markerStart = `AICLI_MARKER_START:${id}`;
|
|
6123
6201
|
const markerEnd = `AICLI_MARKER_END:${id}`;
|
|
6124
6202
|
if (!isWindows) {
|
|
6203
|
+
const quoted = `'${command.replace(/'/g, `'\\''`)}'`;
|
|
6125
6204
|
return `echo "${markerStart}"
|
|
6126
|
-
${
|
|
6127
|
-
echo "${markerEnd}
|
|
6205
|
+
eval ${quoted} </dev/null
|
|
6206
|
+
__aicli_rc=$?; echo "${stderrMarker(id)}" >&2; echo "${markerEnd}:$__aicli_rc"`;
|
|
6128
6207
|
}
|
|
6129
6208
|
const b64 = Buffer.from(command, "utf-8").toString("base64");
|
|
6130
6209
|
const decoded = `[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}'))`;
|
|
@@ -6156,32 +6235,46 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
6156
6235
|
const markerStartPattern = `AICLI_MARKER_START:${id}`;
|
|
6157
6236
|
const markerEndPattern = `AICLI_MARKER_END:${id}`;
|
|
6158
6237
|
const proc = entry.proc;
|
|
6238
|
+
const errMarker = stderrMarker(id);
|
|
6239
|
+
const cleanStderr = (s) => {
|
|
6240
|
+
const i = s.indexOf(errMarker);
|
|
6241
|
+
return i < 0 ? s : s.slice(0, i);
|
|
6242
|
+
};
|
|
6243
|
+
const checkDone = () => {
|
|
6244
|
+
if (resolved) return;
|
|
6245
|
+
const parsed = extractPoolOutput(stdout, markerStartPattern, markerEndPattern);
|
|
6246
|
+
if (parsed.exitCode === null) return;
|
|
6247
|
+
if (!IS_WINDOWS2 && !stderr.includes(errMarker)) return;
|
|
6248
|
+
stdout = parsed.output;
|
|
6249
|
+
stderr = cleanStderr(stderr);
|
|
6250
|
+
resolved = true;
|
|
6251
|
+
cleanup();
|
|
6252
|
+
resolve13({ stdout, stderr, exitCode: parsed.exitCode, timedOut, aborted });
|
|
6253
|
+
};
|
|
6159
6254
|
const onData = (chunk) => {
|
|
6160
6255
|
stdout += IS_WINDOWS2 ? decodeWindowsBuffer(chunk) : chunk.toString("utf-8");
|
|
6161
|
-
|
|
6162
|
-
const endLine = stdout.split("\n").find((l) => l.includes(markerEndPattern));
|
|
6163
|
-
const exitCode = endLine ? parseEndMarker(endLine) : null;
|
|
6164
|
-
stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
|
|
6165
|
-
resolved = true;
|
|
6166
|
-
cleanup();
|
|
6167
|
-
resolve13({ stdout, stderr, exitCode, timedOut, aborted });
|
|
6168
|
-
}
|
|
6256
|
+
checkDone();
|
|
6169
6257
|
};
|
|
6170
6258
|
const onErr = (chunk) => {
|
|
6171
6259
|
stderr += IS_WINDOWS2 ? decodeWindowsBuffer(chunk) : chunk.toString("utf-8");
|
|
6260
|
+
checkDone();
|
|
6172
6261
|
};
|
|
6173
6262
|
const finishPoolFailure = (message, exitCode = null) => {
|
|
6174
6263
|
if (resolved) return;
|
|
6175
6264
|
resolved = true;
|
|
6176
|
-
stdout =
|
|
6265
|
+
stdout = extractPoolOutput(stdout, markerStartPattern, markerEndPattern).output;
|
|
6266
|
+
stderr = cleanStderr(stderr);
|
|
6177
6267
|
stderr += `${stderr ? "\n" : ""}[pool terminated] ${message}`;
|
|
6178
6268
|
cleanup();
|
|
6179
6269
|
pool.delete(sessionKey);
|
|
6180
|
-
resolve13({ stdout, stderr, exitCode
|
|
6270
|
+
resolve13({ stdout, stderr, exitCode, timedOut, aborted });
|
|
6181
6271
|
};
|
|
6182
6272
|
const onClose = (code, signal) => {
|
|
6183
6273
|
const detail = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
|
|
6184
|
-
finishPoolFailure(
|
|
6274
|
+
finishPoolFailure(
|
|
6275
|
+
`The shell exited before the command finished (${detail}) \u2014 typically an explicit \`exit\`/\`exec\`, or \`set -e\` aborting on a failing command. Shell state (variables, options, functions) was reset; the next command runs in a fresh shell in the same directory.`,
|
|
6276
|
+
signal ? null : code
|
|
6277
|
+
);
|
|
6185
6278
|
};
|
|
6186
6279
|
const onStdinError = (err) => {
|
|
6187
6280
|
finishPoolFailure(`Shell stdin failed: ${err.message}`);
|
|
@@ -6194,10 +6287,11 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
6194
6287
|
if (resolved) return;
|
|
6195
6288
|
timedOut = true;
|
|
6196
6289
|
resolved = true;
|
|
6197
|
-
stdout =
|
|
6290
|
+
stdout = extractPoolOutput(stdout, markerStartPattern, markerEndPattern).output;
|
|
6291
|
+
stderr = cleanStderr(stderr);
|
|
6198
6292
|
cleanup();
|
|
6199
6293
|
resolve13({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
6200
|
-
killProcessTree(proc);
|
|
6294
|
+
killProcessTree(proc, true);
|
|
6201
6295
|
pool.delete(sessionKey);
|
|
6202
6296
|
}, timeout);
|
|
6203
6297
|
const onAbort = () => {
|
|
@@ -6205,9 +6299,10 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
6205
6299
|
aborted = true;
|
|
6206
6300
|
resolved = true;
|
|
6207
6301
|
cleanup();
|
|
6208
|
-
stdout =
|
|
6302
|
+
stdout = extractPoolOutput(stdout, markerStartPattern, markerEndPattern).output;
|
|
6303
|
+
stderr = cleanStderr(stderr);
|
|
6209
6304
|
resolve13({ stdout, stderr, exitCode: null, timedOut, aborted });
|
|
6210
|
-
killProcessTree(proc);
|
|
6305
|
+
killProcessTree(proc, true);
|
|
6211
6306
|
pool.delete(sessionKey);
|
|
6212
6307
|
};
|
|
6213
6308
|
if (abortSignal?.aborted) {
|
|
@@ -6239,36 +6334,18 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
|
|
|
6239
6334
|
}
|
|
6240
6335
|
});
|
|
6241
6336
|
}
|
|
6242
|
-
function
|
|
6243
|
-
const
|
|
6244
|
-
|
|
6245
|
-
const
|
|
6246
|
-
|
|
6337
|
+
function extractPoolOutput(stdout, startMarker, endMarker) {
|
|
6338
|
+
const startMatch = new RegExp(`${escapeRegExp(startMarker)}\\r?\\n`).exec(stdout);
|
|
6339
|
+
const bodyStart = startMatch ? startMatch.index + startMatch[0].length : 0;
|
|
6340
|
+
const endMatch = new RegExp(`${escapeRegExp(endMarker)}:(\\d+)\\r?\\n`).exec(stdout.slice(bodyStart));
|
|
6341
|
+
const body = endMatch ? stdout.slice(bodyStart, bodyStart + endMatch.index) : stdout.slice(bodyStart);
|
|
6342
|
+
return {
|
|
6343
|
+
output: body.trim(),
|
|
6344
|
+
exitCode: endMatch ? Number(endMatch[1]) : null
|
|
6345
|
+
};
|
|
6247
6346
|
}
|
|
6248
|
-
function
|
|
6249
|
-
|
|
6250
|
-
let capturing = false;
|
|
6251
|
-
const out = [];
|
|
6252
|
-
for (const line of lines) {
|
|
6253
|
-
if (line.includes(startMarker)) {
|
|
6254
|
-
capturing = true;
|
|
6255
|
-
continue;
|
|
6256
|
-
}
|
|
6257
|
-
if (line.includes(endMarker)) {
|
|
6258
|
-
capturing = false;
|
|
6259
|
-
continue;
|
|
6260
|
-
}
|
|
6261
|
-
if (capturing) {
|
|
6262
|
-
out.push(line);
|
|
6263
|
-
}
|
|
6264
|
-
}
|
|
6265
|
-
if (!stdout.includes(endMarker) && out.length === 0) {
|
|
6266
|
-
const startIdx = stdout.indexOf(startMarker);
|
|
6267
|
-
if (startIdx >= 0) {
|
|
6268
|
-
return stdout.slice(startIdx + startMarker.length).trimStart();
|
|
6269
|
-
}
|
|
6270
|
-
}
|
|
6271
|
-
return out.join("\n").trim();
|
|
6347
|
+
function escapeRegExp(s) {
|
|
6348
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6272
6349
|
}
|
|
6273
6350
|
function cleanupPoolSession(sessionKey) {
|
|
6274
6351
|
const entry = pool.get(sessionKey);
|
|
@@ -6282,7 +6359,7 @@ function cleanupPoolSession(sessionKey) {
|
|
|
6282
6359
|
|
|
6283
6360
|
// src/tools/builtin/bash.ts
|
|
6284
6361
|
var IS_WINDOWS3 = platform2() === "win32";
|
|
6285
|
-
var SHELL2 = IS_WINDOWS3 ? "powershell.exe" :
|
|
6362
|
+
var SHELL2 = IS_WINDOWS3 ? "powershell.exe" : posixShell();
|
|
6286
6363
|
var cwdBySession = /* @__PURE__ */ new Map();
|
|
6287
6364
|
function getCwd() {
|
|
6288
6365
|
const key = getCurrentSessionKey();
|
|
@@ -6411,7 +6488,8 @@ Important rules:
|
|
|
6411
6488
|
}
|
|
6412
6489
|
if (timedOut) {
|
|
6413
6490
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
6414
|
-
throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT, command
|
|
6491
|
+
throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT, command, `${stdout}
|
|
6492
|
+
${stderr}`));
|
|
6415
6493
|
}
|
|
6416
6494
|
if (status !== 0 || timedOut) {
|
|
6417
6495
|
const poolStdout = (stdout ?? "").trim();
|
|
@@ -6430,7 +6508,12 @@ ${combined || formatFailureFallback(status)}
|
|
|
6430
6508
|
}
|
|
6431
6509
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
6432
6510
|
updateCwdFromCommand(command, effectiveCwd);
|
|
6433
|
-
|
|
6511
|
+
const out = annotateSuccessOutput(command, suppressBinaryOutput(stdout));
|
|
6512
|
+
const poolNote = /\[pool terminated\]/.test(stderr ?? "") ? `
|
|
6513
|
+
|
|
6514
|
+
${(stderr ?? "").trim()}` : "";
|
|
6515
|
+
const body = out ? out + poolNote : emptyOutputResult(command, stderr ?? "");
|
|
6516
|
+
return body + backgroundJobNote(command);
|
|
6434
6517
|
}
|
|
6435
6518
|
try {
|
|
6436
6519
|
const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
|
|
@@ -6467,17 +6550,18 @@ ${combined || formatFailureFallback(status)}
|
|
|
6467
6550
|
updateCwdFromCommand(command, effectiveCwd);
|
|
6468
6551
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
6469
6552
|
const result = Buffer.isBuffer(stdout) ? IS_WINDOWS3 ? decodeWindowsBuffer(stdout) : stdout.toString("utf-8") : String(stdout ?? "");
|
|
6470
|
-
return annotateSuccessOutput(command, result) || emptyOutputResult(
|
|
6553
|
+
return (annotateSuccessOutput(command, suppressBinaryOutput(result)) || emptyOutputResult(
|
|
6471
6554
|
command,
|
|
6472
6555
|
Buffer.isBuffer(stderr) ? IS_WINDOWS3 ? decodeWindowsBuffer(stderr) : stderr.toString("utf-8") : String(stderr ?? "")
|
|
6473
|
-
);
|
|
6556
|
+
)) + backgroundJobNote(command);
|
|
6474
6557
|
} catch (err) {
|
|
6475
6558
|
pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
|
|
6476
6559
|
if (err && typeof err === "object") {
|
|
6477
6560
|
const execErr = err;
|
|
6478
6561
|
const isTimeout = execErr.code === "ETIMEDOUT" || execErr.status == null && execErr.signal === "SIGTERM" || /ETIMEDOUT/i.test(execErr.message ?? "");
|
|
6479
6562
|
if (isTimeout) {
|
|
6480
|
-
|
|
6563
|
+
const captured = [execErr.stdout, execErr.stderr].map((b) => Buffer.isBuffer(b) ? IS_WINDOWS3 ? decodeWindowsBuffer(b) : b.toString("utf-8") : String(b ?? "")).join("\n");
|
|
6564
|
+
throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT, command, captured));
|
|
6481
6565
|
}
|
|
6482
6566
|
if ("status" in execErr && execErr.status !== void 0) {
|
|
6483
6567
|
const stderr = IS_WINDOWS3 && Buffer.isBuffer(execErr.stderr) ? decodeWindowsBuffer(execErr.stderr).trim() : execErr.stderr?.toString().trim() ?? "";
|
|
@@ -6510,8 +6594,15 @@ function looksLikeTestCommand(command) {
|
|
|
6510
6594
|
/(?:^|[;&|(\s])(?:go|cargo)\s+test\b/.test(command)
|
|
6511
6595
|
);
|
|
6512
6596
|
}
|
|
6513
|
-
|
|
6597
|
+
var TIMEOUT_CAPTURE_MAX = 2e3;
|
|
6598
|
+
function formatTimeoutMessage(timeout, maxTimeout, command, captured) {
|
|
6514
6599
|
const seconds = Math.round(timeout / 1e3);
|
|
6600
|
+
const tail = (captured ?? "").trim();
|
|
6601
|
+
const capturedSection = tail ? [
|
|
6602
|
+
"Output captured before the timeout (last part \u2014 the cause is often here):",
|
|
6603
|
+
tail.length > TIMEOUT_CAPTURE_MAX ? "\u2026" + tail.slice(-TIMEOUT_CAPTURE_MAX) : tail,
|
|
6604
|
+
""
|
|
6605
|
+
] : [];
|
|
6515
6606
|
const testRunnerHint = command !== void 0 && looksLikeTestCommand(command) ? [
|
|
6516
6607
|
"This looks like a TEST run. Prefer the 'run_tests' tool instead of running the test runner through bash: it has a 5-minute timeout, auto-detects the framework, and returns a structured summary (no findstr/grep filtering needed).",
|
|
6517
6608
|
""
|
|
@@ -6519,6 +6610,7 @@ function formatTimeoutMessage(timeout, maxTimeout, command) {
|
|
|
6519
6610
|
return [
|
|
6520
6611
|
`Command timed out after ${seconds}s.`,
|
|
6521
6612
|
"",
|
|
6613
|
+
...capturedSection,
|
|
6522
6614
|
...testRunnerHint,
|
|
6523
6615
|
"The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.",
|
|
6524
6616
|
"",
|
|
@@ -6691,6 +6783,19 @@ ${err}`;
|
|
|
6691
6783
|
return detectPowerShellBackslashQuote(command) ? base + BACKSLASH_QUOTE_SILENT_WARNING : base;
|
|
6692
6784
|
}
|
|
6693
6785
|
var PS_TEXT_READ_CMDLET = /\b(?:Get-Content|gc|cat|type|Select-String|sls|Import-Csv)\b/i;
|
|
6786
|
+
function suppressBinaryOutput(stdout) {
|
|
6787
|
+
if (!stdout) return stdout;
|
|
6788
|
+
const sample = stdout.slice(0, 8e3);
|
|
6789
|
+
const replacement = (sample.match(/\uFFFD/g) ?? []).length;
|
|
6790
|
+
if (!sample.includes("\0") && !(sample.length >= 64 && replacement / sample.length > 0.3)) {
|
|
6791
|
+
return stdout;
|
|
6792
|
+
}
|
|
6793
|
+
return `[binary output suppressed: ${Buffer.byteLength(stdout, "utf-8")} bytes. Inspect it with a hex dump limited in size (e.g. \`xxd file | head -20\`), or use \`file\` to identify the type.]`;
|
|
6794
|
+
}
|
|
6795
|
+
function backgroundJobNote(command) {
|
|
6796
|
+
if (IS_WINDOWS3 || !/(?:^|\s)&(?![&>])/m.test(command)) return "";
|
|
6797
|
+
return "\n\n[Note: this command started a background job (`&`). It is not tracked by aicli \u2014 task_list/task_stop cannot see it and it keeps running after this session. For long-running processes (dev servers, watchers) prefer task_create.]";
|
|
6798
|
+
}
|
|
6694
6799
|
function annotateSuccessOutput(command, stdout) {
|
|
6695
6800
|
if (!IS_WINDOWS3 || !PS_TEXT_READ_CMDLET.test(command)) return stdout;
|
|
6696
6801
|
if (!looksLikeGbkMojibake(stdout)) return stdout;
|
|
@@ -6868,7 +6973,9 @@ function runShell(command, opts) {
|
|
|
6868
6973
|
cwd: opts.cwd,
|
|
6869
6974
|
env: opts.env,
|
|
6870
6975
|
windowsHide: true,
|
|
6871
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
6976
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6977
|
+
// POSIX: own process group so killChild can take the whole tree down (A-01).
|
|
6978
|
+
detached: !IS_WINDOWS3
|
|
6872
6979
|
});
|
|
6873
6980
|
const stdoutChunks = [];
|
|
6874
6981
|
const stderrChunks = [];
|
|
@@ -6925,7 +7032,7 @@ function runShell(command, opts) {
|
|
|
6925
7032
|
});
|
|
6926
7033
|
}
|
|
6927
7034
|
function killChild(child) {
|
|
6928
|
-
killProcessTree(child);
|
|
7035
|
+
killProcessTree(child, true);
|
|
6929
7036
|
}
|
|
6930
7037
|
function updateCwdFromCommand(command, baseCwd) {
|
|
6931
7038
|
const cdMatches = [...command.matchAll(/(?:^|[;&|])\s*cd\s+(['"]?)([^\s;&|'"]+)\1/g)];
|
|
@@ -17488,7 +17595,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
17488
17595
|
Cost: ${formatCost(cost)}` : "";
|
|
17489
17596
|
let memoryLine = "";
|
|
17490
17597
|
try {
|
|
17491
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
17598
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-ZIM6ICIR.js");
|
|
17492
17599
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
17493
17600
|
if (pending > 0) memoryLine = `
|
|
17494
17601
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -18476,7 +18583,7 @@ async function handleTest(args, ctx) {
|
|
|
18476
18583
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
18477
18584
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
18478
18585
|
}
|
|
18479
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
18586
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-HCID73KE.js")).executeTests;
|
|
18480
18587
|
const report = await runTests(testArgs);
|
|
18481
18588
|
ctx.send({ type: "info", message: report });
|
|
18482
18589
|
} catch (err) {
|
|
@@ -18867,7 +18974,7 @@ async function handleMemory(args, ctx) {
|
|
|
18867
18974
|
}
|
|
18868
18975
|
if (intent.kind === "status") {
|
|
18869
18976
|
const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-RLVLQRRC.js");
|
|
18870
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
18977
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-ZIM6ICIR.js");
|
|
18871
18978
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
18872
18979
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
18873
18980
|
const view = buildMemoryStatusView({
|
|
@@ -18890,7 +18997,7 @@ async function handleMemory(args, ctx) {
|
|
|
18890
18997
|
return;
|
|
18891
18998
|
}
|
|
18892
18999
|
if (intent.kind === "recall") {
|
|
18893
|
-
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-
|
|
19000
|
+
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-ZIM6ICIR.js");
|
|
18894
19001
|
const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-RLVLQRRC.js");
|
|
18895
19002
|
const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
|
|
18896
19003
|
if (persistentHits.length > 0) {
|
|
@@ -19011,7 +19118,7 @@ async function handleMemory(args, ctx) {
|
|
|
19011
19118
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
19012
19119
|
} else if (intent.kind === "export") {
|
|
19013
19120
|
if (args[1] === "md") {
|
|
19014
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
19121
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-ZIM6ICIR.js");
|
|
19015
19122
|
ctx.send({
|
|
19016
19123
|
type: "export_data",
|
|
19017
19124
|
format: "md",
|
|
@@ -20016,7 +20123,7 @@ No tools match "${filter}".
|
|
|
20016
20123
|
const { join: join26 } = await import("path");
|
|
20017
20124
|
const { existsSync: existsSync32 } = await import("fs");
|
|
20018
20125
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
|
|
20019
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
20126
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-EHYM2NS5.js");
|
|
20020
20127
|
const { approveProject, hashMcpFile } = await import("./project-trust-6CJB5ZMX.js");
|
|
20021
20128
|
const cwd = process.cwd();
|
|
20022
20129
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -20935,7 +21042,7 @@ function createReviewCommands() {
|
|
|
20935
21042
|
usage: "/test [command|filter]",
|
|
20936
21043
|
async execute(args, ctx) {
|
|
20937
21044
|
try {
|
|
20938
|
-
const { executeTests } = await import("./run-tests-
|
|
21045
|
+
const { executeTests } = await import("./run-tests-HCID73KE.js");
|
|
20939
21046
|
const argStr = args.join(" ").trim();
|
|
20940
21047
|
let testArgs = {};
|
|
20941
21048
|
if (argStr) {
|
|
@@ -158,7 +158,7 @@ ${content}`);
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
async function runTaskMode(config, providers, configManager, topic) {
|
|
161
|
-
const { TaskOrchestrator } = await import("./task-orchestrator-
|
|
161
|
+
const { TaskOrchestrator } = await import("./task-orchestrator-6NRCGF5V.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|