gauss-ai 4.0.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/CHANGELOG.md +489 -0
- package/LICENSE +21 -0
- package/README.md +269 -0
- package/dist/a2a/index.cjs +7 -0
- package/dist/a2a/index.cjs.map +1 -0
- package/dist/a2a/index.d.cts +30 -0
- package/dist/a2a/index.d.ts +30 -0
- package/dist/a2a/index.js +7 -0
- package/dist/a2a/index.js.map +1 -0
- package/dist/agent-UIQDSYCE.js +16 -0
- package/dist/agent-UIQDSYCE.js.map +1 -0
- package/dist/agent-builder-8W3mBR-N.d.ts +1075 -0
- package/dist/agent-builder-GEMYdb1p.d.cts +1075 -0
- package/dist/agent-graph-AMQYAWNF.js +1422 -0
- package/dist/agent-graph-AMQYAWNF.js.map +1 -0
- package/dist/ai-sdk-mcp.adapter-SEN6KHNU.js +124 -0
- package/dist/ai-sdk-mcp.adapter-SEN6KHNU.js.map +1 -0
- package/dist/browser/index.js +10 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/bun-runtime.adapter-MQDAJLQM.js +8 -0
- package/dist/bun-runtime.adapter-MQDAJLQM.js.map +1 -0
- package/dist/bun-runtime.adapter-XKOUXVAK.cjs +8 -0
- package/dist/bun-runtime.adapter-XKOUXVAK.cjs.map +1 -0
- package/dist/chat-A3XMRPJL.js +129 -0
- package/dist/chat-A3XMRPJL.js.map +1 -0
- package/dist/chunk-2ZRU47NC.js +91 -0
- package/dist/chunk-2ZRU47NC.js.map +1 -0
- package/dist/chunk-3LD3JTH4.cjs +18 -0
- package/dist/chunk-3LD3JTH4.cjs.map +1 -0
- package/dist/chunk-5FE5TG2W.cjs +16 -0
- package/dist/chunk-5FE5TG2W.cjs.map +1 -0
- package/dist/chunk-6XF673YC.cjs +436 -0
- package/dist/chunk-6XF673YC.cjs.map +1 -0
- package/dist/chunk-7CKWZJNS.js +230 -0
- package/dist/chunk-7CKWZJNS.js.map +1 -0
- package/dist/chunk-BI2G665F.js +4588 -0
- package/dist/chunk-BI2G665F.js.map +1 -0
- package/dist/chunk-C5NLWJS2.js +139 -0
- package/dist/chunk-C5NLWJS2.js.map +1 -0
- package/dist/chunk-CJZ66SU3.cjs +4321 -0
- package/dist/chunk-CJZ66SU3.cjs.map +1 -0
- package/dist/chunk-DAMT2CXW.cjs +91 -0
- package/dist/chunk-DAMT2CXW.cjs.map +1 -0
- package/dist/chunk-E7WG3MO5.js +18 -0
- package/dist/chunk-E7WG3MO5.js.map +1 -0
- package/dist/chunk-EFDM6R4J.js +99 -0
- package/dist/chunk-EFDM6R4J.js.map +1 -0
- package/dist/chunk-F7WIPPEO.js +256 -0
- package/dist/chunk-F7WIPPEO.js.map +1 -0
- package/dist/chunk-FAYDE67N.js +6927 -0
- package/dist/chunk-FAYDE67N.js.map +1 -0
- package/dist/chunk-GAE2KKCM.js +21 -0
- package/dist/chunk-GAE2KKCM.js.map +1 -0
- package/dist/chunk-INLNGRXM.cjs +130 -0
- package/dist/chunk-INLNGRXM.cjs.map +1 -0
- package/dist/chunk-JKXKXB5O.js +130 -0
- package/dist/chunk-JKXKXB5O.js.map +1 -0
- package/dist/chunk-K6SAETGP.js +375 -0
- package/dist/chunk-K6SAETGP.js.map +1 -0
- package/dist/chunk-KEASLAYR.js +157 -0
- package/dist/chunk-KEASLAYR.js.map +1 -0
- package/dist/chunk-KKJVNM6O.js +436 -0
- package/dist/chunk-KKJVNM6O.js.map +1 -0
- package/dist/chunk-KYIMVRIM.js +16 -0
- package/dist/chunk-KYIMVRIM.js.map +1 -0
- package/dist/chunk-MB7NXIZD.js +4321 -0
- package/dist/chunk-MB7NXIZD.js.map +1 -0
- package/dist/chunk-MHHDXPGE.js +209 -0
- package/dist/chunk-MHHDXPGE.js.map +1 -0
- package/dist/chunk-NE6JJA5W.js +401 -0
- package/dist/chunk-NE6JJA5W.js.map +1 -0
- package/dist/chunk-PF46XZBF.cjs +6927 -0
- package/dist/chunk-PF46XZBF.cjs.map +1 -0
- package/dist/chunk-PSJIAGDE.cjs +375 -0
- package/dist/chunk-PSJIAGDE.cjs.map +1 -0
- package/dist/chunk-PWOQDXNQ.js +16 -0
- package/dist/chunk-PWOQDXNQ.js.map +1 -0
- package/dist/chunk-QYOMQBBZ.cjs +230 -0
- package/dist/chunk-QYOMQBBZ.cjs.map +1 -0
- package/dist/chunk-UDFXLC4J.cjs +16 -0
- package/dist/chunk-UDFXLC4J.cjs.map +1 -0
- package/dist/chunk-UO4NGXRT.cjs +259 -0
- package/dist/chunk-UO4NGXRT.cjs.map +1 -0
- package/dist/chunk-UPFDFLEW.js +40 -0
- package/dist/chunk-UPFDFLEW.js.map +1 -0
- package/dist/chunk-V55JSQS7.cjs +16 -0
- package/dist/chunk-V55JSQS7.cjs.map +1 -0
- package/dist/chunk-VJADHXZL.cjs +16 -0
- package/dist/chunk-VJADHXZL.cjs.map +1 -0
- package/dist/chunk-VRWD7LCI.js +59 -0
- package/dist/chunk-VRWD7LCI.js.map +1 -0
- package/dist/chunk-WKKQ443C.js +487 -0
- package/dist/chunk-WKKQ443C.js.map +1 -0
- package/dist/chunk-X2GHUHAF.js +436 -0
- package/dist/chunk-X2GHUHAF.js.map +1 -0
- package/dist/chunk-XLGW3XNI.cjs +256 -0
- package/dist/chunk-XLGW3XNI.cjs.map +1 -0
- package/dist/chunk-ZFJKX4DP.js +16 -0
- package/dist/chunk-ZFJKX4DP.js.map +1 -0
- package/dist/chunk-ZM2OEWM2.js +259 -0
- package/dist/chunk-ZM2OEWM2.js.map +1 -0
- package/dist/chunk-ZNAIP2XV.js +16 -0
- package/dist/chunk-ZNAIP2XV.js.map +1 -0
- package/dist/chunk-ZYFAZYSL.js +42 -0
- package/dist/chunk-ZYFAZYSL.js.map +1 -0
- package/dist/cli/index.js +421 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config-4MHT6TQW.js +153 -0
- package/dist/config-4MHT6TQW.js.map +1 -0
- package/dist/config-REERQFK4.cjs +153 -0
- package/dist/config-REERQFK4.cjs.map +1 -0
- package/dist/cost-tracker-JLOU7IZJ.js +7 -0
- package/dist/cost-tracker-JLOU7IZJ.js.map +1 -0
- package/dist/demo-C52GMSYH.js +188 -0
- package/dist/demo-C52GMSYH.js.map +1 -0
- package/dist/deno/index.js +306 -0
- package/dist/deno/index.js.map +1 -0
- package/dist/deno-runtime.adapter-F744HY7K.js +8 -0
- package/dist/deno-runtime.adapter-F744HY7K.js.map +1 -0
- package/dist/deno-runtime.adapter-RFEVNSCV.cjs +8 -0
- package/dist/deno-runtime.adapter-RFEVNSCV.cjs.map +1 -0
- package/dist/dev-D7DDVDA4.js +218 -0
- package/dist/dev-D7DDVDA4.js.map +1 -0
- package/dist/edge/index.js +10 -0
- package/dist/edge/index.js.map +1 -0
- package/dist/edge-runtime.adapter-UQCW2F7X.js +8 -0
- package/dist/edge-runtime.adapter-UQCW2F7X.js.map +1 -0
- package/dist/edge-runtime.adapter-YED6F3AY.cjs +8 -0
- package/dist/edge-runtime.adapter-YED6F3AY.cjs.map +1 -0
- package/dist/graph-MGFAQZ5W.js +50 -0
- package/dist/graph-MGFAQZ5W.js.map +1 -0
- package/dist/graph-visualization-HBSVQXJK.js +9 -0
- package/dist/graph-visualization-HBSVQXJK.js.map +1 -0
- package/dist/index-BRgqNnh3.d.cts +982 -0
- package/dist/index-CZxpYUxZ.d.ts +982 -0
- package/dist/index.cjs +14789 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10275 -0
- package/dist/index.d.ts +10275 -0
- package/dist/index.js +14789 -0
- package/dist/index.js.map +1 -0
- package/dist/init-CFWXTQ35.js +133 -0
- package/dist/init-CFWXTQ35.js.map +1 -0
- package/dist/llm-VWO4MC7J.cjs +17 -0
- package/dist/llm-VWO4MC7J.cjs.map +1 -0
- package/dist/llm-XLXVSPBI.js +17 -0
- package/dist/llm-XLXVSPBI.js.map +1 -0
- package/dist/logging-WRAK5ZXT.js +33 -0
- package/dist/logging-WRAK5ZXT.js.map +1 -0
- package/dist/metrics-FAHZVVD4.js +47 -0
- package/dist/metrics-FAHZVVD4.js.map +1 -0
- package/dist/node/index.cjs +280 -0
- package/dist/node/index.cjs.map +1 -0
- package/dist/node/index.d.cts +51 -0
- package/dist/node/index.d.ts +51 -0
- package/dist/node/index.js +280 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node-runtime.adapter-5L7PJ6W2.js +8 -0
- package/dist/node-runtime.adapter-5L7PJ6W2.js.map +1 -0
- package/dist/node-runtime.adapter-CCRZVGHB.cjs +8 -0
- package/dist/node-runtime.adapter-CCRZVGHB.cjs.map +1 -0
- package/dist/persist-usage-WTBTCWEF.js +7 -0
- package/dist/persist-usage-WTBTCWEF.js.map +1 -0
- package/dist/plugin-RCPBWUUA.js +207 -0
- package/dist/plugin-RCPBWUUA.js.map +1 -0
- package/dist/plugins/index.cjs +75 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.cts +8 -0
- package/dist/plugins/index.d.ts +8 -0
- package/dist/plugins/index.js +75 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins-L4ING3CX.js +4625 -0
- package/dist/plugins-L4ING3CX.js.map +1 -0
- package/dist/providers/index.cjs +189 -0
- package/dist/providers/index.cjs.map +1 -0
- package/dist/providers/index.d.cts +168 -0
- package/dist/providers/index.d.ts +168 -0
- package/dist/providers/index.js +189 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers-3RNQ5CKZ.js +59 -0
- package/dist/providers-3RNQ5CKZ.js.map +1 -0
- package/dist/providers-66GPXUGQ.cjs +59 -0
- package/dist/providers-66GPXUGQ.cjs.map +1 -0
- package/dist/repl-K6QN4I2S.js +678 -0
- package/dist/repl-K6QN4I2S.js.map +1 -0
- package/dist/rest/index.cjs +17 -0
- package/dist/rest/index.cjs.map +1 -0
- package/dist/rest/index.d.cts +102 -0
- package/dist/rest/index.d.ts +102 -0
- package/dist/rest/index.js +17 -0
- package/dist/rest/index.js.map +1 -0
- package/dist/runtime-deno.js +15 -0
- package/dist/runtime-deno.js.map +1 -0
- package/dist/runtime-edge.js +15 -0
- package/dist/runtime-edge.js.map +1 -0
- package/dist/runtime-node.js +15 -0
- package/dist/runtime-node.js.map +1 -0
- package/dist/scraping/index.cjs +11 -0
- package/dist/scraping/index.cjs.map +1 -0
- package/dist/scraping/index.d.cts +17 -0
- package/dist/scraping/index.d.ts +17 -0
- package/dist/scraping/index.js +11 -0
- package/dist/scraping/index.js.map +1 -0
- package/dist/semantic-scraping.port-CZWUea88.d.cts +54 -0
- package/dist/semantic-scraping.port-CZWUea88.d.ts +54 -0
- package/dist/server/index.js +166 -0
- package/dist/server/index.js.map +1 -0
- package/dist/testing/index.cjs +25 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +63 -0
- package/dist/testing/index.d.ts +63 -0
- package/dist/testing/index.js +25 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/token-counter.port-CRgxZZGe.d.ts +334 -0
- package/dist/token-counter.port-D7BHMCRR.d.cts +334 -0
- package/dist/tools-BZM33OBZ.js +10 -0
- package/dist/tools-BZM33OBZ.js.map +1 -0
- package/dist/tracing-XA3TEWP4.js +48 -0
- package/dist/tracing-XA3TEWP4.js.map +1 -0
- package/dist/types-CVsP7gFI.d.cts +235 -0
- package/dist/types-CVsP7gFI.d.ts +235 -0
- package/dist/virtual-fs.adapter-BBLS-3AY.d.ts +26 -0
- package/dist/virtual-fs.adapter-nb0CTYOj.d.cts +26 -0
- package/dist/workflow/index.cjs +9 -0
- package/dist/workflow/index.cjs.map +1 -0
- package/dist/workflow/index.d.cts +62 -0
- package/dist/workflow/index.d.ts +62 -0
- package/dist/workflow/index.js +9 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow.port-BaCttxrw.d.cts +153 -0
- package/dist/workflow.port-BaCttxrw.d.ts +153 -0
- package/package.json +230 -0
|
@@ -0,0 +1,4321 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3; var _class4; var _class5; var _class6; var _class7; var _class8; var _class9; var _class10; var _class11; var _class12; var _class13; var _class14; var _class15;
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
var _chunk6XF673YCcjs = require('./chunk-6XF673YC.cjs');
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
var _chunkPSJIAGDEcjs = require('./chunk-PSJIAGDE.cjs');
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
var _chunkQYOMQBBZcjs = require('./chunk-QYOMQBBZ.cjs');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
var _chunkDAMT2CXWcjs = require('./chunk-DAMT2CXW.cjs');
|
|
14
|
+
|
|
15
|
+
// src/plugins/base.plugin.ts
|
|
16
|
+
var BasePlugin = (_class = class {
|
|
17
|
+
__init() {this.version = "1.0.0"}
|
|
18
|
+
|
|
19
|
+
constructor() {;_class.prototype.__init.call(this);
|
|
20
|
+
this.hooks = this.buildHooks();
|
|
21
|
+
}
|
|
22
|
+
}, _class);
|
|
23
|
+
|
|
24
|
+
// src/plugins/agent-card.plugin.ts
|
|
25
|
+
var _zod = require('zod');
|
|
26
|
+
var DEFAULT_AGENTS_PATH = "agents.md";
|
|
27
|
+
var DEFAULT_SKILLS_PATH = "skills.md";
|
|
28
|
+
var DEFAULT_ZONES = ["persistent", "transient"];
|
|
29
|
+
var AgentCardPlugin = (_class2 = class {
|
|
30
|
+
__init2() {this.name = "agent-card"}
|
|
31
|
+
__init3() {this.version = "1.0.0"}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
__init4() {this.hooks = {
|
|
37
|
+
beforeRun: async (ctx, _params) => {
|
|
38
|
+
this.latestCtx = ctx;
|
|
39
|
+
},
|
|
40
|
+
afterRun: async (ctx, _params) => {
|
|
41
|
+
this.latestCtx = ctx;
|
|
42
|
+
}
|
|
43
|
+
}}
|
|
44
|
+
constructor(options = {}) {;_class2.prototype.__init2.call(this);_class2.prototype.__init3.call(this);_class2.prototype.__init4.call(this);
|
|
45
|
+
this.options = {
|
|
46
|
+
paths: {
|
|
47
|
+
agents: _nullishCoalesce(_optionalChain([options, 'access', _2 => _2.paths, 'optionalAccess', _3 => _3.agents]), () => ( DEFAULT_AGENTS_PATH)),
|
|
48
|
+
skills: _nullishCoalesce(_optionalChain([options, 'access', _4 => _4.paths, 'optionalAccess', _5 => _5.skills]), () => ( DEFAULT_SKILLS_PATH))
|
|
49
|
+
},
|
|
50
|
+
readZones: _nullishCoalesce(options.readZones, () => ( DEFAULT_ZONES)),
|
|
51
|
+
overrides: options.overrides
|
|
52
|
+
};
|
|
53
|
+
this.tools = {
|
|
54
|
+
"agent-card:get": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
55
|
+
description: "Return generated or manual agent card documents.",
|
|
56
|
+
inputSchema: _zod.z.object({
|
|
57
|
+
target: _zod.z.enum(["agents", "skills", "all"]).default("all")
|
|
58
|
+
}),
|
|
59
|
+
execute: async (args) => {
|
|
60
|
+
const parsed = _zod.z.object({ target: _zod.z.enum(["agents", "skills", "all"]).default("all") }).parse(_nullishCoalesce(args, () => ( {})));
|
|
61
|
+
const snapshot = await this.getAgentCard();
|
|
62
|
+
if (parsed.target === "agents") {
|
|
63
|
+
return {
|
|
64
|
+
target: "agents",
|
|
65
|
+
markdown: snapshot.agentsMd,
|
|
66
|
+
source: snapshot.source.agents
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
if (parsed.target === "skills") {
|
|
70
|
+
return {
|
|
71
|
+
target: "skills",
|
|
72
|
+
markdown: snapshot.skillsMd,
|
|
73
|
+
source: snapshot.source.skills
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return snapshot;
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
setup(ctx) {
|
|
82
|
+
this.setupCtx = ctx;
|
|
83
|
+
}
|
|
84
|
+
async getAgentCard() {
|
|
85
|
+
const ctx = _nullishCoalesce(this.latestCtx, () => ( this.setupCtx));
|
|
86
|
+
if (!ctx) {
|
|
87
|
+
throw new Error("AgentCardPlugin has not been initialized by a Agent instance");
|
|
88
|
+
}
|
|
89
|
+
const agents = await this.resolveAgentsMarkdown(ctx);
|
|
90
|
+
const skills = await this.resolveSkillsMarkdown(ctx);
|
|
91
|
+
return {
|
|
92
|
+
agentsMd: agents.markdown,
|
|
93
|
+
skillsMd: skills.markdown,
|
|
94
|
+
source: {
|
|
95
|
+
agents: agents.source,
|
|
96
|
+
skills: skills.source
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async resolveAgentsMarkdown(ctx) {
|
|
101
|
+
const manual = await this.tryReadManual(ctx, this.options.paths.agents);
|
|
102
|
+
if (manual) return { markdown: manual, source: "manual" };
|
|
103
|
+
const auto = this.createAutoAgentCard(ctx);
|
|
104
|
+
const override = _optionalChain([this, 'access', _6 => _6.options, 'access', _7 => _7.overrides, 'optionalAccess', _8 => _8.agents]);
|
|
105
|
+
if (override !== void 0) {
|
|
106
|
+
if (typeof override === "string") {
|
|
107
|
+
return { markdown: override, source: "override" };
|
|
108
|
+
}
|
|
109
|
+
const merged = this.mergeAgentCard(auto, override);
|
|
110
|
+
return { markdown: this.renderAgentCard(merged), source: "override" };
|
|
111
|
+
}
|
|
112
|
+
return { markdown: this.renderAgentCard(auto), source: "auto" };
|
|
113
|
+
}
|
|
114
|
+
async resolveSkillsMarkdown(ctx) {
|
|
115
|
+
const manual = await this.tryReadManual(ctx, this.options.paths.skills);
|
|
116
|
+
if (manual) return { markdown: manual, source: "manual" };
|
|
117
|
+
const auto = this.createAutoSkillsCard(ctx);
|
|
118
|
+
const override = _optionalChain([this, 'access', _9 => _9.options, 'access', _10 => _10.overrides, 'optionalAccess', _11 => _11.skills]);
|
|
119
|
+
if (override !== void 0) {
|
|
120
|
+
if (typeof override === "string") {
|
|
121
|
+
return { markdown: override, source: "override" };
|
|
122
|
+
}
|
|
123
|
+
const merged = this.mergeSkillsCard(auto, override);
|
|
124
|
+
return { markdown: this.renderSkillsCard(merged), source: "override" };
|
|
125
|
+
}
|
|
126
|
+
return { markdown: this.renderSkillsCard(auto), source: "auto" };
|
|
127
|
+
}
|
|
128
|
+
async tryReadManual(ctx, path) {
|
|
129
|
+
for (const zone of this.options.readZones) {
|
|
130
|
+
try {
|
|
131
|
+
const exists = await ctx.filesystem.exists(path, zone);
|
|
132
|
+
if (!exists) continue;
|
|
133
|
+
return await ctx.filesystem.read(path, zone);
|
|
134
|
+
} catch (e2) {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
createAutoAgentCard(ctx) {
|
|
140
|
+
const name = _nullishCoalesce(ctx.agentName, () => ( "Agent"));
|
|
141
|
+
const tools = [...ctx.toolNames].sort();
|
|
142
|
+
return {
|
|
143
|
+
title: "Agent Card",
|
|
144
|
+
name,
|
|
145
|
+
sessionId: ctx.sessionId,
|
|
146
|
+
maxSteps: ctx.config.maxSteps,
|
|
147
|
+
summary: `${name} exposes ${tools.length} tool${tools.length === 1 ? "" : "s"}.`,
|
|
148
|
+
instructions: ctx.config.instructions,
|
|
149
|
+
tools,
|
|
150
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
createAutoSkillsCard(ctx) {
|
|
154
|
+
const name = _nullishCoalesce(ctx.agentName, () => ( "Agent"));
|
|
155
|
+
const skills = [...ctx.toolNames].sort();
|
|
156
|
+
return {
|
|
157
|
+
title: "Skills Card",
|
|
158
|
+
name,
|
|
159
|
+
summary: `${name} can invoke ${skills.length} callable skills/tools.`,
|
|
160
|
+
skills,
|
|
161
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
mergeAgentCard(base, override) {
|
|
165
|
+
return {
|
|
166
|
+
...base,
|
|
167
|
+
...override,
|
|
168
|
+
tools: override.tools ? [...override.tools] : base.tools
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
mergeSkillsCard(base, override) {
|
|
172
|
+
return {
|
|
173
|
+
...base,
|
|
174
|
+
...override,
|
|
175
|
+
skills: override.skills ? [...override.skills] : base.skills
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
renderAgentCard(doc) {
|
|
179
|
+
const tools = doc.tools.length > 0 ? doc.tools.map((toolName) => `- \`${toolName}\``) : ["- _No tools registered_"];
|
|
180
|
+
return [
|
|
181
|
+
`# ${doc.title}`,
|
|
182
|
+
"",
|
|
183
|
+
`- Name: ${doc.name}`,
|
|
184
|
+
`- Session: ${doc.sessionId}`,
|
|
185
|
+
`- Max Steps: ${doc.maxSteps}`,
|
|
186
|
+
`- Generated At: ${doc.generatedAt}`,
|
|
187
|
+
"",
|
|
188
|
+
"## Summary",
|
|
189
|
+
doc.summary,
|
|
190
|
+
"",
|
|
191
|
+
"## Instructions",
|
|
192
|
+
doc.instructions,
|
|
193
|
+
"",
|
|
194
|
+
"## Tools",
|
|
195
|
+
...tools,
|
|
196
|
+
""
|
|
197
|
+
].join("\n");
|
|
198
|
+
}
|
|
199
|
+
renderSkillsCard(doc) {
|
|
200
|
+
const skills = doc.skills.length > 0 ? doc.skills.map((skill) => `- \`${skill}\``) : ["- _No skills registered_"];
|
|
201
|
+
return [
|
|
202
|
+
`# ${doc.title}`,
|
|
203
|
+
"",
|
|
204
|
+
`- Agent: ${doc.name}`,
|
|
205
|
+
`- Generated At: ${doc.generatedAt}`,
|
|
206
|
+
"",
|
|
207
|
+
"## Summary",
|
|
208
|
+
doc.summary,
|
|
209
|
+
"",
|
|
210
|
+
"## Skills",
|
|
211
|
+
...skills,
|
|
212
|
+
""
|
|
213
|
+
].join("\n");
|
|
214
|
+
}
|
|
215
|
+
}, _class2);
|
|
216
|
+
function createAgentCardPlugin(options) {
|
|
217
|
+
return new AgentCardPlugin(options);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/plugins/a2a.plugin.ts
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
// src/plugins/a2a-handler.ts
|
|
224
|
+
function createError(id, code, message, data) {
|
|
225
|
+
const error = data === void 0 ? { code, message } : { code, message, data };
|
|
226
|
+
return {
|
|
227
|
+
jsonrpc: "2.0",
|
|
228
|
+
id,
|
|
229
|
+
error
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function asRecord(value) {
|
|
233
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
return value;
|
|
237
|
+
}
|
|
238
|
+
function asString(value) {
|
|
239
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
240
|
+
}
|
|
241
|
+
function createA2AJsonRpcHandler(handlers) {
|
|
242
|
+
return async (request) => {
|
|
243
|
+
const id = _nullishCoalesce(request.id, () => ( null));
|
|
244
|
+
if (request.jsonrpc !== "2.0" || typeof request.method !== "string") {
|
|
245
|
+
return createError(id, -32600, "Invalid Request");
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
switch (request.method) {
|
|
249
|
+
case "tasks/send": {
|
|
250
|
+
const params = asRecord(request.params);
|
|
251
|
+
if (!params) {
|
|
252
|
+
return createError(id, -32602, "Invalid params: expected object");
|
|
253
|
+
}
|
|
254
|
+
const prompt = asString(params.prompt);
|
|
255
|
+
if (!prompt) {
|
|
256
|
+
return createError(id, -32602, "Invalid params: prompt is required");
|
|
257
|
+
}
|
|
258
|
+
const parsedTaskId = params.taskId === void 0 ? void 0 : asString(params.taskId);
|
|
259
|
+
if (params.taskId !== void 0 && !parsedTaskId) {
|
|
260
|
+
return createError(id, -32602, "Invalid params: taskId must be a non-empty string");
|
|
261
|
+
}
|
|
262
|
+
const taskId = _nullishCoalesce(parsedTaskId, () => ( void 0));
|
|
263
|
+
const metadata = params.metadata === void 0 ? void 0 : asRecord(params.metadata);
|
|
264
|
+
if (params.metadata !== void 0 && !metadata) {
|
|
265
|
+
return createError(id, -32602, "Invalid params: metadata must be an object");
|
|
266
|
+
}
|
|
267
|
+
const task = await handlers.sendTask({ prompt, taskId, metadata: _nullishCoalesce(metadata, () => ( void 0)) });
|
|
268
|
+
return {
|
|
269
|
+
jsonrpc: "2.0",
|
|
270
|
+
id,
|
|
271
|
+
result: task
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
case "tasks/get": {
|
|
275
|
+
const params = asRecord(request.params);
|
|
276
|
+
if (!params) {
|
|
277
|
+
return createError(id, -32602, "Invalid params: expected object");
|
|
278
|
+
}
|
|
279
|
+
const taskId = asString(params.taskId);
|
|
280
|
+
if (!taskId) {
|
|
281
|
+
return createError(id, -32602, "Invalid params: taskId is required");
|
|
282
|
+
}
|
|
283
|
+
const task = await handlers.getTask(taskId);
|
|
284
|
+
if (!task) {
|
|
285
|
+
return createError(id, -32004, "Task not found", { taskId });
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
jsonrpc: "2.0",
|
|
289
|
+
id,
|
|
290
|
+
result: task
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
case "tasks/list": {
|
|
294
|
+
if (!handlers.listTasks) {
|
|
295
|
+
return createError(id, -32601, "Method not found: tasks/list");
|
|
296
|
+
}
|
|
297
|
+
const tasks = await handlers.listTasks();
|
|
298
|
+
return {
|
|
299
|
+
jsonrpc: "2.0",
|
|
300
|
+
id,
|
|
301
|
+
result: { tasks }
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
case "tasks/cancel": {
|
|
305
|
+
if (!handlers.cancelTask) {
|
|
306
|
+
return createError(id, -32601, "Method not found: tasks/cancel");
|
|
307
|
+
}
|
|
308
|
+
const params = asRecord(request.params);
|
|
309
|
+
if (!params) {
|
|
310
|
+
return createError(id, -32602, "Invalid params: expected object");
|
|
311
|
+
}
|
|
312
|
+
const taskId = asString(params.taskId);
|
|
313
|
+
if (!taskId) {
|
|
314
|
+
return createError(id, -32602, "Invalid params: taskId is required");
|
|
315
|
+
}
|
|
316
|
+
const task = await handlers.cancelTask(taskId);
|
|
317
|
+
if (!task) {
|
|
318
|
+
return createError(id, -32004, "Task not found", { taskId });
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
jsonrpc: "2.0",
|
|
322
|
+
id,
|
|
323
|
+
result: task
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
case "agent/card": {
|
|
327
|
+
if (!handlers.getAgentCard) {
|
|
328
|
+
return createError(id, -32601, "Method not found: agent/card");
|
|
329
|
+
}
|
|
330
|
+
const card = await handlers.getAgentCard();
|
|
331
|
+
return {
|
|
332
|
+
jsonrpc: "2.0",
|
|
333
|
+
id,
|
|
334
|
+
result: card
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
case "tasks/sendSubscribe": {
|
|
338
|
+
if (!handlers.sendTaskSubscribe) {
|
|
339
|
+
return createError(id, -32601, "Method not found: tasks/sendSubscribe");
|
|
340
|
+
}
|
|
341
|
+
const params = asRecord(request.params);
|
|
342
|
+
if (!params) {
|
|
343
|
+
return createError(id, -32602, "Invalid params: expected object");
|
|
344
|
+
}
|
|
345
|
+
const prompt = asString(params.prompt);
|
|
346
|
+
if (!prompt) {
|
|
347
|
+
return createError(id, -32602, "Invalid params: prompt is required");
|
|
348
|
+
}
|
|
349
|
+
const parsedTaskId = params.taskId === void 0 ? void 0 : asString(params.taskId);
|
|
350
|
+
if (params.taskId !== void 0 && !parsedTaskId) {
|
|
351
|
+
return createError(id, -32602, "Invalid params: taskId must be a non-empty string");
|
|
352
|
+
}
|
|
353
|
+
const taskId = _nullishCoalesce(parsedTaskId, () => ( void 0));
|
|
354
|
+
const metadata = params.metadata === void 0 ? void 0 : asRecord(params.metadata);
|
|
355
|
+
if (params.metadata !== void 0 && !metadata) {
|
|
356
|
+
return createError(id, -32602, "Invalid params: metadata must be an object");
|
|
357
|
+
}
|
|
358
|
+
return createError(id, -32601, "Use SSE endpoint for tasks/sendSubscribe");
|
|
359
|
+
}
|
|
360
|
+
case "health": {
|
|
361
|
+
return {
|
|
362
|
+
jsonrpc: "2.0",
|
|
363
|
+
id,
|
|
364
|
+
result: { ok: true }
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
default:
|
|
368
|
+
return createError(id, -32601, `Method not found: ${request.method}`);
|
|
369
|
+
}
|
|
370
|
+
} catch (error) {
|
|
371
|
+
return createError(
|
|
372
|
+
id,
|
|
373
|
+
-32603,
|
|
374
|
+
error instanceof Error ? error.message : "Internal error"
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
function createA2AHttpHandler(jsonRpcHandler, sseHandlers) {
|
|
380
|
+
return async (request) => {
|
|
381
|
+
const url = new URL(request.url);
|
|
382
|
+
if (request.method === "GET" && url.pathname === "/.well-known/agent.json") {
|
|
383
|
+
try {
|
|
384
|
+
const cardResponse = await jsonRpcHandler({
|
|
385
|
+
jsonrpc: "2.0",
|
|
386
|
+
id: "agent-discovery",
|
|
387
|
+
method: "agent/card"
|
|
388
|
+
});
|
|
389
|
+
if (cardResponse.error) {
|
|
390
|
+
return new Response(
|
|
391
|
+
JSON.stringify({ error: "Agent card not available" }),
|
|
392
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
const agentCard = cardResponse.result;
|
|
396
|
+
const cardName = _nullishCoalesce(_nullishCoalesce(_optionalChain([agentCard, 'optionalAccess', _12 => _12.name]), () => ( _optionalChain([agentCard, 'optionalAccess', _13 => _13.source, 'optionalAccess', _14 => _14.name]))), () => ( "Agent"));
|
|
397
|
+
const cardDescription = _nullishCoalesce(_nullishCoalesce(_optionalChain([agentCard, 'optionalAccess', _15 => _15.instructions]), () => ( _optionalChain([agentCard, 'optionalAccess', _16 => _16.agentsMd]))), () => ( "A2A-compatible agent"));
|
|
398
|
+
const cardTools = _nullishCoalesce(_optionalChain([agentCard, 'optionalAccess', _17 => _17.tools]), () => ( []));
|
|
399
|
+
const cardSkills = _optionalChain([agentCard, 'optionalAccess', _18 => _18.skillsMd]) ? agentCard.skillsMd.split("\n").filter((l) => l.startsWith("- ")).map((l) => l.slice(2)) : [];
|
|
400
|
+
const allSkills = cardTools.length > 0 ? cardTools : cardSkills;
|
|
401
|
+
const discoveryCard = {
|
|
402
|
+
name: cardName,
|
|
403
|
+
description: cardDescription,
|
|
404
|
+
url: url.origin + "/a2a",
|
|
405
|
+
version: "1.0.0",
|
|
406
|
+
capabilities: {
|
|
407
|
+
streaming: true,
|
|
408
|
+
pushNotifications: true
|
|
409
|
+
},
|
|
410
|
+
skills: allSkills.map((skill, index) => ({
|
|
411
|
+
id: `skill-${index}`,
|
|
412
|
+
name: skill,
|
|
413
|
+
description: `Skill: ${skill}`
|
|
414
|
+
})),
|
|
415
|
+
authentication: { schemes: ["none"] }
|
|
416
|
+
};
|
|
417
|
+
return new Response(JSON.stringify(discoveryCard), {
|
|
418
|
+
status: 200,
|
|
419
|
+
headers: { "Content-Type": "application/json" }
|
|
420
|
+
});
|
|
421
|
+
} catch (error) {
|
|
422
|
+
return new Response(
|
|
423
|
+
JSON.stringify({ error: "Failed to generate agent card" }),
|
|
424
|
+
{ status: 500, headers: { "Content-Type": "application/json" } }
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
if (request.method !== "POST") {
|
|
429
|
+
return new Response(null, { status: 405 });
|
|
430
|
+
}
|
|
431
|
+
let parsed;
|
|
432
|
+
try {
|
|
433
|
+
parsed = await request.json();
|
|
434
|
+
} catch (e3) {
|
|
435
|
+
return new Response(
|
|
436
|
+
JSON.stringify(createError(null, -32700, "Parse error")),
|
|
437
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
if (_optionalChain([sseHandlers, 'optionalAccess', _19 => _19.sendTaskSubscribe])) {
|
|
441
|
+
const requestObject2 = asRecord(parsed);
|
|
442
|
+
if (_optionalChain([requestObject2, 'optionalAccess', _20 => _20.method]) === "tasks/sendSubscribe") {
|
|
443
|
+
const params = asRecord(requestObject2.params);
|
|
444
|
+
if (!params) {
|
|
445
|
+
return new Response("Invalid params", { status: 400 });
|
|
446
|
+
}
|
|
447
|
+
const prompt = asString(params.prompt);
|
|
448
|
+
if (!prompt) {
|
|
449
|
+
return new Response("Prompt required", { status: 400 });
|
|
450
|
+
}
|
|
451
|
+
const taskId = params.taskId ? asString(params.taskId) : void 0;
|
|
452
|
+
const metadata = params.metadata ? asRecord(params.metadata) : void 0;
|
|
453
|
+
const eventStream = sseHandlers.sendTaskSubscribe({
|
|
454
|
+
prompt,
|
|
455
|
+
taskId: _nullishCoalesce(taskId, () => ( void 0)),
|
|
456
|
+
metadata: _nullishCoalesce(metadata, () => ( void 0))
|
|
457
|
+
});
|
|
458
|
+
return createSseResponse(eventStream);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
if (Array.isArray(parsed)) {
|
|
462
|
+
return new Response(
|
|
463
|
+
JSON.stringify(createError(null, -32600, "Batch requests are not supported")),
|
|
464
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
const requestObject = asRecord(parsed);
|
|
468
|
+
if (!requestObject) {
|
|
469
|
+
return new Response(
|
|
470
|
+
JSON.stringify(createError(null, -32600, "Invalid Request")),
|
|
471
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
const hasId = "id" in requestObject;
|
|
475
|
+
const normalizedRequest = {
|
|
476
|
+
jsonrpc: requestObject.jsonrpc,
|
|
477
|
+
id: hasId ? _nullishCoalesce(requestObject.id, () => ( null)) : null,
|
|
478
|
+
method: requestObject.method,
|
|
479
|
+
params: requestObject.params
|
|
480
|
+
};
|
|
481
|
+
if (!hasId) {
|
|
482
|
+
await jsonRpcHandler({ ...normalizedRequest, id: null });
|
|
483
|
+
return new Response(null, { status: 202 });
|
|
484
|
+
}
|
|
485
|
+
const response = await jsonRpcHandler(normalizedRequest);
|
|
486
|
+
return new Response(
|
|
487
|
+
JSON.stringify(response),
|
|
488
|
+
{
|
|
489
|
+
status: response.error ? 400 : 200,
|
|
490
|
+
headers: { "Content-Type": "application/json" }
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
function createSseResponse(eventStream) {
|
|
496
|
+
const encoder = new TextEncoder();
|
|
497
|
+
const readableStream = new ReadableStream({
|
|
498
|
+
async start(controller) {
|
|
499
|
+
try {
|
|
500
|
+
for await (const event of eventStream) {
|
|
501
|
+
const sseData = `event: ${event.type}
|
|
502
|
+
data: ${JSON.stringify(event)}
|
|
503
|
+
|
|
504
|
+
`;
|
|
505
|
+
controller.enqueue(encoder.encode(sseData));
|
|
506
|
+
}
|
|
507
|
+
controller.close();
|
|
508
|
+
} catch (error) {
|
|
509
|
+
const errorEvent = `event: error
|
|
510
|
+
data: ${JSON.stringify({ error: String(error) })}
|
|
511
|
+
|
|
512
|
+
`;
|
|
513
|
+
controller.enqueue(encoder.encode(errorEvent));
|
|
514
|
+
controller.close();
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
return new Response(readableStream, {
|
|
519
|
+
status: 200,
|
|
520
|
+
headers: {
|
|
521
|
+
"Content-Type": "text/event-stream",
|
|
522
|
+
"Cache-Control": "no-cache",
|
|
523
|
+
"Connection": "keep-alive",
|
|
524
|
+
"Access-Control-Allow-Origin": "*",
|
|
525
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
526
|
+
}
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
function createA2ASseHandler(handlers) {
|
|
530
|
+
return (params) => {
|
|
531
|
+
if (!handlers.sendTaskSubscribe) {
|
|
532
|
+
throw new Error("sendTaskSubscribe handler not available");
|
|
533
|
+
}
|
|
534
|
+
return handlers.sendTaskSubscribe(params);
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// src/plugins/a2a-push.ts
|
|
539
|
+
var A2APushNotifier = (_class3 = class _A2APushNotifier {
|
|
540
|
+
__init5() {this.subscriptions = /* @__PURE__ */ new Map()}
|
|
541
|
+
|
|
542
|
+
constructor(fetchImpl = globalThis.fetch) {;_class3.prototype.__init5.call(this);
|
|
543
|
+
if (!fetchImpl) {
|
|
544
|
+
throw new Error("A2APushNotifier requires a fetch implementation");
|
|
545
|
+
}
|
|
546
|
+
this.fetchImpl = fetchImpl;
|
|
547
|
+
}
|
|
548
|
+
static __initStatic() {this.BLOCKED_HEADERS = /* @__PURE__ */ new Set(["host", "authorization", "cookie", "content-type"])}
|
|
549
|
+
static __initStatic2() {this.LOCAL_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]", "0.0.0.0"])}
|
|
550
|
+
subscribe(taskId, config) {
|
|
551
|
+
const parsed = new URL(config.url);
|
|
552
|
+
const isLocal = _A2APushNotifier.LOCAL_HOSTS.has(parsed.hostname) || parsed.hostname.startsWith("127.");
|
|
553
|
+
if (parsed.protocol !== "https:" && !isLocal) {
|
|
554
|
+
throw new Error("Push notification URL must use HTTPS");
|
|
555
|
+
}
|
|
556
|
+
if (parsed.protocol !== "https:" && isLocal && parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1") {
|
|
557
|
+
throw new Error("Push notification URL must use HTTPS for non-standard local addresses");
|
|
558
|
+
}
|
|
559
|
+
if (config.headers) {
|
|
560
|
+
for (const key of Object.keys(config.headers)) {
|
|
561
|
+
if (_A2APushNotifier.BLOCKED_HEADERS.has(key.toLowerCase())) {
|
|
562
|
+
throw new Error(`Header "${key}" is not allowed in push notifications`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
const existing = _nullishCoalesce(this.subscriptions.get(taskId), () => ( []));
|
|
567
|
+
existing.push(config);
|
|
568
|
+
this.subscriptions.set(taskId, existing);
|
|
569
|
+
}
|
|
570
|
+
unsubscribe(taskId, url) {
|
|
571
|
+
const existing = _nullishCoalesce(this.subscriptions.get(taskId), () => ( []));
|
|
572
|
+
const filtered = existing.filter((config) => config.url !== url);
|
|
573
|
+
if (filtered.length === 0) {
|
|
574
|
+
this.subscriptions.delete(taskId);
|
|
575
|
+
} else {
|
|
576
|
+
this.subscriptions.set(taskId, filtered);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async notify(event) {
|
|
580
|
+
const configs = _nullishCoalesce(this.subscriptions.get(event.taskId), () => ( []));
|
|
581
|
+
const promises = configs.map(async (config) => {
|
|
582
|
+
if (config.events && !config.events.includes(event.type)) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
try {
|
|
586
|
+
await this.fetchImpl(config.url, {
|
|
587
|
+
method: "POST",
|
|
588
|
+
headers: {
|
|
589
|
+
"Content-Type": "application/json",
|
|
590
|
+
...config.headers
|
|
591
|
+
},
|
|
592
|
+
body: JSON.stringify(event)
|
|
593
|
+
});
|
|
594
|
+
} catch (error) {
|
|
595
|
+
console.warn(`Push notification failed for ${config.url}:`, error);
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
await Promise.allSettled(promises);
|
|
599
|
+
}
|
|
600
|
+
cleanup(taskId) {
|
|
601
|
+
this.subscriptions.delete(taskId);
|
|
602
|
+
}
|
|
603
|
+
}, _class3.__initStatic(), _class3.__initStatic2(), _class3);
|
|
604
|
+
|
|
605
|
+
// src/plugins/a2a-durable-task-queue.ts
|
|
606
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
607
|
+
maxAttempts: 3,
|
|
608
|
+
initialBackoffMs: 250,
|
|
609
|
+
backoffMultiplier: 2,
|
|
610
|
+
maxBackoffMs: 3e4,
|
|
611
|
+
jitterRatio: 0
|
|
612
|
+
};
|
|
613
|
+
var DEFAULT_QUEUE_CONFIG = {
|
|
614
|
+
leaseDurationMs: 6e4,
|
|
615
|
+
retentionMs: 36e5,
|
|
616
|
+
maxTerminalTasks: 1e3,
|
|
617
|
+
retry: DEFAULT_RETRY_CONFIG
|
|
618
|
+
};
|
|
619
|
+
function cloneTask(task) {
|
|
620
|
+
return {
|
|
621
|
+
...task,
|
|
622
|
+
metadata: task.metadata ? { ...task.metadata } : void 0
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
function isTerminalStatus(status) {
|
|
626
|
+
return status === "completed" || status === "failed" || status === "cancelled";
|
|
627
|
+
}
|
|
628
|
+
var A2ADurableTaskQueue = (_class4 = class {
|
|
629
|
+
__init6() {this.entries = /* @__PURE__ */ new Map()}
|
|
630
|
+
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
constructor(config = {}) {;_class4.prototype.__init6.call(this);
|
|
634
|
+
const retry = {
|
|
635
|
+
...DEFAULT_RETRY_CONFIG,
|
|
636
|
+
..._nullishCoalesce(config.retry, () => ( {}))
|
|
637
|
+
};
|
|
638
|
+
this.config = {
|
|
639
|
+
leaseDurationMs: _nullishCoalesce(config.leaseDurationMs, () => ( DEFAULT_QUEUE_CONFIG.leaseDurationMs)),
|
|
640
|
+
retentionMs: _nullishCoalesce(config.retentionMs, () => ( DEFAULT_QUEUE_CONFIG.retentionMs)),
|
|
641
|
+
maxTerminalTasks: _nullishCoalesce(config.maxTerminalTasks, () => ( DEFAULT_QUEUE_CONFIG.maxTerminalTasks)),
|
|
642
|
+
retry,
|
|
643
|
+
now: config.now,
|
|
644
|
+
idFactory: config.idFactory
|
|
645
|
+
};
|
|
646
|
+
this.now = _nullishCoalesce(config.now, () => ( (() => Date.now())));
|
|
647
|
+
this.idFactory = _nullishCoalesce(config.idFactory, () => ( (() => crypto.randomUUID())));
|
|
648
|
+
}
|
|
649
|
+
get size() {
|
|
650
|
+
return this.entries.size;
|
|
651
|
+
}
|
|
652
|
+
enqueue(task, options = {}) {
|
|
653
|
+
if (this.entries.has(task.id)) {
|
|
654
|
+
throw new Error(`Task already exists: ${task.id}`);
|
|
655
|
+
}
|
|
656
|
+
const now = this.now();
|
|
657
|
+
const maxAttempts = Math.max(1, _nullishCoalesce(options.maxAttempts, () => ( this.config.retry.maxAttempts)));
|
|
658
|
+
const normalizedTask = {
|
|
659
|
+
...cloneTask(task),
|
|
660
|
+
status: "queued",
|
|
661
|
+
updatedAt: new Date(now).toISOString(),
|
|
662
|
+
completedAt: void 0
|
|
663
|
+
};
|
|
664
|
+
this.entries.set(task.id, {
|
|
665
|
+
task: normalizedTask,
|
|
666
|
+
attempts: 0,
|
|
667
|
+
maxAttempts,
|
|
668
|
+
nextAttemptAt: now
|
|
669
|
+
});
|
|
670
|
+
return cloneTask(normalizedTask);
|
|
671
|
+
}
|
|
672
|
+
get(taskId) {
|
|
673
|
+
this.resolveExpiredLeases();
|
|
674
|
+
const entry = this.entries.get(taskId);
|
|
675
|
+
if (!entry) return null;
|
|
676
|
+
return cloneTask(entry.task);
|
|
677
|
+
}
|
|
678
|
+
list() {
|
|
679
|
+
this.resolveExpiredLeases();
|
|
680
|
+
return [...this.entries.values()].map((entry) => cloneTask(entry.task));
|
|
681
|
+
}
|
|
682
|
+
acquire(taskId, workerId) {
|
|
683
|
+
this.resolveExpiredLeases();
|
|
684
|
+
const entry = this.entries.get(taskId);
|
|
685
|
+
if (!entry) return null;
|
|
686
|
+
const now = this.now();
|
|
687
|
+
if (entry.task.status !== "queued") return null;
|
|
688
|
+
if (entry.nextAttemptAt > now) return null;
|
|
689
|
+
entry.attempts += 1;
|
|
690
|
+
const leaseId = this.idFactory();
|
|
691
|
+
entry.lease = {
|
|
692
|
+
leaseId,
|
|
693
|
+
workerId,
|
|
694
|
+
expiresAt: now + this.config.leaseDurationMs
|
|
695
|
+
};
|
|
696
|
+
entry.task.status = "running";
|
|
697
|
+
entry.task.updatedAt = new Date(now).toISOString();
|
|
698
|
+
return {
|
|
699
|
+
taskId,
|
|
700
|
+
leaseId,
|
|
701
|
+
workerId,
|
|
702
|
+
expiresAt: new Date(entry.lease.expiresAt).toISOString(),
|
|
703
|
+
attempt: entry.attempts,
|
|
704
|
+
maxAttempts: entry.maxAttempts
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
extendLease(taskId, leaseId, leaseDurationMs) {
|
|
708
|
+
const entry = this.entries.get(taskId);
|
|
709
|
+
if (!entry || !entry.lease) return false;
|
|
710
|
+
if (entry.lease.leaseId !== leaseId) return false;
|
|
711
|
+
const duration = Math.max(1, _nullishCoalesce(leaseDurationMs, () => ( this.config.leaseDurationMs)));
|
|
712
|
+
entry.lease.expiresAt = this.now() + duration;
|
|
713
|
+
return true;
|
|
714
|
+
}
|
|
715
|
+
complete(taskId, output, leaseId) {
|
|
716
|
+
const entry = this.entries.get(taskId);
|
|
717
|
+
if (!entry) return null;
|
|
718
|
+
if (isTerminalStatus(entry.task.status)) {
|
|
719
|
+
return cloneTask(entry.task);
|
|
720
|
+
}
|
|
721
|
+
if (!this.validateLease(entry, leaseId)) {
|
|
722
|
+
return null;
|
|
723
|
+
}
|
|
724
|
+
const nowIso = new Date(this.now()).toISOString();
|
|
725
|
+
entry.task.status = "completed";
|
|
726
|
+
entry.task.output = output;
|
|
727
|
+
entry.task.error = void 0;
|
|
728
|
+
entry.task.updatedAt = nowIso;
|
|
729
|
+
entry.task.completedAt = nowIso;
|
|
730
|
+
entry.lease = void 0;
|
|
731
|
+
entry.finishedAt = this.now();
|
|
732
|
+
return cloneTask(entry.task);
|
|
733
|
+
}
|
|
734
|
+
fail(taskId, error, leaseId) {
|
|
735
|
+
const entry = this.entries.get(taskId);
|
|
736
|
+
if (!entry) return null;
|
|
737
|
+
if (isTerminalStatus(entry.task.status)) {
|
|
738
|
+
return {
|
|
739
|
+
task: cloneTask(entry.task),
|
|
740
|
+
willRetry: false,
|
|
741
|
+
retryDelayMs: 0,
|
|
742
|
+
attempts: entry.attempts,
|
|
743
|
+
maxAttempts: entry.maxAttempts
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
if (!this.validateLease(entry, leaseId)) {
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
const now = this.now();
|
|
750
|
+
const nowIso = new Date(now).toISOString();
|
|
751
|
+
entry.task.error = error;
|
|
752
|
+
entry.task.updatedAt = nowIso;
|
|
753
|
+
entry.lease = void 0;
|
|
754
|
+
if (entry.attempts < entry.maxAttempts) {
|
|
755
|
+
const retryDelayMs = this.computeBackoffDelay(entry.attempts);
|
|
756
|
+
entry.task.status = "queued";
|
|
757
|
+
entry.task.completedAt = void 0;
|
|
758
|
+
entry.nextAttemptAt = now + retryDelayMs;
|
|
759
|
+
return {
|
|
760
|
+
task: cloneTask(entry.task),
|
|
761
|
+
willRetry: true,
|
|
762
|
+
retryDelayMs,
|
|
763
|
+
attempts: entry.attempts,
|
|
764
|
+
maxAttempts: entry.maxAttempts
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
entry.task.status = "failed";
|
|
768
|
+
entry.task.completedAt = nowIso;
|
|
769
|
+
entry.finishedAt = now;
|
|
770
|
+
return {
|
|
771
|
+
task: cloneTask(entry.task),
|
|
772
|
+
willRetry: false,
|
|
773
|
+
retryDelayMs: 0,
|
|
774
|
+
attempts: entry.attempts,
|
|
775
|
+
maxAttempts: entry.maxAttempts
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
cancel(taskId) {
|
|
779
|
+
const entry = this.entries.get(taskId);
|
|
780
|
+
if (!entry) return null;
|
|
781
|
+
if (isTerminalStatus(entry.task.status)) {
|
|
782
|
+
return cloneTask(entry.task);
|
|
783
|
+
}
|
|
784
|
+
const nowIso = new Date(this.now()).toISOString();
|
|
785
|
+
entry.task.status = "cancelled";
|
|
786
|
+
entry.task.updatedAt = nowIso;
|
|
787
|
+
entry.task.completedAt = nowIso;
|
|
788
|
+
entry.lease = void 0;
|
|
789
|
+
entry.finishedAt = this.now();
|
|
790
|
+
return cloneTask(entry.task);
|
|
791
|
+
}
|
|
792
|
+
evictExpired() {
|
|
793
|
+
const now = this.now();
|
|
794
|
+
this.resolveExpiredLeases();
|
|
795
|
+
const terminals = [];
|
|
796
|
+
for (const [taskId, entry] of this.entries) {
|
|
797
|
+
if (!isTerminalStatus(entry.task.status)) continue;
|
|
798
|
+
const finishedAt = _nullishCoalesce(entry.finishedAt, () => ( Date.parse(entry.task.updatedAt)));
|
|
799
|
+
if (now - finishedAt > this.config.retentionMs) {
|
|
800
|
+
this.entries.delete(taskId);
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
terminals.push({ taskId, finishedAt });
|
|
804
|
+
}
|
|
805
|
+
if (terminals.length <= this.config.maxTerminalTasks) return;
|
|
806
|
+
terminals.sort((a, b) => a.finishedAt - b.finishedAt).slice(0, terminals.length - this.config.maxTerminalTasks).forEach(({ taskId }) => this.entries.delete(taskId));
|
|
807
|
+
}
|
|
808
|
+
snapshot() {
|
|
809
|
+
this.resolveExpiredLeases();
|
|
810
|
+
return {
|
|
811
|
+
version: 1,
|
|
812
|
+
entries: [...this.entries.values()].map((entry) => ({
|
|
813
|
+
task: cloneTask(entry.task),
|
|
814
|
+
attempts: entry.attempts,
|
|
815
|
+
maxAttempts: entry.maxAttempts,
|
|
816
|
+
nextAttemptAt: entry.nextAttemptAt,
|
|
817
|
+
finishedAt: entry.finishedAt,
|
|
818
|
+
lease: entry.lease ? {
|
|
819
|
+
leaseId: entry.lease.leaseId,
|
|
820
|
+
workerId: entry.lease.workerId,
|
|
821
|
+
expiresAt: entry.lease.expiresAt
|
|
822
|
+
} : void 0
|
|
823
|
+
}))
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
hydrate(snapshot) {
|
|
827
|
+
this.entries.clear();
|
|
828
|
+
if (!snapshot || snapshot.version !== 1) return;
|
|
829
|
+
for (const item of snapshot.entries) {
|
|
830
|
+
this.entries.set(item.task.id, {
|
|
831
|
+
task: cloneTask(item.task),
|
|
832
|
+
attempts: item.attempts,
|
|
833
|
+
maxAttempts: item.maxAttempts,
|
|
834
|
+
nextAttemptAt: item.nextAttemptAt,
|
|
835
|
+
finishedAt: item.finishedAt,
|
|
836
|
+
lease: item.lease ? {
|
|
837
|
+
leaseId: item.lease.leaseId,
|
|
838
|
+
workerId: item.lease.workerId,
|
|
839
|
+
expiresAt: item.lease.expiresAt
|
|
840
|
+
} : void 0
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
this.resolveExpiredLeases();
|
|
844
|
+
}
|
|
845
|
+
validateLease(entry, leaseId) {
|
|
846
|
+
if (!entry.lease) return true;
|
|
847
|
+
if (!leaseId) return false;
|
|
848
|
+
if (entry.lease.leaseId !== leaseId) return false;
|
|
849
|
+
if (entry.lease.expiresAt <= this.now()) return false;
|
|
850
|
+
return true;
|
|
851
|
+
}
|
|
852
|
+
resolveExpiredLeases() {
|
|
853
|
+
const now = this.now();
|
|
854
|
+
for (const entry of this.entries.values()) {
|
|
855
|
+
if (!entry.lease) continue;
|
|
856
|
+
if (entry.lease.expiresAt > now) continue;
|
|
857
|
+
if (entry.task.status !== "running") {
|
|
858
|
+
entry.lease = void 0;
|
|
859
|
+
continue;
|
|
860
|
+
}
|
|
861
|
+
entry.lease = void 0;
|
|
862
|
+
entry.task.error = "Task lease expired before completion";
|
|
863
|
+
entry.task.updatedAt = new Date(now).toISOString();
|
|
864
|
+
if (entry.attempts < entry.maxAttempts) {
|
|
865
|
+
const retryDelayMs = this.computeBackoffDelay(entry.attempts);
|
|
866
|
+
entry.task.status = "queued";
|
|
867
|
+
entry.task.completedAt = void 0;
|
|
868
|
+
entry.nextAttemptAt = now + retryDelayMs;
|
|
869
|
+
} else {
|
|
870
|
+
entry.task.status = "failed";
|
|
871
|
+
entry.task.completedAt = new Date(now).toISOString();
|
|
872
|
+
entry.finishedAt = now;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
computeBackoffDelay(attempt) {
|
|
877
|
+
const base = Math.max(1, this.config.retry.initialBackoffMs);
|
|
878
|
+
const multiplier = Math.max(1, this.config.retry.backoffMultiplier);
|
|
879
|
+
const capped = Math.min(
|
|
880
|
+
this.config.retry.maxBackoffMs,
|
|
881
|
+
Math.round(base * Math.pow(multiplier, Math.max(0, attempt - 1)))
|
|
882
|
+
);
|
|
883
|
+
const jitterRatio = Math.max(0, Math.min(1, this.config.retry.jitterRatio));
|
|
884
|
+
if (jitterRatio === 0) return capped;
|
|
885
|
+
const jitterMax = Math.round(capped * jitterRatio);
|
|
886
|
+
const jitter = Math.floor(Math.random() * (jitterMax + 1));
|
|
887
|
+
return Math.min(this.config.retry.maxBackoffMs, capped + jitter);
|
|
888
|
+
}
|
|
889
|
+
}, _class4);
|
|
890
|
+
|
|
891
|
+
// src/plugins/a2a.plugin.ts
|
|
892
|
+
var DEFAULT_REQUEST_TIMEOUT_MS = 3e4;
|
|
893
|
+
var DEFAULT_RETRY_CONFIG2 = {
|
|
894
|
+
maxAttempts: 3,
|
|
895
|
+
initialBackoffMs: 250,
|
|
896
|
+
backoffMultiplier: 2,
|
|
897
|
+
maxBackoffMs: 3e4,
|
|
898
|
+
jitterRatio: 0
|
|
899
|
+
};
|
|
900
|
+
var A2A_CALL_SCHEMA = _zod.z.object({
|
|
901
|
+
endpoint: _zod.z.string().url(),
|
|
902
|
+
method: _zod.z.enum(["tasks/send", "tasks/get", "tasks/list", "tasks/cancel", "agent/card", "health"]).default("tasks/send"),
|
|
903
|
+
prompt: _zod.z.string().optional(),
|
|
904
|
+
taskId: _zod.z.string().optional(),
|
|
905
|
+
params: _zod.z.record(_zod.z.string(), _zod.z.unknown()).optional()
|
|
906
|
+
});
|
|
907
|
+
var A2A_DELEGATE_SCHEMA = _zod.z.object({
|
|
908
|
+
prompt: _zod.z.string(),
|
|
909
|
+
requiredSkills: _zod.z.array(_zod.z.string()).default([])
|
|
910
|
+
});
|
|
911
|
+
var A2A_DISCOVER_SCHEMA = _zod.z.object({
|
|
912
|
+
endpoint: _zod.z.string().url()
|
|
913
|
+
});
|
|
914
|
+
var A2A_SUBSCRIBE_SCHEMA = _zod.z.object({
|
|
915
|
+
endpoint: _zod.z.string().url(),
|
|
916
|
+
prompt: _zod.z.string(),
|
|
917
|
+
taskId: _zod.z.string().optional()
|
|
918
|
+
});
|
|
919
|
+
var A2APlugin = (_class5 = class _A2APlugin {
|
|
920
|
+
__init7() {this.name = "a2a"}
|
|
921
|
+
__init8() {this.version = "1.0.0"}
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
__init9() {this.taskEventListeners = /* @__PURE__ */ new Set()}
|
|
931
|
+
static __initStatic3() {this.QUEUE_SNAPSHOT_KEY = "a2a:durable-task-queue:v1"}
|
|
932
|
+
static __initStatic4() {this.DEFAULT_MAX_TERMINAL_TASKS = 1e3}
|
|
933
|
+
static __initStatic5() {this.DEFAULT_RETENTION_MS = 36e5}
|
|
934
|
+
// 1 hour
|
|
935
|
+
|
|
936
|
+
__init10() {this.queueHydrated = false}
|
|
937
|
+
__init11() {this.queueHydrationPromise = null}
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
__init12() {this.hooks = {
|
|
941
|
+
beforeRun: async (ctx, _params) => {
|
|
942
|
+
this.latestCtx = ctx;
|
|
943
|
+
if (this.isQueueManagedRun(ctx)) return;
|
|
944
|
+
const taskId = this.getTaskIdFromContext(ctx);
|
|
945
|
+
if (!taskId) return;
|
|
946
|
+
this.markTaskRunning(taskId, this.getLeaseIdFromContext(ctx));
|
|
947
|
+
},
|
|
948
|
+
afterRun: async (ctx, params) => {
|
|
949
|
+
this.latestCtx = ctx;
|
|
950
|
+
if (this.isQueueManagedRun(ctx)) return;
|
|
951
|
+
const taskId = this.getTaskIdFromContext(ctx);
|
|
952
|
+
if (!taskId) return;
|
|
953
|
+
this.markTaskCompleted(taskId, params.result.text, this.getLeaseIdFromContext(ctx));
|
|
954
|
+
},
|
|
955
|
+
onError: async (ctx, params) => {
|
|
956
|
+
if (this.isQueueManagedRun(ctx)) return;
|
|
957
|
+
const taskId = this.getTaskIdFromContext(ctx);
|
|
958
|
+
if (!taskId) return;
|
|
959
|
+
this.markTaskFailed(taskId, params.error, this.getLeaseIdFromContext(ctx));
|
|
960
|
+
}
|
|
961
|
+
}}
|
|
962
|
+
constructor(options = {}) {;_class5.prototype.__init7.call(this);_class5.prototype.__init8.call(this);_class5.prototype.__init9.call(this);_class5.prototype.__init10.call(this);_class5.prototype.__init11.call(this);_class5.prototype.__init12.call(this);
|
|
963
|
+
const fetchImpl = _nullishCoalesce(options.fetch, () => ( globalThis.fetch));
|
|
964
|
+
if (!fetchImpl) {
|
|
965
|
+
throw new Error("A2APlugin requires a fetch implementation");
|
|
966
|
+
}
|
|
967
|
+
this.fetchImpl = fetchImpl;
|
|
968
|
+
this.requestTimeoutMs = _nullishCoalesce(options.requestTimeoutMs, () => ( DEFAULT_REQUEST_TIMEOUT_MS));
|
|
969
|
+
this.agentCardProvider = options.agentCardProvider;
|
|
970
|
+
this.persistQueueStateEnabled = _nullishCoalesce(options.persistQueueState, () => ( true));
|
|
971
|
+
this.delegationManager = new (0, _chunkDAMT2CXWcjs.A2ADelegationManager)(fetchImpl);
|
|
972
|
+
this.pushNotifier = new A2APushNotifier(fetchImpl);
|
|
973
|
+
const normalizedRetry = options.retry ? {
|
|
974
|
+
maxAttempts: _nullishCoalesce(options.retry.maxAttempts, () => ( DEFAULT_RETRY_CONFIG2.maxAttempts)),
|
|
975
|
+
initialBackoffMs: _nullishCoalesce(options.retry.initialBackoffMs, () => ( DEFAULT_RETRY_CONFIG2.initialBackoffMs)),
|
|
976
|
+
backoffMultiplier: _nullishCoalesce(options.retry.backoffMultiplier, () => ( DEFAULT_RETRY_CONFIG2.backoffMultiplier)),
|
|
977
|
+
maxBackoffMs: _nullishCoalesce(options.retry.maxBackoffMs, () => ( DEFAULT_RETRY_CONFIG2.maxBackoffMs)),
|
|
978
|
+
jitterRatio: _nullishCoalesce(options.retry.jitterRatio, () => ( DEFAULT_RETRY_CONFIG2.jitterRatio))
|
|
979
|
+
} : void 0;
|
|
980
|
+
this.taskQueue = _nullishCoalesce(options.taskQueue, () => ( new A2ADurableTaskQueue({
|
|
981
|
+
leaseDurationMs: _optionalChain([options, 'access', _21 => _21.queue, 'optionalAccess', _22 => _22.leaseDurationMs]),
|
|
982
|
+
retentionMs: _nullishCoalesce(_optionalChain([options, 'access', _23 => _23.queue, 'optionalAccess', _24 => _24.retentionMs]), () => ( _A2APlugin.DEFAULT_RETENTION_MS)),
|
|
983
|
+
maxTerminalTasks: _nullishCoalesce(_optionalChain([options, 'access', _25 => _25.queue, 'optionalAccess', _26 => _26.maxTerminalTasks]), () => ( _A2APlugin.DEFAULT_MAX_TERMINAL_TASKS)),
|
|
984
|
+
retry: normalizedRetry
|
|
985
|
+
})));
|
|
986
|
+
this.evictionTimer = setInterval(() => this.evictStaleTasks(), 6e4);
|
|
987
|
+
this.tools = {
|
|
988
|
+
"a2a:call": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
989
|
+
description: "Call an external A2A-compatible JSON-RPC endpoint.",
|
|
990
|
+
inputSchema: A2A_CALL_SCHEMA,
|
|
991
|
+
execute: async (input) => {
|
|
992
|
+
const args = A2A_CALL_SCHEMA.parse(_nullishCoalesce(input, () => ( {})));
|
|
993
|
+
const params = this.normalizeCallParams(args);
|
|
994
|
+
const payload = {
|
|
995
|
+
jsonrpc: "2.0",
|
|
996
|
+
id: crypto.randomUUID(),
|
|
997
|
+
method: args.method,
|
|
998
|
+
params
|
|
999
|
+
};
|
|
1000
|
+
const response = await this.callRemoteEndpoint(args.endpoint, payload);
|
|
1001
|
+
if (response.error) {
|
|
1002
|
+
throw new Error(`[A2A ${response.error.code}] ${response.error.message}`);
|
|
1003
|
+
}
|
|
1004
|
+
return response.result;
|
|
1005
|
+
}
|
|
1006
|
+
}),
|
|
1007
|
+
"a2a:delegate": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1008
|
+
description: "Delegate a task to a registered agent based on required skills.",
|
|
1009
|
+
inputSchema: A2A_DELEGATE_SCHEMA,
|
|
1010
|
+
execute: async (input) => {
|
|
1011
|
+
const args = A2A_DELEGATE_SCHEMA.parse(_nullishCoalesce(input, () => ( {})));
|
|
1012
|
+
return await this.delegationManager.delegate(args.prompt, args.requiredSkills, this.fetchImpl);
|
|
1013
|
+
}
|
|
1014
|
+
}),
|
|
1015
|
+
"a2a:discover": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1016
|
+
description: "Discover agent capabilities at an A2A endpoint.",
|
|
1017
|
+
inputSchema: A2A_DISCOVER_SCHEMA,
|
|
1018
|
+
execute: async (input) => {
|
|
1019
|
+
const args = A2A_DISCOVER_SCHEMA.parse(_nullishCoalesce(input, () => ( {})));
|
|
1020
|
+
return await this.discoverAgent(args.endpoint);
|
|
1021
|
+
}
|
|
1022
|
+
}),
|
|
1023
|
+
"a2a:subscribe": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1024
|
+
description: "Subscribe to task status updates via Server-Sent Events.",
|
|
1025
|
+
inputSchema: A2A_SUBSCRIBE_SCHEMA,
|
|
1026
|
+
execute: async (input) => {
|
|
1027
|
+
const args = A2A_SUBSCRIBE_SCHEMA.parse(_nullishCoalesce(input, () => ( {})));
|
|
1028
|
+
return await this.subscribeToTask(args.endpoint, args.prompt, args.taskId);
|
|
1029
|
+
}
|
|
1030
|
+
})
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
setup(ctx) {
|
|
1034
|
+
this.setupCtx = ctx;
|
|
1035
|
+
void this.ensureQueueHydrated();
|
|
1036
|
+
}
|
|
1037
|
+
dispose() {
|
|
1038
|
+
if (this.evictionTimer) {
|
|
1039
|
+
clearInterval(this.evictionTimer);
|
|
1040
|
+
this.evictionTimer = void 0;
|
|
1041
|
+
}
|
|
1042
|
+
void this.persistQueueState();
|
|
1043
|
+
}
|
|
1044
|
+
createJsonRpcHandler(agent) {
|
|
1045
|
+
const plugin = this;
|
|
1046
|
+
const sendTaskSubscribe = async function* (params) {
|
|
1047
|
+
await plugin.ensureQueueHydrated();
|
|
1048
|
+
const taskId = _nullishCoalesce(params.taskId, () => ( crypto.randomUUID()));
|
|
1049
|
+
const eventQueue = [];
|
|
1050
|
+
let completed = false;
|
|
1051
|
+
let pending;
|
|
1052
|
+
function createDeferred() {
|
|
1053
|
+
let resolve;
|
|
1054
|
+
const promise = new Promise((r) => {
|
|
1055
|
+
resolve = r;
|
|
1056
|
+
});
|
|
1057
|
+
return { promise, resolve };
|
|
1058
|
+
}
|
|
1059
|
+
pending = createDeferred();
|
|
1060
|
+
const eventListener = (event) => {
|
|
1061
|
+
if (event.taskId === taskId) {
|
|
1062
|
+
eventQueue.push(event);
|
|
1063
|
+
if (event.type === "task:completed" || event.type === "task:failed" || event.type === "task:cancelled") {
|
|
1064
|
+
completed = true;
|
|
1065
|
+
}
|
|
1066
|
+
pending.resolve();
|
|
1067
|
+
pending = createDeferred();
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
plugin.taskEventListeners.add(eventListener);
|
|
1071
|
+
plugin.queueTask(taskId, params.prompt, params.metadata);
|
|
1072
|
+
try {
|
|
1073
|
+
const runPromise = plugin.executeTaskWithRetry(agent, taskId, params);
|
|
1074
|
+
let lastEventIndex = 0;
|
|
1075
|
+
while (!completed) {
|
|
1076
|
+
if (eventQueue.length <= lastEventIndex) {
|
|
1077
|
+
await pending.promise;
|
|
1078
|
+
}
|
|
1079
|
+
for (let i = lastEventIndex; i < eventQueue.length; i++) {
|
|
1080
|
+
yield eventQueue[i];
|
|
1081
|
+
}
|
|
1082
|
+
lastEventIndex = eventQueue.length;
|
|
1083
|
+
}
|
|
1084
|
+
await runPromise;
|
|
1085
|
+
if (eventQueue.length > lastEventIndex) {
|
|
1086
|
+
for (let i = lastEventIndex; i < eventQueue.length; i++) {
|
|
1087
|
+
yield eventQueue[i];
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
} finally {
|
|
1091
|
+
plugin.taskEventListeners.delete(eventListener);
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
const jsonRpcHandler = createA2AJsonRpcHandler({
|
|
1095
|
+
sendTask: async (params) => {
|
|
1096
|
+
await plugin.ensureQueueHydrated();
|
|
1097
|
+
const taskId = _nullishCoalesce(params.taskId, () => ( crypto.randomUUID()));
|
|
1098
|
+
plugin.queueTask(taskId, params.prompt, params.metadata);
|
|
1099
|
+
await plugin.executeTaskWithRetry(agent, taskId, params);
|
|
1100
|
+
return plugin.cloneTask(taskId);
|
|
1101
|
+
},
|
|
1102
|
+
sendTaskSubscribe,
|
|
1103
|
+
getTask: async (taskId) => {
|
|
1104
|
+
await plugin.ensureQueueHydrated();
|
|
1105
|
+
return plugin.getTask(taskId);
|
|
1106
|
+
},
|
|
1107
|
+
listTasks: async () => {
|
|
1108
|
+
await plugin.ensureQueueHydrated();
|
|
1109
|
+
return plugin.listTasks();
|
|
1110
|
+
},
|
|
1111
|
+
cancelTask: async (taskId) => {
|
|
1112
|
+
await plugin.ensureQueueHydrated();
|
|
1113
|
+
const previous = plugin.taskQueue.get(taskId);
|
|
1114
|
+
if (!previous) return null;
|
|
1115
|
+
const cancelled = plugin.taskQueue.cancel(taskId);
|
|
1116
|
+
if (!cancelled) return null;
|
|
1117
|
+
if (previous.status !== "cancelled" && previous.status !== "completed" && previous.status !== "failed") {
|
|
1118
|
+
plugin.emitTaskEvent("task:cancelled", taskId);
|
|
1119
|
+
}
|
|
1120
|
+
void plugin.persistQueueState();
|
|
1121
|
+
return cancelled;
|
|
1122
|
+
},
|
|
1123
|
+
getAgentCard: async () => {
|
|
1124
|
+
return plugin.resolveAgentCard();
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
jsonRpcHandler.sendTaskSubscribe = sendTaskSubscribe;
|
|
1128
|
+
return jsonRpcHandler;
|
|
1129
|
+
}
|
|
1130
|
+
createHttpHandler(agent) {
|
|
1131
|
+
const handler = this.createJsonRpcHandler(agent);
|
|
1132
|
+
return createA2AHttpHandler(handler, {
|
|
1133
|
+
sendTaskSubscribe: async function* (params) {
|
|
1134
|
+
for await (const event of handler.sendTaskSubscribe(params)) {
|
|
1135
|
+
yield event;
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
});
|
|
1139
|
+
}
|
|
1140
|
+
getTask(taskId) {
|
|
1141
|
+
return this.taskQueue.get(taskId);
|
|
1142
|
+
}
|
|
1143
|
+
listTasks() {
|
|
1144
|
+
return this.taskQueue.list();
|
|
1145
|
+
}
|
|
1146
|
+
// Delegation methods
|
|
1147
|
+
registerAgent(agent) {
|
|
1148
|
+
this.delegationManager.register(agent);
|
|
1149
|
+
}
|
|
1150
|
+
unregisterAgent(name) {
|
|
1151
|
+
this.delegationManager.unregister(name);
|
|
1152
|
+
}
|
|
1153
|
+
listAgents() {
|
|
1154
|
+
return this.delegationManager.listAgents();
|
|
1155
|
+
}
|
|
1156
|
+
async delegateTask(prompt, requiredSkills) {
|
|
1157
|
+
return await this.delegationManager.delegate(prompt, requiredSkills, this.fetchImpl);
|
|
1158
|
+
}
|
|
1159
|
+
// Push notification methods
|
|
1160
|
+
subscribeToTaskNotifications(taskId, config) {
|
|
1161
|
+
this.pushNotifier.subscribe(taskId, config);
|
|
1162
|
+
}
|
|
1163
|
+
unsubscribeFromTaskNotifications(taskId, url) {
|
|
1164
|
+
this.pushNotifier.unsubscribe(taskId, url);
|
|
1165
|
+
}
|
|
1166
|
+
normalizeCallParams(args) {
|
|
1167
|
+
if (args.params) {
|
|
1168
|
+
return {
|
|
1169
|
+
...args.params,
|
|
1170
|
+
...args.prompt !== void 0 ? { prompt: args.prompt } : {},
|
|
1171
|
+
...args.taskId !== void 0 ? { taskId: args.taskId } : {}
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
if (args.method === "tasks/send") {
|
|
1175
|
+
if (!args.prompt) {
|
|
1176
|
+
throw new Error("a2a:call requires `prompt` for tasks/send requests");
|
|
1177
|
+
}
|
|
1178
|
+
return {
|
|
1179
|
+
prompt: args.prompt,
|
|
1180
|
+
...args.taskId !== void 0 ? { taskId: args.taskId } : {}
|
|
1181
|
+
};
|
|
1182
|
+
}
|
|
1183
|
+
if (args.method === "tasks/get" || args.method === "tasks/cancel") {
|
|
1184
|
+
if (!args.taskId) {
|
|
1185
|
+
throw new Error(`a2a:call requires \`taskId\` for ${args.method}`);
|
|
1186
|
+
}
|
|
1187
|
+
return { taskId: args.taskId };
|
|
1188
|
+
}
|
|
1189
|
+
return {};
|
|
1190
|
+
}
|
|
1191
|
+
async callRemoteEndpoint(endpoint, payload) {
|
|
1192
|
+
const controller = new AbortController();
|
|
1193
|
+
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
1194
|
+
try {
|
|
1195
|
+
const response = await this.fetchImpl(endpoint, {
|
|
1196
|
+
method: "POST",
|
|
1197
|
+
headers: { "Content-Type": "application/json" },
|
|
1198
|
+
body: JSON.stringify(payload),
|
|
1199
|
+
signal: controller.signal
|
|
1200
|
+
});
|
|
1201
|
+
if (!response.ok) {
|
|
1202
|
+
throw new Error(`A2A endpoint returned HTTP ${response.status}`);
|
|
1203
|
+
}
|
|
1204
|
+
return await response.json();
|
|
1205
|
+
} finally {
|
|
1206
|
+
clearTimeout(timer);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
queueTask(taskId, prompt, metadata) {
|
|
1210
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1211
|
+
this.taskQueue.enqueue({
|
|
1212
|
+
id: taskId,
|
|
1213
|
+
status: "queued",
|
|
1214
|
+
prompt,
|
|
1215
|
+
metadata,
|
|
1216
|
+
createdAt: now,
|
|
1217
|
+
updatedAt: now
|
|
1218
|
+
});
|
|
1219
|
+
this.emitTaskEvent("task:queued", taskId);
|
|
1220
|
+
void this.persistQueueState();
|
|
1221
|
+
}
|
|
1222
|
+
markTaskRunning(taskId, _leaseId) {
|
|
1223
|
+
const lease = this.taskQueue.acquire(taskId, this.createWorkerId(taskId));
|
|
1224
|
+
if (!lease) return null;
|
|
1225
|
+
this.emitTaskEvent("task:running", taskId);
|
|
1226
|
+
void this.persistQueueState();
|
|
1227
|
+
return lease;
|
|
1228
|
+
}
|
|
1229
|
+
markTaskCompleted(taskId, output, leaseId) {
|
|
1230
|
+
const before = this.taskQueue.get(taskId);
|
|
1231
|
+
const completed = this.taskQueue.complete(taskId, output, leaseId);
|
|
1232
|
+
if (!completed) return;
|
|
1233
|
+
if (_optionalChain([before, 'optionalAccess', _27 => _27.status]) !== "completed") {
|
|
1234
|
+
this.emitTaskEvent("task:completed", taskId);
|
|
1235
|
+
}
|
|
1236
|
+
void this.persistQueueState();
|
|
1237
|
+
}
|
|
1238
|
+
markTaskFailed(taskId, error, leaseId) {
|
|
1239
|
+
const result = this.taskQueue.fail(taskId, this.normalizeError(error), leaseId);
|
|
1240
|
+
if (!result) return;
|
|
1241
|
+
if (result.willRetry) {
|
|
1242
|
+
this.emitTaskEvent("task:queued", taskId);
|
|
1243
|
+
} else {
|
|
1244
|
+
this.emitTaskEvent("task:failed", taskId);
|
|
1245
|
+
}
|
|
1246
|
+
void this.persistQueueState();
|
|
1247
|
+
}
|
|
1248
|
+
async executeTaskWithRetry(agent, taskId, params) {
|
|
1249
|
+
while (true) {
|
|
1250
|
+
const task = this.taskQueue.get(taskId);
|
|
1251
|
+
if (!task || task.status === "cancelled" || task.status === "completed" || task.status === "failed") {
|
|
1252
|
+
return;
|
|
1253
|
+
}
|
|
1254
|
+
const lease = this.markTaskRunning(taskId);
|
|
1255
|
+
if (!lease) {
|
|
1256
|
+
await this.sleep(10);
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
const runMetadata = {
|
|
1260
|
+
..._nullishCoalesce(params.metadata, () => ( {})),
|
|
1261
|
+
a2aTaskId: taskId,
|
|
1262
|
+
a2aLeaseId: lease.leaseId,
|
|
1263
|
+
a2aAttempt: lease.attempt,
|
|
1264
|
+
a2aManagedByQueue: true
|
|
1265
|
+
};
|
|
1266
|
+
try {
|
|
1267
|
+
const result = await agent.run(params.prompt, { pluginMetadata: runMetadata });
|
|
1268
|
+
this.markTaskCompleted(taskId, result.text, lease.leaseId);
|
|
1269
|
+
return;
|
|
1270
|
+
} catch (error) {
|
|
1271
|
+
const failed = this.taskQueue.fail(taskId, this.normalizeError(error), lease.leaseId);
|
|
1272
|
+
if (!failed) return;
|
|
1273
|
+
if (!failed.willRetry) {
|
|
1274
|
+
this.emitTaskEvent("task:failed", taskId);
|
|
1275
|
+
void this.persistQueueState();
|
|
1276
|
+
return;
|
|
1277
|
+
}
|
|
1278
|
+
this.emitTaskEvent("task:queued", taskId);
|
|
1279
|
+
void this.persistQueueState();
|
|
1280
|
+
await this.sleep(failed.retryDelayMs);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
evictStaleTasks() {
|
|
1285
|
+
const before = new Set(this.taskQueue.list().map((task) => task.id));
|
|
1286
|
+
this.taskQueue.evictExpired();
|
|
1287
|
+
const after = new Set(this.taskQueue.list().map((task) => task.id));
|
|
1288
|
+
for (const taskId of before) {
|
|
1289
|
+
if (!after.has(taskId)) {
|
|
1290
|
+
this.pushNotifier.cleanup(taskId);
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
void this.persistQueueState();
|
|
1294
|
+
}
|
|
1295
|
+
emitTaskEvent(type, taskId) {
|
|
1296
|
+
const task = this.taskQueue.get(taskId);
|
|
1297
|
+
if (!task) return;
|
|
1298
|
+
const event = {
|
|
1299
|
+
type,
|
|
1300
|
+
taskId,
|
|
1301
|
+
task,
|
|
1302
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1303
|
+
};
|
|
1304
|
+
for (const listener of this.taskEventListeners) {
|
|
1305
|
+
try {
|
|
1306
|
+
listener(event);
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
console.warn("Task event listener error:", error);
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
this.pushNotifier.notify(event).catch((error) => {
|
|
1312
|
+
console.warn("Push notification error:", error);
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
createWorkerId(taskId) {
|
|
1316
|
+
const sessionId = _nullishCoalesce(_nullishCoalesce(_optionalChain([this, 'access', _28 => _28.latestCtx, 'optionalAccess', _29 => _29.sessionId]), () => ( _optionalChain([this, 'access', _30 => _30.setupCtx, 'optionalAccess', _31 => _31.sessionId]))), () => ( "a2a"));
|
|
1317
|
+
return `${sessionId}:${taskId}`;
|
|
1318
|
+
}
|
|
1319
|
+
normalizeError(error) {
|
|
1320
|
+
return error instanceof Error ? error.message : String(error);
|
|
1321
|
+
}
|
|
1322
|
+
async ensureQueueHydrated() {
|
|
1323
|
+
if (this.queueHydrated) return;
|
|
1324
|
+
if (this.queueHydrationPromise) {
|
|
1325
|
+
await this.queueHydrationPromise;
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
this.queueHydrationPromise = this.hydrateQueueFromMemory();
|
|
1329
|
+
try {
|
|
1330
|
+
await this.queueHydrationPromise;
|
|
1331
|
+
this.queueHydrated = true;
|
|
1332
|
+
} finally {
|
|
1333
|
+
this.queueHydrationPromise = null;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
async hydrateQueueFromMemory() {
|
|
1337
|
+
if (!this.persistQueueStateEnabled || !this.setupCtx) return;
|
|
1338
|
+
try {
|
|
1339
|
+
const snapshot = await this.setupCtx.memory.loadMetadata(
|
|
1340
|
+
this.setupCtx.sessionId,
|
|
1341
|
+
_A2APlugin.QUEUE_SNAPSHOT_KEY
|
|
1342
|
+
);
|
|
1343
|
+
if (snapshot) {
|
|
1344
|
+
this.taskQueue.hydrate(snapshot);
|
|
1345
|
+
}
|
|
1346
|
+
} catch (error) {
|
|
1347
|
+
console.warn("A2A queue hydration failed:", error);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
async persistQueueState() {
|
|
1351
|
+
if (!this.persistQueueStateEnabled || !this.setupCtx) return;
|
|
1352
|
+
try {
|
|
1353
|
+
await this.setupCtx.memory.saveMetadata(
|
|
1354
|
+
this.setupCtx.sessionId,
|
|
1355
|
+
_A2APlugin.QUEUE_SNAPSHOT_KEY,
|
|
1356
|
+
this.taskQueue.snapshot()
|
|
1357
|
+
);
|
|
1358
|
+
} catch (error) {
|
|
1359
|
+
console.warn("A2A queue persistence failed:", error);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
sleep(ms) {
|
|
1363
|
+
if (ms <= 0) return Promise.resolve();
|
|
1364
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1365
|
+
}
|
|
1366
|
+
async discoverAgent(endpoint) {
|
|
1367
|
+
try {
|
|
1368
|
+
const discoveryUrl = new URL("/.well-known/agent.json", endpoint).toString();
|
|
1369
|
+
const controller = new AbortController();
|
|
1370
|
+
const timer = setTimeout(() => controller.abort(), this.requestTimeoutMs);
|
|
1371
|
+
try {
|
|
1372
|
+
const discoveryResponse = await this.fetchImpl(discoveryUrl, { signal: controller.signal });
|
|
1373
|
+
if (discoveryResponse.ok) {
|
|
1374
|
+
const discoveryData = await discoveryResponse.json();
|
|
1375
|
+
return {
|
|
1376
|
+
name: discoveryData.name,
|
|
1377
|
+
description: discoveryData.description,
|
|
1378
|
+
skills: _nullishCoalesce(_optionalChain([discoveryData, 'access', _32 => _32.skills, 'optionalAccess', _33 => _33.map, 'call', _34 => _34((s) => s.name)]), () => ( [])),
|
|
1379
|
+
endpoint
|
|
1380
|
+
};
|
|
1381
|
+
}
|
|
1382
|
+
} finally {
|
|
1383
|
+
clearTimeout(timer);
|
|
1384
|
+
}
|
|
1385
|
+
} catch (e4) {
|
|
1386
|
+
}
|
|
1387
|
+
const payload = {
|
|
1388
|
+
jsonrpc: "2.0",
|
|
1389
|
+
id: crypto.randomUUID(),
|
|
1390
|
+
method: "agent/card"
|
|
1391
|
+
};
|
|
1392
|
+
const response = await this.callRemoteEndpoint(endpoint, payload);
|
|
1393
|
+
if (response.error) {
|
|
1394
|
+
throw new Error(`Failed to discover agent: ${response.error.message}`);
|
|
1395
|
+
}
|
|
1396
|
+
const card = response.result;
|
|
1397
|
+
return {
|
|
1398
|
+
name: _nullishCoalesce(_optionalChain([card, 'optionalAccess', _35 => _35.name]), () => ( "Unknown Agent")),
|
|
1399
|
+
description: _nullishCoalesce(_optionalChain([card, 'optionalAccess', _36 => _36.instructions]), () => ( "No description")),
|
|
1400
|
+
skills: _nullishCoalesce(_optionalChain([card, 'optionalAccess', _37 => _37.tools]), () => ( [])),
|
|
1401
|
+
endpoint
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
async subscribeToTask(endpoint, prompt, taskId) {
|
|
1405
|
+
const payload = {
|
|
1406
|
+
jsonrpc: "2.0",
|
|
1407
|
+
id: crypto.randomUUID(),
|
|
1408
|
+
method: "tasks/sendSubscribe",
|
|
1409
|
+
params: { prompt, taskId }
|
|
1410
|
+
};
|
|
1411
|
+
const sseTimeoutMs = this.requestTimeoutMs * 5;
|
|
1412
|
+
const controller = new AbortController();
|
|
1413
|
+
const timer = setTimeout(() => controller.abort(), sseTimeoutMs);
|
|
1414
|
+
try {
|
|
1415
|
+
const response = await this.fetchImpl(endpoint, {
|
|
1416
|
+
method: "POST",
|
|
1417
|
+
headers: {
|
|
1418
|
+
"Content-Type": "application/json",
|
|
1419
|
+
"Accept": "text/event-stream"
|
|
1420
|
+
},
|
|
1421
|
+
body: JSON.stringify(payload),
|
|
1422
|
+
signal: controller.signal
|
|
1423
|
+
});
|
|
1424
|
+
if (!response.ok) {
|
|
1425
|
+
throw new Error(`SSE subscription failed with HTTP ${response.status}`);
|
|
1426
|
+
}
|
|
1427
|
+
const events = [];
|
|
1428
|
+
let sseCompleted = false;
|
|
1429
|
+
const reader = _optionalChain([response, 'access', _38 => _38.body, 'optionalAccess', _39 => _39.getReader, 'call', _40 => _40()]);
|
|
1430
|
+
const decoder = new TextDecoder();
|
|
1431
|
+
if (!reader) {
|
|
1432
|
+
throw new Error("No response body for SSE stream");
|
|
1433
|
+
}
|
|
1434
|
+
let buffer = "";
|
|
1435
|
+
try {
|
|
1436
|
+
while (true) {
|
|
1437
|
+
const { done, value } = await reader.read();
|
|
1438
|
+
if (done) break;
|
|
1439
|
+
buffer += decoder.decode(value, { stream: true });
|
|
1440
|
+
const segments = buffer.split("\n");
|
|
1441
|
+
buffer = _nullishCoalesce(segments.pop(), () => ( ""));
|
|
1442
|
+
for (const line of segments) {
|
|
1443
|
+
if (line.startsWith("data: ")) {
|
|
1444
|
+
try {
|
|
1445
|
+
const eventData = JSON.parse(line.substring(6));
|
|
1446
|
+
events.push(eventData);
|
|
1447
|
+
if (eventData.type === "task:completed" || eventData.type === "task:failed" || eventData.type === "task:cancelled") {
|
|
1448
|
+
sseCompleted = true;
|
|
1449
|
+
}
|
|
1450
|
+
} catch (e5) {
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
if (sseCompleted) {
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
} finally {
|
|
1459
|
+
reader.releaseLock();
|
|
1460
|
+
}
|
|
1461
|
+
return {
|
|
1462
|
+
message: "Task subscription completed",
|
|
1463
|
+
events
|
|
1464
|
+
};
|
|
1465
|
+
} finally {
|
|
1466
|
+
clearTimeout(timer);
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
getTaskIdFromContext(ctx) {
|
|
1470
|
+
const raw = _optionalChain([ctx, 'access', _41 => _41.runMetadata, 'optionalAccess', _42 => _42.a2aTaskId]);
|
|
1471
|
+
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
1472
|
+
}
|
|
1473
|
+
getLeaseIdFromContext(ctx) {
|
|
1474
|
+
const raw = _optionalChain([ctx, 'access', _43 => _43.runMetadata, 'optionalAccess', _44 => _44.a2aLeaseId]);
|
|
1475
|
+
return typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
1476
|
+
}
|
|
1477
|
+
isQueueManagedRun(ctx) {
|
|
1478
|
+
return _optionalChain([ctx, 'access', _45 => _45.runMetadata, 'optionalAccess', _46 => _46.a2aManagedByQueue]) === true;
|
|
1479
|
+
}
|
|
1480
|
+
async resolveAgentCard() {
|
|
1481
|
+
if (this.agentCardProvider) {
|
|
1482
|
+
return this.agentCardProvider.getAgentCard();
|
|
1483
|
+
}
|
|
1484
|
+
const ctx = _nullishCoalesce(this.latestCtx, () => ( this.setupCtx));
|
|
1485
|
+
if (!ctx) {
|
|
1486
|
+
return {
|
|
1487
|
+
name: "Agent",
|
|
1488
|
+
instructions: "",
|
|
1489
|
+
tools: []
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1492
|
+
return {
|
|
1493
|
+
name: _nullishCoalesce(ctx.agentName, () => ( "Agent")),
|
|
1494
|
+
sessionId: ctx.sessionId,
|
|
1495
|
+
instructions: ctx.config.instructions,
|
|
1496
|
+
maxSteps: ctx.config.maxSteps,
|
|
1497
|
+
tools: [...ctx.toolNames]
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
cloneTask(taskId) {
|
|
1501
|
+
const task = this.taskQueue.get(taskId);
|
|
1502
|
+
if (!task) {
|
|
1503
|
+
throw new Error(`Task not found: ${taskId}`);
|
|
1504
|
+
}
|
|
1505
|
+
return task;
|
|
1506
|
+
}
|
|
1507
|
+
}, _class5.__initStatic3(), _class5.__initStatic4(), _class5.__initStatic5(), _class5);
|
|
1508
|
+
function createA2APlugin(options) {
|
|
1509
|
+
return new A2APlugin(options);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
// src/adapters/validation/zod-validation.adapter.ts
|
|
1513
|
+
var ZodValidationAdapter = class {
|
|
1514
|
+
validate(schema, data) {
|
|
1515
|
+
const zodSchema = schema;
|
|
1516
|
+
const result = zodSchema.safeParse(data);
|
|
1517
|
+
if (result.success) {
|
|
1518
|
+
return { success: true, data: result.data };
|
|
1519
|
+
}
|
|
1520
|
+
return { success: false, error: result.error.message };
|
|
1521
|
+
}
|
|
1522
|
+
validateOrThrow(schema, data) {
|
|
1523
|
+
const zodSchema = schema;
|
|
1524
|
+
return zodSchema.parse(data);
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
|
|
1528
|
+
// src/plugins/utils/get-validator.ts
|
|
1529
|
+
function getValidator(options) {
|
|
1530
|
+
return _nullishCoalesce(options.validator, () => ( new ZodValidationAdapter()));
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
// src/plugins/guardrails.plugin.ts
|
|
1534
|
+
var GuardrailsError = class extends Error {
|
|
1535
|
+
|
|
1536
|
+
constructor(code, message) {
|
|
1537
|
+
super(message);
|
|
1538
|
+
this.name = "GuardrailsError";
|
|
1539
|
+
this.code = code;
|
|
1540
|
+
}
|
|
1541
|
+
};
|
|
1542
|
+
var GuardrailsPlugin = (_class6 = class extends BasePlugin {
|
|
1543
|
+
__init13() {this.name = "guardrails"}
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
constructor(options = {}) {
|
|
1547
|
+
super();_class6.prototype.__init13.call(this);;
|
|
1548
|
+
this.validator = getValidator(options);
|
|
1549
|
+
this.options = {
|
|
1550
|
+
onFailure: _nullishCoalesce(options.onFailure, () => ( "throw")),
|
|
1551
|
+
contentFilters: _nullishCoalesce(options.contentFilters, () => ( [])),
|
|
1552
|
+
inputValidators: _nullishCoalesce(options.inputValidators, () => ( [])),
|
|
1553
|
+
outputValidators: _nullishCoalesce(options.outputValidators, () => ( [])),
|
|
1554
|
+
inputSchema: options.inputSchema,
|
|
1555
|
+
outputSchema: options.outputSchema,
|
|
1556
|
+
toolSchemas: options.toolSchemas
|
|
1557
|
+
};
|
|
1558
|
+
}
|
|
1559
|
+
buildHooks() {
|
|
1560
|
+
return {
|
|
1561
|
+
beforeRun: this.beforeRun.bind(this),
|
|
1562
|
+
afterRun: this.afterRun.bind(this),
|
|
1563
|
+
beforeTool: this.beforeTool.bind(this)
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
// ── Hook implementations ──────────────────────────────────────────────────
|
|
1567
|
+
beforeRun(_ctx, params) {
|
|
1568
|
+
const { prompt } = params;
|
|
1569
|
+
for (const filter of this.options.contentFilters) {
|
|
1570
|
+
if (filter.test(prompt)) {
|
|
1571
|
+
this.fail("content_filter", `Content filter "${filter.name}" matched input`);
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
for (const validator of this.options.inputValidators) {
|
|
1575
|
+
const error = validator(prompt);
|
|
1576
|
+
if (error) {
|
|
1577
|
+
this.fail("input_validation", error);
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
if (this.options.inputSchema) {
|
|
1581
|
+
const result = this.validator.validate(this.options.inputSchema, prompt);
|
|
1582
|
+
if (!result.success) {
|
|
1583
|
+
this.fail("input_validation", `Input schema validation failed: ${result.error}`);
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
return { prompt };
|
|
1587
|
+
}
|
|
1588
|
+
afterRun(_ctx, params) {
|
|
1589
|
+
const { text } = params.result;
|
|
1590
|
+
for (const filter of this.options.contentFilters) {
|
|
1591
|
+
if (filter.test(text)) {
|
|
1592
|
+
this.fail("content_filter", `Content filter "${filter.name}" matched output`);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
for (const validator of this.options.outputValidators) {
|
|
1596
|
+
const error = validator(text);
|
|
1597
|
+
if (error) {
|
|
1598
|
+
this.fail("output_validation", error);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
if (this.options.outputSchema) {
|
|
1602
|
+
const result = this.validator.validate(this.options.outputSchema, text);
|
|
1603
|
+
if (!result.success) {
|
|
1604
|
+
this.fail("output_validation", `Output schema validation failed: ${result.error}`);
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
beforeTool(_ctx, params) {
|
|
1609
|
+
const schema = _optionalChain([this, 'access', _47 => _47.options, 'access', _48 => _48.toolSchemas, 'optionalAccess', _49 => _49[params.toolName]]);
|
|
1610
|
+
if (!schema) return;
|
|
1611
|
+
const result = this.validator.validate(schema, params.args);
|
|
1612
|
+
if (!result.success) {
|
|
1613
|
+
this.fail("tool_validation", `Tool "${params.toolName}" args validation failed: ${result.error}`);
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
// ── Helpers ───────────────────────────────────────────────────────────────
|
|
1617
|
+
fail(code, message) {
|
|
1618
|
+
if (this.options.onFailure === "warn") {
|
|
1619
|
+
console.warn(`[guardrails] ${message}`);
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
throw new GuardrailsError(code, message);
|
|
1623
|
+
}
|
|
1624
|
+
}, _class6);
|
|
1625
|
+
function createGuardrailsPlugin(options = {}) {
|
|
1626
|
+
return new GuardrailsPlugin(options);
|
|
1627
|
+
}
|
|
1628
|
+
function createPiiFilter() {
|
|
1629
|
+
return {
|
|
1630
|
+
name: "pii",
|
|
1631
|
+
test(content) {
|
|
1632
|
+
const patterns = [
|
|
1633
|
+
/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/,
|
|
1634
|
+
// email
|
|
1635
|
+
/\b\d{3}[-.]?\d{2}[-.]?\d{4}\b/,
|
|
1636
|
+
// SSN
|
|
1637
|
+
/\b\d{16}\b/
|
|
1638
|
+
// credit card (basic)
|
|
1639
|
+
];
|
|
1640
|
+
return patterns.some((p) => p.test(content));
|
|
1641
|
+
}
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
// src/plugins/onecrawl.plugin.ts
|
|
1646
|
+
|
|
1647
|
+
var DEFAULT_REQUEST_TIMEOUT_MS2 = 3e4;
|
|
1648
|
+
var OneCrawlPlugin = (_class7 = class extends BasePlugin {
|
|
1649
|
+
__init14() {this.name = "crawl"}
|
|
1650
|
+
|
|
1651
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1652
|
+
__init15() {this.crawlerPromise = null}
|
|
1653
|
+
|
|
1654
|
+
constructor(options = {}) {
|
|
1655
|
+
super();_class7.prototype.__init14.call(this);_class7.prototype.__init15.call(this);;
|
|
1656
|
+
this.options = options;
|
|
1657
|
+
this.validator = getValidator(options);
|
|
1658
|
+
}
|
|
1659
|
+
buildHooks() {
|
|
1660
|
+
return {};
|
|
1661
|
+
}
|
|
1662
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1663
|
+
getCrawler() {
|
|
1664
|
+
if (!this.crawlerPromise) {
|
|
1665
|
+
this.crawlerPromise = this.initCrawler();
|
|
1666
|
+
}
|
|
1667
|
+
return this.crawlerPromise;
|
|
1668
|
+
}
|
|
1669
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1670
|
+
async initCrawler() {
|
|
1671
|
+
if (this.options.crawler) {
|
|
1672
|
+
return this.options.crawler;
|
|
1673
|
+
}
|
|
1674
|
+
try {
|
|
1675
|
+
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("onecrawl")));
|
|
1676
|
+
const CrawlerClass = _nullishCoalesce(_nullishCoalesce(mod.Crawler, () => ( _optionalChain([mod, 'access', _50 => _50.default, 'optionalAccess', _51 => _51.Crawler]))), () => ( mod.default));
|
|
1677
|
+
return new CrawlerClass({
|
|
1678
|
+
timeout: _nullishCoalesce(this.options.timeout, () => ( DEFAULT_REQUEST_TIMEOUT_MS2))
|
|
1679
|
+
});
|
|
1680
|
+
} catch (e6) {
|
|
1681
|
+
throw new Error(
|
|
1682
|
+
'OneCrawlPlugin requires "onecrawl" package. Install it: pnpm add onecrawl'
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
get tools() {
|
|
1687
|
+
const maxLen = _nullishCoalesce(this.options.maxContentLength, () => ( 1e4));
|
|
1688
|
+
const getCrawler = this.getCrawler.bind(this);
|
|
1689
|
+
const validator = this.validator;
|
|
1690
|
+
return {
|
|
1691
|
+
scrape: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1692
|
+
description: "Scrape a web page and extract its text content",
|
|
1693
|
+
inputSchema: _zod.z.object({
|
|
1694
|
+
url: _zod.z.string().url().describe("The URL to scrape")
|
|
1695
|
+
}),
|
|
1696
|
+
execute: async (args) => {
|
|
1697
|
+
const { url } = validator.validateOrThrow(
|
|
1698
|
+
_zod.z.object({ url: _zod.z.string().url() }),
|
|
1699
|
+
args
|
|
1700
|
+
);
|
|
1701
|
+
const crawler = await getCrawler();
|
|
1702
|
+
const result = await crawler.crawl(url);
|
|
1703
|
+
const content = typeof result === "string" ? result : _nullishCoalesce(_nullishCoalesce(_optionalChain([result, 'optionalAccess', _52 => _52.content]), () => ( _optionalChain([result, 'optionalAccess', _53 => _53.text]))), () => ( JSON.stringify(result)));
|
|
1704
|
+
return content.length > maxLen ? content.slice(0, maxLen) + "\n...[truncated]" : content;
|
|
1705
|
+
}
|
|
1706
|
+
}),
|
|
1707
|
+
search: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1708
|
+
description: "Search the web and return results",
|
|
1709
|
+
inputSchema: _zod.z.object({
|
|
1710
|
+
query: _zod.z.string().describe("The search query"),
|
|
1711
|
+
limit: _zod.z.number().min(1).max(20).default(5).describe("Max results to return")
|
|
1712
|
+
}),
|
|
1713
|
+
execute: async (args) => {
|
|
1714
|
+
const { query, limit } = validator.validateOrThrow(
|
|
1715
|
+
_zod.z.object({
|
|
1716
|
+
query: _zod.z.string(),
|
|
1717
|
+
limit: _zod.z.number().min(1).max(20).default(5)
|
|
1718
|
+
}),
|
|
1719
|
+
args
|
|
1720
|
+
);
|
|
1721
|
+
const crawler = await getCrawler();
|
|
1722
|
+
const results = await crawler.search(query, { limit });
|
|
1723
|
+
if (Array.isArray(results)) {
|
|
1724
|
+
return results.map((r) => ({
|
|
1725
|
+
title: _nullishCoalesce(r.title, () => ( "")),
|
|
1726
|
+
url: _nullishCoalesce(_nullishCoalesce(r.url, () => ( r.link)), () => ( "")),
|
|
1727
|
+
snippet: _nullishCoalesce(_nullishCoalesce(r.snippet, () => ( r.description)), () => ( ""))
|
|
1728
|
+
}));
|
|
1729
|
+
}
|
|
1730
|
+
return results;
|
|
1731
|
+
}
|
|
1732
|
+
}),
|
|
1733
|
+
batch: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
1734
|
+
description: "Scrape multiple web pages in parallel",
|
|
1735
|
+
inputSchema: _zod.z.object({
|
|
1736
|
+
urls: _zod.z.array(_zod.z.string().url()).min(1).max(10).describe("URLs to scrape")
|
|
1737
|
+
}),
|
|
1738
|
+
execute: async (args) => {
|
|
1739
|
+
const { urls } = validator.validateOrThrow(
|
|
1740
|
+
_zod.z.object({ urls: _zod.z.array(_zod.z.string().url()).min(1).max(10) }),
|
|
1741
|
+
args
|
|
1742
|
+
);
|
|
1743
|
+
const crawler = await getCrawler();
|
|
1744
|
+
if (typeof crawler.batchCrawl === "function") {
|
|
1745
|
+
const results2 = await crawler.batchCrawl(urls);
|
|
1746
|
+
return Array.isArray(results2) ? results2.map((r, i) => ({
|
|
1747
|
+
url: urls[i],
|
|
1748
|
+
content: (typeof r === "string" ? r : _nullishCoalesce(_nullishCoalesce(_optionalChain([r, 'optionalAccess', _54 => _54.content]), () => ( _optionalChain([r, 'optionalAccess', _55 => _55.text]))), () => ( ""))).slice(0, maxLen)
|
|
1749
|
+
})) : results2;
|
|
1750
|
+
}
|
|
1751
|
+
const results = await Promise.all(
|
|
1752
|
+
urls.map(async (u) => {
|
|
1753
|
+
try {
|
|
1754
|
+
const r = await crawler.crawl(u);
|
|
1755
|
+
const content = typeof r === "string" ? r : _nullishCoalesce(_nullishCoalesce(_optionalChain([r, 'optionalAccess', _56 => _56.content]), () => ( _optionalChain([r, 'optionalAccess', _57 => _57.text]))), () => ( ""));
|
|
1756
|
+
return { url: u, content: content.slice(0, maxLen) };
|
|
1757
|
+
} catch (error) {
|
|
1758
|
+
return { url: u, error: String(error) };
|
|
1759
|
+
}
|
|
1760
|
+
})
|
|
1761
|
+
);
|
|
1762
|
+
return results;
|
|
1763
|
+
}
|
|
1764
|
+
})
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
async dispose() {
|
|
1768
|
+
if (this.crawlerPromise) {
|
|
1769
|
+
try {
|
|
1770
|
+
const crawler = await this.crawlerPromise;
|
|
1771
|
+
if (crawler && typeof crawler.close === "function") {
|
|
1772
|
+
await crawler.close();
|
|
1773
|
+
}
|
|
1774
|
+
} catch (e7) {
|
|
1775
|
+
}
|
|
1776
|
+
this.crawlerPromise = null;
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
}, _class7);
|
|
1780
|
+
function createOneCrawlPlugin(options = {}) {
|
|
1781
|
+
return new OneCrawlPlugin(options);
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
// src/plugins/vectorless.plugin.ts
|
|
1785
|
+
|
|
1786
|
+
|
|
1787
|
+
// src/adapters/chunking/default-chunking.adapter.ts
|
|
1788
|
+
var _crypto = require('crypto');
|
|
1789
|
+
var DEFAULT_MAX_TOKENS = 512;
|
|
1790
|
+
var DEFAULT_OVERLAP = 50;
|
|
1791
|
+
var DEFAULT_SEPARATORS = ["\n\n", "\n", ". ", " "];
|
|
1792
|
+
function wordCount(text) {
|
|
1793
|
+
let count = 0;
|
|
1794
|
+
const re = /\S+/g;
|
|
1795
|
+
while (re.exec(text) !== null) count++;
|
|
1796
|
+
return count;
|
|
1797
|
+
}
|
|
1798
|
+
function makeChunk(text, index, startOffset, source) {
|
|
1799
|
+
return {
|
|
1800
|
+
id: _crypto.randomUUID.call(void 0, ),
|
|
1801
|
+
text,
|
|
1802
|
+
index,
|
|
1803
|
+
metadata: {
|
|
1804
|
+
startOffset,
|
|
1805
|
+
endOffset: startOffset + text.length,
|
|
1806
|
+
tokenCount: wordCount(text),
|
|
1807
|
+
source
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
function getWordPositions(text) {
|
|
1812
|
+
const positions = [];
|
|
1813
|
+
const regex = /\S+/g;
|
|
1814
|
+
let match;
|
|
1815
|
+
while ((match = regex.exec(text)) !== null) {
|
|
1816
|
+
positions.push({ word: match[0], start: match.index, end: match.index + match[0].length });
|
|
1817
|
+
}
|
|
1818
|
+
return positions;
|
|
1819
|
+
}
|
|
1820
|
+
function splitByWordsMax(text, maxTokens) {
|
|
1821
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
1822
|
+
const parts = [];
|
|
1823
|
+
for (let i = 0; i < words.length; i += maxTokens) {
|
|
1824
|
+
parts.push(words.slice(i, i + maxTokens).join(" "));
|
|
1825
|
+
}
|
|
1826
|
+
return parts;
|
|
1827
|
+
}
|
|
1828
|
+
function chunkFixed(text, maxTokens) {
|
|
1829
|
+
return splitByWordsMax(text, maxTokens);
|
|
1830
|
+
}
|
|
1831
|
+
function chunkSlidingWindow(text, maxTokens, overlap) {
|
|
1832
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
1833
|
+
if (words.length === 0) return [];
|
|
1834
|
+
const step = Math.max(1, maxTokens - overlap);
|
|
1835
|
+
const chunks = [];
|
|
1836
|
+
for (let i = 0; i < words.length; i += step) {
|
|
1837
|
+
chunks.push(words.slice(i, i + maxTokens).join(" "));
|
|
1838
|
+
if (i + maxTokens >= words.length) break;
|
|
1839
|
+
}
|
|
1840
|
+
return chunks;
|
|
1841
|
+
}
|
|
1842
|
+
function chunkSemantic(text, maxTokens) {
|
|
1843
|
+
const paragraphs = text.split(/\n\n+/).filter(Boolean);
|
|
1844
|
+
const chunks = [];
|
|
1845
|
+
let current = "";
|
|
1846
|
+
for (const para of paragraphs) {
|
|
1847
|
+
const candidate = current ? `${current}
|
|
1848
|
+
|
|
1849
|
+
${para}` : para;
|
|
1850
|
+
const candidateWc = wordCount(candidate);
|
|
1851
|
+
if (candidateWc <= maxTokens) {
|
|
1852
|
+
current = candidate;
|
|
1853
|
+
} else {
|
|
1854
|
+
if (current) chunks.push(current);
|
|
1855
|
+
const paraWc = current ? wordCount(para) : candidateWc;
|
|
1856
|
+
if (paraWc > maxTokens) {
|
|
1857
|
+
const sentences = para.split(/(?<=[.!?])\s+/).filter(Boolean);
|
|
1858
|
+
let sentBuf = "";
|
|
1859
|
+
for (const s of sentences) {
|
|
1860
|
+
const next = sentBuf ? `${sentBuf} ${s}` : s;
|
|
1861
|
+
const nextWc = wordCount(next);
|
|
1862
|
+
if (nextWc <= maxTokens) {
|
|
1863
|
+
sentBuf = next;
|
|
1864
|
+
} else {
|
|
1865
|
+
if (sentBuf) chunks.push(sentBuf);
|
|
1866
|
+
const sWc = sentBuf ? wordCount(s) : nextWc;
|
|
1867
|
+
if (sWc > maxTokens) {
|
|
1868
|
+
chunks.push(...splitByWordsMax(s, maxTokens));
|
|
1869
|
+
sentBuf = "";
|
|
1870
|
+
} else {
|
|
1871
|
+
sentBuf = s;
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
current = sentBuf;
|
|
1876
|
+
} else {
|
|
1877
|
+
current = para;
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
if (current) chunks.push(current);
|
|
1882
|
+
return chunks;
|
|
1883
|
+
}
|
|
1884
|
+
function chunkRecursive(text, maxTokens, separators) {
|
|
1885
|
+
const wc = wordCount(text);
|
|
1886
|
+
if (wc <= maxTokens || separators.length === 0) {
|
|
1887
|
+
if (wc > maxTokens) return splitByWordsMax(text, maxTokens);
|
|
1888
|
+
return [text];
|
|
1889
|
+
}
|
|
1890
|
+
const sep = separators[0];
|
|
1891
|
+
const rest = separators.slice(1);
|
|
1892
|
+
const parts = text.split(sep).filter(Boolean);
|
|
1893
|
+
const results = [];
|
|
1894
|
+
let buffer = "";
|
|
1895
|
+
for (const part of parts) {
|
|
1896
|
+
const candidate = buffer ? `${buffer}${sep}${part}` : part;
|
|
1897
|
+
const candidateWc = wordCount(candidate);
|
|
1898
|
+
if (candidateWc <= maxTokens) {
|
|
1899
|
+
buffer = candidate;
|
|
1900
|
+
} else {
|
|
1901
|
+
if (buffer) results.push(buffer);
|
|
1902
|
+
const partWc = buffer ? wordCount(part) : candidateWc;
|
|
1903
|
+
if (partWc > maxTokens) {
|
|
1904
|
+
results.push(...chunkRecursive(part, maxTokens, rest));
|
|
1905
|
+
buffer = "";
|
|
1906
|
+
} else {
|
|
1907
|
+
buffer = part;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
if (buffer) results.push(buffer);
|
|
1912
|
+
return results;
|
|
1913
|
+
}
|
|
1914
|
+
var DefaultChunkingAdapter = class {
|
|
1915
|
+
chunk(text, options) {
|
|
1916
|
+
if (!text || !text.trim()) return [];
|
|
1917
|
+
const strategy = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _58 => _58.strategy]), () => ( "fixed"));
|
|
1918
|
+
const maxTokens = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _59 => _59.maxTokens]), () => ( DEFAULT_MAX_TOKENS));
|
|
1919
|
+
const overlap = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _60 => _60.overlap]), () => ( DEFAULT_OVERLAP));
|
|
1920
|
+
const separators = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _61 => _61.separators]), () => ( DEFAULT_SEPARATORS));
|
|
1921
|
+
let rawChunks;
|
|
1922
|
+
switch (strategy) {
|
|
1923
|
+
case "fixed":
|
|
1924
|
+
rawChunks = chunkFixed(text, maxTokens);
|
|
1925
|
+
break;
|
|
1926
|
+
case "sliding-window":
|
|
1927
|
+
rawChunks = chunkSlidingWindow(text, maxTokens, overlap);
|
|
1928
|
+
break;
|
|
1929
|
+
case "semantic":
|
|
1930
|
+
rawChunks = chunkSemantic(text, maxTokens);
|
|
1931
|
+
break;
|
|
1932
|
+
case "recursive":
|
|
1933
|
+
rawChunks = chunkRecursive(text, maxTokens, separators);
|
|
1934
|
+
break;
|
|
1935
|
+
default:
|
|
1936
|
+
rawChunks = chunkFixed(text, maxTokens);
|
|
1937
|
+
}
|
|
1938
|
+
const wordPositions = getWordPositions(text);
|
|
1939
|
+
const chunks = [];
|
|
1940
|
+
let searchWordIdx = 0;
|
|
1941
|
+
for (let i = 0; i < rawChunks.length; i++) {
|
|
1942
|
+
const raw = rawChunks[i];
|
|
1943
|
+
const chunkWords = raw.split(/\s+/).filter(Boolean);
|
|
1944
|
+
if (chunkWords.length === 0) continue;
|
|
1945
|
+
let matchIdx = searchWordIdx;
|
|
1946
|
+
for (let j = searchWordIdx; j < wordPositions.length; j++) {
|
|
1947
|
+
if (wordPositions[j].word === chunkWords[0]) {
|
|
1948
|
+
matchIdx = j;
|
|
1949
|
+
break;
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1952
|
+
const startPos = matchIdx < wordPositions.length ? wordPositions[matchIdx].start : 0;
|
|
1953
|
+
const lastWordIdx = Math.min(matchIdx + chunkWords.length - 1, wordPositions.length - 1);
|
|
1954
|
+
const endPos = lastWordIdx >= 0 ? wordPositions[lastWordIdx].end : startPos + raw.length;
|
|
1955
|
+
chunks.push(makeChunk(raw, i, startPos));
|
|
1956
|
+
chunks[chunks.length - 1].metadata.endOffset = endPos;
|
|
1957
|
+
searchWordIdx = matchIdx + 1;
|
|
1958
|
+
}
|
|
1959
|
+
return chunks;
|
|
1960
|
+
}
|
|
1961
|
+
};
|
|
1962
|
+
|
|
1963
|
+
// src/adapters/reranking/default-reranking.adapter.ts
|
|
1964
|
+
var K1 = 1.2;
|
|
1965
|
+
var B = 0.75;
|
|
1966
|
+
var PUNCTUATION_RE = /[^\w\s]/g;
|
|
1967
|
+
function tokenize(text) {
|
|
1968
|
+
return text.toLowerCase().replace(PUNCTUATION_RE, "").split(/\s+/).filter(Boolean);
|
|
1969
|
+
}
|
|
1970
|
+
function buildTermFrequencyMap(tokens) {
|
|
1971
|
+
const freq = /* @__PURE__ */ new Map();
|
|
1972
|
+
for (const t of tokens) {
|
|
1973
|
+
freq.set(t, (_nullishCoalesce(freq.get(t), () => ( 0))) + 1);
|
|
1974
|
+
}
|
|
1975
|
+
return freq;
|
|
1976
|
+
}
|
|
1977
|
+
function computeTfIdf(query, results) {
|
|
1978
|
+
const queryTokens = tokenize(query);
|
|
1979
|
+
const docTokenSets = results.map((r) => tokenize(r.text));
|
|
1980
|
+
const docFreqMaps = docTokenSets.map(buildTermFrequencyMap);
|
|
1981
|
+
const n = results.length;
|
|
1982
|
+
const idf = /* @__PURE__ */ new Map();
|
|
1983
|
+
for (const term of queryTokens) {
|
|
1984
|
+
let df = 0;
|
|
1985
|
+
for (const fm of docFreqMaps) {
|
|
1986
|
+
if (fm.has(term)) df++;
|
|
1987
|
+
}
|
|
1988
|
+
idf.set(term, Math.log((n + 1) / (df + 1)) + 1);
|
|
1989
|
+
}
|
|
1990
|
+
return results.map((r, i) => {
|
|
1991
|
+
const tokens = docTokenSets[i];
|
|
1992
|
+
const freqMap = docFreqMaps[i];
|
|
1993
|
+
let score = 0;
|
|
1994
|
+
for (const term of queryTokens) {
|
|
1995
|
+
const tf = (_nullishCoalesce(freqMap.get(term), () => ( 0))) / (tokens.length || 1);
|
|
1996
|
+
score += tf * (_nullishCoalesce(idf.get(term), () => ( 0)));
|
|
1997
|
+
}
|
|
1998
|
+
return { ...r, score };
|
|
1999
|
+
}).sort((a, b) => b.score - a.score);
|
|
2000
|
+
}
|
|
2001
|
+
function computeBm25(query, results) {
|
|
2002
|
+
const queryTokens = tokenize(query);
|
|
2003
|
+
const docTokenSets = results.map((r) => tokenize(r.text));
|
|
2004
|
+
const docFreqMaps = docTokenSets.map(buildTermFrequencyMap);
|
|
2005
|
+
const n = results.length;
|
|
2006
|
+
const avgDl = docTokenSets.reduce((sum, t) => sum + t.length, 0) / (n || 1) || 1;
|
|
2007
|
+
const idf = /* @__PURE__ */ new Map();
|
|
2008
|
+
for (const term of queryTokens) {
|
|
2009
|
+
let df = 0;
|
|
2010
|
+
for (const fm of docFreqMaps) {
|
|
2011
|
+
if (fm.has(term)) df++;
|
|
2012
|
+
}
|
|
2013
|
+
idf.set(term, Math.log((n - df + 0.5) / (df + 0.5) + 1));
|
|
2014
|
+
}
|
|
2015
|
+
return results.map((r, i) => {
|
|
2016
|
+
const tokens = docTokenSets[i];
|
|
2017
|
+
const freqMap = docFreqMaps[i];
|
|
2018
|
+
const dl = tokens.length;
|
|
2019
|
+
let score = 0;
|
|
2020
|
+
for (const term of queryTokens) {
|
|
2021
|
+
const tf = _nullishCoalesce(freqMap.get(term), () => ( 0));
|
|
2022
|
+
const idfVal = _nullishCoalesce(idf.get(term), () => ( 0));
|
|
2023
|
+
score += idfVal * (tf * (K1 + 1) / (tf + K1 * (1 - B + B * (dl / avgDl))));
|
|
2024
|
+
}
|
|
2025
|
+
return { ...r, score };
|
|
2026
|
+
}).sort((a, b) => b.score - a.score);
|
|
2027
|
+
}
|
|
2028
|
+
function cosineSimilarity(a, b) {
|
|
2029
|
+
const denom = a.norm * b.norm;
|
|
2030
|
+
if (denom === 0) return 0;
|
|
2031
|
+
const [small, large] = a.vec.size <= b.vec.size ? [a.vec, b.vec] : [b.vec, a.vec];
|
|
2032
|
+
let dot = 0;
|
|
2033
|
+
for (const [k, v] of small) {
|
|
2034
|
+
const other = large.get(k);
|
|
2035
|
+
if (other !== void 0) dot += v * other;
|
|
2036
|
+
}
|
|
2037
|
+
return dot / denom;
|
|
2038
|
+
}
|
|
2039
|
+
function toTfVector(tokens) {
|
|
2040
|
+
const freqMap = buildTermFrequencyMap(tokens);
|
|
2041
|
+
const len = tokens.length;
|
|
2042
|
+
let normSq = 0;
|
|
2043
|
+
for (const [k, v] of freqMap) {
|
|
2044
|
+
const tf = v / len;
|
|
2045
|
+
freqMap.set(k, tf);
|
|
2046
|
+
normSq += tf * tf;
|
|
2047
|
+
}
|
|
2048
|
+
return { vec: freqMap, norm: Math.sqrt(normSq) };
|
|
2049
|
+
}
|
|
2050
|
+
function computeMmr(query, results, lambda) {
|
|
2051
|
+
if (results.length === 0) return [];
|
|
2052
|
+
const queryVec = toTfVector(tokenize(query));
|
|
2053
|
+
const docVecs = results.map((r) => toTfVector(tokenize(r.text)));
|
|
2054
|
+
const relevances = docVecs.map((dv) => cosineSimilarity(queryVec, dv));
|
|
2055
|
+
const pairwiseSim = /* @__PURE__ */ new Map();
|
|
2056
|
+
const pairKey = (i, j) => i < j ? `${i},${j}` : `${j},${i}`;
|
|
2057
|
+
const selected = [];
|
|
2058
|
+
const remaining = new Set(results.map((_, i) => i));
|
|
2059
|
+
const reranked = [];
|
|
2060
|
+
while (remaining.size > 0) {
|
|
2061
|
+
let bestIdx = -1;
|
|
2062
|
+
let bestScore = -Infinity;
|
|
2063
|
+
for (const idx of remaining) {
|
|
2064
|
+
const rel = relevances[idx];
|
|
2065
|
+
let maxSim = 0;
|
|
2066
|
+
for (const selIdx of selected) {
|
|
2067
|
+
const key = pairKey(idx, selIdx);
|
|
2068
|
+
let sim = pairwiseSim.get(key);
|
|
2069
|
+
if (sim === void 0) {
|
|
2070
|
+
sim = cosineSimilarity(docVecs[idx], docVecs[selIdx]);
|
|
2071
|
+
pairwiseSim.set(key, sim);
|
|
2072
|
+
}
|
|
2073
|
+
if (sim > maxSim) maxSim = sim;
|
|
2074
|
+
}
|
|
2075
|
+
const mmrScore = lambda * rel - (1 - lambda) * maxSim;
|
|
2076
|
+
if (mmrScore > bestScore) {
|
|
2077
|
+
bestScore = mmrScore;
|
|
2078
|
+
bestIdx = idx;
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
if (bestIdx >= 0) {
|
|
2082
|
+
selected.push(bestIdx);
|
|
2083
|
+
remaining.delete(bestIdx);
|
|
2084
|
+
reranked.push({ ...results[bestIdx], score: bestScore });
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return reranked;
|
|
2088
|
+
}
|
|
2089
|
+
var DefaultReRankingAdapter = class {
|
|
2090
|
+
rerank(query, results, options) {
|
|
2091
|
+
if (results.length === 0) return [];
|
|
2092
|
+
const strategy = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _62 => _62.strategy]), () => ( "bm25"));
|
|
2093
|
+
switch (strategy) {
|
|
2094
|
+
case "tfidf":
|
|
2095
|
+
return computeTfIdf(query, results);
|
|
2096
|
+
case "bm25":
|
|
2097
|
+
return computeBm25(query, results);
|
|
2098
|
+
case "mmr":
|
|
2099
|
+
return computeMmr(query, results, _nullishCoalesce(_optionalChain([options, 'optionalAccess', _63 => _63.lambda]), () => ( 0.7)));
|
|
2100
|
+
default:
|
|
2101
|
+
return computeBm25(query, results);
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
|
|
2106
|
+
// src/plugins/vectorless.plugin.ts
|
|
2107
|
+
var DEFAULT_MAX_TOKENS_PER_CHUNK = 512;
|
|
2108
|
+
var VectorlessPlugin = (_class8 = class extends BasePlugin {
|
|
2109
|
+
__init16() {this.name = "knowledge"}
|
|
2110
|
+
|
|
2111
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2112
|
+
__init17() {this.vectorlessPromise = null}
|
|
2113
|
+
__init18() {this.currentKnowledge = null}
|
|
2114
|
+
|
|
2115
|
+
__init19() {this.chunks = /* @__PURE__ */ new Map()}
|
|
2116
|
+
|
|
2117
|
+
|
|
2118
|
+
|
|
2119
|
+
constructor(options = {}) {
|
|
2120
|
+
super();_class8.prototype.__init16.call(this);_class8.prototype.__init17.call(this);_class8.prototype.__init18.call(this);_class8.prototype.__init19.call(this);;
|
|
2121
|
+
this.options = options;
|
|
2122
|
+
this.currentKnowledge = _nullishCoalesce(options.knowledgeBase, () => ( null));
|
|
2123
|
+
this.validator = getValidator(options);
|
|
2124
|
+
this.chunkingAdapter = _nullishCoalesce(options.chunkingAdapter, () => ( new DefaultChunkingAdapter()));
|
|
2125
|
+
this.rerankingAdapter = _nullishCoalesce(options.rerankingAdapter, () => ( new DefaultReRankingAdapter()));
|
|
2126
|
+
}
|
|
2127
|
+
buildHooks() {
|
|
2128
|
+
return {};
|
|
2129
|
+
}
|
|
2130
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2131
|
+
getVectorless() {
|
|
2132
|
+
if (!this.vectorlessPromise) {
|
|
2133
|
+
this.vectorlessPromise = this.initVectorless();
|
|
2134
|
+
}
|
|
2135
|
+
return this.vectorlessPromise;
|
|
2136
|
+
}
|
|
2137
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2138
|
+
async initVectorless() {
|
|
2139
|
+
if (this.options.vectorless) {
|
|
2140
|
+
return this.options.vectorless;
|
|
2141
|
+
}
|
|
2142
|
+
try {
|
|
2143
|
+
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("@giulio-leone/gaussflow-vectorless")));
|
|
2144
|
+
return _nullishCoalesce(mod.default, () => ( mod));
|
|
2145
|
+
} catch (e8) {
|
|
2146
|
+
throw new Error(
|
|
2147
|
+
'VectorlessPlugin requires "@giulio-leone/gaussflow-vectorless" package. Install it: pnpm add @giulio-leone/gaussflow-vectorless'
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
get tools() {
|
|
2152
|
+
if (this._toolsCache) return this._toolsCache;
|
|
2153
|
+
const getVectorless = this.getVectorless.bind(this);
|
|
2154
|
+
const getKnowledge = () => this.currentKnowledge;
|
|
2155
|
+
const setKnowledge = (k) => {
|
|
2156
|
+
this.currentKnowledge = k;
|
|
2157
|
+
};
|
|
2158
|
+
const mergeKnowledge = (newK) => {
|
|
2159
|
+
const existing = this.currentKnowledge;
|
|
2160
|
+
const incoming = newK;
|
|
2161
|
+
if (!existing || !incoming) {
|
|
2162
|
+
this.currentKnowledge = _nullishCoalesce(incoming, () => ( existing));
|
|
2163
|
+
return;
|
|
2164
|
+
}
|
|
2165
|
+
const merged = { ...existing };
|
|
2166
|
+
for (const key of ["entities", "relations", "quotes"]) {
|
|
2167
|
+
const a = Array.isArray(existing[key]) ? existing[key] : [];
|
|
2168
|
+
const b = Array.isArray(incoming[key]) ? incoming[key] : [];
|
|
2169
|
+
if (a.length > 0 || b.length > 0) merged[key] = [...a, ...b];
|
|
2170
|
+
}
|
|
2171
|
+
this.currentKnowledge = merged;
|
|
2172
|
+
};
|
|
2173
|
+
const validator = this.validator;
|
|
2174
|
+
const chunks = this.chunks;
|
|
2175
|
+
const chunkingAdapter = this.chunkingAdapter;
|
|
2176
|
+
const rerankingAdapter = this.rerankingAdapter;
|
|
2177
|
+
const toolsMap = {
|
|
2178
|
+
generate: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2179
|
+
description: "Extract knowledge (entities, relations, quotes) from text. Must be called before query/search.",
|
|
2180
|
+
inputSchema: _zod.z.object({
|
|
2181
|
+
text: _zod.z.string().describe("The text to extract knowledge from"),
|
|
2182
|
+
topic: _zod.z.string().optional().describe("Optional topic to focus extraction on")
|
|
2183
|
+
}),
|
|
2184
|
+
execute: async (args) => {
|
|
2185
|
+
const { text, topic } = validator.validateOrThrow(
|
|
2186
|
+
_zod.z.object({
|
|
2187
|
+
text: _zod.z.string(),
|
|
2188
|
+
topic: _zod.z.string().optional()
|
|
2189
|
+
}),
|
|
2190
|
+
args
|
|
2191
|
+
);
|
|
2192
|
+
const vl = await getVectorless();
|
|
2193
|
+
const generate = _nullishCoalesce(_nullishCoalesce(vl.generateKnowledge, () => ( vl.generate)), () => ( vl.extract));
|
|
2194
|
+
if (!generate) throw new Error("vectorless: generateKnowledge function not found");
|
|
2195
|
+
const knowledge = await generate(text, { topic });
|
|
2196
|
+
setKnowledge(knowledge);
|
|
2197
|
+
const summary = {
|
|
2198
|
+
entities: Array.isArray(_optionalChain([knowledge, 'optionalAccess', _64 => _64.entities])) ? knowledge.entities.length : 0,
|
|
2199
|
+
relations: Array.isArray(_optionalChain([knowledge, 'optionalAccess', _65 => _65.relations])) ? knowledge.relations.length : 0,
|
|
2200
|
+
quotes: Array.isArray(_optionalChain([knowledge, 'optionalAccess', _66 => _66.quotes])) ? knowledge.quotes.length : 0
|
|
2201
|
+
};
|
|
2202
|
+
return `Knowledge extracted: ${summary.entities} entities, ${summary.relations} relations, ${summary.quotes} quotes`;
|
|
2203
|
+
}
|
|
2204
|
+
}),
|
|
2205
|
+
query: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2206
|
+
description: "Answer a question using the extracted knowledge base",
|
|
2207
|
+
inputSchema: _zod.z.object({
|
|
2208
|
+
question: _zod.z.string().describe("The question to answer")
|
|
2209
|
+
}),
|
|
2210
|
+
execute: async (args) => {
|
|
2211
|
+
const { question } = validator.validateOrThrow(
|
|
2212
|
+
_zod.z.object({ question: _zod.z.string() }),
|
|
2213
|
+
args
|
|
2214
|
+
);
|
|
2215
|
+
const knowledge = getKnowledge();
|
|
2216
|
+
if (!knowledge) return "No knowledge base loaded. Use knowledge:generate first.";
|
|
2217
|
+
const vl = await getVectorless();
|
|
2218
|
+
const query = _nullishCoalesce(_nullishCoalesce(vl.queryKnowledge, () => ( vl.query)), () => ( vl.ask));
|
|
2219
|
+
if (!query) throw new Error("vectorless: queryKnowledge function not found");
|
|
2220
|
+
const result = await query(question, knowledge);
|
|
2221
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
2222
|
+
}
|
|
2223
|
+
}),
|
|
2224
|
+
"search-entities": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2225
|
+
description: "Search for entities in the extracted knowledge base",
|
|
2226
|
+
inputSchema: _zod.z.object({
|
|
2227
|
+
query: _zod.z.string().describe("Search query for entities"),
|
|
2228
|
+
limit: _zod.z.number().min(1).max(50).default(10).describe("Max results")
|
|
2229
|
+
}),
|
|
2230
|
+
execute: async (args) => {
|
|
2231
|
+
const { query, limit } = validator.validateOrThrow(
|
|
2232
|
+
_zod.z.object({
|
|
2233
|
+
query: _zod.z.string(),
|
|
2234
|
+
limit: _zod.z.number().min(1).max(50).default(10)
|
|
2235
|
+
}),
|
|
2236
|
+
args
|
|
2237
|
+
);
|
|
2238
|
+
const knowledge = getKnowledge();
|
|
2239
|
+
if (!knowledge) return "No knowledge base loaded. Use knowledge:generate first.";
|
|
2240
|
+
const vl = await getVectorless();
|
|
2241
|
+
if (typeof vl.searchEntities === "function") {
|
|
2242
|
+
return await vl.searchEntities(query, knowledge, { limit });
|
|
2243
|
+
}
|
|
2244
|
+
const kb = knowledge;
|
|
2245
|
+
const entities = Array.isArray(_optionalChain([kb, 'optionalAccess', _67 => _67.entities])) ? kb.entities : [];
|
|
2246
|
+
const lower = query.toLowerCase();
|
|
2247
|
+
return entities.filter((e) => (_nullishCoalesce(_nullishCoalesce(e.name, () => ( e.label)), () => ( ""))).toLowerCase().includes(lower)).slice(0, limit);
|
|
2248
|
+
}
|
|
2249
|
+
}),
|
|
2250
|
+
list: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2251
|
+
description: "List all entities in the current knowledge base",
|
|
2252
|
+
inputSchema: _zod.z.object({}),
|
|
2253
|
+
execute: async () => {
|
|
2254
|
+
const knowledge = getKnowledge();
|
|
2255
|
+
if (!knowledge) return "No knowledge base loaded. Use knowledge:generate first.";
|
|
2256
|
+
const kb = knowledge;
|
|
2257
|
+
const entities = Array.isArray(kb.entities) ? kb.entities : [];
|
|
2258
|
+
return entities.map((e) => ({
|
|
2259
|
+
name: _nullishCoalesce(_nullishCoalesce(e.name, () => ( e.label)), () => ( "unknown")),
|
|
2260
|
+
type: _nullishCoalesce(_nullishCoalesce(e.type, () => ( e.category)), () => ( "unknown"))
|
|
2261
|
+
}));
|
|
2262
|
+
}
|
|
2263
|
+
}),
|
|
2264
|
+
// ─── Advanced RAG tools ──────────────────────────────────────────
|
|
2265
|
+
"rag:ingest": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2266
|
+
description: "Chunk a document and extract knowledge from each chunk",
|
|
2267
|
+
inputSchema: _zod.z.object({
|
|
2268
|
+
text: _zod.z.string().describe("The document text to ingest"),
|
|
2269
|
+
source: _zod.z.string().optional().describe("Source identifier for attribution"),
|
|
2270
|
+
chunkingStrategy: _zod.z.enum(["fixed", "sliding-window", "semantic", "recursive"]).default("recursive").describe("Chunking strategy"),
|
|
2271
|
+
maxTokens: _zod.z.number().min(1).default(DEFAULT_MAX_TOKENS_PER_CHUNK).describe("Max tokens per chunk"),
|
|
2272
|
+
overlap: _zod.z.number().min(0).default(50).describe("Token overlap for sliding-window")
|
|
2273
|
+
}),
|
|
2274
|
+
execute: async (args) => {
|
|
2275
|
+
const { text, source, chunkingStrategy, maxTokens, overlap } = validator.validateOrThrow(
|
|
2276
|
+
_zod.z.object({
|
|
2277
|
+
text: _zod.z.string(),
|
|
2278
|
+
source: _zod.z.string().optional(),
|
|
2279
|
+
chunkingStrategy: _zod.z.enum(["fixed", "sliding-window", "semantic", "recursive"]).default("recursive"),
|
|
2280
|
+
maxTokens: _zod.z.number().min(1).default(DEFAULT_MAX_TOKENS_PER_CHUNK),
|
|
2281
|
+
overlap: _zod.z.number().min(0).default(50)
|
|
2282
|
+
}),
|
|
2283
|
+
args
|
|
2284
|
+
);
|
|
2285
|
+
const produced = chunkingAdapter.chunk(text, {
|
|
2286
|
+
strategy: chunkingStrategy,
|
|
2287
|
+
maxTokens,
|
|
2288
|
+
overlap
|
|
2289
|
+
});
|
|
2290
|
+
for (const c of produced) {
|
|
2291
|
+
c.metadata.source = source;
|
|
2292
|
+
chunks.set(c.id, c);
|
|
2293
|
+
}
|
|
2294
|
+
try {
|
|
2295
|
+
const vl = await getVectorless();
|
|
2296
|
+
const generate = _nullishCoalesce(_nullishCoalesce(vl.generateKnowledge, () => ( vl.generate)), () => ( vl.extract));
|
|
2297
|
+
if (generate) {
|
|
2298
|
+
const knowledge = await generate(text, { topic: source });
|
|
2299
|
+
mergeKnowledge(knowledge);
|
|
2300
|
+
}
|
|
2301
|
+
} catch (e9) {
|
|
2302
|
+
}
|
|
2303
|
+
return `Ingested ${produced.length} chunks (strategy: ${chunkingStrategy}, maxTokens: ${maxTokens})${source ? ` from "${source}"` : ""}`;
|
|
2304
|
+
}
|
|
2305
|
+
}),
|
|
2306
|
+
"rag:search": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2307
|
+
description: "Hybrid search: combine entity search + keyword search, then re-rank results",
|
|
2308
|
+
inputSchema: _zod.z.object({
|
|
2309
|
+
query: _zod.z.string().describe("Search query"),
|
|
2310
|
+
limit: _zod.z.number().min(1).max(100).default(10).describe("Max results"),
|
|
2311
|
+
rerankerStrategy: _zod.z.enum(["tfidf", "bm25", "mmr"]).default("bm25").describe("Re-ranking strategy"),
|
|
2312
|
+
includeAttribution: _zod.z.boolean().default(true).describe("Include source attribution")
|
|
2313
|
+
}),
|
|
2314
|
+
execute: async (args) => {
|
|
2315
|
+
const { query, limit, rerankerStrategy, includeAttribution } = validator.validateOrThrow(
|
|
2316
|
+
_zod.z.object({
|
|
2317
|
+
query: _zod.z.string(),
|
|
2318
|
+
limit: _zod.z.number().min(1).max(100).default(10),
|
|
2319
|
+
rerankerStrategy: _zod.z.enum(["tfidf", "bm25", "mmr"]).default("bm25"),
|
|
2320
|
+
includeAttribution: _zod.z.boolean().default(true)
|
|
2321
|
+
}),
|
|
2322
|
+
args
|
|
2323
|
+
);
|
|
2324
|
+
const candidates = [];
|
|
2325
|
+
const queryLower = query.toLowerCase();
|
|
2326
|
+
const queryWords = queryLower.split(/\s+/);
|
|
2327
|
+
const knowledge = getKnowledge();
|
|
2328
|
+
if (knowledge) {
|
|
2329
|
+
const kb = knowledge;
|
|
2330
|
+
const entities = Array.isArray(_optionalChain([kb, 'optionalAccess', _68 => _68.entities])) ? kb.entities : [];
|
|
2331
|
+
for (const e of entities) {
|
|
2332
|
+
const name = (_nullishCoalesce(_nullishCoalesce(e.name, () => ( e.label)), () => ( ""))).toLowerCase();
|
|
2333
|
+
if (name.includes(queryLower) || queryLower.includes(name)) {
|
|
2334
|
+
candidates.push({
|
|
2335
|
+
id: `entity:${_nullishCoalesce(e.name, () => ( e.label))}`,
|
|
2336
|
+
text: `${_nullishCoalesce(e.name, () => ( e.label))} (${_nullishCoalesce(_nullishCoalesce(e.type, () => ( e.category)), () => ( "unknown"))})`,
|
|
2337
|
+
score: 0
|
|
2338
|
+
});
|
|
2339
|
+
}
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2342
|
+
for (const [, chunk] of chunks) {
|
|
2343
|
+
const chunkLower = chunk.text.toLowerCase();
|
|
2344
|
+
if (chunkLower.includes(queryLower) || queryWords.some((w) => chunkLower.includes(w))) {
|
|
2345
|
+
const result = {
|
|
2346
|
+
id: chunk.id,
|
|
2347
|
+
text: chunk.text,
|
|
2348
|
+
score: 0
|
|
2349
|
+
};
|
|
2350
|
+
if (includeAttribution) {
|
|
2351
|
+
result.source = {
|
|
2352
|
+
chunkId: chunk.id,
|
|
2353
|
+
chunkIndex: chunk.index,
|
|
2354
|
+
documentId: chunk.metadata.source,
|
|
2355
|
+
startOffset: chunk.metadata.startOffset,
|
|
2356
|
+
endOffset: chunk.metadata.endOffset,
|
|
2357
|
+
relevanceScore: 0
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2360
|
+
candidates.push(result);
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
if (candidates.length === 0) return [];
|
|
2364
|
+
const reranked = rerankingAdapter.rerank(query, candidates, {
|
|
2365
|
+
strategy: rerankerStrategy
|
|
2366
|
+
});
|
|
2367
|
+
const top = reranked.slice(0, limit);
|
|
2368
|
+
for (const r of top) {
|
|
2369
|
+
if (r.source) r.source.relevanceScore = r.score;
|
|
2370
|
+
}
|
|
2371
|
+
return top;
|
|
2372
|
+
}
|
|
2373
|
+
}),
|
|
2374
|
+
"rag:search-chunks": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
2375
|
+
description: "Search directly against stored chunks",
|
|
2376
|
+
inputSchema: _zod.z.object({
|
|
2377
|
+
query: _zod.z.string().describe("Search query"),
|
|
2378
|
+
limit: _zod.z.number().min(1).max(100).default(10).describe("Max results")
|
|
2379
|
+
}),
|
|
2380
|
+
execute: async (args) => {
|
|
2381
|
+
const { query, limit } = validator.validateOrThrow(
|
|
2382
|
+
_zod.z.object({
|
|
2383
|
+
query: _zod.z.string(),
|
|
2384
|
+
limit: _zod.z.number().min(1).max(100).default(10)
|
|
2385
|
+
}),
|
|
2386
|
+
args
|
|
2387
|
+
);
|
|
2388
|
+
const queryWords = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
2389
|
+
const results = [];
|
|
2390
|
+
for (const [, chunk] of chunks) {
|
|
2391
|
+
const chunkLower = chunk.text.toLowerCase();
|
|
2392
|
+
const matchCount = queryWords.filter((w) => chunkLower.includes(w)).length;
|
|
2393
|
+
if (matchCount > 0) {
|
|
2394
|
+
results.push({ ...chunk, matchScore: matchCount / queryWords.length });
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2397
|
+
return results.sort((a, b) => b.matchScore - a.matchScore).slice(0, limit).map(({ matchScore, ...chunk }) => chunk);
|
|
2398
|
+
}
|
|
2399
|
+
})
|
|
2400
|
+
};
|
|
2401
|
+
this._toolsCache = toolsMap;
|
|
2402
|
+
return toolsMap;
|
|
2403
|
+
}
|
|
2404
|
+
async dispose() {
|
|
2405
|
+
this.currentKnowledge = null;
|
|
2406
|
+
this.vectorlessPromise = null;
|
|
2407
|
+
this.chunks.clear();
|
|
2408
|
+
this._toolsCache = void 0;
|
|
2409
|
+
}
|
|
2410
|
+
}, _class8);
|
|
2411
|
+
function createVectorlessPlugin(options = {}) {
|
|
2412
|
+
return new VectorlessPlugin(options);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
// src/plugins/evals.plugin.ts
|
|
2416
|
+
var EvalsPlugin = (_class9 = class extends BasePlugin {
|
|
2417
|
+
__init20() {this.name = "evals"}
|
|
2418
|
+
|
|
2419
|
+
__init21() {this.results = []}
|
|
2420
|
+
__init22() {this.runStates = /* @__PURE__ */ new Map()}
|
|
2421
|
+
constructor(options = {}) {
|
|
2422
|
+
super();_class9.prototype.__init20.call(this);_class9.prototype.__init21.call(this);_class9.prototype.__init22.call(this);;
|
|
2423
|
+
this.options = options;
|
|
2424
|
+
}
|
|
2425
|
+
buildHooks() {
|
|
2426
|
+
return {
|
|
2427
|
+
beforeRun: this.beforeRun.bind(this),
|
|
2428
|
+
afterRun: this.afterRun.bind(this),
|
|
2429
|
+
afterTool: this.afterTool.bind(this),
|
|
2430
|
+
onError: this.onError.bind(this)
|
|
2431
|
+
};
|
|
2432
|
+
}
|
|
2433
|
+
beforeRun(ctx, params) {
|
|
2434
|
+
this.runStates.set(ctx.sessionId, {
|
|
2435
|
+
startTime: Date.now(),
|
|
2436
|
+
prompt: params.prompt,
|
|
2437
|
+
toolCallCounts: {}
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
async afterRun(ctx, params) {
|
|
2441
|
+
const state = this.runStates.get(ctx.sessionId);
|
|
2442
|
+
const latencyMs = state ? Date.now() - state.startTime : 0;
|
|
2443
|
+
const prompt = _nullishCoalesce(_optionalChain([state, 'optionalAccess', _69 => _69.prompt]), () => ( ""));
|
|
2444
|
+
const toolCalls = state ? { ...state.toolCallCounts } : {};
|
|
2445
|
+
this.runStates.delete(ctx.sessionId);
|
|
2446
|
+
const steps = params.result.steps;
|
|
2447
|
+
let promptTokens = 0;
|
|
2448
|
+
let completionTokens = 0;
|
|
2449
|
+
for (const step of steps) {
|
|
2450
|
+
const usage = _optionalChain([step, 'optionalAccess', _70 => _70.usage]);
|
|
2451
|
+
if (usage) {
|
|
2452
|
+
promptTokens += _nullishCoalesce(usage.promptTokens, () => ( 0));
|
|
2453
|
+
completionTokens += _nullishCoalesce(usage.completionTokens, () => ( 0));
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
const metrics = {
|
|
2457
|
+
latencyMs,
|
|
2458
|
+
stepCount: steps.length,
|
|
2459
|
+
toolCalls,
|
|
2460
|
+
tokenUsage: {
|
|
2461
|
+
prompt: promptTokens,
|
|
2462
|
+
completion: completionTokens,
|
|
2463
|
+
total: promptTokens + completionTokens
|
|
2464
|
+
},
|
|
2465
|
+
customScores: {}
|
|
2466
|
+
};
|
|
2467
|
+
for (const scorer of _nullishCoalesce(this.options.scorers, () => ( []))) {
|
|
2468
|
+
try {
|
|
2469
|
+
metrics.customScores[scorer.name] = await scorer.score(
|
|
2470
|
+
prompt,
|
|
2471
|
+
params.result.text,
|
|
2472
|
+
metrics
|
|
2473
|
+
);
|
|
2474
|
+
} catch (e10) {
|
|
2475
|
+
metrics.customScores[scorer.name] = -1;
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
const evalResult = {
|
|
2479
|
+
id: crypto.randomUUID(),
|
|
2480
|
+
sessionId: params.result.sessionId,
|
|
2481
|
+
prompt,
|
|
2482
|
+
output: params.result.text,
|
|
2483
|
+
metrics,
|
|
2484
|
+
createdAt: Date.now()
|
|
2485
|
+
};
|
|
2486
|
+
this.results.push(evalResult);
|
|
2487
|
+
if (this.options.persist) {
|
|
2488
|
+
await ctx.memory.saveMetadata(
|
|
2489
|
+
ctx.sessionId,
|
|
2490
|
+
`eval:${evalResult.id}`,
|
|
2491
|
+
evalResult
|
|
2492
|
+
);
|
|
2493
|
+
}
|
|
2494
|
+
if (this.options.onEval) {
|
|
2495
|
+
await this.options.onEval(evalResult);
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
afterTool(ctx, params) {
|
|
2499
|
+
const state = this.runStates.get(ctx.sessionId);
|
|
2500
|
+
if (state) {
|
|
2501
|
+
state.toolCallCounts[params.toolName] = (_nullishCoalesce(state.toolCallCounts[params.toolName], () => ( 0))) + 1;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
onError(ctx, params) {
|
|
2505
|
+
if (params.phase === "run") {
|
|
2506
|
+
this.runStates.delete(ctx.sessionId);
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
/** Get all collected eval results */
|
|
2510
|
+
getResults() {
|
|
2511
|
+
return this.results;
|
|
2512
|
+
}
|
|
2513
|
+
/** Get the most recent eval result */
|
|
2514
|
+
getLastResult() {
|
|
2515
|
+
return this.results[this.results.length - 1];
|
|
2516
|
+
}
|
|
2517
|
+
/** Clear collected results */
|
|
2518
|
+
clearResults() {
|
|
2519
|
+
this.results.length = 0;
|
|
2520
|
+
}
|
|
2521
|
+
}, _class9);
|
|
2522
|
+
function createEvalsPlugin(options = {}) {
|
|
2523
|
+
return new EvalsPlugin(options);
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
// src/adapters/workflow/default-workflow.engine.ts
|
|
2527
|
+
var DEFAULT_RETRY = {
|
|
2528
|
+
maxAttempts: 3,
|
|
2529
|
+
backoffMs: 1e3,
|
|
2530
|
+
backoffMultiplier: 2
|
|
2531
|
+
};
|
|
2532
|
+
var DEFAULT_MAX_ITERATIONS = 10;
|
|
2533
|
+
var DEFAULT_MAX_CONCURRENCY = 1;
|
|
2534
|
+
var DefaultWorkflowEngine = class {
|
|
2535
|
+
|
|
2536
|
+
|
|
2537
|
+
constructor(options = {}) {
|
|
2538
|
+
this.agentExecutor = options.agentExecutor;
|
|
2539
|
+
this.onEvent = options.onEvent;
|
|
2540
|
+
}
|
|
2541
|
+
async execute(definition, context) {
|
|
2542
|
+
const start = Date.now();
|
|
2543
|
+
let ctx = structuredClone(_nullishCoalesce(definition.initialContext, () => ( {})));
|
|
2544
|
+
if (context) {
|
|
2545
|
+
ctx = { ...ctx, ...structuredClone(context) };
|
|
2546
|
+
}
|
|
2547
|
+
const completedSteps = [];
|
|
2548
|
+
const skippedSteps = [];
|
|
2549
|
+
const executedRegistry = /* @__PURE__ */ new Map();
|
|
2550
|
+
const timeoutMs = definition.maxDurationMs;
|
|
2551
|
+
const deadline = timeoutMs ? start + timeoutMs : void 0;
|
|
2552
|
+
for (const step of definition.steps) {
|
|
2553
|
+
if (deadline && Date.now() >= deadline) {
|
|
2554
|
+
await this.rollbackSteps(executedRegistry, completedSteps, ctx);
|
|
2555
|
+
return {
|
|
2556
|
+
status: "failed",
|
|
2557
|
+
context: ctx,
|
|
2558
|
+
completedSteps,
|
|
2559
|
+
skippedSteps,
|
|
2560
|
+
failedStep: step.id,
|
|
2561
|
+
error: `Workflow timeout exceeded (${timeoutMs}ms)`,
|
|
2562
|
+
totalDurationMs: Date.now() - start
|
|
2563
|
+
};
|
|
2564
|
+
}
|
|
2565
|
+
try {
|
|
2566
|
+
const stepResult = await this.executeStep(step, ctx, completedSteps, skippedSteps, executedRegistry, deadline);
|
|
2567
|
+
if (skippedSteps.includes(step.id)) {
|
|
2568
|
+
continue;
|
|
2569
|
+
}
|
|
2570
|
+
ctx = stepResult;
|
|
2571
|
+
completedSteps.push(step.id);
|
|
2572
|
+
} catch (error) {
|
|
2573
|
+
await this.rollbackSteps(executedRegistry, completedSteps, ctx);
|
|
2574
|
+
return {
|
|
2575
|
+
status: "failed",
|
|
2576
|
+
context: ctx,
|
|
2577
|
+
completedSteps,
|
|
2578
|
+
skippedSteps,
|
|
2579
|
+
failedStep: step.id,
|
|
2580
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2581
|
+
totalDurationMs: Date.now() - start
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
return {
|
|
2586
|
+
status: "completed",
|
|
2587
|
+
context: ctx,
|
|
2588
|
+
completedSteps,
|
|
2589
|
+
skippedSteps,
|
|
2590
|
+
totalDurationMs: Date.now() - start
|
|
2591
|
+
};
|
|
2592
|
+
}
|
|
2593
|
+
validate(definition) {
|
|
2594
|
+
const errors = [];
|
|
2595
|
+
if (!definition.id) errors.push("Workflow must have an id");
|
|
2596
|
+
if (!definition.name) errors.push("Workflow must have a name");
|
|
2597
|
+
if (!definition.steps || !Array.isArray(definition.steps)) {
|
|
2598
|
+
errors.push("Workflow must have a steps array");
|
|
2599
|
+
} else if (definition.steps.length === 0) {
|
|
2600
|
+
errors.push("Workflow must have at least one step");
|
|
2601
|
+
}
|
|
2602
|
+
const ids = /* @__PURE__ */ new Set();
|
|
2603
|
+
for (const step of _nullishCoalesce(definition.steps, () => ( []))) {
|
|
2604
|
+
if (!step.id) errors.push("Every step must have an id");
|
|
2605
|
+
if (!step.name) errors.push(`Step "${step.id}" must have a name`);
|
|
2606
|
+
if (ids.has(step.id)) errors.push(`Duplicate step id: "${step.id}"`);
|
|
2607
|
+
ids.add(step.id);
|
|
2608
|
+
this.validateStep(step, errors);
|
|
2609
|
+
}
|
|
2610
|
+
if (definition.maxDurationMs !== void 0 && definition.maxDurationMs <= 0) {
|
|
2611
|
+
errors.push("maxDurationMs must be positive");
|
|
2612
|
+
}
|
|
2613
|
+
return { valid: errors.length === 0, errors };
|
|
2614
|
+
}
|
|
2615
|
+
// ── Step execution ──────────────────────────────────────────────────────
|
|
2616
|
+
async executeStep(step, ctx, completedSteps, skippedSteps, registry, deadline) {
|
|
2617
|
+
this.emit({ type: "step:start", stepId: step.id, stepName: step.name, timestamp: Date.now() });
|
|
2618
|
+
try {
|
|
2619
|
+
let result;
|
|
2620
|
+
if (this.isParallelStep(step)) {
|
|
2621
|
+
result = await this.executeParallel(step, ctx, registry, deadline);
|
|
2622
|
+
} else if (this.isConditionalStep(step)) {
|
|
2623
|
+
result = await this.executeConditional(step, ctx, completedSteps, skippedSteps, registry, deadline);
|
|
2624
|
+
} else if (this.isLoopStep(step)) {
|
|
2625
|
+
result = await this.executeLoop(step, ctx, registry, deadline);
|
|
2626
|
+
} else if (this.isForeachStep(step)) {
|
|
2627
|
+
result = await this.executeForeach(step, ctx, registry, deadline);
|
|
2628
|
+
} else if (this.isMapStep(step)) {
|
|
2629
|
+
result = await this.executeMap(step, ctx, registry, deadline);
|
|
2630
|
+
} else if (this.isAgentStep(step)) {
|
|
2631
|
+
result = await this.executeAgent(step, ctx);
|
|
2632
|
+
if ("rollback" in step && typeof step.rollback === "function") {
|
|
2633
|
+
registry.set(step.id, step);
|
|
2634
|
+
}
|
|
2635
|
+
} else {
|
|
2636
|
+
const ws = step;
|
|
2637
|
+
if (ws.condition && !ws.condition(ctx)) {
|
|
2638
|
+
skippedSteps.push(step.id);
|
|
2639
|
+
this.emit({ type: "step:complete", stepId: step.id, stepName: step.name, timestamp: Date.now(), context: ctx });
|
|
2640
|
+
return ctx;
|
|
2641
|
+
}
|
|
2642
|
+
const projectedCtx = this.applyInputMapping(ws, ctx);
|
|
2643
|
+
const rawResult = await this.executeWithRetry(ws, projectedCtx);
|
|
2644
|
+
result = ws.inputMapping ? { ...ctx, ...rawResult } : rawResult;
|
|
2645
|
+
result = this.applyOutputMappings(ws, result);
|
|
2646
|
+
if (ws.rollback) {
|
|
2647
|
+
registry.set(step.id, ws);
|
|
2648
|
+
}
|
|
2649
|
+
}
|
|
2650
|
+
this.emit({ type: "step:complete", stepId: step.id, stepName: step.name, timestamp: Date.now(), context: result });
|
|
2651
|
+
return result;
|
|
2652
|
+
} catch (error) {
|
|
2653
|
+
const errMsg = error instanceof Error ? error.message : String(error);
|
|
2654
|
+
this.emit({ type: "step:error", stepId: step.id, stepName: step.name, timestamp: Date.now(), error: errMsg });
|
|
2655
|
+
throw error;
|
|
2656
|
+
}
|
|
2657
|
+
}
|
|
2658
|
+
async executeParallel(step, ctx, registry, deadline) {
|
|
2659
|
+
const strategy = _nullishCoalesce(step.mergeStrategy, () => ( "all"));
|
|
2660
|
+
const branchCtx = structuredClone(ctx);
|
|
2661
|
+
const wrapWithTimeout = (promise) => {
|
|
2662
|
+
if (!deadline) return promise;
|
|
2663
|
+
const remaining = deadline - Date.now();
|
|
2664
|
+
if (remaining <= 0) return Promise.reject(new Error("Workflow timeout exceeded"));
|
|
2665
|
+
let timer;
|
|
2666
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
2667
|
+
timer = setTimeout(() => reject(new Error("Workflow timeout exceeded")), remaining);
|
|
2668
|
+
});
|
|
2669
|
+
return Promise.race([promise, timeoutPromise]).finally(() => clearTimeout(timer));
|
|
2670
|
+
};
|
|
2671
|
+
const promises = step.branches.map((branch) => {
|
|
2672
|
+
if (branch.rollback) registry.set(branch.id, branch);
|
|
2673
|
+
return wrapWithTimeout(this.executeWithRetry(branch, structuredClone(branchCtx)));
|
|
2674
|
+
});
|
|
2675
|
+
if (strategy === "race") {
|
|
2676
|
+
return await Promise.race(promises);
|
|
2677
|
+
}
|
|
2678
|
+
if (strategy === "first") {
|
|
2679
|
+
return await Promise.any(promises);
|
|
2680
|
+
}
|
|
2681
|
+
const results = await Promise.all(promises);
|
|
2682
|
+
let merged = structuredClone(ctx);
|
|
2683
|
+
for (const r of results) {
|
|
2684
|
+
merged = { ...merged, ...r };
|
|
2685
|
+
}
|
|
2686
|
+
return merged;
|
|
2687
|
+
}
|
|
2688
|
+
async executeConditional(step, ctx, completedSteps, skippedSteps, registry, deadline) {
|
|
2689
|
+
if (step.condition(ctx)) {
|
|
2690
|
+
return this.executeStep(step.ifTrue, structuredClone(ctx), completedSteps, skippedSteps, registry, deadline);
|
|
2691
|
+
} else if (step.ifFalse) {
|
|
2692
|
+
return this.executeStep(step.ifFalse, structuredClone(ctx), completedSteps, skippedSteps, registry, deadline);
|
|
2693
|
+
}
|
|
2694
|
+
return ctx;
|
|
2695
|
+
}
|
|
2696
|
+
async executeLoop(step, ctx, registry, deadline) {
|
|
2697
|
+
const maxIter = _nullishCoalesce(step.maxIterations, () => ( DEFAULT_MAX_ITERATIONS));
|
|
2698
|
+
let current = structuredClone(ctx);
|
|
2699
|
+
if (step.body.rollback) {
|
|
2700
|
+
registry.set(step.body.id, step.body);
|
|
2701
|
+
}
|
|
2702
|
+
for (let i = 0; i < maxIter; i++) {
|
|
2703
|
+
if (!step.condition(current)) break;
|
|
2704
|
+
if (deadline && Date.now() >= deadline) {
|
|
2705
|
+
throw new Error("Workflow timeout exceeded");
|
|
2706
|
+
}
|
|
2707
|
+
current = await this.executeWithRetry(step.body, current);
|
|
2708
|
+
}
|
|
2709
|
+
return current;
|
|
2710
|
+
}
|
|
2711
|
+
async executeForeach(step, ctx, registry, deadline) {
|
|
2712
|
+
const iterable = this.getByPath(ctx, step.iterable);
|
|
2713
|
+
if (!Array.isArray(iterable)) {
|
|
2714
|
+
throw new Error(`Foreach step "${step.id}": iterable path "${step.iterable}" is not an array`);
|
|
2715
|
+
}
|
|
2716
|
+
const maxIter = step.maxIterations ? Math.min(step.maxIterations, iterable.length) : iterable.length;
|
|
2717
|
+
const items = iterable.slice(0, maxIter);
|
|
2718
|
+
const itemKey = _nullishCoalesce(step.itemKey, () => ( "item"));
|
|
2719
|
+
const indexKey = _nullishCoalesce(step.indexKey, () => ( "index"));
|
|
2720
|
+
const outputs = await this.executeItemsWithConcurrency(
|
|
2721
|
+
items,
|
|
2722
|
+
_nullishCoalesce(step.maxConcurrency, () => ( DEFAULT_MAX_CONCURRENCY)),
|
|
2723
|
+
async (item, index) => {
|
|
2724
|
+
if (deadline && Date.now() >= deadline) {
|
|
2725
|
+
throw new Error("Workflow timeout exceeded");
|
|
2726
|
+
}
|
|
2727
|
+
const itemCtx = {
|
|
2728
|
+
...ctx,
|
|
2729
|
+
[itemKey]: item,
|
|
2730
|
+
[indexKey]: index
|
|
2731
|
+
};
|
|
2732
|
+
if (step.step.rollback) {
|
|
2733
|
+
registry.set(step.step.id, step.step);
|
|
2734
|
+
}
|
|
2735
|
+
const projectedCtx = this.applyInputMapping(step.step, itemCtx);
|
|
2736
|
+
const rawResult = await this.executeWithRetry(step.step, projectedCtx);
|
|
2737
|
+
const mergedResult = step.step.inputMapping ? { ...itemCtx, ...rawResult } : rawResult;
|
|
2738
|
+
const mappedResult = this.applyOutputMappings(step.step, mergedResult);
|
|
2739
|
+
return this.extractStepOutput(mappedResult, step.step.id);
|
|
2740
|
+
}
|
|
2741
|
+
);
|
|
2742
|
+
const aggregateKey = _nullishCoalesce(step.aggregateOutputKey, () => ( step.id));
|
|
2743
|
+
return {
|
|
2744
|
+
...ctx,
|
|
2745
|
+
[aggregateKey]: this.aggregateOutputs(outputs, _nullishCoalesce(step.aggregationMode, () => ( "array")))
|
|
2746
|
+
};
|
|
2747
|
+
}
|
|
2748
|
+
async executeMap(step, ctx, registry, deadline) {
|
|
2749
|
+
const source = this.getByPath(ctx, step.input);
|
|
2750
|
+
if (!Array.isArray(source)) {
|
|
2751
|
+
throw new Error(`Map step "${step.id}": input path "${step.input}" is not an array`);
|
|
2752
|
+
}
|
|
2753
|
+
const filtered = source.filter(
|
|
2754
|
+
(item, index) => step.filter ? step.filter(item, index, ctx) : true
|
|
2755
|
+
);
|
|
2756
|
+
const itemKey = _nullishCoalesce(step.itemKey, () => ( "item"));
|
|
2757
|
+
const indexKey = _nullishCoalesce(step.indexKey, () => ( "index"));
|
|
2758
|
+
const transformed = await this.executeItemsWithConcurrency(
|
|
2759
|
+
filtered,
|
|
2760
|
+
_nullishCoalesce(step.maxConcurrency, () => ( DEFAULT_MAX_CONCURRENCY)),
|
|
2761
|
+
async (item, index) => {
|
|
2762
|
+
if (deadline && Date.now() >= deadline) {
|
|
2763
|
+
throw new Error("Workflow timeout exceeded");
|
|
2764
|
+
}
|
|
2765
|
+
const itemCtx = {
|
|
2766
|
+
...ctx,
|
|
2767
|
+
[itemKey]: item,
|
|
2768
|
+
[indexKey]: index
|
|
2769
|
+
};
|
|
2770
|
+
if (step.transform.rollback) {
|
|
2771
|
+
registry.set(step.transform.id, step.transform);
|
|
2772
|
+
}
|
|
2773
|
+
const projectedCtx = this.applyInputMapping(step.transform, itemCtx);
|
|
2774
|
+
const rawResult = await this.executeWithRetry(step.transform, projectedCtx);
|
|
2775
|
+
const mergedResult = step.transform.inputMapping ? { ...itemCtx, ...rawResult } : rawResult;
|
|
2776
|
+
const mappedResult = this.applyOutputMappings(step.transform, mergedResult);
|
|
2777
|
+
return this.extractStepOutput(mappedResult, step.transform.id);
|
|
2778
|
+
}
|
|
2779
|
+
);
|
|
2780
|
+
return {
|
|
2781
|
+
...ctx,
|
|
2782
|
+
[step.outputKey]: transformed
|
|
2783
|
+
};
|
|
2784
|
+
}
|
|
2785
|
+
async executeAgent(step, ctx) {
|
|
2786
|
+
if (step.execute) {
|
|
2787
|
+
return this.executeWithRetry(step, ctx);
|
|
2788
|
+
}
|
|
2789
|
+
if (!this.agentExecutor) {
|
|
2790
|
+
throw new Error(`AgentStep "${step.id}" requires an agentExecutor`);
|
|
2791
|
+
}
|
|
2792
|
+
const prompt = typeof step.prompt === "function" ? step.prompt(ctx) : step.prompt;
|
|
2793
|
+
const retry = { ...DEFAULT_RETRY, ...step.retry };
|
|
2794
|
+
let lastError;
|
|
2795
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt++) {
|
|
2796
|
+
try {
|
|
2797
|
+
const result = await this.agentExecutor(prompt, structuredClone(ctx));
|
|
2798
|
+
return { ...ctx, [step.outputKey]: result };
|
|
2799
|
+
} catch (error) {
|
|
2800
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
2801
|
+
if (attempt < retry.maxAttempts) {
|
|
2802
|
+
const delay = retry.backoffMs * Math.pow(retry.backoffMultiplier, attempt - 1);
|
|
2803
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
throw lastError;
|
|
2808
|
+
}
|
|
2809
|
+
// ── Retry ───────────────────────────────────────────────────────────────
|
|
2810
|
+
async executeWithRetry(step, ctx) {
|
|
2811
|
+
const retry = { ...DEFAULT_RETRY, ...step.retry };
|
|
2812
|
+
let lastError;
|
|
2813
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt++) {
|
|
2814
|
+
try {
|
|
2815
|
+
return await step.execute(structuredClone(ctx));
|
|
2816
|
+
} catch (error) {
|
|
2817
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
2818
|
+
if (attempt < retry.maxAttempts) {
|
|
2819
|
+
const delay = retry.backoffMs * Math.pow(retry.backoffMultiplier, attempt - 1);
|
|
2820
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
}
|
|
2824
|
+
throw lastError;
|
|
2825
|
+
}
|
|
2826
|
+
// ── Rollback ────────────────────────────────────────────────────────────
|
|
2827
|
+
async rollbackSteps(registry, completedStepIds, ctx) {
|
|
2828
|
+
const allIds = [...completedStepIds, ...Array.from(registry.keys())];
|
|
2829
|
+
const uniqueIds = [...new Set(allIds)].reverse();
|
|
2830
|
+
for (const stepId of uniqueIds) {
|
|
2831
|
+
const step = registry.get(stepId);
|
|
2832
|
+
if (_optionalChain([step, 'optionalAccess', _71 => _71.rollback])) {
|
|
2833
|
+
try {
|
|
2834
|
+
await step.rollback(ctx);
|
|
2835
|
+
} catch (e11) {
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
// ── Helpers ─────────────────────────────────────────────────────────────
|
|
2841
|
+
emit(event) {
|
|
2842
|
+
_optionalChain([this, 'access', _72 => _72.onEvent, 'optionalCall', _73 => _73(event)]);
|
|
2843
|
+
}
|
|
2844
|
+
isParallelStep(step) {
|
|
2845
|
+
return step.type === "parallel";
|
|
2846
|
+
}
|
|
2847
|
+
isConditionalStep(step) {
|
|
2848
|
+
return step.type === "conditional";
|
|
2849
|
+
}
|
|
2850
|
+
isLoopStep(step) {
|
|
2851
|
+
return step.type === "loop";
|
|
2852
|
+
}
|
|
2853
|
+
isForeachStep(step) {
|
|
2854
|
+
return step.type === "foreach";
|
|
2855
|
+
}
|
|
2856
|
+
isMapStep(step) {
|
|
2857
|
+
return step.type === "map";
|
|
2858
|
+
}
|
|
2859
|
+
isAgentStep(step) {
|
|
2860
|
+
return step.type === "agent";
|
|
2861
|
+
}
|
|
2862
|
+
validateStep(step, errors) {
|
|
2863
|
+
if (this.isParallelStep(step)) {
|
|
2864
|
+
if (!step.branches || step.branches.length === 0) {
|
|
2865
|
+
errors.push(`Parallel step "${step.id}" must have at least one branch`);
|
|
2866
|
+
}
|
|
2867
|
+
} else if (this.isConditionalStep(step)) {
|
|
2868
|
+
if (!step.condition) errors.push(`Conditional step "${step.id}" must have a condition`);
|
|
2869
|
+
if (!step.ifTrue) errors.push(`Conditional step "${step.id}" must have an ifTrue step`);
|
|
2870
|
+
} else if (this.isLoopStep(step)) {
|
|
2871
|
+
if (!step.body) errors.push(`Loop step "${step.id}" must have a body`);
|
|
2872
|
+
if (!step.condition) errors.push(`Loop step "${step.id}" must have a condition`);
|
|
2873
|
+
} else if (this.isForeachStep(step)) {
|
|
2874
|
+
if (!step.iterable) errors.push(`Foreach step "${step.id}" must define iterable path`);
|
|
2875
|
+
if (!step.step) errors.push(`Foreach step "${step.id}" must define an item step`);
|
|
2876
|
+
if (step.maxConcurrency !== void 0 && step.maxConcurrency < 1) {
|
|
2877
|
+
errors.push(`Foreach step "${step.id}" maxConcurrency must be >= 1`);
|
|
2878
|
+
}
|
|
2879
|
+
if (step.maxIterations !== void 0 && step.maxIterations < 1) {
|
|
2880
|
+
errors.push(`Foreach step "${step.id}" maxIterations must be >= 1`);
|
|
2881
|
+
}
|
|
2882
|
+
} else if (this.isMapStep(step)) {
|
|
2883
|
+
if (!step.input) errors.push(`Map step "${step.id}" must define input path`);
|
|
2884
|
+
if (!step.transform) errors.push(`Map step "${step.id}" must define transform step`);
|
|
2885
|
+
if (!step.outputKey) errors.push(`Map step "${step.id}" must define outputKey`);
|
|
2886
|
+
if (step.maxConcurrency !== void 0 && step.maxConcurrency < 1) {
|
|
2887
|
+
errors.push(`Map step "${step.id}" maxConcurrency must be >= 1`);
|
|
2888
|
+
}
|
|
2889
|
+
} else if (this.isAgentStep(step)) {
|
|
2890
|
+
if (!step.prompt) errors.push(`Agent step "${step.id}" must have a prompt`);
|
|
2891
|
+
if (!step.outputKey) errors.push(`Agent step "${step.id}" must have an outputKey`);
|
|
2892
|
+
} else {
|
|
2893
|
+
const ws = step;
|
|
2894
|
+
if (!ws.execute) errors.push(`Step "${step.id}" must have an execute function`);
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
getByPath(ctx, path) {
|
|
2898
|
+
if (!path) return void 0;
|
|
2899
|
+
const normalized = path.replace(/\[(\d+)\]/g, ".$1");
|
|
2900
|
+
const segments = normalized.split(".").filter(Boolean);
|
|
2901
|
+
let current = ctx;
|
|
2902
|
+
for (const segment of segments) {
|
|
2903
|
+
if (current === null || current === void 0) return void 0;
|
|
2904
|
+
if (Array.isArray(current)) {
|
|
2905
|
+
const index = Number(segment);
|
|
2906
|
+
if (!Number.isInteger(index)) return void 0;
|
|
2907
|
+
current = current[index];
|
|
2908
|
+
continue;
|
|
2909
|
+
}
|
|
2910
|
+
if (typeof current !== "object") return void 0;
|
|
2911
|
+
current = current[segment];
|
|
2912
|
+
}
|
|
2913
|
+
return current;
|
|
2914
|
+
}
|
|
2915
|
+
applyInputMapping(step, ctx) {
|
|
2916
|
+
const mapping = step.inputMapping;
|
|
2917
|
+
if (!mapping) {
|
|
2918
|
+
return ctx;
|
|
2919
|
+
}
|
|
2920
|
+
let projected = mapping.defaults ? { ...mapping.defaults } : {};
|
|
2921
|
+
if (mapping.keys) {
|
|
2922
|
+
for (const key of mapping.keys) {
|
|
2923
|
+
if (key in ctx) {
|
|
2924
|
+
projected[key] = ctx[key];
|
|
2925
|
+
}
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
if (mapping.paths) {
|
|
2929
|
+
for (const [targetKey, path] of Object.entries(mapping.paths)) {
|
|
2930
|
+
projected[targetKey] = this.getByPath(ctx, path);
|
|
2931
|
+
}
|
|
2932
|
+
}
|
|
2933
|
+
if (mapping.overrides) {
|
|
2934
|
+
projected = {
|
|
2935
|
+
...projected,
|
|
2936
|
+
...mapping.overrides
|
|
2937
|
+
};
|
|
2938
|
+
}
|
|
2939
|
+
return projected;
|
|
2940
|
+
}
|
|
2941
|
+
applyOutputMappings(step, result) {
|
|
2942
|
+
if (!step.outputMapping || step.outputMapping.length === 0) {
|
|
2943
|
+
return result;
|
|
2944
|
+
}
|
|
2945
|
+
const mapped = { ...result };
|
|
2946
|
+
for (const mapping of step.outputMapping) {
|
|
2947
|
+
let value = this.getByPath(result, mapping.source);
|
|
2948
|
+
if (mapping.transform) {
|
|
2949
|
+
value = mapping.transform(value, result);
|
|
2950
|
+
}
|
|
2951
|
+
if (value === void 0) {
|
|
2952
|
+
value = mapping.defaultValue;
|
|
2953
|
+
}
|
|
2954
|
+
mapped[mapping.targetKey] = value;
|
|
2955
|
+
}
|
|
2956
|
+
return mapped;
|
|
2957
|
+
}
|
|
2958
|
+
extractStepOutput(result, stepId) {
|
|
2959
|
+
if (stepId in result) {
|
|
2960
|
+
return result[stepId];
|
|
2961
|
+
}
|
|
2962
|
+
return result;
|
|
2963
|
+
}
|
|
2964
|
+
aggregateOutputs(outputs, mode) {
|
|
2965
|
+
if (mode === "concat") {
|
|
2966
|
+
return outputs.flatMap(
|
|
2967
|
+
(output) => Array.isArray(output) ? output : [output]
|
|
2968
|
+
);
|
|
2969
|
+
}
|
|
2970
|
+
if (mode === "merge") {
|
|
2971
|
+
const merged = {};
|
|
2972
|
+
for (const output of outputs) {
|
|
2973
|
+
if (output && typeof output === "object" && !Array.isArray(output)) {
|
|
2974
|
+
Object.assign(merged, output);
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
return merged;
|
|
2978
|
+
}
|
|
2979
|
+
return outputs;
|
|
2980
|
+
}
|
|
2981
|
+
async executeItemsWithConcurrency(items, concurrency, worker) {
|
|
2982
|
+
const safeConcurrency = Math.max(1, Math.floor(concurrency));
|
|
2983
|
+
if (safeConcurrency === 1 || items.length <= 1) {
|
|
2984
|
+
const sequential = [];
|
|
2985
|
+
for (let i = 0; i < items.length; i++) {
|
|
2986
|
+
sequential.push(await worker(items[i], i));
|
|
2987
|
+
}
|
|
2988
|
+
return sequential;
|
|
2989
|
+
}
|
|
2990
|
+
const results = new Array(items.length);
|
|
2991
|
+
let nextIndex = 0;
|
|
2992
|
+
const workers = Array.from(
|
|
2993
|
+
{ length: Math.min(safeConcurrency, items.length) },
|
|
2994
|
+
async () => {
|
|
2995
|
+
while (true) {
|
|
2996
|
+
const current = nextIndex;
|
|
2997
|
+
nextIndex++;
|
|
2998
|
+
if (current >= items.length) return;
|
|
2999
|
+
results[current] = await worker(items[current], current);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
);
|
|
3003
|
+
await Promise.all(workers);
|
|
3004
|
+
return results;
|
|
3005
|
+
}
|
|
3006
|
+
};
|
|
3007
|
+
|
|
3008
|
+
// src/plugins/workflow.plugin.ts
|
|
3009
|
+
var DEFAULT_RETRY2 = {
|
|
3010
|
+
maxAttempts: 3,
|
|
3011
|
+
backoffMs: 1e3,
|
|
3012
|
+
backoffMultiplier: 2
|
|
3013
|
+
};
|
|
3014
|
+
var WorkflowError = class extends Error {
|
|
3015
|
+
|
|
3016
|
+
constructor(message, result) {
|
|
3017
|
+
super(message);
|
|
3018
|
+
this.name = "WorkflowError";
|
|
3019
|
+
this.result = result;
|
|
3020
|
+
}
|
|
3021
|
+
};
|
|
3022
|
+
function isWorkflowDefinition(input) {
|
|
3023
|
+
return "id" in input && "name" in input;
|
|
3024
|
+
}
|
|
3025
|
+
var WorkflowPlugin = (_class10 = class extends BasePlugin {
|
|
3026
|
+
__init23() {this.name = "workflow"}
|
|
3027
|
+
|
|
3028
|
+
|
|
3029
|
+
|
|
3030
|
+
|
|
3031
|
+
|
|
3032
|
+
constructor(config, engine) {
|
|
3033
|
+
super();_class10.prototype.__init23.call(this);;
|
|
3034
|
+
if (isWorkflowDefinition(config)) {
|
|
3035
|
+
this.definition = config;
|
|
3036
|
+
this.steps = config.steps;
|
|
3037
|
+
this.initialContext = _nullishCoalesce(config.initialContext, () => ( {}));
|
|
3038
|
+
this.engine = _nullishCoalesce(engine, () => ( new DefaultWorkflowEngine()));
|
|
3039
|
+
} else {
|
|
3040
|
+
this.steps = config.steps;
|
|
3041
|
+
this.initialContext = _nullishCoalesce(config.initialContext, () => ( {}));
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
buildHooks() {
|
|
3045
|
+
return {
|
|
3046
|
+
beforeRun: this.beforeRun.bind(this)
|
|
3047
|
+
};
|
|
3048
|
+
}
|
|
3049
|
+
getLastResult() {
|
|
3050
|
+
return this.lastResult;
|
|
3051
|
+
}
|
|
3052
|
+
// ── Hook implementation ─────────────────────────────────────────────────
|
|
3053
|
+
async beforeRun(_ctx, params) {
|
|
3054
|
+
const result = this.definition && this.engine ? await this.engine.execute(this.definition) : await this.executeWorkflow();
|
|
3055
|
+
this.lastResult = result;
|
|
3056
|
+
if (result.status === "failed") {
|
|
3057
|
+
throw new WorkflowError(
|
|
3058
|
+
`Workflow failed at step "${result.failedStep}": ${result.error}`,
|
|
3059
|
+
result
|
|
3060
|
+
);
|
|
3061
|
+
}
|
|
3062
|
+
const contextSummary = Object.entries(result.context).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join("\n");
|
|
3063
|
+
return {
|
|
3064
|
+
prompt: `${params.prompt}
|
|
3065
|
+
|
|
3066
|
+
--- Workflow Context ---
|
|
3067
|
+
${contextSummary}`
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
// ── Built-in workflow engine (backward compatible) ──────────────────────
|
|
3071
|
+
async executeWorkflow() {
|
|
3072
|
+
const start = Date.now();
|
|
3073
|
+
let context = structuredClone(this.initialContext);
|
|
3074
|
+
const completedSteps = [];
|
|
3075
|
+
const skippedSteps = [];
|
|
3076
|
+
for (const step of this.steps) {
|
|
3077
|
+
if (step.condition && !step.condition(context)) {
|
|
3078
|
+
skippedSteps.push(step.id);
|
|
3079
|
+
continue;
|
|
3080
|
+
}
|
|
3081
|
+
try {
|
|
3082
|
+
context = await this.executeWithRetry(step, context);
|
|
3083
|
+
completedSteps.push(step.id);
|
|
3084
|
+
} catch (error) {
|
|
3085
|
+
await this.rollback(completedSteps, context);
|
|
3086
|
+
return {
|
|
3087
|
+
status: "failed",
|
|
3088
|
+
context,
|
|
3089
|
+
completedSteps,
|
|
3090
|
+
skippedSteps,
|
|
3091
|
+
failedStep: step.id,
|
|
3092
|
+
error: error instanceof Error ? error.message : String(error),
|
|
3093
|
+
totalDurationMs: Date.now() - start
|
|
3094
|
+
};
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
return {
|
|
3098
|
+
status: "completed",
|
|
3099
|
+
context,
|
|
3100
|
+
completedSteps,
|
|
3101
|
+
skippedSteps,
|
|
3102
|
+
totalDurationMs: Date.now() - start
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
async executeWithRetry(step, context) {
|
|
3106
|
+
const retry = { ...DEFAULT_RETRY2, ...step.retry };
|
|
3107
|
+
let lastError;
|
|
3108
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt++) {
|
|
3109
|
+
try {
|
|
3110
|
+
return await step.execute(context);
|
|
3111
|
+
} catch (error) {
|
|
3112
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
3113
|
+
if (attempt < retry.maxAttempts) {
|
|
3114
|
+
const delay = retry.backoffMs * Math.pow(retry.backoffMultiplier, attempt - 1);
|
|
3115
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
}
|
|
3119
|
+
throw lastError;
|
|
3120
|
+
}
|
|
3121
|
+
async rollback(completedStepIds, context) {
|
|
3122
|
+
for (const stepId of [...completedStepIds].reverse()) {
|
|
3123
|
+
const step = this.steps.find((s) => s.id === stepId);
|
|
3124
|
+
if (_optionalChain([step, 'optionalAccess', _74 => _74.rollback])) {
|
|
3125
|
+
try {
|
|
3126
|
+
await step.rollback(context);
|
|
3127
|
+
} catch (e12) {
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
}, _class10);
|
|
3133
|
+
function createWorkflowPlugin(config, engine) {
|
|
3134
|
+
return new WorkflowPlugin(config, engine);
|
|
3135
|
+
}
|
|
3136
|
+
|
|
3137
|
+
// src/plugins/utils/default-metrics.ts
|
|
3138
|
+
function createDefaultMetrics() {
|
|
3139
|
+
return {
|
|
3140
|
+
totalTokens: { input: 0, output: 0 },
|
|
3141
|
+
totalLatencyMs: 0,
|
|
3142
|
+
toolCalls: [],
|
|
3143
|
+
llmCalls: []
|
|
3144
|
+
};
|
|
3145
|
+
}
|
|
3146
|
+
|
|
3147
|
+
// src/plugins/observability.plugin.ts
|
|
3148
|
+
var ObservabilityPlugin = (_class11 = class extends BasePlugin {
|
|
3149
|
+
__init24() {this.name = "observability"}
|
|
3150
|
+
__init25() {this.version = "1.0.0"}
|
|
3151
|
+
|
|
3152
|
+
__init26() {this.spans = /* @__PURE__ */ new Map()}
|
|
3153
|
+
__init27() {this.rootSpans = []}
|
|
3154
|
+
__init28() {this.activeSpans = /* @__PURE__ */ new Map()}
|
|
3155
|
+
// sessionId → current root span
|
|
3156
|
+
__init29() {this.sessionMetrics = /* @__PURE__ */ new Map()}
|
|
3157
|
+
// sessionId → metrics
|
|
3158
|
+
__init30() {this.sessionStartTimes = /* @__PURE__ */ new Map()}
|
|
3159
|
+
// sessionId → run start time
|
|
3160
|
+
__init31() {this.toolStartTimes = /* @__PURE__ */ new Map()}
|
|
3161
|
+
// sessionId:toolName → start time stack (LIFO)
|
|
3162
|
+
__init32() {this.toolSpanStack = /* @__PURE__ */ new Map()}
|
|
3163
|
+
// sessionId:toolName → spanId stack (LIFO)
|
|
3164
|
+
|
|
3165
|
+
constructor(config = {}) {
|
|
3166
|
+
super();_class11.prototype.__init24.call(this);_class11.prototype.__init25.call(this);_class11.prototype.__init26.call(this);_class11.prototype.__init27.call(this);_class11.prototype.__init28.call(this);_class11.prototype.__init29.call(this);_class11.prototype.__init30.call(this);_class11.prototype.__init31.call(this);_class11.prototype.__init32.call(this);;
|
|
3167
|
+
this.config = {
|
|
3168
|
+
enableTracing: true,
|
|
3169
|
+
enableMetrics: true,
|
|
3170
|
+
enableCostEstimation: false,
|
|
3171
|
+
...config
|
|
3172
|
+
};
|
|
3173
|
+
this.maxSpans = _nullishCoalesce(config.maxSpans, () => ( 1e4));
|
|
3174
|
+
}
|
|
3175
|
+
buildHooks() {
|
|
3176
|
+
return {
|
|
3177
|
+
beforeRun: this.onRequest.bind(this),
|
|
3178
|
+
afterRun: this.onResponse.bind(this),
|
|
3179
|
+
beforeTool: this.onToolStart.bind(this),
|
|
3180
|
+
afterTool: this.onToolEnd.bind(this),
|
|
3181
|
+
onError: this.onError.bind(this)
|
|
3182
|
+
};
|
|
3183
|
+
}
|
|
3184
|
+
generateId() {
|
|
3185
|
+
return Math.random().toString(36).substring(2, 15);
|
|
3186
|
+
}
|
|
3187
|
+
createSpan(name, traceId, parentId) {
|
|
3188
|
+
if (this.spans.size >= this.maxSpans) {
|
|
3189
|
+
const oldestKey = this.spans.keys().next().value;
|
|
3190
|
+
if (oldestKey) {
|
|
3191
|
+
const oldSpan = this.spans.get(oldestKey);
|
|
3192
|
+
this.spans.delete(oldestKey);
|
|
3193
|
+
if (oldSpan && !oldSpan.parentId) {
|
|
3194
|
+
const idx = this.rootSpans.indexOf(oldSpan);
|
|
3195
|
+
if (idx >= 0) this.rootSpans.splice(idx, 1);
|
|
3196
|
+
}
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
const span = {
|
|
3200
|
+
id: this.generateId(),
|
|
3201
|
+
traceId,
|
|
3202
|
+
name,
|
|
3203
|
+
startTime: Date.now(),
|
|
3204
|
+
attributes: {},
|
|
3205
|
+
parentId,
|
|
3206
|
+
status: "ok",
|
|
3207
|
+
children: []
|
|
3208
|
+
};
|
|
3209
|
+
this.spans.set(span.id, span);
|
|
3210
|
+
if (parentId) {
|
|
3211
|
+
const parent = this.spans.get(parentId);
|
|
3212
|
+
if (parent) {
|
|
3213
|
+
parent.children.push(span);
|
|
3214
|
+
}
|
|
3215
|
+
} else {
|
|
3216
|
+
this.rootSpans.push(span);
|
|
3217
|
+
}
|
|
3218
|
+
return span;
|
|
3219
|
+
}
|
|
3220
|
+
endSpan(spanId, status = "ok") {
|
|
3221
|
+
const span = this.spans.get(spanId);
|
|
3222
|
+
if (span) {
|
|
3223
|
+
span.endTime = Date.now();
|
|
3224
|
+
span.status = status;
|
|
3225
|
+
}
|
|
3226
|
+
}
|
|
3227
|
+
getOrCreateMetrics(sessionId) {
|
|
3228
|
+
let metrics = this.sessionMetrics.get(sessionId);
|
|
3229
|
+
if (!metrics) {
|
|
3230
|
+
metrics = createDefaultMetrics();
|
|
3231
|
+
this.sessionMetrics.set(sessionId, metrics);
|
|
3232
|
+
}
|
|
3233
|
+
return metrics;
|
|
3234
|
+
}
|
|
3235
|
+
async onRequest(ctx, params) {
|
|
3236
|
+
if (!this.config.enableTracing && !this.config.enableMetrics) {
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3239
|
+
const sessionId = ctx.sessionId;
|
|
3240
|
+
if (this.config.enableTracing) {
|
|
3241
|
+
const traceId = this.generateId();
|
|
3242
|
+
const span = this.createSpan("agent.run", traceId);
|
|
3243
|
+
span.attributes = {
|
|
3244
|
+
sessionId,
|
|
3245
|
+
agentName: ctx.agentName,
|
|
3246
|
+
prompt: params.prompt,
|
|
3247
|
+
maxSteps: ctx.config.maxSteps
|
|
3248
|
+
};
|
|
3249
|
+
this.activeSpans.set(sessionId, span);
|
|
3250
|
+
}
|
|
3251
|
+
if (this.config.enableMetrics) {
|
|
3252
|
+
this.sessionStartTimes.set(sessionId, Date.now());
|
|
3253
|
+
this.sessionMetrics.set(sessionId, createDefaultMetrics());
|
|
3254
|
+
}
|
|
3255
|
+
}
|
|
3256
|
+
async onResponse(ctx, params) {
|
|
3257
|
+
if (!this.config.enableTracing && !this.config.enableMetrics) {
|
|
3258
|
+
return;
|
|
3259
|
+
}
|
|
3260
|
+
const sessionId = ctx.sessionId;
|
|
3261
|
+
const rootSpan = this.activeSpans.get(sessionId);
|
|
3262
|
+
if (this.config.enableTracing && rootSpan) {
|
|
3263
|
+
this.endSpan(rootSpan.id);
|
|
3264
|
+
rootSpan.attributes.result = params.result.text;
|
|
3265
|
+
rootSpan.attributes.steps = _optionalChain([params, 'access', _75 => _75.result, 'access', _76 => _76.steps, 'optionalAccess', _77 => _77.length]) || 0;
|
|
3266
|
+
}
|
|
3267
|
+
if (this.config.enableMetrics) {
|
|
3268
|
+
const metrics = this.getOrCreateMetrics(sessionId);
|
|
3269
|
+
const startTime = this.sessionStartTimes.get(sessionId);
|
|
3270
|
+
if (startTime) {
|
|
3271
|
+
metrics.totalLatencyMs = Date.now() - startTime;
|
|
3272
|
+
}
|
|
3273
|
+
if (this.config.enableCostEstimation && this.config.costPerInputToken && this.config.costPerOutputToken) {
|
|
3274
|
+
metrics.estimatedCostUsd = metrics.totalTokens.input * this.config.costPerInputToken + metrics.totalTokens.output * this.config.costPerOutputToken;
|
|
3275
|
+
}
|
|
3276
|
+
this.sessionStartTimes.delete(sessionId);
|
|
3277
|
+
}
|
|
3278
|
+
this.activeSpans.delete(sessionId);
|
|
3279
|
+
}
|
|
3280
|
+
async onToolStart(ctx, params) {
|
|
3281
|
+
if (!this.config.enableTracing && !this.config.enableMetrics) {
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
if (this.config.enableMetrics) {
|
|
3285
|
+
const metricsKey = `${ctx.sessionId}:${params.toolName}`;
|
|
3286
|
+
const stack = _nullishCoalesce(this.toolStartTimes.get(metricsKey), () => ( []));
|
|
3287
|
+
stack.push(Date.now());
|
|
3288
|
+
this.toolStartTimes.set(metricsKey, stack);
|
|
3289
|
+
}
|
|
3290
|
+
if (this.config.enableTracing) {
|
|
3291
|
+
const rootSpan = this.activeSpans.get(ctx.sessionId);
|
|
3292
|
+
const traceId = _nullishCoalesce(_optionalChain([rootSpan, 'optionalAccess', _78 => _78.traceId]), () => ( this.generateId()));
|
|
3293
|
+
const toolSpan = this.createSpan(`tool.${params.toolName}`, traceId, _optionalChain([rootSpan, 'optionalAccess', _79 => _79.id]));
|
|
3294
|
+
toolSpan.attributes = {
|
|
3295
|
+
toolName: params.toolName,
|
|
3296
|
+
args: params.args
|
|
3297
|
+
};
|
|
3298
|
+
const stackKey = `${ctx.sessionId}:${params.toolName}`;
|
|
3299
|
+
const stack = _nullishCoalesce(this.toolSpanStack.get(stackKey), () => ( []));
|
|
3300
|
+
stack.push(toolSpan.id);
|
|
3301
|
+
this.toolSpanStack.set(stackKey, stack);
|
|
3302
|
+
}
|
|
3303
|
+
}
|
|
3304
|
+
async onToolEnd(ctx, params) {
|
|
3305
|
+
if (!this.config.enableTracing && !this.config.enableMetrics) {
|
|
3306
|
+
return;
|
|
3307
|
+
}
|
|
3308
|
+
if (this.config.enableTracing) {
|
|
3309
|
+
const spanKey = `${ctx.sessionId}:${params.toolName}`;
|
|
3310
|
+
const stack = this.toolSpanStack.get(spanKey);
|
|
3311
|
+
const spanId = _optionalChain([stack, 'optionalAccess', _80 => _80.pop, 'call', _81 => _81()]);
|
|
3312
|
+
if (spanId) {
|
|
3313
|
+
const toolSpan = this.spans.get(spanId);
|
|
3314
|
+
if (toolSpan) {
|
|
3315
|
+
this.endSpan(toolSpan.id);
|
|
3316
|
+
toolSpan.attributes.result = params.result;
|
|
3317
|
+
}
|
|
3318
|
+
if (stack && stack.length === 0) {
|
|
3319
|
+
this.toolSpanStack.delete(spanKey);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
3322
|
+
}
|
|
3323
|
+
if (this.config.enableMetrics) {
|
|
3324
|
+
const key = `${ctx.sessionId}:${params.toolName}`;
|
|
3325
|
+
const stack = this.toolStartTimes.get(key);
|
|
3326
|
+
const startTime = _optionalChain([stack, 'optionalAccess', _82 => _82.pop, 'call', _83 => _83()]);
|
|
3327
|
+
const latencyMs = startTime ? Date.now() - startTime : 0;
|
|
3328
|
+
if (stack && stack.length === 0) {
|
|
3329
|
+
this.toolStartTimes.delete(key);
|
|
3330
|
+
}
|
|
3331
|
+
const metrics = this.getOrCreateMetrics(ctx.sessionId);
|
|
3332
|
+
metrics.toolCalls.push({
|
|
3333
|
+
name: params.toolName,
|
|
3334
|
+
latencyMs,
|
|
3335
|
+
success: true
|
|
3336
|
+
});
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
async onError(ctx, params) {
|
|
3340
|
+
if (!this.config.enableTracing) {
|
|
3341
|
+
return;
|
|
3342
|
+
}
|
|
3343
|
+
const rootSpan = this.activeSpans.get(ctx.sessionId);
|
|
3344
|
+
const unfinishedSpans = Array.from(this.spans.values()).filter((s) => !s.endTime && s.traceId === _optionalChain([rootSpan, 'optionalAccess', _84 => _84.traceId])).sort((a, b) => b.startTime - a.startTime);
|
|
3345
|
+
if (unfinishedSpans.length > 0) {
|
|
3346
|
+
const span = unfinishedSpans[0];
|
|
3347
|
+
this.endSpan(span.id, "error");
|
|
3348
|
+
span.attributes.error = {
|
|
3349
|
+
message: params.error instanceof Error ? params.error.message : String(params.error),
|
|
3350
|
+
phase: params.phase
|
|
3351
|
+
};
|
|
3352
|
+
}
|
|
3353
|
+
}
|
|
3354
|
+
// Public methods
|
|
3355
|
+
getTraces() {
|
|
3356
|
+
return this.config.enableTracing ? [...this.rootSpans] : [];
|
|
3357
|
+
}
|
|
3358
|
+
getMetrics(sessionId) {
|
|
3359
|
+
if (!this.config.enableMetrics) {
|
|
3360
|
+
return createDefaultMetrics();
|
|
3361
|
+
}
|
|
3362
|
+
if (sessionId) {
|
|
3363
|
+
const m = this.sessionMetrics.get(sessionId);
|
|
3364
|
+
return m ? this.deepCopyMetrics(m) : createDefaultMetrics();
|
|
3365
|
+
}
|
|
3366
|
+
const entries = Array.from(this.sessionMetrics.values());
|
|
3367
|
+
const last = entries[entries.length - 1];
|
|
3368
|
+
return last ? this.deepCopyMetrics(last) : createDefaultMetrics();
|
|
3369
|
+
}
|
|
3370
|
+
deepCopyMetrics(m) {
|
|
3371
|
+
return {
|
|
3372
|
+
totalTokens: { ...m.totalTokens },
|
|
3373
|
+
totalLatencyMs: m.totalLatencyMs,
|
|
3374
|
+
toolCalls: m.toolCalls.map((t) => ({ ...t })),
|
|
3375
|
+
llmCalls: m.llmCalls.map((l) => ({ ...l })),
|
|
3376
|
+
estimatedCostUsd: m.estimatedCostUsd
|
|
3377
|
+
};
|
|
3378
|
+
}
|
|
3379
|
+
exportOpenTelemetry() {
|
|
3380
|
+
if (!this.config.enableTracing) {
|
|
3381
|
+
return { resourceSpans: [] };
|
|
3382
|
+
}
|
|
3383
|
+
const spans = Array.from(this.spans.values()).map((span) => ({
|
|
3384
|
+
traceId: span.traceId,
|
|
3385
|
+
spanId: span.id,
|
|
3386
|
+
parentSpanId: span.parentId,
|
|
3387
|
+
name: span.name,
|
|
3388
|
+
startTimeUnixNano: span.startTime * 1e6,
|
|
3389
|
+
endTimeUnixNano: span.endTime ? span.endTime * 1e6 : void 0,
|
|
3390
|
+
attributes: Object.entries(span.attributes).map(([key, value]) => ({
|
|
3391
|
+
key,
|
|
3392
|
+
value: { stringValue: String(value) }
|
|
3393
|
+
})),
|
|
3394
|
+
status: {
|
|
3395
|
+
code: span.status === "ok" ? 1 : 2
|
|
3396
|
+
}
|
|
3397
|
+
}));
|
|
3398
|
+
return {
|
|
3399
|
+
resourceSpans: [{
|
|
3400
|
+
resource: {
|
|
3401
|
+
attributes: [
|
|
3402
|
+
{ key: "service.name", value: { stringValue: "deepagent" } },
|
|
3403
|
+
{ key: "service.version", value: { stringValue: this.version } }
|
|
3404
|
+
]
|
|
3405
|
+
},
|
|
3406
|
+
scopeSpans: [{
|
|
3407
|
+
scope: {
|
|
3408
|
+
name: "deepagent-observability",
|
|
3409
|
+
version: this.version
|
|
3410
|
+
},
|
|
3411
|
+
spans
|
|
3412
|
+
}]
|
|
3413
|
+
}]
|
|
3414
|
+
};
|
|
3415
|
+
}
|
|
3416
|
+
reset() {
|
|
3417
|
+
this.spans.clear();
|
|
3418
|
+
this.rootSpans = [];
|
|
3419
|
+
this.activeSpans.clear();
|
|
3420
|
+
this.sessionMetrics.clear();
|
|
3421
|
+
this.sessionStartTimes.clear();
|
|
3422
|
+
this.toolStartTimes.clear();
|
|
3423
|
+
this.toolSpanStack.clear();
|
|
3424
|
+
}
|
|
3425
|
+
}, _class11);
|
|
3426
|
+
function createObservabilityPlugin(config) {
|
|
3427
|
+
return new ObservabilityPlugin(config);
|
|
3428
|
+
}
|
|
3429
|
+
|
|
3430
|
+
// src/plugins/semantic-scraping.plugin.ts
|
|
3431
|
+
|
|
3432
|
+
var SemanticToolSchema = _zod.z.object({
|
|
3433
|
+
name: _zod.z.string(),
|
|
3434
|
+
description: _zod.z.string(),
|
|
3435
|
+
inputSchema: _zod.z.union([_zod.z.string(), _zod.z.record(_zod.z.string(), _zod.z.unknown())]),
|
|
3436
|
+
confidence: _zod.z.number().optional(),
|
|
3437
|
+
category: _zod.z.string().optional(),
|
|
3438
|
+
annotations: _zod.z.record(_zod.z.string(), _zod.z.boolean()).optional()
|
|
3439
|
+
});
|
|
3440
|
+
var ScanPageInputSchema = _zod.z.object({
|
|
3441
|
+
url: _zod.z.string().url().describe("The page URL that was scanned"),
|
|
3442
|
+
tools: _zod.z.array(SemanticToolSchema).describe("Semantic tools extracted from the page HTML")
|
|
3443
|
+
});
|
|
3444
|
+
var GetManifestInputSchema = _zod.z.object({
|
|
3445
|
+
origin: _zod.z.string().describe("Site origin (e.g., https://example.com)")
|
|
3446
|
+
});
|
|
3447
|
+
var GetToolsForUrlInputSchema = _zod.z.object({
|
|
3448
|
+
origin: _zod.z.string().describe("Site origin (e.g., https://example.com)"),
|
|
3449
|
+
url: _zod.z.string().url().describe("The URL to get tools for")
|
|
3450
|
+
});
|
|
3451
|
+
var SemanticScrapingPlugin = (_class12 = class extends BasePlugin {
|
|
3452
|
+
__init33() {this.name = "semantic-scraping"}
|
|
3453
|
+
|
|
3454
|
+
constructor(options = {}) {
|
|
3455
|
+
super();_class12.prototype.__init33.call(this);;
|
|
3456
|
+
this.adapter = _nullishCoalesce(options.adapter, () => ( new (0, _chunkQYOMQBBZcjs.SemanticScrapingAdapter)()));
|
|
3457
|
+
}
|
|
3458
|
+
buildHooks() {
|
|
3459
|
+
return {};
|
|
3460
|
+
}
|
|
3461
|
+
get tools() {
|
|
3462
|
+
const adapter = this.adapter;
|
|
3463
|
+
return {
|
|
3464
|
+
semantic_scan_page: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
3465
|
+
description: "Register semantic tools extracted from a web page into the site manifest",
|
|
3466
|
+
inputSchema: ScanPageInputSchema,
|
|
3467
|
+
execute: async (args) => {
|
|
3468
|
+
const { url, tools: rawTools } = args;
|
|
3469
|
+
const origin = new URL(url).origin;
|
|
3470
|
+
const semanticTools = rawTools.map((t) => ({
|
|
3471
|
+
name: t.name,
|
|
3472
|
+
description: t.description,
|
|
3473
|
+
inputSchema: t.inputSchema,
|
|
3474
|
+
confidence: t.confidence,
|
|
3475
|
+
category: t.category,
|
|
3476
|
+
annotations: t.annotations
|
|
3477
|
+
}));
|
|
3478
|
+
const manifest = adapter.updatePage(origin, url, semanticTools);
|
|
3479
|
+
return {
|
|
3480
|
+
origin,
|
|
3481
|
+
version: manifest.version,
|
|
3482
|
+
toolCount: manifest.tools.length,
|
|
3483
|
+
pageCount: Object.keys(manifest.pages).length
|
|
3484
|
+
};
|
|
3485
|
+
}
|
|
3486
|
+
}),
|
|
3487
|
+
get_site_manifest: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
3488
|
+
description: "Get the MCP-compatible JSON manifest for a site",
|
|
3489
|
+
inputSchema: GetManifestInputSchema,
|
|
3490
|
+
execute: async (args) => {
|
|
3491
|
+
const { origin } = args;
|
|
3492
|
+
return adapter.toMCPJson(origin);
|
|
3493
|
+
}
|
|
3494
|
+
}),
|
|
3495
|
+
get_tools_for_url: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
3496
|
+
description: "Get the semantic tools available at a specific URL",
|
|
3497
|
+
inputSchema: GetToolsForUrlInputSchema,
|
|
3498
|
+
execute: async (args) => {
|
|
3499
|
+
const { origin, url } = args;
|
|
3500
|
+
return adapter.getToolsForUrl(origin, url);
|
|
3501
|
+
}
|
|
3502
|
+
})
|
|
3503
|
+
};
|
|
3504
|
+
}
|
|
3505
|
+
}, _class12);
|
|
3506
|
+
function createSemanticScrapingPlugin(options = {}) {
|
|
3507
|
+
return new SemanticScrapingPlugin(options);
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
// src/plugins/semantic-web-search.plugin.ts
|
|
3511
|
+
|
|
3512
|
+
var strategySchema = _zod.z.enum(["tfidf", "bm25", "mmr"]);
|
|
3513
|
+
var SemanticWebSearchPlugin = (_class13 = class extends BasePlugin {
|
|
3514
|
+
constructor(options = {}) {
|
|
3515
|
+
super();_class13.prototype.__init34.call(this);_class13.prototype.__init35.call(this);_class13.prototype.__init36.call(this);;
|
|
3516
|
+
this.options = options;
|
|
3517
|
+
this.reranker = _nullishCoalesce(options.reranker, () => ( new DefaultReRankingAdapter()));
|
|
3518
|
+
this.telemetry = options.telemetry;
|
|
3519
|
+
this.costTracker = options.costTracker;
|
|
3520
|
+
this.costModel = _nullishCoalesce(options.costModel, () => ( "gpt-5.2-mini"));
|
|
3521
|
+
this.emitTelemetry = _nullishCoalesce(options.emitTelemetry, () => ( true));
|
|
3522
|
+
this.cache = _nullishCoalesce(options.cache, () => ( new (0, _chunk6XF673YCcjs.ToolCache)()));
|
|
3523
|
+
this.circuitBreaker = _nullishCoalesce(options.circuitBreaker, () => ( new (0, _chunk6XF673YCcjs.CircuitBreaker)()));
|
|
3524
|
+
this.defaultLimit = _nullishCoalesce(options.defaultLimit, () => ( 5));
|
|
3525
|
+
this.defaultScrapeTopK = _nullishCoalesce(options.defaultScrapeTopK, () => ( 2));
|
|
3526
|
+
this.defaultStrategy = _nullishCoalesce(options.defaultStrategy, () => ( "bm25"));
|
|
3527
|
+
this.fallbackStrategy = _nullishCoalesce(options.fallbackStrategy, () => ( "tfidf"));
|
|
3528
|
+
this.fallbackOnRerankError = _nullishCoalesce(options.fallbackOnRerankError, () => ( true));
|
|
3529
|
+
this.requestTimeoutMs = _nullishCoalesce(options.requestTimeoutMs, () => ( 1e4));
|
|
3530
|
+
this.maxRetries = _nullishCoalesce(options.maxRetries, () => ( 2));
|
|
3531
|
+
this.retryDelayMs = _nullishCoalesce(options.retryDelayMs, () => ( 200));
|
|
3532
|
+
this.cacheTtlMs = _nullishCoalesce(options.cacheTtlMs, () => ( 6e4));
|
|
3533
|
+
}
|
|
3534
|
+
__init34() {this.name = "Semantic Web Search"}
|
|
3535
|
+
__init35() {this.description = "Native search\u2192rerank\u2192citation pipeline for high-quality web evidence."}
|
|
3536
|
+
__init36() {this.crawlerPromise = null}
|
|
3537
|
+
|
|
3538
|
+
|
|
3539
|
+
|
|
3540
|
+
|
|
3541
|
+
|
|
3542
|
+
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
|
|
3546
|
+
|
|
3547
|
+
|
|
3548
|
+
|
|
3549
|
+
|
|
3550
|
+
|
|
3551
|
+
|
|
3552
|
+
|
|
3553
|
+
buildHooks() {
|
|
3554
|
+
return {};
|
|
3555
|
+
}
|
|
3556
|
+
get tools() {
|
|
3557
|
+
return {
|
|
3558
|
+
semantic_web_search: _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
3559
|
+
description: "Search the web, rerank semantically and return ranked citations.",
|
|
3560
|
+
inputSchema: _zod.z.object({
|
|
3561
|
+
query: _zod.z.string().min(1),
|
|
3562
|
+
limit: _zod.z.number().int().min(1).max(20).optional(),
|
|
3563
|
+
scrapeTopK: _zod.z.number().int().min(0).max(10).optional(),
|
|
3564
|
+
strategy: strategySchema.optional()
|
|
3565
|
+
}),
|
|
3566
|
+
execute: async (input) => {
|
|
3567
|
+
const limit = _nullishCoalesce(input.limit, () => ( this.defaultLimit));
|
|
3568
|
+
const scrapeTopK = _nullishCoalesce(input.scrapeTopK, () => ( this.defaultScrapeTopK));
|
|
3569
|
+
const strategy = _nullishCoalesce(input.strategy, () => ( this.defaultStrategy));
|
|
3570
|
+
const startedAt = Date.now();
|
|
3571
|
+
const traceId = crypto.randomUUID();
|
|
3572
|
+
this.emitEvent("semantic_search_started", {
|
|
3573
|
+
traceId,
|
|
3574
|
+
query: input.query,
|
|
3575
|
+
limit,
|
|
3576
|
+
scrapeTopK,
|
|
3577
|
+
strategy
|
|
3578
|
+
});
|
|
3579
|
+
const cacheKey = `semantic-web:${input.query}:${limit}:${scrapeTopK}:${strategy}`;
|
|
3580
|
+
const cached = this.cache.get(cacheKey);
|
|
3581
|
+
if (cached) {
|
|
3582
|
+
const cacheResponse = {
|
|
3583
|
+
...cached,
|
|
3584
|
+
quality: {
|
|
3585
|
+
...cached.quality,
|
|
3586
|
+
traceId,
|
|
3587
|
+
cacheServed: true
|
|
3588
|
+
},
|
|
3589
|
+
cacheHit: true
|
|
3590
|
+
};
|
|
3591
|
+
this.emitEvent("semantic_search_cache_hit", {
|
|
3592
|
+
traceId,
|
|
3593
|
+
query: input.query,
|
|
3594
|
+
resultCount: cacheResponse.results.length
|
|
3595
|
+
});
|
|
3596
|
+
this.emitMetric("semantic_search_cache_hit", 1, {
|
|
3597
|
+
strategy
|
|
3598
|
+
});
|
|
3599
|
+
return {
|
|
3600
|
+
...cacheResponse
|
|
3601
|
+
};
|
|
3602
|
+
}
|
|
3603
|
+
try {
|
|
3604
|
+
const crawler = await this.getCrawler();
|
|
3605
|
+
const {
|
|
3606
|
+
value: rawSearch,
|
|
3607
|
+
attempts: searchAttempts
|
|
3608
|
+
} = await this.executeWithRetry(
|
|
3609
|
+
"search",
|
|
3610
|
+
async () => crawler.search(input.query, { limit })
|
|
3611
|
+
);
|
|
3612
|
+
const normalized = this.normalizeResults(rawSearch, limit);
|
|
3613
|
+
const { failures: scrapeFailures, attempts: scrapeAttempts } = await this.enrichTopResults(normalized, scrapeTopK, crawler);
|
|
3614
|
+
const byId = new Map(normalized.map((candidate) => [candidate.id, candidate]));
|
|
3615
|
+
const toRank = normalized.map((candidate) => ({
|
|
3616
|
+
id: candidate.id,
|
|
3617
|
+
text: candidate.content,
|
|
3618
|
+
score: 1
|
|
3619
|
+
}));
|
|
3620
|
+
let reranked;
|
|
3621
|
+
let strategyUsed = strategy;
|
|
3622
|
+
let fallbackUsed = false;
|
|
3623
|
+
try {
|
|
3624
|
+
reranked = this.reranker.rerank(input.query, toRank, {
|
|
3625
|
+
strategy
|
|
3626
|
+
});
|
|
3627
|
+
} catch (error) {
|
|
3628
|
+
if (!this.fallbackOnRerankError || strategy === this.fallbackStrategy) {
|
|
3629
|
+
throw error;
|
|
3630
|
+
}
|
|
3631
|
+
reranked = this.reranker.rerank(input.query, toRank, {
|
|
3632
|
+
strategy: this.fallbackStrategy
|
|
3633
|
+
});
|
|
3634
|
+
strategyUsed = this.fallbackStrategy;
|
|
3635
|
+
fallbackUsed = true;
|
|
3636
|
+
}
|
|
3637
|
+
const results = reranked.slice(0, limit).map((result, index) => {
|
|
3638
|
+
const source = byId.get(result.id);
|
|
3639
|
+
const title = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _85 => _85.title]), () => ( result.id));
|
|
3640
|
+
const url = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _86 => _86.url]), () => ( ""));
|
|
3641
|
+
const snippet = _nullishCoalesce(_optionalChain([source, 'optionalAccess', _87 => _87.snippet]), () => ( result.text.slice(0, 300)));
|
|
3642
|
+
const citation = `[${index + 1}] ${title} \u2014 ${url}`;
|
|
3643
|
+
return {
|
|
3644
|
+
rank: index + 1,
|
|
3645
|
+
score: result.score,
|
|
3646
|
+
title,
|
|
3647
|
+
url,
|
|
3648
|
+
snippet,
|
|
3649
|
+
citation
|
|
3650
|
+
};
|
|
3651
|
+
});
|
|
3652
|
+
const durationMs = Date.now() - startedAt;
|
|
3653
|
+
const quality = {
|
|
3654
|
+
traceId,
|
|
3655
|
+
cacheServed: false,
|
|
3656
|
+
durationMs,
|
|
3657
|
+
strategyRequested: strategy,
|
|
3658
|
+
strategyUsed,
|
|
3659
|
+
fallbackUsed,
|
|
3660
|
+
candidates: normalized.length,
|
|
3661
|
+
reranked: reranked.length,
|
|
3662
|
+
averageScore: this.calculateAverageScore(reranked),
|
|
3663
|
+
searchAttempts,
|
|
3664
|
+
scrapeAttempts,
|
|
3665
|
+
scrapeFailures
|
|
3666
|
+
};
|
|
3667
|
+
const cost = this.buildCostRecord(
|
|
3668
|
+
input.query,
|
|
3669
|
+
results,
|
|
3670
|
+
quality
|
|
3671
|
+
);
|
|
3672
|
+
const response = {
|
|
3673
|
+
query: input.query,
|
|
3674
|
+
results,
|
|
3675
|
+
citations: results.map((result) => result.citation),
|
|
3676
|
+
quality,
|
|
3677
|
+
...cost ? {
|
|
3678
|
+
cost: {
|
|
3679
|
+
model: this.costModel,
|
|
3680
|
+
promptTokens: cost.promptTokens,
|
|
3681
|
+
completionTokens: cost.completionTokens,
|
|
3682
|
+
totalTokens: cost.totalTokens,
|
|
3683
|
+
totalCost: cost.totalCost,
|
|
3684
|
+
currency: "USD"
|
|
3685
|
+
}
|
|
3686
|
+
} : {},
|
|
3687
|
+
cacheHit: false
|
|
3688
|
+
};
|
|
3689
|
+
this.emitEvent("semantic_search_completed", {
|
|
3690
|
+
traceId,
|
|
3691
|
+
query: input.query,
|
|
3692
|
+
resultCount: results.length,
|
|
3693
|
+
durationMs,
|
|
3694
|
+
fallbackUsed,
|
|
3695
|
+
strategyUsed,
|
|
3696
|
+
cacheHit: false,
|
|
3697
|
+
...cost ? { totalCost: cost.totalCost, totalTokens: cost.totalTokens } : {}
|
|
3698
|
+
});
|
|
3699
|
+
this.emitMetric("semantic_search_duration_ms", durationMs, {
|
|
3700
|
+
strategy: strategyUsed,
|
|
3701
|
+
fallback: fallbackUsed ? "true" : "false"
|
|
3702
|
+
});
|
|
3703
|
+
if (cost) {
|
|
3704
|
+
this.emitMetric("semantic_search_cost_usd", cost.totalCost, {
|
|
3705
|
+
model: this.costModel
|
|
3706
|
+
});
|
|
3707
|
+
}
|
|
3708
|
+
this.cache.set(cacheKey, response, this.cacheTtlMs);
|
|
3709
|
+
return response;
|
|
3710
|
+
} catch (error) {
|
|
3711
|
+
this.emitEvent("semantic_search_failed", {
|
|
3712
|
+
traceId,
|
|
3713
|
+
query: input.query,
|
|
3714
|
+
durationMs: Date.now() - startedAt,
|
|
3715
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3716
|
+
}, "ERROR");
|
|
3717
|
+
this.emitMetric("semantic_search_failure", 1, {
|
|
3718
|
+
strategy
|
|
3719
|
+
});
|
|
3720
|
+
throw error;
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
})
|
|
3724
|
+
};
|
|
3725
|
+
}
|
|
3726
|
+
async dispose() {
|
|
3727
|
+
if (!this.crawlerPromise) return;
|
|
3728
|
+
const crawler = await this.crawlerPromise;
|
|
3729
|
+
await _optionalChain([crawler, 'optionalAccess', _88 => _88.close, 'optionalCall', _89 => _89()]);
|
|
3730
|
+
}
|
|
3731
|
+
getCrawler() {
|
|
3732
|
+
if (!this.crawlerPromise) {
|
|
3733
|
+
this.crawlerPromise = this.initCrawler();
|
|
3734
|
+
}
|
|
3735
|
+
return this.crawlerPromise;
|
|
3736
|
+
}
|
|
3737
|
+
async initCrawler() {
|
|
3738
|
+
if (this.options.crawler) {
|
|
3739
|
+
return this.options.crawler;
|
|
3740
|
+
}
|
|
3741
|
+
try {
|
|
3742
|
+
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require("onecrawl")));
|
|
3743
|
+
const CrawlerClass = _nullishCoalesce(_nullishCoalesce(mod.Crawler, () => ( _optionalChain([mod, 'access', _90 => _90.default, 'optionalAccess', _91 => _91.Crawler]))), () => ( mod.default));
|
|
3744
|
+
return new CrawlerClass({
|
|
3745
|
+
...this.options.apiKey ? { apiKey: this.options.apiKey } : {}
|
|
3746
|
+
});
|
|
3747
|
+
} catch (e13) {
|
|
3748
|
+
throw new Error(
|
|
3749
|
+
'SemanticWebSearchPlugin requires "onecrawl" package. Install it: pnpm add onecrawl'
|
|
3750
|
+
);
|
|
3751
|
+
}
|
|
3752
|
+
}
|
|
3753
|
+
normalizeResults(raw, limit) {
|
|
3754
|
+
if (!Array.isArray(raw)) {
|
|
3755
|
+
return [];
|
|
3756
|
+
}
|
|
3757
|
+
return raw.slice(0, limit).map((entry, index) => this.normalizeEntry(entry, index)).filter((entry) => entry !== null);
|
|
3758
|
+
}
|
|
3759
|
+
normalizeEntry(entry, index) {
|
|
3760
|
+
if (!entry || typeof entry !== "object") {
|
|
3761
|
+
return null;
|
|
3762
|
+
}
|
|
3763
|
+
const item = entry;
|
|
3764
|
+
const url = _nullishCoalesce(item.url, () => ( item.link));
|
|
3765
|
+
if (!url) {
|
|
3766
|
+
return null;
|
|
3767
|
+
}
|
|
3768
|
+
const title = _nullishCoalesce(item.title, () => ( `Result ${index + 1}`));
|
|
3769
|
+
const snippet = _nullishCoalesce(_nullishCoalesce(item.snippet, () => ( item.description)), () => ( ""));
|
|
3770
|
+
const content = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(item.content, () => ( item.text)), () => ( snippet)), () => ( title));
|
|
3771
|
+
return {
|
|
3772
|
+
id: `result-${index + 1}`,
|
|
3773
|
+
title,
|
|
3774
|
+
url,
|
|
3775
|
+
snippet,
|
|
3776
|
+
content
|
|
3777
|
+
};
|
|
3778
|
+
}
|
|
3779
|
+
async enrichTopResults(candidates, scrapeTopK, crawler) {
|
|
3780
|
+
if (!crawler.crawl || scrapeTopK <= 0) {
|
|
3781
|
+
return { failures: 0, attempts: 0 };
|
|
3782
|
+
}
|
|
3783
|
+
const targets = candidates.slice(0, Math.min(scrapeTopK, candidates.length));
|
|
3784
|
+
let failures = 0;
|
|
3785
|
+
let attempts = 0;
|
|
3786
|
+
await Promise.all(
|
|
3787
|
+
targets.map(async (candidate) => {
|
|
3788
|
+
try {
|
|
3789
|
+
const result = await this.executeWithRetry(
|
|
3790
|
+
"scrape",
|
|
3791
|
+
async () => crawler.crawl(candidate.url)
|
|
3792
|
+
);
|
|
3793
|
+
attempts += result.attempts;
|
|
3794
|
+
const raw = result.value;
|
|
3795
|
+
const normalized = this.normalizeCrawlContent(raw);
|
|
3796
|
+
if (normalized.length > 0) {
|
|
3797
|
+
candidate.content = normalized;
|
|
3798
|
+
}
|
|
3799
|
+
} catch (e14) {
|
|
3800
|
+
failures += 1;
|
|
3801
|
+
attempts += this.maxRetries + 1;
|
|
3802
|
+
}
|
|
3803
|
+
})
|
|
3804
|
+
);
|
|
3805
|
+
return { failures, attempts };
|
|
3806
|
+
}
|
|
3807
|
+
normalizeCrawlContent(raw) {
|
|
3808
|
+
if (typeof raw === "string") {
|
|
3809
|
+
return raw;
|
|
3810
|
+
}
|
|
3811
|
+
if (raw && typeof raw === "object") {
|
|
3812
|
+
const item = raw;
|
|
3813
|
+
return _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_nullishCoalesce(item.content, () => ( item.text)), () => ( item.snippet)), () => ( item.description)), () => ( ""));
|
|
3814
|
+
}
|
|
3815
|
+
return "";
|
|
3816
|
+
}
|
|
3817
|
+
async executeWithRetry(label, operation) {
|
|
3818
|
+
let lastError;
|
|
3819
|
+
for (let attempt = 1; attempt <= this.maxRetries + 1; attempt++) {
|
|
3820
|
+
try {
|
|
3821
|
+
const value = await this.circuitBreaker.execute(
|
|
3822
|
+
() => this.withTimeout(operation(), `${label} attempt ${attempt}`)
|
|
3823
|
+
);
|
|
3824
|
+
return { value, attempts: attempt };
|
|
3825
|
+
} catch (error) {
|
|
3826
|
+
lastError = error;
|
|
3827
|
+
if (attempt <= this.maxRetries) {
|
|
3828
|
+
await this.sleep(this.retryDelayMs * attempt);
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
throw lastError;
|
|
3833
|
+
}
|
|
3834
|
+
async withTimeout(promise, label) {
|
|
3835
|
+
return await new Promise((resolve, reject) => {
|
|
3836
|
+
const timer = setTimeout(() => {
|
|
3837
|
+
reject(new Error(`${label} timed out after ${this.requestTimeoutMs}ms`));
|
|
3838
|
+
}, this.requestTimeoutMs);
|
|
3839
|
+
promise.then((value) => {
|
|
3840
|
+
clearTimeout(timer);
|
|
3841
|
+
resolve(value);
|
|
3842
|
+
}).catch((error) => {
|
|
3843
|
+
clearTimeout(timer);
|
|
3844
|
+
reject(error);
|
|
3845
|
+
});
|
|
3846
|
+
});
|
|
3847
|
+
}
|
|
3848
|
+
async sleep(ms) {
|
|
3849
|
+
await new Promise((resolve) => setTimeout(resolve, ms));
|
|
3850
|
+
}
|
|
3851
|
+
calculateAverageScore(results) {
|
|
3852
|
+
if (results.length === 0) return 0;
|
|
3853
|
+
const sum = results.reduce((acc, item) => acc + item.score, 0);
|
|
3854
|
+
return sum / results.length;
|
|
3855
|
+
}
|
|
3856
|
+
buildCostRecord(query, results, quality) {
|
|
3857
|
+
if (!this.costTracker) {
|
|
3858
|
+
return void 0;
|
|
3859
|
+
}
|
|
3860
|
+
const promptTokens = this.estimateTokens(query);
|
|
3861
|
+
const completionText = results.map((result) => `${result.title}
|
|
3862
|
+
${result.snippet}
|
|
3863
|
+
${result.citation}`).join("\n\n");
|
|
3864
|
+
const completionTokens = this.estimateTokens(completionText);
|
|
3865
|
+
const totalTokens = promptTokens + completionTokens;
|
|
3866
|
+
const usage = {
|
|
3867
|
+
model: this.costModel,
|
|
3868
|
+
provider: "semantic-web-search",
|
|
3869
|
+
inputTokens: promptTokens,
|
|
3870
|
+
outputTokens: completionTokens,
|
|
3871
|
+
timestamp: Date.now()
|
|
3872
|
+
};
|
|
3873
|
+
const totalBefore = this.costTracker.getEstimate().totalCost;
|
|
3874
|
+
this.costTracker.recordUsage(usage);
|
|
3875
|
+
const totalAfter = this.costTracker.getEstimate().totalCost;
|
|
3876
|
+
const totalCost = Math.max(0, totalAfter - totalBefore);
|
|
3877
|
+
this.emitEvent("semantic_search_cost_recorded", {
|
|
3878
|
+
traceId: quality.traceId,
|
|
3879
|
+
model: this.costModel,
|
|
3880
|
+
promptTokens,
|
|
3881
|
+
completionTokens,
|
|
3882
|
+
totalTokens,
|
|
3883
|
+
totalCost
|
|
3884
|
+
});
|
|
3885
|
+
return {
|
|
3886
|
+
promptTokens,
|
|
3887
|
+
completionTokens,
|
|
3888
|
+
totalTokens,
|
|
3889
|
+
totalCost
|
|
3890
|
+
};
|
|
3891
|
+
}
|
|
3892
|
+
estimateTokens(text) {
|
|
3893
|
+
if (text.trim().length === 0) {
|
|
3894
|
+
return 0;
|
|
3895
|
+
}
|
|
3896
|
+
return Math.max(1, Math.ceil(text.length / 4));
|
|
3897
|
+
}
|
|
3898
|
+
emitEvent(name, properties, status = "OK") {
|
|
3899
|
+
if (!this.emitTelemetry || !this.telemetry) {
|
|
3900
|
+
return;
|
|
3901
|
+
}
|
|
3902
|
+
try {
|
|
3903
|
+
const span = this.telemetry.startSpan(name);
|
|
3904
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
3905
|
+
span.setAttribute(key, this.toTelemetryAttribute(value));
|
|
3906
|
+
}
|
|
3907
|
+
span.setStatus(status);
|
|
3908
|
+
span.end();
|
|
3909
|
+
} catch (e15) {
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
emitMetric(name, value, tags) {
|
|
3913
|
+
if (!this.emitTelemetry || !this.telemetry) {
|
|
3914
|
+
return;
|
|
3915
|
+
}
|
|
3916
|
+
try {
|
|
3917
|
+
this.telemetry.recordMetric(name, value, tags);
|
|
3918
|
+
} catch (e16) {
|
|
3919
|
+
}
|
|
3920
|
+
}
|
|
3921
|
+
toTelemetryAttribute(value) {
|
|
3922
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
3923
|
+
return value;
|
|
3924
|
+
}
|
|
3925
|
+
if (value === null || value === void 0) {
|
|
3926
|
+
return "";
|
|
3927
|
+
}
|
|
3928
|
+
try {
|
|
3929
|
+
return JSON.stringify(value);
|
|
3930
|
+
} catch (e17) {
|
|
3931
|
+
return String(value);
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
}, _class13);
|
|
3935
|
+
function createSemanticWebSearchPlugin(options = {}) {
|
|
3936
|
+
return new SemanticWebSearchPlugin(options);
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
// src/plugins/mcp-server.plugin.ts
|
|
3940
|
+
|
|
3941
|
+
|
|
3942
|
+
// src/adapters/mcp-server/default-mcp-server.adapter.ts
|
|
3943
|
+
var _http = require('http');
|
|
3944
|
+
|
|
3945
|
+
var DefaultMcpServerAdapter = (_class14 = class _DefaultMcpServerAdapter {
|
|
3946
|
+
__init37() {this.tools = []}
|
|
3947
|
+
__init38() {this.toolsByName = /* @__PURE__ */ new Map()}
|
|
3948
|
+
|
|
3949
|
+
|
|
3950
|
+
// stdio
|
|
3951
|
+
|
|
3952
|
+
__init39() {this.stdinBuffer = ""}
|
|
3953
|
+
// sse
|
|
3954
|
+
|
|
3955
|
+
__init40() {this.sseClients = /* @__PURE__ */ new Map()}
|
|
3956
|
+
constructor(tools, executor) {;_class14.prototype.__init37.call(this);_class14.prototype.__init38.call(this);_class14.prototype.__init39.call(this);_class14.prototype.__init40.call(this);
|
|
3957
|
+
this.tools = tools;
|
|
3958
|
+
this.rebuildToolIndex();
|
|
3959
|
+
this.executor = executor;
|
|
3960
|
+
}
|
|
3961
|
+
rebuildToolIndex() {
|
|
3962
|
+
this.toolsByName.clear();
|
|
3963
|
+
for (const t of this.tools) {
|
|
3964
|
+
this.toolsByName.set(t.name, t);
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
// ── Public API ──────────────────────────────────────────────────────────
|
|
3968
|
+
getRegisteredTools() {
|
|
3969
|
+
return [...this.tools];
|
|
3970
|
+
}
|
|
3971
|
+
setTools(tools) {
|
|
3972
|
+
this.tools = tools;
|
|
3973
|
+
this.rebuildToolIndex();
|
|
3974
|
+
}
|
|
3975
|
+
async start(options) {
|
|
3976
|
+
this.options = options;
|
|
3977
|
+
const filtered = options.toolFilter ? this.tools.filter((t) => options.toolFilter.includes(t.name)) : this.tools;
|
|
3978
|
+
this.tools = filtered;
|
|
3979
|
+
this.rebuildToolIndex();
|
|
3980
|
+
if (options.transport === "stdio") {
|
|
3981
|
+
this.startStdio();
|
|
3982
|
+
} else {
|
|
3983
|
+
await this.startSse(_nullishCoalesce(options.port, () => ( 3100)));
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
async stop() {
|
|
3987
|
+
if (this.stdinHandler) {
|
|
3988
|
+
process.stdin.removeListener("data", this.stdinHandler);
|
|
3989
|
+
this.stdinHandler = void 0;
|
|
3990
|
+
this.stdinBuffer = "";
|
|
3991
|
+
}
|
|
3992
|
+
if (this.httpServer) {
|
|
3993
|
+
for (const [, client] of this.sseClients) {
|
|
3994
|
+
client.end();
|
|
3995
|
+
}
|
|
3996
|
+
this.sseClients.clear();
|
|
3997
|
+
await new Promise((resolve, reject) => {
|
|
3998
|
+
this.httpServer.close((err) => err ? reject(err) : resolve());
|
|
3999
|
+
});
|
|
4000
|
+
this.httpServer = void 0;
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
// ── JSON-RPC handler ──────────────────────────────────────────────────
|
|
4004
|
+
async handleRequest(request) {
|
|
4005
|
+
const { id, method, params } = request;
|
|
4006
|
+
switch (method) {
|
|
4007
|
+
case "initialize":
|
|
4008
|
+
return {
|
|
4009
|
+
jsonrpc: "2.0",
|
|
4010
|
+
id,
|
|
4011
|
+
result: {
|
|
4012
|
+
protocolVersion: "2024-11-05",
|
|
4013
|
+
serverInfo: {
|
|
4014
|
+
name: _nullishCoalesce(_optionalChain([this, 'access', _92 => _92.options, 'optionalAccess', _93 => _93.name]), () => ( "gaussflow-mcp-server")),
|
|
4015
|
+
version: _nullishCoalesce(_optionalChain([this, 'access', _94 => _94.options, 'optionalAccess', _95 => _95.version]), () => ( "1.0.0"))
|
|
4016
|
+
},
|
|
4017
|
+
capabilities: {
|
|
4018
|
+
tools: { listChanged: false }
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
};
|
|
4022
|
+
case "tools/list":
|
|
4023
|
+
return {
|
|
4024
|
+
jsonrpc: "2.0",
|
|
4025
|
+
id,
|
|
4026
|
+
result: {
|
|
4027
|
+
tools: this.tools.map((t) => ({
|
|
4028
|
+
name: t.name,
|
|
4029
|
+
description: t.description,
|
|
4030
|
+
inputSchema: t.inputSchema
|
|
4031
|
+
}))
|
|
4032
|
+
}
|
|
4033
|
+
};
|
|
4034
|
+
case "tools/call": {
|
|
4035
|
+
const toolName = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _96 => _96.name]), () => ( ""));
|
|
4036
|
+
const toolArgs = _nullishCoalesce(_optionalChain([params, 'optionalAccess', _97 => _97.arguments]), () => ( {}));
|
|
4037
|
+
const toolDef = this.toolsByName.get(toolName);
|
|
4038
|
+
if (!toolDef) {
|
|
4039
|
+
return {
|
|
4040
|
+
jsonrpc: "2.0",
|
|
4041
|
+
id,
|
|
4042
|
+
error: { code: -32601, message: `Unknown tool: ${toolName}` }
|
|
4043
|
+
};
|
|
4044
|
+
}
|
|
4045
|
+
try {
|
|
4046
|
+
const result = await this.executor(toolName, toolArgs);
|
|
4047
|
+
return { jsonrpc: "2.0", id, result };
|
|
4048
|
+
} catch (err) {
|
|
4049
|
+
return {
|
|
4050
|
+
jsonrpc: "2.0",
|
|
4051
|
+
id,
|
|
4052
|
+
result: {
|
|
4053
|
+
content: [{ type: "text", text: String(err) }],
|
|
4054
|
+
isError: true
|
|
4055
|
+
}
|
|
4056
|
+
};
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
case "notifications/initialized":
|
|
4060
|
+
return { jsonrpc: "2.0", id, result: {} };
|
|
4061
|
+
default:
|
|
4062
|
+
return {
|
|
4063
|
+
jsonrpc: "2.0",
|
|
4064
|
+
id,
|
|
4065
|
+
error: { code: -32601, message: `Method not found: ${method}` }
|
|
4066
|
+
};
|
|
4067
|
+
}
|
|
4068
|
+
}
|
|
4069
|
+
// ── Stdio transport ───────────────────────────────────────────────────
|
|
4070
|
+
startStdio() {
|
|
4071
|
+
this.stdinBuffer = "";
|
|
4072
|
+
this.stdinHandler = (data) => {
|
|
4073
|
+
this.stdinBuffer += data.toString("utf-8");
|
|
4074
|
+
let newlineIdx;
|
|
4075
|
+
while ((newlineIdx = this.stdinBuffer.indexOf("\n")) !== -1) {
|
|
4076
|
+
const line = this.stdinBuffer.slice(0, newlineIdx).trim();
|
|
4077
|
+
this.stdinBuffer = this.stdinBuffer.slice(newlineIdx + 1);
|
|
4078
|
+
if (!line) continue;
|
|
4079
|
+
this.processStdioLine(line).catch((err) => {
|
|
4080
|
+
console.warn("[mcp-stdio] Unhandled error processing line:", err instanceof Error ? err.message : String(err));
|
|
4081
|
+
});
|
|
4082
|
+
}
|
|
4083
|
+
};
|
|
4084
|
+
process.stdin.on("data", this.stdinHandler);
|
|
4085
|
+
}
|
|
4086
|
+
async processStdioLine(line) {
|
|
4087
|
+
let request;
|
|
4088
|
+
try {
|
|
4089
|
+
request = JSON.parse(line);
|
|
4090
|
+
} catch (e18) {
|
|
4091
|
+
const errResponse = {
|
|
4092
|
+
jsonrpc: "2.0",
|
|
4093
|
+
id: null,
|
|
4094
|
+
error: { code: -32700, message: "Parse error" }
|
|
4095
|
+
};
|
|
4096
|
+
process.stdout.write(JSON.stringify(errResponse) + "\n");
|
|
4097
|
+
return;
|
|
4098
|
+
}
|
|
4099
|
+
const response = await this.handleRequest(request);
|
|
4100
|
+
if (request.id !== null && request.id !== void 0) {
|
|
4101
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
4102
|
+
}
|
|
4103
|
+
}
|
|
4104
|
+
// ── SSE transport ─────────────────────────────────────────────────────
|
|
4105
|
+
startSse(port) {
|
|
4106
|
+
return new Promise((resolve, reject) => {
|
|
4107
|
+
this.httpServer = _http.createServer.call(void 0, (req, res) => {
|
|
4108
|
+
this.handleHttpRequest(req, res).catch((err) => {
|
|
4109
|
+
console.warn("[mcp-sse] Unhandled request error:", err instanceof Error ? err.message : String(err));
|
|
4110
|
+
if (!res.headersSent) {
|
|
4111
|
+
res.writeHead(500);
|
|
4112
|
+
res.end();
|
|
4113
|
+
}
|
|
4114
|
+
});
|
|
4115
|
+
});
|
|
4116
|
+
this.httpServer.once("error", reject);
|
|
4117
|
+
this.httpServer.listen(port, "127.0.0.1", () => resolve());
|
|
4118
|
+
});
|
|
4119
|
+
}
|
|
4120
|
+
async handleHttpRequest(req, res) {
|
|
4121
|
+
res.setHeader("Access-Control-Allow-Origin", "http://localhost");
|
|
4122
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
|
4123
|
+
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
4124
|
+
if (req.method === "OPTIONS") {
|
|
4125
|
+
res.writeHead(204);
|
|
4126
|
+
res.end();
|
|
4127
|
+
return;
|
|
4128
|
+
}
|
|
4129
|
+
const url = new URL(_nullishCoalesce(req.url, () => ( "/")), `http://${_nullishCoalesce(req.headers.host, () => ( "localhost"))}`);
|
|
4130
|
+
if (url.pathname === "/sse" && req.method === "GET") {
|
|
4131
|
+
const clientId = _crypto.randomUUID.call(void 0, );
|
|
4132
|
+
res.writeHead(200, {
|
|
4133
|
+
"Content-Type": "text/event-stream",
|
|
4134
|
+
"Cache-Control": "no-cache",
|
|
4135
|
+
Connection: "keep-alive"
|
|
4136
|
+
});
|
|
4137
|
+
res.write(`data: ${JSON.stringify({ type: "endpoint", url: `/message?clientId=${clientId}` })}
|
|
4138
|
+
|
|
4139
|
+
`);
|
|
4140
|
+
this.sseClients.set(clientId, res);
|
|
4141
|
+
req.on("close", () => this.sseClients.delete(clientId));
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
if (url.pathname === "/message" && req.method === "POST") {
|
|
4145
|
+
const body = await this.readBody(req);
|
|
4146
|
+
let request;
|
|
4147
|
+
try {
|
|
4148
|
+
request = JSON.parse(body);
|
|
4149
|
+
} catch (e19) {
|
|
4150
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
4151
|
+
res.end(JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } }));
|
|
4152
|
+
return;
|
|
4153
|
+
}
|
|
4154
|
+
const response = await this.handleRequest(request);
|
|
4155
|
+
const responseJson = JSON.stringify(response);
|
|
4156
|
+
const clientId = url.searchParams.get("clientId");
|
|
4157
|
+
if (clientId) {
|
|
4158
|
+
const client = this.sseClients.get(clientId);
|
|
4159
|
+
if (client) client.write(`data: ${responseJson}
|
|
4160
|
+
|
|
4161
|
+
`);
|
|
4162
|
+
}
|
|
4163
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
4164
|
+
res.end(responseJson);
|
|
4165
|
+
return;
|
|
4166
|
+
}
|
|
4167
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
4168
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
4169
|
+
}
|
|
4170
|
+
static __initStatic6() {this.MAX_BODY_SIZE = 1048576}
|
|
4171
|
+
// 1 MB
|
|
4172
|
+
readBody(req) {
|
|
4173
|
+
return new Promise((resolve, reject) => {
|
|
4174
|
+
const chunks = [];
|
|
4175
|
+
let size = 0;
|
|
4176
|
+
req.on("data", (chunk) => {
|
|
4177
|
+
size += chunk.length;
|
|
4178
|
+
if (size > _DefaultMcpServerAdapter.MAX_BODY_SIZE) {
|
|
4179
|
+
req.destroy(new Error("Request body too large"));
|
|
4180
|
+
return;
|
|
4181
|
+
}
|
|
4182
|
+
chunks.push(chunk);
|
|
4183
|
+
});
|
|
4184
|
+
req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
|
|
4185
|
+
req.on("error", reject);
|
|
4186
|
+
});
|
|
4187
|
+
}
|
|
4188
|
+
}, _class14.__initStatic6(), _class14);
|
|
4189
|
+
|
|
4190
|
+
// src/plugins/mcp-server.plugin.ts
|
|
4191
|
+
var START_SCHEMA = _zod.z.object({
|
|
4192
|
+
transport: _zod.z.enum(["stdio", "sse"]).default("stdio"),
|
|
4193
|
+
port: _zod.z.number().optional(),
|
|
4194
|
+
toolFilter: _zod.z.array(_zod.z.string()).optional()
|
|
4195
|
+
});
|
|
4196
|
+
var STOP_SCHEMA = _zod.z.object({});
|
|
4197
|
+
var McpServerPlugin = (_class15 = class {
|
|
4198
|
+
__init41() {this.name = "mcp-server"}
|
|
4199
|
+
__init42() {this.version = "1.0.0"}
|
|
4200
|
+
|
|
4201
|
+
|
|
4202
|
+
|
|
4203
|
+
__init43() {this.collectedTools = []}
|
|
4204
|
+
constructor(options = {}) {;_class15.prototype.__init41.call(this);_class15.prototype.__init42.call(this);_class15.prototype.__init43.call(this);
|
|
4205
|
+
this.pluginOptions = options;
|
|
4206
|
+
this.tools = {
|
|
4207
|
+
"mcp:start-server": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
4208
|
+
description: "Start an MCP server that exposes the agent's tools via MCP protocol. Supports stdio (default) and sse transports.",
|
|
4209
|
+
inputSchema: START_SCHEMA,
|
|
4210
|
+
execute: async (input) => {
|
|
4211
|
+
const args = START_SCHEMA.parse(_nullishCoalesce(input, () => ( {})));
|
|
4212
|
+
if (this.adapter) {
|
|
4213
|
+
await this.adapter.stop();
|
|
4214
|
+
}
|
|
4215
|
+
this.adapter = new DefaultMcpServerAdapter(
|
|
4216
|
+
this.collectedTools,
|
|
4217
|
+
_nullishCoalesce(this.pluginOptions.executor, () => ( this.defaultExecutor.bind(this)))
|
|
4218
|
+
);
|
|
4219
|
+
await this.adapter.start({
|
|
4220
|
+
name: _nullishCoalesce(this.pluginOptions.name, () => ( "gaussflow-mcp-server")),
|
|
4221
|
+
version: _nullishCoalesce(this.pluginOptions.version, () => ( "1.0.0")),
|
|
4222
|
+
transport: args.transport,
|
|
4223
|
+
port: args.port,
|
|
4224
|
+
toolFilter: args.toolFilter
|
|
4225
|
+
});
|
|
4226
|
+
const tools = this.adapter.getRegisteredTools();
|
|
4227
|
+
return {
|
|
4228
|
+
status: "started",
|
|
4229
|
+
transport: args.transport,
|
|
4230
|
+
port: args.transport === "sse" ? _nullishCoalesce(args.port, () => ( 3100)) : void 0,
|
|
4231
|
+
toolCount: tools.length,
|
|
4232
|
+
tools: tools.map((t) => t.name)
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
4235
|
+
}),
|
|
4236
|
+
"mcp:stop-server": _chunkPSJIAGDEcjs.tool.call(void 0, {
|
|
4237
|
+
description: "Stop the running MCP server.",
|
|
4238
|
+
inputSchema: STOP_SCHEMA,
|
|
4239
|
+
execute: async () => {
|
|
4240
|
+
if (!this.adapter) {
|
|
4241
|
+
return { status: "not_running" };
|
|
4242
|
+
}
|
|
4243
|
+
await this.adapter.stop();
|
|
4244
|
+
this.adapter = void 0;
|
|
4245
|
+
return { status: "stopped" };
|
|
4246
|
+
}
|
|
4247
|
+
})
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
async setup(ctx) {
|
|
4251
|
+
this.collectedTools = ctx.toolNames.map((name) => ({
|
|
4252
|
+
name,
|
|
4253
|
+
description: `Agent tool: ${name}`,
|
|
4254
|
+
inputSchema: { type: "object", properties: {} }
|
|
4255
|
+
}));
|
|
4256
|
+
if (this.pluginOptions.extraTools) {
|
|
4257
|
+
this.collectedTools.push(...this.pluginOptions.extraTools);
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
async dispose() {
|
|
4261
|
+
if (this.adapter) {
|
|
4262
|
+
await this.adapter.stop();
|
|
4263
|
+
this.adapter = void 0;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
/** Expose the underlying adapter for testing */
|
|
4267
|
+
getAdapter() {
|
|
4268
|
+
return this.adapter;
|
|
4269
|
+
}
|
|
4270
|
+
/** Expose collected tools for testing */
|
|
4271
|
+
getCollectedTools() {
|
|
4272
|
+
return [...this.collectedTools];
|
|
4273
|
+
}
|
|
4274
|
+
async defaultExecutor(name, _args) {
|
|
4275
|
+
return {
|
|
4276
|
+
content: [{ type: "text", text: `Tool "${name}" executed (no custom executor provided)` }]
|
|
4277
|
+
};
|
|
4278
|
+
}
|
|
4279
|
+
}, _class15);
|
|
4280
|
+
function createMcpServerPlugin(options) {
|
|
4281
|
+
return new McpServerPlugin(options);
|
|
4282
|
+
}
|
|
4283
|
+
|
|
4284
|
+
|
|
4285
|
+
|
|
4286
|
+
|
|
4287
|
+
|
|
4288
|
+
|
|
4289
|
+
|
|
4290
|
+
|
|
4291
|
+
|
|
4292
|
+
|
|
4293
|
+
|
|
4294
|
+
|
|
4295
|
+
|
|
4296
|
+
|
|
4297
|
+
|
|
4298
|
+
|
|
4299
|
+
|
|
4300
|
+
|
|
4301
|
+
|
|
4302
|
+
|
|
4303
|
+
|
|
4304
|
+
|
|
4305
|
+
|
|
4306
|
+
|
|
4307
|
+
|
|
4308
|
+
|
|
4309
|
+
|
|
4310
|
+
|
|
4311
|
+
|
|
4312
|
+
|
|
4313
|
+
|
|
4314
|
+
|
|
4315
|
+
|
|
4316
|
+
|
|
4317
|
+
|
|
4318
|
+
|
|
4319
|
+
|
|
4320
|
+
exports.BasePlugin = BasePlugin; exports.AgentCardPlugin = AgentCardPlugin; exports.createAgentCardPlugin = createAgentCardPlugin; exports.createA2AJsonRpcHandler = createA2AJsonRpcHandler; exports.createA2AHttpHandler = createA2AHttpHandler; exports.createA2ASseHandler = createA2ASseHandler; exports.A2APushNotifier = A2APushNotifier; exports.A2APlugin = A2APlugin; exports.createA2APlugin = createA2APlugin; exports.ZodValidationAdapter = ZodValidationAdapter; exports.GuardrailsError = GuardrailsError; exports.GuardrailsPlugin = GuardrailsPlugin; exports.createGuardrailsPlugin = createGuardrailsPlugin; exports.createPiiFilter = createPiiFilter; exports.OneCrawlPlugin = OneCrawlPlugin; exports.createOneCrawlPlugin = createOneCrawlPlugin; exports.DefaultChunkingAdapter = DefaultChunkingAdapter; exports.DefaultReRankingAdapter = DefaultReRankingAdapter; exports.VectorlessPlugin = VectorlessPlugin; exports.createVectorlessPlugin = createVectorlessPlugin; exports.EvalsPlugin = EvalsPlugin; exports.createEvalsPlugin = createEvalsPlugin; exports.DefaultWorkflowEngine = DefaultWorkflowEngine; exports.WorkflowError = WorkflowError; exports.WorkflowPlugin = WorkflowPlugin; exports.createWorkflowPlugin = createWorkflowPlugin; exports.ObservabilityPlugin = ObservabilityPlugin; exports.createObservabilityPlugin = createObservabilityPlugin; exports.SemanticScrapingPlugin = SemanticScrapingPlugin; exports.createSemanticScrapingPlugin = createSemanticScrapingPlugin; exports.SemanticWebSearchPlugin = SemanticWebSearchPlugin; exports.createSemanticWebSearchPlugin = createSemanticWebSearchPlugin; exports.DefaultMcpServerAdapter = DefaultMcpServerAdapter; exports.McpServerPlugin = McpServerPlugin; exports.createMcpServerPlugin = createMcpServerPlugin;
|
|
4321
|
+
//# sourceMappingURL=chunk-CJZ66SU3.cjs.map
|