@zhushanwen/pi-subagent-workflow 0.4.0 → 0.4.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/package.json +6 -6
- package/src/execution/__tests__/bg-notify-render.test.ts +1 -1
- package/src/execution/__tests__/crash-recovery.test.ts +3 -3
- package/src/execution/__tests__/execute-nesting.test.ts +16 -0
- package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
- package/src/execution/__tests__/index-session-start.test.ts +4 -4
- package/src/execution/__tests__/sdk-contract.test.ts +1 -1
- package/src/execution/__tests__/session-start-reaper.test.ts +3 -3
- package/src/execution/__tests__/ui-request-handler-factory.test.ts +1 -1
- package/src/execution/host-mode.ts +1 -1
- package/src/execution/session-runner.ts +1 -1
- package/src/execution/subagent-service.ts +1 -1
- package/src/execution/ui-request-handler-factory.ts +2 -2
- package/src/execution/ui-request-observability.ts +1 -1
- package/src/index.ts +3 -3
- package/src/interface/__tests__/workflow-tool-prompt.test.ts +13 -2
- package/src/interface/bg-notify-render.ts +1 -1
- package/src/interface/commands.ts +1 -1
- package/src/interface/helpers.ts +1 -1
- package/src/interface/list-view.ts +1 -1
- package/src/interface/subagent-actions.ts +1 -1
- package/src/interface/subagent-tool.ts +2 -2
- package/src/interface/subagents.ts +1 -1
- package/src/interface/tool-render.ts +1 -1
- package/src/interface/tool-workflow-script.ts +7 -6
- package/src/interface/tool-workflow.ts +10 -7
- package/src/interface/views/WorkflowsView.ts +2 -2
- package/src/interface/views/detail-content.ts +1 -1
- package/src/interface/views/format.ts +1 -1
- package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +390 -0
- package/src/orchestration/__tests__/worker-script-builder.test.ts +74 -0
- package/src/orchestration/config-loader.ts +1 -1
- package/src/orchestration/error-recovery.ts +77 -13
- package/src/orchestration/jsonl-run-store.ts +2 -2
- package/src/orchestration/worker-script-builder.ts +49 -8
- package/workflows/README.md +5 -3
- package/workflows/chain.js +2 -2
- package/workflows/map-reduce.js +10 -6
- package/workflows/parallel.js +17 -27
- package/workflows/scatter-gather.js +15 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-subagent-workflow",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"description": "Unified subagent execution and multi-agent workflow orchestration for Pi — spawned-process agent runtime with sync/background modes, stateful workflow management with persistence, state machine, and execution tracing.",
|
|
@@ -43,14 +43,14 @@
|
|
|
43
43
|
"@xyz-agent/extension-protocol": "^0.2.0"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
|
-
"@
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
46
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
47
|
+
"@earendil-works/pi-ai": "*",
|
|
48
|
+
"@earendil-works/pi-tui": "*",
|
|
49
49
|
"@sinclair/typebox": "*",
|
|
50
|
-
"@zhushanwen/pi-structured-output": "
|
|
50
|
+
"@zhushanwen/pi-structured-output": "0.3.5"
|
|
51
51
|
},
|
|
52
52
|
"peerDependenciesMeta": {
|
|
53
|
-
"@
|
|
53
|
+
"@earendil-works/pi-coding-agent": {
|
|
54
54
|
"optional": true
|
|
55
55
|
},
|
|
56
56
|
"@zhushanwen/pi-structured-output": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
//
|
|
9
9
|
// 测试用 mock theme(bg 记录调用色 token),不依赖真实 Pi Theme。
|
|
10
10
|
|
|
11
|
-
import type { Theme } from "@
|
|
11
|
+
import type { Theme } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import { describe, expect, it } from "vitest";
|
|
13
13
|
|
|
14
14
|
import { renderBgNotifyMessage } from "../../interface/bg-notify-render.ts";
|
|
@@ -17,13 +17,13 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
17
17
|
|
|
18
18
|
// ── mock modules(在 import 前声明)──
|
|
19
19
|
|
|
20
|
-
vi.mock("@
|
|
20
|
+
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
21
21
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
22
22
|
}));
|
|
23
23
|
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
24
24
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
25
25
|
}));
|
|
26
|
-
vi.mock("@
|
|
26
|
+
vi.mock("@earendil-works/pi-ai", () => ({
|
|
27
27
|
StringEnum: (values: string[]) => ({ type: "string", enum: values }),
|
|
28
28
|
}));
|
|
29
29
|
vi.mock("@earendil-works/pi-ai", () => ({
|
|
@@ -118,7 +118,7 @@ vi.mock("../../interface/commands.ts", () => ({
|
|
|
118
118
|
}));
|
|
119
119
|
|
|
120
120
|
// ── import 被测工厂 ──
|
|
121
|
-
import type { ExtensionAPI } from "@
|
|
121
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
122
122
|
|
|
123
123
|
import subagentsExtension from "../../index.ts";
|
|
124
124
|
import { Budget } from "../../orchestration/models/budget.ts";
|
|
@@ -105,6 +105,22 @@ vi.mock("../finalized-marker.ts", () => ({
|
|
|
105
105
|
readFinalized: vi.fn(() => false),
|
|
106
106
|
}));
|
|
107
107
|
|
|
108
|
+
// manifest-store mock:writeManifest 用真实 fs.promises 写盘,但本文件 fs 同步方法已 mock
|
|
109
|
+
// (目录从不真实创建)→ open/rename/unlink 全 ENOENT → bestEffort 异步 console.debug。
|
|
110
|
+
// 这些延迟 console 通过 worker RPC(onUserConsoleLog)回流,与 vitest teardown 形成 race:
|
|
111
|
+
// "Closing rpc while onUserConsoleLog was pending" → unhandled rejection / exit 1(flaky)。
|
|
112
|
+
// 本组用例测编排逻辑(pool / depth / throttle),不测 manifest 持久化(有 manifest-store.test.ts
|
|
113
|
+
// 独立覆盖)。故 mock 成 no-op,消除 teardown race 的根因——异步 console 输出。
|
|
114
|
+
vi.mock("../manifest-store.ts", () => {
|
|
115
|
+
class FakeManifestStore {
|
|
116
|
+
writeManifest = vi.fn(async () => {});
|
|
117
|
+
readManifest = vi.fn(async () => null);
|
|
118
|
+
listAllSync = vi.fn(() => []);
|
|
119
|
+
recoverTmpFiles = vi.fn(async () => []);
|
|
120
|
+
}
|
|
121
|
+
return { ManifestStore: FakeManifestStore };
|
|
122
|
+
});
|
|
123
|
+
|
|
108
124
|
// temp-prompt:mock 掉真实 fs.promises I/O,消除 fake-timers 下的 flaky 竞态
|
|
109
125
|
// (详见 run-spawn-integration.test.ts 同名 mock 的注释)。
|
|
110
126
|
vi.mock("../temp-prompt.ts", () => ({
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* Proxy 的 trap 对所有属性访问返回 override 值或 no-op 函数,运行时安全
|
|
14
14
|
* (注册 handler 只调用被 override 的方法,其余方法测试不触及)。
|
|
15
15
|
*/
|
|
16
|
-
import type { ExtensionAPI } from "@
|
|
16
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
17
17
|
|
|
18
18
|
export function mockExtensionApi(
|
|
19
19
|
overrides: Record<string, unknown> = {},
|
|
@@ -28,7 +28,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
28
28
|
// ExtensionContext/ExtensionMode 等 *类型*(编译期擦除)+ getAgentDir 运行时值。服务于
|
|
29
29
|
// 全仓库绝大多数测试的类型解析与轻量 mock(不 import 真实重模块的测试直接吃 alias)。
|
|
30
30
|
// 2. **本文件内联 vi.mock(下方)**:vi.mock 在运行时覆盖 config alias,确保本文件 import
|
|
31
|
-
// 真实 index.ts(它 `import { getAgentDir } from "@
|
|
31
|
+
// 真实 index.ts(它 `import { getAgentDir } from "@earendil-works/pi-coding-agent"` +
|
|
32
32
|
// 一组 type-only import)时,运行时只暴露 getAgentDir,彻底隔离真实 SDK 的模块顶层
|
|
33
33
|
// 副作用(避免 jiti 加载真实 pi 包触发未 mock 的依赖链)。
|
|
34
34
|
// 3. 形状一致性:内联 mock 的运行时值形状(`{ getAgentDir }`)与 alias stub 的运行时值
|
|
@@ -39,13 +39,13 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
39
39
|
// 测试统一用内联 vi.mock 覆盖),三者保持一致。
|
|
40
40
|
// 结论:不抽共享 mocks 文件。alias 已承担类型解析,内联 vi.mock 承担运行时隔离,职责正交。
|
|
41
41
|
|
|
42
|
-
vi.mock("@
|
|
42
|
+
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
43
43
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
44
44
|
}));
|
|
45
45
|
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
46
46
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
47
47
|
}));
|
|
48
|
-
vi.mock("@
|
|
48
|
+
vi.mock("@earendil-works/pi-ai", () => ({
|
|
49
49
|
StringEnum: (values: string[]) => ({ type: "string", enum: values }),
|
|
50
50
|
}));
|
|
51
51
|
vi.mock("@earendil-works/pi-ai", () => ({
|
|
@@ -155,7 +155,7 @@ vi.mock("../../interface/commands.ts", () => ({
|
|
|
155
155
|
}));
|
|
156
156
|
|
|
157
157
|
// ── import 被测工厂 ──
|
|
158
|
-
import type { ExtensionAPI } from "@
|
|
158
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
159
159
|
|
|
160
160
|
import subagentsExtension from "../../index.ts";
|
|
161
161
|
|
|
@@ -18,7 +18,7 @@ import { describe, expect, it, vi } from "vitest";
|
|
|
18
18
|
|
|
19
19
|
// registerSubagentTool 经 subagent-tool.ts 值导入 StringEnum(pi-ai)+ Type(typebox)。
|
|
20
20
|
// shared/types stub 是 .d.ts(仅类型),pnpm optional-peer-dep 插件拦截值导入 → vi.mock 兜底。
|
|
21
|
-
vi.mock("@
|
|
21
|
+
vi.mock("@earendil-works/pi-ai", () => ({
|
|
22
22
|
StringEnum: (values: string[]) => ({ type: "string", enum: values }),
|
|
23
23
|
}));
|
|
24
24
|
vi.mock("@earendil-works/pi-ai", () => ({
|
|
@@ -9,13 +9,13 @@ import { beforeEach,describe, expect, it, vi } from "vitest";
|
|
|
9
9
|
|
|
10
10
|
// ── mock modules(在 import 前声明)──
|
|
11
11
|
|
|
12
|
-
vi.mock("@
|
|
12
|
+
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
13
13
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
14
14
|
}));
|
|
15
15
|
vi.mock("@earendil-works/pi-coding-agent", () => ({
|
|
16
16
|
getAgentDir: () => "/home/user/.pi/agent",
|
|
17
17
|
}));
|
|
18
|
-
vi.mock("@
|
|
18
|
+
vi.mock("@earendil-works/pi-ai", () => ({
|
|
19
19
|
StringEnum: (values: string[]) => ({ type: "string", enum: values }),
|
|
20
20
|
}));
|
|
21
21
|
vi.mock("@earendil-works/pi-ai", () => ({
|
|
@@ -104,7 +104,7 @@ vi.mock("../tui/bg-notify-render.ts", () => ({
|
|
|
104
104
|
}));
|
|
105
105
|
|
|
106
106
|
// ── import 被测工厂 ──
|
|
107
|
-
import type { ExtensionAPI } from "@
|
|
107
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
108
108
|
|
|
109
109
|
import subagentsExtension from "../../index.ts";
|
|
110
110
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
// realHandler 路由:channel 命中 → channelHandler(经 coerceUiResponse 形变);未命中 → defaultDialogForward(cancelled)。
|
|
10
10
|
// 测接口契约,不测实现细节。
|
|
11
11
|
|
|
12
|
-
import type { ExtensionContext, ExtensionMode } from "@
|
|
12
|
+
import type { ExtensionContext, ExtensionMode } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
14
14
|
|
|
15
15
|
import { DialogGlobalQueue, type UiRequest } from "../dialog-queue.ts";
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
// 集中到单一修改点,未来 Pi 新增 mode 值时只改本文件。
|
|
17
17
|
// - 业务语义命名("gui"/"headless")比原始枚举值更清晰表达意图。
|
|
18
18
|
|
|
19
|
-
import type { ExtensionMode } from "@
|
|
19
|
+
import type { ExtensionMode } from "@earendil-works/pi-coding-agent";
|
|
20
20
|
|
|
21
21
|
/** 主进程运行模式分类。基于 ExtensionMode 聚合为业务语义。
|
|
22
22
|
* - "tui":纯 Pi TUI,ctx.ui.custom 可用,用户在终端交互
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { type ChildProcess,execFileSync, spawn } from "node:child_process";
|
|
10
10
|
import * as fs from "node:fs";
|
|
11
11
|
|
|
12
|
-
import type { ExtensionMode } from "@
|
|
12
|
+
import type { ExtensionMode } from "@earendil-works/pi-coding-agent";
|
|
13
13
|
|
|
14
14
|
import { type MirrorFlags, mirrorMainProcessFlags } from "./argv-mirror.ts";
|
|
15
15
|
import { writeAliveMarker } from "./alive-store.ts";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
|
|
7
|
-
import type { ExtensionMode } from "@
|
|
7
|
+
import type { ExtensionMode } from "@earendil-works/pi-coding-agent";
|
|
8
8
|
|
|
9
9
|
import type { AgentResult as WorkflowAgentResult } from "../orchestration/models/types.ts";
|
|
10
10
|
// D-A10: workflow 侧 AgentResult 映射(executeAndAwait 出口)
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
// SR-3:调用方(index.ts session_start)无论 new 还是 existing SubagentService 都必须调
|
|
19
19
|
// setUiRequestHandler——/resume /fork 复用 existingService 时旧 handler 可能已失效。
|
|
20
20
|
|
|
21
|
-
import type { ExtensionContext } from "@
|
|
21
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
22
22
|
|
|
23
23
|
import { DialogGlobalQueue, type UiRequest, type UiRequestHandler, type UiResponse } from "./dialog-queue.ts";
|
|
24
24
|
import { type HostMode, resolveHostMode } from "./host-mode.ts";
|
|
@@ -117,7 +117,7 @@ function coerceUiResponse(raw: unknown, reqId: string): UiResponse {
|
|
|
117
117
|
* select 请求转发为普通 select(title 可能含 marker,主 agent 会忽略或当普通 select 渲染)。
|
|
118
118
|
*
|
|
119
119
|
* 实现依据(SDK ExtensionUIContext 真实签名,read from
|
|
120
|
-
* @
|
|
120
|
+
* @earendil-works/pi-coding-agent dist/core/extensions/types.d.ts):
|
|
121
121
|
* select(title: string, options: string[], opts?): Promise<string | undefined>
|
|
122
122
|
* confirm(title: string, message: string, opts?): Promise<boolean>
|
|
123
123
|
* input(title: string, placeholder?: string, opts?): Promise<string | undefined>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// UI 请求可观测性状态(从 subagent-service.ts 提取,降低主文件行数)。
|
|
4
4
|
// 持有 sessionMode + handler 缺失告警去重集合,供 SubagentService 委托调用。
|
|
5
5
|
|
|
6
|
-
import type { ExtensionMode } from "@
|
|
6
|
+
import type { ExtensionMode } from "@earendil-works/pi-coding-agent";
|
|
7
7
|
|
|
8
8
|
// ── 跨模块桥接(ui-request-queue 无 ctx.service 引用时走这里) ──
|
|
9
9
|
//
|
package/src/index.ts
CHANGED
|
@@ -17,8 +17,8 @@ import * as fs from "node:fs";
|
|
|
17
17
|
import * as os from "node:os";
|
|
18
18
|
import * as path from "node:path";
|
|
19
19
|
|
|
20
|
-
import type { ExtensionAPI, ExtensionContext, ModelSelectEvent, ResourcesDiscoverEvent, ResourcesDiscoverResult, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent } from "@
|
|
21
|
-
import { getAgentDir } from "@
|
|
20
|
+
import type { ExtensionAPI, ExtensionContext, ModelSelectEvent, ResourcesDiscoverEvent, ResourcesDiscoverResult, SessionShutdownEvent, SessionStartEvent, SessionTreeEvent } from "@earendil-works/pi-coding-agent";
|
|
21
|
+
import { getAgentDir } from "@earendil-works/pi-coding-agent";
|
|
22
22
|
|
|
23
23
|
import type { AgentRegistry } from "./execution/agent-registry.ts";
|
|
24
24
|
import { bestEffort } from "./execution/best-effort.ts";
|
|
@@ -60,7 +60,7 @@ import { WorkflowScriptRegistryImpl } from "./orchestration/workflow-script-regi
|
|
|
60
60
|
|
|
61
61
|
// ── pi.__workflowRun 类型扩展(D-8 签名) ─────────────────
|
|
62
62
|
|
|
63
|
-
declare module "@
|
|
63
|
+
declare module "@earendil-works/pi-coding-agent" {
|
|
64
64
|
interface ExtensionAPI {
|
|
65
65
|
__workflowRun?: (
|
|
66
66
|
workflowName: string,
|
|
@@ -40,8 +40,8 @@ describe("U1: workflow tool prompt mentions built-in workflows", () => {
|
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
it("tool-workflow.ts promptGuidelines 含 run action 的正例", () => {
|
|
43
|
-
// 给出
|
|
44
|
-
expect(TOOL_WORKFLOW_SRC).
|
|
43
|
+
// 给出 run 调用的 JSON 示例,LLM 才知道参数格式(action/name/args 嵌套)。
|
|
44
|
+
expect(TOOL_WORKFLOW_SRC).toContain('{"action":"run","name":"');
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
it("promptGuidelines 含 JSON 调用正例(run/status/lifecycle)", () => {
|
|
@@ -69,4 +69,15 @@ describe("U1: workflow tool prompt mentions built-in workflows", () => {
|
|
|
69
69
|
// 反向交叉引用:list 的指引里要提到用 workflow tool 的 run action 启动脚本。
|
|
70
70
|
expect(TOOL_WORKFLOW_SCRIPT_SRC).toMatch(/workflow.*tool.*run|run.*workflow.*tool/i);
|
|
71
71
|
});
|
|
72
|
+
|
|
73
|
+
it("tool-workflow.ts promptGuidelines 强化 anti-generate(直接 run,不要 generate)", () => {
|
|
74
|
+
// session 证据:弱模型看到 workflow list 后倾向 workflow-script generate 而非直接 run。
|
|
75
|
+
// 提示词必须显式禁止对内置编排使用 generate。
|
|
76
|
+
expect(TOOL_WORKFLOW_SRC).toContain("NEVER use workflow-script action:generate");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("tool-workflow-script.ts promptGuidelines 强化 anti-generate(CRITICAL ANTI-PATTERN)", () => {
|
|
80
|
+
expect(TOOL_WORKFLOW_SCRIPT_SRC).toContain("CRITICAL ANTI-PATTERN");
|
|
81
|
+
expect(TOOL_WORKFLOW_SCRIPT_SRC).toContain("NEVER generate");
|
|
82
|
+
});
|
|
72
83
|
});
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* - spec.md UC-3(用户输入 /workflows,打开三级导航 TUI 面板)
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@
|
|
22
|
+
import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
23
23
|
|
|
24
24
|
import type { LauncherDeps } from "../orchestration/launcher.ts";
|
|
25
25
|
import { abortRun, pauseRun, resumeRun } from "../orchestration/lifecycle.ts";
|
package/src/interface/helpers.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 参考:domain-models.md §D-12。
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type { ExtensionAPI } from "@
|
|
11
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
|
|
13
13
|
import type { WorkflowRun } from "../orchestration/models/workflow-run.ts";
|
|
14
14
|
import {
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// 9. 动画 setInterval(250ms) 安全:行数恒定(pad 到满屏),diff 只重画 spinner/elapsed
|
|
34
34
|
|
|
35
35
|
import { matchesKey } from "@earendil-works/pi-tui";
|
|
36
|
-
import type { ExtensionContext } from "@
|
|
36
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
37
37
|
|
|
38
38
|
import type { SubagentService } from "../execution/subagent-service.ts";
|
|
39
39
|
import type { SubagentRecord } from "../execution/types.ts";
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
//
|
|
9
9
|
// content(JSON 字符串)给 LLM,details(SubagentToolResult)给 renderResult,同源同处生成。
|
|
10
10
|
|
|
11
|
-
import type { AgentToolResult } from "@
|
|
11
|
+
import type { AgentToolResult } from "@earendil-works/pi-coding-agent";
|
|
12
12
|
import {
|
|
13
13
|
guiComponent,
|
|
14
14
|
type GuiContext,
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
// 抽到顶层后参数类型由 alias 提供,绕过该 quirk。
|
|
11
11
|
|
|
12
12
|
import type { Component } from "@earendil-works/pi-tui";
|
|
13
|
-
import { StringEnum } from "@
|
|
14
|
-
import type { AgentToolResult, ExtensionAPI, ExtensionContext, Theme } from "@
|
|
13
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
14
|
+
import type { AgentToolResult, ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
15
15
|
import { Type } from "@sinclair/typebox";
|
|
16
16
|
|
|
17
17
|
import { SLUG_MAX_LENGTH } from "../execution/execute-options-mapper.ts";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// 解析:args[0] 直接作可选 <id>(聚焦该 record)。
|
|
6
6
|
// RPC 模式(xyz-agent GUI):解析 cancel action 直接执行,不打开 TUI。
|
|
7
7
|
|
|
8
|
-
import type { ExtensionAPI, ExtensionCommandContext } from "@
|
|
8
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
9
9
|
|
|
10
10
|
import { getSubagentService } from "../execution/subagent-service.ts";
|
|
11
11
|
import { parseSubagentRpcCommand } from "./command-actions.ts";
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
import type { Component } from "@earendil-works/pi-tui";
|
|
21
21
|
import { Container, Text } from "@earendil-works/pi-tui";
|
|
22
|
-
import type { AgentToolResult, Theme } from "@
|
|
22
|
+
import type { AgentToolResult, Theme } from "@earendil-works/pi-coding-agent";
|
|
23
23
|
|
|
24
24
|
import type {
|
|
25
25
|
ListResponse,
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
19
19
|
import { resolve as pathResolve } from "node:path";
|
|
20
20
|
|
|
21
|
-
import { StringEnum } from "@
|
|
22
|
-
import type { ExtensionAPI, ExtensionContext, Theme } from "@
|
|
23
|
-
import { Text } from "@
|
|
21
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
22
|
+
import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
23
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
24
24
|
import { type Static, Type } from "typebox";
|
|
25
25
|
|
|
26
26
|
import {
|
|
@@ -178,9 +178,10 @@ export function registerWorkflowScriptTool(
|
|
|
178
178
|
"Use this to discover built-in workflows (chain/parallel/scatter-gather/map-reduce) " +
|
|
179
179
|
"and user-generated scripts before starting a run. After listing, start a script via " +
|
|
180
180
|
"the workflow tool with action:run and the script name.",
|
|
181
|
-
"ANTI-PATTERN:
|
|
182
|
-
"
|
|
183
|
-
"
|
|
181
|
+
"CRITICAL ANTI-PATTERN: NEVER generate scripts for chain/parallel/scatter-gather/map-reduce. " +
|
|
182
|
+
"These are BUILT-IN — use the workflow tool with action:run directly. " +
|
|
183
|
+
"generate is for NOVEL orchestration patterns ONLY. When in doubt, action:list first, " +
|
|
184
|
+
"then action:run — not action:generate.",
|
|
184
185
|
],
|
|
185
186
|
parameters: WorkflowScriptParams,
|
|
186
187
|
|
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
* 参考:domain-models.md §FR-5(tool 收口 4→2)。
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import { StringEnum } from "@
|
|
21
|
-
import type { ExtensionAPI, ExtensionContext, Theme } from "@
|
|
22
|
-
import { Text } from "@
|
|
20
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
21
|
+
import type { ExtensionAPI, ExtensionContext, Theme } from "@earendil-works/pi-coding-agent";
|
|
22
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
23
23
|
import {
|
|
24
24
|
guiComponent,
|
|
25
25
|
type GuiContext,
|
|
@@ -235,12 +235,12 @@ export function registerWorkflowTool(
|
|
|
235
235
|
promptSnippet: "Run, pause, resume, abort, or check workflow status",
|
|
236
236
|
promptGuidelines: [
|
|
237
237
|
"PRIORITY: When user says 'workflow', 'run workflow', try run action FIRST.",
|
|
238
|
-
"BUILT-IN workflows
|
|
239
|
-
"chain (analyze→transform→synthesize
|
|
238
|
+
"BUILT-IN workflows — run DIRECTLY with action:run, do NOT use workflow-script generate for these: " +
|
|
239
|
+
"chain (sequential 3-step: analyze→transform→synthesize; args: task), " +
|
|
240
240
|
"parallel (multi-perspective analysis; args: target, optional perspectives), " +
|
|
241
|
-
"scatter-gather (split→parallel
|
|
241
|
+
"scatter-gather (split→parallel→merge; args: task), " +
|
|
242
242
|
"map-reduce (parallel map→reduce; args: items/itemsJson + operation). " +
|
|
243
|
-
"Example:
|
|
243
|
+
"Example: {\"action\":\"run\",\"name\":\"parallel\",\"args\":{\"target\":\"src/auth.ts\"}}.",
|
|
244
244
|
"DISCOVERY: If unsure what workflows exist, call the workflow-script tool with " +
|
|
245
245
|
"action:list first — it returns all available scripts (built-in + user-generated) " +
|
|
246
246
|
"with source tags and descriptions. Then use this tool's run action to start one.",
|
|
@@ -251,6 +251,9 @@ export function registerWorkflowTool(
|
|
|
251
251
|
"- status: {\"action\":\"status\"}. " +
|
|
252
252
|
"- pause/resume/abort: {\"action\":\"pause\",\"runId\":\"<id>\"} (abort optional: ,\"error\":\"<reason>\"}).",
|
|
253
253
|
"Anti-patterns: Flattening args sub-fields (task/items/...) to the top level — they belong inside args. Calling {\"action\":\"run\"} without name.",
|
|
254
|
+
"CRITICAL: For chain/parallel/scatter-gather/map-reduce orchestration, ALWAYS use action:run with the built-in name. " +
|
|
255
|
+
"NEVER use workflow-script action:generate to create these patterns — they already exist. " +
|
|
256
|
+
"workflow-script generate is ONLY for novel patterns not covered by built-ins.",
|
|
254
257
|
],
|
|
255
258
|
parameters: WorkflowParams,
|
|
256
259
|
|
|
@@ -26,8 +26,8 @@ import { promises as fsPromises } from "node:fs";
|
|
|
26
26
|
import { homedir } from "node:os";
|
|
27
27
|
import { join as pathJoin } from "node:path";
|
|
28
28
|
|
|
29
|
-
import type { ExtensionContext } from "@
|
|
30
|
-
import { Key, matchesKey } from "@
|
|
29
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
30
|
+
import { Key, matchesKey } from "@earendil-works/pi-tui";
|
|
31
31
|
|
|
32
32
|
import {
|
|
33
33
|
getAllToolCalls,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* 避免两者发散(对齐 subagents buildDetailContent / detailContentLength)。
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { Key, matchesKey } from "@
|
|
13
|
+
import { Key, matchesKey } from "@earendil-works/pi-tui";
|
|
14
14
|
|
|
15
15
|
import { getAllToolCalls, projectLiveProgress } from "../../execution/execution-record.ts";
|
|
16
16
|
import type { AgentEventLogEntry } from "../../execution/types.ts";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All functions are pure: no Pi runtime, no side effects.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { truncateToWidth, visibleWidth } from "@
|
|
8
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
9
9
|
|
|
10
10
|
import type { AgentEventLogEntry } from "../../execution/types.ts";
|
|
11
11
|
import type { ExecutionTraceNode, ToolCallEntry } from "../../orchestration/models/types.ts";
|