agent-framework-js 0.1.1
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/AGENT_USAGE.md +207 -0
- package/LICENSE +21 -0
- package/README.md +99 -0
- package/dist/agents/index.cjs +35 -0
- package/dist/agents/index.cjs.map +1 -0
- package/dist/agents/index.d.cts +8 -0
- package/dist/agents/index.d.ts +8 -0
- package/dist/agents/index.js +10 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/chunk-5M6ER4ZX.cjs +4 -0
- package/dist/chunk-5M6ER4ZX.cjs.map +1 -0
- package/dist/chunk-5PDJOBTD.js +38 -0
- package/dist/chunk-5PDJOBTD.js.map +1 -0
- package/dist/chunk-7ZXUIHLH.js +18 -0
- package/dist/chunk-7ZXUIHLH.js.map +1 -0
- package/dist/chunk-ACBIHS5H.js +30 -0
- package/dist/chunk-ACBIHS5H.js.map +1 -0
- package/dist/chunk-DEABART4.js +54 -0
- package/dist/chunk-DEABART4.js.map +1 -0
- package/dist/chunk-FOTCUNP5.cjs +34 -0
- package/dist/chunk-FOTCUNP5.cjs.map +1 -0
- package/dist/chunk-FSDMBWQV.cjs +20 -0
- package/dist/chunk-FSDMBWQV.cjs.map +1 -0
- package/dist/chunk-GYDY3KX5.cjs +72 -0
- package/dist/chunk-GYDY3KX5.cjs.map +1 -0
- package/dist/chunk-HGEPXJDG.js +129 -0
- package/dist/chunk-HGEPXJDG.js.map +1 -0
- package/dist/chunk-IJASUMIQ.cjs +57 -0
- package/dist/chunk-IJASUMIQ.cjs.map +1 -0
- package/dist/chunk-IU3LS5FC.cjs +10 -0
- package/dist/chunk-IU3LS5FC.cjs.map +1 -0
- package/dist/chunk-IUKD54F7.js +8 -0
- package/dist/chunk-IUKD54F7.js.map +1 -0
- package/dist/chunk-IXV4UIF5.js +79 -0
- package/dist/chunk-IXV4UIF5.js.map +1 -0
- package/dist/chunk-KEI3EALJ.cjs +10 -0
- package/dist/chunk-KEI3EALJ.cjs.map +1 -0
- package/dist/chunk-LMN75W3W.cjs +87 -0
- package/dist/chunk-LMN75W3W.cjs.map +1 -0
- package/dist/chunk-MCLVWCOB.js +3 -0
- package/dist/chunk-MCLVWCOB.js.map +1 -0
- package/dist/chunk-MQ2XTH3S.cjs +87 -0
- package/dist/chunk-MQ2XTH3S.cjs.map +1 -0
- package/dist/chunk-QJ5XHA6S.cjs +95 -0
- package/dist/chunk-QJ5XHA6S.cjs.map +1 -0
- package/dist/chunk-RD5YUB2E.js +190 -0
- package/dist/chunk-RD5YUB2E.js.map +1 -0
- package/dist/chunk-RZ43WNHR.js +8 -0
- package/dist/chunk-RZ43WNHR.js.map +1 -0
- package/dist/chunk-RZP2ZUUX.cjs +252 -0
- package/dist/chunk-RZP2ZUUX.cjs.map +1 -0
- package/dist/chunk-T2GHJ5R4.js +241 -0
- package/dist/chunk-T2GHJ5R4.js.map +1 -0
- package/dist/chunk-TAMJ5HSR.cjs +137 -0
- package/dist/chunk-TAMJ5HSR.cjs.map +1 -0
- package/dist/chunk-TLACSVEZ.cjs +201 -0
- package/dist/chunk-TLACSVEZ.cjs.map +1 -0
- package/dist/chunk-UVWQWOLO.js +196 -0
- package/dist/chunk-UVWQWOLO.js.map +1 -0
- package/dist/chunk-V472N2PK.js +91 -0
- package/dist/chunk-V472N2PK.js.map +1 -0
- package/dist/chunk-V6O6SYAN.cjs +43 -0
- package/dist/chunk-V6O6SYAN.cjs.map +1 -0
- package/dist/chunk-VLSVL5N2.js +48 -0
- package/dist/chunk-VLSVL5N2.js.map +1 -0
- package/dist/chunk-WSMYH2IN.cjs +86 -0
- package/dist/chunk-WSMYH2IN.cjs.map +1 -0
- package/dist/chunk-XPXTXOYQ.js +81 -0
- package/dist/chunk-XPXTXOYQ.js.map +1 -0
- package/dist/chunk-YBFLWRO5.cjs +194 -0
- package/dist/chunk-YBFLWRO5.cjs.map +1 -0
- package/dist/chunk-YCBDEEAV.js +82 -0
- package/dist/chunk-YCBDEEAV.js.map +1 -0
- package/dist/chunk-YH5746OF.js +69 -0
- package/dist/chunk-YH5746OF.js.map +1 -0
- package/dist/chunk-YKZJRE32.cjs +50 -0
- package/dist/chunk-YKZJRE32.cjs.map +1 -0
- package/dist/declarative/index.cjs +19 -0
- package/dist/declarative/index.cjs.map +1 -0
- package/dist/declarative/index.d.cts +60 -0
- package/dist/declarative/index.d.ts +60 -0
- package/dist/declarative/index.js +10 -0
- package/dist/declarative/index.js.map +1 -0
- package/dist/errors-CjVz4W_5.d.cts +68 -0
- package/dist/errors-CjVz4W_5.d.ts +68 -0
- package/dist/index-C2vzfbBz.d.cts +57 -0
- package/dist/index-C2vzfbBz.d.ts +57 -0
- package/dist/index-D7-znzrc.d.ts +153 -0
- package/dist/index-DdYZeNIu.d.cts +153 -0
- package/dist/index.cjs +236 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +51 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.cjs +19 -0
- package/dist/mcp/index.cjs.map +1 -0
- package/dist/mcp/index.d.cts +72 -0
- package/dist/mcp/index.d.ts +72 -0
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/middleware/index.cjs +17 -0
- package/dist/middleware/index.cjs.map +1 -0
- package/dist/middleware/index.d.cts +29 -0
- package/dist/middleware/index.d.ts +29 -0
- package/dist/middleware/index.js +4 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/observability/index.cjs +29 -0
- package/dist/observability/index.cjs.map +1 -0
- package/dist/observability/index.d.cts +1 -0
- package/dist/observability/index.d.ts +1 -0
- package/dist/observability/index.js +4 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/persistence/index.cjs +24 -0
- package/dist/persistence/index.cjs.map +1 -0
- package/dist/persistence/index.d.cts +51 -0
- package/dist/persistence/index.d.ts +51 -0
- package/dist/persistence/index.js +7 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/provider-CMAymr1b.d.cts +82 -0
- package/dist/provider-osAtfZ7x.d.ts +82 -0
- package/dist/providers/index.cjs +26 -0
- package/dist/providers/index.cjs.map +1 -0
- package/dist/providers/index.d.cts +107 -0
- package/dist/providers/index.d.ts +107 -0
- package/dist/providers/index.js +5 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/registry-CpO0yH5v.d.ts +57 -0
- package/dist/registry-D4fThGiN.d.cts +57 -0
- package/dist/skill-DfNChtJN.d.cts +45 -0
- package/dist/skill-DfNChtJN.d.ts +45 -0
- package/dist/skills/index.cjs +20 -0
- package/dist/skills/index.cjs.map +1 -0
- package/dist/skills/index.d.cts +30 -0
- package/dist/skills/index.d.ts +30 -0
- package/dist/skills/index.js +3 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/thread-CWVzTyti.d.ts +51 -0
- package/dist/thread-Dfo9LLf7.d.cts +51 -0
- package/dist/tool-BZg_znMZ.d.cts +50 -0
- package/dist/tool-CSCC87OD.d.ts +50 -0
- package/dist/tools/index.cjs +27 -0
- package/dist/tools/index.cjs.map +1 -0
- package/dist/tools/index.d.cts +21 -0
- package/dist/tools/index.d.ts +21 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types-Cn1g9Tg4.d.cts +63 -0
- package/dist/types-Cn1g9Tg4.d.ts +63 -0
- package/dist/workflows/index.cjs +50 -0
- package/dist/workflows/index.cjs.map +1 -0
- package/dist/workflows/index.d.cts +182 -0
- package/dist/workflows/index.d.ts +182 -0
- package/dist/workflows/index.js +5 -0
- package/dist/workflows/index.js.map +1 -0
- package/package.json +145 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/middleware.ts"],"names":[],"mappings":";;;AAgCO,SAAS,iBAAA,CACf,YACA,IAAA,EACwD;AACxD,EAAA,OAAO,CAAC,GAAA,KAAQ;AACf,IAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,IAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAyC;AAC1D,MAAA,IAAI,CAAA,IAAK,OAAO,OAAO,OAAA,CAAQ,OAAO,IAAI,KAAA,CAAM,8BAA8B,CAAC,CAAA;AAC/E,MAAA,KAAA,GAAQ,CAAA;AACR,MAAA,MAAM,EAAA,GAAK,WAAW,CAAC,CAAA;AACvB,MAAA,IAAI,CAAC,EAAA,EAAI,OAAO,IAAA,CAAK,GAAG,CAAA;AACxB,MAAA,OAAO,GAAG,MAAA,CAAO,GAAA,EAAK,MAAM,QAAA,CAAS,CAAA,GAAI,CAAC,CAAC,CAAA;AAAA,IAC5C,CAAA;AACA,IAAA,OAAO,SAAS,CAAC,CAAA;AAAA,EAClB,CAAA;AACD","file":"chunk-FSDMBWQV.cjs","sourcesContent":["/**\n * Middleware pipeline for intercepting and processing agent provider calls —\n * request/response transformation, custom pipelines, and error handling. (FR-023)\n *\n * @packageDocumentation\n */\n\nimport type { GenerateRequest, GenerateResponse } from \"../providers/provider.js\";\n\n/** Context passed through the middleware chain for one provider call. */\nexport interface MiddlewareContext {\n\t/** The agent's name. */\n\tagentName: string;\n\t/** The outgoing request (may be mutated by middleware). */\n\trequest: GenerateRequest;\n}\n\n/** Continue to the next middleware (or the provider call itself). */\nexport type Next = () => Promise<GenerateResponse>;\n\n/** A pipeline interceptor. */\nexport interface Middleware {\n\tname: string;\n\thandle(ctx: MiddlewareContext, next: Next): Promise<GenerateResponse>;\n}\n\n/**\n * Compose middleware into a single function wrapping `core`.\n *\n * @param middleware - Ordered interceptors (first runs outermost).\n * @param core - The terminal operation (the actual provider call).\n */\nexport function composeMiddleware(\n\tmiddleware: Middleware[],\n\tcore: (ctx: MiddlewareContext) => Promise<GenerateResponse>,\n): (ctx: MiddlewareContext) => Promise<GenerateResponse> {\n\treturn (ctx) => {\n\t\tlet index = -1;\n\t\tconst dispatch = (i: number): Promise<GenerateResponse> => {\n\t\t\tif (i <= index) return Promise.reject(new Error(\"next() called multiple times\"));\n\t\t\tindex = i;\n\t\t\tconst mw = middleware[i];\n\t\t\tif (!mw) return core(ctx);\n\t\t\treturn mw.handle(ctx, () => dispatch(i + 1));\n\t\t};\n\t\treturn dispatch(0);\n\t};\n}\n"]}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkFOTCUNP5_cjs = require('./chunk-FOTCUNP5.cjs');
|
|
4
|
+
var chunkMQ2XTH3S_cjs = require('./chunk-MQ2XTH3S.cjs');
|
|
5
|
+
|
|
6
|
+
// src/mcp/adapter.ts
|
|
7
|
+
function mcpToolToTool(serverId, def, client) {
|
|
8
|
+
return {
|
|
9
|
+
name: def.name,
|
|
10
|
+
description: def.description ?? "",
|
|
11
|
+
inputSchema: def.inputSchema,
|
|
12
|
+
source: serverId,
|
|
13
|
+
enabled: true,
|
|
14
|
+
async run(args) {
|
|
15
|
+
try {
|
|
16
|
+
const result = await client.callTool({ name: def.name, arguments: args });
|
|
17
|
+
return result.content ?? result;
|
|
18
|
+
} catch (e) {
|
|
19
|
+
throw new chunkMQ2XTH3S_cjs.MCPError(`MCP tool "${def.name}" failed: ${e.message}`, serverId);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// src/mcp/connection.ts
|
|
26
|
+
async function createTransport(config) {
|
|
27
|
+
if (config.transport.kind === "stdio") {
|
|
28
|
+
chunkFOTCUNP5_cjs.requireCapability("canSpawnProcess", "MCP stdio transport");
|
|
29
|
+
const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');
|
|
30
|
+
return new StdioClientTransport({
|
|
31
|
+
command: config.transport.command,
|
|
32
|
+
args: config.transport.args ?? []
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const { StreamableHTTPClientTransport } = await import('@modelcontextprotocol/sdk/client/streamableHttp.js');
|
|
36
|
+
return new StreamableHTTPClientTransport(new URL(config.transport.url));
|
|
37
|
+
}
|
|
38
|
+
async function connectMCP(config) {
|
|
39
|
+
let client;
|
|
40
|
+
async function connect() {
|
|
41
|
+
try {
|
|
42
|
+
const { Client } = await import('@modelcontextprotocol/sdk/client/index.js');
|
|
43
|
+
const transport = await createTransport(config);
|
|
44
|
+
client = new Client({ name: "agent-framework-js", version: "0.1.0" }, { capabilities: {} });
|
|
45
|
+
await client.connect(transport);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
if (e.name === "RuntimeUnsupportedError") throw e;
|
|
48
|
+
throw new chunkMQ2XTH3S_cjs.MCPError(`Failed to connect to MCP server: ${e.message}`, config.id);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function listTools() {
|
|
52
|
+
if (!client) throw new chunkMQ2XTH3S_cjs.MCPError("Not connected", config.id);
|
|
53
|
+
try {
|
|
54
|
+
const result = await client.listTools();
|
|
55
|
+
return (result.tools ?? []).map(
|
|
56
|
+
(t) => mcpToolToTool(config.id, t, client)
|
|
57
|
+
);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
throw new chunkMQ2XTH3S_cjs.MCPError(`Failed to list tools: ${e.message}`, config.id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function close() {
|
|
63
|
+
await client?.close?.();
|
|
64
|
+
client = void 0;
|
|
65
|
+
}
|
|
66
|
+
return { id: config.id, connect, listTools, close };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
exports.connectMCP = connectMCP;
|
|
70
|
+
exports.mcpToolToTool = mcpToolToTool;
|
|
71
|
+
//# sourceMappingURL=chunk-GYDY3KX5.cjs.map
|
|
72
|
+
//# sourceMappingURL=chunk-GYDY3KX5.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/mcp/adapter.ts","../src/mcp/connection.ts"],"names":["MCPError","requireCapability"],"mappings":"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","file":"chunk-GYDY3KX5.cjs","sourcesContent":["/**\n * Adapts MCP-provided tools onto the framework's uniform {@link Tool} contract,\n * namespaced by the connection id so collisions are impossible. (FR-014, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"../tools/tool.js\";\nimport { MCPError } from \"../core/errors.js\";\n\ninterface MCPToolDef {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Wrap an MCP tool definition as a framework tool. Invocation calls back through\n * the MCP client; failures surface as typed {@link MCPError}/tool errors.\n */\nexport function mcpToolToTool(serverId: string, def: MCPToolDef, client: any): Tool {\n\treturn {\n\t\tname: def.name,\n\t\tdescription: def.description ?? \"\",\n\t\tinputSchema: def.inputSchema,\n\t\tsource: serverId,\n\t\tenabled: true,\n\t\tasync run(args: unknown): Promise<unknown> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool({ name: def.name, arguments: args });\n\t\t\t\treturn result.content ?? result;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new MCPError(`MCP tool \"${def.name}\" failed: ${(e as Error).message}`, serverId);\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * MCP (Model Context Protocol) integration. Connects to MCP servers and exposes\n * their tools through the framework's uniform tool interface.\n *\n * Remote transport (HTTP/SSE) works in all runtimes; stdio (spawning a server\n * process) works only where process spawning is permitted (Node). Requesting\n * stdio elsewhere throws a typed {@link RuntimeUnsupportedError}. (FR-013, FR-013a,\n * FR-013b, FR-030a)\n *\n * The `@modelcontextprotocol/sdk` package is an optional peer dependency and is\n * loaded lazily so browser bundles that do not use MCP pay no cost.\n *\n * @packageDocumentation\n */\n\nimport { MCPError } from \"../core/errors.js\";\nimport { requireCapability } from \"../core/runtime.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport { mcpToolToTool } from \"./adapter.js\";\n\n/** Transport options for an MCP connection. */\nexport type MCPTransport =\n\t| { kind: \"remote\"; url: string }\n\t| { kind: \"stdio\"; command: string; args?: string[] };\n\n/** Configuration for connecting to an MCP server. */\nexport interface MCPConnectionConfig {\n\t/** Connection id; becomes the namespace prefix for discovered tools. (FR-014a) */\n\tid: string;\n\ttransport: MCPTransport;\n\t/** Whether the connection's tools are enabled. Defaults to true. */\n\tenabled?: boolean;\n}\n\n/** A live connection to an MCP server. */\nexport interface MCPConnection {\n\treadonly id: string;\n\tconnect(): Promise<void>;\n\tlistTools(): Promise<Tool[]>;\n\tclose(): Promise<void>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype AnyClient = any;\n\nasync function createTransport(config: MCPConnectionConfig): Promise<AnyClient> {\n\tif (config.transport.kind === \"stdio\") {\n\t\t// Gate on runtime capability before attempting to spawn. (FR-013b, FR-030a)\n\t\trequireCapability(\"canSpawnProcess\", \"MCP stdio transport\");\n\t\tconst { StdioClientTransport } = await import(\n\t\t\t\"@modelcontextprotocol/sdk/client/stdio.js\"\n\t\t);\n\t\treturn new StdioClientTransport({\n\t\t\tcommand: config.transport.command,\n\t\t\targs: config.transport.args ?? [],\n\t\t});\n\t}\n\tconst { StreamableHTTPClientTransport } = await import(\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\"\n\t);\n\treturn new StreamableHTTPClientTransport(new URL(config.transport.url));\n}\n\n/**\n * Connect to an MCP server.\n *\n * @example\n * ```ts\n * const mcp = await connectMCP({ id: \"docs\", transport: { kind: \"remote\", url: \"https://mcp.example.com\" } });\n * const tools = await mcp.listTools(); // namespaced as docs.<tool>\n * ```\n */\nexport async function connectMCP(config: MCPConnectionConfig): Promise<MCPConnection> {\n\tlet client: AnyClient | undefined;\n\n\tasync function connect(): Promise<void> {\n\t\ttry {\n\t\t\tconst { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n\t\t\tconst transport = await createTransport(config);\n\t\t\tclient = new Client({ name: \"agent-framework-js\", version: \"0.1.0\" }, { capabilities: {} });\n\t\t\tawait client.connect(transport);\n\t\t} catch (e) {\n\t\t\t// Preserve typed runtime errors; wrap everything else as an MCP error.\n\t\t\tif ((e as Error).name === \"RuntimeUnsupportedError\") throw e;\n\t\t\tthrow new MCPError(`Failed to connect to MCP server: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function listTools(): Promise<Tool[]> {\n\t\tif (!client) throw new MCPError(\"Not connected\", config.id);\n\t\ttry {\n\t\t\tconst result = await client.listTools();\n\t\t\treturn (result.tools ?? []).map((t: { name: string; description?: string; inputSchema: Record<string, unknown> }) =>\n\t\t\t\tmcpToolToTool(config.id, t, client),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new MCPError(`Failed to list tools: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function close(): Promise<void> {\n\t\tawait client?.close?.();\n\t\tclient = undefined;\n\t}\n\n\treturn { id: config.id, connect, listTools, close };\n}\n"]}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { ValidationError, ToolError } from './chunk-IXV4UIF5.js';
|
|
2
|
+
import Ajv from 'ajv';
|
|
3
|
+
|
|
4
|
+
var ajv = new Ajv({ allErrors: true, strict: false });
|
|
5
|
+
var cache = /* @__PURE__ */ new WeakMap();
|
|
6
|
+
function compile(schema) {
|
|
7
|
+
let fn = cache.get(schema);
|
|
8
|
+
if (!fn) {
|
|
9
|
+
fn = ajv.compile(schema);
|
|
10
|
+
cache.set(schema, fn);
|
|
11
|
+
}
|
|
12
|
+
return fn;
|
|
13
|
+
}
|
|
14
|
+
function validateArgs(schema, args) {
|
|
15
|
+
const validate = compile(schema);
|
|
16
|
+
if (!validate(args)) {
|
|
17
|
+
const messages = (validate.errors ?? []).map((e) => `${e.instancePath || "(root)"} ${e.message}`).join("; ");
|
|
18
|
+
throw new ValidationError(`Invalid arguments: ${messages}`, { errors: validate.errors });
|
|
19
|
+
}
|
|
20
|
+
return args;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/tools/registry.ts
|
|
24
|
+
function namespacedName(tool) {
|
|
25
|
+
if (!tool.source || tool.source === "local") return tool.name;
|
|
26
|
+
return tool.name.startsWith(`${tool.source}.`) ? tool.name : `${tool.source}.${tool.name}`;
|
|
27
|
+
}
|
|
28
|
+
var ToolRegistry = class {
|
|
29
|
+
tools = /* @__PURE__ */ new Map();
|
|
30
|
+
disabled = /* @__PURE__ */ new Set();
|
|
31
|
+
disabledServers = /* @__PURE__ */ new Set();
|
|
32
|
+
constructor(tools = []) {
|
|
33
|
+
for (const t of tools) this.register(t);
|
|
34
|
+
}
|
|
35
|
+
/** Register a tool under its namespaced name. */
|
|
36
|
+
register(tool) {
|
|
37
|
+
this.tools.set(namespacedName(tool), tool);
|
|
38
|
+
}
|
|
39
|
+
/** Enable a tool by namespaced name. */
|
|
40
|
+
enable(name) {
|
|
41
|
+
this.disabled.delete(name);
|
|
42
|
+
}
|
|
43
|
+
/** Disable a single tool by namespaced name. (FR-012a) */
|
|
44
|
+
disable(name) {
|
|
45
|
+
this.disabled.add(name);
|
|
46
|
+
}
|
|
47
|
+
/** Disable every tool from an MCP server id. (FR-012a) */
|
|
48
|
+
disableServer(serverId) {
|
|
49
|
+
this.disabledServers.add(serverId);
|
|
50
|
+
}
|
|
51
|
+
/** Re-enable every tool from an MCP server id. */
|
|
52
|
+
enableServer(serverId) {
|
|
53
|
+
this.disabledServers.delete(serverId);
|
|
54
|
+
}
|
|
55
|
+
isEnabled(name, tool) {
|
|
56
|
+
if (tool.enabled === false) return false;
|
|
57
|
+
if (this.disabled.has(name)) return false;
|
|
58
|
+
if (tool.source && tool.source !== "local" && this.disabledServers.has(tool.source)) return false;
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/** List currently enabled tools (those presented to the agent). */
|
|
62
|
+
list() {
|
|
63
|
+
return [...this.tools.entries()].filter(([name, tool]) => this.isEnabled(name, tool)).map(([, tool]) => tool);
|
|
64
|
+
}
|
|
65
|
+
/** Provider-facing specs for enabled tools. */
|
|
66
|
+
specs() {
|
|
67
|
+
return [...this.tools.entries()].filter(([name, tool]) => this.isEnabled(name, tool)).map(([name, tool]) => ({
|
|
68
|
+
name,
|
|
69
|
+
description: tool.description,
|
|
70
|
+
inputSchema: tool.inputSchema
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Validate and invoke a tool. Never throws for tool-level failures; instead
|
|
75
|
+
* returns a {@link ToolResult} with a typed error so the agent can self-correct.
|
|
76
|
+
* (FR-011a, FR-012, FR-012c)
|
|
77
|
+
*
|
|
78
|
+
* @param name - Namespaced tool name.
|
|
79
|
+
* @param args - Raw arguments from the model.
|
|
80
|
+
* @param timeoutMs - Optional per-call timeout.
|
|
81
|
+
*/
|
|
82
|
+
async invoke(name, args, timeoutMs) {
|
|
83
|
+
const tool = this.tools.get(name);
|
|
84
|
+
if (!tool || !this.isEnabled(name, tool)) {
|
|
85
|
+
return {
|
|
86
|
+
name,
|
|
87
|
+
error: new ToolError(`Tool "${name}" not found or disabled`, "not-found", name)
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
validateArgs(tool.inputSchema, args);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
const ve = e;
|
|
94
|
+
return {
|
|
95
|
+
name,
|
|
96
|
+
error: new ToolError(ve.message, "invalid-arguments", name, ve.details)
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const value = await runWithTimeout(() => tool.run(args), timeoutMs, name);
|
|
101
|
+
return { name, value };
|
|
102
|
+
} catch (e) {
|
|
103
|
+
if (e instanceof ToolError) return { name, error: e };
|
|
104
|
+
return {
|
|
105
|
+
name,
|
|
106
|
+
error: new ToolError(e.message, "run-failure", name)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
async function runWithTimeout(fn, timeoutMs, name) {
|
|
112
|
+
if (!timeoutMs || timeoutMs <= 0) return fn();
|
|
113
|
+
let timer;
|
|
114
|
+
const timeout = new Promise((_, reject) => {
|
|
115
|
+
timer = setTimeout(
|
|
116
|
+
() => reject(new ToolError(`Tool "${name}" timed out after ${timeoutMs}ms`, "timeout", name)),
|
|
117
|
+
timeoutMs
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
return await Promise.race([fn(), timeout]);
|
|
122
|
+
} finally {
|
|
123
|
+
clearTimeout(timer);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export { ToolRegistry, namespacedName, validateArgs };
|
|
128
|
+
//# sourceMappingURL=chunk-HGEPXJDG.js.map
|
|
129
|
+
//# sourceMappingURL=chunk-HGEPXJDG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/validate.ts","../src/tools/registry.ts"],"names":[],"mappings":"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","file":"chunk-HGEPXJDG.js","sourcesContent":["/**\n * JSON Schema validation for tool arguments, backed by Ajv. Invalid arguments are\n * rejected before a tool runs and reported as a typed error the agent can act on.\n * (FR-011)\n *\n * @packageDocumentation\n */\n\nimport Ajv, { type ValidateFunction } from \"ajv\";\nimport type { JSONSchema } from \"../core/types.js\";\nimport { ValidationError } from \"../core/errors.js\";\n\nconst ajv = new Ajv({ allErrors: true, strict: false });\nconst cache = new WeakMap<JSONSchema, ValidateFunction>();\n\nfunction compile(schema: JSONSchema): ValidateFunction {\n\tlet fn = cache.get(schema);\n\tif (!fn) {\n\t\tfn = ajv.compile(schema);\n\t\tcache.set(schema, fn);\n\t}\n\treturn fn;\n}\n\n/**\n * Validate `args` against `schema`. Returns the args on success; throws a\n * {@link ValidationError} listing the failures otherwise.\n */\nexport function validateArgs<T = unknown>(schema: JSONSchema, args: unknown): T {\n\tconst validate = compile(schema);\n\tif (!validate(args)) {\n\t\tconst messages = (validate.errors ?? [])\n\t\t\t.map((e) => `${e.instancePath || \"(root)\"} ${e.message}`)\n\t\t\t.join(\"; \");\n\t\tthrow new ValidationError(`Invalid arguments: ${messages}`, { errors: validate.errors });\n\t}\n\treturn args as T;\n}\n","/**\n * Tool registry: registration, namespacing, granular enable/disable, and\n * validated invocation. Tools are addressed namespaced by source (`server.tool`)\n * so collisions across MCP servers and local code are impossible. (FR-012a, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"./tool.js\";\nimport type { ToolSpec } from \"../providers/provider.js\";\nimport { validateArgs } from \"./validate.js\";\nimport { ToolError, ValidationError } from \"../core/errors.js\";\n\n/** Result of invoking a tool. */\nexport interface ToolResult {\n\t/** The tool's (namespaced) name. */\n\tname: string;\n\t/** The returned value on success. */\n\tvalue?: unknown;\n\t/** A typed error on failure (fed back to the model for self-correction). */\n\terror?: ToolError;\n}\n\n/** Compute the namespaced address for a tool. */\nexport function namespacedName(tool: Pick<Tool, \"name\" | \"source\">): string {\n\tif (!tool.source || tool.source === \"local\") return tool.name;\n\t// Avoid double-prefixing if already namespaced.\n\treturn tool.name.startsWith(`${tool.source}.`) ? tool.name : `${tool.source}.${tool.name}`;\n}\n\n/** A registry of tools available to an agent. */\nexport class ToolRegistry {\n\tprivate readonly tools = new Map<string, Tool>();\n\tprivate readonly disabled = new Set<string>();\n\tprivate readonly disabledServers = new Set<string>();\n\n\tconstructor(tools: Tool[] = []) {\n\t\tfor (const t of tools) this.register(t);\n\t}\n\n\t/** Register a tool under its namespaced name. */\n\tregister(tool: Tool): void {\n\t\tthis.tools.set(namespacedName(tool), tool);\n\t}\n\n\t/** Enable a tool by namespaced name. */\n\tenable(name: string): void {\n\t\tthis.disabled.delete(name);\n\t}\n\n\t/** Disable a single tool by namespaced name. (FR-012a) */\n\tdisable(name: string): void {\n\t\tthis.disabled.add(name);\n\t}\n\n\t/** Disable every tool from an MCP server id. (FR-012a) */\n\tdisableServer(serverId: string): void {\n\t\tthis.disabledServers.add(serverId);\n\t}\n\n\t/** Re-enable every tool from an MCP server id. */\n\tenableServer(serverId: string): void {\n\t\tthis.disabledServers.delete(serverId);\n\t}\n\n\tprivate isEnabled(name: string, tool: Tool): boolean {\n\t\tif (tool.enabled === false) return false;\n\t\tif (this.disabled.has(name)) return false;\n\t\tif (tool.source && tool.source !== \"local\" && this.disabledServers.has(tool.source)) return false;\n\t\treturn true;\n\t}\n\n\t/** List currently enabled tools (those presented to the agent). */\n\tlist(): Tool[] {\n\t\treturn [...this.tools.entries()]\n\t\t\t.filter(([name, tool]) => this.isEnabled(name, tool))\n\t\t\t.map(([, tool]) => tool);\n\t}\n\n\t/** Provider-facing specs for enabled tools. */\n\tspecs(): ToolSpec[] {\n\t\treturn [...this.tools.entries()]\n\t\t\t.filter(([name, tool]) => this.isEnabled(name, tool))\n\t\t\t.map(([name, tool]) => ({\n\t\t\t\tname,\n\t\t\t\tdescription: tool.description,\n\t\t\t\tinputSchema: tool.inputSchema,\n\t\t\t}));\n\t}\n\n\t/**\n\t * Validate and invoke a tool. Never throws for tool-level failures; instead\n\t * returns a {@link ToolResult} with a typed error so the agent can self-correct.\n\t * (FR-011a, FR-012, FR-012c)\n\t *\n\t * @param name - Namespaced tool name.\n\t * @param args - Raw arguments from the model.\n\t * @param timeoutMs - Optional per-call timeout.\n\t */\n\tasync invoke(name: string, args: unknown, timeoutMs?: number): Promise<ToolResult> {\n\t\tconst tool = this.tools.get(name);\n\t\tif (!tool || !this.isEnabled(name, tool)) {\n\t\t\treturn {\n\t\t\t\tname,\n\t\t\t\terror: new ToolError(`Tool \"${name}\" not found or disabled`, \"not-found\", name),\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tvalidateArgs(tool.inputSchema, args);\n\t\t} catch (e) {\n\t\t\tconst ve = e as ValidationError;\n\t\t\treturn {\n\t\t\t\tname,\n\t\t\t\terror: new ToolError(ve.message, \"invalid-arguments\", name, ve.details),\n\t\t\t};\n\t\t}\n\t\ttry {\n\t\t\tconst value = await runWithTimeout(() => tool.run(args), timeoutMs, name);\n\t\t\treturn { name, value };\n\t\t} catch (e) {\n\t\t\tif (e instanceof ToolError) return { name, error: e };\n\t\t\treturn {\n\t\t\t\tname,\n\t\t\t\terror: new ToolError((e as Error).message, \"run-failure\", name),\n\t\t\t};\n\t\t}\n\t}\n}\n\nasync function runWithTimeout<T>(\n\tfn: () => Promise<T>,\n\ttimeoutMs: number | undefined,\n\tname: string,\n): Promise<T> {\n\tif (!timeoutMs || timeoutMs <= 0) return fn();\n\tlet timer: ReturnType<typeof setTimeout>;\n\tconst timeout = new Promise<never>((_, reject) => {\n\t\ttimer = setTimeout(\n\t\t\t() => reject(new ToolError(`Tool \"${name}\" timed out after ${timeoutMs}ms`, \"timeout\", name)),\n\t\t\ttimeoutMs,\n\t\t);\n\t});\n\ttry {\n\t\treturn await Promise.race([fn(), timeout]);\n\t} finally {\n\t\tclearTimeout(timer!);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/core/redaction.ts
|
|
4
|
+
var REDACTED = "[REDACTED]";
|
|
5
|
+
var SENSITIVE_KEY_PATTERNS = [
|
|
6
|
+
"authorization",
|
|
7
|
+
"api-key",
|
|
8
|
+
"apikey",
|
|
9
|
+
"api_key",
|
|
10
|
+
"token",
|
|
11
|
+
"secret",
|
|
12
|
+
"password",
|
|
13
|
+
"passwd",
|
|
14
|
+
"credential",
|
|
15
|
+
"bearer",
|
|
16
|
+
"x-api-key"
|
|
17
|
+
];
|
|
18
|
+
var SENSITIVE_VALUE_PATTERNS = [
|
|
19
|
+
/\bBearer\s+[A-Za-z0-9._-]+/gi,
|
|
20
|
+
/\bsk-[A-Za-z0-9]{16,}/g,
|
|
21
|
+
// OpenAI-style keys
|
|
22
|
+
/\bgh[pousr]_[A-Za-z0-9]{20,}/g
|
|
23
|
+
// GitHub tokens
|
|
24
|
+
];
|
|
25
|
+
function isSensitiveKey(key) {
|
|
26
|
+
const k = key.toLowerCase();
|
|
27
|
+
return SENSITIVE_KEY_PATTERNS.some((p) => k.includes(p));
|
|
28
|
+
}
|
|
29
|
+
function scrubString(value) {
|
|
30
|
+
let out = value;
|
|
31
|
+
for (const re of SENSITIVE_VALUE_PATTERNS) {
|
|
32
|
+
out = out.replace(re, REDACTED);
|
|
33
|
+
}
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
function redact(value) {
|
|
37
|
+
return redactInner(value, /* @__PURE__ */ new WeakSet());
|
|
38
|
+
}
|
|
39
|
+
function redactInner(value, seen) {
|
|
40
|
+
if (typeof value === "string") return scrubString(value);
|
|
41
|
+
if (value === null || typeof value !== "object") return value;
|
|
42
|
+
if (seen.has(value)) return "[Circular]";
|
|
43
|
+
seen.add(value);
|
|
44
|
+
if (Array.isArray(value)) {
|
|
45
|
+
return value.map((v) => redactInner(v, seen));
|
|
46
|
+
}
|
|
47
|
+
const out = {};
|
|
48
|
+
for (const [k, v] of Object.entries(value)) {
|
|
49
|
+
out[k] = isSensitiveKey(k) ? REDACTED : redactInner(v, seen);
|
|
50
|
+
}
|
|
51
|
+
return out;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.REDACTED = REDACTED;
|
|
55
|
+
exports.redact = redact;
|
|
56
|
+
//# sourceMappingURL=chunk-IJASUMIQ.cjs.map
|
|
57
|
+
//# sourceMappingURL=chunk-IJASUMIQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/redaction.ts"],"names":[],"mappings":";;;AASO,IAAM,QAAA,GAAW;AAGxB,IAAM,sBAAA,GAAyB;AAAA,EAC9B,eAAA;AAAA,EACA,SAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA;AACD,CAAA;AAGA,IAAM,wBAAA,GAAqC;AAAA,EAC1C,8BAAA;AAAA,EACA,wBAAA;AAAA;AAAA,EACA;AAAA;AACD,CAAA;AAEA,SAAS,eAAe,GAAA,EAAsB;AAC7C,EAAA,MAAM,CAAA,GAAI,IAAI,WAAA,EAAY;AAC1B,EAAA,OAAO,uBAAuB,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,CAAC,CAAC,CAAA;AACxD;AAEA,SAAS,YAAY,KAAA,EAAuB;AAC3C,EAAA,IAAI,GAAA,GAAM,KAAA;AACV,EAAA,KAAA,MAAW,MAAM,wBAAA,EAA0B;AAC1C,IAAA,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,EAAA,EAAI,QAAQ,CAAA;AAAA,EAC/B;AACA,EAAA,OAAO,GAAA;AACR;AAWO,SAAS,OAAU,KAAA,EAAa;AACtC,EAAA,OAAO,WAAA,CAAY,KAAA,kBAAO,IAAI,OAAA,EAAS,CAAA;AACxC;AAEA,SAAS,WAAA,CAAY,OAAgB,IAAA,EAAgC;AACpE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,YAAY,KAAK,CAAA;AACvD,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,KAAU,UAAU,OAAO,KAAA;AAExD,EAAA,IAAI,IAAA,CAAK,GAAA,CAAI,KAAe,CAAA,EAAG,OAAO,YAAA;AACtC,EAAA,IAAA,CAAK,IAAI,KAAe,CAAA;AAExB,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,MAAM,GAAA,CAAI,CAAC,MAAM,WAAA,CAAY,CAAA,EAAG,IAAI,CAAC,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,MAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAgC,CAAA,EAAG;AACtE,IAAA,GAAA,CAAI,CAAC,IAAI,cAAA,CAAe,CAAC,IAAI,QAAA,GAAW,WAAA,CAAY,GAAG,IAAI,CAAA;AAAA,EAC5D;AACA,EAAA,OAAO,GAAA;AACR","file":"chunk-IJASUMIQ.cjs","sourcesContent":["/**\n * Centralized secret redaction applied at every output boundary (logs, traces,\n * serialized errors). Security is secure-by-default: no credential value may\n * appear in any emitted output. (FR-026, FR-026a, Constitution II)\n *\n * @packageDocumentation\n */\n\n/** Placeholder substituted for redacted values. */\nexport const REDACTED = \"[REDACTED]\";\n\n/** Field names whose values are always scrubbed (case-insensitive substring match). */\nconst SENSITIVE_KEY_PATTERNS = [\n\t\"authorization\",\n\t\"api-key\",\n\t\"apikey\",\n\t\"api_key\",\n\t\"token\",\n\t\"secret\",\n\t\"password\",\n\t\"passwd\",\n\t\"credential\",\n\t\"bearer\",\n\t\"x-api-key\",\n];\n\n/** Value patterns that look like credentials even outside a known field. */\nconst SENSITIVE_VALUE_PATTERNS: RegExp[] = [\n\t/\\bBearer\\s+[A-Za-z0-9._-]+/gi,\n\t/\\bsk-[A-Za-z0-9]{16,}/g, // OpenAI-style keys\n\t/\\bgh[pousr]_[A-Za-z0-9]{20,}/g, // GitHub tokens\n];\n\nfunction isSensitiveKey(key: string): boolean {\n\tconst k = key.toLowerCase();\n\treturn SENSITIVE_KEY_PATTERNS.some((p) => k.includes(p));\n}\n\nfunction scrubString(value: string): string {\n\tlet out = value;\n\tfor (const re of SENSITIVE_VALUE_PATTERNS) {\n\t\tout = out.replace(re, REDACTED);\n\t}\n\treturn out;\n}\n\n/**\n * Return a deep copy of `value` with secrets scrubbed. Safe for arbitrary\n * structures; handles cycles. Never mutates the input.\n *\n * @example\n * ```ts\n * redact({ authorization: \"Bearer abc\" }); // => { authorization: \"[REDACTED]\" }\n * ```\n */\nexport function redact<T>(value: T): T {\n\treturn redactInner(value, new WeakSet()) as T;\n}\n\nfunction redactInner(value: unknown, seen: WeakSet<object>): unknown {\n\tif (typeof value === \"string\") return scrubString(value);\n\tif (value === null || typeof value !== \"object\") return value;\n\n\tif (seen.has(value as object)) return \"[Circular]\";\n\tseen.add(value as object);\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((v) => redactInner(v, seen));\n\t}\n\n\tconst out: Record<string, unknown> = {};\n\tfor (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n\t\tout[k] = isSensitiveKey(k) ? REDACTED : redactInner(v, seen);\n\t}\n\treturn out;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/tools/tool.ts"],"names":[],"mappings":";;;AA0CO,SAAS,WAAiB,IAAA,EAMlB;AACd,EAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS,IAAA,EAAM,GAAG,IAAA,EAAK;AAClD","file":"chunk-IU3LS5FC.cjs","sourcesContent":["/**\n * The uniform tool contract. Every capability exposed to an agent — whether a\n * local function or an MCP-provided tool — implements this single interface, with\n * a JSON Schema (MCP-popularized) describing its inputs/outputs. The framework\n * ships no built-in tools. (FR-009, FR-012d, Constitution V)\n *\n * @packageDocumentation\n */\n\nimport type { JSONSchema } from \"../core/types.js\";\n\n/** A callable capability available to an agent. */\nexport interface Tool<I = unknown, O = unknown> {\n\t/** Unique name. When provided by an MCP server it is namespaced as `server.tool`. */\n\tname: string;\n\t/** Natural-language description used by the model to decide when to call it. */\n\tdescription: string;\n\t/** JSON Schema for the arguments; validated before invocation. */\n\tinputSchema: JSONSchema;\n\t/** Optional JSON Schema describing the result. */\n\toutputSchema?: JSONSchema;\n\t/** Origin: `\"local\"` for code tools, or an MCP server id. */\n\tsource?: \"local\" | string;\n\t/** Whether the tool is currently presented to the agent. Defaults to true. */\n\tenabled?: boolean;\n\t/** Execute the tool with validated arguments. */\n\trun(args: I): Promise<O>;\n}\n\n/**\n * Define a local function tool with full type inference.\n *\n * @example\n * ```ts\n * const add = defineTool({\n * name: \"add\",\n * description: \"Add two numbers.\",\n * inputSchema: { type: \"object\", properties: { a: { type: \"number\" }, b: { type: \"number\" } }, required: [\"a\", \"b\"] },\n * run: async ({ a, b }: { a: number; b: number }) => ({ sum: a + b }),\n * });\n * ```\n */\nexport function defineTool<I, O>(tool: {\n\tname: string;\n\tdescription: string;\n\tinputSchema: JSONSchema;\n\toutputSchema?: JSONSchema;\n\trun: (args: I) => Promise<O>;\n}): Tool<I, O> {\n\treturn { source: \"local\", enabled: true, ...tool };\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// src/middleware/use.ts
|
|
2
|
+
function useMiddleware(config, ...middleware) {
|
|
3
|
+
return { ...config, middleware: [...config.middleware ?? [], ...middleware] };
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export { useMiddleware };
|
|
7
|
+
//# sourceMappingURL=chunk-IUKD54F7.js.map
|
|
8
|
+
//# sourceMappingURL=chunk-IUKD54F7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/use.ts"],"names":[],"mappings":";AAmBO,SAAS,aAAA,CAAc,WAAwB,UAAA,EAAuC;AAC5F,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,UAAA,EAAY,CAAC,GAAI,MAAA,CAAO,UAAA,IAAc,EAAC,EAAI,GAAG,UAAU,CAAA,EAAE;AAC/E","file":"chunk-IUKD54F7.js","sourcesContent":["/**\n * Convenience helper for attaching middleware to an agent configuration.\n * Middleware is applied around provider calls when the agent runs. (FR-023)\n *\n * @packageDocumentation\n */\n\nimport type { AgentConfig } from \"../agents/agent.js\";\nimport type { Middleware } from \"./middleware.js\";\n\n/**\n * Return a copy of `config` with the given middleware appended.\n *\n * @example\n * ```ts\n * const cfg = useMiddleware(baseConfig, loggingMiddleware, retryMiddleware);\n * const agent = createAgent(cfg);\n * ```\n */\nexport function useMiddleware(config: AgentConfig, ...middleware: Middleware[]): AgentConfig {\n\treturn { ...config, middleware: [...(config.middleware ?? []), ...middleware] };\n}\n"]}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { redact } from './chunk-DEABART4.js';
|
|
2
|
+
|
|
3
|
+
// src/core/errors.ts
|
|
4
|
+
var FrameworkError = class extends Error {
|
|
5
|
+
/** Optional structured details (already redaction-safe at serialization time). */
|
|
6
|
+
details;
|
|
7
|
+
constructor(message, details) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = new.target.name;
|
|
10
|
+
this.details = details;
|
|
11
|
+
}
|
|
12
|
+
/** Redaction-safe JSON form used by logs/traces. */
|
|
13
|
+
toJSON() {
|
|
14
|
+
return redact({
|
|
15
|
+
name: this.name,
|
|
16
|
+
kind: this.kind,
|
|
17
|
+
message: this.message,
|
|
18
|
+
details: this.details
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var ProviderError = class extends FrameworkError {
|
|
23
|
+
kind = "provider";
|
|
24
|
+
reason;
|
|
25
|
+
status;
|
|
26
|
+
constructor(message, reason, opts) {
|
|
27
|
+
super(message, opts?.details);
|
|
28
|
+
this.reason = reason;
|
|
29
|
+
this.status = opts?.status;
|
|
30
|
+
}
|
|
31
|
+
/** Whether this error should be retried with backoff. */
|
|
32
|
+
get retryable() {
|
|
33
|
+
return this.reason === "transient";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var ToolError = class extends FrameworkError {
|
|
37
|
+
kind = "tool";
|
|
38
|
+
reason;
|
|
39
|
+
toolName;
|
|
40
|
+
constructor(message, reason, toolName, details) {
|
|
41
|
+
super(message, details);
|
|
42
|
+
this.reason = reason;
|
|
43
|
+
this.toolName = toolName;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var MCPError = class extends FrameworkError {
|
|
47
|
+
kind = "mcp";
|
|
48
|
+
serverId;
|
|
49
|
+
constructor(message, serverId, details) {
|
|
50
|
+
super(message, details);
|
|
51
|
+
this.serverId = serverId;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var CheckpointError = class extends FrameworkError {
|
|
55
|
+
kind = "checkpoint";
|
|
56
|
+
reason;
|
|
57
|
+
constructor(message, reason, details) {
|
|
58
|
+
super(message, details);
|
|
59
|
+
this.reason = reason;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
var RuntimeUnsupportedError = class extends FrameworkError {
|
|
63
|
+
kind = "runtime-unsupported";
|
|
64
|
+
feature;
|
|
65
|
+
constructor(feature, details) {
|
|
66
|
+
super(`Feature "${feature}" is not supported in the current runtime`, details);
|
|
67
|
+
this.feature = feature;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var ValidationError = class extends FrameworkError {
|
|
71
|
+
kind = "validation";
|
|
72
|
+
constructor(message, details) {
|
|
73
|
+
super(message, details);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export { CheckpointError, FrameworkError, MCPError, ProviderError, RuntimeUnsupportedError, ToolError, ValidationError };
|
|
78
|
+
//# sourceMappingURL=chunk-IXV4UIF5.js.map
|
|
79
|
+
//# sourceMappingURL=chunk-IXV4UIF5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts"],"names":[],"mappings":";;;AAoBO,IAAe,cAAA,GAAf,cAAsC,KAAA,CAAM;AAAA;AAAA,EAGzC,OAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAAmC;AAC/D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,OAAO,GAAA,CAAA,MAAA,CAAW,IAAA;AACvB,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EAChB;AAAA;AAAA,EAGA,MAAA,GAAkC;AACjC,IAAA,OAAO,MAAA,CAAO;AAAA,MACb,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,SAAS,IAAA,CAAK;AAAA,KACd,CAAA;AAAA,EACF;AACD;AAUO,IAAM,aAAA,GAAN,cAA4B,cAAA,CAAe;AAAA,EACxC,IAAA,GAAO,UAAA;AAAA,EACP,MAAA;AAAA,EACA,MAAA;AAAA,EAET,WAAA,CACC,OAAA,EACA,MAAA,EACA,IAAA,EACC;AACD,IAAA,KAAA,CAAM,OAAA,EAAS,MAAM,OAAO,CAAA;AAC5B,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,SAAS,IAAA,EAAM,MAAA;AAAA,EACrB;AAAA;AAAA,EAGA,IAAI,SAAA,GAAqB;AACxB,IAAA,OAAO,KAAK,MAAA,KAAW,WAAA;AAAA,EACxB;AACD;AAUO,IAAM,SAAA,GAAN,cAAwB,cAAA,CAAe;AAAA,EACpC,IAAA,GAAO,MAAA;AAAA,EACP,MAAA;AAAA,EACA,QAAA;AAAA,EAET,WAAA,CACC,OAAA,EACA,MAAA,EACA,QAAA,EACA,OAAA,EACC;AACD,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EACjB;AACD;AAGO,IAAM,QAAA,GAAN,cAAuB,cAAA,CAAe;AAAA,EACnC,IAAA,GAAO,KAAA;AAAA,EACP,QAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,QAAA,EAAkB,OAAA,EAAmC;AACjF,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAAA,EACjB;AACD;AAMO,IAAM,eAAA,GAAN,cAA8B,cAAA,CAAe;AAAA,EAC1C,IAAA,GAAO,YAAA;AAAA,EACP,MAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,MAAA,EAA+B,OAAA,EAAmC;AAC9F,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AACtB,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EACf;AACD;AAGO,IAAM,uBAAA,GAAN,cAAsC,cAAA,CAAe;AAAA,EAClD,IAAA,GAAO,qBAAA;AAAA,EACP,OAAA;AAAA,EAET,WAAA,CAAY,SAAiB,OAAA,EAAmC;AAC/D,IAAA,KAAA,CAAM,CAAA,SAAA,EAAY,OAAO,CAAA,yCAAA,CAAA,EAA6C,OAAO,CAAA;AAC7E,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EAChB;AACD;AAGO,IAAM,eAAA,GAAN,cAA8B,cAAA,CAAe;AAAA,EAC1C,IAAA,GAAO,YAAA;AAAA,EAEhB,WAAA,CAAY,SAAiB,OAAA,EAAmC;AAC/D,IAAA,KAAA,CAAM,SAAS,OAAO,CAAA;AAAA,EACvB;AACD","file":"chunk-IXV4UIF5.js","sourcesContent":["/**\n * Typed error hierarchy. Every failure surfaced by the framework is one of these\n * typed errors so callers (and agents) can branch on `kind` rather than parsing\n * messages. All error serialization passes through redaction (see `redaction.ts`).\n *\n * @packageDocumentation\n */\n\nimport { redact } from \"./redaction.js\";\n\n/** Discriminator for {@link FrameworkError} subclasses. */\nexport type ErrorKind =\n\t| \"provider\"\n\t| \"tool\"\n\t| \"mcp\"\n\t| \"checkpoint\"\n\t| \"runtime-unsupported\"\n\t| \"validation\";\n\n/** Base class for all framework errors. */\nexport abstract class FrameworkError extends Error {\n\tabstract readonly kind: ErrorKind;\n\t/** Optional structured details (already redaction-safe at serialization time). */\n\treadonly details?: Record<string, unknown>;\n\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = new.target.name;\n\t\tthis.details = details;\n\t}\n\n\t/** Redaction-safe JSON form used by logs/traces. */\n\ttoJSON(): Record<string, unknown> {\n\t\treturn redact({\n\t\t\tname: this.name,\n\t\t\tkind: this.kind,\n\t\t\tmessage: this.message,\n\t\t\tdetails: this.details,\n\t\t});\n\t}\n}\n\n/** Reason a provider call failed. Transient reasons are retryable. */\nexport type ProviderErrorReason =\n\t| \"transient\" // 429/5xx/network/timeout — retryable\n\t| \"auth\" // 401/403 — fail fast\n\t| \"client\" // other 4xx — fail fast\n\t| \"malformed\"; // unparseable/incomplete response\n\n/** LLM provider failure. (FR-008a) */\nexport class ProviderError extends FrameworkError {\n\treadonly kind = \"provider\" as const;\n\treadonly reason: ProviderErrorReason;\n\treadonly status?: number;\n\n\tconstructor(\n\t\tmessage: string,\n\t\treason: ProviderErrorReason,\n\t\topts?: { status?: number; details?: Record<string, unknown> },\n\t) {\n\t\tsuper(message, opts?.details);\n\t\tthis.reason = reason;\n\t\tthis.status = opts?.status;\n\t}\n\n\t/** Whether this error should be retried with backoff. */\n\tget retryable(): boolean {\n\t\treturn this.reason === \"transient\";\n\t}\n}\n\n/** Reason a tool invocation failed. */\nexport type ToolErrorReason =\n\t| \"not-found\"\n\t| \"invalid-arguments\"\n\t| \"timeout\"\n\t| \"run-failure\";\n\n/** Tool invocation failure. (FR-011a, FR-012c) */\nexport class ToolError extends FrameworkError {\n\treadonly kind = \"tool\" as const;\n\treadonly reason: ToolErrorReason;\n\treadonly toolName: string;\n\n\tconstructor(\n\t\tmessage: string,\n\t\treason: ToolErrorReason,\n\t\ttoolName: string,\n\t\tdetails?: Record<string, unknown>,\n\t) {\n\t\tsuper(message, details);\n\t\tthis.reason = reason;\n\t\tthis.toolName = toolName;\n\t}\n}\n\n/** MCP server failure (e.g., unavailable). (FR-015) */\nexport class MCPError extends FrameworkError {\n\treadonly kind = \"mcp\" as const;\n\treadonly serverId: string;\n\n\tconstructor(message: string, serverId: string, details?: Record<string, unknown>) {\n\t\tsuper(message, details);\n\t\tthis.serverId = serverId;\n\t}\n}\n\n/** Reason a checkpoint could not be restored. (FR-022a) */\nexport type CheckpointErrorReason = \"corrupt\" | \"version-mismatch\";\n\n/** Checkpoint restore failure. Fails closed — no partial restore. */\nexport class CheckpointError extends FrameworkError {\n\treadonly kind = \"checkpoint\" as const;\n\treadonly reason: CheckpointErrorReason;\n\n\tconstructor(message: string, reason: CheckpointErrorReason, details?: Record<string, unknown>) {\n\t\tsuper(message, details);\n\t\tthis.reason = reason;\n\t}\n}\n\n/** A feature was requested that the current runtime cannot support. (FR-030a) */\nexport class RuntimeUnsupportedError extends FrameworkError {\n\treadonly kind = \"runtime-unsupported\" as const;\n\treadonly feature: string;\n\n\tconstructor(feature: string, details?: Record<string, unknown>) {\n\t\tsuper(`Feature \"${feature}\" is not supported in the current runtime`, details);\n\t\tthis.feature = feature;\n\t}\n}\n\n/** Schema validation failure. (FR-011) */\nexport class ValidationError extends FrameworkError {\n\treadonly kind = \"validation\" as const;\n\n\tconstructor(message: string, details?: Record<string, unknown>) {\n\t\tsuper(message, details);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/middleware/use.ts
|
|
4
|
+
function useMiddleware(config, ...middleware) {
|
|
5
|
+
return { ...config, middleware: [...config.middleware ?? [], ...middleware] };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
exports.useMiddleware = useMiddleware;
|
|
9
|
+
//# sourceMappingURL=chunk-KEI3EALJ.cjs.map
|
|
10
|
+
//# sourceMappingURL=chunk-KEI3EALJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/middleware/use.ts"],"names":[],"mappings":";;;AAmBO,SAAS,aAAA,CAAc,WAAwB,UAAA,EAAuC;AAC5F,EAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,UAAA,EAAY,CAAC,GAAI,MAAA,CAAO,UAAA,IAAc,EAAC,EAAI,GAAG,UAAU,CAAA,EAAE;AAC/E","file":"chunk-KEI3EALJ.cjs","sourcesContent":["/**\n * Convenience helper for attaching middleware to an agent configuration.\n * Middleware is applied around provider calls when the agent runs. (FR-023)\n *\n * @packageDocumentation\n */\n\nimport type { AgentConfig } from \"../agents/agent.js\";\nimport type { Middleware } from \"./middleware.js\";\n\n/**\n * Return a copy of `config` with the given middleware appended.\n *\n * @example\n * ```ts\n * const cfg = useMiddleware(baseConfig, loggingMiddleware, retryMiddleware);\n * const agent = createAgent(cfg);\n * ```\n */\nexport function useMiddleware(config: AgentConfig, ...middleware: Middleware[]): AgentConfig {\n\treturn { ...config, middleware: [...(config.middleware ?? []), ...middleware] };\n}\n"]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/core/types.ts
|
|
4
|
+
function textMessage(role, text) {
|
|
5
|
+
return { role, parts: [{ type: "text", text }] };
|
|
6
|
+
}
|
|
7
|
+
function hasImage(message) {
|
|
8
|
+
return message.parts.some((p) => p.type === "image");
|
|
9
|
+
}
|
|
10
|
+
function messageText(message) {
|
|
11
|
+
return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/agents/thread.ts
|
|
15
|
+
function estimateTokens(messages) {
|
|
16
|
+
const chars = messages.reduce((sum, m) => sum + messageText(m).length, 0);
|
|
17
|
+
return Math.ceil(chars / 4);
|
|
18
|
+
}
|
|
19
|
+
var Thread = class _Thread {
|
|
20
|
+
id;
|
|
21
|
+
messages;
|
|
22
|
+
/** Whether the thread has been compacted at least once. */
|
|
23
|
+
compacted = false;
|
|
24
|
+
constructor(id, messages = []) {
|
|
25
|
+
this.id = id ?? cryptoRandomId();
|
|
26
|
+
this.messages = messages;
|
|
27
|
+
}
|
|
28
|
+
/** Append a message. */
|
|
29
|
+
add(message) {
|
|
30
|
+
this.messages.push(message);
|
|
31
|
+
}
|
|
32
|
+
/** Serializable snapshot for persistence. */
|
|
33
|
+
toJSON() {
|
|
34
|
+
return { id: this.id, messages: this.messages, compacted: this.compacted };
|
|
35
|
+
}
|
|
36
|
+
/** Restore a thread from a snapshot. */
|
|
37
|
+
static fromJSON(data) {
|
|
38
|
+
const t = new _Thread(data.id, data.messages);
|
|
39
|
+
t.compacted = data.compacted ?? false;
|
|
40
|
+
return t;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compact the thread if it exceeds the threshold. System messages and the most
|
|
44
|
+
* recent turn are preserved; older turns are summarized via the model.
|
|
45
|
+
*
|
|
46
|
+
* @returns true if compaction occurred.
|
|
47
|
+
*/
|
|
48
|
+
async maybeCompact(provider, options) {
|
|
49
|
+
const threshold = options?.compactionThreshold ?? 0.9;
|
|
50
|
+
const limit = provider.capabilities.maxInputTokens * threshold;
|
|
51
|
+
if (estimateTokens(this.messages) < limit) return false;
|
|
52
|
+
const summarizer = options?.compactionModel ?? provider;
|
|
53
|
+
const system = this.messages.filter((m) => m.role === "system");
|
|
54
|
+
const recent = this.messages.slice(-2);
|
|
55
|
+
const toSummarize = this.messages.filter((m) => m.role !== "system").slice(0, -2);
|
|
56
|
+
if (toSummarize.length === 0) return false;
|
|
57
|
+
const summary = await summarizer.generate({
|
|
58
|
+
messages: [
|
|
59
|
+
textMessage(
|
|
60
|
+
"system",
|
|
61
|
+
"Summarize the following conversation compactly, preserving facts, decisions, and open questions."
|
|
62
|
+
),
|
|
63
|
+
textMessage("user", toSummarize.map((m) => `${m.role}: ${messageText(m)}`).join("\n"))
|
|
64
|
+
]
|
|
65
|
+
});
|
|
66
|
+
this.messages = [
|
|
67
|
+
...system,
|
|
68
|
+
textMessage("system", `Summary of earlier conversation: ${summary.text}`),
|
|
69
|
+
...recent
|
|
70
|
+
];
|
|
71
|
+
this.compacted = true;
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
function cryptoRandomId() {
|
|
76
|
+
const c = globalThis.crypto;
|
|
77
|
+
if (c?.randomUUID) return c.randomUUID();
|
|
78
|
+
return `thread-${Math.random().toString(36).slice(2)}-${Date.now()}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
exports.Thread = Thread;
|
|
82
|
+
exports.estimateTokens = estimateTokens;
|
|
83
|
+
exports.hasImage = hasImage;
|
|
84
|
+
exports.messageText = messageText;
|
|
85
|
+
exports.textMessage = textMessage;
|
|
86
|
+
//# sourceMappingURL=chunk-LMN75W3W.cjs.map
|
|
87
|
+
//# sourceMappingURL=chunk-LMN75W3W.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/types.ts","../src/agents/thread.ts"],"names":[],"mappings":"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","file":"chunk-LMN75W3W.cjs","sourcesContent":["/**\n * Shared content, message, and model-capability types used across the framework.\n *\n * These are the lowest-level building blocks: every higher-level module (agents,\n * providers, tools, workflows) speaks in terms of {@link Message} and\n * {@link ContentPart}. Keeping them dependency-free keeps the core tree-shakeable.\n *\n * @packageDocumentation\n */\n\n/** A JSON Schema object (draft 2020-12 compatible), as popularized by MCP. */\nexport type JSONSchema = Record<string, unknown>;\n\n/** Role of a message in a conversation. */\nexport type Role = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\n/** A single piece of message content. Images are only valid for vision-capable models. */\nexport type ContentPart =\n\t| { type: \"text\"; text: string }\n\t| { type: \"image\"; data: string; mimeType: string };\n\n/**\n * A conversation message.\n *\n * @example\n * ```ts\n * const msg: Message = { role: \"user\", parts: [{ type: \"text\", text: \"Hi\" }] };\n * ```\n */\nexport interface Message {\n\trole: Role;\n\tparts: ContentPart[];\n\t/** Optional tool-call linkage for assistant/tool messages. */\n\ttoolCallId?: string;\n\t/** Optional display name (e.g., the tool name for a tool message). */\n\tname?: string;\n}\n\n/**\n * Per-model capabilities supplied by the caller. The framework cannot reliably\n * discover these for arbitrary OpenAI-compatible/LM Studio models, so they are\n * provided explicitly. (FR-007a)\n */\nexport interface ModelCapabilities {\n\t/** Model id/name. */\n\tmodel: string;\n\t/** Maximum input/context tokens; drives compaction threshold. */\n\tmaxInputTokens: number;\n\t/** Maximum output tokens. */\n\tmaxOutputTokens: number;\n\t/** Whether the model accepts image input. Defaults to false. */\n\tsupportsVision?: boolean;\n\t/** Whether the model emits separate reasoning/thinking content. Defaults to false. */\n\tsupportsReasoning?: boolean;\n}\n\n/** Convenience: build a user message from a plain string. */\nexport function textMessage(role: Role, text: string): Message {\n\treturn { role, parts: [{ type: \"text\", text }] };\n}\n\n/** Returns true if a message contains any image content part. */\nexport function hasImage(message: Message): boolean {\n\treturn message.parts.some((p) => p.type === \"image\");\n}\n\n/** Extract the concatenated text from a message. */\nexport function messageText(message: Message): string {\n\treturn message.parts\n\t\t.filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n\t\t.map((p) => p.text)\n\t\t.join(\"\");\n}\n","/**\n * Conversation thread with automatic compaction. When a thread approaches the\n * model's input-token budget it is summarized into a compact form so the\n * conversation can continue. (FR-004, FR-004a, FR-004b)\n *\n * @packageDocumentation\n */\n\nimport type { Message } from \"../core/types.js\";\nimport { messageText, textMessage } from \"../core/types.js\";\nimport type { Provider } from \"../providers/provider.js\";\n\n/** Options controlling a thread's compaction behavior. */\nexport interface ThreadOptions {\n\t/** Fraction of `maxInputTokens` at which compaction triggers. Default 0.9. */\n\tcompactionThreshold?: number;\n\t/** Provider used to summarize; defaults to the agent's own provider. (FR-004b) */\n\tcompactionModel?: Provider;\n}\n\n/** Rough token estimate (~4 chars/token) — avoids a tokenizer dependency. */\nexport function estimateTokens(messages: Message[]): number {\n\tconst chars = messages.reduce((sum, m) => sum + messageText(m).length, 0);\n\treturn Math.ceil(chars / 4);\n}\n\n/** A multi-turn conversation that preserves context and compacts when large. */\nexport class Thread {\n\treadonly id: string;\n\tmessages: Message[];\n\t/** Whether the thread has been compacted at least once. */\n\tcompacted = false;\n\n\tconstructor(id?: string, messages: Message[] = []) {\n\t\tthis.id = id ?? cryptoRandomId();\n\t\tthis.messages = messages;\n\t}\n\n\t/** Append a message. */\n\tadd(message: Message): void {\n\t\tthis.messages.push(message);\n\t}\n\n\t/** Serializable snapshot for persistence. */\n\ttoJSON(): { id: string; messages: Message[]; compacted: boolean } {\n\t\treturn { id: this.id, messages: this.messages, compacted: this.compacted };\n\t}\n\n\t/** Restore a thread from a snapshot. */\n\tstatic fromJSON(data: { id: string; messages: Message[]; compacted?: boolean }): Thread {\n\t\tconst t = new Thread(data.id, data.messages);\n\t\tt.compacted = data.compacted ?? false;\n\t\treturn t;\n\t}\n\n\t/**\n\t * Compact the thread if it exceeds the threshold. System messages and the most\n\t * recent turn are preserved; older turns are summarized via the model.\n\t *\n\t * @returns true if compaction occurred.\n\t */\n\tasync maybeCompact(provider: Provider, options?: ThreadOptions): Promise<boolean> {\n\t\tconst threshold = options?.compactionThreshold ?? 0.9;\n\t\tconst limit = provider.capabilities.maxInputTokens * threshold;\n\t\tif (estimateTokens(this.messages) < limit) return false;\n\n\t\tconst summarizer = options?.compactionModel ?? provider;\n\t\tconst system = this.messages.filter((m) => m.role === \"system\");\n\t\tconst recent = this.messages.slice(-2);\n\t\tconst toSummarize = this.messages.filter((m) => m.role !== \"system\").slice(0, -2);\n\t\tif (toSummarize.length === 0) return false;\n\n\t\tconst summary = await summarizer.generate({\n\t\t\tmessages: [\n\t\t\t\ttextMessage(\n\t\t\t\t\t\"system\",\n\t\t\t\t\t\"Summarize the following conversation compactly, preserving facts, decisions, and open questions.\",\n\t\t\t\t),\n\t\t\t\ttextMessage(\"user\", toSummarize.map((m) => `${m.role}: ${messageText(m)}`).join(\"\\n\")),\n\t\t\t],\n\t\t});\n\n\t\tthis.messages = [\n\t\t\t...system,\n\t\t\ttextMessage(\"system\", `Summary of earlier conversation: ${summary.text}`),\n\t\t\t...recent,\n\t\t];\n\t\tthis.compacted = true;\n\t\treturn true;\n\t}\n}\n\nfunction cryptoRandomId(): string {\n\tconst c = (globalThis as { crypto?: Crypto }).crypto;\n\tif (c?.randomUUID) return c.randomUUID();\n\treturn `thread-${Math.random().toString(36).slice(2)}-${Date.now()}`;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-MCLVWCOB.js"}
|