@lssm/lib.ai-agent 0.0.0-canary-20251217063201 → 0.0.0-canary-20251217072406

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.
@@ -1 +1,123 @@
1
- import{z as e}from"zod";function t(o){let s=o,c=t=>s.nullable?e.union([t,e.null()]):t;if(s.const!==void 0)return e.literal(s.const);if(s.enum){let t=s.enum;return c(e.enum(t.map(String)))}if(s.anyOf&&s.anyOf.length>0){let n=s.anyOf.map(e=>t(e));return n.length===1?n[0]:e.union([n[0],n[1],...n.slice(2)])}if(s.oneOf&&s.oneOf.length>0){let n=s.oneOf.map(e=>t(e));return n.length===1?n[0]:e.union([n[0],n[1],...n.slice(2)])}if(s.allOf&&s.allOf.length>0)return s.allOf.map(e=>t(e)).reduce((t,n)=>e.intersection(t,n));switch(s.type){case`string`:return c(n(s));case`number`:case`integer`:return c(r(s));case`boolean`:return c(e.boolean());case`null`:return e.null();case`array`:return c(i(s));case`object`:return c(a(s));default:return e.unknown()}}function n(t){let n=e.string();switch(t.description&&(n=n.describe(t.description)),t.format){case`email`:n=n.email();break;case`uri`:case`url`:n=n.url();break;case`uuid`:n=n.uuid();break;case`date-time`:n=n.datetime();break;case`date`:n=n.date();break}return t.minLength!==void 0&&(n=n.min(t.minLength)),t.maxLength!==void 0&&(n=n.max(t.maxLength)),t.pattern&&(n=n.regex(new RegExp(t.pattern))),n}function r(t){let n=t.type===`integer`?e.number().int():e.number();return t.description&&(n=n.describe(t.description)),t.minimum!==void 0&&(n=n.min(t.minimum)),t.maximum!==void 0&&(n=n.max(t.maximum)),n}function i(n){let r=n.items?t(n.items):e.unknown(),i=e.array(r);return n.description&&(i=i.describe(n.description)),i}function a(n){let r=n.properties??{},i=new Set(n.required??[]),a={};for(let[e,n]of Object.entries(r)){let r=t(n);a[e]=i.has(e)?r:r.optional()}let o=e.object(a);return n.description&&(o=o.describe(n.description)),o}function o(n){return!n||Object.keys(n).length===0?e.object({}):t(n)}export{t as jsonSchemaToZod,o as jsonSchemaToZodSafe};
1
+ import { z } from "zod";
2
+
3
+ //#region src/schema/json-schema-to-zod.ts
4
+ /**
5
+ * Convert a JSON Schema to a Zod schema.
6
+ *
7
+ * Supports common JSON Schema types and constraints:
8
+ * - string, number, integer, boolean, null
9
+ * - object with properties and required
10
+ * - array with items
11
+ * - enum and const
12
+ * - anyOf, oneOf, allOf
13
+ * - format constraints (email, uri, uuid, date-time)
14
+ * - numeric constraints (minimum, maximum)
15
+ * - string constraints (minLength, maxLength, pattern)
16
+ *
17
+ * @param schema - JSON Schema object
18
+ * @returns Zod schema
19
+ */
20
+ function jsonSchemaToZod(schema) {
21
+ const s = schema;
22
+ const makeNullable = (zodSchema) => {
23
+ return s.nullable ? z.union([zodSchema, z.null()]) : zodSchema;
24
+ };
25
+ if (s.const !== void 0) return z.literal(s.const);
26
+ if (s.enum) {
27
+ const values = s.enum;
28
+ return makeNullable(z.enum(values.map(String)));
29
+ }
30
+ if (s.anyOf && s.anyOf.length > 0) {
31
+ const schemas = s.anyOf.map((sub) => jsonSchemaToZod(sub));
32
+ if (schemas.length === 1) return schemas[0];
33
+ return z.union([
34
+ schemas[0],
35
+ schemas[1],
36
+ ...schemas.slice(2)
37
+ ]);
38
+ }
39
+ if (s.oneOf && s.oneOf.length > 0) {
40
+ const schemas = s.oneOf.map((sub) => jsonSchemaToZod(sub));
41
+ if (schemas.length === 1) return schemas[0];
42
+ return z.union([
43
+ schemas[0],
44
+ schemas[1],
45
+ ...schemas.slice(2)
46
+ ]);
47
+ }
48
+ if (s.allOf && s.allOf.length > 0) return s.allOf.map((sub) => jsonSchemaToZod(sub)).reduce((acc, curr) => z.intersection(acc, curr));
49
+ switch (s.type) {
50
+ case "string": return makeNullable(buildStringSchema(s));
51
+ case "number":
52
+ case "integer": return makeNullable(buildNumberSchema(s));
53
+ case "boolean": return makeNullable(z.boolean());
54
+ case "null": return z.null();
55
+ case "array": return makeNullable(buildArraySchema(s));
56
+ case "object": return makeNullable(buildObjectSchema(s));
57
+ default: return z.unknown();
58
+ }
59
+ }
60
+ function buildStringSchema(schema) {
61
+ let zodSchema = z.string();
62
+ if (schema.description) zodSchema = zodSchema.describe(schema.description);
63
+ switch (schema.format) {
64
+ case "email":
65
+ zodSchema = zodSchema.email();
66
+ break;
67
+ case "uri":
68
+ case "url":
69
+ zodSchema = zodSchema.url();
70
+ break;
71
+ case "uuid":
72
+ zodSchema = zodSchema.uuid();
73
+ break;
74
+ case "date-time":
75
+ zodSchema = zodSchema.datetime();
76
+ break;
77
+ case "date":
78
+ zodSchema = zodSchema.date();
79
+ break;
80
+ }
81
+ if (schema.minLength !== void 0) zodSchema = zodSchema.min(schema.minLength);
82
+ if (schema.maxLength !== void 0) zodSchema = zodSchema.max(schema.maxLength);
83
+ if (schema.pattern) zodSchema = zodSchema.regex(new RegExp(schema.pattern));
84
+ return zodSchema;
85
+ }
86
+ function buildNumberSchema(schema) {
87
+ let zodSchema = schema.type === "integer" ? z.number().int() : z.number();
88
+ if (schema.description) zodSchema = zodSchema.describe(schema.description);
89
+ if (schema.minimum !== void 0) zodSchema = zodSchema.min(schema.minimum);
90
+ if (schema.maximum !== void 0) zodSchema = zodSchema.max(schema.maximum);
91
+ return zodSchema;
92
+ }
93
+ function buildArraySchema(schema) {
94
+ const itemsSchema = schema.items ? jsonSchemaToZod(schema.items) : z.unknown();
95
+ let zodSchema = z.array(itemsSchema);
96
+ if (schema.description) zodSchema = zodSchema.describe(schema.description);
97
+ return zodSchema;
98
+ }
99
+ function buildObjectSchema(schema) {
100
+ const properties = schema.properties ?? {};
101
+ const required = new Set(schema.required ?? []);
102
+ const shape = {};
103
+ for (const [key, propSchema] of Object.entries(properties)) {
104
+ const zodProp = jsonSchemaToZod(propSchema);
105
+ shape[key] = required.has(key) ? zodProp : zodProp.optional();
106
+ }
107
+ let zodSchema = z.object(shape);
108
+ if (schema.description) zodSchema = zodSchema.describe(schema.description);
109
+ return zodSchema;
110
+ }
111
+ /**
112
+ * Convert a JSON Schema to a Zod schema with a default empty object fallback.
113
+ *
114
+ * @param schema - Optional JSON Schema object
115
+ * @returns Zod schema (defaults to empty object schema)
116
+ */
117
+ function jsonSchemaToZodSafe(schema) {
118
+ if (!schema || Object.keys(schema).length === 0) return z.object({});
119
+ return jsonSchemaToZod(schema);
120
+ }
121
+
122
+ //#endregion
123
+ export { jsonSchemaToZod, jsonSchemaToZodSafe };
@@ -1 +1,64 @@
1
- import{jsonSchemaToZod as e}from"./json-schema-to-zod.js";import{Output as t}from"ai";import{z as n}from"zod";function r(n){let r=e(n);return t.object({schema:r})}function i(n){let r=e(n);return t.array({element:r})}function a(e){return t.choice({options:e})}function o(e){return t.object({schema:e})}function s(){return t.text()}const c={fromJsonSchema:r,arrayFromJsonSchema:i,fromEnum:a,fromZod:o,text:s};export{c as SchemaOutput,a as enumToChoiceOutput,i as jsonSchemaToArrayOutput,r as jsonSchemaToOutput,s as textOutput,o as zodToOutput};
1
+ import { jsonSchemaToZod } from "./json-schema-to-zod.js";
2
+ import { Output } from "ai";
3
+ import { z } from "zod";
4
+
5
+ //#region src/schema/schema-output.ts
6
+ /**
7
+ * Create an AI SDK Output.object from a JSON Schema.
8
+ *
9
+ * @param schema - JSON Schema object
10
+ * @returns AI SDK Output configuration
11
+ */
12
+ function jsonSchemaToOutput(schema) {
13
+ const zodSchema = jsonSchemaToZod(schema);
14
+ return Output.object({ schema: zodSchema });
15
+ }
16
+ /**
17
+ * Create an AI SDK Output.array from a JSON Schema items definition.
18
+ *
19
+ * @param itemSchema - JSON Schema for array items
20
+ * @returns AI SDK Output configuration
21
+ */
22
+ function jsonSchemaToArrayOutput(itemSchema) {
23
+ const zodSchema = jsonSchemaToZod(itemSchema);
24
+ return Output.array({ element: zodSchema });
25
+ }
26
+ /**
27
+ * Create an AI SDK Output.choice from enum values.
28
+ *
29
+ * @param choices - Array of choice values
30
+ * @returns AI SDK Output configuration
31
+ */
32
+ function enumToChoiceOutput(choices) {
33
+ return Output.choice({ options: choices });
34
+ }
35
+ /**
36
+ * Create an AI SDK Output from a Zod schema directly.
37
+ *
38
+ * @param schema - Zod schema
39
+ * @returns AI SDK Output configuration
40
+ */
41
+ function zodToOutput(schema) {
42
+ return Output.object({ schema });
43
+ }
44
+ /**
45
+ * Create a simple text output configuration.
46
+ *
47
+ * @returns AI SDK Output configuration for text
48
+ */
49
+ function textOutput() {
50
+ return Output.text();
51
+ }
52
+ /**
53
+ * Output builder that can be used fluently.
54
+ */
55
+ const SchemaOutput = {
56
+ fromJsonSchema: jsonSchemaToOutput,
57
+ arrayFromJsonSchema: jsonSchemaToArrayOutput,
58
+ fromEnum: enumToChoiceOutput,
59
+ fromZod: zodToOutput,
60
+ text: textOutput
61
+ };
62
+
63
+ //#endregion
64
+ export { SchemaOutput, enumToChoiceOutput, jsonSchemaToArrayOutput, jsonSchemaToOutput, textOutput, zodToOutput };
@@ -1 +1,3 @@
1
- import{InMemorySessionStore as e,createInMemorySessionStore as t,generateSessionId as n}from"./store.js";export{e as InMemorySessionStore,t as createInMemorySessionStore,n as generateSessionId};
1
+ import { InMemorySessionStore, createInMemorySessionStore, generateSessionId } from "./store.js";
2
+
3
+ export { InMemorySessionStore, createInMemorySessionStore, generateSessionId };
@@ -1 +1,78 @@
1
- var e=class{sessions=new Map;async get(e){return this.sessions.get(e)??null}async create(e){let t=new Date,n={...e,createdAt:t,updatedAt:t};return this.sessions.set(e.sessionId,n),n}async appendStep(e,t){let n=this.sessions.get(e);n&&(n.steps.push(t),n.updatedAt=new Date)}async appendMessage(e,t){let n=this.sessions.get(e);n&&(n.messages.push(t),n.updatedAt=new Date)}async update(e,t){let n=this.sessions.get(e);n&&Object.assign(n,t,{updatedAt:new Date})}async delete(e){return this.sessions.delete(e)}async listByAgent(e,t=100){let n=[];for(let r of this.sessions.values())if(r.agentId===e&&(n.push(r),n.length>=t))break;return n.sort((e,t)=>t.updatedAt.getTime()-e.updatedAt.getTime())}async listByTenant(e,t=100){let n=[];for(let r of this.sessions.values())if(r.tenantId===e&&(n.push(r),n.length>=t))break;return n.sort((e,t)=>t.updatedAt.getTime()-e.updatedAt.getTime())}clear(){this.sessions.clear()}};function t(){return new e}function n(){return`sess_${Date.now()}_${Math.random().toString(36).slice(2,11)}`}export{e as InMemorySessionStore,t as createInMemorySessionStore,n as generateSessionId};
1
+ //#region src/session/store.ts
2
+ /**
3
+ * In-memory session store for development and testing.
4
+ */
5
+ var InMemorySessionStore = class {
6
+ sessions = /* @__PURE__ */ new Map();
7
+ async get(sessionId) {
8
+ return this.sessions.get(sessionId) ?? null;
9
+ }
10
+ async create(session) {
11
+ const now = /* @__PURE__ */ new Date();
12
+ const fullSession = {
13
+ ...session,
14
+ createdAt: now,
15
+ updatedAt: now
16
+ };
17
+ this.sessions.set(session.sessionId, fullSession);
18
+ return fullSession;
19
+ }
20
+ async appendStep(sessionId, step) {
21
+ const session = this.sessions.get(sessionId);
22
+ if (session) {
23
+ session.steps.push(step);
24
+ session.updatedAt = /* @__PURE__ */ new Date();
25
+ }
26
+ }
27
+ async appendMessage(sessionId, message) {
28
+ const session = this.sessions.get(sessionId);
29
+ if (session) {
30
+ session.messages.push(message);
31
+ session.updatedAt = /* @__PURE__ */ new Date();
32
+ }
33
+ }
34
+ async update(sessionId, updates) {
35
+ const session = this.sessions.get(sessionId);
36
+ if (session) Object.assign(session, updates, { updatedAt: /* @__PURE__ */ new Date() });
37
+ }
38
+ async delete(sessionId) {
39
+ return this.sessions.delete(sessionId);
40
+ }
41
+ async listByAgent(agentId, limit = 100) {
42
+ const results = [];
43
+ for (const session of this.sessions.values()) if (session.agentId === agentId) {
44
+ results.push(session);
45
+ if (results.length >= limit) break;
46
+ }
47
+ return results.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
48
+ }
49
+ async listByTenant(tenantId, limit = 100) {
50
+ const results = [];
51
+ for (const session of this.sessions.values()) if (session.tenantId === tenantId) {
52
+ results.push(session);
53
+ if (results.length >= limit) break;
54
+ }
55
+ return results.sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
56
+ }
57
+ /**
58
+ * Clear all sessions (for testing).
59
+ */
60
+ clear() {
61
+ this.sessions.clear();
62
+ }
63
+ };
64
+ /**
65
+ * Create an in-memory session store.
66
+ */
67
+ function createInMemorySessionStore() {
68
+ return new InMemorySessionStore();
69
+ }
70
+ /**
71
+ * Generate a unique session ID.
72
+ */
73
+ function generateSessionId() {
74
+ return `sess_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`;
75
+ }
76
+
77
+ //#endregion
78
+ export { InMemorySessionStore, createInMemorySessionStore, generateSessionId };
@@ -1 +1,4 @@
1
- import{agentKey as e,defineAgent as t}from"./spec.js";import{AgentRegistry as n,createAgentRegistry as r}from"./registry.js";export{n as AgentRegistry,e as agentKey,r as createAgentRegistry,t as defineAgent};
1
+ import { agentKey, defineAgent } from "./spec.js";
2
+ import { AgentRegistry, createAgentRegistry } from "./registry.js";
3
+
4
+ export { AgentRegistry, agentKey, createAgentRegistry, defineAgent };
@@ -1 +1,116 @@
1
- import{agentKey as e}from"./spec.js";var t=class{specs=new Map;register(t){let n=e(t.meta);if(this.specs.has(n))throw Error(`Duplicate agent spec registered for ${n}`);return this.specs.set(n,t),this}unregister(e,t){return this.specs.delete(`${e}.v${t}`)}list(){return[...this.specs.values()]}listNames(){let e=new Set;for(let t of this.specs.values())e.add(t.meta.name);return[...e]}get(e,t){if(t!=null)return this.specs.get(`${e}.v${t}`);let n,r=-1/0;for(let t of this.specs.values())t.meta.name===e&&t.meta.version>r&&(n=t,r=t.meta.version);return n}require(e,t){let n=this.get(e,t);if(!n)throw Error(`Agent spec not found for ${e}${t==null?``:`.v${t}`}`);return n}has(e,t){return this.get(e,t)!==void 0}getVersions(e){let t=[];for(let n of this.specs.values())n.meta.name===e&&t.push(n);return t.sort((e,t)=>e.meta.version-t.meta.version)}clear(){this.specs.clear()}};function n(){return new t}export{t as AgentRegistry,n as createAgentRegistry};
1
+ import { agentKey } from "./spec.js";
2
+
3
+ //#region src/spec/registry.ts
4
+ /**
5
+ * Registry for managing agent specifications.
6
+ *
7
+ * Provides registration, lookup, and version management for agent specs.
8
+ */
9
+ var AgentRegistry = class {
10
+ specs = /* @__PURE__ */ new Map();
11
+ /**
12
+ * Register an agent specification.
13
+ *
14
+ * @param spec - The agent specification to register
15
+ * @returns This registry for chaining
16
+ * @throws Error if the spec is already registered
17
+ */
18
+ register(spec) {
19
+ const key = agentKey(spec.meta);
20
+ if (this.specs.has(key)) throw new Error(`Duplicate agent spec registered for ${key}`);
21
+ this.specs.set(key, spec);
22
+ return this;
23
+ }
24
+ /**
25
+ * Unregister an agent specification.
26
+ *
27
+ * @param name - Agent name
28
+ * @param version - Agent version
29
+ * @returns True if the spec was removed
30
+ */
31
+ unregister(name, version) {
32
+ return this.specs.delete(`${name}.v${version}`);
33
+ }
34
+ /**
35
+ * List all registered agent specifications.
36
+ */
37
+ list() {
38
+ return [...this.specs.values()];
39
+ }
40
+ /**
41
+ * List all unique agent names (without versions).
42
+ */
43
+ listNames() {
44
+ const names = /* @__PURE__ */ new Set();
45
+ for (const spec of this.specs.values()) names.add(spec.meta.name);
46
+ return [...names];
47
+ }
48
+ /**
49
+ * Get an agent specification by name and optional version.
50
+ *
51
+ * @param name - Agent name
52
+ * @param version - Optional version. If omitted, returns the latest version.
53
+ * @returns The agent spec or undefined if not found
54
+ */
55
+ get(name, version) {
56
+ if (version != null) return this.specs.get(`${name}.v${version}`);
57
+ let latest;
58
+ let maxVersion = -Infinity;
59
+ for (const spec of this.specs.values()) {
60
+ if (spec.meta.name !== name) continue;
61
+ if (spec.meta.version > maxVersion) {
62
+ latest = spec;
63
+ maxVersion = spec.meta.version;
64
+ }
65
+ }
66
+ return latest;
67
+ }
68
+ /**
69
+ * Get an agent specification or throw if not found.
70
+ *
71
+ * @param name - Agent name
72
+ * @param version - Optional version
73
+ * @returns The agent spec
74
+ * @throws Error if the spec is not found
75
+ */
76
+ require(name, version) {
77
+ const spec = this.get(name, version);
78
+ if (!spec) throw new Error(`Agent spec not found for ${name}${version != null ? `.v${version}` : ""}`);
79
+ return spec;
80
+ }
81
+ /**
82
+ * Check if an agent is registered.
83
+ *
84
+ * @param name - Agent name
85
+ * @param version - Optional version
86
+ */
87
+ has(name, version) {
88
+ return this.get(name, version) !== void 0;
89
+ }
90
+ /**
91
+ * Get all versions of an agent.
92
+ *
93
+ * @param name - Agent name
94
+ * @returns Array of specs sorted by version (ascending)
95
+ */
96
+ getVersions(name) {
97
+ const versions = [];
98
+ for (const spec of this.specs.values()) if (spec.meta.name === name) versions.push(spec);
99
+ return versions.sort((a, b) => a.meta.version - b.meta.version);
100
+ }
101
+ /**
102
+ * Clear all registered specs.
103
+ */
104
+ clear() {
105
+ this.specs.clear();
106
+ }
107
+ };
108
+ /**
109
+ * Create a new agent registry.
110
+ */
111
+ function createAgentRegistry() {
112
+ return new AgentRegistry();
113
+ }
114
+
115
+ //#endregion
116
+ export { AgentRegistry, createAgentRegistry };
package/dist/spec/spec.js CHANGED
@@ -1 +1,29 @@
1
- function e(e){if(!e.meta?.name)throw Error(`Agent name is required`);if(!Number.isFinite(e.meta.version))throw Error(`Agent ${e.meta.name} is missing a numeric version`);if(!e.instructions?.trim())throw Error(`Agent ${e.meta.name} requires instructions`);if(!e.tools?.length)throw Error(`Agent ${e.meta.name} must expose at least one tool`);let t=new Set;for(let n of e.tools){if(t.has(n.name))throw Error(`Agent ${e.meta.name} has duplicate tool name: ${n.name}`);t.add(n.name)}return Object.freeze(e)}function t(e){return`${e.name}.v${e.version}`}export{t as agentKey,e as defineAgent};
1
+ //#region src/spec/spec.ts
2
+ /**
3
+ * Define and validate an agent specification.
4
+ *
5
+ * @param spec - The agent specification
6
+ * @returns The frozen, validated specification
7
+ * @throws Error if the specification is invalid
8
+ */
9
+ function defineAgent(spec) {
10
+ if (!spec.meta?.name) throw new Error("Agent name is required");
11
+ if (!Number.isFinite(spec.meta.version)) throw new Error(`Agent ${spec.meta.name} is missing a numeric version`);
12
+ if (!spec.instructions?.trim()) throw new Error(`Agent ${spec.meta.name} requires instructions`);
13
+ if (!spec.tools?.length) throw new Error(`Agent ${spec.meta.name} must expose at least one tool`);
14
+ const toolNames = /* @__PURE__ */ new Set();
15
+ for (const tool of spec.tools) {
16
+ if (toolNames.has(tool.name)) throw new Error(`Agent ${spec.meta.name} has duplicate tool name: ${tool.name}`);
17
+ toolNames.add(tool.name);
18
+ }
19
+ return Object.freeze(spec);
20
+ }
21
+ /**
22
+ * Generate a unique key for an agent spec.
23
+ */
24
+ function agentKey(meta) {
25
+ return `${meta.name}.v${meta.version}`;
26
+ }
27
+
28
+ //#endregion
29
+ export { agentKey, defineAgent };
@@ -1 +1,102 @@
1
- function e(e){let t=e.match(/^(.+)\.v(\d+)$/);return t?{name:t[1],version:parseInt(t[2],10)}:{name:e,version:1}}async function t(t,n,r,i){let{name:a,version:o}=e(n);for(let e of r.toolCalls??[]){let s={operation:{name:`${a}.${e.toolName}`,version:o},durationMs:i??0,success:r.toolResults?.some(t=>t.toolCallId===e.toolCallId&&t.output!==void 0)??!1,timestamp:new Date,metadata:{agentId:n,toolName:e.toolName,finishReason:r.finishReason}};await t.collect(s)}let s={operation:{name:a,version:o},durationMs:i??0,success:r.finishReason!==`error`,timestamp:new Date,metadata:{agentId:n,finishReason:r.finishReason,tokenUsage:r.usage,toolCallCount:r.toolCalls?.length??0}};await t.collect(s)}var n=class{samples=[];async collect(e){this.samples.push(e)}getSamples(){return[...this.samples]}getSamplesForOperation(e){return this.samples.filter(t=>t.operation.name===e)}clear(){this.samples.length=0}};function r(){return new n}const i={collect:async()=>{}};export{n as InMemoryTelemetryCollector,r as createInMemoryTelemetryCollector,i as noopTelemetryCollector,t as trackAgentStep};
1
+ //#region src/telemetry/adapter.ts
2
+ /**
3
+ * Parse agent ID into name and version.
4
+ */
5
+ function parseAgentId(agentId) {
6
+ const match = agentId.match(/^(.+)\.v(\d+)$/);
7
+ if (match) return {
8
+ name: match[1],
9
+ version: parseInt(match[2], 10)
10
+ };
11
+ return {
12
+ name: agentId,
13
+ version: 1
14
+ };
15
+ }
16
+ /**
17
+ * Track an agent step for telemetry.
18
+ *
19
+ * Called from ContractSpecAgent.onStepFinish to feed metrics
20
+ * to the evolution engine.
21
+ *
22
+ * @param collector - Telemetry collector
23
+ * @param agentId - Agent identifier (e.g., "support.bot.v1")
24
+ * @param step - AI SDK step result
25
+ * @param durationMs - Optional step duration in milliseconds
26
+ */
27
+ async function trackAgentStep(collector, agentId, step, durationMs) {
28
+ const { name, version } = parseAgentId(agentId);
29
+ for (const toolCall of step.toolCalls ?? []) {
30
+ const toolSample = {
31
+ operation: {
32
+ name: `${name}.${toolCall.toolName}`,
33
+ version
34
+ },
35
+ durationMs: durationMs ?? 0,
36
+ success: step.toolResults?.some((r) => r.toolCallId === toolCall.toolCallId && r.output !== void 0) ?? false,
37
+ timestamp: /* @__PURE__ */ new Date(),
38
+ metadata: {
39
+ agentId,
40
+ toolName: toolCall.toolName,
41
+ finishReason: step.finishReason
42
+ }
43
+ };
44
+ await collector.collect(toolSample);
45
+ }
46
+ const stepSample = {
47
+ operation: {
48
+ name,
49
+ version
50
+ },
51
+ durationMs: durationMs ?? 0,
52
+ success: step.finishReason !== "error",
53
+ timestamp: /* @__PURE__ */ new Date(),
54
+ metadata: {
55
+ agentId,
56
+ finishReason: step.finishReason,
57
+ tokenUsage: step.usage,
58
+ toolCallCount: step.toolCalls?.length ?? 0
59
+ }
60
+ };
61
+ await collector.collect(stepSample);
62
+ }
63
+ /**
64
+ * In-memory telemetry collector for testing.
65
+ */
66
+ var InMemoryTelemetryCollector = class {
67
+ samples = [];
68
+ async collect(sample) {
69
+ this.samples.push(sample);
70
+ }
71
+ /**
72
+ * Get all collected samples.
73
+ */
74
+ getSamples() {
75
+ return [...this.samples];
76
+ }
77
+ /**
78
+ * Get samples for a specific operation.
79
+ */
80
+ getSamplesForOperation(operationName) {
81
+ return this.samples.filter((s) => s.operation.name === operationName);
82
+ }
83
+ /**
84
+ * Clear all samples.
85
+ */
86
+ clear() {
87
+ this.samples.length = 0;
88
+ }
89
+ };
90
+ /**
91
+ * Create an in-memory telemetry collector.
92
+ */
93
+ function createInMemoryTelemetryCollector() {
94
+ return new InMemoryTelemetryCollector();
95
+ }
96
+ /**
97
+ * No-op telemetry collector that discards all metrics.
98
+ */
99
+ const noopTelemetryCollector = { collect: async () => {} };
100
+
101
+ //#endregion
102
+ export { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep };
@@ -1 +1,3 @@
1
- import{InMemoryTelemetryCollector as e,createInMemoryTelemetryCollector as t,noopTelemetryCollector as n,trackAgentStep as r}from"./adapter.js";export{e as InMemoryTelemetryCollector,t as createInMemoryTelemetryCollector,n as noopTelemetryCollector,r as trackAgentStep};
1
+ import { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep } from "./adapter.js";
2
+
3
+ export { InMemoryTelemetryCollector, createInMemoryTelemetryCollector, noopTelemetryCollector, trackAgentStep };
@@ -1 +1,6 @@
1
- import{buildToolHandlers as e,createToolHandler as t,specToolToAISDKTool as n,specToolsToAISDKTools as r}from"./tool-adapter.js";import{createKnowledgeQueryTool as i}from"./knowledge-tool.js";import{createMcpToolsets as a,mcpServerToTools as o}from"./mcp-client.js";import{agentToMcpServer as s,createAgentMcpServer as c}from"./mcp-server.js";export{s as agentToMcpServer,e as buildToolHandlers,c as createAgentMcpServer,i as createKnowledgeQueryTool,a as createMcpToolsets,t as createToolHandler,o as mcpServerToTools,n as specToolToAISDKTool,r as specToolsToAISDKTools};
1
+ import { buildToolHandlers, createToolHandler, specToolToAISDKTool, specToolsToAISDKTools } from "./tool-adapter.js";
2
+ import { createKnowledgeQueryTool } from "./knowledge-tool.js";
3
+ import { createMcpToolsets, mcpServerToTools } from "./mcp-client.js";
4
+ import { agentToMcpServer, createAgentMcpServer } from "./mcp-server.js";
5
+
6
+ export { agentToMcpServer, buildToolHandlers, createAgentMcpServer, createKnowledgeQueryTool, createMcpToolsets, createToolHandler, mcpServerToTools, specToolToAISDKTool, specToolsToAISDKTools };
@@ -1,9 +1,53 @@
1
- import{tool as e}from"ai";import*as t from"zod";function n(n,r){let i=r.filter(e=>!e.required).map(e=>e.key).filter(e=>n.supportsSpace(e));return i.length===0?null:e({description:`Query knowledge bases for relevant information. Use this tool when you need to look up specific information that may not be in your context.
1
+ import { tool } from "ai";
2
+ import * as z$1 from "zod";
2
3
 
3
- Available knowledge spaces:
4
- ${r.filter(e=>!e.required&&n.supportsSpace(e.key)).map(e=>`- ${e.key}: ${e.instructions??`Knowledge space`}`).join(`
5
- `)}`,inputSchema:t.object({query:t.string().describe(`The question or search query to find relevant information`),spaceKey:t.enum(i).optional().describe(`Specific knowledge space to query. If omitted, searches all available spaces.`),topK:t.number().optional().default(5).describe(`Maximum number of results to return`)}),execute:async({query:e,spaceKey:t,topK:r})=>{let a=t?[t]:i,o=[];for(let t of a)try{let i=await n.retrieve(e,{spaceKey:t,topK:r??5});for(let e of i)o.push({space:t,content:e.content,score:e.score})}catch(e){console.warn(`Failed to query knowledge space ${t}:`,e)}return o.length===0?`No relevant information found in the knowledge bases.`:(o.sort((e,t)=>t.score-e.score),o.slice(0,r??5).map((e,t)=>`[Source ${t+1} - ${e.space}] (relevance: ${(e.score*100).toFixed(0)}%)\n${e.content}`).join(`
4
+ //#region src/tools/knowledge-tool.ts
5
+ /**
6
+ * Create a knowledge query tool for dynamic RAG.
7
+ *
8
+ * This tool allows the agent to query optional knowledge spaces
9
+ * at runtime. Required knowledge is injected statically via
10
+ * the knowledge injector.
11
+ *
12
+ * @param retriever - The knowledge retriever to use
13
+ * @param knowledgeRefs - Knowledge references from the agent spec
14
+ * @returns AI SDK CoreTool for knowledge queries
15
+ */
16
+ function createKnowledgeQueryTool(retriever, knowledgeRefs) {
17
+ const optionalSpaces = knowledgeRefs.filter((k) => !k.required).map((k) => k.key).filter((key) => retriever.supportsSpace(key));
18
+ if (optionalSpaces.length === 0) return null;
19
+ return tool({
20
+ description: `Query knowledge bases for relevant information. Use this tool when you need to look up specific information that may not be in your context.
6
21
 
7
- ---
22
+ Available knowledge spaces:
23
+ ${knowledgeRefs.filter((k) => !k.required && retriever.supportsSpace(k.key)).map((k) => `- ${k.key}: ${k.instructions ?? "Knowledge space"}`).join("\n")}`,
24
+ inputSchema: z$1.object({
25
+ query: z$1.string().describe("The question or search query to find relevant information"),
26
+ spaceKey: z$1.enum(optionalSpaces).optional().describe("Specific knowledge space to query. If omitted, searches all available spaces."),
27
+ topK: z$1.number().optional().default(5).describe("Maximum number of results to return")
28
+ }),
29
+ execute: async ({ query, spaceKey, topK }) => {
30
+ const spacesToSearch = spaceKey ? [spaceKey] : optionalSpaces;
31
+ const allResults = [];
32
+ for (const space of spacesToSearch) try {
33
+ const results = await retriever.retrieve(query, {
34
+ spaceKey: space,
35
+ topK: topK ?? 5
36
+ });
37
+ for (const result of results) allResults.push({
38
+ space,
39
+ content: result.content,
40
+ score: result.score
41
+ });
42
+ } catch (error) {
43
+ console.warn(`Failed to query knowledge space ${space}:`, error);
44
+ }
45
+ if (allResults.length === 0) return "No relevant information found in the knowledge bases.";
46
+ allResults.sort((a, b) => b.score - a.score);
47
+ return allResults.slice(0, topK ?? 5).map((r, i) => `[Source ${i + 1} - ${r.space}] (relevance: ${(r.score * 100).toFixed(0)}%)\n${r.content}`).join("\n\n---\n\n");
48
+ }
49
+ });
50
+ }
8
51
 
9
- `))}})}export{n as createKnowledgeQueryTool};
52
+ //#endregion
53
+ export { createKnowledgeQueryTool };
@@ -1 +1,57 @@
1
- import{experimental_createMCPClient as e}from"@ai-sdk/mcp";import{Experimental_StdioMCPTransport as t}from"@ai-sdk/mcp/mcp-stdio";async function n(n){let r=await e({transport:new t({command:n.command,args:n.args,env:n.env})});return{tools:await r.tools(),cleanup:()=>r.close()}}async function r(e){let t=await Promise.all(e.map(n)),r={};for(let e of t)Object.assign(r,e.tools);return{tools:r,cleanup:async()=>{await Promise.all(t.map(e=>e.cleanup()))}}}export{r as createMcpToolsets,n as mcpServerToTools};
1
+ import { experimental_createMCPClient } from "@ai-sdk/mcp";
2
+ import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio";
3
+
4
+ //#region src/tools/mcp-client.ts
5
+ /**
6
+ * Create AI SDK tools from an MCP server.
7
+ *
8
+ * This adapter allows ContractSpec agents to consume tools
9
+ * from external MCP servers (e.g., filesystem, database, etc.).
10
+ *
11
+ * @param config - MCP server configuration
12
+ * @returns Tools and cleanup function
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * const { tools, cleanup } = await mcpServerToTools({
17
+ * name: 'filesystem',
18
+ * command: 'npx',
19
+ * args: ['-y', '@modelcontextprotocol/server-filesystem', '/path'],
20
+ * });
21
+ *
22
+ * // Use tools in agent...
23
+ *
24
+ * await cleanup();
25
+ * ```
26
+ */
27
+ async function mcpServerToTools(config) {
28
+ const client = await experimental_createMCPClient({ transport: new Experimental_StdioMCPTransport({
29
+ command: config.command,
30
+ args: config.args,
31
+ env: config.env
32
+ }) });
33
+ return {
34
+ tools: await client.tools(),
35
+ cleanup: () => client.close()
36
+ };
37
+ }
38
+ /**
39
+ * Create multiple MCP tool sets from configurations.
40
+ *
41
+ * @param configs - Array of MCP server configurations
42
+ * @returns Combined tools and cleanup function
43
+ */
44
+ async function createMcpToolsets(configs) {
45
+ const results = await Promise.all(configs.map(mcpServerToTools));
46
+ const combinedTools = {};
47
+ for (const result of results) Object.assign(combinedTools, result.tools);
48
+ return {
49
+ tools: combinedTools,
50
+ cleanup: async () => {
51
+ await Promise.all(results.map((r) => r.cleanup()));
52
+ }
53
+ };
54
+ }
55
+
56
+ //#endregion
57
+ export { createMcpToolsets, mcpServerToTools };