pi-loop-graph-sdk 0.2.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 +21 -0
- package/README-zh.md +416 -0
- package/README.md +414 -0
- package/ROADMAP.md +60 -0
- package/dist/adapter/complete-tool.d.ts +3 -0
- package/dist/adapter/complete-tool.js +53 -0
- package/dist/adapter/debug-log.d.ts +38 -0
- package/dist/adapter/debug-log.js +151 -0
- package/dist/adapter/extension.d.ts +2 -0
- package/dist/adapter/extension.js +11 -0
- package/dist/adapter/graph-execution-host.d.ts +73 -0
- package/dist/adapter/graph-execution-host.js +181 -0
- package/dist/adapter/isolated-graph-session.d.ts +75 -0
- package/dist/adapter/isolated-graph-session.js +313 -0
- package/dist/adapter/loop-graph-extension.d.ts +96 -0
- package/dist/adapter/loop-graph-extension.js +487 -0
- package/dist/adapter/mechanism-runtime.d.ts +97 -0
- package/dist/adapter/mechanism-runtime.js +670 -0
- package/dist/adapter/model-messages.d.ts +17 -0
- package/dist/adapter/model-messages.js +11 -0
- package/dist/adapter/observability.d.ts +88 -0
- package/dist/adapter/observability.js +31 -0
- package/dist/adapter/output-contract.d.ts +12 -0
- package/dist/adapter/output-contract.js +87 -0
- package/dist/adapter/pi-node-context.d.ts +132 -0
- package/dist/adapter/pi-node-context.js +619 -0
- package/dist/adapter/projection.d.ts +121 -0
- package/dist/adapter/projection.js +169 -0
- package/dist/adapter/skill-content.d.ts +16 -0
- package/dist/adapter/skill-content.js +16 -0
- package/dist/advanced.d.ts +32 -0
- package/dist/advanced.js +17 -0
- package/dist/builders/graph.d.ts +27 -0
- package/dist/builders/graph.js +39 -0
- package/dist/builders/node.d.ts +8 -0
- package/dist/builders/node.js +9 -0
- package/dist/builders/refs.d.ts +5 -0
- package/dist/builders/refs.js +10 -0
- package/dist/builders/route.d.ts +11 -0
- package/dist/builders/route.js +18 -0
- package/dist/core/context.d.ts +73 -0
- package/dist/core/context.js +229 -0
- package/dist/core/graph.d.ts +172 -0
- package/dist/core/graph.js +57 -0
- package/dist/core/json.d.ts +8 -0
- package/dist/core/json.js +46 -0
- package/dist/core/limits.d.ts +7 -0
- package/dist/core/limits.js +14 -0
- package/dist/core/mechanism.d.ts +88 -0
- package/dist/core/mechanism.js +5 -0
- package/dist/core/result.d.ts +41 -0
- package/dist/core/result.js +1 -0
- package/dist/core/schema.d.ts +8 -0
- package/dist/core/schema.js +23 -0
- package/dist/core/skill.d.ts +12 -0
- package/dist/core/skill.js +1 -0
- package/dist/host/baseline.d.ts +11 -0
- package/dist/host/baseline.js +4 -0
- package/dist/host/graph-catalog.d.ts +8 -0
- package/dist/host/graph-catalog.js +24 -0
- package/dist/host/graph-host.d.ts +53 -0
- package/dist/host/graph-host.js +181 -0
- package/dist/host/preflight.d.ts +17 -0
- package/dist/host/preflight.js +81 -0
- package/dist/host/skill-catalog.d.ts +24 -0
- package/dist/host/skill-catalog.js +92 -0
- package/dist/host/tool-catalog.d.ts +27 -0
- package/dist/host/tool-catalog.js +33 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +10 -0
- package/dist/replay/checkpoint.d.ts +40 -0
- package/dist/replay/checkpoint.js +57 -0
- package/dist/replay/events.d.ts +40 -0
- package/dist/replay/events.js +1 -0
- package/dist/replay/finalizer.d.ts +26 -0
- package/dist/replay/finalizer.js +117 -0
- package/dist/replay/html.d.ts +3 -0
- package/dist/replay/html.js +270 -0
- package/dist/replay/index.d.ts +13 -0
- package/dist/replay/index.js +7 -0
- package/dist/replay/model.d.ts +81 -0
- package/dist/replay/model.js +1 -0
- package/dist/replay/parser.d.ts +3 -0
- package/dist/replay/parser.js +332 -0
- package/dist/replay/recorder.d.ts +30 -0
- package/dist/replay/recorder.js +195 -0
- package/dist/replay/store.d.ts +41 -0
- package/dist/replay/store.js +94 -0
- package/dist/router.d.ts +4 -0
- package/dist/router.js +61 -0
- package/dist/runtime/event-bus.d.ts +101 -0
- package/dist/runtime/event-bus.js +18 -0
- package/dist/runtime/graph-runtime.d.ts +173 -0
- package/dist/runtime/graph-runtime.js +1293 -0
- package/dist/runtime/invocation-budget.d.ts +22 -0
- package/dist/runtime/invocation-budget.js +52 -0
- package/dist/runtime/mechanism-runtime.d.ts +92 -0
- package/dist/runtime/mechanism-runtime.js +387 -0
- package/dist/runtime.d.ts +91 -0
- package/dist/runtime.js +258 -0
- package/dist/tools-resolve.d.ts +20 -0
- package/dist/tools-resolve.js +52 -0
- package/dist/type.d.ts +593 -0
- package/dist/type.js +30 -0
- package/dist/validate.d.ts +25 -0
- package/dist/validate.js +203 -0
- package/package.json +69 -0
package/dist/type.d.ts
ADDED
|
@@ -0,0 +1,593 @@
|
|
|
1
|
+
import type { ExtensionAPI, ToolCallEvent, ToolResultEvent, TurnEndEvent, TurnStartEvent } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
/**
|
|
3
|
+
* 图的终止标记,也是图的「返回」出口。
|
|
4
|
+
*
|
|
5
|
+
* 当一条边的 to 指向 END,Runtime 弹出当前图的栈帧,
|
|
6
|
+
* 并将该边 migrate 产出的 output 作为本图的返回值:
|
|
7
|
+
* · 子图调用 → 成为父图 kind="graph" 节点的 NodeCompletion.result
|
|
8
|
+
* · tool 调用 → 成为返回给 agent 的工具结果
|
|
9
|
+
* · 顶层调用 → 成为整次运行的最终产出
|
|
10
|
+
*
|
|
11
|
+
* 向后兼容:未声明 output 时依次回退到 frame.status/result、completion。
|
|
12
|
+
*
|
|
13
|
+
* END 边的 migrate 承担双重身份——既自由定义最后一层工作记忆,
|
|
14
|
+
* 又通过 output 声明「这张图对外交付什么」。
|
|
15
|
+
*/
|
|
16
|
+
export declare const END: unique symbol;
|
|
17
|
+
/**
|
|
18
|
+
* 节点执行完毕的原始产出。
|
|
19
|
+
*/
|
|
20
|
+
export interface NodeCompletion {
|
|
21
|
+
nodeId: string;
|
|
22
|
+
status: "ok" | "failed" | "cancelled";
|
|
23
|
+
result: Record<string, unknown>;
|
|
24
|
+
/** Runtime 生成的可信验收结果;与 AI 自报 result 严格分离。 */
|
|
25
|
+
verifiedResult?: Readonly<{
|
|
26
|
+
checks: readonly MechanismVerifiedResultEntry[];
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 栈中的一层。内容完全由开发者定义;SDK 控制元数据不进入该对象,也不
|
|
31
|
+
* 默认向 LLM 添加 nodeId/status 等内部概念。兼容字段全部可选。
|
|
32
|
+
*/
|
|
33
|
+
export interface ContextFrame extends Record<string, unknown> {
|
|
34
|
+
/** @deprecated 兼容字段;SDK 不再要求或特殊投影这些字段。 */
|
|
35
|
+
nodeId?: string;
|
|
36
|
+
/** @deprecated 兼容字段;图控制状态来自 NodeCompletion。 */
|
|
37
|
+
status?: "ok" | "failed" | "cancelled";
|
|
38
|
+
/** @deprecated 兼容字段;开发者可使用任意上下文结构。 */
|
|
39
|
+
summary?: string;
|
|
40
|
+
/** @deprecated END 返回值兼容通道;新代码优先使用 MigrationResult.output。 */
|
|
41
|
+
result?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
/** 图调用来源。只记录谁触发了运行,不决定上下文共享语义。 */
|
|
44
|
+
export type GraphInvocationKind = "command" | "tool" | "graph-node" | "api";
|
|
45
|
+
/** 图调用边界。来源和边界是两个正交维度。 */
|
|
46
|
+
export type GraphInvocationBoundary = "compose" | "call" | "delegate";
|
|
47
|
+
/** 一次图运行的稳定业务返回;frames/trace 不属于普通返回。 */
|
|
48
|
+
export interface GraphRunResult {
|
|
49
|
+
graphId: string;
|
|
50
|
+
status: "ok" | "failed" | "cancelled";
|
|
51
|
+
result: Record<string, unknown>;
|
|
52
|
+
steps: number;
|
|
53
|
+
}
|
|
54
|
+
/** 一次图运行的显式请求。 */
|
|
55
|
+
export interface GraphRunRequest {
|
|
56
|
+
background: Record<string, unknown>;
|
|
57
|
+
invocationKind: GraphInvocationKind;
|
|
58
|
+
boundary: GraphInvocationBoundary;
|
|
59
|
+
signal?: AbortSignal;
|
|
60
|
+
}
|
|
61
|
+
/** compose fold 接收的帧段只读快照与子图最终结果。 */
|
|
62
|
+
export interface ComposeFoldInput {
|
|
63
|
+
segment: readonly ContextFrame[];
|
|
64
|
+
finalResult: GraphRunResult;
|
|
65
|
+
}
|
|
66
|
+
/** fold 不能伪造父 graph node 的 nodeId,该身份由 Runtime 补齐。 */
|
|
67
|
+
export type ComposeFoldResult = Pick<NodeCompletion, "status" | "result">;
|
|
68
|
+
export type ComposeFrameFolder = (input: ComposeFoldInput) => ComposeFoldResult;
|
|
69
|
+
/**
|
|
70
|
+
* 回路图中的活动主体,持有一个有序帧栈。
|
|
71
|
+
*
|
|
72
|
+
* background — 进入当前图时的背景上下文(不变)
|
|
73
|
+
* frames — 模型可见的有序逻辑工作栈;普通 call 当前只由 Edge.migrate 追加
|
|
74
|
+
* mechanisms — 全局横切机制,跨节点持续生效
|
|
75
|
+
* scratch — mechanism 的唯一合法可变区(见下)
|
|
76
|
+
*
|
|
77
|
+
* 阶段性业务状态不挂在 AgentInstance 上。节点只能从 background 和 frames
|
|
78
|
+
* 读取已经显式进入历史的上下文。
|
|
79
|
+
*
|
|
80
|
+
* scratch 的契约:
|
|
81
|
+
* 1. 只有 Mechanism.apply 可写 scratch。execute 可读,不应写——
|
|
82
|
+
* scratch 是代码侧横切通道,不应绕过 Edge/frame 做跨节点业务状态迁移
|
|
83
|
+
* 2. scratch 不进 agent 上下文。projection 永不渲染它,
|
|
84
|
+
* 它与 input 同侧(代码侧横切状态)。
|
|
85
|
+
* 3. scratch 随 AgentInstance 生命周期。子图新实例 = 新 scratch,
|
|
86
|
+
* 与 frames 隔离契约一致。
|
|
87
|
+
* 4. 跨节点的业务状态迁移仍走 Edge/frame,不走 scratch。scratch 只承载
|
|
88
|
+
* 横切基础设施的工作状态(计时器起点、重试计数等),不是业务迁移通道。
|
|
89
|
+
*/
|
|
90
|
+
export interface AgentInstance {
|
|
91
|
+
id: string;
|
|
92
|
+
globalGoal: string;
|
|
93
|
+
background: Record<string, unknown>;
|
|
94
|
+
frames: ContextFrame[];
|
|
95
|
+
mechanisms: Mechanism[];
|
|
96
|
+
scratch: Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* 当前节点的一次性入参。
|
|
100
|
+
*
|
|
101
|
+
* Entry 为第一个节点构造 input;Edge.migrate 为后继节点构造 input。
|
|
102
|
+
* input 不属于 AgentInstance 的持久状态,节点若希望后续阶段可见某些信息,
|
|
103
|
+
* 必须在完成信号中产出,并由 Edge 折叠进 ContextFrame。
|
|
104
|
+
*/
|
|
105
|
+
export interface NodeInput {
|
|
106
|
+
data: Record<string, unknown>;
|
|
107
|
+
source: {
|
|
108
|
+
kind: "entry";
|
|
109
|
+
entryId: string;
|
|
110
|
+
} | {
|
|
111
|
+
kind: "edge";
|
|
112
|
+
edgeId: string;
|
|
113
|
+
fromNodeId: string;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* 节点执行所需的运行时能力。
|
|
118
|
+
*
|
|
119
|
+
* 这里保持框架级抽象,不绑定 pi 的具体 AgentSession 实现。
|
|
120
|
+
* pi extension 适配层负责把 runAgent/callTool 映射到真实会话、工具和 UI。
|
|
121
|
+
*/
|
|
122
|
+
export interface NodeContext {
|
|
123
|
+
signal: AbortSignal;
|
|
124
|
+
runAgent(request: AgentRunRequest): Promise<NodeCompletion>;
|
|
125
|
+
callTool(name: string, input: Record<string, unknown>): Promise<unknown>;
|
|
126
|
+
}
|
|
127
|
+
export interface AgentRunRequest {
|
|
128
|
+
prompt: string;
|
|
129
|
+
/** @deprecated 工具集由 Node.tools 统一声明。此字段不再生效。 */
|
|
130
|
+
tools?: string[];
|
|
131
|
+
skill?: string;
|
|
132
|
+
/** 单次 Agent Run 的模型可见输出契约,同时作为 Runtime validator 的唯一来源。 */
|
|
133
|
+
outputSchema?: JsonSchema;
|
|
134
|
+
/** 可选:验证 __graph_complete__ 的 result 是否满足节点要求。
|
|
135
|
+
* 不通过 → 当前工具结果立即返回拒绝原因,agent 可修正后再次提交。 */
|
|
136
|
+
validateCompletion?: (result: Record<string, unknown>) => CompletionValidationResult | Promise<CompletionValidationResult>;
|
|
137
|
+
}
|
|
138
|
+
export type JsonSchema = Readonly<Record<string, unknown>>;
|
|
139
|
+
/** Agent 对 __graph_complete__ 的一次候选提交;通过检查前不等于 NodeCompletion。 */
|
|
140
|
+
export interface CompletionSubmission {
|
|
141
|
+
result: Record<string, unknown>;
|
|
142
|
+
}
|
|
143
|
+
export type CompletionValidationStage = "outputSchema" | "agent-run" | "node" | "route" | "mechanism" | "agent-choice";
|
|
144
|
+
export type CompletionSubmissionDecision = {
|
|
145
|
+
readonly decision: "accepted";
|
|
146
|
+
readonly completionStatus: NodeCompletion["status"];
|
|
147
|
+
readonly validation: "passed" | "skipped";
|
|
148
|
+
readonly schemaFingerprint?: string;
|
|
149
|
+
} | {
|
|
150
|
+
readonly decision: "rejected";
|
|
151
|
+
readonly reason: string;
|
|
152
|
+
readonly validatorStage?: CompletionValidationStage;
|
|
153
|
+
readonly schemaFingerprint?: string;
|
|
154
|
+
} | {
|
|
155
|
+
readonly decision: "failed";
|
|
156
|
+
readonly scope: "node" | "graph";
|
|
157
|
+
readonly reason: string;
|
|
158
|
+
readonly validatorStage?: CompletionValidationStage;
|
|
159
|
+
readonly schemaFingerprint?: string;
|
|
160
|
+
};
|
|
161
|
+
export type CompletionValidationResult = {
|
|
162
|
+
isValid: true;
|
|
163
|
+
} | {
|
|
164
|
+
isValid: false;
|
|
165
|
+
reason: string;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* 可运行工作阶段。
|
|
169
|
+
*
|
|
170
|
+
* 普通节点(kind: "code")和复合节点(kind: "graph")互斥:
|
|
171
|
+
* code → 提供 execute
|
|
172
|
+
* graph → 提供 graph(子图调用),execute 由 Runtime 自动委托给子图
|
|
173
|
+
*
|
|
174
|
+
* code 节点的执行配置声明在 Node 自身:
|
|
175
|
+
* - subGoal 本阶段的子目标(特殊的"构造函数"机制,必须存在)
|
|
176
|
+
* - skill 关联的 skill 名称。节点进入时,对应 SKILL.md 的完整内容
|
|
177
|
+
* 通过 sendUserMessage 追加到消息流中(不动 system prompt),
|
|
178
|
+
* 辅助 agent 完成本阶段任务。
|
|
179
|
+
* - tools 本阶段工具白名单
|
|
180
|
+
* - mechanisms 局部横切机制,叠加在全局机制之上
|
|
181
|
+
*
|
|
182
|
+
* graph 节点声明被调用图及调用边界。缺省 call 创建新的 AgentInstance:
|
|
183
|
+
* - globalGoal 来自子图 Graph.goal
|
|
184
|
+
* - background 来自调用点传入的 NodeInput.data
|
|
185
|
+
* - frames 从空数组开始,父图 frames 对子图不可见
|
|
186
|
+
* - 子图 END 后归约为父图 graph 节点的一次 NodeCompletion
|
|
187
|
+
* (即子图 END 边的 frame.result 成为该节点的 NodeCompletion.result)
|
|
188
|
+
*
|
|
189
|
+
* compose 在父 Instance 上建立临时帧段,退出时必须归约为当前 graph node 的
|
|
190
|
+
* completion;delegate 需要独立 GraphExecutionHost,未配置 createDelegateHost
|
|
191
|
+
* 时会在校验阶段明确拒绝,绝不静默按 call 执行。fold 只对 compose 合法。
|
|
192
|
+
*/
|
|
193
|
+
export type Node = {
|
|
194
|
+
kind: "code";
|
|
195
|
+
id: string;
|
|
196
|
+
subGoal: string;
|
|
197
|
+
skill?: string;
|
|
198
|
+
tools?: string[];
|
|
199
|
+
mechanisms?: Mechanism[];
|
|
200
|
+
execute(instance: AgentInstance, input: NodeInput, ctx: NodeContext): Promise<NodeCompletion>;
|
|
201
|
+
/** 可选:验证 __graph_complete__ 的 result。不通过则驳回让 agent 重试 */
|
|
202
|
+
validateCompletion?: AgentRunRequest["validateCompletion"];
|
|
203
|
+
} | {
|
|
204
|
+
kind: "graph";
|
|
205
|
+
id: string;
|
|
206
|
+
subGoal: string;
|
|
207
|
+
graph: Graph;
|
|
208
|
+
/** 图调用边界。缺省 `call`,保持当前子图隔离语义。 */
|
|
209
|
+
boundary?: GraphInvocationBoundary;
|
|
210
|
+
/** compose 边界的帧段归约策略。非 compose 边界上配置 fold 在校验期报错。 */
|
|
211
|
+
fold?: ComposeFrameFolder;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Mechanism 运行时上下文。onNodeEnter 通过它拿到 pi、节点、入参与实例状态,
|
|
215
|
+
* 并可通过与当前 NodeScope 绑定的安全能力追加上下文和注册清理动作。
|
|
216
|
+
*
|
|
217
|
+
* pi — 全部 pi 能力(注册原生事件、改工具集、发消息等)
|
|
218
|
+
* instance — 当前 AgentInstance(可写 instance.scratch)
|
|
219
|
+
* node — 当前节点
|
|
220
|
+
* input — 代码侧一次性入参
|
|
221
|
+
* scope — 当前 mechanism invocation 的作用域、取消信号和 cleanup。
|
|
222
|
+
* context.append — 向 agent 消息流追加文本或 SDK 内容块(append-only,不触发 turn)。
|
|
223
|
+
* appendContext — context.append 的兼容别名。
|
|
224
|
+
*
|
|
225
|
+
* context.append/appendContext 是 SDK 托管的安全通道:
|
|
226
|
+
* · 仅当创建它的 NodeScope 仍为当前活动 scope 时写入;失效后返回 false。
|
|
227
|
+
* · 遵循原则 7「追加不注入」:不改 system prompt,只在消息流侧追加。
|
|
228
|
+
* ctx.pi 保留完整 ExtensionAPI,是非托管逃生口;通过它产生的监听、消息和
|
|
229
|
+
* 后台任务不自动获得 NodeScope 隔离、取消或 cleanup 保证。
|
|
230
|
+
*/
|
|
231
|
+
export interface MechanismScope {
|
|
232
|
+
readonly scopeId: string;
|
|
233
|
+
readonly visit: number;
|
|
234
|
+
readonly signal: AbortSignal;
|
|
235
|
+
isActive(): boolean;
|
|
236
|
+
onCleanup(cleanup: () => void | Promise<void>): void;
|
|
237
|
+
}
|
|
238
|
+
export type MechanismEventView<T> = T extends (...args: any[]) => any ? T : T extends readonly (infer U)[] ? readonly MechanismEventView<U>[] : T extends object ? {
|
|
239
|
+
readonly [K in keyof T]: MechanismEventView<T[K]>;
|
|
240
|
+
} : T;
|
|
241
|
+
export type MechanismAgentRunId = number;
|
|
242
|
+
export type MechanismToolResultEvent = MechanismEventView<ToolResultEvent> & {
|
|
243
|
+
readonly agentRunId: MechanismAgentRunId | null;
|
|
244
|
+
readonly truncated: boolean;
|
|
245
|
+
};
|
|
246
|
+
export type MechanismTurnStartEvent = MechanismEventView<TurnStartEvent> & {
|
|
247
|
+
readonly agentRunId: MechanismAgentRunId | null;
|
|
248
|
+
};
|
|
249
|
+
export type MechanismTurnEndEvent = MechanismEventView<TurnEndEvent> & {
|
|
250
|
+
readonly agentRunId: MechanismAgentRunId | null;
|
|
251
|
+
};
|
|
252
|
+
export type MechanismToolStartEvent = Readonly<{
|
|
253
|
+
type: "tool_execution_start";
|
|
254
|
+
toolCallId: string;
|
|
255
|
+
toolName: string;
|
|
256
|
+
args: unknown;
|
|
257
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
258
|
+
}>;
|
|
259
|
+
export type MechanismToolCallEvent = MechanismEventView<ToolCallEvent> & {
|
|
260
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
261
|
+
};
|
|
262
|
+
export interface MechanismEventSubscription {
|
|
263
|
+
readonly disposed: boolean;
|
|
264
|
+
dispose(): void;
|
|
265
|
+
}
|
|
266
|
+
export interface MechanismEvents {
|
|
267
|
+
onToolResult(handler: (event: MechanismToolResultEvent) => void | Promise<void>): MechanismEventSubscription;
|
|
268
|
+
onTurnStart(handler: (event: MechanismTurnStartEvent) => void | Promise<void>): MechanismEventSubscription;
|
|
269
|
+
onTurnEnd(handler: (event: MechanismTurnEndEvent) => void | Promise<void>): MechanismEventSubscription;
|
|
270
|
+
}
|
|
271
|
+
export interface MechanismExecRunOptions {
|
|
272
|
+
/** 默认使用 Extension 配置值;必须是正数。 */
|
|
273
|
+
timeoutMs?: number;
|
|
274
|
+
/** 默认使用受控根目录;除非 Extension 显式放行,否则不能逃出该目录。 */
|
|
275
|
+
cwd?: string;
|
|
276
|
+
/** stdout 与 stderr 各自的 UTF-8 字节上限。 */
|
|
277
|
+
maxOutputBytes?: number;
|
|
278
|
+
}
|
|
279
|
+
export interface MechanismExecResult {
|
|
280
|
+
readonly stdout: string;
|
|
281
|
+
readonly stderr: string;
|
|
282
|
+
readonly code: number;
|
|
283
|
+
readonly killed: boolean;
|
|
284
|
+
readonly stdoutTruncated: boolean;
|
|
285
|
+
readonly stderrTruncated: boolean;
|
|
286
|
+
}
|
|
287
|
+
export interface MechanismExec {
|
|
288
|
+
run(command: string, args?: readonly string[], options?: MechanismExecRunOptions): Promise<MechanismExecResult>;
|
|
289
|
+
}
|
|
290
|
+
export type MechanismDecisionKind = "tool-allow" | "tool-deny" | "tool-patch" | "tool-result-keep" | "tool-result-replace";
|
|
291
|
+
export interface MechanismDecisionTraceEntry {
|
|
292
|
+
readonly timestamp: number;
|
|
293
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
294
|
+
readonly mechanismName: string;
|
|
295
|
+
readonly toolName: string;
|
|
296
|
+
readonly toolCallId: string;
|
|
297
|
+
readonly decision: MechanismDecisionKind;
|
|
298
|
+
readonly reason?: string;
|
|
299
|
+
}
|
|
300
|
+
export interface MechanismDecisionLog {
|
|
301
|
+
list(): readonly MechanismDecisionTraceEntry[];
|
|
302
|
+
}
|
|
303
|
+
export interface MechanismContext<TState = Record<string, unknown>> {
|
|
304
|
+
pi: ExtensionAPI;
|
|
305
|
+
instance: AgentInstance;
|
|
306
|
+
node: Node;
|
|
307
|
+
input: NodeInput;
|
|
308
|
+
scope: MechanismScope;
|
|
309
|
+
events: MechanismEvents;
|
|
310
|
+
exec: MechanismExec;
|
|
311
|
+
decisions: MechanismDecisionLog;
|
|
312
|
+
state: TState;
|
|
313
|
+
context: MechanismContextAppender;
|
|
314
|
+
/** @deprecated 兼容别名;新代码优先使用 ctx.context.append。 */
|
|
315
|
+
appendContext(content: MechanismContextContent): boolean;
|
|
316
|
+
}
|
|
317
|
+
export type MechanismContextContentBlock = {
|
|
318
|
+
readonly type: "text";
|
|
319
|
+
readonly text: string;
|
|
320
|
+
} | {
|
|
321
|
+
readonly type: "image";
|
|
322
|
+
readonly data: string;
|
|
323
|
+
readonly mimeType: string;
|
|
324
|
+
};
|
|
325
|
+
export type MechanismContextContent = string | readonly MechanismContextContentBlock[];
|
|
326
|
+
export interface MechanismContextAppender {
|
|
327
|
+
append(content: MechanismContextContent): boolean;
|
|
328
|
+
}
|
|
329
|
+
export type MechanismFailurePolicy = "continue" | "fail-node" | "fail-graph";
|
|
330
|
+
export interface MechanismCompletionView {
|
|
331
|
+
readonly nodeId: string;
|
|
332
|
+
readonly status: NodeCompletion["status"];
|
|
333
|
+
readonly result: Readonly<Record<string, unknown>>;
|
|
334
|
+
readonly verifiedResult?: Readonly<{
|
|
335
|
+
checks: readonly MechanismVerifiedResultEntry[];
|
|
336
|
+
}>;
|
|
337
|
+
}
|
|
338
|
+
export interface MechanismErrorView {
|
|
339
|
+
readonly name: string;
|
|
340
|
+
readonly message: string;
|
|
341
|
+
readonly stack?: string;
|
|
342
|
+
}
|
|
343
|
+
export interface MechanismExitContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
344
|
+
readonly completion: Readonly<MechanismCompletionView>;
|
|
345
|
+
}
|
|
346
|
+
export interface MechanismErrorContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
347
|
+
readonly error: Readonly<MechanismErrorView>;
|
|
348
|
+
}
|
|
349
|
+
export interface MechanismAgentRunRequestView {
|
|
350
|
+
readonly prompt: string;
|
|
351
|
+
readonly skill?: string;
|
|
352
|
+
readonly outputSchema?: JsonSchema;
|
|
353
|
+
}
|
|
354
|
+
export interface MechanismAgentRunContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
355
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
356
|
+
readonly request: Readonly<MechanismAgentRunRequestView>;
|
|
357
|
+
}
|
|
358
|
+
export interface MechanismTurnStartContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
359
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
360
|
+
readonly event: MechanismTurnStartEvent;
|
|
361
|
+
}
|
|
362
|
+
export interface MechanismTurnEndContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
363
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
364
|
+
readonly event: MechanismTurnEndEvent;
|
|
365
|
+
}
|
|
366
|
+
export interface MechanismToolStartContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
367
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
368
|
+
readonly event: MechanismToolStartEvent;
|
|
369
|
+
}
|
|
370
|
+
export interface MechanismToolResultContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
371
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
372
|
+
readonly event: MechanismToolResultEvent;
|
|
373
|
+
}
|
|
374
|
+
export interface MechanismToolCallContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
375
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
376
|
+
readonly event: MechanismToolCallEvent;
|
|
377
|
+
}
|
|
378
|
+
export type ToolCallDecision = {
|
|
379
|
+
readonly action: "allow";
|
|
380
|
+
} | {
|
|
381
|
+
readonly action: "deny";
|
|
382
|
+
readonly reason: string;
|
|
383
|
+
} | {
|
|
384
|
+
readonly action: "patch";
|
|
385
|
+
readonly input: Readonly<Record<string, unknown>>;
|
|
386
|
+
};
|
|
387
|
+
export type ToolResultContent = {
|
|
388
|
+
readonly type: "text";
|
|
389
|
+
readonly text: string;
|
|
390
|
+
} | {
|
|
391
|
+
readonly type: "image";
|
|
392
|
+
readonly data: string;
|
|
393
|
+
readonly mimeType: string;
|
|
394
|
+
};
|
|
395
|
+
export type ToolResultDecision = {
|
|
396
|
+
readonly action: "keep";
|
|
397
|
+
} | {
|
|
398
|
+
readonly action: "replace";
|
|
399
|
+
readonly content?: readonly ToolResultContent[];
|
|
400
|
+
readonly isError?: boolean;
|
|
401
|
+
};
|
|
402
|
+
export interface MechanismVerifiedResultEntry {
|
|
403
|
+
readonly mechanismName: string;
|
|
404
|
+
readonly result: Readonly<Record<string, unknown>>;
|
|
405
|
+
}
|
|
406
|
+
export type CompletionDecision = {
|
|
407
|
+
readonly action: "allow";
|
|
408
|
+
readonly verifiedResult?: Readonly<Record<string, unknown>>;
|
|
409
|
+
} | {
|
|
410
|
+
readonly action: "reject";
|
|
411
|
+
readonly reason: string;
|
|
412
|
+
} | {
|
|
413
|
+
readonly action: "fail-node";
|
|
414
|
+
readonly reason: string;
|
|
415
|
+
} | {
|
|
416
|
+
readonly action: "fail-graph";
|
|
417
|
+
readonly reason: string;
|
|
418
|
+
};
|
|
419
|
+
export interface MechanismCompletionContext<TState = Record<string, unknown>> extends MechanismContext<TState> {
|
|
420
|
+
readonly agentRunId: MechanismAgentRunId;
|
|
421
|
+
readonly completion: Readonly<MechanismCompletionView>;
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* 横切机制。框架在节点进入后、execute 之前自动分派 onNodeEnter。
|
|
425
|
+
*
|
|
426
|
+
* ctx.scope 提供与本次 node visit 绑定的 signal、active 检查和 LIFO cleanup。
|
|
427
|
+
* 直接使用 ctx.pi.on() 仍然允许,但 pi 没有 off,属于非托管高级用法:监听器
|
|
428
|
+
* 会持续到 Session 结束,开发者必须自行限制回调和处理副作用。
|
|
429
|
+
*
|
|
430
|
+
* 全局机制(Graph.mechanisms → AgentInstance.mechanisms)跨节点持续生效;
|
|
431
|
+
* 局部机制(Node.mechanisms)仅在本阶段叠加到全局之上。
|
|
432
|
+
*
|
|
433
|
+
* SDK 托管的产出通道:
|
|
434
|
+
* · ctx.instance.scratch —— 代码侧横切工作状态(见 AgentInstance.scratch)
|
|
435
|
+
* · ctx.context.append() —— 向 agent 消息流追加上下文(appendContext 为兼容别名)
|
|
436
|
+
* ctx.pi 提供完整非托管定制能力。不得直接写 frames/background,也不得依赖
|
|
437
|
+
* 闭包/模块变量传递跨节点业务状态。
|
|
438
|
+
* onNodeEnter 抛错统一记日志后继续(不中止节点)。
|
|
439
|
+
*/
|
|
440
|
+
export interface Mechanism<TState = Record<string, unknown>> {
|
|
441
|
+
name: string;
|
|
442
|
+
/** hook 抛错后的控制策略。默认 continue,保持向后兼容。 */
|
|
443
|
+
failurePolicy?: MechanismFailurePolicy;
|
|
444
|
+
/** 当前 AgentInstance 中按 mechanism 对象身份懒初始化一次。 */
|
|
445
|
+
createState?(): TState;
|
|
446
|
+
onNodeEnter?(ctx: MechanismContext<TState>): void | Promise<void>;
|
|
447
|
+
/** 每次 runAgent 发送 prompt 前调用;只读观察,不直接改写请求。 */
|
|
448
|
+
beforeAgentRun?(ctx: MechanismAgentRunContext<TState>): void | Promise<void>;
|
|
449
|
+
onTurnStart?(ctx: MechanismTurnStartContext<TState>): void | Promise<void>;
|
|
450
|
+
onTurnEnd?(ctx: MechanismTurnEndContext<TState>): void | Promise<void>;
|
|
451
|
+
/** 工具真正开始执行后的只读观察点。 */
|
|
452
|
+
onToolStart?(ctx: MechanismToolStartContext<TState>): void | Promise<void>;
|
|
453
|
+
/** 工具结果完成有限变换后收到只读、带预算的最终快照。 */
|
|
454
|
+
onToolResult?(ctx: MechanismToolResultContext<TState>): void | Promise<void>;
|
|
455
|
+
beforeToolCall?(ctx: MechanismToolCallContext<TState>): ToolCallDecision | void | Promise<ToolCallDecision | void>;
|
|
456
|
+
afterToolResult?(ctx: MechanismToolResultContext<TState>): ToolResultDecision | void | Promise<ToolResultDecision | void>;
|
|
457
|
+
validateCompletion?(ctx: MechanismCompletionContext<TState>): CompletionDecision | Promise<CompletionDecision>;
|
|
458
|
+
/** 节点主体已产出 completion、Router/Edge 尚未处理时调用。 */
|
|
459
|
+
onNodeExit?(ctx: MechanismExitContext<TState>): void | Promise<void>;
|
|
460
|
+
/** 当前 node visit 任意阶段抛错时调用;只观察原始错误,不能替换它。 */
|
|
461
|
+
onNodeError?(ctx: MechanismErrorContext<TState>): void | Promise<void>;
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* 边的迁移产出。
|
|
465
|
+
*
|
|
466
|
+
* 边只处置栈顶层(刚刚完成的节点):
|
|
467
|
+
* - frame 将该节点的 Completion 折叠为一帧,push 到栈顶
|
|
468
|
+
* - input 可选,作为下一节点的一次性入参
|
|
469
|
+
*
|
|
470
|
+
* 当边的 to 为 END:frame 仍折叠进历史,且 frame.result 同时被 Runtime
|
|
471
|
+
* 取作本图的返回值(见 END 注释);input 此时无后继节点,应省略。
|
|
472
|
+
*/
|
|
473
|
+
export interface MigrationResult {
|
|
474
|
+
/** 完全由开发者定义的模型工作记忆;SDK 不预设其字段。 */
|
|
475
|
+
frame: ContextFrame;
|
|
476
|
+
/** END 边可显式声明图返回。省略时兼容读取 frame.status/result,再回退到 NodeCompletion。 */
|
|
477
|
+
output?: Pick<NodeCompletion, "status" | "result">;
|
|
478
|
+
input?: Record<string, unknown>;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* 状态迁移的承载者。
|
|
482
|
+
*
|
|
483
|
+
* Edge 独占三件事:
|
|
484
|
+
* 1. guard — 什么时候走这条边(只看 NodeCompletion)
|
|
485
|
+
* 2. migrate — 栈顶层怎么折叠进历史,并可生成下一节点入参
|
|
486
|
+
* 3. to — 指向哪个节点(或 END 终止) //开发者注释:边不应该去管理from和to应该交给rout去做,node,edge应该被独立定义,然后用rout串起来,最后输入给图的只有rout和entry,保持代码高复用
|
|
487
|
+
*
|
|
488
|
+
* description 是边的可读描述,由开发者定义。
|
|
489
|
+
* 当路由策略为 agent-choice 时 description 必填——
|
|
490
|
+
* 它会被渲染进 CURRENT 段,供 agent 判断"此时该走哪条边"。
|
|
491
|
+
* 其他路由策略下 description 可选,仅作文档用途。
|
|
492
|
+
*/
|
|
493
|
+
export interface Edge {
|
|
494
|
+
id: string;
|
|
495
|
+
from: string;
|
|
496
|
+
to: string | typeof END;
|
|
497
|
+
priority: number;
|
|
498
|
+
/** 边的可读描述。agent-choice 路由下必填,渲染给 agent 辅助决策。 */
|
|
499
|
+
description?: string;
|
|
500
|
+
guard(completion: NodeCompletion): boolean;
|
|
501
|
+
migrate(instance: AgentInstance, completion: NodeCompletion): MigrationResult;
|
|
502
|
+
}
|
|
503
|
+
export type RouterFn = (edges: Edge[], completion: NodeCompletion, instance: AgentInstance) => Edge | null | Promise<Edge | null>;
|
|
504
|
+
export type RouterStrategy = {
|
|
505
|
+
kind: "priority-first";
|
|
506
|
+
} | {
|
|
507
|
+
kind: "agent-choice";
|
|
508
|
+
} | {
|
|
509
|
+
kind: "first-match";
|
|
510
|
+
} | {
|
|
511
|
+
kind: "custom";
|
|
512
|
+
fn: RouterFn;
|
|
513
|
+
};
|
|
514
|
+
export interface NodeRouting {
|
|
515
|
+
nodeId: string;
|
|
516
|
+
edges: Edge[];
|
|
517
|
+
router: RouterStrategy;
|
|
518
|
+
/** agent-choice 路由下,从 completion.result 读取边选择的字段名。默认 "chosen_edge_id"。 */
|
|
519
|
+
agentChoiceField?: string;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* 图的对外调用契约。让同一张图同时可被:
|
|
523
|
+
* · 用户像 skill 调用 → Runtime 注册成 /name 命令
|
|
524
|
+
* · agent 像 tool 调用 → Runtime 注册成一个 LLM 工具
|
|
525
|
+
*
|
|
526
|
+
* 二者共享 name / description / inputSchema。
|
|
527
|
+
* inputSchema 声明工具入参结构(agent 调用必需);
|
|
528
|
+
* parseArgs 将命令调用的裸文本 args 解析成 inputSchema 的形状。
|
|
529
|
+
*/
|
|
530
|
+
export interface GraphInvocation {
|
|
531
|
+
name: string;
|
|
532
|
+
description: string;
|
|
533
|
+
inputSchema: Record<string, unknown>;
|
|
534
|
+
/** 命令调用:把裸文本 args 解析成 inputSchema 的形状。默认 { args } */
|
|
535
|
+
parseArgs?(args: string): Record<string, unknown>;
|
|
536
|
+
/** 自定义 graph tool 返回给模型的文本;details 始终保留原始 GraphRunResult。 */
|
|
537
|
+
formatToolResult?(result: Readonly<GraphRunResult>): string;
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* 一次图调用的运行时信号。三种来源,Runtime 统一归约为 background:
|
|
541
|
+
*
|
|
542
|
+
* command — 用户 /name,parseArgs(args) → background
|
|
543
|
+
* tool — agent 工具调用,schema 校验过的 params 即 background
|
|
544
|
+
* subgraph — 上游节点(父图中 kind="graph" 的 Node)的 completion.result 即 background
|
|
545
|
+
*
|
|
546
|
+
* 三种来源统一后,Entry.guard 只需关注 background 中的内容,
|
|
547
|
+
* 无需关心来源是用户还是 agent。
|
|
548
|
+
*/
|
|
549
|
+
export type Trigger = {
|
|
550
|
+
source: "command";
|
|
551
|
+
args: string;
|
|
552
|
+
} | {
|
|
553
|
+
source: "tool";
|
|
554
|
+
params: Record<string, unknown>;
|
|
555
|
+
} | {
|
|
556
|
+
source: "subgraph";
|
|
557
|
+
background: Record<string, unknown>;
|
|
558
|
+
};
|
|
559
|
+
/**
|
|
560
|
+
* 图的入口声明。
|
|
561
|
+
*
|
|
562
|
+
* Runtime 将 Trigger 归一为 background 后,遍历 entries 调用 guard。
|
|
563
|
+
* guard 只根据 background 的内容判断是否匹配,不关心 Trigger 的来源。
|
|
564
|
+
*/
|
|
565
|
+
export interface Entry {
|
|
566
|
+
id: string;
|
|
567
|
+
guard(background: Record<string, unknown>): boolean;
|
|
568
|
+
startNodeId: string;
|
|
569
|
+
/** 可选:构造第一个节点的 NodeInput.data。默认 background 原样传入。 */
|
|
570
|
+
mapInput?(background: Record<string, unknown>): Record<string, unknown>;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* 回路图。
|
|
574
|
+
*
|
|
575
|
+
* invocation? 可选。有 → 可被用户 /agent 直接调用(注册命令 + 工具);
|
|
576
|
+
* 无 → 纯内部子图,只能被别的节点引用。天然区分
|
|
577
|
+
* "库的公开 API"和"内部实现"。
|
|
578
|
+
*
|
|
579
|
+
* entries 声明入口;guard 只根据 background 内容判断,不关心来源。
|
|
580
|
+
*
|
|
581
|
+
* 子图组合:kind="graph" 的 Node 引用另一个 Graph,形成隔离栈调用。
|
|
582
|
+
* 顶层图调用 = 没有调用者的子图调用。
|
|
583
|
+
*/
|
|
584
|
+
export interface Graph {
|
|
585
|
+
id: string;
|
|
586
|
+
goal: string;
|
|
587
|
+
invocation?: GraphInvocation;
|
|
588
|
+
entries: Entry[];
|
|
589
|
+
nodes: Record<string, Node>;
|
|
590
|
+
routing: Record<string, NodeRouting>;
|
|
591
|
+
/** 全局横切机制。Runtime 压帧时赋给 AgentInstance.mechanisms,跨节点持续生效。 */
|
|
592
|
+
mechanisms?: Mechanism[];
|
|
593
|
+
}
|
package/dist/type.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Loop Graph SDK — 核心类型定义
|
|
3
|
+
// ============================================================
|
|
4
|
+
//
|
|
5
|
+
// 栈式子图编排
|
|
6
|
+
//
|
|
7
|
+
// AgentInstance 持有一个有序逻辑帧栈(frames),节点离开时由边折叠;
|
|
8
|
+
// compose 以有界 frame segment 实现结构化生长与归约。
|
|
9
|
+
//
|
|
10
|
+
// 子图调用是一等公民:Node 可以引用另一个 Graph 作为其实现。
|
|
11
|
+
// graph node 缺省使用 call:Runtime 为子图创建新的 AgentInstance;
|
|
12
|
+
// compose 已可执行;delegate 保留在类型协议中,待独立 host 接线。
|
|
13
|
+
//
|
|
14
|
+
// ============================================================
|
|
15
|
+
// ── 终止标记 ──
|
|
16
|
+
/**
|
|
17
|
+
* 图的终止标记,也是图的「返回」出口。
|
|
18
|
+
*
|
|
19
|
+
* 当一条边的 to 指向 END,Runtime 弹出当前图的栈帧,
|
|
20
|
+
* 并将该边 migrate 产出的 output 作为本图的返回值:
|
|
21
|
+
* · 子图调用 → 成为父图 kind="graph" 节点的 NodeCompletion.result
|
|
22
|
+
* · tool 调用 → 成为返回给 agent 的工具结果
|
|
23
|
+
* · 顶层调用 → 成为整次运行的最终产出
|
|
24
|
+
*
|
|
25
|
+
* 向后兼容:未声明 output 时依次回退到 frame.status/result、completion。
|
|
26
|
+
*
|
|
27
|
+
* END 边的 migrate 承担双重身份——既自由定义最后一层工作记忆,
|
|
28
|
+
* 又通过 output 声明「这张图对外交付什么」。
|
|
29
|
+
*/
|
|
30
|
+
export const END = Symbol("graph.end");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Graph, GraphInvocationBoundary } from "./type.js";
|
|
2
|
+
import type { Graph as CoreGraph } from "./core/graph.js";
|
|
3
|
+
export interface GraphValidationIssue {
|
|
4
|
+
code: "NO_ENTRY" | "ENTRY_TARGET_MISSING" | "ROUTING_NODE_MISSING" | "EDGE_FROM_MISMATCH" | "EDGE_TARGET_MISSING" | "NODE_ROUTING_MISSING" | "DUPLICATE_TOOL_IN_NODE" | "TOOL_NOT_REGISTERED" | "AGENT_CHOICE_EDGE_MISSING_DESCRIPTION" | "INVALID_BOUNDARY_FOLD" | "GRAPH_REFERENCE_CYCLE" | "UNSUPPORTED_GRAPH_BOUNDARY" | "DELEGATE_HOST_UNAVAILABLE";
|
|
5
|
+
message: string;
|
|
6
|
+
path: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GraphValidationOptions {
|
|
9
|
+
/** 当前执行载体已实现的 graph-node 边界。省略时只做结构校验。 */
|
|
10
|
+
supportedBoundaries?: readonly GraphInvocationBoundary[];
|
|
11
|
+
/** 当前注册/执行环境是否声明了 delegate host。 */
|
|
12
|
+
delegateHostAvailable?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function validateGraph(graph: Graph | CoreGraph, options?: GraphValidationOptions): GraphValidationIssue[];
|
|
15
|
+
export declare function assertValidGraph(graph: Graph | CoreGraph, options?: GraphValidationOptions): void;
|
|
16
|
+
/**
|
|
17
|
+
* 校验图中所有节点的工具配置。
|
|
18
|
+
*
|
|
19
|
+
* - 同一节点 tools 数组内有重复名 → 报错
|
|
20
|
+
* - 如果提供 registeredNames,检查所有引用的工具是否已注册 → 报错
|
|
21
|
+
*
|
|
22
|
+
* defaultTools 与 node.tools 之间的重叠不做报错(那是故意注入),
|
|
23
|
+
* 在 resolveNodeTools 中去重即可。
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateGraphTools(graph: Graph, defaultTools: string[], registeredNames?: Set<string>, resolveTools?: (nodeId: string, nodeTools: readonly string[]) => readonly string[]): GraphValidationIssue[];
|