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
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type { ContextFrame, Node } from "../type.js";
|
|
2
|
+
import type { NodeScopeDescriptor } from "../runtime.js";
|
|
3
|
+
export interface EdgeChoice {
|
|
4
|
+
id: string;
|
|
5
|
+
description: string;
|
|
6
|
+
priority: number;
|
|
7
|
+
target: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ProjectionInput {
|
|
10
|
+
messages: MessageEntry[];
|
|
11
|
+
frames: ContextFrame[];
|
|
12
|
+
currentNode: Node | null;
|
|
13
|
+
activeScope?: NodeScopeDescriptor | null;
|
|
14
|
+
/** agent-choice 路由下可供 agent 选择的边列表,渲染在 CURRENT 段 */
|
|
15
|
+
availableEdges?: EdgeChoice[];
|
|
16
|
+
/** 自定义帧折叠后的 COMPLETED 段内容格式。
|
|
17
|
+
* 接收所有已完成帧,返回完整文本注入上下文。
|
|
18
|
+
* 返回 null 则跳过 COMPLETED 段(不折叠)。
|
|
19
|
+
* 默认:保持当前 JSON 格式(向后兼容)。 */
|
|
20
|
+
frameFormatter?: (frames: ContextFrame[]) => string | null;
|
|
21
|
+
/** 活动图已经历 compaction;原生 summary 是此前上下文的权威替代。 */
|
|
22
|
+
compactionActive?: boolean;
|
|
23
|
+
/** node-enter 时已冻结的 SDK 合成上下文。仅在活动 scope 锚点缺失时恢复,
|
|
24
|
+
* 不包含 live ReAct,也不接管 GraphCallScope/compaction 清洗。 */
|
|
25
|
+
renderedContext?: readonly MessageEntry[];
|
|
26
|
+
}
|
|
27
|
+
export interface MessageEntry {
|
|
28
|
+
id?: string;
|
|
29
|
+
role?: string;
|
|
30
|
+
content?: unknown;
|
|
31
|
+
/** pi CustomMessage 的 UI 展示标记。 */
|
|
32
|
+
display?: boolean;
|
|
33
|
+
/** pi compactionSummary / branchSummary 使用 summary 而不是 content。 */
|
|
34
|
+
summary?: string;
|
|
35
|
+
timestamp?: number;
|
|
36
|
+
customType?: string;
|
|
37
|
+
details?: unknown;
|
|
38
|
+
}
|
|
39
|
+
export declare function projectMessages(input: ProjectionInput): MessageEntry[];
|
|
40
|
+
/**
|
|
41
|
+
* 从消息数组中删除已闭合的图调用区段。
|
|
42
|
+
*
|
|
43
|
+
* compose / call 子图运行时在当前 session 的 transcript 中产生内部消息(NodeScope、
|
|
44
|
+
* skill、mechanism、prompt 和 live ReAct)。这些消息由 loop_graph_call_start / end
|
|
45
|
+
* 区段包围。子图结束后调用方不应再看到这些内部消息——它们必须从上下文中删除。
|
|
46
|
+
*
|
|
47
|
+
* 算法:
|
|
48
|
+
* 1. 从 tail 向 head 扫描,为每个 call_end 寻找最近的前驱 call_start(按 callId 匹配)
|
|
49
|
+
* 2. 已闭合区段内的全部消息标记为删除
|
|
50
|
+
* 3. 未闭合的 call_start(图仍在运行中)对应的区段保留
|
|
51
|
+
*
|
|
52
|
+
* 此函数始终执行(无论当前是否有活动图),因为之前图调用的闭合区段需要在后续对话中持续清洗。
|
|
53
|
+
*/
|
|
54
|
+
export declare function stripClosedGraphCalls(messages: MessageEntry[]): MessageEntry[];
|
|
55
|
+
/** 默认帧格式化器:保持向后兼容的 JSON 格式(=== COMPLETED === / === END === 包裹)。 */
|
|
56
|
+
export declare const defaultFrameFormatter: (frames: ContextFrame[]) => string;
|
|
57
|
+
type NodeInfoLike = Pick<Node, "id" | "kind" | "subGoal"> & {
|
|
58
|
+
tools?: readonly string[];
|
|
59
|
+
skill?: string;
|
|
60
|
+
};
|
|
61
|
+
export declare function buildNodeInfoContent(node: NodeInfoLike, availableEdges?: EdgeChoice[]): string;
|
|
62
|
+
export type RenderedContextContentBlock = {
|
|
63
|
+
type: "text";
|
|
64
|
+
text: string;
|
|
65
|
+
} | {
|
|
66
|
+
type: "image";
|
|
67
|
+
data: string;
|
|
68
|
+
mimeType: string;
|
|
69
|
+
};
|
|
70
|
+
export interface RenderedContextMessage {
|
|
71
|
+
content: string | readonly RenderedContextContentBlock[];
|
|
72
|
+
kind?: "current" | "completed" | "skill" | "instruction";
|
|
73
|
+
}
|
|
74
|
+
export interface GraphContextView {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly goal: string;
|
|
77
|
+
}
|
|
78
|
+
export interface NodeContextView {
|
|
79
|
+
readonly id: string;
|
|
80
|
+
readonly kind: Node["kind"];
|
|
81
|
+
readonly subGoal: string;
|
|
82
|
+
readonly skill?: string;
|
|
83
|
+
readonly tools: readonly string[];
|
|
84
|
+
readonly boundary?: import("../type.js").GraphInvocationBoundary;
|
|
85
|
+
readonly childGraphId?: string;
|
|
86
|
+
}
|
|
87
|
+
export interface NodeInputView {
|
|
88
|
+
readonly data: Readonly<Record<string, unknown>>;
|
|
89
|
+
readonly source: Readonly<import("../type.js").NodeInput["source"]>;
|
|
90
|
+
}
|
|
91
|
+
export interface NodeContextRenderInput {
|
|
92
|
+
graph: GraphContextView;
|
|
93
|
+
node: NodeContextView;
|
|
94
|
+
input: NodeInputView;
|
|
95
|
+
/** node-enter 时 Runtime 已选择的 frame 快照。COMPLETED 主投影仍由
|
|
96
|
+
* frameFormatter 管理,避免 compaction 后重复投影旧 frame。 */
|
|
97
|
+
frames: readonly ContextFrame[];
|
|
98
|
+
availableEdges: readonly EdgeChoice[];
|
|
99
|
+
skill: {
|
|
100
|
+
ref: string;
|
|
101
|
+
content: string;
|
|
102
|
+
message: RenderedContextMessage | null;
|
|
103
|
+
showRefInCurrent: boolean;
|
|
104
|
+
} | null;
|
|
105
|
+
completion: {
|
|
106
|
+
toolName: "__graph_complete__";
|
|
107
|
+
statuses: readonly ["ok", "failed", "cancelled"];
|
|
108
|
+
};
|
|
109
|
+
reason: "node-enter";
|
|
110
|
+
}
|
|
111
|
+
export interface RenderedNodeContext {
|
|
112
|
+
/** NodeScope 锚点的模型可见正文。null 表示使用空正文,但安全锚点仍存在。 */
|
|
113
|
+
anchor: RenderedContextMessage | null;
|
|
114
|
+
/** 锚点之后追加的其它 SDK 合成消息。 */
|
|
115
|
+
additional?: readonly RenderedContextMessage[];
|
|
116
|
+
}
|
|
117
|
+
export type NodeContextRenderer = (input: NodeContextRenderInput) => RenderedNodeContext | null;
|
|
118
|
+
/** 兼容 renderer:保持当前 CURRENT 与 skill 消息的正文格式。历史 frames 继续
|
|
119
|
+
* 由 frameFormatter 投影,使 compaction baseline 可以独立推进。 */
|
|
120
|
+
export declare const defaultNodeContextRenderer: NodeContextRenderer;
|
|
121
|
+
export {};
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// 投影 — context 钩子的消息组装(纯函数)
|
|
3
|
+
// ============================================================
|
|
4
|
+
export function projectMessages(input) {
|
|
5
|
+
const { messages, frames, currentNode, activeScope } = input;
|
|
6
|
+
const currentIdx = activeScope ? findLastMatchingScope(messages, activeScope) : -1;
|
|
7
|
+
const result = [];
|
|
8
|
+
const summaryIdx = input.compactionActive ? findLastCompactionSummary(messages) : -1;
|
|
9
|
+
// pi 的 summary + recent messages 是压缩后上下文的权威表达。若活动 scope
|
|
10
|
+
// 仍在保留区,只保留 summary 与该 scope 后内容;若 scope 已被压缩,则在
|
|
11
|
+
// summary 后恢复 CURRENT,并保留所有 recent messages。
|
|
12
|
+
if (summaryIdx >= 0)
|
|
13
|
+
result.push(messages[summaryIdx]);
|
|
14
|
+
// frame 段
|
|
15
|
+
if (frames.length > 0) {
|
|
16
|
+
const fmt = input.frameFormatter ?? defaultFrameFormatter;
|
|
17
|
+
const content = fmt(frames);
|
|
18
|
+
if (content != null) {
|
|
19
|
+
result.push({
|
|
20
|
+
role: "user",
|
|
21
|
+
content,
|
|
22
|
+
timestamp: Date.now(),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (currentIdx >= 0) {
|
|
27
|
+
const includeAnchor = messages[currentIdx]?.customType === "loop_graph_node_scope";
|
|
28
|
+
result.push(...messages.slice(currentIdx + (includeAnchor ? 0 : 1)));
|
|
29
|
+
}
|
|
30
|
+
else if (currentNode) {
|
|
31
|
+
const recovered = input.renderedContext?.length
|
|
32
|
+
? input.renderedContext
|
|
33
|
+
: [buildNodeInfo(currentNode, input.availableEdges)];
|
|
34
|
+
result.push(...recovered);
|
|
35
|
+
if (summaryIdx >= 0) {
|
|
36
|
+
result.push(...messages.slice(summaryIdx + 1).filter((message) => message.customType !== "loop_graph_mechanism" ||
|
|
37
|
+
(activeScope != null && isScopedMechanismMessage(message, activeScope))));
|
|
38
|
+
}
|
|
39
|
+
else if (activeScope) {
|
|
40
|
+
// scope anchor 丢失时只恢复带 SDK 固定 scope 元数据的 mechanism 消息。
|
|
41
|
+
// prompt/live ReAct 没有可证明归属,继续 fail closed。
|
|
42
|
+
result.push(...messages.filter((message) => isScopedMechanismMessage(message, activeScope)));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
function isScopedMechanismMessage(message, activeScope) {
|
|
48
|
+
if (message.customType !== "loop_graph_mechanism")
|
|
49
|
+
return false;
|
|
50
|
+
const details = message.details;
|
|
51
|
+
return details?.protocol === 1 && details.scopeId === activeScope.scopeId;
|
|
52
|
+
}
|
|
53
|
+
// ── GraphCallScope 清洗(Phase 9)─────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* 从消息数组中删除已闭合的图调用区段。
|
|
56
|
+
*
|
|
57
|
+
* compose / call 子图运行时在当前 session 的 transcript 中产生内部消息(NodeScope、
|
|
58
|
+
* skill、mechanism、prompt 和 live ReAct)。这些消息由 loop_graph_call_start / end
|
|
59
|
+
* 区段包围。子图结束后调用方不应再看到这些内部消息——它们必须从上下文中删除。
|
|
60
|
+
*
|
|
61
|
+
* 算法:
|
|
62
|
+
* 1. 从 tail 向 head 扫描,为每个 call_end 寻找最近的前驱 call_start(按 callId 匹配)
|
|
63
|
+
* 2. 已闭合区段内的全部消息标记为删除
|
|
64
|
+
* 3. 未闭合的 call_start(图仍在运行中)对应的区段保留
|
|
65
|
+
*
|
|
66
|
+
* 此函数始终执行(无论当前是否有活动图),因为之前图调用的闭合区段需要在后续对话中持续清洗。
|
|
67
|
+
*/
|
|
68
|
+
export function stripClosedGraphCalls(messages) {
|
|
69
|
+
// 从尾部收集已闭合的区段
|
|
70
|
+
const closedRanges = [];
|
|
71
|
+
const endStack = [];
|
|
72
|
+
// tail → head 单次扫描:遇到 call_end 压栈,遇到匹配的 call_start 弹出并记录区段
|
|
73
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
74
|
+
const m = messages[i];
|
|
75
|
+
if (m.customType === "loop_graph_call_end") {
|
|
76
|
+
const d = m.details;
|
|
77
|
+
if (d?.callId && typeof d.callId === "string") {
|
|
78
|
+
endStack.push({ callId: d.callId, endIdx: i });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
else if (m.customType === "loop_graph_call_start") {
|
|
82
|
+
const d = m.details;
|
|
83
|
+
if (d?.callId && typeof d.callId === "string") {
|
|
84
|
+
// 找最近匹配的 call_end
|
|
85
|
+
for (let j = endStack.length - 1; j >= 0; j--) {
|
|
86
|
+
if (endStack[j].callId === d.callId) {
|
|
87
|
+
closedRanges.push([i, endStack[j].endIdx]);
|
|
88
|
+
endStack.splice(j, 1);
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (closedRanges.length === 0)
|
|
96
|
+
return messages;
|
|
97
|
+
// 构建排除索引集合
|
|
98
|
+
const exclude = new Set();
|
|
99
|
+
for (const [start, end] of closedRanges) {
|
|
100
|
+
for (let i = start; i <= end; i++)
|
|
101
|
+
exclude.add(i);
|
|
102
|
+
}
|
|
103
|
+
return messages.filter((_, i) => !exclude.has(i));
|
|
104
|
+
}
|
|
105
|
+
function findLastMatchingScope(messages, activeScope) {
|
|
106
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
107
|
+
if (isMatchingScope(messages[index], activeScope))
|
|
108
|
+
return index;
|
|
109
|
+
}
|
|
110
|
+
return -1;
|
|
111
|
+
}
|
|
112
|
+
function isMatchingScope(message, activeScope) {
|
|
113
|
+
if (message.customType !== "loop_graph_node_scope")
|
|
114
|
+
return false;
|
|
115
|
+
const details = message.details;
|
|
116
|
+
return details?.protocol === 2 && details.scopeId === activeScope.scopeId;
|
|
117
|
+
}
|
|
118
|
+
/** 默认帧格式化器:保持向后兼容的 JSON 格式(=== COMPLETED === / === END === 包裹)。 */
|
|
119
|
+
export const defaultFrameFormatter = (frames) => `=== COMPLETED ===\n${JSON.stringify(frames)}\n=== END ===`;
|
|
120
|
+
function findLastCompactionSummary(messages) {
|
|
121
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
122
|
+
if (messages[index].role === "compactionSummary")
|
|
123
|
+
return index;
|
|
124
|
+
}
|
|
125
|
+
return -1;
|
|
126
|
+
}
|
|
127
|
+
export function buildNodeInfoContent(node, availableEdges) {
|
|
128
|
+
const lines = ["=== CURRENT ==="];
|
|
129
|
+
lines.push(`nodeId: ${node.id}`);
|
|
130
|
+
lines.push(`subGoal: ${node.subGoal}`);
|
|
131
|
+
if (node.kind === "code") {
|
|
132
|
+
if (node.tools?.length)
|
|
133
|
+
lines.push(`tools: ${node.tools.join(", ")}`);
|
|
134
|
+
if (node.skill)
|
|
135
|
+
lines.push(`skill: ${node.skill}`);
|
|
136
|
+
}
|
|
137
|
+
// agent-choice 路由:渲染可用边列表供 agent 决策
|
|
138
|
+
if (availableEdges && availableEdges.length > 0) {
|
|
139
|
+
lines.push("");
|
|
140
|
+
lines.push("availableEdges(请在 __graph_complete__ 的 result.chosen_edge_id 中选择一条):");
|
|
141
|
+
for (const e of availableEdges) {
|
|
142
|
+
const targetLabel = e.target === "Symbol(graph.end)" ? "END" : (e.target || "?");
|
|
143
|
+
lines.push(` • ${e.id} (priority: ${e.priority}) → ${targetLabel}`);
|
|
144
|
+
lines.push(` ${e.description}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
lines.push("completeWith: __graph_complete__({ status, result })");
|
|
148
|
+
lines.push("=== END ===");
|
|
149
|
+
return lines.join("\n");
|
|
150
|
+
}
|
|
151
|
+
/** 兼容 renderer:保持当前 CURRENT 与 skill 消息的正文格式。历史 frames 继续
|
|
152
|
+
* 由 frameFormatter 投影,使 compaction baseline 可以独立推进。 */
|
|
153
|
+
export const defaultNodeContextRenderer = (input) => {
|
|
154
|
+
const additional = [];
|
|
155
|
+
if (input.skill?.message)
|
|
156
|
+
additional.push(input.skill.message);
|
|
157
|
+
return {
|
|
158
|
+
anchor: {
|
|
159
|
+
kind: "current",
|
|
160
|
+
content: buildNodeInfoContent(input.skill && !input.skill.showRefInCurrent
|
|
161
|
+
? { ...input.node, skill: undefined }
|
|
162
|
+
: input.node, [...input.availableEdges]),
|
|
163
|
+
},
|
|
164
|
+
additional,
|
|
165
|
+
};
|
|
166
|
+
};
|
|
167
|
+
function buildNodeInfo(node, availableEdges) {
|
|
168
|
+
return { role: "user", content: buildNodeInfoContent(node, availableEdges), timestamp: Date.now() };
|
|
169
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { GraphContextView, NodeContextView, NodeInputView, RenderedContextMessage } from "./projection.js";
|
|
2
|
+
export interface SkillLoadContext {
|
|
3
|
+
readonly graph: GraphContextView;
|
|
4
|
+
readonly node: NodeContextView;
|
|
5
|
+
readonly input: NodeInputView;
|
|
6
|
+
readonly basePath: string;
|
|
7
|
+
}
|
|
8
|
+
export type SkillContentProvider = (ref: string, context: SkillLoadContext) => Promise<string | null>;
|
|
9
|
+
export type SkillContentRenderer = (ref: string, content: string, context: SkillLoadContext) => RenderedContextMessage | null;
|
|
10
|
+
export type SkillFailurePolicy = "ignore" | "fail";
|
|
11
|
+
export interface SkillFailurePolicies {
|
|
12
|
+
missing?: SkillFailurePolicy;
|
|
13
|
+
error?: SkillFailurePolicy;
|
|
14
|
+
}
|
|
15
|
+
export declare const defaultSkillContentProvider: SkillContentProvider;
|
|
16
|
+
export declare const defaultSkillContentRenderer: SkillContentRenderer;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export const defaultSkillContentProvider = async (ref, context) => {
|
|
4
|
+
try {
|
|
5
|
+
return await readFile(join(context.basePath, ref, "SKILL.md"), "utf8");
|
|
6
|
+
}
|
|
7
|
+
catch (error) {
|
|
8
|
+
if (error?.code === "ENOENT")
|
|
9
|
+
return null;
|
|
10
|
+
throw error;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
export const defaultSkillContentRenderer = (ref, content) => ({
|
|
14
|
+
kind: "skill",
|
|
15
|
+
content: `[skill: ${ref}]\n\n${content}`,
|
|
16
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Advanced, opt-in runtime and extension points. */
|
|
2
|
+
export { AgentExecutionFailure, GraphRuntime } from "./runtime/graph-runtime.js";
|
|
3
|
+
export type { GraphRuntimeHost, AgentExecutionContext, InvocationBoundary, InvocationOutcome } from "./runtime/graph-runtime.js";
|
|
4
|
+
export { ContextState, materializeProjection } from "./core/context.js";
|
|
5
|
+
export type { ContextProjection } from "./core/graph.js";
|
|
6
|
+
export type { ContextContribution, ContextContributionHandle, ContextLayer, ContextLifetime, ContextRetention, ContextSnapshot, ContextStateOptions, NodeContextMaterialization, } from "./core/context.js";
|
|
7
|
+
export { validateGraph, assertValidGraph, validateGraphTools } from "./validate.js";
|
|
8
|
+
export type { GraphValidationIssue, GraphValidationOptions } from "./validate.js";
|
|
9
|
+
export { selectEdge } from "./router.js";
|
|
10
|
+
export type { ToolResolver, ToolResolverInput } from "./tools-resolve.js";
|
|
11
|
+
export { defaultToolResolver, resolveNodeTools, FRAMEWORK_TOOLS } from "./tools-resolve.js";
|
|
12
|
+
export type { UnsafeToolResolver, UnsafeToolResolverInput } from "./host/tool-catalog.js";
|
|
13
|
+
export { resolveHostBaseline } from "./host/baseline.js";
|
|
14
|
+
export type { HostBaseline } from "./host/baseline.js";
|
|
15
|
+
export type { GraphExecutionHost, IsolatedGraphSession, IsolatedSessionGraphHostOptions } from "./adapter/graph-execution-host.js";
|
|
16
|
+
export { IsolatedSessionGraphHost } from "./adapter/graph-execution-host.js";
|
|
17
|
+
export { ToolCatalog } from "./host/tool-catalog.js";
|
|
18
|
+
export type { ToolImplementation } from "./host/tool-catalog.js";
|
|
19
|
+
export { SkillCatalog } from "./host/skill-catalog.js";
|
|
20
|
+
export type { SkillResolver } from "./host/skill-catalog.js";
|
|
21
|
+
export { GraphCatalog } from "./host/graph-catalog.js";
|
|
22
|
+
export { createJsonlTraceSink } from "./adapter/observability.js";
|
|
23
|
+
export type { AgentRunLifecycleContext, LoopGraphLifecycleEvent, LoopGraphLogger, LoopGraphTraceSink, } from "./adapter/observability.js";
|
|
24
|
+
export { defaultCompletionFeedbackFormatter, } from "./adapter/loop-graph-extension.js";
|
|
25
|
+
export type { CompletionFeedbackFormatter, CompletionFeedbackInput, ContextRendererRegistry, } from "./adapter/loop-graph-extension.js";
|
|
26
|
+
export { DEFAULT_OUTPUT_CONTRACT_MAX_BYTES, OUTPUT_CONTRACT_MESSAGE_TYPE, prepareOutputContract, } from "./adapter/output-contract.js";
|
|
27
|
+
export type { PreparedOutputContract } from "./adapter/output-contract.js";
|
|
28
|
+
export type { DeadRunMessageInput, GraphFailureMessageInput, IncompleteNodeMessageInput, ModelMessageFormatter, } from "./adapter/model-messages.js";
|
|
29
|
+
export { defaultSkillContentProvider, defaultSkillContentRenderer, } from "./adapter/skill-content.js";
|
|
30
|
+
export type { SkillContentProvider, SkillContentRenderer, SkillFailurePolicies, SkillFailurePolicy, SkillLoadContext, } from "./adapter/skill-content.js";
|
|
31
|
+
export { DEFAULT_HOST_BASELINE } from "./host/baseline.js";
|
|
32
|
+
export { DEFAULT_INVOCATION_LIMITS, resolveInvocationLimits } from "./core/limits.js";
|
package/dist/advanced.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Advanced, opt-in runtime and extension points. */
|
|
2
|
+
export { AgentExecutionFailure, GraphRuntime } from "./runtime/graph-runtime.js";
|
|
3
|
+
export { ContextState, materializeProjection } from "./core/context.js";
|
|
4
|
+
export { validateGraph, assertValidGraph, validateGraphTools } from "./validate.js";
|
|
5
|
+
export { selectEdge } from "./router.js";
|
|
6
|
+
export { defaultToolResolver, resolveNodeTools, FRAMEWORK_TOOLS } from "./tools-resolve.js";
|
|
7
|
+
export { resolveHostBaseline } from "./host/baseline.js";
|
|
8
|
+
export { IsolatedSessionGraphHost } from "./adapter/graph-execution-host.js";
|
|
9
|
+
export { ToolCatalog } from "./host/tool-catalog.js";
|
|
10
|
+
export { SkillCatalog } from "./host/skill-catalog.js";
|
|
11
|
+
export { GraphCatalog } from "./host/graph-catalog.js";
|
|
12
|
+
export { createJsonlTraceSink } from "./adapter/observability.js";
|
|
13
|
+
export { defaultCompletionFeedbackFormatter, } from "./adapter/loop-graph-extension.js";
|
|
14
|
+
export { DEFAULT_OUTPUT_CONTRACT_MAX_BYTES, OUTPUT_CONTRACT_MESSAGE_TYPE, prepareOutputContract, } from "./adapter/output-contract.js";
|
|
15
|
+
export { defaultSkillContentProvider, defaultSkillContentRenderer, } from "./adapter/skill-content.js";
|
|
16
|
+
export { DEFAULT_HOST_BASELINE } from "./host/baseline.js";
|
|
17
|
+
export { DEFAULT_INVOCATION_LIMITS, resolveInvocationLimits } from "./core/limits.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
import type { Graph, GraphDefinition, NodeDefinition } from "../core/graph.js";
|
|
3
|
+
export { defineGraph } from "../core/graph.js";
|
|
4
|
+
export declare function defineSingleAgentGraph<TInputSchema extends TSchema, TOutputSchema extends TSchema, TBackground extends import("../core/json.js").JsonValue, TMemory extends import("../core/json.js").JsonValue = import("../core/json.js").JsonValue>(input: {
|
|
5
|
+
id: string;
|
|
6
|
+
version: string;
|
|
7
|
+
goal: string;
|
|
8
|
+
input: TInputSchema;
|
|
9
|
+
output: TOutputSchema;
|
|
10
|
+
context: GraphDefinition<TInputSchema, TOutputSchema, TBackground, TMemory>["context"];
|
|
11
|
+
node: Extract<NodeDefinition, {
|
|
12
|
+
kind: "agent";
|
|
13
|
+
}>;
|
|
14
|
+
tools?: GraphDefinition<TInputSchema, TOutputSchema>["tools"];
|
|
15
|
+
skills?: GraphDefinition<TInputSchema, TOutputSchema>["skills"];
|
|
16
|
+
}): Graph<TInputSchema, TOutputSchema, TBackground, TMemory>;
|
|
17
|
+
export declare function defineLinearGraph<TInputSchema extends TSchema, TOutputSchema extends TSchema, TBackground extends import("../core/json.js").JsonValue, TMemory extends import("../core/json.js").JsonValue = import("../core/json.js").JsonValue>(input: {
|
|
18
|
+
id: string;
|
|
19
|
+
version: string;
|
|
20
|
+
goal: string;
|
|
21
|
+
input: TInputSchema;
|
|
22
|
+
output: TOutputSchema;
|
|
23
|
+
context: GraphDefinition<TInputSchema, TOutputSchema, TBackground, TMemory>["context"];
|
|
24
|
+
nodes: readonly NodeDefinition[];
|
|
25
|
+
tools?: GraphDefinition<TInputSchema, TOutputSchema>["tools"];
|
|
26
|
+
skills?: GraphDefinition<TInputSchema, TOutputSchema>["skills"];
|
|
27
|
+
}): Graph<TInputSchema, TOutputSchema, TBackground, TMemory>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineGraph } from "../core/graph.js";
|
|
2
|
+
export { defineGraph } from "../core/graph.js";
|
|
3
|
+
export function defineSingleAgentGraph(input) {
|
|
4
|
+
const stages = {
|
|
5
|
+
main: {
|
|
6
|
+
node: input.node,
|
|
7
|
+
route: {
|
|
8
|
+
kind: "first-match",
|
|
9
|
+
connections: [{
|
|
10
|
+
id: "finish",
|
|
11
|
+
to: "__graph_finish__",
|
|
12
|
+
transition: { output: ({ completion }) => completion.result },
|
|
13
|
+
}],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
return defineGraph({ ...input, entries: [{ id: "main", to: "main" }], stages });
|
|
18
|
+
}
|
|
19
|
+
export function defineLinearGraph(input) {
|
|
20
|
+
const stages = {};
|
|
21
|
+
input.nodes.forEach((node, index) => {
|
|
22
|
+
const id = node.identity?.name ?? `stage-${index + 1}`;
|
|
23
|
+
const next = input.nodes[index + 1]?.identity?.name ?? (index + 1 < input.nodes.length ? `stage-${index + 2}` : "__graph_finish__");
|
|
24
|
+
stages[id] = {
|
|
25
|
+
node,
|
|
26
|
+
route: {
|
|
27
|
+
kind: "first-match",
|
|
28
|
+
connections: [{
|
|
29
|
+
id: next === "__graph_finish__" ? "finish" : `to-${next}`,
|
|
30
|
+
to: next,
|
|
31
|
+
transition: next === "__graph_finish__"
|
|
32
|
+
? { output: ({ completion }) => completion.result }
|
|
33
|
+
: { map: ({ completion }) => completion.result },
|
|
34
|
+
}],
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
});
|
|
38
|
+
return defineGraph({ ...input, entries: [{ id: "main", to: Object.keys(stages)[0] ?? "" }], stages });
|
|
39
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
import type { AgentNodeDefinition, CodeNodeDefinition, GraphNodeDefinition } from "../core/graph.js";
|
|
3
|
+
import type { JsonValue } from "../core/json.js";
|
|
4
|
+
export declare function agentNode<TInputSchema extends TSchema, TOutputSchema extends TSchema, TFocus extends JsonValue = JsonValue>(input: Omit<AgentNodeDefinition<TInputSchema, TOutputSchema, TFocus>, "kind">): AgentNodeDefinition<TInputSchema, TOutputSchema, TFocus>;
|
|
5
|
+
export declare function codeNode<TInputSchema extends TSchema, TOutputSchema extends TSchema, TFocus extends JsonValue = JsonValue>(input: Omit<CodeNodeDefinition<TInputSchema, TOutputSchema, TFocus>, "kind">): CodeNodeDefinition<TInputSchema, TOutputSchema, TFocus>;
|
|
6
|
+
export declare function graphNode<TInputSchema extends TSchema, TOutputSchema extends TSchema>(input: Omit<GraphNodeDefinition<TInputSchema, TOutputSchema>, "kind" | "boundary"> & {
|
|
7
|
+
boundary?: GraphNodeDefinition["boundary"];
|
|
8
|
+
}): GraphNodeDefinition<TInputSchema, TOutputSchema>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function agentNode(input) {
|
|
2
|
+
return Object.freeze({ ...input, kind: "agent" });
|
|
3
|
+
}
|
|
4
|
+
export function codeNode(input) {
|
|
5
|
+
return Object.freeze({ ...input, kind: "code" });
|
|
6
|
+
}
|
|
7
|
+
export function graphNode(input) {
|
|
8
|
+
return Object.freeze({ ...input, kind: "graph", boundary: input.boundary ?? "call" });
|
|
9
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { SkillRef } from "../core/skill.js";
|
|
2
|
+
export type { SkillRef } from "../core/skill.js";
|
|
3
|
+
export type ToolSet<TNames extends readonly string[] = readonly string[]> = TNames;
|
|
4
|
+
export declare function skillRef(name: string, version?: string, required?: boolean): SkillRef;
|
|
5
|
+
export declare function toolSet<const TNames extends readonly string[]>(...names: TNames): ToolSet<TNames>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export function skillRef(name, version, required = true) {
|
|
2
|
+
if (!name)
|
|
3
|
+
throw new Error("SkillRef requires a name");
|
|
4
|
+
return Object.freeze({ name, version, required });
|
|
5
|
+
}
|
|
6
|
+
export function toolSet(...names) {
|
|
7
|
+
if (new Set(names).size !== names.length)
|
|
8
|
+
throw new Error("ToolSet contains duplicate names");
|
|
9
|
+
return Object.freeze([...names]);
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JsonValue } from "../core/json.js";
|
|
2
|
+
import type { Connection, Entry, Route, Transition } from "../core/graph.js";
|
|
3
|
+
export interface ConnectionDraft<TCompletion extends JsonValue = JsonValue, TFrame extends JsonValue = JsonValue, TInput extends JsonValue = JsonValue> {
|
|
4
|
+
readonly to: Connection["to"];
|
|
5
|
+
readonly transition: Transition<TCompletion, TFrame, TInput>;
|
|
6
|
+
}
|
|
7
|
+
export declare function entry<TInput = JsonValue>(id: string, config: Omit<Entry<TInput>, "id">): Entry<TInput>;
|
|
8
|
+
export declare function defineTransition<TCompletion extends JsonValue = JsonValue, TFrame extends JsonValue = JsonValue, TInput extends JsonValue = JsonValue>(transition: Transition<TCompletion, TFrame, TInput>): Transition<TCompletion, TFrame, TInput>;
|
|
9
|
+
export declare function connect<TCompletion extends JsonValue = JsonValue, TFrame extends JsonValue = JsonValue, TInput extends JsonValue = JsonValue>(to: string, transition?: Transition<TCompletion, TFrame, TInput>): ConnectionDraft<TCompletion, TFrame, TInput>;
|
|
10
|
+
export declare function finish<TCompletion extends JsonValue = JsonValue, TFrame extends JsonValue = JsonValue>(transition?: Transition<TCompletion, TFrame, never>): ConnectionDraft<TCompletion, TFrame, never>;
|
|
11
|
+
export declare function firstMatch(connections: Readonly<Record<string, ConnectionDraft<any, any, any>>>): Route;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function entry(id, config) {
|
|
2
|
+
return Object.freeze({ id, ...config });
|
|
3
|
+
}
|
|
4
|
+
export function defineTransition(transition) {
|
|
5
|
+
return Object.freeze({ ...transition });
|
|
6
|
+
}
|
|
7
|
+
export function connect(to, transition = {}) {
|
|
8
|
+
return Object.freeze({ to, transition });
|
|
9
|
+
}
|
|
10
|
+
export function finish(transition = {}) {
|
|
11
|
+
return Object.freeze({ to: "__graph_finish__", transition });
|
|
12
|
+
}
|
|
13
|
+
export function firstMatch(connections) {
|
|
14
|
+
return Object.freeze({
|
|
15
|
+
kind: "first-match",
|
|
16
|
+
connections: Object.freeze(Object.entries(connections).map(([id, connection]) => Object.freeze({ id, ...connection }))),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { ContextContent, ContextProjection, Graph, Stage } from "./graph.js";
|
|
2
|
+
import type { JsonValue } from "./json.js";
|
|
3
|
+
import type { ResolvedSkillView } from "./skill.js";
|
|
4
|
+
export type ContextRetention = "sticky" | "foldable" | "transient";
|
|
5
|
+
export type ContextLifetime = "agent-run" | "node-visit" | "graph-invocation" | "root-run";
|
|
6
|
+
export interface ContextContribution {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly owner: "host" | "graph" | "node" | "agent-run" | "runtime";
|
|
9
|
+
readonly scopeId: string;
|
|
10
|
+
readonly lifetime: ContextLifetime;
|
|
11
|
+
readonly retention: ContextRetention;
|
|
12
|
+
readonly content: ContextContent;
|
|
13
|
+
}
|
|
14
|
+
export interface ContextContributionHandle {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
update(content: ContextContent): void;
|
|
17
|
+
dispose(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface ContextLayer {
|
|
20
|
+
readonly name: "host" | "graph" | "memory" | "node" | "mechanism" | "output-contract" | "prompt";
|
|
21
|
+
readonly scopeId: string;
|
|
22
|
+
readonly retention: ContextRetention;
|
|
23
|
+
readonly content: ContextContent;
|
|
24
|
+
}
|
|
25
|
+
export interface ContextSnapshot {
|
|
26
|
+
readonly rootRunId: string;
|
|
27
|
+
readonly graphInvocationId: string;
|
|
28
|
+
readonly nodeVisitId?: string;
|
|
29
|
+
readonly agentRunId?: string;
|
|
30
|
+
readonly graphId: string;
|
|
31
|
+
readonly graphVersion: string;
|
|
32
|
+
readonly memoryRevision: number;
|
|
33
|
+
readonly layers: readonly ContextLayer[];
|
|
34
|
+
readonly contributions: readonly ContextContribution[];
|
|
35
|
+
}
|
|
36
|
+
export interface ContextStateOptions {
|
|
37
|
+
readonly rootRunId: string;
|
|
38
|
+
readonly graphInvocationId: string;
|
|
39
|
+
readonly graph: Graph;
|
|
40
|
+
readonly graphInput: JsonValue;
|
|
41
|
+
readonly graphSkills: readonly ResolvedSkillView[];
|
|
42
|
+
readonly frames: readonly JsonValue[];
|
|
43
|
+
readonly hostContent?: ContextContent | null;
|
|
44
|
+
readonly frameRevision?: {
|
|
45
|
+
value: number;
|
|
46
|
+
};
|
|
47
|
+
readonly externalContributions?: (nodeVisitId?: string) => readonly ContextContribution[];
|
|
48
|
+
}
|
|
49
|
+
export interface NodeContextMaterialization {
|
|
50
|
+
readonly nodeVisitId: string;
|
|
51
|
+
readonly stageId: string;
|
|
52
|
+
readonly snapshot: ContextSnapshot;
|
|
53
|
+
}
|
|
54
|
+
/** Canonical, scope-owned context state for one Graph Invocation. */
|
|
55
|
+
export declare class ContextState {
|
|
56
|
+
private readonly options;
|
|
57
|
+
private graphLayers;
|
|
58
|
+
private readonly contributions;
|
|
59
|
+
private readonly frameRevision;
|
|
60
|
+
private memoryCache;
|
|
61
|
+
constructor(options: ContextStateOptions);
|
|
62
|
+
initialize(): Promise<void>;
|
|
63
|
+
bumpMemoryRevision(): void;
|
|
64
|
+
materializeNode(nodeVisitId: string, stageId: string, stage: Stage, nodeInput: JsonValue, nodeSkills: readonly ResolvedSkillView[]): Promise<NodeContextMaterialization>;
|
|
65
|
+
snapshot(nodeVisitId?: string, layers?: readonly ContextLayer[]): ContextSnapshot;
|
|
66
|
+
refreshSnapshot(snapshot: ContextSnapshot, agentRunId?: string): ContextSnapshot;
|
|
67
|
+
addContribution(contribution: ContextContribution): ContextContributionHandle;
|
|
68
|
+
private materializeMemory;
|
|
69
|
+
}
|
|
70
|
+
export declare function materializeProjection<TSource, TSelected extends JsonValue, TMeta>(projection: ContextProjection<TSource, TSelected, TMeta>, source: TSource, meta: TMeta, fallback: (input: {
|
|
71
|
+
readonly selected: Readonly<TSelected> | null;
|
|
72
|
+
readonly meta: Readonly<TMeta>;
|
|
73
|
+
}) => ContextContent | null): Promise<ContextContent | null>;
|