@coralai/sps-cli 0.65.95 → 0.66.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/console/index.d.ts.map +1 -1
- package/dist/console/index.js +2 -0
- package/dist/console/index.js.map +1 -1
- package/dist/console/routes/art.d.ts +41 -0
- package/dist/console/routes/art.d.ts.map +1 -1
- package/dist/console/routes/art.js +12 -267
- package/dist/console/routes/art.js.map +1 -1
- package/dist/console/routes/capabilities.d.ts +22 -0
- package/dist/console/routes/capabilities.d.ts.map +1 -0
- package/dist/console/routes/capabilities.js +37 -0
- package/dist/console/routes/capabilities.js.map +1 -0
- package/dist/console/routes/cards.d.ts.map +1 -1
- package/dist/console/routes/cards.js +26 -0
- package/dist/console/routes/cards.js.map +1 -1
- package/dist/console-assets/assets/{ShowcasePage-BCO-h0JV.js → ShowcasePage-Ct_TJCyO.js} +1 -1
- package/dist/console-assets/assets/{index-DT-bJh9j.css → index-CKvLXfFP.css} +1 -1
- package/dist/console-assets/assets/{index-C-y1kIT5.js → index-DnQSjy6_.js} +90 -90
- package/dist/console-assets/index.html +2 -2
- package/dist/core/art/ops.d.ts +16 -0
- package/dist/core/art/ops.d.ts.map +1 -0
- package/dist/core/art/ops.js +290 -0
- package/dist/core/art/ops.js.map +1 -0
- package/dist/{console/lib/artPaths.d.ts → core/art/paths.d.ts} +2 -2
- package/dist/core/art/paths.d.ts.map +1 -0
- package/dist/{console/lib/artPaths.js → core/art/paths.js} +11 -6
- package/dist/core/art/paths.js.map +1 -0
- package/dist/core/tools/ToolCardExecutor.d.ts +28 -0
- package/dist/core/tools/ToolCardExecutor.d.ts.map +1 -0
- package/dist/core/tools/ToolCardExecutor.js +37 -0
- package/dist/core/tools/ToolCardExecutor.js.map +1 -0
- package/dist/core/tools/artCapabilities.d.ts +3 -0
- package/dist/core/tools/artCapabilities.d.ts.map +1 -0
- package/dist/core/tools/artCapabilities.js +55 -0
- package/dist/core/tools/artCapabilities.js.map +1 -0
- package/dist/core/tools/cardRefs.d.ts +37 -0
- package/dist/core/tools/cardRefs.d.ts.map +1 -0
- package/dist/core/tools/cardRefs.js +83 -0
- package/dist/core/tools/cardRefs.js.map +1 -0
- package/dist/core/tools/registry.d.ts +80 -0
- package/dist/core/tools/registry.d.ts.map +1 -0
- package/dist/core/tools/registry.js +29 -0
- package/dist/core/tools/registry.js.map +1 -0
- package/dist/core/tools/rerunGraph.d.ts +29 -0
- package/dist/core/tools/rerunGraph.d.ts.map +1 -0
- package/dist/core/tools/rerunGraph.js +40 -0
- package/dist/core/tools/rerunGraph.js.map +1 -0
- package/dist/engines/StageEngine.d.ts +13 -0
- package/dist/engines/StageEngine.d.ts.map +1 -1
- package/dist/engines/StageEngine.js +72 -1
- package/dist/engines/StageEngine.js.map +1 -1
- package/dist/providers/MarkdownTaskBackend.d.ts +13 -0
- package/dist/providers/MarkdownTaskBackend.d.ts.map +1 -1
- package/dist/providers/MarkdownTaskBackend.js +45 -2
- package/dist/providers/MarkdownTaskBackend.js.map +1 -1
- package/dist/providers/llm/chatTools.d.ts.map +1 -1
- package/dist/providers/llm/chatTools.js +9 -1
- package/dist/providers/llm/chatTools.js.map +1 -1
- package/dist/services/AgentGenService.d.ts.map +1 -1
- package/dist/services/AgentGenService.js +2 -2
- package/dist/services/AgentGenService.js.map +1 -1
- package/dist/services/CardService.d.ts +29 -1
- package/dist/services/CardService.d.ts.map +1 -1
- package/dist/services/CardService.js +34 -0
- package/dist/services/CardService.js.map +1 -1
- package/dist/services/ChatService.d.ts.map +1 -1
- package/dist/services/ChatService.js +1 -1
- package/dist/services/ChatService.js.map +1 -1
- package/dist/services/MemoryService.d.ts +1 -1
- package/dist/services/MemoryService.d.ts.map +1 -1
- package/dist/services/MemoryService.js +2 -2
- package/dist/services/MemoryService.js.map +1 -1
- package/dist/services/ProjectService.d.ts.map +1 -1
- package/dist/services/ProjectService.js +2 -2
- package/dist/services/ProjectService.js.map +1 -1
- package/dist/services/SkillService.d.ts +1 -1
- package/dist/services/SkillService.d.ts.map +1 -1
- package/dist/services/SkillService.js +1 -1
- package/dist/services/SkillService.js.map +1 -1
- package/dist/services/SystemService.d.ts.map +1 -1
- package/dist/services/SystemService.js.map +1 -1
- package/dist/services/WorkerService.d.ts +1 -1
- package/dist/services/WorkerService.d.ts.map +1 -1
- package/dist/services/WorkerService.js +3 -4
- package/dist/services/WorkerService.js.map +1 -1
- package/dist/services/container.d.ts +2 -2
- package/dist/services/container.d.ts.map +1 -1
- package/dist/services/container.js +1 -1
- package/dist/services/container.js.map +1 -1
- package/dist/shared/types.d.ts +26 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/console/lib/artPaths.d.ts.map +0 -1
- package/dist/console/lib/artPaths.js.map +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/tools/cardRefs
|
|
3
|
+
* @description 卡片间引用:`${card:12.out}` —— 让下一张卡吃上一张卡的产物。
|
|
4
|
+
*
|
|
5
|
+
* @layer core
|
|
6
|
+
*
|
|
7
|
+
* 🔴 **引用必须跨波次**:被引用的卡 `order` 必须**严格小于**引用它的卡。
|
|
8
|
+
* 同波并行 ⇒ 同波内互相引用是**竞态**,而竞态的表现是"有时对有时错",
|
|
9
|
+
* 比恒错难查得多。⇒ 建卡/校验时就拒,不留到运行时才发现。
|
|
10
|
+
*
|
|
11
|
+
* 🔴 **引用不到要报错,不能静默留原文**:留原文的话参数会变成字符串
|
|
12
|
+
* `"${card:12.out}"` 一路传到能力里,最后表现为"文件不存在" ——
|
|
13
|
+
* 而真因在两步之前。**别让归因跑偏。**
|
|
14
|
+
*/
|
|
15
|
+
/** `${card:<seq>.<key>}`;key 允许点号取嵌套(`.result.out`)。 */
|
|
16
|
+
const REF = /\$\{card:(\d+)\.([A-Za-z0-9_.]+)\}/g;
|
|
17
|
+
/** 扫出一份输入里的全部引用(不解析,只列出来 —— 校验与解析是两件事)。 */
|
|
18
|
+
export function collectRefs(input) {
|
|
19
|
+
const out = [];
|
|
20
|
+
const walk = (v) => {
|
|
21
|
+
if (typeof v === 'string') {
|
|
22
|
+
for (const m of v.matchAll(REF))
|
|
23
|
+
out.push({ seq: m[1], path: m[2] });
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(v))
|
|
27
|
+
return void v.forEach(walk);
|
|
28
|
+
if (v && typeof v === 'object')
|
|
29
|
+
return void Object.values(v).forEach(walk);
|
|
30
|
+
};
|
|
31
|
+
walk(input);
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function pick(obj, path) {
|
|
35
|
+
let cur = obj;
|
|
36
|
+
for (const seg of path.split('.')) {
|
|
37
|
+
if (!cur || typeof cur !== 'object')
|
|
38
|
+
return undefined;
|
|
39
|
+
cur = cur[seg];
|
|
40
|
+
}
|
|
41
|
+
return cur;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 解析引用。
|
|
45
|
+
*
|
|
46
|
+
* @param outputs seq → 那张卡的产物(通常存在卡片 meta 的 `toolResult` 下)
|
|
47
|
+
* @param orderOf seq → 波次;用于跨波校验。取不到波次的卡按**拒绝**处理
|
|
48
|
+
* —— "不知道它在第几波"不能当成"它在前面"。
|
|
49
|
+
*/
|
|
50
|
+
export function resolveRefs(input, selfOrder, outputs, orderOf) {
|
|
51
|
+
for (const r of collectRefs(input)) {
|
|
52
|
+
const ord = orderOf.get(r.seq);
|
|
53
|
+
if (ord === undefined || ord >= selfOrder) {
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
code: 'REF_SAME_OR_LATER_WAVE',
|
|
57
|
+
message: `引用了同波或更晚的卡 seq ${r.seq}(它 order=${ord ?? '未知'},本卡 order=${selfOrder})——同波并行,互相引用是竞态`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let failure = null;
|
|
62
|
+
const sub = (s) => s.replace(REF, (whole, seq, path) => {
|
|
63
|
+
const v = pick(outputs.get(seq) ?? {}, path);
|
|
64
|
+
if (v === undefined) {
|
|
65
|
+
failure ??= { ok: false, code: 'REF_NOT_FOUND', message: `引用取不到值:${whole}` };
|
|
66
|
+
return whole;
|
|
67
|
+
}
|
|
68
|
+
return String(v);
|
|
69
|
+
});
|
|
70
|
+
const walk = (v) => {
|
|
71
|
+
if (typeof v === 'string')
|
|
72
|
+
return sub(v);
|
|
73
|
+
if (Array.isArray(v))
|
|
74
|
+
return v.map(walk);
|
|
75
|
+
if (v && typeof v === 'object') {
|
|
76
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x)]));
|
|
77
|
+
}
|
|
78
|
+
return v;
|
|
79
|
+
};
|
|
80
|
+
const resolved = walk(input);
|
|
81
|
+
return failure ?? { ok: true, input: resolved };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=cardRefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cardRefs.js","sourceRoot":"","sources":["../../../src/core/tools/cardRefs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/tools/registry
|
|
3
|
+
* @description 工具能力注册表 —— **目录**:有哪些能力、参数什么形状、会写什么、同步还是异步。
|
|
4
|
+
*
|
|
5
|
+
* @layer core
|
|
6
|
+
*
|
|
7
|
+
* 🔴 **注册表是目录,实现方式是它的属性,卡片看不见实现方式。**
|
|
8
|
+
* 一旦卡片要区分"这是内建还是脚本",实现方式就变成了编排数据的一部分,
|
|
9
|
+
* 以后换实现要改所有卡。所以卡片只写 `tool` + `input`。
|
|
10
|
+
*
|
|
11
|
+
* 🔴 **卡片不带代码。** 脚本没有被赶走,只是换了载体:它随**模板包**走、
|
|
12
|
+
* 由 `template.json` 声明入口(先例:`smoke: { script, checks }`,sps **只跑不解释**)。
|
|
13
|
+
* 卡片里内嵌脚本会把**不可审计的代码搬进编排数据**,而且脚本必然要拿路径 ⇒
|
|
14
|
+
* 绕过 `core/art/paths` 那条"落点权是 sps 的"。
|
|
15
|
+
*
|
|
16
|
+
* ⚠️ **注册表是 per-project 视图,不是全局表**:
|
|
17
|
+
* `built-in` 所有项目都有;`script` **只属于装了那个模板的项目**。
|
|
18
|
+
* 全局表会列出这个项目根本用不了的能力 —— 那是让人排出一张跑不起来的图。
|
|
19
|
+
*/
|
|
20
|
+
import type { ZodTypeAny } from 'zod';
|
|
21
|
+
export type CapabilityMode = 'sync' | 'async';
|
|
22
|
+
export interface Capability {
|
|
23
|
+
/** 能力 id,卡片用它引用。命名 `<域>.<动作>`,如 `art.chromaKey`。 */
|
|
24
|
+
id: string;
|
|
25
|
+
mode: CapabilityMode;
|
|
26
|
+
/** 参数形状由**能力**定,不是卡片里的自由 JSON。 */
|
|
27
|
+
inputSchema: ZodTypeAny;
|
|
28
|
+
/**
|
|
29
|
+
* 这个能力会写什么(相对项目根的路径模式)。
|
|
30
|
+
*
|
|
31
|
+
* 🔴 **可审计性的来源**:不读代码就知道这张卡会写什么;
|
|
32
|
+
* 也是"幂等判据的覆盖面必须等于产物面"能被检查的前提。
|
|
33
|
+
* ⚠️ 但两种实现的**强度不同**:built-in 是**代码事实**(可用例钉住);
|
|
34
|
+
* script 只是**声明** —— sps 不解释脚本,它写了别的 sps 事后才知道。
|
|
35
|
+
* ⇒ 脚本能力的越界只能靠**围栏**兜(realpath + 项目根内),**不能靠这条声明**。
|
|
36
|
+
*/
|
|
37
|
+
produces: string[];
|
|
38
|
+
/** 可信度来源。卡片不看这一格,**审计要看**。 */
|
|
39
|
+
source: {
|
|
40
|
+
kind: 'built-in';
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'script';
|
|
43
|
+
template: string;
|
|
44
|
+
script: string;
|
|
45
|
+
};
|
|
46
|
+
/** 一句话说明,给编排页展示。 */
|
|
47
|
+
summary: string;
|
|
48
|
+
/** 执行体。`async` 能力返回后**任务仍在跑**,由 join 卡等终态。 */
|
|
49
|
+
run(input: unknown, ctx: CapabilityContext): Promise<Record<string, unknown>>;
|
|
50
|
+
}
|
|
51
|
+
export interface CapabilityContext {
|
|
52
|
+
/** 项目在共享树下的相对路径(`t<租户>/<产品>/<项目>`)。 */
|
|
53
|
+
project: string;
|
|
54
|
+
/** 项目工作区绝对路径。**能力不从卡片收路径**,只从这里取根。 */
|
|
55
|
+
projectDir: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 一个**不可变**的能力表。
|
|
59
|
+
*
|
|
60
|
+
* 🔴 注册在**模块加载时**完成,不做运行时增删:
|
|
61
|
+
* 一个能被运行时改的注册表,等于"这张卡今天能跑、明天不能",而排错时看不出为什么。
|
|
62
|
+
*/
|
|
63
|
+
export declare class CapabilityRegistry {
|
|
64
|
+
private readonly byId;
|
|
65
|
+
constructor(capabilities?: Capability[]);
|
|
66
|
+
/** 重复 id **抛错**,不是后者覆盖前者 —— 静默覆盖会让"我调的是哪一个"无从判断。 */
|
|
67
|
+
add(cap: Capability): void;
|
|
68
|
+
get(id: string): Capability | undefined;
|
|
69
|
+
list(): Capability[];
|
|
70
|
+
}
|
|
71
|
+
/** 对外(编排页 / 建卡面)看到的形状 —— **不含 `run`**。 */
|
|
72
|
+
export interface CapabilityView {
|
|
73
|
+
id: string;
|
|
74
|
+
mode: CapabilityMode;
|
|
75
|
+
produces: string[];
|
|
76
|
+
summary: string;
|
|
77
|
+
source: Capability['source'];
|
|
78
|
+
}
|
|
79
|
+
export declare function toView(c: Capability): CapabilityView;
|
|
80
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/tools/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAEtC,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,kCAAkC;IAClC,WAAW,EAAE,UAAU,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8BAA8B;IAC9B,MAAM,EAAE;QAAE,IAAI,EAAE,UAAU,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACpF,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC/E;AAED,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiC;gBAE1C,YAAY,GAAE,UAAU,EAAO;IAI3C,oDAAoD;IACpD,GAAG,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI;IAK1B,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIvC,IAAI,IAAI,UAAU,EAAE;CAGrB;AAED,0CAA0C;AAC1C,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,cAAc,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;CAC9B;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,UAAU,GAAG,cAAc,CAEpD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个**不可变**的能力表。
|
|
3
|
+
*
|
|
4
|
+
* 🔴 注册在**模块加载时**完成,不做运行时增删:
|
|
5
|
+
* 一个能被运行时改的注册表,等于"这张卡今天能跑、明天不能",而排错时看不出为什么。
|
|
6
|
+
*/
|
|
7
|
+
export class CapabilityRegistry {
|
|
8
|
+
byId = new Map();
|
|
9
|
+
constructor(capabilities = []) {
|
|
10
|
+
for (const c of capabilities)
|
|
11
|
+
this.add(c);
|
|
12
|
+
}
|
|
13
|
+
/** 重复 id **抛错**,不是后者覆盖前者 —— 静默覆盖会让"我调的是哪一个"无从判断。 */
|
|
14
|
+
add(cap) {
|
|
15
|
+
if (this.byId.has(cap.id))
|
|
16
|
+
throw new Error(`能力 id 重复:${cap.id}`);
|
|
17
|
+
this.byId.set(cap.id, cap);
|
|
18
|
+
}
|
|
19
|
+
get(id) {
|
|
20
|
+
return this.byId.get(id);
|
|
21
|
+
}
|
|
22
|
+
list() {
|
|
23
|
+
return [...this.byId.values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function toView(c) {
|
|
27
|
+
return { id: c.id, mode: c.mode, produces: c.produces, summary: c.summary, source: c.source };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/tools/registry.ts"],"names":[],"mappings":"AAsDA;;;;;GAKG;AACH,MAAM,OAAO,kBAAkB;IACZ,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEtD,YAAY,eAA6B,EAAE;QACzC,KAAK,MAAM,CAAC,IAAI,YAAY;YAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,oDAAoD;IACpD,GAAG,CAAC,GAAe;QACjB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1E,CAAC;CACF;AAWD,MAAM,UAAU,MAAM,CAAC,CAAa;IAClC,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAChG,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module core/tools/rerunGraph
|
|
3
|
+
* @description 重跑的**波及面**:从一张卡出发,沿引用图算出还必须一起重跑的下游卡。
|
|
4
|
+
*
|
|
5
|
+
* @layer core
|
|
6
|
+
*
|
|
7
|
+
* 🔴 **重跑一张卡而不重跑它的下游 = 留下一个基于旧产物的结果,而且图上全绿。**
|
|
8
|
+
* 这正是本轮反复咬的那族("成功的回执 ≠ 达成的目的")。
|
|
9
|
+
* ⇒ 计算波及面是重跑的**一部分**,不是可选项。
|
|
10
|
+
*
|
|
11
|
+
* 🔴 **只按引用连边,不按波次相邻**:第 3 波的卡不一定用了第 2 波的产物。
|
|
12
|
+
* 按波次连会把无关的卡一起重跑 —— 那是"多做无害"的错觉:
|
|
13
|
+
* 重跑一张 AI 生成卡要花钱,而且会覆盖用户可能已经手工修过的产物。
|
|
14
|
+
*
|
|
15
|
+
* ⚠️ 只处理 `input` 里的引用。worker 卡的下游依赖写在自然语言里,**看不出来** ——
|
|
16
|
+
* 所以本函数**不声称**能算出 worker 卡的波及面。这一格是已知盲区,不是漏了。
|
|
17
|
+
*/
|
|
18
|
+
import type { Card } from '../../shared/types.js';
|
|
19
|
+
/** seq → 直接引用了它的卡。 */
|
|
20
|
+
export declare function buildReverseRefs(cards: Card[]): Map<string, Set<string>>;
|
|
21
|
+
/**
|
|
22
|
+
* 从 `seq` 出发的重跑波及面(**含它自己**)。
|
|
23
|
+
*
|
|
24
|
+
* 🔴 环:引用被限制为**跨波**(见 `cardRefs`),所以图上不该有环。
|
|
25
|
+
* 但这里仍然按"访问过就不再展开"处理 —— **防御的是数据坏掉,不是设计**;
|
|
26
|
+
* 真出现环时它表现为"少跑几张",而不是**死循环把 tick 挂住**。
|
|
27
|
+
*/
|
|
28
|
+
export declare function rerunClosure(seq: string, cards: Card[]): string[];
|
|
29
|
+
//# sourceMappingURL=rerunGraph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rerunGraph.d.ts","sourceRoot":"","sources":["../../../src/core/tools/rerunGraph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAGlD,sBAAsB;AACtB,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAUxE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,EAAE,CAejE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { collectRefs } from './cardRefs.js';
|
|
2
|
+
/** seq → 直接引用了它的卡。 */
|
|
3
|
+
export function buildReverseRefs(cards) {
|
|
4
|
+
const rev = new Map();
|
|
5
|
+
for (const c of cards) {
|
|
6
|
+
if (!c.input)
|
|
7
|
+
continue;
|
|
8
|
+
for (const r of collectRefs(c.input)) {
|
|
9
|
+
if (!rev.has(r.seq))
|
|
10
|
+
rev.set(r.seq, new Set());
|
|
11
|
+
rev.get(r.seq).add(c.seq);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return rev;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* 从 `seq` 出发的重跑波及面(**含它自己**)。
|
|
18
|
+
*
|
|
19
|
+
* 🔴 环:引用被限制为**跨波**(见 `cardRefs`),所以图上不该有环。
|
|
20
|
+
* 但这里仍然按"访问过就不再展开"处理 —— **防御的是数据坏掉,不是设计**;
|
|
21
|
+
* 真出现环时它表现为"少跑几张",而不是**死循环把 tick 挂住**。
|
|
22
|
+
*/
|
|
23
|
+
export function rerunClosure(seq, cards) {
|
|
24
|
+
const rev = buildReverseRefs(cards);
|
|
25
|
+
const seen = new Set([seq]);
|
|
26
|
+
const queue = [seq];
|
|
27
|
+
while (queue.length > 0) {
|
|
28
|
+
const cur = queue.shift();
|
|
29
|
+
for (const next of rev.get(cur) ?? []) {
|
|
30
|
+
if (seen.has(next))
|
|
31
|
+
continue;
|
|
32
|
+
seen.add(next);
|
|
33
|
+
queue.push(next);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// 按波次升序回 —— 调用方据此重置/重跑,顺序与执行顺序一致
|
|
37
|
+
const orderOf = new Map(cards.map((c) => [c.seq, typeof c.order === 'number' ? c.order : Number.parseInt(c.seq, 10)]));
|
|
38
|
+
return [...seen].sort((a, b) => (orderOf.get(a) ?? 0) - (orderOf.get(b) ?? 0) || a.localeCompare(b));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=rerunGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rerunGraph.js","sourceRoot":"","sources":["../../../src/core/tools/rerunGraph.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,sBAAsB;AACtB,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,CAAC,KAAK;YAAE,SAAS;QACvB,KAAK,MAAM,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;YAC9C,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,KAAa;IACrD,MAAM,GAAG,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,EAAY,CAAC;QACpC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACf,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,iCAAiC;IACjC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvH,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC"}
|
|
@@ -103,6 +103,19 @@ export declare class StageEngine {
|
|
|
103
103
|
private releaseAndDone;
|
|
104
104
|
private checkActiveCard;
|
|
105
105
|
private prepareCard;
|
|
106
|
+
/**
|
|
107
|
+
* 执行一张 `kind:'tool'` 卡。
|
|
108
|
+
*
|
|
109
|
+
* 🔴 **与 worker 卡的差别只有两件:载荷与执行者** —— 状态流转、波次、依赖完全一样,
|
|
110
|
+
* 所以这里做的仍然是"跑完 → 移到 done",不是另一套生命周期。
|
|
111
|
+
*
|
|
112
|
+
* 🔴 **不占 worker 槽位**:工具卡是本进程内的函数调用(秒级),
|
|
113
|
+
* 占槽位会让一张缩图卡挡住一个真正要跑几十分钟的 worker。
|
|
114
|
+
*
|
|
115
|
+
* 🔴 失败**不自动重试**留给上层:能力是幂等的,所以重试是安全的 ——
|
|
116
|
+
* 但"什么时候重试"是编排策略,不是执行细节。这里只如实回失败。
|
|
117
|
+
*/
|
|
118
|
+
private runToolCard;
|
|
106
119
|
private launchWorker;
|
|
107
120
|
private listRuntimeAwareActiveCards;
|
|
108
121
|
private reconcilePmStatesWithRuntime;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StageEngine.d.ts","sourceRoot":"","sources":["../../src/engines/StageEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAKzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAIjG,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAmC,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAEnG,OAAO,KAAK,EAAgC,IAAI,EAAE,aAAa,EAAqB,MAAM,oBAAoB,CAAC;AAe/G,kEAAkE;AAClE,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAE7D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAGjD;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,MAAM,CAKzD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CASlF;AAED;;;;;;;;;GASG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW;IAEnB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,eAAe;IACvB,OAAO,CAAC,QAAQ,CAAC;IAZnB,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAAe;gBAGzB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,WAAW,EAChC,YAAY,EAAE,WAAW,EACjB,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,sBAAsB,EACvC,QAAQ,CAAC,EAAE,QAAQ,YAAA;IAM7B,2BAA2B;IAC3B,IAAI,IAAI,IAAI,MAAM,CAA4B;IAE9C,mFAAmF;IACnF,IAAI,YAAY,IAAI,OAAO,CAAkC;IAE7D,iFAAiF;IACjF,IAAI,WAAW,IAAI,OAAO,CAAqD;IAE/E,2DAA2D;IAGrD,IAAI,CAAC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"StageEngine.d.ts","sourceRoot":"","sources":["../../src/engines/StageEngine.ts"],"names":[],"mappings":"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"}
|
|
@@ -200,7 +200,10 @@ export class StageEngine {
|
|
|
200
200
|
actions.push({ action: 'skip', entity: `seq:${card.seq}`, result: 'skip', message: 'Has auxiliary state label' });
|
|
201
201
|
continue;
|
|
202
202
|
}
|
|
203
|
-
|
|
203
|
+
// v0.66 编排:按 kind 分派。缺省(无 kind)= worker ⇒ 存量卡走原路,一行行为不变。
|
|
204
|
+
const launchResult = card.kind === 'tool'
|
|
205
|
+
? await this.runToolCard(card, opts)
|
|
206
|
+
: await this.launchWorker(card, opts, failedSlots);
|
|
204
207
|
actions.push(launchResult);
|
|
205
208
|
if (launchResult.result === 'ok')
|
|
206
209
|
actionsThisTick++;
|
|
@@ -709,6 +712,74 @@ export class StageEngine {
|
|
|
709
712
|
}
|
|
710
713
|
}
|
|
711
714
|
// ─── First stage: launch worker (Ready → Active) ───────────────
|
|
715
|
+
/**
|
|
716
|
+
* 执行一张 `kind:'tool'` 卡。
|
|
717
|
+
*
|
|
718
|
+
* 🔴 **与 worker 卡的差别只有两件:载荷与执行者** —— 状态流转、波次、依赖完全一样,
|
|
719
|
+
* 所以这里做的仍然是"跑完 → 移到 done",不是另一套生命周期。
|
|
720
|
+
*
|
|
721
|
+
* 🔴 **不占 worker 槽位**:工具卡是本进程内的函数调用(秒级),
|
|
722
|
+
* 占槽位会让一张缩图卡挡住一个真正要跑几十分钟的 worker。
|
|
723
|
+
*
|
|
724
|
+
* 🔴 失败**不自动重试**留给上层:能力是幂等的,所以重试是安全的 ——
|
|
725
|
+
* 但"什么时候重试"是编排策略,不是执行细节。这里只如实回失败。
|
|
726
|
+
*/
|
|
727
|
+
async runToolCard(card, opts) {
|
|
728
|
+
const seq = card.seq;
|
|
729
|
+
if (opts.dryRun) {
|
|
730
|
+
return { action: 'tool', entity: `seq:${seq}`, result: 'ok', message: `dry-run ${card.tool ?? '(no tool)'}` };
|
|
731
|
+
}
|
|
732
|
+
const { executeToolCard } = await import('../core/tools/ToolCardExecutor.js');
|
|
733
|
+
const { CapabilityRegistry } = await import('../core/tools/registry.js');
|
|
734
|
+
const { artCapabilities } = await import('../core/tools/artCapabilities.js');
|
|
735
|
+
const { resolveRefs } = await import('../core/tools/cardRefs.js');
|
|
736
|
+
const registry = new CapabilityRegistry(artCapabilities());
|
|
737
|
+
// 卡片间引用:`${card:11.out}`。**跨波才允许** —— 同波并行,互相引用是竞态。
|
|
738
|
+
const all = await this.taskBackend.listAll();
|
|
739
|
+
const orderOf = new Map(all.map((x) => [x.seq, typeof x.order === 'number' ? x.order : Number.parseInt(x.seq, 10)]));
|
|
740
|
+
const outputs = new Map(all
|
|
741
|
+
.map((x) => [x.seq, x.meta?.toolResult ?? null])
|
|
742
|
+
.filter((e) => e[1] !== null));
|
|
743
|
+
const selfOrder = typeof card.order === 'number' ? card.order : Number.parseInt(seq, 10);
|
|
744
|
+
const refs = resolveRefs(card.input ?? {}, selfOrder, outputs, orderOf);
|
|
745
|
+
if (!refs.ok) {
|
|
746
|
+
this.log.error(`seq ${seq}: 引用解析失败 ${refs.code}: ${refs.message}`);
|
|
747
|
+
this.logEvent('tool-card', seq, 'fail', { code: refs.code, error: refs.message });
|
|
748
|
+
try {
|
|
749
|
+
await this.taskBackend.addLabel(seq, 'NEEDS-FIX');
|
|
750
|
+
}
|
|
751
|
+
catch { /* 打标失败不掩盖真因 */ }
|
|
752
|
+
return { action: 'tool', entity: `seq:${seq}`, result: 'fail', message: `${refs.code}: ${refs.message}` };
|
|
753
|
+
}
|
|
754
|
+
const resolvedCard = { ...card, input: refs.input };
|
|
755
|
+
const outcome = await executeToolCard(resolvedCard, registry, {
|
|
756
|
+
project: this.ctx.projectName,
|
|
757
|
+
projectDir: this.ctx.paths.repoDir,
|
|
758
|
+
});
|
|
759
|
+
if (!outcome.ok) {
|
|
760
|
+
this.log.error(`seq ${seq}: 工具卡失败 ${outcome.code}: ${outcome.message}`);
|
|
761
|
+
this.logEvent('tool-card', seq, 'fail', { code: outcome.code, error: outcome.message });
|
|
762
|
+
// 与 worker 卡同一条:失败**留在原地**并打标,不自动往前推 —— 图上要看得见它卡住了
|
|
763
|
+
try {
|
|
764
|
+
await this.taskBackend.addLabel(seq, 'NEEDS-FIX');
|
|
765
|
+
}
|
|
766
|
+
catch { /* 打标失败不掩盖真因 */ }
|
|
767
|
+
return { action: 'tool', entity: `seq:${seq}`, result: 'fail', message: `${outcome.code}: ${outcome.message}` };
|
|
768
|
+
}
|
|
769
|
+
this.logEvent('tool-card', seq, 'ok', { tool: card.tool, result: outcome.result });
|
|
770
|
+
// 产物写进卡片 meta —— 下一波的卡靠 `${card:<seq>.…}` 引用它。
|
|
771
|
+
// 🔴 **先落产物再移状态**:反过来的话,卡片已经 done 而产物还没落,
|
|
772
|
+
// 下一波读到空产物,而图上看起来一切正常(提交点语义,同发布链那条)。
|
|
773
|
+
try {
|
|
774
|
+
const meta = await this.taskBackend.metaRead(seq);
|
|
775
|
+
await this.taskBackend.metaWrite(seq, { ...meta, toolResult: outcome.result });
|
|
776
|
+
}
|
|
777
|
+
catch (err) {
|
|
778
|
+
this.log.warn(`seq ${seq}: 产物写入 meta 失败(引用它的卡会取不到值): ${err instanceof Error ? err.message : String(err)}`);
|
|
779
|
+
}
|
|
780
|
+
await this.releaseAndDone(card, []);
|
|
781
|
+
return { action: 'tool', entity: `seq:${seq}`, result: 'ok', message: `${card.tool} 完成` };
|
|
782
|
+
}
|
|
712
783
|
async launchWorker(card, opts, failedSlots = new Set()) {
|
|
713
784
|
const seq = card.seq;
|
|
714
785
|
const worktreePath = this.ctx.paths.repoDir; // Single worker: always use PROJECT_DIR
|