tianshu-harness 3.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +189 -0
- package/README.en.md +1066 -0
- package/README.ja.md +1214 -0
- package/README.ko.md +1216 -0
- package/README.md +309 -0
- package/completions/rivet.bash +118 -0
- package/completions/rivet.fish +110 -0
- package/completions/rivet.ps1 +230 -0
- package/completions/rivet.zsh +187 -0
- package/dist/account-OAEKORZE.js +47 -0
- package/dist/account-login-V6FOLHJR.js +65 -0
- package/dist/account-status-KHNPPAFL.js +23 -0
- package/dist/agent/worker-process/child.js +407 -0
- package/dist/browser-cli-FLNY5ZHI.js +19 -0
- package/dist/browser-readiness-LWVGSBD5.js +12 -0
- package/dist/build-backends-5KXKR2S4.js +13 -0
- package/dist/build-options-66Y4ZE7C.js +9 -0
- package/dist/bundled-skills/brainstorming/SKILL.md +139 -0
- package/dist/bundled-skills/visual-acceptance/SKILL.md +64 -0
- package/dist/chain-7MAMFXZ3.js +10 -0
- package/dist/checkpoint-MND4DUIX.js +33 -0
- package/dist/chunk-2E6CK2RC.js +392 -0
- package/dist/chunk-2EBWGAXD.js +51 -0
- package/dist/chunk-2HDP7RMR.js +119 -0
- package/dist/chunk-2HKD2UFM.js +1000 -0
- package/dist/chunk-2VYRLULP.js +51 -0
- package/dist/chunk-2XN7PM4N.js +125 -0
- package/dist/chunk-35H7GVNR.js +66 -0
- package/dist/chunk-3C3R7JXY.js +77 -0
- package/dist/chunk-3VGD2FXB.js +118 -0
- package/dist/chunk-424AP7FM.js +534 -0
- package/dist/chunk-4J5TZGOE.js +3707 -0
- package/dist/chunk-4QJ3Y5JM.js +898 -0
- package/dist/chunk-4U2ET7ZY.js +1326 -0
- package/dist/chunk-4XPFLICE.js +876 -0
- package/dist/chunk-5B2OCU5P.js +31707 -0
- package/dist/chunk-5GGOGLSN.js +73 -0
- package/dist/chunk-5JRZPLI6.js +251 -0
- package/dist/chunk-5TQ3JYBU.js +397 -0
- package/dist/chunk-66JPZSGX.js +55 -0
- package/dist/chunk-6HSVXHCZ.js +764 -0
- package/dist/chunk-6S5FPUS7.js +21 -0
- package/dist/chunk-722LQO64.js +131 -0
- package/dist/chunk-73NJ7IT7.js +354 -0
- package/dist/chunk-7FW3I7WC.js +95 -0
- package/dist/chunk-7KUCBNLB.js +173 -0
- package/dist/chunk-7RDOV3DF.js +201 -0
- package/dist/chunk-A5MNH4ER.js +79 -0
- package/dist/chunk-ADIVZ2D5.js +15 -0
- package/dist/chunk-AE3P3F6W.js +366 -0
- package/dist/chunk-AERM3VGP.js +280 -0
- package/dist/chunk-AEWHC4WM.js +246 -0
- package/dist/chunk-AOVQ7VIF.js +169 -0
- package/dist/chunk-AOYHP3WI.js +12411 -0
- package/dist/chunk-B3YEBABJ.js +7160 -0
- package/dist/chunk-BCQXEZPJ.js +154 -0
- package/dist/chunk-BKTQAYO2.js +418 -0
- package/dist/chunk-BSECIPAQ.js +80 -0
- package/dist/chunk-BUIMGNDD.js +52 -0
- package/dist/chunk-BXHV3GSB.js +10320 -0
- package/dist/chunk-C6ZVZCPP.js +139 -0
- package/dist/chunk-CEZNQVWM.js +82 -0
- package/dist/chunk-CGFZGR7G.js +1492 -0
- package/dist/chunk-CGOADM2X.js +337 -0
- package/dist/chunk-CI4R6P2B.js +24 -0
- package/dist/chunk-D2TCGRSX.js +73 -0
- package/dist/chunk-D4PTYFOG.js +154 -0
- package/dist/chunk-D54ZWG4T.js +717 -0
- package/dist/chunk-DEBI37QB.js +145 -0
- package/dist/chunk-DWROHPXP.js +1051 -0
- package/dist/chunk-DZ6UOJ5D.js +92 -0
- package/dist/chunk-EBJTVRQN.js +81 -0
- package/dist/chunk-EGEI2RQA.js +1167 -0
- package/dist/chunk-EHHUASO5.js +1305 -0
- package/dist/chunk-EPKTIOED.js +41 -0
- package/dist/chunk-ER5JW2QZ.js +5681 -0
- package/dist/chunk-ETHFACAB.js +315 -0
- package/dist/chunk-EXUE5W2F.js +112 -0
- package/dist/chunk-EXXICUIW.js +73 -0
- package/dist/chunk-FFQSZJOO.js +169 -0
- package/dist/chunk-FHFKPGDO.js +85 -0
- package/dist/chunk-FW3QKMFX.js +158 -0
- package/dist/chunk-GD4ZNZ7W.js +30 -0
- package/dist/chunk-GHVMWF2I.js +581 -0
- package/dist/chunk-GMKAXSYQ.js +297 -0
- package/dist/chunk-HBVF6BWO.js +325 -0
- package/dist/chunk-HV4YGVMS.js +379 -0
- package/dist/chunk-ILBCKAV6.js +89 -0
- package/dist/chunk-J4U4AW46.js +440 -0
- package/dist/chunk-J6ESSM47.js +1791 -0
- package/dist/chunk-JBZHIC6T.js +2309 -0
- package/dist/chunk-JCFWOULR.js +245 -0
- package/dist/chunk-JRF5L6OD.js +131 -0
- package/dist/chunk-JSS75KCG.js +2014 -0
- package/dist/chunk-JSXWIWWJ.js +225 -0
- package/dist/chunk-JYV7I2QH.js +98 -0
- package/dist/chunk-KIOXTQQL.js +1596 -0
- package/dist/chunk-KWVTXT5B.js +89 -0
- package/dist/chunk-KX22RD6R.js +33 -0
- package/dist/chunk-LA6IPTGH.js +709 -0
- package/dist/chunk-LH5VCGLB.js +1796 -0
- package/dist/chunk-LQQ6XJ2Y.js +269 -0
- package/dist/chunk-MJQ55WZZ.js +65 -0
- package/dist/chunk-ML3UKMH3.js +40 -0
- package/dist/chunk-MOZPLHSU.js +5526 -0
- package/dist/chunk-NGEWJ4DF.js +89 -0
- package/dist/chunk-NH6VIOAR.js +211 -0
- package/dist/chunk-O5VZQKCB.js +26106 -0
- package/dist/chunk-OHSV42QB.js +748 -0
- package/dist/chunk-OO3TAHO5.js +4070 -0
- package/dist/chunk-OTNHSAGN.js +38282 -0
- package/dist/chunk-OUWAC7AQ.js +442 -0
- package/dist/chunk-OXMIV4WE.js +270 -0
- package/dist/chunk-P5KJURUR.js +229 -0
- package/dist/chunk-P6GJOVO6.js +307 -0
- package/dist/chunk-QARAGUXX.js +23 -0
- package/dist/chunk-R43HJCDX.js +2711 -0
- package/dist/chunk-RAXBAWRN.js +210 -0
- package/dist/chunk-RK3JHWPT.js +39 -0
- package/dist/chunk-RWA23GMM.js +24 -0
- package/dist/chunk-S4K4L6IM.js +179 -0
- package/dist/chunk-SAXK6LVF.js +124 -0
- package/dist/chunk-SEPGEJNK.js +1607 -0
- package/dist/chunk-SUJERP5I.js +285 -0
- package/dist/chunk-T3ED6BY2.js +913 -0
- package/dist/chunk-THKDVSEC.js +90 -0
- package/dist/chunk-TI4GSEL5.js +52 -0
- package/dist/chunk-TPI73L57.js +164 -0
- package/dist/chunk-TVHW77C7.js +338 -0
- package/dist/chunk-TWNHOSDT.js +1073 -0
- package/dist/chunk-UFMN76QD.js +347 -0
- package/dist/chunk-UHGLFRZE.js +205 -0
- package/dist/chunk-UTZYPKBF.js +15231 -0
- package/dist/chunk-UXNLELW6.js +25 -0
- package/dist/chunk-UXXS53EA.js +166 -0
- package/dist/chunk-V5DHFGI7.js +171 -0
- package/dist/chunk-V5YIPMHV.js +2353 -0
- package/dist/chunk-WMUWEO2C.js +754 -0
- package/dist/chunk-WOE3D7JM.js +945 -0
- package/dist/chunk-X2IK5LVR.js +2592 -0
- package/dist/chunk-XU2YXCDL.js +459 -0
- package/dist/chunk-YJG5HIX5.js +203 -0
- package/dist/chunk-Z3QE7TZM.js +72 -0
- package/dist/chunk-Z5Z3JHJY.js +64 -0
- package/dist/chunk-ZDIFBJFT.js +168 -0
- package/dist/chunk-ZGGCEXDC.js +176 -0
- package/dist/chunk-ZMZCZNKU.js +263 -0
- package/dist/chunk-ZNC5T65N.js +17 -0
- package/dist/chunk-ZO3I3A7O.js +308 -0
- package/dist/chunk-ZQKXBUB7.js +217 -0
- package/dist/chunk-ZTRINFM2.js +78 -0
- package/dist/chunk-ZU7JZCVP.js +193 -0
- package/dist/chunk-ZZAWNALS.js +350 -0
- package/dist/cli/entry.js +54 -0
- package/dist/connector-L5QQTR6Y.js +26 -0
- package/dist/context-62DC6EC3.js +31 -0
- package/dist/council-convene-NJWPNBDU.js +46 -0
- package/dist/create-agent-config-ODSQWNVC.js +55 -0
- package/dist/default-registry-2PU3BTAU.js +68 -0
- package/dist/deliver-task-KONV4C4M.js +57 -0
- package/dist/delivery-gate-v2-F2YVMVGK.js +27 -0
- package/dist/domain-knowledge-store-DDZ3F4J7.js +11 -0
- package/dist/fetch-core-ZPPYDSZH.js +14 -0
- package/dist/galaxy-K72BBDQN.js +91 -0
- package/dist/goal-criteria-SCALAU2D.js +141 -0
- package/dist/goal-persist-XWY2GDQX.js +19 -0
- package/dist/goal-tracker-FXMJ2GVK.js +11 -0
- package/dist/headless-LSB6I7PT.js +162 -0
- package/dist/headless-coordinator-VDPDMVUT.js +90 -0
- package/dist/inject-U55SMB6A.js +39 -0
- package/dist/login-flow-CD4ZGXOC.js +59 -0
- package/dist/logs-cli-SQVYFMMN.js +283 -0
- package/dist/loop-ULZYBDA3.js +76 -0
- package/dist/main.js +4064 -0
- package/dist/manager-ROZBCWPA.js +171 -0
- package/dist/manager-Z7XFFUOM.js +10670 -0
- package/dist/meridian-indexer-ZIW363L7.js +21 -0
- package/dist/native-resolver-PN34UIVV.js +13 -0
- package/dist/node_modules/better-sqlite3/lib/database.js +90 -0
- package/dist/node_modules/better-sqlite3/lib/index.js +3 -0
- package/dist/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
- package/dist/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
- package/dist/node_modules/better-sqlite3/lib/methods/function.js +31 -0
- package/dist/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
- package/dist/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
- package/dist/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
- package/dist/node_modules/better-sqlite3/lib/methods/table.js +189 -0
- package/dist/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
- package/dist/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
- package/dist/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
- package/dist/node_modules/better-sqlite3/lib/util.js +12 -0
- package/dist/node_modules/better-sqlite3/package.json +59 -0
- package/dist/ownership-ledger-E3WIEKPL.js +9 -0
- package/dist/package.json +3 -0
- package/dist/path-grants-XRRXHXG7.js +40 -0
- package/dist/paths-LVV5IMQN.js +49 -0
- package/dist/plan-fact-anchors-LMVQZCW5.js +13 -0
- package/dist/plan-store-ODLTTPFB.js +17 -0
- package/dist/plan-templates-5FPFBOL6.js +109 -0
- package/dist/plugin-loader-ZZKX7ZE6.js +22 -0
- package/dist/prefix-budget-62OV5HQC.js +13 -0
- package/dist/project-trust-5WS5MOMU.js +31 -0
- package/dist/provider-cli-ALDQXIT7.js +37 -0
- package/dist/providers-XQYTAVPK.js +11 -0
- package/dist/proxy-resolver-V2Y6534D.js +15 -0
- package/dist/recovery-cli-KPGY6FY3.js +106 -0
- package/dist/review-discipline-MNSYCST5.js +55 -0
- package/dist/review-router-BVQZW3MX.js +18 -0
- package/dist/seed-capsules/seed-capsule-attack-methodology.md +62 -0
- package/dist/seed-capsules/seed-capsule-changgeng.md +31 -0
- package/dist/seed-capsules/seed-capsule-design-aesthetics.md +38 -0
- package/dist/seed-capsules/seed-capsule-diagnostic-ladder.md +54 -0
- package/dist/seed-capsules/seed-capsule-fu.md +39 -0
- package/dist/seed-capsules/seed-capsule-huagai.md +73 -0
- package/dist/seed-capsules/seed-capsule-kaiyang.md +65 -0
- package/dist/seed-capsules/seed-capsule-knowledge-work.md +40 -0
- package/dist/seed-capsules/seed-capsule-tanlang.md +47 -0
- package/dist/seed-capsules/seed-capsule-tianfu.md +23 -0
- package/dist/seed-capsules/seed-capsule-tianliang.md +63 -0
- package/dist/seed-capsules/seed-capsule-tianquan.md +32 -0
- package/dist/seed-capsules/seed-capsule-tianxuan-ccr.md +22 -0
- package/dist/seed-capsules/seed-capsule-tianxuan.md +64 -0
- package/dist/seed-capsules/seed-capsule-yaoguang.md +87 -0
- package/dist/serve-X2R2UTLF.js +170 -0
- package/dist/serve-agent-KHSU6RVV.js +965 -0
- package/dist/session-persist-HUUC772H.js +37 -0
- package/dist/session-registry-6XUD5C4Y.js +15 -0
- package/dist/skill-loader-CK3RMO47.js +48 -0
- package/dist/skills/cli-harness-sop.md +207 -0
- package/dist/spawn-git-4HFU65AH.js +29 -0
- package/dist/sse-EYUTBWUK.js +512 -0
- package/dist/starflow-NOFBMPFU.js +30 -0
- package/dist/streamableHttp-V67CNJMO.js +447 -0
- package/dist/task-contract-6XHBNJQK.js +32 -0
- package/dist/task-ledger-3K4TJIER.js +9 -0
- package/dist/team-orchestrate-S6NHZP7X.js +64 -0
- package/dist/title-extract-QX4XGCYN.js +50 -0
- package/dist/todo-QDXGRZZP.js +31 -0
- package/dist/todo-store-V3TTO5AH.js +12 -0
- package/dist/tool-preset-LU5BYEDZ.js +23 -0
- package/dist/tool-tiers-GD742YBN.js +23 -0
- package/dist/turndown.es-OI55K6C3.js +17373 -0
- package/dist/verification-attribution-EKG4CNUV.js +13 -0
- package/dist/volatile-git-MBTST7RA.js +15 -0
- package/dist/wave-checkpoint-XLIIHXQA.js +30 -0
- package/dist/web-cli-DUG4I35O.js +233 -0
- package/dist/web-search-3IK542AA.js +34 -0
- package/dist/workers/cpu-worker.js +45 -0
- package/dist/workflow-runner-HX7UBAYG.js +297 -0
- package/dist/worktree-baseline-O5NCU6M2.js +9 -0
- package/package.json +122 -0
- package/scripts/check-mobile-env.mjs +76 -0
- package/scripts/fetch-native-sqlite.js +392 -0
- package/scripts/prune-installed-wasms.js +45 -0
- package/scripts/tree-sitter-wasm-keep.js +40 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --expose-gc --max-old-space-size=4096
|
|
2
|
+
import { createRequire as __rivetCreateRequire } from 'node:module'; const require = __rivetCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
getSessionDir
|
|
5
|
+
} from "./chunk-LH5VCGLB.js";
|
|
6
|
+
import {
|
|
7
|
+
TODO_EMPTY_RESULT,
|
|
8
|
+
TodoStore
|
|
9
|
+
} from "./chunk-DEBI37QB.js";
|
|
10
|
+
import {
|
|
11
|
+
external_exports
|
|
12
|
+
} from "./chunk-OO3TAHO5.js";
|
|
13
|
+
import {
|
|
14
|
+
writeFileAtomicSync
|
|
15
|
+
} from "./chunk-A5MNH4ER.js";
|
|
16
|
+
import {
|
|
17
|
+
init_esm_shims
|
|
18
|
+
} from "./chunk-5GGOGLSN.js";
|
|
19
|
+
|
|
20
|
+
// src/tools/todo.ts
|
|
21
|
+
init_esm_shims();
|
|
22
|
+
|
|
23
|
+
// src/tools/todo-deps.ts
|
|
24
|
+
init_esm_shims();
|
|
25
|
+
var DEP_CUE = /(?:基于|依赖|需先|先完成|完成后|建立在|after|depends?\s+on|requires?|blocked\s+by|builds?\s+on|based\s+on)/i;
|
|
26
|
+
function escapeRe(s) {
|
|
27
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28
|
+
}
|
|
29
|
+
function referencesId(content, id) {
|
|
30
|
+
const escaped = escapeRe(id);
|
|
31
|
+
if (/[A-Za-z]/.test(id)) {
|
|
32
|
+
return new RegExp(`\\b${escaped}\\b`).test(content);
|
|
33
|
+
}
|
|
34
|
+
return new RegExp(`${DEP_CUE.source}\\s*#?${escaped}\\b`, "i").test(content);
|
|
35
|
+
}
|
|
36
|
+
function detectDependencies(todos) {
|
|
37
|
+
const ids = todos.map((t) => t.id);
|
|
38
|
+
return todos.map((t) => {
|
|
39
|
+
const deps = [];
|
|
40
|
+
for (const otherId of ids) {
|
|
41
|
+
if (otherId === t.id) continue;
|
|
42
|
+
if (referencesId(t.content, otherId)) {
|
|
43
|
+
deps.push(otherId);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { id: t.id, dependsOn: deps };
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function computeMaxDepth(deps) {
|
|
50
|
+
const depMap = new Map(deps.map((d) => [d.id, d.dependsOn]));
|
|
51
|
+
const cache = /* @__PURE__ */ new Map();
|
|
52
|
+
function depth(id, visiting) {
|
|
53
|
+
if (cache.has(id)) return cache.get(id);
|
|
54
|
+
if (visiting.has(id)) return Infinity;
|
|
55
|
+
visiting.add(id);
|
|
56
|
+
const upstreams = depMap.get(id) ?? [];
|
|
57
|
+
if (upstreams.length === 0) {
|
|
58
|
+
cache.set(id, 0);
|
|
59
|
+
visiting.delete(id);
|
|
60
|
+
return 0;
|
|
61
|
+
}
|
|
62
|
+
let max = 0;
|
|
63
|
+
for (const up of upstreams) {
|
|
64
|
+
const d = depth(up, visiting);
|
|
65
|
+
if (d === Infinity) {
|
|
66
|
+
cache.set(id, Infinity);
|
|
67
|
+
visiting.delete(id);
|
|
68
|
+
return Infinity;
|
|
69
|
+
}
|
|
70
|
+
if (d + 1 > max) max = d + 1;
|
|
71
|
+
}
|
|
72
|
+
cache.set(id, max);
|
|
73
|
+
visiting.delete(id);
|
|
74
|
+
return max;
|
|
75
|
+
}
|
|
76
|
+
let result = 0;
|
|
77
|
+
for (const dep of deps) {
|
|
78
|
+
const d = depth(dep.id, /* @__PURE__ */ new Set());
|
|
79
|
+
if (d === Infinity) return Infinity;
|
|
80
|
+
if (d > result) result = d;
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
}
|
|
84
|
+
function findExecutable(todos, deps) {
|
|
85
|
+
const completedSet = new Set(
|
|
86
|
+
todos.filter((t) => t.status === "completed").map((t) => t.id)
|
|
87
|
+
);
|
|
88
|
+
const depMap = new Map(deps.map((d) => [d.id, d.dependsOn]));
|
|
89
|
+
return todos.filter((t) => {
|
|
90
|
+
if (t.status !== "pending") return false;
|
|
91
|
+
const upstreams = depMap.get(t.id) ?? [];
|
|
92
|
+
return upstreams.every((dep) => completedSet.has(dep));
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
function orderPendingByExecutability(todos, deps) {
|
|
96
|
+
const executableIds = new Set(findExecutable(todos, deps).map((t) => t.id));
|
|
97
|
+
const pending = todos.filter((t) => t.status === "pending");
|
|
98
|
+
const executable = pending.filter((t) => executableIds.has(t.id));
|
|
99
|
+
const blocked = pending.filter((t) => !executableIds.has(t.id));
|
|
100
|
+
return [...executable, ...blocked];
|
|
101
|
+
}
|
|
102
|
+
var SCOPE_PENDING_THRESHOLD = 5;
|
|
103
|
+
var SCOPE_DEPTH_THRESHOLD = 3;
|
|
104
|
+
function assessScopeRisk(todos, deps) {
|
|
105
|
+
const pendingCount = todos.filter((t) => t.status === "pending").length;
|
|
106
|
+
const maxDepth = computeMaxDepth(deps);
|
|
107
|
+
const hasCycle = maxDepth === Infinity;
|
|
108
|
+
const completedSet = new Set(
|
|
109
|
+
todos.filter((t) => t.status === "completed").map((t) => t.id)
|
|
110
|
+
);
|
|
111
|
+
const depMap = new Map(deps.map((d) => [d.id, d.dependsOn]));
|
|
112
|
+
let blockedCount = 0;
|
|
113
|
+
for (const t of todos) {
|
|
114
|
+
if (t.status !== "pending") continue;
|
|
115
|
+
const upstreams = depMap.get(t.id) ?? [];
|
|
116
|
+
if (upstreams.some((dep) => !completedSet.has(dep))) blockedCount++;
|
|
117
|
+
}
|
|
118
|
+
const reasons = [];
|
|
119
|
+
if (pendingCount > SCOPE_PENDING_THRESHOLD) {
|
|
120
|
+
reasons.push(`${pendingCount} \u4E2A\u5F85\u529E\u9879\u4E00\u6B21\u6027\u94FA\u5F00\uFF08\u9608\u503C ${SCOPE_PENDING_THRESHOLD}\uFF09`);
|
|
121
|
+
}
|
|
122
|
+
if (hasCycle) {
|
|
123
|
+
reasons.push("\u5F85\u529E\u4E4B\u95F4\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56\uFF0C\u65E0\u6CD5\u7EBF\u6027\u63A8\u8FDB");
|
|
124
|
+
} else if (maxDepth > SCOPE_DEPTH_THRESHOLD) {
|
|
125
|
+
reasons.push(`\u4F9D\u8D56\u94FE\u6DF1\u5EA6 ${maxDepth}\uFF08\u9608\u503C ${SCOPE_DEPTH_THRESHOLD}\uFF09`);
|
|
126
|
+
}
|
|
127
|
+
let level = "none";
|
|
128
|
+
if (hasCycle || maxDepth > SCOPE_DEPTH_THRESHOLD || pendingCount > SCOPE_PENDING_THRESHOLD * 2) {
|
|
129
|
+
level = "high";
|
|
130
|
+
} else if (pendingCount > SCOPE_PENDING_THRESHOLD) {
|
|
131
|
+
level = "elevated";
|
|
132
|
+
}
|
|
133
|
+
return { level, pendingCount, maxDepth: hasCycle ? Infinity : maxDepth, blockedCount, hasCycle, reasons };
|
|
134
|
+
}
|
|
135
|
+
function buildScopeNotice(todos, deps, risk) {
|
|
136
|
+
const completedSet = new Set(
|
|
137
|
+
todos.filter((t) => t.status === "completed").map((t) => t.id)
|
|
138
|
+
);
|
|
139
|
+
const depMap = new Map(deps.map((d) => [d.id, d.dependsOn]));
|
|
140
|
+
const blocked = [];
|
|
141
|
+
for (const t of todos) {
|
|
142
|
+
if (t.status !== "pending") continue;
|
|
143
|
+
const upstreams = depMap.get(t.id) ?? [];
|
|
144
|
+
const unmet = upstreams.filter((dep) => !completedSet.has(dep));
|
|
145
|
+
if (unmet.length > 0) {
|
|
146
|
+
blocked.push(` \u26D4 ${t.id} "${t.content.slice(0, 40)}" \u2190 blocked by ${unmet.join(", ")}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (risk.level === "none" && blocked.length === 0) return null;
|
|
150
|
+
const lines = [];
|
|
151
|
+
if (risk.level === "high") {
|
|
152
|
+
lines.push(`\u26A0\uFE0F \u8303\u56F4\u98CE\u9669\u504F\u9AD8\uFF1A${risk.reasons.join("\uFF1B")}\u3002`);
|
|
153
|
+
lines.push("\u5EFA\u8BAE\u7ACB\u523B\u505C\u4E0B\u6765\u4E0E\u7528\u6237\u786E\u8BA4\u8303\u56F4/\u4F18\u5148\u7EA7\uFF0C\u62C6\u4E3A 2-3 wave \u5206\u6279\u6267\u884C\u3002\u6BCF\u6CE2 typecheck+test \u901A\u8FC7\u540E\u518D\u7EE7\u7EED\u4E0B\u4E00\u6CE2\u3002\u82E5\u5DF2\u4E0E\u7528\u6237\u5BF9\u9F50\uFF0C\u53EF\u7EE7\u7EED\u3002");
|
|
154
|
+
} else if (risk.level === "elevated") {
|
|
155
|
+
lines.push(`\u63D0\u793A\uFF1A${risk.reasons.join("\uFF1B")}\u3002`);
|
|
156
|
+
lines.push("\u5EFA\u8BAE\u63D0\u524D\u62C6\u4E3A 2-3 wave \u5206\u6279\u6267\u884C\uFF0C\u6BCF\u6CE2 typecheck+test \u901A\u8FC7\u540E\u518D\u505A\u4E0B\u4E00\u6CE2\u2014\u2014\u4E0D\u8981\u4E00\u6B21\u6027\u94FA\u5F00\u5168\u90E8\u3002\u82E5\u7528\u6237\u786E\u8BA4\u6241\u5E73\u6267\u884C\uFF0C\u53EF\u7EE7\u7EED\u3002");
|
|
157
|
+
}
|
|
158
|
+
if (blocked.length > 0) {
|
|
159
|
+
lines.push(`\u4F9D\u8D56\u672A\u6EE1\u8DB3 (${blocked.length} \u9879\uFF0C\u4ECD\u4FDD\u7559\u5728\u5217\u8868\u4E2D):`);
|
|
160
|
+
lines.push(...blocked);
|
|
161
|
+
}
|
|
162
|
+
return lines.join("\n");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// src/tools/todo.ts
|
|
166
|
+
import { existsSync, readFileSync } from "fs";
|
|
167
|
+
var VALID_STATUSES = ["pending", "in_progress", "completed"];
|
|
168
|
+
var todoItemSchema = external_exports.object({
|
|
169
|
+
id: external_exports.string().min(1),
|
|
170
|
+
content: external_exports.string().min(1),
|
|
171
|
+
status: external_exports.enum(VALID_STATUSES),
|
|
172
|
+
/** 进行中的现在时说法(如「正在修复认证 bug」);缺席时面板回退 content。 */
|
|
173
|
+
activeForm: external_exports.string().min(1).optional()
|
|
174
|
+
});
|
|
175
|
+
var acceptanceItemSchema = external_exports.object({
|
|
176
|
+
criterion: external_exports.string().min(1),
|
|
177
|
+
status: external_exports.enum(["pending", "met", "blocked"]),
|
|
178
|
+
evidence: external_exports.string().optional()
|
|
179
|
+
});
|
|
180
|
+
var todoActionSchema = external_exports.discriminatedUnion("action", [
|
|
181
|
+
external_exports.object({ action: external_exports.literal("read") }),
|
|
182
|
+
external_exports.object({
|
|
183
|
+
action: external_exports.literal("write"),
|
|
184
|
+
todos: external_exports.array(todoItemSchema),
|
|
185
|
+
acceptance: external_exports.array(acceptanceItemSchema).optional()
|
|
186
|
+
})
|
|
187
|
+
]);
|
|
188
|
+
var defaultStore = new TodoStore();
|
|
189
|
+
function getTodos() {
|
|
190
|
+
return defaultStore.read();
|
|
191
|
+
}
|
|
192
|
+
function getTodoRegressionStats() {
|
|
193
|
+
return defaultStore.getRegressionStats();
|
|
194
|
+
}
|
|
195
|
+
function setTodos(todos) {
|
|
196
|
+
defaultStore.write(todos);
|
|
197
|
+
persistTodos();
|
|
198
|
+
}
|
|
199
|
+
var todoSessionId;
|
|
200
|
+
var todoCwd;
|
|
201
|
+
function setTodoSession(sessionId, cwd) {
|
|
202
|
+
todoSessionId = sessionId;
|
|
203
|
+
todoCwd = cwd;
|
|
204
|
+
}
|
|
205
|
+
function todoPersistPath() {
|
|
206
|
+
if (!todoSessionId || !todoCwd) return void 0;
|
|
207
|
+
return `${getSessionDir(todoCwd)}/${todoSessionId}.todos.json`;
|
|
208
|
+
}
|
|
209
|
+
function persistTodos() {
|
|
210
|
+
const path = todoPersistPath();
|
|
211
|
+
if (!path) return;
|
|
212
|
+
try {
|
|
213
|
+
writeFileAtomicSync(path, JSON.stringify(defaultStore.read(), null, 2) + "\n");
|
|
214
|
+
} catch {
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function loadTodos(sessionId, cwd) {
|
|
218
|
+
const path = `${getSessionDir(cwd)}/${sessionId}.todos.json`;
|
|
219
|
+
if (!existsSync(path)) return null;
|
|
220
|
+
try {
|
|
221
|
+
const raw = JSON.parse(readFileSync(path, "utf-8"));
|
|
222
|
+
if (Array.isArray(raw)) {
|
|
223
|
+
defaultStore.write(raw);
|
|
224
|
+
return raw;
|
|
225
|
+
}
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
function createTodoTool(store = defaultStore) {
|
|
231
|
+
return {
|
|
232
|
+
definition: {
|
|
233
|
+
name: "todo",
|
|
234
|
+
description: `\u8BFB\u5199\u4F1A\u8BDD\u4EFB\u52A1\u6E05\u5355\u2014\u2014\u4F60\u7684\u76EE\u6807\u5206\u89E3\u3002\u4E3B\u52A8\u4F7F\u7528\u5B83\u3002
|
|
235
|
+
|
|
236
|
+
Actions:
|
|
237
|
+
- write: \u6574\u4F53\u66FF\u6362\u6E05\u5355\uFF08\u5168\u91CF\u66FF\u6362\uFF0C\u4E0D\u662F\u8865\u4E01\uFF09\u3002\u6BCF\u9879\u542B id\u3001content\u3001status\uFF08pending/in_progress/completed\uFF09\u3002\u5DF2\u5B8C\u6210\u9879\u4E5F\u8981\u91CD\u53D1\uFF0C\u5426\u5219\u4E22\u5931\u3002
|
|
238
|
+
- read: \u8FD4\u56DE\u5F53\u524D\u6E05\u5355\u3002
|
|
239
|
+
|
|
240
|
+
\u4F55\u65F6\u521B\u5EFA/\u66F4\u65B0\uFF08\u4E0D\u7528\u7B49\u7528\u6237\u8981\u6C42\uFF09\uFF1A
|
|
241
|
+
- \u4EFB\u52A1\u9700\u8981 3 \u4E2A\u4EE5\u4E0A\u4E0D\u540C\u6B65\u9AA4\uFF0C\u6216\u975E\u5E73\u51E1/\u8DE8\u591A\u6587\u4EF6\u3002
|
|
242
|
+
- \u7528\u6237\u4E00\u6B21\u7ED9\u591A\u4E2A\u4EFB\u52A1\uFF08\u7F16\u53F7\u6216\u9017\u53F7\u5206\u9694\u7684\u6E05\u5355\uFF09\u3002
|
|
243
|
+
- \u6536\u5230\u65B0\u6307\u4EE4\u540E\u7ACB\u5373\u5EFA\u2014\u2014\u5148\u843D\u6210 todo\uFF0C\u518D\u5F00\u5DE5\u3002
|
|
244
|
+
|
|
245
|
+
\u4F55\u65F6\u4E0D\u7528\uFF1A\u5355\u6B65\u7410\u788E\u64CD\u4F5C\uFF08\u4E00\u6B21\u6027\u5C0F\u7F16\u8F91\u522B\u52A0\u4EEA\u5F0F\uFF09\u3002
|
|
246
|
+
|
|
247
|
+
Plan mode \u4E0B\uFF1A\u7528 todo \u8DDF\u8E2A\u8C03\u7814\u6B65\u9AA4\uFF08\u6700\u540E\u4E00\u9879\u56FA\u5B9A\u4E3A\u300C\u6C47\u603B\u5199\u8BA1\u5212\u5E76\u63D0\u4EA4\u5BA1\u6279\u300D\uFF09\uFF1B\u8BA1\u5212\u6B63\u6587\u5199\u6D3B\u52A8\u8BA1\u5212\u6587\u4EF6\uFF0C\u4E0D\u8FDB todo\u3002
|
|
248
|
+
|
|
249
|
+
TDD \u7EAA\u5F8B\uFF1A
|
|
250
|
+
- \u4EE3\u7801\u4EFB\u52A1\uFF08\u975E\u6587\u6863/\u914D\u7F6E\uFF09\u6BCF\u4E2A\u4EFB\u52A1\u7684\u7B2C\u4E00\u6B65\u5E94\u662F\u5199\u6216\u66F4\u65B0\u6D4B\u8BD5\uFF08RED\uFF09\uFF0C\u518D\u5B9E\u73B0\u901A\u8FC7\uFF08GREEN\uFF09\u3002todo \u7ED3\u6784\u4F53\u73B0\u8FD9\u4E00\u70B9\uFF1A\u5982\u300C\u5199 X \u7684\u6D4B\u8BD5\u300D\u2192\u300C\u5B9E\u73B0 X\u300D\u2192\u300C\u91CD\u6784\u300D\u3002
|
|
251
|
+
- \u4EE5\u4E0B\u4E0D\u5F3A\u5236\uFF1A\u6587\u6863\u3001\u914D\u7F6E\u6539\u52A8\u3001\u5DF2\u6709\u6D4B\u8BD5\u8986\u76D6\u7684\u91CD\u6784\u3001\u5FEB\u901F typo \u4FEE\u590D\u3002
|
|
252
|
+
|
|
253
|
+
\u72B6\u6001\u89C4\u5219\uFF1A
|
|
254
|
+
- \u5F00\u5DE5\u524D\u628A\u4EFB\u52A1\u6807\u4E3A in_progress\uFF1B\u4EFB\u4F55\u65F6\u523B\u6070\u597D\u53EA\u6709\u4E00\u4E2A in_progress\u3002
|
|
255
|
+
- \u5B8C\u6210\u7ACB\u5373\u6807 completed\u2014\u2014\u4E0D\u8981\u6512\u6279\u3002
|
|
256
|
+
- \u91CD\u5199\u6E05\u5355\u65F6\u4E0D\u8981\u9759\u9ED8\u4E22\u5F03\u6216\u91CD\u7F6E\u5DF2\u5B8C\u6210\u9879\u3002
|
|
257
|
+
|
|
258
|
+
\u9A8C\u6536\u9762\uFF1A\u4EE3\u7801\u4EFB\u52A1\u9996\u6B21 write \u65F6\u7528 acceptance \u5B57\u6BB5\u58F0\u660E\u53EF\u89C2\u5BDF\u7684\u5B8C\u6210\u6807\u5FD7\uFF08\u5F62\u72B6\u4E0E\u6B63\u53CD\u4F8B\u89C1\u8BE5\u5B57\u6BB5\u8BF4\u660E\uFF09\u3002`,
|
|
259
|
+
input_schema: {
|
|
260
|
+
type: "object",
|
|
261
|
+
properties: {
|
|
262
|
+
action: {
|
|
263
|
+
type: "string",
|
|
264
|
+
enum: ["read", "write"],
|
|
265
|
+
description: "read \u8BFB\u5F53\u524D\u6E05\u5355\uFF1Bwrite \u5199\u65B0\u6E05\u5355"
|
|
266
|
+
},
|
|
267
|
+
todos: {
|
|
268
|
+
type: "array",
|
|
269
|
+
description: "\u5B8C\u6574 todo \u6E05\u5355\uFF08\u4EC5 write \u7528\uFF09",
|
|
270
|
+
items: {
|
|
271
|
+
type: "object",
|
|
272
|
+
properties: {
|
|
273
|
+
id: { type: "string", description: "\u4EFB\u52A1\u552F\u4E00\u6807\u8BC6" },
|
|
274
|
+
content: { type: "string", description: "\u4EFB\u52A1\u63CF\u8FF0\uFF08\u7948\u4F7F\u5F0F\uFF0C\u5982\u300C\u4FEE\u590D\u8BA4\u8BC1 bug\u300D\uFF09" },
|
|
275
|
+
status: { type: "string", enum: [...VALID_STATUSES], description: "\u4EFB\u52A1\u72B6\u6001" },
|
|
276
|
+
activeForm: { type: "string", description: "\u8FDB\u884C\u4E2D\u7684\u73B0\u5728\u65F6\u8BF4\u6CD5\uFF08\u5982\u300C\u6B63\u5728\u4FEE\u590D\u8BA4\u8BC1 bug\u300D\uFF09\uFF1B\u53EF\u9009\uFF0C\u7F3A\u7701\u65F6\u9762\u677F\u663E\u793A content" }
|
|
277
|
+
},
|
|
278
|
+
required: ["id", "content", "status"]
|
|
279
|
+
}
|
|
280
|
+
},
|
|
281
|
+
acceptance: {
|
|
282
|
+
type: "array",
|
|
283
|
+
description: "\u7528\u6237\u7EA7\u9A8C\u6536\u9762\uFF08\u53EF\u9009\uFF0C\u4EE3\u7801\u4EFB\u52A1\u5EFA\u8BAE\u9996\u6B21 write \u5C31\u5E26\uFF1B\u58F0\u660E\u987B\u65E9\u4E8E\u9A8C\u8BC1\uFF09\u3002\u6B63\u4F8B\u300C\u6309 ESC \u540E\u5F39\u7A97 isVisible() \u4E3A False\u300D\u3002\u53CD\u4F8B\u4E00\u5F8B\u62D2\u7EDD\uFF1A\u300C\u4FE1\u53F7\u8FDE\u901A\u300D\u300C\u51FD\u6570\u903B\u8F91\u6B63\u786E\u300D\u662F\u5185\u90E8\u5C5E\u6027\uFF1B\u300C\u6240\u6709\u6D4B\u8BD5\u901A\u8FC7\u300D\u300C\u8DD1 test_x.py \u770B\u5230 3 passed\u300D\u662F\u4FE1\u53F7\u7EA7\u2014\u2014\u5355\u6D4B\u8986\u76D6\u7684\u662F\u51FD\u6570\u5206\u652F\uFF0C\u4E0D\u662F\u7528\u6237\u6309\u952E\u540E\u7684\u884C\u4E3A\u3002",
|
|
284
|
+
items: {
|
|
285
|
+
type: "object",
|
|
286
|
+
properties: {
|
|
287
|
+
criterion: { type: "string", description: "\u7528\u6237\u505A\u4EC0\u4E48\u52A8\u4F5C \u2192 \u770B\u5230\u4EC0\u4E48\u53EF\u89C2\u5BDF\u7ED3\u679C" },
|
|
288
|
+
status: { type: "string", enum: ["pending", "met", "blocked"] },
|
|
289
|
+
evidence: { type: "string", description: "met\uFF1A\u5B9E\u9645\u505A\u4E86\u4EC0\u4E48\u3001\u89C2\u5BDF\u5230\u4EC0\u4E48\uFF1Bblocked\uFF1A\u4E3A\u4F55\u6267\u884C\u4E0D\u4E86" }
|
|
290
|
+
},
|
|
291
|
+
required: ["criterion", "status"]
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
},
|
|
295
|
+
required: ["action"]
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
async execute(params) {
|
|
299
|
+
const parsed = todoActionSchema.safeParse(params.input);
|
|
300
|
+
if (!parsed.success) {
|
|
301
|
+
return { content: `\u65E0\u6548\u8F93\u5165\uFF1A${parsed.error.message}`, isError: true, errorKind: "format_error" };
|
|
302
|
+
}
|
|
303
|
+
const data = parsed.data;
|
|
304
|
+
if (data.action === "read") {
|
|
305
|
+
const todos = store.read();
|
|
306
|
+
if (todos.length === 0) {
|
|
307
|
+
return { content: TODO_EMPTY_RESULT };
|
|
308
|
+
}
|
|
309
|
+
return { content: TodoStore.formatList(todos) };
|
|
310
|
+
}
|
|
311
|
+
const detection = store.detectRegressions(data.todos);
|
|
312
|
+
store.recordWrite(detection);
|
|
313
|
+
store.write(data.todos);
|
|
314
|
+
if (params.onPlanSteps && data.todos.length > 0) {
|
|
315
|
+
params.onPlanSteps(data.todos.map((t) => ({ id: t.id, content: t.content, status: t.status })));
|
|
316
|
+
}
|
|
317
|
+
if (params.onAcceptance && data.acceptance && data.acceptance.length > 0) {
|
|
318
|
+
params.onAcceptance(data.acceptance);
|
|
319
|
+
}
|
|
320
|
+
const summary = TodoStore.formatSummary(data.todos);
|
|
321
|
+
let content = summary;
|
|
322
|
+
const deps = detectDependencies(data.todos);
|
|
323
|
+
const risk = assessScopeRisk(data.todos, deps);
|
|
324
|
+
const notice = buildScopeNotice(data.todos, deps, risk);
|
|
325
|
+
if (notice) {
|
|
326
|
+
content += "\n\n" + notice;
|
|
327
|
+
}
|
|
328
|
+
if (detection.regressed.length > 0) {
|
|
329
|
+
const warn = detection.regressed.map((r) => ` - ${r}`).join("\n");
|
|
330
|
+
content = `\u26A0\uFE0F ${detection.regressed.length} \u9879\u6B64\u524D\u5DF2\u5B8C\u6210\u7684\u4EFB\u52A1\u88AB\u91CD\u7F6E\u6216\u79FB\u9664\uFF1A
|
|
331
|
+
${warn}
|
|
332
|
+
|
|
333
|
+
\u82E5\u975E\u6709\u610F\u4E3A\u4E4B\uFF08\u4F8B\u5982\u957F\u4EFB\u52A1\u540E\u51ED\u8BB0\u5FC6\u91CD\u5EFA\u6E05\u5355\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6807\u4E3A completed\u3002\u4E0D\u8981\u91CD\u505A\u5DF2\u5B8C\u6210\u7684\u5DE5\u4F5C\u3002
|
|
334
|
+
|
|
335
|
+
${content}`;
|
|
336
|
+
}
|
|
337
|
+
if (data.acceptance && data.acceptance.length > 0) {
|
|
338
|
+
const met = data.acceptance.filter((a) => a.status === "met").length;
|
|
339
|
+
const blocked = data.acceptance.filter((a) => a.status === "blocked").length;
|
|
340
|
+
const pending = data.acceptance.length - met - blocked;
|
|
341
|
+
content += `
|
|
342
|
+
|
|
343
|
+
\u9A8C\u6536\u9762 ${met}/${data.acceptance.length} \u8FBE\u6807` + (pending > 0 ? `\uFF0C${pending} \u9879\u5F85\u6267\u884C` : "") + (blocked > 0 ? `\uFF0C${blocked} \u9879\u53D7\u963B\uFF08\u4EA4\u4ED8\u65F6\u987B\u62AB\u9732\uFF09` : "") + "\u3002";
|
|
344
|
+
}
|
|
345
|
+
content += "\n\n\u7EE7\u7EED\u7528 todo \u8DDF\u8E2A\u8FDB\u5EA6\u2014\u2014\u5B8C\u6210\u5373\u6807 completed\uFF0C\u4FDD\u6301\u6070\u597D\u4E00\u4E2A in_progress\u3002";
|
|
346
|
+
return { content };
|
|
347
|
+
},
|
|
348
|
+
requiresApproval: () => false,
|
|
349
|
+
isConcurrencySafe: () => true,
|
|
350
|
+
isEnabled: () => true
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
var TODO_TOOL = createTodoTool();
|
|
354
|
+
|
|
355
|
+
export {
|
|
356
|
+
detectDependencies,
|
|
357
|
+
orderPendingByExecutability,
|
|
358
|
+
defaultStore,
|
|
359
|
+
getTodos,
|
|
360
|
+
getTodoRegressionStats,
|
|
361
|
+
setTodos,
|
|
362
|
+
setTodoSession,
|
|
363
|
+
loadTodos,
|
|
364
|
+
createTodoTool,
|
|
365
|
+
TODO_TOOL
|
|
366
|
+
};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#!/usr/bin/env -S node --expose-gc --max-old-space-size=4096
|
|
2
|
+
import { createRequire as __rivetCreateRequire } from 'node:module'; const require = __rivetCreateRequire(import.meta.url);
|
|
3
|
+
import {
|
|
4
|
+
init_esm_shims
|
|
5
|
+
} from "./chunk-5GGOGLSN.js";
|
|
6
|
+
|
|
7
|
+
// src/tools/worker-activity-stream.ts
|
|
8
|
+
init_esm_shims();
|
|
9
|
+
function shortOrderLabel(workOrderId) {
|
|
10
|
+
const seg = workOrderId.split(":").pop() ?? workOrderId;
|
|
11
|
+
return seg.replace(/^wo_/, "").slice(0, 12);
|
|
12
|
+
}
|
|
13
|
+
function progressSnippet(text, max = 80) {
|
|
14
|
+
return text.replace(/\s+/g, " ").trim().slice(0, max);
|
|
15
|
+
}
|
|
16
|
+
function terminalActivity(result, parentToolId, objective, opts) {
|
|
17
|
+
const identity = result;
|
|
18
|
+
const authority = opts && "authority" in opts ? opts.authority : result.authority;
|
|
19
|
+
return {
|
|
20
|
+
workOrderId: result.workOrderId,
|
|
21
|
+
parentToolId,
|
|
22
|
+
...identity.dispatchId ? { dispatchId: identity.dispatchId } : {},
|
|
23
|
+
...identity.attemptId ? { attemptId: identity.attemptId } : {},
|
|
24
|
+
...identity.parentAttemptId ? { parentAttemptId: identity.parentAttemptId } : {},
|
|
25
|
+
...opts?.omitProfile ? {} : { profile: result.profile ?? opts?.profileFallback },
|
|
26
|
+
authority,
|
|
27
|
+
objective,
|
|
28
|
+
status: result.status === "passed" ? "completed" : result.status,
|
|
29
|
+
progressLine: progressSnippet(result.summary),
|
|
30
|
+
summary: result.summary,
|
|
31
|
+
failureReason: result.failureReason,
|
|
32
|
+
model: result.model,
|
|
33
|
+
provider: result.provider,
|
|
34
|
+
usage: result.usage,
|
|
35
|
+
...opts?.omitArtifacts ? {} : {
|
|
36
|
+
artifactId: result.diffArtifactId,
|
|
37
|
+
changedFiles: result.changedFiles.length > 0 ? result.changedFiles : void 0
|
|
38
|
+
},
|
|
39
|
+
findingsCount: result.findings.length > 0 ? result.findings.length : void 0,
|
|
40
|
+
topFinding: result.findings[0]?.claim,
|
|
41
|
+
verificationBrief: result.verification ? { status: result.verification.status, passed: result.verification.passed, failed: result.verification.failed } : void 0,
|
|
42
|
+
evidenceStatus: result.evidenceStatus
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function activityProgressLine(event) {
|
|
46
|
+
if (event.kind === "tool_use") return `\u2699 ${event.detail ? progressSnippet(event.detail, 60) : "\u5DE5\u5177\u8C03\u7528"}`;
|
|
47
|
+
if (event.kind === "tool_result") return `\u2713 ${event.detail ? progressSnippet(event.detail, 50) : "\u5B8C\u6210"}`;
|
|
48
|
+
if (event.kind === "thinking") return "\u601D\u8003\u4E2D";
|
|
49
|
+
if (event.kind === "retry") return "\u21BB \u4E0A\u6E38\u91CD\u8BD5";
|
|
50
|
+
if (event.kind === "lifecycle") return event.detail ? `\u21BB ${progressSnippet(event.detail, 60)}` : "\u21BB \u8865\u507F\u8F6E";
|
|
51
|
+
if (event.kind === "turn") return "";
|
|
52
|
+
return "\u5199\u5165\u4E2D";
|
|
53
|
+
}
|
|
54
|
+
var DEFAULT_COALESCE_MS = 120;
|
|
55
|
+
function activityAttemptKey(activity) {
|
|
56
|
+
if (activity.attemptId) return `attempt:${activity.attemptId}`;
|
|
57
|
+
if (activity.dispatchId) return `dispatch:${activity.dispatchId}:${activity.workOrderId}`;
|
|
58
|
+
return `legacy:${activity.workOrderId}`;
|
|
59
|
+
}
|
|
60
|
+
var defaultActivityScheduler = {
|
|
61
|
+
setTimeout: (callback, ms) => setTimeout(callback, ms),
|
|
62
|
+
clearTimeout: (handle) => clearTimeout(handle)
|
|
63
|
+
};
|
|
64
|
+
function createDelegationActivityMapper(parentToolId, onWorkerActivity, opts) {
|
|
65
|
+
const counters = /* @__PURE__ */ new Map();
|
|
66
|
+
const objectiveSent = /* @__PURE__ */ new Set();
|
|
67
|
+
const contractSent = /* @__PURE__ */ new Set();
|
|
68
|
+
const coalesceMs = opts?.coalesceMs ?? DEFAULT_COALESCE_MS;
|
|
69
|
+
const scheduler = opts?.scheduler ?? defaultActivityScheduler;
|
|
70
|
+
const pending = /* @__PURE__ */ new Map();
|
|
71
|
+
const sealed = /* @__PURE__ */ new Set();
|
|
72
|
+
const sealedWorkers = /* @__PURE__ */ new Set();
|
|
73
|
+
const finished = /* @__PURE__ */ new Set();
|
|
74
|
+
const attemptOwners = /* @__PURE__ */ new Map();
|
|
75
|
+
let disposed = false;
|
|
76
|
+
const counterOf = (attemptKey) => {
|
|
77
|
+
let c = counters.get(attemptKey);
|
|
78
|
+
if (!c) {
|
|
79
|
+
c = { toolUseCount: 0, tokenCount: 0 };
|
|
80
|
+
counters.set(attemptKey, c);
|
|
81
|
+
}
|
|
82
|
+
return c;
|
|
83
|
+
};
|
|
84
|
+
const safeEmit = (activity) => {
|
|
85
|
+
if (disposed) return false;
|
|
86
|
+
try {
|
|
87
|
+
onWorkerActivity(activity);
|
|
88
|
+
return true;
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const emitRunning = (event, detail) => {
|
|
94
|
+
const attemptKey = activityAttemptKey(event);
|
|
95
|
+
const c = counterOf(attemptKey);
|
|
96
|
+
const line = activityProgressLine(event);
|
|
97
|
+
let objective;
|
|
98
|
+
let contract;
|
|
99
|
+
if (!objectiveSent.has(attemptKey)) {
|
|
100
|
+
objective = event.objective ?? opts?.objectiveOf?.(event.workOrderId);
|
|
101
|
+
if (objective) objectiveSent.add(attemptKey);
|
|
102
|
+
}
|
|
103
|
+
if (!contractSent.has(attemptKey)) {
|
|
104
|
+
contract = event.contract ?? opts?.contractOf?.(event.workOrderId);
|
|
105
|
+
if (contract) contractSent.add(attemptKey);
|
|
106
|
+
}
|
|
107
|
+
const identity = event;
|
|
108
|
+
safeEmit({
|
|
109
|
+
workOrderId: event.workOrderId,
|
|
110
|
+
parentToolId,
|
|
111
|
+
...identity.attemptId ? { attemptId: identity.attemptId } : {},
|
|
112
|
+
...identity.dispatchId ? { dispatchId: identity.dispatchId } : {},
|
|
113
|
+
...identity.parentAttemptId ? { parentAttemptId: identity.parentAttemptId } : {},
|
|
114
|
+
profile: event.profile,
|
|
115
|
+
authority: event.authority,
|
|
116
|
+
authorityReason: event.authorityReason,
|
|
117
|
+
status: "running",
|
|
118
|
+
...objective ? { objective } : {},
|
|
119
|
+
progressLine: line || void 0,
|
|
120
|
+
toolUseCount: c.toolUseCount,
|
|
121
|
+
tokenCount: c.tokenCount > 0 ? c.tokenCount : void 0,
|
|
122
|
+
eventKind: event.kind,
|
|
123
|
+
eventDetail: detail,
|
|
124
|
+
...contract ? { contract } : {}
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
const cancelSlotTimer = (slot) => {
|
|
128
|
+
slot.timerGeneration += 1;
|
|
129
|
+
if (slot.timer === void 0) return;
|
|
130
|
+
scheduler.clearTimeout(slot.timer);
|
|
131
|
+
slot.timer = void 0;
|
|
132
|
+
};
|
|
133
|
+
const flushPending = (attemptKey, expectedSlot, allowSealed = false) => {
|
|
134
|
+
const slot = pending.get(attemptKey);
|
|
135
|
+
if (!slot || expectedSlot && slot !== expectedSlot) return;
|
|
136
|
+
cancelSlotTimer(slot);
|
|
137
|
+
pending.delete(attemptKey);
|
|
138
|
+
if (disposed || !allowSealed && sealed.has(attemptKey)) return;
|
|
139
|
+
const merged = { ...slot.base };
|
|
140
|
+
if (slot.objective !== void 0) merged.objective = slot.objective;
|
|
141
|
+
if (slot.contract !== void 0) merged.contract = slot.contract;
|
|
142
|
+
emitRunning(merged, slot.parts.join(""));
|
|
143
|
+
};
|
|
144
|
+
const flush = (workOrderId) => {
|
|
145
|
+
if (disposed) return;
|
|
146
|
+
if (workOrderId !== void 0) {
|
|
147
|
+
for (const [attemptKey, slot] of [...pending.entries()]) {
|
|
148
|
+
if (slot.base.workOrderId === workOrderId) flushPending(attemptKey);
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
for (const attemptKey of [...pending.keys()]) flushPending(attemptKey);
|
|
153
|
+
};
|
|
154
|
+
const sealAttempt = (attemptKey) => {
|
|
155
|
+
if (disposed || sealed.has(attemptKey)) return;
|
|
156
|
+
sealed.add(attemptKey);
|
|
157
|
+
flushPending(attemptKey, void 0, true);
|
|
158
|
+
counters.delete(attemptKey);
|
|
159
|
+
objectiveSent.delete(attemptKey);
|
|
160
|
+
contractSent.delete(attemptKey);
|
|
161
|
+
};
|
|
162
|
+
const seal = (workOrderId) => {
|
|
163
|
+
if (disposed) return;
|
|
164
|
+
sealedWorkers.add(workOrderId);
|
|
165
|
+
const keys = [...attemptOwners.entries()].filter(([, owner]) => owner === workOrderId).map(([attemptKey]) => attemptKey);
|
|
166
|
+
if (keys.length === 0) keys.push(activityAttemptKey({ workOrderId }));
|
|
167
|
+
for (const attemptKey of keys) sealAttempt(attemptKey);
|
|
168
|
+
};
|
|
169
|
+
const finish = (activity) => {
|
|
170
|
+
if (disposed) return;
|
|
171
|
+
const attemptKey = activityAttemptKey(activity);
|
|
172
|
+
attemptOwners.set(attemptKey, activity.workOrderId);
|
|
173
|
+
if (activity.status === "running" || finished.has(attemptKey)) return;
|
|
174
|
+
sealAttempt(attemptKey);
|
|
175
|
+
if (safeEmit(activity)) finished.add(attemptKey);
|
|
176
|
+
};
|
|
177
|
+
const dispose = () => {
|
|
178
|
+
if (disposed) return;
|
|
179
|
+
disposed = true;
|
|
180
|
+
for (const slot of pending.values()) cancelSlotTimer(slot);
|
|
181
|
+
pending.clear();
|
|
182
|
+
counters.clear();
|
|
183
|
+
objectiveSent.clear();
|
|
184
|
+
contractSent.clear();
|
|
185
|
+
sealed.clear();
|
|
186
|
+
sealedWorkers.clear();
|
|
187
|
+
finished.clear();
|
|
188
|
+
attemptOwners.clear();
|
|
189
|
+
};
|
|
190
|
+
const mapper = ((event) => {
|
|
191
|
+
if (disposed) return;
|
|
192
|
+
const attemptKey = activityAttemptKey(event);
|
|
193
|
+
attemptOwners.set(attemptKey, event.workOrderId);
|
|
194
|
+
if (sealedWorkers.has(event.workOrderId) || sealed.has(attemptKey)) return;
|
|
195
|
+
if (event.kind === "text" || event.kind === "thinking") {
|
|
196
|
+
const cur = pending.get(attemptKey);
|
|
197
|
+
if (cur && cur.kind !== event.kind) flushPending(attemptKey);
|
|
198
|
+
let slot = pending.get(attemptKey);
|
|
199
|
+
if (!slot) {
|
|
200
|
+
slot = { timerGeneration: 0, kind: event.kind, parts: [], base: event };
|
|
201
|
+
pending.set(attemptKey, slot);
|
|
202
|
+
}
|
|
203
|
+
if (event.detail) slot.parts.push(event.detail);
|
|
204
|
+
if (slot.objective === void 0 && event.objective !== void 0) slot.objective = event.objective;
|
|
205
|
+
if (slot.contract === void 0 && event.contract !== void 0) slot.contract = event.contract;
|
|
206
|
+
cancelSlotTimer(slot);
|
|
207
|
+
const generation = ++slot.timerGeneration;
|
|
208
|
+
const expectedSlot = slot;
|
|
209
|
+
let timer;
|
|
210
|
+
timer = scheduler.setTimeout(() => {
|
|
211
|
+
if (disposed || sealedWorkers.has(event.workOrderId) || sealed.has(attemptKey)) return;
|
|
212
|
+
if (pending.get(attemptKey) !== expectedSlot) return;
|
|
213
|
+
if (expectedSlot.timerGeneration !== generation || expectedSlot.timer !== timer) return;
|
|
214
|
+
flushPending(attemptKey, expectedSlot);
|
|
215
|
+
}, coalesceMs);
|
|
216
|
+
slot.timer = timer;
|
|
217
|
+
timer?.unref?.();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
flushPending(attemptKey);
|
|
221
|
+
const c = counterOf(attemptKey);
|
|
222
|
+
if (event.kind === "tool_use") c.toolUseCount += 1;
|
|
223
|
+
if (event.kind === "turn") {
|
|
224
|
+
const n = Number(event.detail);
|
|
225
|
+
if (Number.isFinite(n) && n > c.tokenCount) c.tokenCount = n;
|
|
226
|
+
}
|
|
227
|
+
emitRunning(event, event.detail);
|
|
228
|
+
});
|
|
229
|
+
mapper.flush = flush;
|
|
230
|
+
mapper.seal = seal;
|
|
231
|
+
mapper.finish = finish;
|
|
232
|
+
mapper.dispose = dispose;
|
|
233
|
+
return mapper;
|
|
234
|
+
}
|
|
235
|
+
function createActivityStreamer(emit, _opts) {
|
|
236
|
+
const textSeen = /* @__PURE__ */ new Set();
|
|
237
|
+
const retrySeen = /* @__PURE__ */ new Set();
|
|
238
|
+
return (event) => {
|
|
239
|
+
if (event.kind === "turn") return;
|
|
240
|
+
const label = `${shortOrderLabel(event.workOrderId)}\xB7${event.profile}`;
|
|
241
|
+
if (event.kind === "tool_use") {
|
|
242
|
+
const toolDetail = event.detail ? ` ${progressSnippet(event.detail, 60)}` : "";
|
|
243
|
+
emit(` \u21B3 [${label}] \u2699${toolDetail}
|
|
244
|
+
`);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (event.kind === "tool_result") {
|
|
248
|
+
const resultHint = event.detail ? ` (${progressSnippet(event.detail, 40)})` : "";
|
|
249
|
+
emit(` \u21B3 [${label}] \u2713 \u5B8C\u6210${resultHint}
|
|
250
|
+
`);
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (event.kind === "lifecycle") {
|
|
254
|
+
if (event.detail) emit(` \u21B3 [${label}] \u21BB ${progressSnippet(event.detail, 60)}
|
|
255
|
+
`);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (event.kind === "retry") {
|
|
259
|
+
if (!retrySeen.has(event.workOrderId)) {
|
|
260
|
+
retrySeen.add(event.workOrderId);
|
|
261
|
+
emit(` \u21B3 [${label}] \u21BB \u4E0A\u6E38\u91CD\u8BD5\u4E2D
|
|
262
|
+
`);
|
|
263
|
+
}
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
if (!textSeen.has(event.workOrderId)) {
|
|
267
|
+
textSeen.add(event.workOrderId);
|
|
268
|
+
const glyph = event.kind === "thinking" ? "\u601D\u8003\u4E2D" : "\u5199\u4F5C\u4E2D";
|
|
269
|
+
emit(` \u21B3 [${label}] \u270E ${glyph}
|
|
270
|
+
`);
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
shortOrderLabel,
|
|
277
|
+
terminalActivity,
|
|
278
|
+
createDelegationActivityMapper,
|
|
279
|
+
createActivityStreamer
|
|
280
|
+
};
|