jinzd-ai-cli 0.4.319 → 0.4.321
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-CQ542WJF.js → batch-EW6QTSE6.js} +2 -2
- package/dist/{chunk-D6BLSFYD.js → chunk-2GOBINY4.js} +4 -4
- package/dist/{chunk-A7YZLLWN.js → chunk-2R6Y5SJH.js} +1 -1
- package/dist/{chunk-2PAQOR2X.js → chunk-4MO2I5JB.js} +9 -9
- package/dist/{chunk-YHMQMP2I.js → chunk-6RCGQQFM.js} +57 -20
- package/dist/{chunk-Y3SEC5EC.js → chunk-6XXHAS5B.js} +1 -1
- package/dist/{chunk-GP24X3KJ.js → chunk-7QW3DFYV.js} +1 -1
- package/dist/{chunk-KEOMNFBH.js → chunk-COHKPZ2E.js} +1 -1
- package/dist/{chunk-GVAAGBHX.js → chunk-E2W2MI6H.js} +74 -5
- package/dist/{chunk-PGQ5OV3P.js → chunk-I3GEFCKP.js} +1 -1
- package/dist/{chunk-AC44E4CV.js → chunk-JHSULP5D.js} +1 -1
- package/dist/{chunk-OQZIP4LU.js → chunk-LEA4AMXE.js} +1 -1
- package/dist/{chunk-46OEMKQX.js → chunk-NFPJ6KUU.js} +8 -4
- package/dist/{chunk-DCQDFQDW.js → chunk-VEO2MILP.js} +1 -1
- package/dist/{chunk-662ZJPJE.js → chunk-VS43QMR2.js} +1 -1
- package/dist/{chunk-N2MHUA4B.js → chunk-XVB4RARX.js} +75 -2
- package/dist/{chunk-SZBSTSG4.js → chunk-ZDO3XCXL.js} +4 -4
- package/dist/{ci-HAPWBC37.js → ci-EZZD7CMS.js} +6 -6
- package/dist/{ci-format-NGWP4GTQ.js → ci-format-ZWECV6XI.js} +2 -2
- package/dist/{constants-GSUK6ILC.js → constants-F2ULZ6W2.js} +1 -1
- package/dist/{constants-CPHZLOCQ.js → constants-HF5AYLBR.js} +1 -1
- package/dist/{doctor-cli-L6AK2GJ7.js → doctor-cli-QAKYBWLG.js} +6 -6
- package/dist/electron-server.js +218 -35
- package/dist/{hub-TCZFG2ZG.js → hub-OYH2UGER.js} +1 -1
- package/dist/index.js +56 -26
- package/dist/{persistent-memory-IPNMYXU4.js → persistent-memory-EVZX7SLR.js} +2 -2
- package/dist/{persistent-memory-E3UYP7RJ.js → persistent-memory-WNPZSVE4.js} +2 -2
- package/dist/{pr-J5TSU5P6.js → pr-XPQVXG2G.js} +6 -6
- package/dist/{run-tests-PDD4KUQL.js → run-tests-3SYXE2PJ.js} +2 -2
- package/dist/{run-tests-FLGSE63O.js → run-tests-MFXQ76ZJ.js} +2 -2
- package/dist/{server-3C6IK3JE.js → server-AF5PIBUD.js} +6 -6
- package/dist/{server-XQ3IQUZ5.js → server-VOGBRYA5.js} +16 -16
- package/dist/{task-orchestrator-544JETWF.js → task-orchestrator-QHJEDRDS.js} +9 -7
- package/dist/{usage-MQTA7HHZ.js → usage-EZOW27TR.js} +3 -3
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
evaluateCiGate,
|
|
4
4
|
normalizeCiThresholds
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LEA4AMXE.js";
|
|
6
6
|
import {
|
|
7
7
|
buildReviewPrompt,
|
|
8
8
|
buildSecurityReviewPrompt,
|
|
@@ -13,13 +13,13 @@ import {
|
|
|
13
13
|
} from "./chunk-6YZEZFX5.js";
|
|
14
14
|
import {
|
|
15
15
|
ProviderRegistry
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-XVB4RARX.js";
|
|
17
17
|
import {
|
|
18
18
|
ConfigManager
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-COHKPZ2E.js";
|
|
20
20
|
import {
|
|
21
21
|
VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-2R6Y5SJH.js";
|
|
23
23
|
|
|
24
24
|
// src/cli/ci.ts
|
|
25
25
|
import { execFileSync } from "child_process";
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
CI_COMMENT_MARKER,
|
|
4
4
|
countSeverity,
|
|
5
5
|
runCi
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-ZDO3XCXL.js";
|
|
7
|
+
import "./chunk-LEA4AMXE.js";
|
|
8
8
|
import "./chunk-HLWUDRBO.js";
|
|
9
9
|
import "./chunk-6YZEZFX5.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-XVB4RARX.js";
|
|
11
|
+
import "./chunk-COHKPZ2E.js";
|
|
12
|
+
import "./chunk-E2W2MI6H.js";
|
|
13
13
|
import "./chunk-TU3L3PW7.js";
|
|
14
14
|
import "./chunk-BMLQPSHP.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-2R6Y5SJH.js";
|
|
16
16
|
export {
|
|
17
17
|
CI_COMMENT_MARKER,
|
|
18
18
|
countSeverity,
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
formatDoctorReport,
|
|
4
4
|
runDoctorCli
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-2GOBINY4.js";
|
|
6
|
+
import "./chunk-VS43QMR2.js";
|
|
7
7
|
import "./chunk-RS7SKYTS.js";
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-XVB4RARX.js";
|
|
9
|
+
import "./chunk-COHKPZ2E.js";
|
|
10
|
+
import "./chunk-E2W2MI6H.js";
|
|
11
11
|
import "./chunk-TU3L3PW7.js";
|
|
12
12
|
import "./chunk-HOSJZMQS.js";
|
|
13
13
|
import "./chunk-BMLQPSHP.js";
|
|
14
|
-
import "./chunk-
|
|
14
|
+
import "./chunk-2R6Y5SJH.js";
|
|
15
15
|
export {
|
|
16
16
|
formatDoctorReport,
|
|
17
17
|
runDoctorCli
|
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-7QW3DFYV.js";
|
|
59
59
|
import {
|
|
60
60
|
DEFAULT_PATTERNS,
|
|
61
61
|
redactJson,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
recoverGbkMojibake,
|
|
82
82
|
runTestsTool,
|
|
83
83
|
shellInvocation
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-JHSULP5D.js";
|
|
85
85
|
import {
|
|
86
86
|
getCurrentSessionKey,
|
|
87
87
|
getExecutionConfigDir,
|
|
@@ -123,7 +123,7 @@ import {
|
|
|
123
123
|
SUBAGENT_MAX_ROUNDS_LIMIT,
|
|
124
124
|
VERSION,
|
|
125
125
|
buildUserIdentityPrompt
|
|
126
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-VEO2MILP.js";
|
|
127
127
|
|
|
128
128
|
// src/web/access.ts
|
|
129
129
|
import { randomBytes, timingSafeEqual } from "crypto";
|
|
@@ -981,17 +981,21 @@ var PRICING_TABLE = {
|
|
|
981
981
|
"glm-4.6": { input: 0.6, output: 2.2 },
|
|
982
982
|
"glm-4.6v": { input: 0.6, output: 2.2 },
|
|
983
983
|
"glm-5": { input: 0.85, output: 2.85 },
|
|
984
|
-
// GLM-5.3
|
|
984
|
+
// GLM-5.3:官方定价页(open.bigmodel.cn/pricing,2026-10-08 浏览器读取)——输入 8 元、
|
|
985
|
+
// 输出 28 元、缓存命中 2 元(每百万 token),按 ¥6.9/$1 换算。此前记的 $1.40/$4.40 是
|
|
986
|
+
// Z.ai 国际站的美元价,而本 provider 打的是国内站、按人民币计费,高报约 20%;更大的
|
|
987
|
+
// 偏差在**缓存**:没有 cacheRead 时缓存命中按输入全价算,2026-10-07 审计会话 1474 万
|
|
988
|
+
// 缓存 token 被记成 $21.34,按官方缓存价约 $4.90(2026-10-07 审计 X-03)。
|
|
985
989
|
// 注意它**始终思考**,思考 token 按输出价计费 —— 实际成本高度取决于 reasoning_effort。
|
|
986
|
-
"glm-5.3": { input:
|
|
990
|
+
"glm-5.3": { input: 8 / CNY_PER_USD, output: 28 / CNY_PER_USD, cacheRead: 2 / CNY_PER_USD },
|
|
987
991
|
// GLM-5.3-Flash:官方定价页(open.bigmodel.cn/pricing)一手数字——输入 0.8 元、
|
|
988
992
|
// 输出 2.8 元、缓存命中 0.23 元(每百万 token),按记账汇率 ¥6.9/$1 换算。
|
|
989
993
|
// **刻意记恢复价而非当前的 5 折限时价**(0.4/1.4/0.115 元):官方只说「限时两周」、
|
|
990
994
|
// 没公布截止日期,静态表表达不了这个时间维度;高估比低估安全——预算告警早触发
|
|
991
995
|
// 好过晚触发。折扣期内 `/cost` 会比实际偏高约一倍,这是刻意的取舍。
|
|
992
996
|
"glm-5.3-flash": { input: 0.116, output: 0.406, cacheRead: 0.033 },
|
|
993
|
-
// GLM-5.2
|
|
994
|
-
"glm-5.2": { input:
|
|
997
|
+
// GLM-5.2:与 GLM-5.3 同价(同一定价页:8 / 28 / 缓存命中 2 元),口径修正同上。
|
|
998
|
+
"glm-5.2": { input: 8 / CNY_PER_USD, output: 28 / CNY_PER_USD, cacheRead: 2 / CNY_PER_USD },
|
|
995
999
|
// GLM-5V-Turbo(2026-04 视觉编程旗舰)官方直连 API 定价 $1.20 / $4.00。
|
|
996
1000
|
"glm-5v-turbo": { input: 1.2, output: 4 },
|
|
997
1001
|
"glm-5.1": { input: 0.95, output: 3.15 },
|
|
@@ -2433,6 +2437,14 @@ var HALLUCINATION_PATTERNS = [
|
|
|
2433
2437
|
// 已创建!
|
|
2434
2438
|
/File\s+(?:written|saved|created)\s+(?:to|as|at)/i,
|
|
2435
2439
|
// File written to / saved as(要求介词)
|
|
2440
|
+
// 2026-10-07 审计 B-02:中英文判据不对称。中文「已保存到」要求引号、英文只认 `File saved to`,
|
|
2441
|
+
// 于是「已保存到 report.md。」「I saved the changes to src/index.ts.」双双漏检。
|
|
2442
|
+
// 改为「后面跟一个带扩展名的文件名」——同样挡得住「已保存到数据库」「saved my time」这类误报。
|
|
2443
|
+
/已(?:保存|写入)到?\s*[^\s,,。;;::]{1,120}\.\w{1,6}(?![\w/])/,
|
|
2444
|
+
// 动词后直接跟文件名(中间只许冠词 / both / the file 之类),或「动词 … to/into 文件名」。
|
|
2445
|
+
// 刻意不放宽成「同句任意文件名」:「I saved you some time by checking README.md」不是写入声明。
|
|
2446
|
+
/\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,
|
|
2447
|
+
/\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,
|
|
2436
2448
|
/生成完成[!!]/,
|
|
2437
2449
|
// 生成完成!
|
|
2438
2450
|
/✅\s*(?:文件|已[生保写创]|第)\S*\.\w{1,5}/,
|
|
@@ -2483,6 +2495,8 @@ var QUICK_WRITE_KEYWORDS = [
|
|
|
2483
2495
|
"saved",
|
|
2484
2496
|
"written",
|
|
2485
2497
|
"created",
|
|
2498
|
+
"wrote",
|
|
2499
|
+
"generated",
|
|
2486
2500
|
"File",
|
|
2487
2501
|
"file",
|
|
2488
2502
|
// emoji 勾选标记
|
|
@@ -2599,8 +2613,13 @@ function extractClaimedFilePaths(content) {
|
|
|
2599
2613
|
}
|
|
2600
2614
|
const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'”””]?([^\s`'”””,,。\n]+\.\w{1,6})/g;
|
|
2601
2615
|
while ((m = zhRe.exec(content)) !== null) add(m[1]);
|
|
2602
|
-
const enRe =
|
|
2616
|
+
const enRe = /\b(?:saved|written|wrote|created)\b[^.\n]{0,40}?\b(?:to|as|at|into)\s+[`'”]?([^\s`'”\n,]+\.\w{1,6})/gi;
|
|
2603
2617
|
while ((m = enRe.exec(content)) !== null) add(m[1]);
|
|
2618
|
+
const enClaimRe = /\b(?:I|We)(?:'ve| have)?\s+(?:now\s+|just\s+|also\s+|successfully\s+)?(?:created|written|wrote|saved|generated)\b([^\n;]*)/gi;
|
|
2619
|
+
while ((m = enClaimRe.exec(content)) !== null) {
|
|
2620
|
+
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] ?? "";
|
|
2621
|
+
for (const f of clause.matchAll(/[`'"]?([\w./-]+\.\w{1,6})\b/g)) add(f[1]);
|
|
2622
|
+
}
|
|
2604
2623
|
const checkRe = /✅[^\n`]*?[`'”]?([^\s`'”\n,,。]+?\.\w{1,6})/g;
|
|
2605
2624
|
while ((m = checkRe.exec(content)) !== null) {
|
|
2606
2625
|
const pathStart = m.index + m[0].lastIndexOf(m[1]);
|
|
@@ -2875,8 +2894,27 @@ var META_NARRATION_HEURISTICS = [
|
|
|
2875
2894
|
/(?:我来|让我|容我)\s*(?:整理|梳理|归纳|想想|看看|重新|检查|核实)/u,
|
|
2876
2895
|
// 过渡语(需要 2+ hits):"以下是:" / "如下:" 作为独立行。文档中可作小节标题,
|
|
2877
2896
|
// 但配合另一个对话模式(如"好的")时是典型的 AI 内容包装。
|
|
2878
|
-
/^.{0,60}(?:以下是|下面是|如下)\s*[::,,]\s*$/mu
|
|
2897
|
+
/^.{0,60}(?:以下是|下面是|如下)\s*[::,,]\s*$/mu,
|
|
2898
|
+
// 叙述自己要调用工具(2026-10-07 审计 B-05):文档正文不会这样写自己。
|
|
2899
|
+
/(?:让我|我来|我将|我会|接下来)\s*(?:调用|使用|用)\s*`?\w+`?\s*工具/u,
|
|
2900
|
+
/\bI(?:'ll| will| am going to)\s+(?:now\s+)?(?:use|call|invoke)\s+the\s+`?\w+`?\s+tool\b/i
|
|
2901
|
+
];
|
|
2902
|
+
var ANNOUNCEMENT_PATTERNS = [
|
|
2903
|
+
/^\s*(?:好的|好|收到|明白|了解|嗯|OK|Okay|Sure|Certainly)[,,。.!!\s]/iu,
|
|
2904
|
+
/(?:我(?:这就|马上|现在|立即|立刻|来|将|会)|让我|下面我|接下来我)\s*(?:为[您你])?\s*(?:开始|着手|撰写|写|生成|整理|输出|编写|准备|调用|使用)/u,
|
|
2905
|
+
/(?:请稍[候等]|稍等|马上就好|这就开始)/u,
|
|
2906
|
+
/\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,
|
|
2907
|
+
/\b(?:please wait|one moment|stand by)\b/i
|
|
2879
2908
|
];
|
|
2909
|
+
function looksLikeAnnouncementOnly(content) {
|
|
2910
|
+
const text = content.trim();
|
|
2911
|
+
if (!text || text.length > 300 || text.split("\n").length > 4) return null;
|
|
2912
|
+
if (/^#{1,6}\s+\S/m.test(text)) return null;
|
|
2913
|
+
for (const re of ANNOUNCEMENT_PATTERNS) {
|
|
2914
|
+
if (re.test(text)) return re.source;
|
|
2915
|
+
}
|
|
2916
|
+
return null;
|
|
2917
|
+
}
|
|
2880
2918
|
var CHINESE_TAIL_CLOSING_MARKERS = [
|
|
2881
2919
|
/(?:需要你|请你|麻烦你|你看)\s*(?:确认|决定|选择|帮忙|看[一看下]|过目|觉得|认为)/u,
|
|
2882
2920
|
/(?:随时|有问题|有需要|需要调整|需要修改)\s*(?:联系|找我|告诉|沟通|调整|修改)/u,
|
|
@@ -3013,6 +3051,15 @@ This fresh stream has NO tools \u2014 output is captured verbatim. STOP emitting
|
|
|
3013
3051
|
summary: `[save_last_response REJECTED] The content-only stream produced NO text at all (output budget likely spent on reasoning). ${saveToFile} was NOT saved.`
|
|
3014
3052
|
};
|
|
3015
3053
|
}
|
|
3054
|
+
const announced = looksLikeAnnouncementOnly(rawContent);
|
|
3055
|
+
if (announced) {
|
|
3056
|
+
return fallback(`announcement only: ${announced}`) ?? {
|
|
3057
|
+
kind: "reject",
|
|
3058
|
+
reason: "not-a-document",
|
|
3059
|
+
matched: announced,
|
|
3060
|
+
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.`
|
|
3061
|
+
};
|
|
3062
|
+
}
|
|
3016
3063
|
const { lines, bytes } = teeFileStats(rawContent);
|
|
3017
3064
|
return {
|
|
3018
3065
|
kind: "ok",
|
|
@@ -3034,6 +3081,7 @@ function teeStreamErrorSummary(saveToFile, errMsg) {
|
|
|
3034
3081
|
// src/core/stalled-intent.ts
|
|
3035
3082
|
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;
|
|
3036
3083
|
var COMPLETED_RE = /已|完成|好了|完毕|写好|搞定|\b(?:done|finished|completed|have (?:written|created|generated))\b/i;
|
|
3084
|
+
var NEGATION_RE = /没有?|未|无法|不(?:会|能|再|打算|需要|用|必|要)|n't\b|\b(?:not|never|no longer|cannot)\b/i;
|
|
3037
3085
|
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";
|
|
3038
3086
|
var CN_FIRST_PERSON_INTENT_RE = new RegExp(
|
|
3039
3087
|
`(?:\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})`
|
|
@@ -3055,11 +3103,11 @@ function detectStalledIntent(content) {
|
|
|
3055
3103
|
if (WAITING_FOR_USER_RE.test(tail)) return null;
|
|
3056
3104
|
const clauses = tail.split(/[,,;;。!!::\n]/).map((c) => c.trim()).filter(Boolean);
|
|
3057
3105
|
for (const clause of clauses) {
|
|
3058
|
-
if (COMPLETED_RE.test(clause)) continue;
|
|
3106
|
+
if (COMPLETED_RE.test(clause) || NEGATION_RE.test(clause)) continue;
|
|
3059
3107
|
if (CN_FIRST_PERSON_INTENT_RE.test(clause) || CN_BARE_INTENT_RE.test(clause)) return clause;
|
|
3060
3108
|
}
|
|
3061
3109
|
for (const sentence of tail.split(/(?<=[.!])\s+|\n/)) {
|
|
3062
|
-
if (COMPLETED_RE.test(sentence)) continue;
|
|
3110
|
+
if (COMPLETED_RE.test(sentence) || NEGATION_RE.test(sentence)) continue;
|
|
3063
3111
|
const m = EN_INTENT_RE.exec(sentence);
|
|
3064
3112
|
if (m) return sentence.trim();
|
|
3065
3113
|
}
|
|
@@ -3507,7 +3555,12 @@ async function runAgentLoop(host) {
|
|
|
3507
3555
|
if (tc.name.startsWith("mcp__")) host.onMcpToolUsed?.(tc.name);
|
|
3508
3556
|
}
|
|
3509
3557
|
host.persistRound?.(toolCalls, toolResults, {
|
|
3510
|
-
|
|
3558
|
+
// 工具调用前模型说的话("A 方向汇报:…"、"先看一下配置")挂在 _streamedText 上:
|
|
3559
|
+
// 本轮上下文里有(buildToolResultMessages 会带上),但此前存档只取 outcome.content,
|
|
3560
|
+
// 而工具调用轮次的 outcome 没有 content——2026-10-07 审计会话 157 条带工具调用的
|
|
3561
|
+
// assistant 消息正文**全部为空**:下一条用户消息时模型看不到自己之前的阶段性汇报,
|
|
3562
|
+
// /session show、导出、回放也全缺这部分(审计 X-01)。
|
|
3563
|
+
assistantContent: outcome.content ?? toolCalls._streamedText,
|
|
3511
3564
|
reasoningContent: outcome.reasoningContent
|
|
3512
3565
|
});
|
|
3513
3566
|
host.afterToolRoundPersist?.(toolCalls, toolResults, extraMessages);
|
|
@@ -3562,6 +3615,7 @@ async function runLeanAgentLoop(opts) {
|
|
|
3562
3615
|
let roundsUsed = 0;
|
|
3563
3616
|
let toolCallCount = 0;
|
|
3564
3617
|
let stalledIntentNudges = 0;
|
|
3618
|
+
let hallucinationRetries = 0;
|
|
3565
3619
|
try {
|
|
3566
3620
|
for (let round = 0; round < opts.maxRounds; round++) {
|
|
3567
3621
|
roundsUsed = round + 1;
|
|
@@ -3577,6 +3631,7 @@ async function runLeanAgentLoop(opts) {
|
|
|
3577
3631
|
timeout: opts.chatParams?.timeout,
|
|
3578
3632
|
thinking: opts.chatParams?.thinking,
|
|
3579
3633
|
thinkingEffort: opts.chatParams?.thinkingEffort,
|
|
3634
|
+
thinkingBudget: opts.chatParams?.thinkingBudget,
|
|
3580
3635
|
...extraMessages.length > 0 ? { _extraMessages: extraMessages } : {}
|
|
3581
3636
|
},
|
|
3582
3637
|
opts.toolDefsForRound(round)
|
|
@@ -3596,6 +3651,24 @@ async function runLeanAgentLoop(opts) {
|
|
|
3596
3651
|
);
|
|
3597
3652
|
continue;
|
|
3598
3653
|
}
|
|
3654
|
+
const nextTools = round < opts.maxRounds - 1 ? opts.toolDefsForRound(round + 1) : [];
|
|
3655
|
+
const canWrite = nextTools.some((t) => t.name === "write_file" || t.name === "edit_file");
|
|
3656
|
+
if (canWrite && hallucinationRetries < 1 && result.content) {
|
|
3657
|
+
const alreadyWrote = hadPreviousWriteToolCalls(extraMessages);
|
|
3658
|
+
const coarse = !alreadyWrote && detectsHallucinatedFileOp(result.content) && extractBashCommands(extraMessages).length === 0;
|
|
3659
|
+
const phantom = coarse || alreadyWrote ? findPhantomClaims(result.content, extraMessages) : [];
|
|
3660
|
+
if (phantom.length > 0 || coarse) {
|
|
3661
|
+
hallucinationRetries++;
|
|
3662
|
+
extraMessages.push(
|
|
3663
|
+
{ role: "assistant", content: result.content },
|
|
3664
|
+
{
|
|
3665
|
+
role: "user",
|
|
3666
|
+
content: phantom.length > 0 ? buildPhantomCorrectionMessage(phantom) : HALLUCINATION_CORRECTION_MESSAGE
|
|
3667
|
+
}
|
|
3668
|
+
);
|
|
3669
|
+
continue;
|
|
3670
|
+
}
|
|
3671
|
+
}
|
|
3599
3672
|
content = result.content;
|
|
3600
3673
|
break;
|
|
3601
3674
|
}
|
|
@@ -4704,6 +4777,7 @@ function ollamaNativeBaseUrl(openAiBaseUrl) {
|
|
|
4704
4777
|
return openAiBaseUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
|
|
4705
4778
|
}
|
|
4706
4779
|
var NATIVE_API_TIMEOUT_MS = 3e3;
|
|
4780
|
+
var SMALL_CONTEXT_WARN = 16384;
|
|
4707
4781
|
var OllamaProvider = class extends OpenAICompatibleProvider {
|
|
4708
4782
|
// 用 127.0.0.1 而非 localhost:Node.js 18+ 在 Windows 上优先解析 localhost 为 IPv6 (::1),
|
|
4709
4783
|
// 但 Ollama 默认只监听 IPv4,导致连接失败。
|
|
@@ -4782,12 +4856,13 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
|
|
|
4782
4856
|
if (show?.capabilities?.includes("thinking")) thinkingModels.add(id);
|
|
4783
4857
|
if (running.size === 0 && !show) return;
|
|
4784
4858
|
const digest = digests.get(id);
|
|
4785
|
-
const { contextWindow } = resolveOllamaContextWindow({
|
|
4859
|
+
const { contextWindow, source: source2 } = resolveOllamaContextWindow({
|
|
4786
4860
|
runningContext: digest && running.get(digest) || running.get(id),
|
|
4787
4861
|
show,
|
|
4788
4862
|
fallback: this.estimateContextWindow(id)
|
|
4789
4863
|
});
|
|
4790
4864
|
result.set(id, contextWindow);
|
|
4865
|
+
this.contextSources.set(id, source2);
|
|
4791
4866
|
}));
|
|
4792
4867
|
return { contextWindows: result, thinkingModels };
|
|
4793
4868
|
}
|
|
@@ -4883,6 +4958,77 @@ var OllamaProvider = class extends OpenAICompatibleProvider {
|
|
|
4883
4958
|
const target = norm2(model);
|
|
4884
4959
|
return this.dynamicModels.some((m) => m.supportsThinking === true && norm2(m.id) === target);
|
|
4885
4960
|
}
|
|
4961
|
+
// ── 加载后补读真实窗口(2026-10-07 审计 C-01)────────────────────────────
|
|
4962
|
+
//
|
|
4963
|
+
// 上下文窗口只在启动时读一次。模型当时若还没加载,`/api/ps` 里没有它,只能取训练上限
|
|
4964
|
+
// (Qwen3.8 是 262K);而服务端实际开的窗口可能只有它的几十分之一。第一次请求把模型
|
|
4965
|
+
// 加载进来之后若不再读,上下文压力监控、自动压缩与工具预算就整场按那个大数在算——
|
|
4966
|
+
// aicli 以为还有余量,Ollama 早已在悄悄截掉最早的消息(v0.4.311 那次说的正是这个后果)。
|
|
4967
|
+
// 所以每个模型在首次请求之后补读一次 `/api/ps`;读到的窗口若小得连工具定义都放不下,
|
|
4968
|
+
// 提示一次怎么调大。都是后台做,不拖慢这次请求。
|
|
4969
|
+
/** 每个模型的窗口是从哪一级读到的(只有 'running' 是服务端实际值) */
|
|
4970
|
+
contextSources = /* @__PURE__ */ new Map();
|
|
4971
|
+
refreshedAfterLoad = /* @__PURE__ */ new Set();
|
|
4972
|
+
warnedSmallContext = /* @__PURE__ */ new Set();
|
|
4973
|
+
async chat(request) {
|
|
4974
|
+
try {
|
|
4975
|
+
return await super.chat(request);
|
|
4976
|
+
} finally {
|
|
4977
|
+
this.scheduleContextRefresh(request.model);
|
|
4978
|
+
}
|
|
4979
|
+
}
|
|
4980
|
+
async *chatStream(request) {
|
|
4981
|
+
try {
|
|
4982
|
+
yield* super.chatStream(request);
|
|
4983
|
+
} finally {
|
|
4984
|
+
this.scheduleContextRefresh(request.model);
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
async chatWithTools(request, tools) {
|
|
4988
|
+
try {
|
|
4989
|
+
return await super.chatWithTools(request, tools);
|
|
4990
|
+
} finally {
|
|
4991
|
+
this.scheduleContextRefresh(request.model);
|
|
4992
|
+
}
|
|
4993
|
+
}
|
|
4994
|
+
async *chatWithToolsStream(request, tools) {
|
|
4995
|
+
try {
|
|
4996
|
+
yield* super.chatWithToolsStream(request, tools);
|
|
4997
|
+
} finally {
|
|
4998
|
+
this.scheduleContextRefresh(request.model);
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
scheduleContextRefresh(model) {
|
|
5002
|
+
const key = model.replace(/:latest$/, "");
|
|
5003
|
+
if (this.refreshedAfterLoad.has(key)) return;
|
|
5004
|
+
this.refreshedAfterLoad.add(key);
|
|
5005
|
+
void this.refreshLoadedContext(model).catch(() => {
|
|
5006
|
+
});
|
|
5007
|
+
}
|
|
5008
|
+
/** 补读已加载模型的实际窗口,更新同一份权重(digest 相同)的所有别名。测试可直接 await。 */
|
|
5009
|
+
async refreshLoadedContext(model) {
|
|
5010
|
+
const norm2 = (id2) => id2.replace(/:latest$/, "");
|
|
5011
|
+
const [running, digests] = await Promise.all([this.fetchRunningContexts(), this.fetchDigests()]);
|
|
5012
|
+
const self = this.dynamicModels.find((m) => norm2(m.id) === norm2(model));
|
|
5013
|
+
const id = self?.id ?? model;
|
|
5014
|
+
const digest = digests.get(id);
|
|
5015
|
+
const actual = digest && running.get(digest) || running.get(id);
|
|
5016
|
+
if (!actual) return;
|
|
5017
|
+
for (const m of this.dynamicModels) {
|
|
5018
|
+
if (m.id === id || digest && digests.get(m.id) === digest) {
|
|
5019
|
+
m.contextWindow = actual;
|
|
5020
|
+
this.contextSources.set(m.id, "running");
|
|
5021
|
+
}
|
|
5022
|
+
}
|
|
5023
|
+
if (actual < SMALL_CONTEXT_WARN && !this.warnedSmallContext.has(norm2(id))) {
|
|
5024
|
+
this.warnedSmallContext.add(norm2(id));
|
|
5025
|
+
process.stderr.write(
|
|
5026
|
+
`
|
|
5027
|
+
[ollama] ${id} is loaded with a ${actual.toLocaleString()}-token context window. aicli's tool definitions alone take about 8K tokens, so earlier messages will be silently cut off. Raise it: set OLLAMA_CONTEXT_LENGTH=32768 (or more) for the Ollama server, or add "PARAMETER num_ctx 32768" to the model's Modelfile.
|
|
5028
|
+
`
|
|
5029
|
+
);
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
4886
5032
|
/** 实时刷新模型列表 */
|
|
4887
5033
|
async listModels() {
|
|
4888
5034
|
await this.tryConnect();
|
|
@@ -13418,21 +13564,37 @@ function estimateTokens(text) {
|
|
|
13418
13564
|
return Math.ceil(tokens) + 4;
|
|
13419
13565
|
}
|
|
13420
13566
|
function estimateToolDefinitionTokens(def) {
|
|
13421
|
-
|
|
13422
|
-
|
|
13423
|
-
|
|
13424
|
-
if (param.enum) {
|
|
13425
|
-
charCount += param.enum.join(" ").length;
|
|
13426
|
-
}
|
|
13427
|
-
}
|
|
13428
|
-
const structuralOverhead = 40 + Object.keys(def.parameters).length * 30;
|
|
13429
|
-
return Math.ceil((charCount + structuralOverhead) * 0.25) + 10;
|
|
13567
|
+
const json = JSON.stringify({ name: def.name, description: def.description, parameters: def.parameters });
|
|
13568
|
+
const cjk = json.match(CJK_REGEX)?.length ?? 0;
|
|
13569
|
+
return Math.ceil((json.length - cjk + 40) / 3.7 + cjk * 1.5);
|
|
13430
13570
|
}
|
|
13431
13571
|
|
|
13432
13572
|
// src/tools/registry.ts
|
|
13433
13573
|
import { pathToFileURL } from "url";
|
|
13434
13574
|
import { existsSync as existsSync19, mkdirSync as mkdirSync9, readdirSync as readdirSync9 } from "fs";
|
|
13435
13575
|
import { join as join13 } from "path";
|
|
13576
|
+
var TRIMMABLE_BUILTIN_ORDER = [
|
|
13577
|
+
"google_search",
|
|
13578
|
+
"recall_memory",
|
|
13579
|
+
"search_code",
|
|
13580
|
+
"notebook_edit",
|
|
13581
|
+
"spawn_agent",
|
|
13582
|
+
"run_interactive",
|
|
13583
|
+
"save_memory",
|
|
13584
|
+
"find_references",
|
|
13585
|
+
"get_outline",
|
|
13586
|
+
"find_symbol",
|
|
13587
|
+
"task_stop",
|
|
13588
|
+
"task_list",
|
|
13589
|
+
"task_create",
|
|
13590
|
+
"git_log",
|
|
13591
|
+
"git_diff",
|
|
13592
|
+
"git_commit",
|
|
13593
|
+
"git_status",
|
|
13594
|
+
"web_fetch",
|
|
13595
|
+
"web_search",
|
|
13596
|
+
"run_tests"
|
|
13597
|
+
];
|
|
13436
13598
|
var ToolRegistry = class {
|
|
13437
13599
|
tools = /* @__PURE__ */ new Map();
|
|
13438
13600
|
pluginToolNames = /* @__PURE__ */ new Set();
|
|
@@ -13500,7 +13662,7 @@ var ToolRegistry = class {
|
|
|
13500
13662
|
totalTokens += estimateToolDefinitionTokens(def);
|
|
13501
13663
|
}
|
|
13502
13664
|
if (totalTokens <= tokenBudget) {
|
|
13503
|
-
return { definitions: allDefs, trimmedCount: 0, systemNote: null };
|
|
13665
|
+
return { definitions: allDefs, trimmedCount: 0, trimmedBuiltins: [], systemNote: null };
|
|
13504
13666
|
}
|
|
13505
13667
|
const builtinDefs = [];
|
|
13506
13668
|
const mcpDefs = [];
|
|
@@ -13512,10 +13674,19 @@ var ToolRegistry = class {
|
|
|
13512
13674
|
}
|
|
13513
13675
|
}
|
|
13514
13676
|
let budget = tokenBudget;
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
const
|
|
13677
|
+
const trimmedBuiltins = [];
|
|
13678
|
+
let builtinCost = builtinDefs.reduce((n, d) => n + estimateToolDefinitionTokens(d), 0);
|
|
13679
|
+
const keptBuiltins = new Set(builtinDefs.map((d) => d.name));
|
|
13680
|
+
for (const name of TRIMMABLE_BUILTIN_ORDER) {
|
|
13681
|
+
if (builtinCost <= budget) break;
|
|
13682
|
+
const def = builtinDefs.find((d) => d.name === name);
|
|
13683
|
+
if (!def || this.pluginToolNames.has(name)) continue;
|
|
13684
|
+
keptBuiltins.delete(name);
|
|
13685
|
+
trimmedBuiltins.push(name);
|
|
13686
|
+
builtinCost -= estimateToolDefinitionTokens(def);
|
|
13687
|
+
}
|
|
13688
|
+
budget -= builtinCost;
|
|
13689
|
+
const kept = builtinDefs.filter((d) => keptBuiltins.has(d.name));
|
|
13519
13690
|
const used = usedToolNames ?? /* @__PURE__ */ new Set();
|
|
13520
13691
|
const remaining = [];
|
|
13521
13692
|
for (const def of mcpDefs) {
|
|
@@ -13537,6 +13708,12 @@ var ToolRegistry = class {
|
|
|
13537
13708
|
trimmed++;
|
|
13538
13709
|
}
|
|
13539
13710
|
}
|
|
13711
|
+
const notes = [];
|
|
13712
|
+
if (trimmedBuiltins.length > 0) {
|
|
13713
|
+
notes.push(
|
|
13714
|
+
`[Tool Budget] To fit this model's context window, these tools are not available in this session: ${trimmedBuiltins.join(", ")}. Use bash for the equivalent (git commands, grep for symbols, curl for web pages) instead of calling them.`
|
|
13715
|
+
);
|
|
13716
|
+
}
|
|
13540
13717
|
let systemNote = null;
|
|
13541
13718
|
if (trimmed > 0) {
|
|
13542
13719
|
const trimmedServers = /* @__PURE__ */ new Set();
|
|
@@ -13549,7 +13726,13 @@ var ToolRegistry = class {
|
|
|
13549
13726
|
}
|
|
13550
13727
|
systemNote = `[MCP Tool Budget] ${trimmed} MCP tool(s) from server(s) [${[...trimmedServers].join(", ")}] were excluded to fit the context window. If you need a specific MCP tool that isn't listed, tell the user to ask for it explicitly.`;
|
|
13551
13728
|
}
|
|
13552
|
-
|
|
13729
|
+
if (systemNote) notes.push(systemNote);
|
|
13730
|
+
return {
|
|
13731
|
+
definitions: kept,
|
|
13732
|
+
trimmedCount: trimmed,
|
|
13733
|
+
trimmedBuiltins,
|
|
13734
|
+
systemNote: notes.length > 0 ? notes.join("\n\n") : null
|
|
13735
|
+
};
|
|
13553
13736
|
}
|
|
13554
13737
|
listAll() {
|
|
13555
13738
|
return [...this.tools.values()];
|
|
@@ -17526,7 +17709,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
|
|
|
17526
17709
|
Cost: ${formatCost(cost)}` : "";
|
|
17527
17710
|
let memoryLine = "";
|
|
17528
17711
|
try {
|
|
17529
|
-
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-
|
|
17712
|
+
const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-EVZX7SLR.js");
|
|
17530
17713
|
const pending = countPendingMemories2(ctx.config.getConfigDir());
|
|
17531
17714
|
if (pending > 0) memoryLine = `
|
|
17532
17715
|
Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
|
|
@@ -18514,7 +18697,7 @@ async function handleTest(args, ctx) {
|
|
|
18514
18697
|
const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
|
|
18515
18698
|
testArgs = isCommand ? { command: argStr } : { filter: argStr };
|
|
18516
18699
|
}
|
|
18517
|
-
const runTests = ctx.runTests ?? (await import("./run-tests-
|
|
18700
|
+
const runTests = ctx.runTests ?? (await import("./run-tests-3SYXE2PJ.js")).executeTests;
|
|
18518
18701
|
const report = await runTests(testArgs);
|
|
18519
18702
|
ctx.send({ type: "info", message: report });
|
|
18520
18703
|
} catch (err) {
|
|
@@ -18905,7 +19088,7 @@ async function handleMemory(args, ctx) {
|
|
|
18905
19088
|
}
|
|
18906
19089
|
if (intent.kind === "status") {
|
|
18907
19090
|
const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-RLVLQRRC.js");
|
|
18908
|
-
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-
|
|
19091
|
+
const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-EVZX7SLR.js");
|
|
18909
19092
|
const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
|
|
18910
19093
|
const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
|
|
18911
19094
|
const view = buildMemoryStatusView({
|
|
@@ -18928,7 +19111,7 @@ async function handleMemory(args, ctx) {
|
|
|
18928
19111
|
return;
|
|
18929
19112
|
}
|
|
18930
19113
|
if (intent.kind === "recall") {
|
|
18931
|
-
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-
|
|
19114
|
+
const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-EVZX7SLR.js");
|
|
18932
19115
|
const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-RLVLQRRC.js");
|
|
18933
19116
|
const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
|
|
18934
19117
|
if (persistentHits.length > 0) {
|
|
@@ -19049,7 +19232,7 @@ async function handleMemory(args, ctx) {
|
|
|
19049
19232
|
ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
|
|
19050
19233
|
} else if (intent.kind === "export") {
|
|
19051
19234
|
if (args[1] === "md") {
|
|
19052
|
-
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-
|
|
19235
|
+
const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-EVZX7SLR.js");
|
|
19053
19236
|
ctx.send({
|
|
19054
19237
|
type: "export_data",
|
|
19055
19238
|
format: "md",
|
|
@@ -20054,7 +20237,7 @@ No tools match "${filter}".
|
|
|
20054
20237
|
const { join: join26 } = await import("path");
|
|
20055
20238
|
const { existsSync: existsSync32 } = await import("fs");
|
|
20056
20239
|
const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
|
|
20057
|
-
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-
|
|
20240
|
+
const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-HF5AYLBR.js");
|
|
20058
20241
|
const { approveProject, hashMcpFile } = await import("./project-trust-6CJB5ZMX.js");
|
|
20059
20242
|
const cwd = process.cwd();
|
|
20060
20243
|
const projectRoot = getGitRoot2(cwd) ?? cwd;
|
|
@@ -20973,7 +21156,7 @@ function createReviewCommands() {
|
|
|
20973
21156
|
usage: "/test [command|filter]",
|
|
20974
21157
|
async execute(args, ctx) {
|
|
20975
21158
|
try {
|
|
20976
|
-
const { executeTests } = await import("./run-tests-
|
|
21159
|
+
const { executeTests } = await import("./run-tests-3SYXE2PJ.js");
|
|
20977
21160
|
const argStr = args.join(" ").trim();
|
|
20978
21161
|
let testArgs = {};
|
|
20979
21162
|
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-QHJEDRDS.js");
|
|
162
162
|
const orchestrator = new TaskOrchestrator(config, providers, configManager);
|
|
163
163
|
let interrupted = false;
|
|
164
164
|
const onSigint = () => {
|