@ai-agent-forge/plugin-sdk 0.85.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/dist/artifact.d.ts +20 -0
- package/dist/artifact.d.ts.map +1 -0
- package/dist/artifact.js +63 -0
- package/dist/artifact.js.map +1 -0
- package/dist/capability-manifest.d.ts +11 -0
- package/dist/capability-manifest.d.ts.map +1 -0
- package/dist/capability-manifest.js +188 -0
- package/dist/capability-manifest.js.map +1 -0
- package/dist/common.d.ts +24 -0
- package/dist/common.d.ts.map +1 -0
- package/dist/common.js +115 -0
- package/dist/common.js.map +1 -0
- package/dist/context-budget.d.ts +33 -0
- package/dist/context-budget.d.ts.map +1 -0
- package/dist/context-budget.js +124 -0
- package/dist/context-budget.js.map +1 -0
- package/dist/diff.d.ts +38 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +164 -0
- package/dist/diff.js.map +1 -0
- package/dist/durable.d.ts +108 -0
- package/dist/durable.d.ts.map +1 -0
- package/dist/durable.js +15 -0
- package/dist/durable.js.map +1 -0
- package/dist/ecosystem-manifest.d.ts +56 -0
- package/dist/ecosystem-manifest.d.ts.map +1 -0
- package/dist/ecosystem-manifest.js +11 -0
- package/dist/ecosystem-manifest.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/memory.d.ts +370 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +26 -0
- package/dist/memory.js.map +1 -0
- package/dist/observability.d.ts +354 -0
- package/dist/observability.d.ts.map +1 -0
- package/dist/observability.js +33 -0
- package/dist/observability.js.map +1 -0
- package/dist/operation.d.ts +60 -0
- package/dist/operation.d.ts.map +1 -0
- package/dist/operation.js +202 -0
- package/dist/operation.js.map +1 -0
- package/dist/public-api.d.ts +1977 -0
- package/dist/public-api.d.ts.map +1 -0
- package/dist/public-api.js +237 -0
- package/dist/public-api.js.map +1 -0
- package/dist/render.d.ts +38 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +112 -0
- package/dist/render.js.map +1 -0
- package/dist/session-lineage.d.ts +36 -0
- package/dist/session-lineage.d.ts.map +1 -0
- package/dist/session-lineage.js +134 -0
- package/dist/session-lineage.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 会话头血缘读取公共面(D-075 S4 第三批):`sessions/_agents/` 布局的 JSONL 会话
|
|
3
|
+
* 文件**只读首行头**的最小子集——按 `sessionId` 读会话头(`parentAgentSession` /
|
|
4
|
+
* `agentRole`)与沿父链上溯的祖先链。权威格式契约见
|
|
5
|
+
* docs/design/子代理会话与通信设计.md(D-060 S2 落盘格式)。
|
|
6
|
+
*
|
|
7
|
+
* 消费方:第一方 subagent 信箱(兄弟投递的血缘校验,@agent-forge/protocol)与
|
|
8
|
+
* subagent-delegate 的嵌套深度门(宿主)。两条纪律随宿主实现一并迁移:
|
|
9
|
+
* - **只读**:不创建任何目录/文件(区别于宿主写入侧的 `agentSessionsDir` mkdir 语义);
|
|
10
|
+
* - **寻址安全**:`sessionId` 先过形状校验(UUID / `st:` 形态、无路径分隔符)再做
|
|
11
|
+
* 路径拼接,杜绝 `../` 逃逸;不存在/形状非法/无头行与"无权"同型返回 undefined。
|
|
12
|
+
*
|
|
13
|
+
* 纯 `node:fs`、确定性可测。
|
|
14
|
+
*/
|
|
15
|
+
import { closeSync, openSync, readdirSync, readSync, statSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
/** 头行扫描字节上限(头行超出时按截断后的首行解析,解析失败即视为无头行)。 */
|
|
18
|
+
const HEADER_SCAN_BYTES = 8192;
|
|
19
|
+
/** 会话 id 形状:UUID(root/子会话)或池化 wire 任务 id(`st:` 前缀)。 */
|
|
20
|
+
export function isAgentSessionId(value) {
|
|
21
|
+
if (value.length === 0 || value.length > 128)
|
|
22
|
+
return false;
|
|
23
|
+
if (value.startsWith("st:"))
|
|
24
|
+
return /^st:[0-9]+:[a-z0-9-]+$/i.test(value);
|
|
25
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
26
|
+
}
|
|
27
|
+
/** 子代理会话目录(纯路径拼接,不创建):`<agentDir>/sessions/_agents/`。 */
|
|
28
|
+
function agentSessionsDir(agentDir) {
|
|
29
|
+
return join(agentDir, "sessions", "_agents");
|
|
30
|
+
}
|
|
31
|
+
/** 目录内定位某会话文件:命名形如 `<时间戳>_<sessionId>.jsonl`(或裸 `<sessionId>.jsonl`)。 */
|
|
32
|
+
export function findSessionFile(dir, sessionId) {
|
|
33
|
+
let names;
|
|
34
|
+
try {
|
|
35
|
+
names = readdirSync(dir);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
const suffix = `_${sessionId}.jsonl`;
|
|
41
|
+
const match = names.find((name) => name === `${sessionId}.jsonl` || name.endsWith(suffix));
|
|
42
|
+
return match === undefined ? undefined : join(dir, match);
|
|
43
|
+
}
|
|
44
|
+
function parseHeader(line) {
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse(line);
|
|
47
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
48
|
+
return undefined;
|
|
49
|
+
const record = parsed;
|
|
50
|
+
return record.type === "session" ? record : undefined;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** 只读文件前 HEADER_SCAN_BYTES 字节取首行(大 transcript 不整读)。 */
|
|
57
|
+
function readFirstLine(filePath) {
|
|
58
|
+
let handle;
|
|
59
|
+
try {
|
|
60
|
+
handle = openSync(filePath, "r");
|
|
61
|
+
const buffer = Buffer.alloc(HEADER_SCAN_BYTES);
|
|
62
|
+
const read = readSync(handle, buffer, 0, HEADER_SCAN_BYTES, 0);
|
|
63
|
+
if (read <= 0)
|
|
64
|
+
return undefined;
|
|
65
|
+
return buffer.toString("utf8", 0, read).split("\n", 1)[0] ?? "";
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
if (handle !== undefined)
|
|
72
|
+
closeSync(handle);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* 按 `sessionId` 读会话头(只读首行,不解析消息体)。不存在/形状非法/无头行都返回
|
|
77
|
+
* undefined(与"无权"同型,不区分原因)。
|
|
78
|
+
*/
|
|
79
|
+
export function readAgentSessionHead(agentDir, sessionId) {
|
|
80
|
+
if (!isAgentSessionId(sessionId))
|
|
81
|
+
return undefined;
|
|
82
|
+
const filePath = findSessionFile(agentSessionsDir(agentDir), sessionId);
|
|
83
|
+
if (filePath === undefined)
|
|
84
|
+
return undefined;
|
|
85
|
+
let bytes;
|
|
86
|
+
let firstLine;
|
|
87
|
+
try {
|
|
88
|
+
bytes = statSync(filePath).size;
|
|
89
|
+
firstLine = readFirstLine(filePath);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
if (firstLine === undefined)
|
|
95
|
+
return undefined;
|
|
96
|
+
const header = parseHeader(firstLine);
|
|
97
|
+
if (header === undefined)
|
|
98
|
+
return undefined;
|
|
99
|
+
const parentAgentSession = typeof header.parentAgentSession === "string" ? header.parentAgentSession : undefined;
|
|
100
|
+
const agentRole = typeof header.agentRole === "string" ? header.agentRole : undefined;
|
|
101
|
+
const createdAt = typeof header.timestamp === "string" ? header.timestamp : undefined;
|
|
102
|
+
return {
|
|
103
|
+
sessionId,
|
|
104
|
+
...(parentAgentSession === undefined ? {} : { parentAgentSession }),
|
|
105
|
+
...(agentRole === undefined ? {} : { agentRole }),
|
|
106
|
+
...(createdAt === undefined ? {} : { createdAt }),
|
|
107
|
+
bytes,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 读 `sessionId` 的祖先链(有界上溯):沿每级会话头的 `parentAgentSession` 上行,最多
|
|
112
|
+
* `maxDepth` 步。链在无父、自指(`parentAgentSession === sessionId`)或父 id 无落盘
|
|
113
|
+
* 文件处停止;走满步数仍有父则 `truncated: true`(损坏数据成环时按步数截断,不悬挂)。
|
|
114
|
+
*/
|
|
115
|
+
export function readAgentSessionLineage(agentDir, sessionId, maxDepth) {
|
|
116
|
+
const self = readAgentSessionHead(agentDir, sessionId);
|
|
117
|
+
if (self === undefined)
|
|
118
|
+
return { self: undefined, ancestors: [], truncated: false };
|
|
119
|
+
const ancestors = [];
|
|
120
|
+
let current = self;
|
|
121
|
+
for (let step = 0; step < maxDepth; step += 1) {
|
|
122
|
+
const parent = current.parentAgentSession;
|
|
123
|
+
if (parent === undefined || parent === current.sessionId) {
|
|
124
|
+
return { self, ancestors, truncated: false };
|
|
125
|
+
}
|
|
126
|
+
const head = readAgentSessionHead(agentDir, parent);
|
|
127
|
+
if (head === undefined)
|
|
128
|
+
return { self, ancestors, truncated: false };
|
|
129
|
+
ancestors.push(head);
|
|
130
|
+
current = head;
|
|
131
|
+
}
|
|
132
|
+
return { self, ancestors, truncated: true };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=session-lineage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-lineage.js","sourceRoot":"","sources":["../src/session-lineage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,mHAA2C;AAC3C,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,+FAAuD;AACvD,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAW;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;QAAE,OAAO,KAAK,CAAC;IAC3D,IAAI,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC;QAAE,OAAO,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1E,OAAO,iEAAiE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAAA,CACrF;AAED,iGAAyD;AACzD,SAAS,gBAAgB,CAAC,QAAgB,EAAU;IACnD,OAAO,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;AAAA,CAC7C;AAED,uHAAyE;AACzE,MAAM,UAAU,eAAe,CAAC,GAAW,EAAE,SAAiB,EAAsB;IACnF,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACJ,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,SAAS,QAAQ,CAAC;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,SAAS,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3F,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAAA,CAC1D;AAcD,SAAS,WAAW,CAAC,IAAY,EAAuC;IACvE,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,SAAS,CAAC;QAC7F,MAAM,MAAM,GAAG,MAAiC,CAAC;QACjD,OAAO,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AAAA,CACD;AAED,yFAAuD;AACvD,SAAS,aAAa,CAAC,QAAgB,EAAsB;IAC5D,IAAI,MAA0B,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,GAAG,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC;QAC/D,IAAI,IAAI,IAAI,CAAC;YAAE,OAAO,SAAS,CAAC;QAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;YAAS,CAAC;QACV,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;AAAA,CACD;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAgB,EAAE,SAAiB,EAAkC;IACzG,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACnD,MAAM,QAAQ,GAAG,eAAe,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IACxE,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC7C,IAAI,KAAa,CAAC;IAClB,IAAI,SAA6B,CAAC;IAClC,IAAI,CAAC;QACJ,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;QAChC,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,IAAI,SAAS,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,kBAAkB,GAAG,OAAO,MAAM,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,SAAS,CAAC;IACjH,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACtF,OAAO;QACN,SAAS;QACT,GAAG,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC;QACnE,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;QACjD,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;QACjD,KAAK;KACL,CAAC;AAAA,CACF;AAYD;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAgB,EAAE,SAAiB,EAAE,QAAgB,EAAyB;IACrH,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACpF,MAAM,SAAS,GAAyB,EAAE,CAAC;IAC3C,IAAI,OAAO,GAAG,IAAI,CAAC;IACnB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAC1C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,OAAO,CAAC,SAAS,EAAE,CAAC;YAC1D,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QAC9C,CAAC;QACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;QACrE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,OAAO,GAAG,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAAA,CAC5C","sourcesContent":["/**\n * 会话头血缘读取公共面(D-075 S4 第三批):`sessions/_agents/` 布局的 JSONL 会话\n * 文件**只读首行头**的最小子集——按 `sessionId` 读会话头(`parentAgentSession` /\n * `agentRole`)与沿父链上溯的祖先链。权威格式契约见\n * docs/design/子代理会话与通信设计.md(D-060 S2 落盘格式)。\n *\n * 消费方:第一方 subagent 信箱(兄弟投递的血缘校验,@agent-forge/protocol)与\n * subagent-delegate 的嵌套深度门(宿主)。两条纪律随宿主实现一并迁移:\n * - **只读**:不创建任何目录/文件(区别于宿主写入侧的 `agentSessionsDir` mkdir 语义);\n * - **寻址安全**:`sessionId` 先过形状校验(UUID / `st:` 形态、无路径分隔符)再做\n * 路径拼接,杜绝 `../` 逃逸;不存在/形状非法/无头行与\"无权\"同型返回 undefined。\n *\n * 纯 `node:fs`、确定性可测。\n */\nimport { closeSync, openSync, readdirSync, readSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** 头行扫描字节上限(头行超出时按截断后的首行解析,解析失败即视为无头行)。 */\nconst HEADER_SCAN_BYTES = 8192;\n\n/** 会话 id 形状:UUID(root/子会话)或池化 wire 任务 id(`st:` 前缀)。 */\nexport function isAgentSessionId(value: string): boolean {\n\tif (value.length === 0 || value.length > 128) return false;\n\tif (value.startsWith(\"st:\")) return /^st:[0-9]+:[a-z0-9-]+$/i.test(value);\n\treturn /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);\n}\n\n/** 子代理会话目录(纯路径拼接,不创建):`<agentDir>/sessions/_agents/`。 */\nfunction agentSessionsDir(agentDir: string): string {\n\treturn join(agentDir, \"sessions\", \"_agents\");\n}\n\n/** 目录内定位某会话文件:命名形如 `<时间戳>_<sessionId>.jsonl`(或裸 `<sessionId>.jsonl`)。 */\nexport function findSessionFile(dir: string, sessionId: string): string | undefined {\n\tlet names: string[];\n\ttry {\n\t\tnames = readdirSync(dir);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tconst suffix = `_${sessionId}.jsonl`;\n\tconst match = names.find((name) => name === `${sessionId}.jsonl` || name.endsWith(suffix));\n\treturn match === undefined ? undefined : join(dir, match);\n}\n\n/** 会话头(首行 `type: \"session\"` JSON 的有界投影,不含消息正文)。 */\nexport interface AgentSessionHeadV1 {\n\treadonly sessionId: string;\n\t/** 血缘:父 agent 会话 id(子会话必有;缺失说明文件非 D-060 落盘产物)。 */\n\treadonly parentAgentSession?: string;\n\t/** 血缘:创建该会话的角色 id(审计用途,不是权限判据)。 */\n\treadonly agentRole?: string;\n\treadonly createdAt?: string;\n\t/** 整份 transcript 的字节数(不是头行的字节数)。 */\n\treadonly bytes: number;\n}\n\nfunction parseHeader(line: string): Record<string, unknown> | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(line) as unknown;\n\t\tif (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) return undefined;\n\t\tconst record = parsed as Record<string, unknown>;\n\t\treturn record.type === \"session\" ? record : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\n/** 只读文件前 HEADER_SCAN_BYTES 字节取首行(大 transcript 不整读)。 */\nfunction readFirstLine(filePath: string): string | undefined {\n\tlet handle: number | undefined;\n\ttry {\n\t\thandle = openSync(filePath, \"r\");\n\t\tconst buffer = Buffer.alloc(HEADER_SCAN_BYTES);\n\t\tconst read = readSync(handle, buffer, 0, HEADER_SCAN_BYTES, 0);\n\t\tif (read <= 0) return undefined;\n\t\treturn buffer.toString(\"utf8\", 0, read).split(\"\\n\", 1)[0] ?? \"\";\n\t} catch {\n\t\treturn undefined;\n\t} finally {\n\t\tif (handle !== undefined) closeSync(handle);\n\t}\n}\n\n/**\n * 按 `sessionId` 读会话头(只读首行,不解析消息体)。不存在/形状非法/无头行都返回\n * undefined(与\"无权\"同型,不区分原因)。\n */\nexport function readAgentSessionHead(agentDir: string, sessionId: string): AgentSessionHeadV1 | undefined {\n\tif (!isAgentSessionId(sessionId)) return undefined;\n\tconst filePath = findSessionFile(agentSessionsDir(agentDir), sessionId);\n\tif (filePath === undefined) return undefined;\n\tlet bytes: number;\n\tlet firstLine: string | undefined;\n\ttry {\n\t\tbytes = statSync(filePath).size;\n\t\tfirstLine = readFirstLine(filePath);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (firstLine === undefined) return undefined;\n\tconst header = parseHeader(firstLine);\n\tif (header === undefined) return undefined;\n\tconst parentAgentSession = typeof header.parentAgentSession === \"string\" ? header.parentAgentSession : undefined;\n\tconst agentRole = typeof header.agentRole === \"string\" ? header.agentRole : undefined;\n\tconst createdAt = typeof header.timestamp === \"string\" ? header.timestamp : undefined;\n\treturn {\n\t\tsessionId,\n\t\t...(parentAgentSession === undefined ? {} : { parentAgentSession }),\n\t\t...(agentRole === undefined ? {} : { agentRole }),\n\t\t...(createdAt === undefined ? {} : { createdAt }),\n\t\tbytes,\n\t};\n}\n\n/** 沿 `parentAgentSession` 上溯的祖先链读取结果。 */\nexport interface AgentSessionLineageV1 {\n\t/** 起点会话头;缺文件/缺头行/非法 id 时 undefined(root 或未落盘会话即此形态)。 */\n\treadonly self: AgentSessionHeadV1 | undefined;\n\t/** 祖先链(最近父在前),不含 self;链在无父/自指/缺文件处停止。 */\n\treadonly ancestors: readonly AgentSessionHeadV1[];\n\t/** 走满 `maxDepth` 步仍有可解析的父时为 true(有界截断;防环按步数,语义与宿主 lineageDepth 的 maxWalk 对齐)。 */\n\treadonly truncated: boolean;\n}\n\n/**\n * 读 `sessionId` 的祖先链(有界上溯):沿每级会话头的 `parentAgentSession` 上行,最多\n * `maxDepth` 步。链在无父、自指(`parentAgentSession === sessionId`)或父 id 无落盘\n * 文件处停止;走满步数仍有父则 `truncated: true`(损坏数据成环时按步数截断,不悬挂)。\n */\nexport function readAgentSessionLineage(agentDir: string, sessionId: string, maxDepth: number): AgentSessionLineageV1 {\n\tconst self = readAgentSessionHead(agentDir, sessionId);\n\tif (self === undefined) return { self: undefined, ancestors: [], truncated: false };\n\tconst ancestors: AgentSessionHeadV1[] = [];\n\tlet current = self;\n\tfor (let step = 0; step < maxDepth; step += 1) {\n\t\tconst parent = current.parentAgentSession;\n\t\tif (parent === undefined || parent === current.sessionId) {\n\t\t\treturn { self, ancestors, truncated: false };\n\t\t}\n\t\tconst head = readAgentSessionHead(agentDir, parent);\n\t\tif (head === undefined) return { self, ancestors, truncated: false };\n\t\tancestors.push(head);\n\t\tcurrent = head;\n\t}\n\treturn { self, ancestors, truncated: true };\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-agent-forge/plugin-sdk",
|
|
3
|
+
"version": "0.85.0",
|
|
4
|
+
"description": "Shared plugin development contracts (artifact, operation, diff, render, context budget DTOs) for Agent Forge plugins",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./session-lineage": {
|
|
14
|
+
"types": "./dist/session-lineage.d.ts",
|
|
15
|
+
"import": "./dist/session-lineage.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"clean": "shx rm -rf dist",
|
|
24
|
+
"build": "tsgo -p tsconfig.build.json",
|
|
25
|
+
"test": "vitest --run",
|
|
26
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"agent-forge",
|
|
30
|
+
"plugin",
|
|
31
|
+
"sdk",
|
|
32
|
+
"contracts"
|
|
33
|
+
],
|
|
34
|
+
"author": "Agent Forge contributors",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/agent-forge/agent-forge.git",
|
|
39
|
+
"directory": "packages/plugin-sdk"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/agent-forge/agent-forge/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/agent-forge/agent-forge#readme",
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=22.19.0"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"semver": "7.8.0"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"shx": "0.4.0",
|
|
53
|
+
"vitest": "4.1.9"
|
|
54
|
+
}
|
|
55
|
+
}
|