oh-my-opencode-cohub 1.13.1 → 1.13.2
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 +5 -5
- package/dist/context/engine.d.ts.map +1 -1
- package/dist/context/engine.test.d.ts +2 -0
- package/dist/context/engine.test.d.ts.map +1 -0
- package/dist/context/extractor.d.ts +11 -0
- package/dist/context/extractor.d.ts.map +1 -1
- package/dist/context/types.d.ts +4 -0
- package/dist/context/types.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +159 -81
- package/dist/orchestration/contract.d.ts +6 -0
- package/dist/orchestration/contract.d.ts.map +1 -1
- package/dist/task-manager/tracker.d.ts +8 -0
- package/dist/task-manager/tracker.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -49,7 +49,7 @@ function computeStats(records, window = DEFAULT_STATS_WINDOW) {
|
|
|
49
49
|
return result;
|
|
50
50
|
}
|
|
51
51
|
// package.json
|
|
52
|
-
var version = "1.13.
|
|
52
|
+
var version = "1.13.2";
|
|
53
53
|
|
|
54
54
|
// src/cli/config-io.ts
|
|
55
55
|
import * as fs from "node:fs";
|
|
@@ -85,11 +85,11 @@ function writeJSON(filePath, data) {
|
|
|
85
85
|
`;
|
|
86
86
|
fs.writeFileSync(filePath, content, "utf-8");
|
|
87
87
|
}
|
|
88
|
-
function addPluginToOpenCodeConfig(
|
|
88
|
+
function addPluginToOpenCodeConfig(version) {
|
|
89
89
|
const configPath = getOpencodeConfigPath();
|
|
90
90
|
let config = readJSON(configPath) ?? {};
|
|
91
91
|
const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
|
|
92
|
-
const pkgSpec = `${PACKAGE_NAME}@${
|
|
92
|
+
const pkgSpec = `${PACKAGE_NAME}@${version}`;
|
|
93
93
|
if (plugins.some((p) => p.includes(PACKAGE_NAME))) {
|
|
94
94
|
for (let i = 0;i < plugins.length; i++) {
|
|
95
95
|
if (plugins[i].includes(PACKAGE_NAME)) {
|
|
@@ -473,7 +473,7 @@ function uninstallCoHub() {
|
|
|
473
473
|
messages.push("✅ CoHub 卸载完成。完全关闭 OpenCode 后重新打开即可。");
|
|
474
474
|
return { success: true, messages };
|
|
475
475
|
}
|
|
476
|
-
function installToCacheDir(
|
|
476
|
+
function installToCacheDir(version) {
|
|
477
477
|
try {
|
|
478
478
|
const targetDir = PACKAGES_CACHE;
|
|
479
479
|
if (fs.existsSync(targetDir)) {
|
|
@@ -482,7 +482,7 @@ function installToCacheDir(version2) {
|
|
|
482
482
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
483
483
|
const pkgJson = { private: true };
|
|
484
484
|
fs.writeFileSync(path2.join(targetDir, "package.json"), JSON.stringify(pkgJson, null, 2), "utf-8");
|
|
485
|
-
const pkgSpec = `${PACKAGE_NAME}@${
|
|
485
|
+
const pkgSpec = `${PACKAGE_NAME}@${version}`;
|
|
486
486
|
const cmd = `npm install "${pkgSpec}" --save --legacy-peer-deps`;
|
|
487
487
|
execSync(cmd, { cwd: targetDir, stdio: "pipe", timeout: 120000 });
|
|
488
488
|
const entryPath = path2.join(targetDir, "node_modules", PACKAGE_NAME, "dist", "index.js");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/context/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAe,aAAa,EAAkC,MAAM,SAAS,CAAC;AAK3G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEzD,qBAAa,aAAa;IACxB,8BAA8B;IAC9B,OAAO,CAAC,QAAQ,CAAkC;IAClD,sBAAsB;IACtB,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAU9D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAYtD;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,GAClC,OAAO,CAAC,IAAI,CAAC;IAsChB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;;OAIG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiBxD;;;OAGG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/context/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAe,aAAa,EAAkC,MAAM,SAAS,CAAC;AAK3G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEzD,qBAAa,aAAa;IACxB,8BAA8B;IAC9B,OAAO,CAAC,QAAQ,CAAkC;IAClD,sBAAsB;IACtB,OAAO,CAAC,eAAe,CAAuC;IAC9D,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAgB;gBAElB,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC;IAU9D;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IAYtD;;OAEG;IACG,gBAAgB,CACpB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,IAAI,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,GAClC,OAAO,CAAC,IAAI,CAAC;IAsChB;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAa7B;;;;OAIG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAiBxD;;;OAGG;IACH,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAkE/C;;;;;OAKG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAqDpG;;OAEG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe;IAI/C;;OAEG;IACH,wBAAwB,CAAC,QAAQ,GAAE,MAAuB,GAAG,IAAI;CAQlE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.test.d.ts","sourceRoot":"","sources":["../../src/context/engine.test.ts"],"names":[],"mappings":""}
|
|
@@ -32,6 +32,17 @@ export declare function extractDecisions(messages: SdkMessage[], maxDecisions: n
|
|
|
32
32
|
* 从 bash 输出中提取编译/测试错误。
|
|
33
33
|
*/
|
|
34
34
|
export declare function extractErrors(messages: SdkMessage[], maxErrors: number, windowSize: number): string[];
|
|
35
|
+
/**
|
|
36
|
+
* 估算文本的 token 数。
|
|
37
|
+
* 中文字符(CJK 及东亚表意区)按 1 token/字符,其余字符按 0.25 token/字符。
|
|
38
|
+
*/
|
|
39
|
+
export declare function estimateTokens(text: string): number;
|
|
40
|
+
/**
|
|
41
|
+
* 强制 prompt 预算约束。
|
|
42
|
+
* 若 full 的估算 token 数 ≤ maxTokens → 返回 full(完整保留);
|
|
43
|
+
* 否则 → 返回 base(丢弃全部 CoHub 注入后缀,只保留用户原始 prompt)。
|
|
44
|
+
*/
|
|
45
|
+
export declare function enforcePromptBudget(base: string, full: string, maxTokens: number): string;
|
|
35
46
|
/**
|
|
36
47
|
* 按 token 预算截断文本。
|
|
37
48
|
* P2-5: 估算规则区分中西文——中文字符(CJK 及东亚表意区)按 1 token/字符,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/context/extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAuB5C,yBAAyB;AACzB,UAAU,OAAO;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,sBAAsB;AACtB,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/context/extractor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAuB5C,yBAAyB;AACzB,UAAU,OAAO;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,sBAAsB;AACtB,UAAU,UAAU;IAClB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzB,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,UAAU,EAAE,EACtB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,YAAY,EAAE,CAmGhB;AAUD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,UAAU,EAAE,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAqBV;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,UAAU,EAAE,EACtB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAwBV;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAanD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAqBxE"}
|
package/dist/context/types.d.ts
CHANGED
|
@@ -41,6 +41,10 @@ export interface ContextConfig {
|
|
|
41
41
|
summarizeMaxTokens: number;
|
|
42
42
|
/** 从父 session 中扫描最近多少条消息 */
|
|
43
43
|
relevantMessageWindow: number;
|
|
44
|
+
/** 错误列表总字符上限 */
|
|
45
|
+
maxErrorTotalChars: number;
|
|
46
|
+
/** 依赖结果 keyOutput 截断字符数 */
|
|
47
|
+
dependencyKeyOutputChars: number;
|
|
44
48
|
}
|
|
45
49
|
/** 默认配置 */
|
|
46
50
|
export declare const DEFAULT_CONTEXT_CONFIG: ContextConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAEA,cAAc;AACd,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,eAAe;AACf,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iBAAiB;AACjB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,cAAc;AACd,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4BAA4B;IAC5B,qBAAqB,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/context/types.ts"],"names":[],"mappings":"AAEA,cAAc;AACd,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvE,eAAe;AACf,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iBAAiB;AACjB,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oBAAoB;AACpB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED,cAAc;AACd,MAAM,WAAW,aAAa;IAC5B,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC1C,kBAAkB;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,gCAAgC;IAChC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,uBAAuB;IACvB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4BAA4B;IAC5B,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB;IAChB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,2BAA2B;IAC3B,wBAAwB,EAAE,MAAM,CAAC;CAClC;AAED,WAAW;AACX,eAAO,MAAM,sBAAsB,EAAE,aAuBpC,CAAC"}
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAiIlD,QAAA,MAAM,WAAW,EAAE,MAgrBlB,CAAC;AAEF,eAAO,MAAM,MAAM,QAAc,CAAC;AAClC,eAAe,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -905,18 +905,30 @@ class TaskTracker {
|
|
|
905
905
|
lines.push("");
|
|
906
906
|
if (activeJobs.length > 0) {
|
|
907
907
|
lines.push("#### Active / Unreconciled");
|
|
908
|
-
|
|
908
|
+
const maxShow = 15;
|
|
909
|
+
const shown = activeJobs.slice(0, maxShow);
|
|
910
|
+
for (const j of shown) {
|
|
909
911
|
lines.push(` - ${j.agent} / ${j.status} / ${j.sessionId || "pending"} / alias=${j.alias}`);
|
|
910
912
|
}
|
|
913
|
+
const extra = activeJobs.length - maxShow;
|
|
914
|
+
if (extra > 0) {
|
|
915
|
+
lines.push(` …及 ${extra} 个任务未显示`);
|
|
916
|
+
}
|
|
911
917
|
lines.push("");
|
|
912
918
|
}
|
|
913
919
|
if (reusableJobs.length > 0) {
|
|
914
920
|
lines.push("#### Reusable Sessions");
|
|
915
921
|
lines.push(" Session ID | Agent | Alias");
|
|
916
922
|
lines.push(" ---------------------------------------|--------------|-------");
|
|
917
|
-
|
|
923
|
+
const maxShow = 15;
|
|
924
|
+
const shown = reusableJobs.slice(0, maxShow);
|
|
925
|
+
for (const j of shown) {
|
|
918
926
|
lines.push(` \`${j.sessionId}\` | ${j.agent} | _${j.alias}_`);
|
|
919
927
|
}
|
|
928
|
+
const extra = reusableJobs.length - maxShow;
|
|
929
|
+
if (extra > 0) {
|
|
930
|
+
lines.push(` …及 ${extra} 个任务未显示`);
|
|
931
|
+
}
|
|
920
932
|
lines.push("");
|
|
921
933
|
}
|
|
922
934
|
return lines.join(`
|
|
@@ -942,6 +954,19 @@ class TaskTracker {
|
|
|
942
954
|
this.persistStats();
|
|
943
955
|
return staleSessions;
|
|
944
956
|
}
|
|
957
|
+
pruneTerminalJobs(olderThanMs) {
|
|
958
|
+
const now = Date.now();
|
|
959
|
+
const toDelete = [];
|
|
960
|
+
for (const [alias, job] of this.jobs) {
|
|
961
|
+
if (job.terminalReconciled && job.status !== "running" && now - job.createdAt > olderThanMs) {
|
|
962
|
+
toDelete.push(alias);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
for (const alias of toDelete) {
|
|
966
|
+
this.jobs.delete(alias);
|
|
967
|
+
}
|
|
968
|
+
return toDelete.length;
|
|
969
|
+
}
|
|
945
970
|
isReusable(alias) {
|
|
946
971
|
const job = this.jobs.get(alias);
|
|
947
972
|
return job?.status === "completed" && job.terminalReconciled;
|
|
@@ -1221,7 +1246,9 @@ var DEFAULT_CONTEXT_CONFIG = {
|
|
|
1221
1246
|
maxDependencies: 8,
|
|
1222
1247
|
dependencyPropagation: true,
|
|
1223
1248
|
summarizeMaxTokens: 2000,
|
|
1224
|
-
relevantMessageWindow: 20
|
|
1249
|
+
relevantMessageWindow: 20,
|
|
1250
|
+
maxErrorTotalChars: 600,
|
|
1251
|
+
dependencyKeyOutputChars: 200
|
|
1225
1252
|
};
|
|
1226
1253
|
|
|
1227
1254
|
// src/context/engine.ts
|
|
@@ -1278,12 +1305,12 @@ function extractRelevantFiles(messages, maxFiles, windowSize) {
|
|
|
1278
1305
|
if (part.type === "tool" && part.state) {
|
|
1279
1306
|
const state = part.state;
|
|
1280
1307
|
const input = state.input ?? {};
|
|
1281
|
-
const
|
|
1282
|
-
if (
|
|
1283
|
-
if (!fileMap.has(
|
|
1284
|
-
fileMap.set(
|
|
1308
|
+
const path = extractPath(input);
|
|
1309
|
+
if (path) {
|
|
1310
|
+
if (!fileMap.has(path)) {
|
|
1311
|
+
fileMap.set(path, { path, summary: "" });
|
|
1285
1312
|
}
|
|
1286
|
-
const existing = fileMap.get(
|
|
1313
|
+
const existing = fileMap.get(path);
|
|
1287
1314
|
if (typeof input.offset === "number") {
|
|
1288
1315
|
const limit = typeof input.limit === "number" ? input.limit : 50;
|
|
1289
1316
|
existing.lines = `${input.offset}-${input.offset + limit}`;
|
|
@@ -1342,7 +1369,18 @@ function extractRelevantFiles(messages, maxFiles, windowSize) {
|
|
|
1342
1369
|
}
|
|
1343
1370
|
}
|
|
1344
1371
|
}
|
|
1345
|
-
|
|
1372
|
+
const DENY_PATTERNS = [
|
|
1373
|
+
/node_modules/,
|
|
1374
|
+
/\.git\//,
|
|
1375
|
+
/\.config[\\\/]opencode/,
|
|
1376
|
+
/\.local[\\\/]share/,
|
|
1377
|
+
/storage[\\\/]oh-my-opencode-cohub/,
|
|
1378
|
+
/oh-my-opencode-cohub\.schema\.json$/,
|
|
1379
|
+
/stats\.json$/,
|
|
1380
|
+
/\.log$/
|
|
1381
|
+
];
|
|
1382
|
+
const isDenied = (path) => DENY_PATTERNS.some((p) => p.test(path));
|
|
1383
|
+
return Array.from(fileMap.values()).filter((f) => !isDenied(f.path)).slice(0, maxFiles);
|
|
1346
1384
|
}
|
|
1347
1385
|
function extractPath(obj) {
|
|
1348
1386
|
if (typeof obj.filePath === "string")
|
|
@@ -1393,8 +1431,8 @@ function extractErrors(messages, maxErrors, windowSize) {
|
|
|
1393
1431
|
const lines = output.split(`
|
|
1394
1432
|
`);
|
|
1395
1433
|
for (const line of lines) {
|
|
1396
|
-
if (errorPatterns.test(line)
|
|
1397
|
-
errors.push(line.trim());
|
|
1434
|
+
if (errorPatterns.test(line)) {
|
|
1435
|
+
errors.push(line.trim().slice(0, 200));
|
|
1398
1436
|
if (errors.length >= maxErrors)
|
|
1399
1437
|
return errors;
|
|
1400
1438
|
}
|
|
@@ -1403,9 +1441,25 @@ function extractErrors(messages, maxErrors, windowSize) {
|
|
|
1403
1441
|
}
|
|
1404
1442
|
return errors;
|
|
1405
1443
|
}
|
|
1444
|
+
function estimateTokens(text) {
|
|
1445
|
+
let used = 0;
|
|
1446
|
+
for (let i = 0;i < text.length; i++) {
|
|
1447
|
+
const code = text.charCodeAt(i);
|
|
1448
|
+
const isCjk = code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 63744 && code <= 64255 || code >= 12352 && code <= 12543 || code >= 44032 && code <= 55215;
|
|
1449
|
+
used += isCjk ? 1 : 0.25;
|
|
1450
|
+
}
|
|
1451
|
+
return used;
|
|
1452
|
+
}
|
|
1453
|
+
function enforcePromptBudget(base, full, maxTokens) {
|
|
1454
|
+
if (estimateTokens(full) <= maxTokens)
|
|
1455
|
+
return full;
|
|
1456
|
+
return truncateByTokens(base, maxTokens);
|
|
1457
|
+
}
|
|
1406
1458
|
function truncateByTokens(text, maxTokens) {
|
|
1407
1459
|
if (!text || maxTokens <= 0)
|
|
1408
1460
|
return "";
|
|
1461
|
+
if (estimateTokens(text) <= maxTokens)
|
|
1462
|
+
return text;
|
|
1409
1463
|
let used = 0;
|
|
1410
1464
|
let cut = text.length;
|
|
1411
1465
|
for (let i = 0;i < text.length; i++) {
|
|
@@ -1417,8 +1471,6 @@ function truncateByTokens(text, maxTokens) {
|
|
|
1417
1471
|
break;
|
|
1418
1472
|
}
|
|
1419
1473
|
}
|
|
1420
|
-
if (cut >= text.length)
|
|
1421
|
-
return text;
|
|
1422
1474
|
return text.slice(0, cut) + `
|
|
1423
1475
|
… [正文已按 token 预算截断]`;
|
|
1424
1476
|
}
|
|
@@ -1590,14 +1642,26 @@ class ContextEngine {
|
|
|
1590
1642
|
}
|
|
1591
1643
|
if (context.errors.length > 0) {
|
|
1592
1644
|
parts.push("### ⚠️ 近期错误");
|
|
1645
|
+
let totalChars = 0;
|
|
1646
|
+
let omitted = 0;
|
|
1593
1647
|
for (const e of context.errors) {
|
|
1594
|
-
|
|
1648
|
+
const line = `- ${e}`;
|
|
1649
|
+
if (totalChars + line.length > this.config.maxErrorTotalChars) {
|
|
1650
|
+
omitted++;
|
|
1651
|
+
} else {
|
|
1652
|
+
parts.push(line);
|
|
1653
|
+
totalChars += line.length;
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
if (omitted > 0) {
|
|
1657
|
+
parts.push(`…(错误已省略 ${omitted} 条)`);
|
|
1595
1658
|
}
|
|
1596
1659
|
}
|
|
1597
1660
|
if (context.dependencies.length > 0) {
|
|
1598
1661
|
parts.push("### \uD83D\uDCE6 依赖结果");
|
|
1599
1662
|
for (const dep of context.dependencies) {
|
|
1600
|
-
|
|
1663
|
+
const output = dep.keyOutput.length > this.config.dependencyKeyOutputChars ? dep.keyOutput.slice(0, this.config.dependencyKeyOutputChars) + "…" : dep.keyOutput;
|
|
1664
|
+
parts.push(`- **${dep.agent}**: ${output}`);
|
|
1601
1665
|
}
|
|
1602
1666
|
}
|
|
1603
1667
|
return parts.length > 0 ? `
|
|
@@ -1622,7 +1686,7 @@ class ContextEngine {
|
|
|
1622
1686
|
}
|
|
1623
1687
|
for (const part of messages[i].parts ?? []) {
|
|
1624
1688
|
if (part.type === "text" && part.text) {
|
|
1625
|
-
keyOutput = part.text.slice(0,
|
|
1689
|
+
keyOutput = part.text.slice(0, this.config.dependencyKeyOutputChars).replace(/\n/g, " ");
|
|
1626
1690
|
break;
|
|
1627
1691
|
}
|
|
1628
1692
|
}
|
|
@@ -1942,12 +2006,12 @@ async function abortSession(client, sessionId) {
|
|
|
1942
2006
|
appendLog("abortSession", "中止会话失败", err);
|
|
1943
2007
|
}
|
|
1944
2008
|
}
|
|
1945
|
-
async function promptWithTimeout(client,
|
|
1946
|
-
const sessionId =
|
|
2009
|
+
async function promptWithTimeout(client, path, body, timeoutMs, directory) {
|
|
2010
|
+
const sessionId = path.id;
|
|
1947
2011
|
let timer;
|
|
1948
2012
|
try {
|
|
1949
2013
|
const promptPromise = client.session.prompt({
|
|
1950
|
-
path
|
|
2014
|
+
path,
|
|
1951
2015
|
body,
|
|
1952
2016
|
query: directory ? { directory } : undefined
|
|
1953
2017
|
});
|
|
@@ -2075,8 +2139,8 @@ ${cr.result}`).join(`
|
|
|
2075
2139
|
function formatModelComposition(councillorResults) {
|
|
2076
2140
|
return councillorResults.map((cr) => `${cr.name}: ${shortModelLabel(cr.model)}`).join(", ");
|
|
2077
2141
|
}
|
|
2078
|
-
function adaptiveKey(
|
|
2079
|
-
return `${
|
|
2142
|
+
function adaptiveKey(config) {
|
|
2143
|
+
return `${config.variant ?? "default"}\x00${config.model}`;
|
|
2080
2144
|
}
|
|
2081
2145
|
function classifyFailure(message) {
|
|
2082
2146
|
if (message.includes("Empty response from provider"))
|
|
@@ -2298,10 +2362,10 @@ class CouncilManager {
|
|
|
2298
2362
|
client;
|
|
2299
2363
|
directory;
|
|
2300
2364
|
config;
|
|
2301
|
-
constructor(client, directory,
|
|
2365
|
+
constructor(client, directory, config) {
|
|
2302
2366
|
this.client = client;
|
|
2303
2367
|
this.directory = directory;
|
|
2304
|
-
this.config =
|
|
2368
|
+
this.config = config;
|
|
2305
2369
|
}
|
|
2306
2370
|
async runCouncil(prompt, presetName, parentSessionId) {
|
|
2307
2371
|
const resolvedPreset = presetName ?? this.config.default_preset ?? "default";
|
|
@@ -2351,8 +2415,8 @@ class CouncilManager {
|
|
|
2351
2415
|
const results = [];
|
|
2352
2416
|
const explicitTimeout = this.config.timeout;
|
|
2353
2417
|
const explicitRetries = this.config.councillor_retries;
|
|
2354
|
-
const resolveParams = (
|
|
2355
|
-
const p = getAdaptiveParams(adaptiveKey(
|
|
2418
|
+
const resolveParams = (config) => {
|
|
2419
|
+
const p = getAdaptiveParams(adaptiveKey(config), {
|
|
2356
2420
|
...DEFAULT_ADAPTIVE_CONFIG,
|
|
2357
2421
|
defaultTimeoutMs: explicitTimeout ?? timeout,
|
|
2358
2422
|
defaultRetries: explicitRetries ?? 3
|
|
@@ -2367,10 +2431,10 @@ class CouncilManager {
|
|
|
2367
2431
|
for (let round = 1;round <= options.maxRounds; round++) {
|
|
2368
2432
|
const roundResults = [];
|
|
2369
2433
|
const firstAttemptIsExtra = round > 1;
|
|
2370
|
-
for (const [name,
|
|
2371
|
-
const params = resolveParams(
|
|
2434
|
+
for (const [name, config] of entries) {
|
|
2435
|
+
const params = resolveParams(config);
|
|
2372
2436
|
const roundPrompt = round > 1 ? buildDeliberationPrompt(prompt, lastRound, name) : prompt;
|
|
2373
|
-
const r = await this.runCouncillorWithRetry(name,
|
|
2437
|
+
const r = await this.runCouncillorWithRetry(name, config, roundPrompt, parentSessionId, params.timeout, budget, { firstAttemptIsExtra, retries: params.retries });
|
|
2374
2438
|
roundResults.push(r);
|
|
2375
2439
|
}
|
|
2376
2440
|
lastRound = roundResults;
|
|
@@ -2381,9 +2445,9 @@ class CouncilManager {
|
|
|
2381
2445
|
}
|
|
2382
2446
|
results.push(...lastRound);
|
|
2383
2447
|
} else {
|
|
2384
|
-
const promises = entries.map(([name,
|
|
2385
|
-
const params = resolveParams(
|
|
2386
|
-
return this.runCouncillorWithRetry(name,
|
|
2448
|
+
const promises = entries.map(([name, config]) => {
|
|
2449
|
+
const params = resolveParams(config);
|
|
2450
|
+
return this.runCouncillorWithRetry(name, config, prompt, parentSessionId, params.timeout, budget, { retries: params.retries });
|
|
2387
2451
|
});
|
|
2388
2452
|
const settled = await Promise.allSettled(promises);
|
|
2389
2453
|
for (let i = 0;i < settled.length; i++) {
|
|
@@ -2403,37 +2467,37 @@ class CouncilManager {
|
|
|
2403
2467
|
}
|
|
2404
2468
|
return results;
|
|
2405
2469
|
}
|
|
2406
|
-
async runCouncillorWithRetry(name,
|
|
2407
|
-
let attemptPrompt = formatCouncillorPrompt(prompt,
|
|
2408
|
-
let attemptVariant =
|
|
2470
|
+
async runCouncillorWithRetry(name, config, prompt, parentSessionId, timeout, budget, options) {
|
|
2471
|
+
let attemptPrompt = formatCouncillorPrompt(prompt, config.prompt);
|
|
2472
|
+
let attemptVariant = config.variant;
|
|
2409
2473
|
let lastCategory = null;
|
|
2410
2474
|
let streak = 0;
|
|
2411
2475
|
const categoryRetries = {};
|
|
2412
2476
|
let attempt = 1;
|
|
2413
2477
|
for (;; ) {
|
|
2414
2478
|
if (budget.expired()) {
|
|
2415
|
-
return { name, model:
|
|
2479
|
+
return { name, model: config.model, status: "error", error: "budget-exhausted" };
|
|
2416
2480
|
}
|
|
2417
2481
|
const isExtraAttempt = attempt > 1 || options?.firstAttemptIsExtra === true;
|
|
2418
2482
|
if (isExtraAttempt && !budget.consumeRetry()) {
|
|
2419
|
-
return { name, model:
|
|
2483
|
+
return { name, model: config.model, status: "error", error: "budget-exhausted" };
|
|
2420
2484
|
}
|
|
2421
2485
|
let category;
|
|
2422
2486
|
let errorInfo;
|
|
2423
2487
|
try {
|
|
2424
2488
|
const session = await this.runAgentSession({
|
|
2425
2489
|
parentSessionId,
|
|
2426
|
-
title: `Council ${name} (${shortModelLabel(
|
|
2427
|
-
model:
|
|
2490
|
+
title: `Council ${name} (${shortModelLabel(config.model)})`,
|
|
2491
|
+
model: config.model,
|
|
2428
2492
|
promptText: attemptPrompt,
|
|
2429
2493
|
variant: attemptVariant,
|
|
2430
2494
|
timeout
|
|
2431
2495
|
});
|
|
2432
2496
|
const quality = assessQuality({ output: session.text, decisions: session.summary.entities.length });
|
|
2433
2497
|
if (quality.passed) {
|
|
2434
|
-
recordModelResult(
|
|
2435
|
-
recordAdaptiveSample(adaptiveKey(
|
|
2436
|
-
return { name, model:
|
|
2498
|
+
recordModelResult(config.model, "success");
|
|
2499
|
+
recordAdaptiveSample(adaptiveKey(config), true);
|
|
2500
|
+
return { name, model: config.model, status: "completed", result: session.text, summary: session.summary };
|
|
2437
2501
|
}
|
|
2438
2502
|
category = quality.failureCategory ?? "quality-low";
|
|
2439
2503
|
errorInfo = `Councillor "${name}": quality score ${quality.score} (${category})`;
|
|
@@ -2442,8 +2506,8 @@ class CouncilManager {
|
|
|
2442
2506
|
category = classifyFailure(msg);
|
|
2443
2507
|
errorInfo = `Councillor "${name}": ${msg}`;
|
|
2444
2508
|
}
|
|
2445
|
-
recordModelResult(
|
|
2446
|
-
recordAdaptiveSample(adaptiveKey(
|
|
2509
|
+
recordModelResult(config.model, category);
|
|
2510
|
+
recordAdaptiveSample(adaptiveKey(config), false);
|
|
2447
2511
|
streak = lastCategory === category ? streak + 1 : 1;
|
|
2448
2512
|
lastCategory = category;
|
|
2449
2513
|
const used = categoryRetries[category] ?? 0;
|
|
@@ -2452,18 +2516,18 @@ class CouncilManager {
|
|
|
2452
2516
|
if (action === "needs-human") {
|
|
2453
2517
|
return {
|
|
2454
2518
|
name,
|
|
2455
|
-
model:
|
|
2519
|
+
model: config.model,
|
|
2456
2520
|
status: "needs_human",
|
|
2457
2521
|
error: `${errorInfo} — ${streak} consecutive ${category} failures, needs human review`
|
|
2458
2522
|
};
|
|
2459
2523
|
}
|
|
2460
2524
|
if (action === "budget-exhausted") {
|
|
2461
|
-
return { name, model:
|
|
2525
|
+
return { name, model: config.model, status: "error", error: "budget-exhausted" };
|
|
2462
2526
|
}
|
|
2463
2527
|
if (action === "give-up") {
|
|
2464
2528
|
return {
|
|
2465
2529
|
name,
|
|
2466
|
-
model:
|
|
2530
|
+
model: config.model,
|
|
2467
2531
|
status: category === "timeout" ? "timed_out" : "failed",
|
|
2468
2532
|
error: errorInfo
|
|
2469
2533
|
};
|
|
@@ -2819,6 +2883,10 @@ class OrchestrationEngine {
|
|
|
2819
2883
|
|
|
2820
2884
|
// src/orchestration/contract.ts
|
|
2821
2885
|
var CONTRACT_PATTERN = /<!-- CONTRACT_BEGIN -->\n([\s\S]*?)<!-- CONTRACT_END -->/;
|
|
2886
|
+
var CONTRACT_STRIP_PATTERN = /<!-- CONTRACT_BEGIN -->[\s\S]*?<!-- CONTRACT_END -->/g;
|
|
2887
|
+
function stripExistingContracts(text) {
|
|
2888
|
+
return text.replace(CONTRACT_STRIP_PATTERN, "");
|
|
2889
|
+
}
|
|
2822
2890
|
|
|
2823
2891
|
class ContractManager {
|
|
2824
2892
|
extract(output) {
|
|
@@ -2971,15 +3039,16 @@ class Scheduler {
|
|
|
2971
3039
|
}
|
|
2972
3040
|
|
|
2973
3041
|
// src/orchestration/index.ts
|
|
2974
|
-
function createOrchestrationLayer(tracker,
|
|
3042
|
+
function createOrchestrationLayer(tracker, config) {
|
|
2975
3043
|
const contractMgr = new ContractManager;
|
|
2976
|
-
const retryMgr = new RetryManager(
|
|
3044
|
+
const retryMgr = new RetryManager(config?.retryPolicies);
|
|
2977
3045
|
const engine = new OrchestrationEngine(contractMgr, retryMgr);
|
|
2978
|
-
const scheduler = new Scheduler(engine,
|
|
3046
|
+
const scheduler = new Scheduler(engine, config?.concurrency?.maxConcurrency);
|
|
2979
3047
|
return { engine, contractMgr, retryMgr, scheduler };
|
|
2980
3048
|
}
|
|
2981
3049
|
|
|
2982
3050
|
// src/index.ts
|
|
3051
|
+
var DEFAULT_PROMPT_MAX_TOKENS = 12000;
|
|
2983
3052
|
function loadFileOverrides(projectDir) {
|
|
2984
3053
|
const overrides = {};
|
|
2985
3054
|
const agentNames = [
|
|
@@ -3301,40 +3370,45 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3301
3370
|
} catch (err) {
|
|
3302
3371
|
appendLog("config", "双重注册写入文件失败", err);
|
|
3303
3372
|
}
|
|
3304
|
-
appendLog("config.hook", `config hook 注入完成: ${JSON.stringify(Object.entries(agentConfigs).map(([name,
|
|
3305
|
-
const
|
|
3306
|
-
const prompt = typeof
|
|
3373
|
+
appendLog("config.hook", `config hook 注入完成: ${JSON.stringify(Object.entries(agentConfigs).map(([name, cfg]) => {
|
|
3374
|
+
const c = cfg;
|
|
3375
|
+
const prompt = typeof c.prompt === "string" ? c.prompt : "";
|
|
3307
3376
|
return {
|
|
3308
3377
|
name,
|
|
3309
3378
|
promptLen: prompt.length,
|
|
3310
3379
|
promptPreview: prompt.slice(0, 120),
|
|
3311
|
-
hasModel: !!
|
|
3312
|
-
hasVariant: !!
|
|
3380
|
+
hasModel: !!c.model,
|
|
3381
|
+
hasVariant: !!c.variant
|
|
3313
3382
|
};
|
|
3314
3383
|
}))}`);
|
|
3315
3384
|
},
|
|
3316
|
-
"tool.execute.before": async (
|
|
3385
|
+
"tool.execute.before": async (input, output) => {
|
|
3317
3386
|
try {
|
|
3318
|
-
if (
|
|
3387
|
+
if (input.tool === "task") {
|
|
3388
|
+
const rawPrompt = typeof output.args?.prompt === "string" ? output.args.prompt : "";
|
|
3389
|
+
const rawDesc = typeof output.args?.description === "string" ? output.args.description : "";
|
|
3390
|
+
const basePrompt = rawPrompt || rawDesc || "";
|
|
3319
3391
|
const args = output.args ?? {};
|
|
3320
3392
|
const subagentType = typeof args.subagent_type === "string" ? args.subagent_type : "";
|
|
3321
3393
|
const description = typeof args.description === "string" ? args.description : "";
|
|
3322
3394
|
if (typeof args.task_id === "string" && args.task_id !== "" && !args.task_id.startsWith("ses_")) {
|
|
3323
3395
|
delete output.args.task_id;
|
|
3324
3396
|
}
|
|
3325
|
-
const alias = tracker.registerBeforeTask(
|
|
3397
|
+
const alias = tracker.registerBeforeTask(input.sessionID, {
|
|
3326
3398
|
description,
|
|
3327
3399
|
subagent_type: subagentType,
|
|
3328
3400
|
task_id: typeof output.args.task_id === "string" && output.args.task_id.startsWith("ses_") ? output.args.task_id : undefined,
|
|
3329
3401
|
background: typeof args.background === "boolean" ? args.background : undefined
|
|
3330
3402
|
});
|
|
3331
3403
|
_lastAlias = alias;
|
|
3332
|
-
syncTrackerState(
|
|
3404
|
+
syncTrackerState(input.sessionID ?? "");
|
|
3405
|
+
tracker.pruneTerminalJobs(30 * 60 * 1000);
|
|
3333
3406
|
if (orchestrationLayer && subagentType && description) {
|
|
3334
3407
|
try {
|
|
3335
3408
|
orchestrationLayer.engine.registerTask(alias, subagentType, description, []);
|
|
3336
3409
|
const targetField = output.args?.prompt ? "prompt" : "description";
|
|
3337
3410
|
if (output.args?.[targetField] && typeof output.args[targetField] === "string") {
|
|
3411
|
+
output.args[targetField] = stripExistingContracts(output.args[targetField]);
|
|
3338
3412
|
output.args[targetField] += `
|
|
3339
3413
|
` + orchestrationLayer.contractMgr.buildPrompt({
|
|
3340
3414
|
goal: description,
|
|
@@ -3358,7 +3432,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3358
3432
|
`;
|
|
3359
3433
|
const targetField = typeof output.args.prompt === "string" ? "prompt" : "description";
|
|
3360
3434
|
output.args[targetField] = ((targetField === "prompt" ? output.args.prompt : description) ?? "") + contextBlock;
|
|
3361
|
-
await contextEngine.fillContextAsync(contextId,
|
|
3435
|
+
await contextEngine.fillContextAsync(contextId, input.sessionID, {
|
|
3362
3436
|
strategy
|
|
3363
3437
|
});
|
|
3364
3438
|
const details = contextEngine.formatContextDetails(contextId);
|
|
@@ -3379,7 +3453,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3379
3453
|
const finalPrompt = typeof output.args?.prompt === "string" ? output.args.prompt : "";
|
|
3380
3454
|
fs5.appendFileSync(logPath, JSON.stringify({
|
|
3381
3455
|
time: new Date().toISOString(),
|
|
3382
|
-
session:
|
|
3456
|
+
session: input.sessionID?.slice(0, 20) ?? "?",
|
|
3383
3457
|
subagent: subagentType,
|
|
3384
3458
|
strategy,
|
|
3385
3459
|
targetField,
|
|
@@ -3391,25 +3465,29 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3391
3465
|
`);
|
|
3392
3466
|
}
|
|
3393
3467
|
}
|
|
3468
|
+
const targetField = typeof output.args?.prompt === "string" ? "prompt" : "description";
|
|
3469
|
+
if (output.args?.[targetField] && typeof output.args[targetField] === "string") {
|
|
3470
|
+
output.args[targetField] = enforcePromptBudget(basePrompt, output.args[targetField], DEFAULT_PROMPT_MAX_TOKENS);
|
|
3471
|
+
}
|
|
3394
3472
|
}
|
|
3395
3473
|
} catch (err) {
|
|
3396
3474
|
appendLog("tool.execute.before", "hook 失败", err);
|
|
3397
3475
|
}
|
|
3398
3476
|
},
|
|
3399
|
-
"tool.execute.after": async (
|
|
3477
|
+
"tool.execute.after": async (input, output) => {
|
|
3400
3478
|
try {
|
|
3401
|
-
if (
|
|
3402
|
-
const args =
|
|
3479
|
+
if (input.tool === "cancel_task") {
|
|
3480
|
+
const args = input.args;
|
|
3403
3481
|
const taskId = args?.task_id;
|
|
3404
3482
|
if (typeof taskId === "string")
|
|
3405
3483
|
tracker.markCancelled(taskId);
|
|
3406
|
-
syncTrackerState(
|
|
3484
|
+
syncTrackerState(input.sessionID ?? "");
|
|
3407
3485
|
}
|
|
3408
|
-
if (
|
|
3486
|
+
if (input.tool === "task") {
|
|
3409
3487
|
const childSessionId = extractChildSessionId(output);
|
|
3410
|
-
tracker.updateAfterTask(
|
|
3411
|
-
syncTrackerState(
|
|
3412
|
-
if (orchestrationLayer &&
|
|
3488
|
+
tracker.updateAfterTask(input.sessionID, "completed", childSessionId);
|
|
3489
|
+
syncTrackerState(input.sessionID ?? "");
|
|
3490
|
+
if (orchestrationLayer && input.tool === "task") {
|
|
3413
3491
|
try {
|
|
3414
3492
|
if (typeof output === "string") {
|
|
3415
3493
|
const contract = orchestrationLayer.contractMgr.extract(output);
|
|
@@ -3427,9 +3505,9 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3427
3505
|
appendLog("tool.execute.after", "hook 失败", err);
|
|
3428
3506
|
}
|
|
3429
3507
|
},
|
|
3430
|
-
event: async (
|
|
3508
|
+
event: async (input) => {
|
|
3431
3509
|
try {
|
|
3432
|
-
const e =
|
|
3510
|
+
const e = input.event;
|
|
3433
3511
|
const sessionId = extractSessionIdFromEvent(e.properties);
|
|
3434
3512
|
if (!sessionId)
|
|
3435
3513
|
return;
|
|
@@ -3438,13 +3516,13 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3438
3516
|
syncTrackerState(tracker.currentParentSessionId);
|
|
3439
3517
|
if (orchestrationLayer) {
|
|
3440
3518
|
try {
|
|
3441
|
-
const
|
|
3442
|
-
if (
|
|
3443
|
-
orchestrationLayer.engine.transition(
|
|
3444
|
-
orchestrationLayer.scheduler.markCompleted(
|
|
3519
|
+
const job = tracker.getJobBySessionId(sessionId);
|
|
3520
|
+
if (job) {
|
|
3521
|
+
orchestrationLayer.engine.transition(job.alias, "completed");
|
|
3522
|
+
orchestrationLayer.scheduler.markCompleted(job.alias);
|
|
3445
3523
|
}
|
|
3446
|
-
} catch (
|
|
3447
|
-
appendLog("orchestration", "session.idle transition error",
|
|
3524
|
+
} catch (e) {
|
|
3525
|
+
appendLog("orchestration", "session.idle transition error", e);
|
|
3448
3526
|
}
|
|
3449
3527
|
}
|
|
3450
3528
|
const job = tracker.getJobBySessionId(sessionId);
|
|
@@ -3486,8 +3564,8 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3486
3564
|
}
|
|
3487
3565
|
}
|
|
3488
3566
|
}
|
|
3489
|
-
} catch (
|
|
3490
|
-
appendLog("orchestration", "session.deleted transition error",
|
|
3567
|
+
} catch (e) {
|
|
3568
|
+
appendLog("orchestration", "session.deleted transition error", e);
|
|
3491
3569
|
}
|
|
3492
3570
|
}
|
|
3493
3571
|
} else if (e.type === "session.error") {
|
|
@@ -3507,8 +3585,8 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3507
3585
|
}
|
|
3508
3586
|
}
|
|
3509
3587
|
}
|
|
3510
|
-
} catch (
|
|
3511
|
-
appendLog("orchestration", "session.error transition error",
|
|
3588
|
+
} catch (e) {
|
|
3589
|
+
appendLog("orchestration", "session.error transition error", e);
|
|
3512
3590
|
}
|
|
3513
3591
|
}
|
|
3514
3592
|
}
|
|
@@ -3589,7 +3667,7 @@ var CoHubPlugin = async (input, options) => {
|
|
|
3589
3667
|
appendLog("messages.transform", "hook 失败", err);
|
|
3590
3668
|
}
|
|
3591
3669
|
},
|
|
3592
|
-
"experimental.chat.system.transform": async (
|
|
3670
|
+
"experimental.chat.system.transform": async (input, output) => {
|
|
3593
3671
|
try {
|
|
3594
3672
|
if (output?.system && Array.isArray(output.system)) {
|
|
3595
3673
|
output.system.push(CHINESE_LANGUAGE_INSTRUCTION);
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { AgentContract } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 删除文本中所有 `<!-- CONTRACT_BEGIN -->...<!-- CONTRACT_END -->` 块。
|
|
4
|
+
* 用于防止同一次 task() 的 prompt 中契约块重复膨胀。
|
|
5
|
+
* 无匹配时原样返回。
|
|
6
|
+
*/
|
|
7
|
+
export declare function stripExistingContracts(text: string): string;
|
|
2
8
|
export declare class ContractManager {
|
|
3
9
|
/**
|
|
4
10
|
* 从代理输出中提取结构化契约块。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/orchestration/contract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../../src/orchestration/contract.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAK7C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,qBAAa,eAAe;IAC1B;;;OAGG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAM7C;;;OAGG;IACH,OAAO,CAAC,UAAU;IAqBlB;;;OAGG;IACH,WAAW,CAAC,OAAO,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,aAAa,CAAA;SAAE,EAAE,CAAC;QAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,GAAG,MAAM;IAuBV;;OAEG;IACH,SAAS,CAAC,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM;CAY9C"}
|
|
@@ -76,6 +76,14 @@ export declare class TaskTracker {
|
|
|
76
76
|
* @returns 被标为 errored 的超时任务的 sessionId 列表(无 sessionId 的任务不包含)
|
|
77
77
|
*/
|
|
78
78
|
cleanupStaleJobs(timeoutMs: number): string[];
|
|
79
|
+
/**
|
|
80
|
+
* 清理超龄终态任务:删除 terminalReconciled 且超过 olderThanMs 未更新的终态 job。
|
|
81
|
+
* 绝不会删除 running/pending 的活跃任务。
|
|
82
|
+
*
|
|
83
|
+
* @param olderThanMs 超龄阈值(毫秒),超过此时间的终态任务会被删除
|
|
84
|
+
* @returns 实际删除的任务数量
|
|
85
|
+
*/
|
|
86
|
+
pruneTerminalJobs(olderThanMs: number): number;
|
|
79
87
|
/**
|
|
80
88
|
* 检查任务是否可复用
|
|
81
89
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/task-manager/tracker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAwB;AACxB,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,mCAAmC;AACnC,eAAO,MAAM,UAAU,QAQtB,CAAC;AAWF,mBAAmB;AACnB,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEjE;AAED,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,GAAE,MAA6B,GAAG,WAAW,EAAE,CAsCzG;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAgC;IAC5C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,yCAAyC;IACzC,OAAO,CAAC,uBAAuB,CAAM;IACrC,kDAAkD;IAClD,OAAO,CAAC,oBAAoB,CAAM;IAElC,IAAI,sBAAsB,IAAI,MAAM,CAEnC;IAED,mDAAmD;IACnD,OAAO,CAAC,KAAK;IAOb;;OAEG;IACH,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM;IA+BnE;;;OAGG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IA2BtF;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAWnE;;OAEG;IACH,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM;
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/task-manager/tracker.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAwB;AACxB,eAAO,MAAM,oBAAoB,KAAK,CAAC;AAEvC,mCAAmC;AACnC,eAAO,MAAM,UAAU,QAQtB,CAAC;AAWF,mBAAmB;AACnB,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAEjE;AAED,gCAAgC;AAChC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED,iCAAiC;AACjC,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,MAAM,GAAE,MAA6B,GAAG,WAAW,EAAE,CAsCzG;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,IAAI,CAAgC;IAC5C,OAAO,CAAC,QAAQ,CAA6B;IAC7C,yCAAyC;IACzC,OAAO,CAAC,uBAAuB,CAAM;IACrC,kDAAkD;IAClD,OAAO,CAAC,oBAAoB,CAAM;IAElC,IAAI,sBAAsB,IAAI,MAAM,CAEnC;IAED,mDAAmD;IACnD,OAAO,CAAC,KAAK;IAOb;;OAEG;IACH,kBAAkB,CAAC,eAAe,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,MAAM;IA+BnE;;;OAGG;IACH,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI;IA2BtF;;;OAGG;IACH,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAWnE;;OAEG;IACH,YAAY,CAAC,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM;IAsF9C;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAOjC;;;;;;OAMG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE;IAc7C;;;;;;OAMG;IACH,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM;IAc9C;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAKlC,2BAA2B;IAC3B,gBAAgB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE;IAUnD,uBAAuB;IACvB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM;IAUhD,oCAAoC;IACpC,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAS3D;;;OAGG;IACH,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI;IAWlF;;;;OAIG;IACH,OAAO,CAAC,QAAQ;IAShB,6BAA6B;IAC7B,OAAO,CAAC,mBAAmB;IAa3B,sDAAsD;IACtD,QAAQ,CAAC,MAAM,GAAE,MAA6B,GAAG,WAAW,EAAE;IAI9D,wDAAwD;IACxD,YAAY,CAAC,MAAM,GAAE,MAA6B,GAAG,IAAI;IASzD,yDAAyD;IACzD,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAenC;;;;;;;;;OASG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,SAAS,CAAA;KAAE,GAAG,SAAS;CAqB7E"}
|