@zhushanwen/pi-subagent-workflow 8.7.0 → 8.8.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/README.md +5 -11
- package/package.json +7 -10
- package/skills/workflow-script-format/SKILL.md +32 -13
- package/src/host/__tests__/pi-host.test.ts +23 -2
- package/src/host/pi-host.ts +57 -3
- package/src/index.ts +56 -110
- package/src/injectors/__tests__/engine-awareness.test.ts +2 -2
- package/src/injectors/__tests__/engine-section-stability.test.ts +6 -4
- package/src/injectors/__tests__/model-list-injector.test.ts +18 -21
- package/src/injectors/__tests__/subagent-list-injector.test.ts +54 -14
- package/src/injectors/__tests__/workflow-list-injector.test.ts +26 -12
- package/src/injectors/engine-awareness.ts +0 -4
- package/src/injectors/model-list-injector.ts +15 -58
- package/src/injectors/subagent-list-injector.ts +55 -113
- package/src/injectors/workflow-list-injector.ts +33 -66
- package/src/interface/__tests__/detectors.test.ts +45 -34
- package/src/interface/__tests__/subagent-tool-prompt.test.ts +6 -3
- package/src/interface/__tests__/tool-workflow-run-builtin-name.test.ts +216 -0
- package/src/interface/__tests__/tool-workflow-script-generate.test.ts +17 -6
- package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +37 -1
- package/src/interface/bg-notify-render.ts +3 -13
- package/src/interface/command-actions.ts +5 -15
- package/src/interface/commands.ts +1 -1
- package/src/interface/format.ts +15 -4
- package/src/interface/gui-mappers.ts +18 -22
- package/src/interface/helpers.ts +8 -129
- package/src/interface/list-component.ts +1 -1
- package/src/interface/list-shared.ts +1 -1
- package/src/interface/list-view.ts +1 -1
- package/src/interface/subagent-actions.ts +51 -676
- package/src/interface/subagent-tool-schema.ts +1 -4
- package/src/interface/subagent-tool.ts +1 -1
- package/src/interface/subagents.ts +1 -1
- package/src/interface/tool-render.ts +3 -13
- package/src/interface/tool-workflow-script.ts +33 -75
- package/src/interface/tool-workflow.ts +51 -88
- package/src/interface/views/WorkflowsView.ts +3 -11
- package/src/interface/views/format.ts +19 -58
- package/src/jsonl-run-store.ts +134 -222
- package/agents/analyst.md +0 -61
- package/agents/coder.md +0 -70
- package/agents/debugger.md +0 -67
- package/agents/doc-reviewer.md +0 -50
- package/agents/explorer.md +0 -64
- package/agents/general-purpose.md +0 -32
- package/agents/orchestrator.md +0 -63
- package/agents/planner.md +0 -54
- package/agents/researcher.md +0 -65
- package/agents/reviewer.md +0 -74
package/src/interface/helpers.ts
CHANGED
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
|
|
11
11
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
|
|
13
|
+
// bounded JSON pretty 序列化(IF13/#19,TC5/ES5)已下沉 core shared
|
|
14
|
+
// (u-core-atomic 逐字平移,输出与原本地实现字节一致;本地实现已删)。
|
|
15
|
+
import { boundedPrettySerialize } from "@zhushanwen/subagent-core/shared/bounded-serialize.ts";
|
|
16
|
+
|
|
13
17
|
import type { WorkflowRun } from "@zhushanwen/subagent-core/orchestration/models/workflow-run.ts";
|
|
14
18
|
import {
|
|
15
19
|
guiComponent,
|
|
@@ -22,134 +26,8 @@ import { mapRunIcon, mapRunStatus } from "./gui-mappers.ts";
|
|
|
22
26
|
|
|
23
27
|
// ── 常量 ─────────────────────────────────────────────────────
|
|
24
28
|
|
|
25
|
-
const JSON_INDENT = 2;
|
|
26
29
|
const MAX_RESULT_LENGTH = 8000;
|
|
27
30
|
|
|
28
|
-
// ── bounded pretty 序列化(IF13/#19,TC5/ES5,helpers 私有)─────────
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* bounded JSON pretty 序列化:只生成会被保留的前缀(≤8000 输出与
|
|
32
|
-
* JSON.stringify(value, null, JSON_INDENT) 逐字节一致;>8000 输出与
|
|
33
|
-
* 全量序列化后 .slice(0, budget) + "\n... (truncated)" 逐字节一致——
|
|
34
|
-
* 等价测试锚定,见 __tests__/helpers-bounded-serialize.test.ts)。
|
|
35
|
-
*
|
|
36
|
-
* 现状成本:全量 stringify 产生数 MB 中间串再丢弃 99%;本函数在输出字符流
|
|
37
|
-
* 越过 budget 后停止一切生成。保真策略:原语(string/number/boolean/null/bigint)
|
|
38
|
-
* 逐值复用 JSON.stringify(转义/Unicode/数字格式原生一致,零重实现),仅结构
|
|
39
|
-
* 拼装(2 空格缩进/逗号/括号)自实现。
|
|
40
|
-
*
|
|
41
|
-
* 特殊值语义(TC5 a-d,与原生 JSON.stringify 全值域对齐):
|
|
42
|
-
* (a) 含 toJSON 的对象 → 该子树整体走一次 JSON.stringify(subtree)(原生会先调
|
|
43
|
-
* toJSON,如 Date 输出带引号序列化串;bounded 拼装展开会与原生不同)。注意
|
|
44
|
-
* 边界:toJSON 返回对象时原生 pretty 会按缩进展开,本实现按原语串接其
|
|
45
|
-
* compact 形态——设计 TC5 锚定面为 Date 型(返回字符串)toJSON。
|
|
46
|
-
* (b) 任何 stringify 抛出(BigInt → TypeError)→ 整体回退 String(value)(对齐
|
|
47
|
-
* 旧实现整体 try/catch 的整串回退;禁止逐节点回退——输出形态与整串回退不同)。
|
|
48
|
-
* (c) 对象属性值为 undefined/function/symbol → 拼装时跳过(原生省略)。
|
|
49
|
-
* (d) 数组元素为 undefined/function/symbol → 序列化为 "null"(原生行为)。
|
|
50
|
-
*
|
|
51
|
-
* 截断边界(输出字符流层级,与对完整串 slice 逐字节等价):逐段 append 时本段
|
|
52
|
-
* 会使总长越过 budget → 只 append 本段前 (budget - 已累积) 字符(恰好 budget,
|
|
53
|
-
* 可切在转义序列/括号中间,不补任何结构闭合);越过(exceeded)才追加
|
|
54
|
-
* "\n... (truncated)" 标记——恰好 ===budget 不加(> 判定)。
|
|
55
|
-
*
|
|
56
|
-
* 祖先 Set 循环引用守卫:命中 → 整体回退 String(value)(同 (b) 整串回退语义)。
|
|
57
|
-
*/
|
|
58
|
-
function boundedPrettySerialize(value: unknown, budget: number): string {
|
|
59
|
-
const ancestors = new Set<object>();
|
|
60
|
-
let out = "";
|
|
61
|
-
let exceeded = false;
|
|
62
|
-
|
|
63
|
-
/** 逐段追加:越过 budget 时截到恰好 budget 并置 exceeded(后续生成全部剪枝)。 */
|
|
64
|
-
function append(s: string): void {
|
|
65
|
-
if (exceeded) return;
|
|
66
|
-
if (out.length + s.length <= budget) {
|
|
67
|
-
out += s;
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
out += s.slice(0, budget - out.length);
|
|
71
|
-
exceeded = true;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function serialize(v: unknown, depth: number): void {
|
|
75
|
-
if (exceeded) return;
|
|
76
|
-
const t = typeof v;
|
|
77
|
-
// 原语逐值复用原生序列化;bigint 的 JSON.stringify 抛 TypeError → 顶层 catch
|
|
78
|
-
// 整体回退 (b);NaN/Infinity → "null"(原生行为)
|
|
79
|
-
if (v === null || t === "string" || t === "number" || t === "boolean" || t === "bigint") {
|
|
80
|
-
append(JSON.stringify(v));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (t === "object" && v !== null) {
|
|
84
|
-
const obj = v as object;
|
|
85
|
-
if (ancestors.has(obj)) {
|
|
86
|
-
// 循环引用 → 整体回退 String(value)(旧实现同款整串回退)
|
|
87
|
-
throw new TypeError("circular reference");
|
|
88
|
-
}
|
|
89
|
-
// (a) toJSON 子树整体 stringify(Reflect.get 取属性,避免不安全断言)
|
|
90
|
-
if (typeof Reflect.get(obj, "toJSON") === "function") {
|
|
91
|
-
append(JSON.stringify(obj));
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
ancestors.add(obj);
|
|
95
|
-
const childIndent = " ".repeat(JSON_INDENT * (depth + 1));
|
|
96
|
-
const closeIndent = " ".repeat(JSON_INDENT * depth);
|
|
97
|
-
if (Array.isArray(obj)) {
|
|
98
|
-
const arr = obj as unknown[];
|
|
99
|
-
if (arr.length === 0) {
|
|
100
|
-
append("[]");
|
|
101
|
-
} else {
|
|
102
|
-
append("[\n");
|
|
103
|
-
for (let i = 0; i < arr.length && !exceeded; i++) {
|
|
104
|
-
if (i > 0) append(",\n");
|
|
105
|
-
append(childIndent);
|
|
106
|
-
const el = arr[i];
|
|
107
|
-
// (d) 数组元素 undefined/function/symbol → "null"
|
|
108
|
-
if (el === undefined || typeof el === "function" || typeof el === "symbol") {
|
|
109
|
-
append("null");
|
|
110
|
-
} else {
|
|
111
|
-
serialize(el, depth + 1);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
append("\n" + closeIndent + "]");
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
// (c) 对象属性 undefined/function/symbol 跳过(Object.entries 同原生:
|
|
118
|
-
// 只取 own enumerable,symbol 键天然不出现;getter 求值语义与原生一致)
|
|
119
|
-
const entries = Object.entries(obj).filter(
|
|
120
|
-
([, val]) => val !== undefined && typeof val !== "function" && typeof val !== "symbol",
|
|
121
|
-
);
|
|
122
|
-
if (entries.length === 0) {
|
|
123
|
-
append("{}");
|
|
124
|
-
} else {
|
|
125
|
-
append("{\n");
|
|
126
|
-
for (let i = 0; i < entries.length && !exceeded; i++) {
|
|
127
|
-
if (i > 0) append(",\n");
|
|
128
|
-
append(childIndent + JSON.stringify(entries[i][0]) + ": ");
|
|
129
|
-
serialize(entries[i][1], depth + 1);
|
|
130
|
-
}
|
|
131
|
-
append("\n" + closeIndent + "}");
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
ancestors.delete(obj);
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
// 顶层 undefined/function/symbol(调用方守卫后不可达;防御兜底对齐原生 "null")
|
|
138
|
-
append(JSON.stringify(v) ?? "null");
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
serialize(value, 0);
|
|
143
|
-
return exceeded ? out + "\n... (truncated)" : out;
|
|
144
|
-
} catch {
|
|
145
|
-
// (b) 整体回退:String(value)(超 budget 仍截断 + 标记,与旧实现截断路径一致)
|
|
146
|
-
const fallback = String(value);
|
|
147
|
-
return fallback.length > budget
|
|
148
|
-
? fallback.slice(0, budget) + "\n... (truncated)"
|
|
149
|
-
: fallback;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
31
|
/**
|
|
154
32
|
* notifiedRunIds 去重窗口大小。
|
|
155
33
|
*
|
|
@@ -164,10 +42,11 @@ const RUN_ID_DISPLAY_LENGTH = 8;
|
|
|
164
42
|
/**
|
|
165
43
|
* notifyDone 的 details 结构(通过 pi.sendMessage 透传给前端)。
|
|
166
44
|
*
|
|
167
|
-
* 抽取为显式接口替代裸 Record<string, unknown>,明确 __gui__
|
|
168
|
-
*
|
|
45
|
+
* 抽取为显式接口替代裸 Record<string, unknown>,明确 __gui__ 契约。
|
|
46
|
+
* 模块私有(原 export 已删):无跨文件消费者,测试经 notifyDone 公共入口
|
|
47
|
+
* 观察并内联类型。
|
|
169
48
|
*/
|
|
170
|
-
|
|
49
|
+
interface WorkflowNotifyDetails {
|
|
171
50
|
runId: string;
|
|
172
51
|
name: string;
|
|
173
52
|
status: string;
|