@contractspec/lib.ai-agent 1.45.6 → 1.46.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/dist/_virtual/rolldown_runtime.js +8 -0
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +2 -2
- package/dist/agent/unified-agent.d.ts +131 -0
- package/dist/agent/unified-agent.d.ts.map +1 -0
- package/dist/agent/unified-agent.js +267 -0
- package/dist/agent/unified-agent.js.map +1 -0
- package/dist/exporters/claude-agent-exporter.d.ts +64 -0
- package/dist/exporters/claude-agent-exporter.d.ts.map +1 -0
- package/dist/exporters/claude-agent-exporter.js +210 -0
- package/dist/exporters/claude-agent-exporter.js.map +1 -0
- package/dist/exporters/index.d.ts +4 -0
- package/dist/exporters/index.js +4 -0
- package/dist/exporters/opencode-exporter.d.ts +64 -0
- package/dist/exporters/opencode-exporter.d.ts.map +1 -0
- package/dist/exporters/opencode-exporter.js +200 -0
- package/dist/exporters/opencode-exporter.js.map +1 -0
- package/dist/exporters/types.d.ts +239 -0
- package/dist/exporters/types.d.ts.map +1 -0
- package/dist/exporters/types.js +0 -0
- package/dist/index.d.ts +16 -3
- package/dist/index.js +11 -2
- package/dist/interop/index.d.ts +4 -0
- package/dist/interop/index.js +4 -0
- package/dist/interop/spec-consumer.d.ts +81 -0
- package/dist/interop/spec-consumer.d.ts.map +1 -0
- package/dist/interop/spec-consumer.js +287 -0
- package/dist/interop/spec-consumer.js.map +1 -0
- package/dist/interop/tool-consumer.d.ts +68 -0
- package/dist/interop/tool-consumer.d.ts.map +1 -0
- package/dist/interop/tool-consumer.js +220 -0
- package/dist/interop/tool-consumer.js.map +1 -0
- package/dist/interop/types.d.ts +262 -0
- package/dist/interop/types.d.ts.map +1 -0
- package/dist/interop/types.js +0 -0
- package/dist/providers/claude-agent-sdk/adapter.d.ts +58 -0
- package/dist/providers/claude-agent-sdk/adapter.d.ts.map +1 -0
- package/dist/providers/claude-agent-sdk/adapter.js +306 -0
- package/dist/providers/claude-agent-sdk/adapter.js.map +1 -0
- package/dist/providers/claude-agent-sdk/index.d.ts +4 -0
- package/dist/providers/claude-agent-sdk/index.js +5 -0
- package/dist/providers/claude-agent-sdk/session-bridge.d.ts +101 -0
- package/dist/providers/claude-agent-sdk/session-bridge.d.ts.map +1 -0
- package/dist/providers/claude-agent-sdk/session-bridge.js +158 -0
- package/dist/providers/claude-agent-sdk/session-bridge.js.map +1 -0
- package/dist/providers/claude-agent-sdk/tool-bridge.d.ts +110 -0
- package/dist/providers/claude-agent-sdk/tool-bridge.d.ts.map +1 -0
- package/dist/providers/claude-agent-sdk/tool-bridge.js +122 -0
- package/dist/providers/claude-agent-sdk/tool-bridge.js.map +1 -0
- package/dist/providers/index.d.ts +7 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/opencode-sdk/adapter.d.ts +54 -0
- package/dist/providers/opencode-sdk/adapter.d.ts.map +1 -0
- package/dist/providers/opencode-sdk/adapter.js +276 -0
- package/dist/providers/opencode-sdk/adapter.js.map +1 -0
- package/dist/providers/opencode-sdk/agent-bridge.d.ts +94 -0
- package/dist/providers/opencode-sdk/agent-bridge.d.ts.map +1 -0
- package/dist/providers/opencode-sdk/agent-bridge.js +165 -0
- package/dist/providers/opencode-sdk/agent-bridge.js.map +1 -0
- package/dist/providers/opencode-sdk/index.d.ts +4 -0
- package/dist/providers/opencode-sdk/index.js +5 -0
- package/dist/providers/opencode-sdk/tool-bridge.d.ts +81 -0
- package/dist/providers/opencode-sdk/tool-bridge.d.ts.map +1 -0
- package/dist/providers/opencode-sdk/tool-bridge.js +127 -0
- package/dist/providers/opencode-sdk/tool-bridge.js.map +1 -0
- package/dist/providers/registry.d.ts +22 -0
- package/dist/providers/registry.d.ts.map +1 -0
- package/dist/providers/registry.js +52 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/types.d.ts +243 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +44 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/tools/index.d.ts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +37 -5
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { agentKey } from "../spec/spec.js";
|
|
2
|
+
|
|
3
|
+
//#region src/interop/spec-consumer.ts
|
|
4
|
+
/**
|
|
5
|
+
* ContractSpec consumer for external agents.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const consumer = createSpecConsumer({
|
|
10
|
+
* specs: [myAgentSpec, anotherSpec],
|
|
11
|
+
* includeMetadata: true,
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* // Get markdown representation
|
|
15
|
+
* const markdown = consumer.getSpecMarkdown('my-agent.v1.0.0');
|
|
16
|
+
*
|
|
17
|
+
* // Get prompt for LLM
|
|
18
|
+
* const prompt = consumer.getSpecPrompt('my-agent.v1.0.0', {
|
|
19
|
+
* includeTools: true,
|
|
20
|
+
* });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
var ContractSpecConsumer = class {
|
|
24
|
+
specs;
|
|
25
|
+
includeMetadata;
|
|
26
|
+
baseUrl;
|
|
27
|
+
constructor(config) {
|
|
28
|
+
this.specs = /* @__PURE__ */ new Map();
|
|
29
|
+
this.includeMetadata = config.includeMetadata ?? true;
|
|
30
|
+
this.baseUrl = config.baseUrl;
|
|
31
|
+
for (const spec of config.specs) {
|
|
32
|
+
const key = agentKey(spec.meta);
|
|
33
|
+
this.specs.set(key, spec);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get a spec as markdown.
|
|
38
|
+
*/
|
|
39
|
+
getSpecMarkdown(specKey, options) {
|
|
40
|
+
const spec = this.specs.get(specKey);
|
|
41
|
+
if (!spec) throw new Error(`Spec not found: ${specKey}`);
|
|
42
|
+
const sections = [];
|
|
43
|
+
const opts = {
|
|
44
|
+
includeToc: options?.includeToc ?? true,
|
|
45
|
+
includeTools: options?.includeTools ?? true,
|
|
46
|
+
...options
|
|
47
|
+
};
|
|
48
|
+
if (opts.customHeader) {
|
|
49
|
+
sections.push(opts.customHeader);
|
|
50
|
+
sections.push("");
|
|
51
|
+
}
|
|
52
|
+
const specName = spec.meta.key;
|
|
53
|
+
sections.push(`# ${specName}`);
|
|
54
|
+
sections.push("");
|
|
55
|
+
if (spec.description) {
|
|
56
|
+
sections.push(spec.description);
|
|
57
|
+
sections.push("");
|
|
58
|
+
}
|
|
59
|
+
if (opts.includeToc) {
|
|
60
|
+
sections.push("## Table of Contents");
|
|
61
|
+
sections.push("");
|
|
62
|
+
sections.push("- [Overview](#overview)");
|
|
63
|
+
sections.push("- [Instructions](#instructions)");
|
|
64
|
+
if (opts.includeTools && spec.tools && spec.tools.length > 0) sections.push("- [Tools](#tools)");
|
|
65
|
+
if (spec.knowledge && spec.knowledge.length > 0) sections.push("- [Knowledge](#knowledge)");
|
|
66
|
+
sections.push("");
|
|
67
|
+
}
|
|
68
|
+
sections.push("## Overview");
|
|
69
|
+
sections.push("");
|
|
70
|
+
if (this.includeMetadata) {
|
|
71
|
+
sections.push(`- **Key**: \`${spec.meta.key}\``);
|
|
72
|
+
sections.push(`- **Version**: ${spec.meta.version}`);
|
|
73
|
+
if (spec.meta.stability) sections.push(`- **Stability**: ${spec.meta.stability}`);
|
|
74
|
+
if (spec.meta.owners && spec.meta.owners.length > 0) sections.push(`- **Owners**: ${spec.meta.owners.join(", ")}`);
|
|
75
|
+
if (spec.tags && spec.tags.length > 0) sections.push(`- **Tags**: ${spec.tags.join(", ")}`);
|
|
76
|
+
}
|
|
77
|
+
sections.push("");
|
|
78
|
+
sections.push("## Instructions");
|
|
79
|
+
sections.push("");
|
|
80
|
+
sections.push(spec.instructions);
|
|
81
|
+
sections.push("");
|
|
82
|
+
if (opts.includeTools && spec.tools && spec.tools.length > 0) {
|
|
83
|
+
sections.push("## Tools");
|
|
84
|
+
sections.push("");
|
|
85
|
+
for (const tool of spec.tools) {
|
|
86
|
+
sections.push(`### ${tool.name}`);
|
|
87
|
+
sections.push("");
|
|
88
|
+
if (tool.description) {
|
|
89
|
+
sections.push(tool.description);
|
|
90
|
+
sections.push("");
|
|
91
|
+
}
|
|
92
|
+
if (tool.schema) {
|
|
93
|
+
sections.push("**Schema:**");
|
|
94
|
+
sections.push("");
|
|
95
|
+
sections.push("```json");
|
|
96
|
+
sections.push(JSON.stringify(tool.schema, null, 2));
|
|
97
|
+
sections.push("```");
|
|
98
|
+
sections.push("");
|
|
99
|
+
}
|
|
100
|
+
if (tool.automationSafe !== void 0) {
|
|
101
|
+
sections.push(`**Automation Safe**: ${tool.automationSafe ? "Yes" : "No"}`);
|
|
102
|
+
sections.push("");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (spec.knowledge && spec.knowledge.length > 0) {
|
|
107
|
+
sections.push("## Knowledge");
|
|
108
|
+
sections.push("");
|
|
109
|
+
for (const k of spec.knowledge) {
|
|
110
|
+
sections.push(`- **${k.key}**${k.required ? " (required)" : ""}`);
|
|
111
|
+
if (k.instructions) sections.push(` - ${k.instructions}`);
|
|
112
|
+
}
|
|
113
|
+
sections.push("");
|
|
114
|
+
}
|
|
115
|
+
if (spec.policy) {
|
|
116
|
+
sections.push("## Policy");
|
|
117
|
+
sections.push("");
|
|
118
|
+
if (spec.policy.confidence) sections.push(`- **Minimum Confidence**: ${spec.policy.confidence.min ?? .7}`);
|
|
119
|
+
if (spec.policy.escalation) {
|
|
120
|
+
const esc = spec.policy.escalation;
|
|
121
|
+
if (esc.confidenceThreshold) sections.push(`- **Escalation Threshold**: ${esc.confidenceThreshold}`);
|
|
122
|
+
if (esc.onToolFailure) sections.push("- **Escalate on Tool Failure**: Yes");
|
|
123
|
+
if (esc.onTimeout) sections.push("- **Escalate on Timeout**: Yes");
|
|
124
|
+
}
|
|
125
|
+
sections.push("");
|
|
126
|
+
}
|
|
127
|
+
return sections.join("\n");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get a spec as an LLM prompt.
|
|
131
|
+
*/
|
|
132
|
+
getSpecPrompt(specKey, options) {
|
|
133
|
+
const spec = this.specs.get(specKey);
|
|
134
|
+
if (!spec) throw new Error(`Spec not found: ${specKey}`);
|
|
135
|
+
const sections = [];
|
|
136
|
+
const opts = {
|
|
137
|
+
includeTools: options?.includeTools ?? true,
|
|
138
|
+
format: options?.format ?? "structured",
|
|
139
|
+
...options
|
|
140
|
+
};
|
|
141
|
+
sections.push("# Agent Identity");
|
|
142
|
+
sections.push("");
|
|
143
|
+
sections.push(`You are ${spec.meta.key} (v${spec.meta.version}).`);
|
|
144
|
+
sections.push("");
|
|
145
|
+
if (spec.description) {
|
|
146
|
+
sections.push("## Description");
|
|
147
|
+
sections.push("");
|
|
148
|
+
sections.push(spec.description);
|
|
149
|
+
sections.push("");
|
|
150
|
+
}
|
|
151
|
+
sections.push("## Instructions");
|
|
152
|
+
sections.push("");
|
|
153
|
+
sections.push(spec.instructions);
|
|
154
|
+
sections.push("");
|
|
155
|
+
if (opts.includeTools && spec.tools && spec.tools.length > 0) {
|
|
156
|
+
sections.push("## Available Tools");
|
|
157
|
+
sections.push("");
|
|
158
|
+
sections.push("You have access to the following tools:");
|
|
159
|
+
sections.push("");
|
|
160
|
+
for (const tool of spec.tools) {
|
|
161
|
+
sections.push(`### ${tool.name}`);
|
|
162
|
+
sections.push("");
|
|
163
|
+
if (tool.description) {
|
|
164
|
+
sections.push(tool.description);
|
|
165
|
+
sections.push("");
|
|
166
|
+
}
|
|
167
|
+
if (tool.schema && opts.format === "structured") {
|
|
168
|
+
sections.push("Parameters:");
|
|
169
|
+
sections.push("```json");
|
|
170
|
+
sections.push(JSON.stringify(tool.schema, null, 2));
|
|
171
|
+
sections.push("```");
|
|
172
|
+
sections.push("");
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (spec.knowledge && spec.knowledge.length > 0) {
|
|
177
|
+
const requiredKnowledge = spec.knowledge.filter((k) => k.required);
|
|
178
|
+
if (requiredKnowledge.length > 0) {
|
|
179
|
+
sections.push("## Knowledge Context");
|
|
180
|
+
sections.push("");
|
|
181
|
+
for (const k of requiredKnowledge) if (k.instructions) {
|
|
182
|
+
sections.push(k.instructions);
|
|
183
|
+
sections.push("");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (options?.customContext) {
|
|
188
|
+
sections.push("## Additional Context");
|
|
189
|
+
sections.push("");
|
|
190
|
+
sections.push(options.customContext);
|
|
191
|
+
sections.push("");
|
|
192
|
+
}
|
|
193
|
+
return sections.join("\n");
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* List available specs.
|
|
197
|
+
*/
|
|
198
|
+
listSpecs(options) {
|
|
199
|
+
const results = [];
|
|
200
|
+
for (const [key, spec] of this.specs) {
|
|
201
|
+
if (options?.stability && spec.meta.stability !== options.stability) continue;
|
|
202
|
+
if (options?.tags && options.tags.length > 0) {
|
|
203
|
+
const specTags = spec.tags ?? [];
|
|
204
|
+
if (!options.tags.some((tag) => specTags.includes(tag))) continue;
|
|
205
|
+
}
|
|
206
|
+
results.push({
|
|
207
|
+
key,
|
|
208
|
+
name: spec.meta.key,
|
|
209
|
+
version: spec.meta.version,
|
|
210
|
+
description: spec.description,
|
|
211
|
+
stability: spec.meta.stability,
|
|
212
|
+
tags: spec.tags,
|
|
213
|
+
toolCount: spec.tools?.length ?? 0
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return results;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Query a spec by key.
|
|
220
|
+
*/
|
|
221
|
+
querySpec(specKey) {
|
|
222
|
+
const spec = this.specs.get(specKey);
|
|
223
|
+
if (!spec) return;
|
|
224
|
+
return {
|
|
225
|
+
key: specKey,
|
|
226
|
+
spec,
|
|
227
|
+
markdown: this.getSpecMarkdown(specKey),
|
|
228
|
+
prompt: this.getSpecPrompt(specKey)
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Check if a spec exists.
|
|
233
|
+
*/
|
|
234
|
+
hasSpec(specKey) {
|
|
235
|
+
return this.specs.has(specKey);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get a spec by key.
|
|
239
|
+
*/
|
|
240
|
+
getSpec(specKey) {
|
|
241
|
+
return this.specs.get(specKey);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get all specs.
|
|
245
|
+
*/
|
|
246
|
+
getAllSpecs() {
|
|
247
|
+
return Array.from(this.specs.values());
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get spec count.
|
|
251
|
+
*/
|
|
252
|
+
getSpecCount() {
|
|
253
|
+
return this.specs.size;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Add a spec to the consumer.
|
|
257
|
+
*/
|
|
258
|
+
addSpec(spec) {
|
|
259
|
+
const key = agentKey(spec.meta);
|
|
260
|
+
this.specs.set(key, spec);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Remove a spec from the consumer.
|
|
264
|
+
*/
|
|
265
|
+
removeSpec(specKey) {
|
|
266
|
+
return this.specs.delete(specKey);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
* Create a new spec consumer.
|
|
271
|
+
*/
|
|
272
|
+
function createSpecConsumer(config) {
|
|
273
|
+
return new ContractSpecConsumer(config);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Create a spec consumer from a single spec.
|
|
277
|
+
*/
|
|
278
|
+
function createSingleSpecConsumer(spec, options) {
|
|
279
|
+
return new ContractSpecConsumer({
|
|
280
|
+
specs: [spec],
|
|
281
|
+
...options
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
//#endregion
|
|
286
|
+
export { ContractSpecConsumer, createSingleSpecConsumer, createSpecConsumer };
|
|
287
|
+
//# sourceMappingURL=spec-consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-consumer.js","names":["sections: string[]","results: SpecListResult[]"],"sources":["../../src/interop/spec-consumer.ts"],"sourcesContent":["/**\n * Spec consumer for external agents.\n *\n * Enables external agent SDKs to consume ContractSpec specs:\n * - Read spec definitions as markdown/prompts\n * - List available specs\n * - Query spec metadata\n */\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n SpecConsumer,\n SpecConsumerConfig,\n SpecMarkdownOptions,\n SpecPromptOptions,\n SpecQueryResult,\n SpecListOptions,\n SpecListResult,\n} from './types';\n\n// =============================================================================\n// Spec Consumer Implementation\n// =============================================================================\n\n/**\n * ContractSpec consumer for external agents.\n *\n * @example\n * ```typescript\n * const consumer = createSpecConsumer({\n * specs: [myAgentSpec, anotherSpec],\n * includeMetadata: true,\n * });\n *\n * // Get markdown representation\n * const markdown = consumer.getSpecMarkdown('my-agent.v1.0.0');\n *\n * // Get prompt for LLM\n * const prompt = consumer.getSpecPrompt('my-agent.v1.0.0', {\n * includeTools: true,\n * });\n * ```\n */\nexport class ContractSpecConsumer implements SpecConsumer {\n private readonly specs: Map<string, AgentSpec>;\n private readonly includeMetadata: boolean;\n private readonly baseUrl?: string;\n\n constructor(config: SpecConsumerConfig) {\n this.specs = new Map();\n this.includeMetadata = config.includeMetadata ?? true;\n this.baseUrl = config.baseUrl;\n\n // Index specs by key\n for (const spec of config.specs) {\n const key = agentKey(spec.meta);\n this.specs.set(key, spec);\n }\n }\n\n /**\n * Get a spec as markdown.\n */\n getSpecMarkdown(specKey: string, options?: SpecMarkdownOptions): string {\n const spec = this.specs.get(specKey);\n if (!spec) {\n throw new Error(`Spec not found: ${specKey}`);\n }\n\n const sections: string[] = [];\n const opts = {\n includeToc: options?.includeToc ?? true,\n includeTools: options?.includeTools ?? true,\n ...options,\n };\n\n // Custom header\n if (opts.customHeader) {\n sections.push(opts.customHeader);\n sections.push('');\n }\n\n // Header - use key as name\n const specName = spec.meta.key;\n sections.push(`# ${specName}`);\n sections.push('');\n\n if (spec.description) {\n sections.push(spec.description);\n sections.push('');\n }\n\n // Table of contents\n if (opts.includeToc) {\n sections.push('## Table of Contents');\n sections.push('');\n sections.push('- [Overview](#overview)');\n sections.push('- [Instructions](#instructions)');\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('- [Tools](#tools)');\n }\n if (spec.knowledge && spec.knowledge.length > 0) {\n sections.push('- [Knowledge](#knowledge)');\n }\n sections.push('');\n }\n\n // Overview\n sections.push('## Overview');\n sections.push('');\n if (this.includeMetadata) {\n sections.push(`- **Key**: \\`${spec.meta.key}\\``);\n sections.push(`- **Version**: ${spec.meta.version}`);\n if (spec.meta.stability) {\n sections.push(`- **Stability**: ${spec.meta.stability}`);\n }\n if (spec.meta.owners && spec.meta.owners.length > 0) {\n sections.push(`- **Owners**: ${spec.meta.owners.join(', ')}`);\n }\n if (spec.tags && spec.tags.length > 0) {\n sections.push(`- **Tags**: ${spec.tags.join(', ')}`);\n }\n }\n sections.push('');\n\n // Instructions\n sections.push('## Instructions');\n sections.push('');\n sections.push(spec.instructions);\n sections.push('');\n\n // Tools\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('## Tools');\n sections.push('');\n for (const tool of spec.tools) {\n sections.push(`### ${tool.name}`);\n sections.push('');\n if (tool.description) {\n sections.push(tool.description);\n sections.push('');\n }\n if (tool.schema) {\n sections.push('**Schema:**');\n sections.push('');\n sections.push('```json');\n sections.push(JSON.stringify(tool.schema, null, 2));\n sections.push('```');\n sections.push('');\n }\n if (tool.automationSafe !== undefined) {\n sections.push(\n `**Automation Safe**: ${tool.automationSafe ? 'Yes' : 'No'}`\n );\n sections.push('');\n }\n }\n }\n\n // Knowledge\n if (spec.knowledge && spec.knowledge.length > 0) {\n sections.push('## Knowledge');\n sections.push('');\n for (const k of spec.knowledge) {\n sections.push(`- **${k.key}**${k.required ? ' (required)' : ''}`);\n if (k.instructions) {\n sections.push(` - ${k.instructions}`);\n }\n }\n sections.push('');\n }\n\n // Policy\n if (spec.policy) {\n sections.push('## Policy');\n sections.push('');\n if (spec.policy.confidence) {\n sections.push(\n `- **Minimum Confidence**: ${spec.policy.confidence.min ?? 0.7}`\n );\n }\n if (spec.policy.escalation) {\n const esc = spec.policy.escalation;\n if (esc.confidenceThreshold) {\n sections.push(\n `- **Escalation Threshold**: ${esc.confidenceThreshold}`\n );\n }\n if (esc.onToolFailure) {\n sections.push('- **Escalate on Tool Failure**: Yes');\n }\n if (esc.onTimeout) {\n sections.push('- **Escalate on Timeout**: Yes');\n }\n }\n sections.push('');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * Get a spec as an LLM prompt.\n */\n getSpecPrompt(specKey: string, options?: SpecPromptOptions): string {\n const spec = this.specs.get(specKey);\n if (!spec) {\n throw new Error(`Spec not found: ${specKey}`);\n }\n\n const sections: string[] = [];\n const opts = {\n includeTools: options?.includeTools ?? true,\n format: options?.format ?? 'structured',\n ...options,\n };\n\n // Identity section\n sections.push('# Agent Identity');\n sections.push('');\n sections.push(`You are ${spec.meta.key} (v${spec.meta.version}).`);\n sections.push('');\n\n // Description\n if (spec.description) {\n sections.push('## Description');\n sections.push('');\n sections.push(spec.description);\n sections.push('');\n }\n\n // Instructions\n sections.push('## Instructions');\n sections.push('');\n sections.push(spec.instructions);\n sections.push('');\n\n // Tools\n if (opts.includeTools && spec.tools && spec.tools.length > 0) {\n sections.push('## Available Tools');\n sections.push('');\n sections.push('You have access to the following tools:');\n sections.push('');\n\n for (const tool of spec.tools) {\n sections.push(`### ${tool.name}`);\n sections.push('');\n if (tool.description) {\n sections.push(tool.description);\n sections.push('');\n }\n if (tool.schema && opts.format === 'structured') {\n sections.push('Parameters:');\n sections.push('```json');\n sections.push(JSON.stringify(tool.schema, null, 2));\n sections.push('```');\n sections.push('');\n }\n }\n }\n\n // Knowledge instructions\n if (spec.knowledge && spec.knowledge.length > 0) {\n const requiredKnowledge = spec.knowledge.filter((k) => k.required);\n if (requiredKnowledge.length > 0) {\n sections.push('## Knowledge Context');\n sections.push('');\n for (const k of requiredKnowledge) {\n if (k.instructions) {\n sections.push(k.instructions);\n sections.push('');\n }\n }\n }\n }\n\n // Custom context\n if (options?.customContext) {\n sections.push('## Additional Context');\n sections.push('');\n sections.push(options.customContext);\n sections.push('');\n }\n\n return sections.join('\\n');\n }\n\n /**\n * List available specs.\n */\n listSpecs(options?: SpecListOptions): SpecListResult[] {\n const results: SpecListResult[] = [];\n\n for (const [key, spec] of this.specs) {\n // Apply filters\n if (options?.stability && spec.meta.stability !== options.stability) {\n continue;\n }\n if (options?.tags && options.tags.length > 0) {\n const specTags = spec.tags ?? [];\n const hasMatchingTag = options.tags.some((tag) =>\n specTags.includes(tag)\n );\n if (!hasMatchingTag) {\n continue;\n }\n }\n\n results.push({\n key,\n name: spec.meta.key,\n version: spec.meta.version,\n description: spec.description,\n stability: spec.meta.stability,\n tags: spec.tags,\n toolCount: spec.tools?.length ?? 0,\n });\n }\n\n return results;\n }\n\n /**\n * Query a spec by key.\n */\n querySpec(specKey: string): SpecQueryResult | undefined {\n const spec = this.specs.get(specKey);\n if (!spec) {\n return undefined;\n }\n\n return {\n key: specKey,\n spec,\n markdown: this.getSpecMarkdown(specKey),\n prompt: this.getSpecPrompt(specKey),\n };\n }\n\n /**\n * Check if a spec exists.\n */\n hasSpec(specKey: string): boolean {\n return this.specs.has(specKey);\n }\n\n /**\n * Get a spec by key.\n */\n getSpec(specKey: string): AgentSpec | undefined {\n return this.specs.get(specKey);\n }\n\n /**\n * Get all specs.\n */\n getAllSpecs(): AgentSpec[] {\n return Array.from(this.specs.values());\n }\n\n /**\n * Get spec count.\n */\n getSpecCount(): number {\n return this.specs.size;\n }\n\n /**\n * Add a spec to the consumer.\n */\n addSpec(spec: AgentSpec): void {\n const key = agentKey(spec.meta);\n this.specs.set(key, spec);\n }\n\n /**\n * Remove a spec from the consumer.\n */\n removeSpec(specKey: string): boolean {\n return this.specs.delete(specKey);\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a new spec consumer.\n */\nexport function createSpecConsumer(config: SpecConsumerConfig): SpecConsumer {\n return new ContractSpecConsumer(config);\n}\n\n/**\n * Create a spec consumer from a single spec.\n */\nexport function createSingleSpecConsumer(\n spec: AgentSpec,\n options?: Omit<SpecConsumerConfig, 'specs'>\n): SpecConsumer {\n return new ContractSpecConsumer({\n specs: [spec],\n ...options,\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { AgentToolConfig } from "../spec/spec.js";
|
|
2
|
+
import { ToolExecutionContext, ToolHandler } from "../types.js";
|
|
3
|
+
import { ToolConsumer, ToolConsumerConfig, ToolExportFormat, ToolServer, ToolServerConfig } from "./types.js";
|
|
4
|
+
|
|
5
|
+
//#region src/interop/tool-consumer.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* ContractSpec tool consumer for external agents.
|
|
9
|
+
*/
|
|
10
|
+
declare class ContractSpecToolConsumer implements ToolConsumer {
|
|
11
|
+
private readonly tools;
|
|
12
|
+
constructor(config: ToolConsumerConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Create an MCP server exposing the tools.
|
|
15
|
+
*/
|
|
16
|
+
createToolServer(config?: Partial<ToolServerConfig>): ToolServer;
|
|
17
|
+
/**
|
|
18
|
+
* Export tools for a specific SDK format.
|
|
19
|
+
*/
|
|
20
|
+
exportToolsForSDK(format: ToolExportFormat): unknown[];
|
|
21
|
+
/**
|
|
22
|
+
* Create a bridged handler for a specific SDK.
|
|
23
|
+
*/
|
|
24
|
+
createBridgedHandler(toolName: string, _format: ToolExportFormat): ((args: Record<string, unknown>) => Promise<unknown>) | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* Get all tools.
|
|
27
|
+
*/
|
|
28
|
+
getTools(): AgentToolConfig[];
|
|
29
|
+
/**
|
|
30
|
+
* Get a specific tool.
|
|
31
|
+
*/
|
|
32
|
+
getTool(name: string): AgentToolConfig | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Check if a tool exists.
|
|
35
|
+
*/
|
|
36
|
+
hasTool(name: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Execute a tool.
|
|
39
|
+
*/
|
|
40
|
+
executeTool(name: string, args: Record<string, unknown>, context?: ToolExecutionContext): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Add a tool.
|
|
43
|
+
*/
|
|
44
|
+
addTool(config: AgentToolConfig, handler?: ToolHandler): void;
|
|
45
|
+
/**
|
|
46
|
+
* Remove a tool.
|
|
47
|
+
*/
|
|
48
|
+
removeTool(name: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Get tool count.
|
|
51
|
+
*/
|
|
52
|
+
getToolCount(): number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Create a new tool consumer.
|
|
56
|
+
*/
|
|
57
|
+
declare function createToolConsumer(config: ToolConsumerConfig): ToolConsumer;
|
|
58
|
+
/**
|
|
59
|
+
* Create an MCP tool server from tools.
|
|
60
|
+
*/
|
|
61
|
+
declare function createToolServer(config: ToolServerConfig): ToolServer;
|
|
62
|
+
/**
|
|
63
|
+
* Export tools to a specific SDK format.
|
|
64
|
+
*/
|
|
65
|
+
declare function exportToolsForExternalSDK(tools: AgentToolConfig[], format: ToolExportFormat): unknown[];
|
|
66
|
+
//#endregion
|
|
67
|
+
export { ContractSpecToolConsumer, createToolConsumer, createToolServer, exportToolsForExternalSDK };
|
|
68
|
+
//# sourceMappingURL=tool-consumer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-consumer.d.ts","names":[],"sources":["../../src/interop/tool-consumer.ts"],"sourcesContent":[],"mappings":";;;;;;;;;AAoQc,cA1GD,wBAAA,YAAoC,YA0GnC,CAAA;EAOW,iBAAA,KAAA;EAgBf,WAAA,CAAA,MAAA,EA3HY,kBA2HZ;EACI;;;EA0B+B,gBAAA,CAAA,MAAA,CAAA,EA1IjB,OA0IiB,CA1IT,gBA0IS,CAAA,CAAA,EA1IW,UA0IX;EA5JI;;AAsLjD;EAOgB,iBAAA,CAAA,MAAgB,EAjKJ,gBAiKa,CAAA,EAAA,OAAmB,EAAA;EAO5C;;;kDAlHH,2BACA,4BAA4B;;;;cAuB3B;;;;yBAOW;;;;;;;;kCAgBf,mCACI,uBACT;;;;kBAyBa,2BAA2B;;;;;;;;;;;;;iBA0B7B,kBAAA,SAA2B,qBAAqB;;;;iBAOhD,gBAAA,SAAyB,mBAAmB;;;;iBAO5C,yBAAA,QACP,2BACC"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { specToolToClaudeAgentTool } from "../providers/claude-agent-sdk/tool-bridge.js";
|
|
2
|
+
import { specToolToOpenCodeTool } from "../providers/opencode-sdk/tool-bridge.js";
|
|
3
|
+
|
|
4
|
+
//#region src/interop/tool-consumer.ts
|
|
5
|
+
/**
|
|
6
|
+
* Simple MCP-compatible tool server.
|
|
7
|
+
*/
|
|
8
|
+
var MCPToolServer = class {
|
|
9
|
+
tools;
|
|
10
|
+
name;
|
|
11
|
+
version;
|
|
12
|
+
running = false;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
15
|
+
this.name = config.name ?? "contractspec-tools";
|
|
16
|
+
this.version = config.version ?? "1.0.0";
|
|
17
|
+
for (const tool of config.tools) this.tools.set(tool.config.name, tool);
|
|
18
|
+
}
|
|
19
|
+
async start() {
|
|
20
|
+
if (this.running) return;
|
|
21
|
+
this.running = true;
|
|
22
|
+
console.log(`[MCPToolServer] Started ${this.name}@${this.version} with ${this.tools.size} tools`);
|
|
23
|
+
}
|
|
24
|
+
async stop() {
|
|
25
|
+
if (!this.running) return;
|
|
26
|
+
this.running = false;
|
|
27
|
+
console.log(`[MCPToolServer] Stopped ${this.name}`);
|
|
28
|
+
}
|
|
29
|
+
isRunning() {
|
|
30
|
+
return this.running;
|
|
31
|
+
}
|
|
32
|
+
getTools() {
|
|
33
|
+
return Array.from(this.tools.values()).map((t) => t.config);
|
|
34
|
+
}
|
|
35
|
+
async executeTool(toolName, args, context) {
|
|
36
|
+
const tool = this.tools.get(toolName);
|
|
37
|
+
if (!tool) throw new Error(`Tool not found: ${toolName}`);
|
|
38
|
+
if (!tool.handler) throw new Error(`No handler registered for tool: ${toolName}`);
|
|
39
|
+
const fullContext = {
|
|
40
|
+
agentId: context?.agentId ?? "mcp-server",
|
|
41
|
+
sessionId: context?.sessionId ?? "mcp-session",
|
|
42
|
+
tenantId: context?.tenantId,
|
|
43
|
+
actorId: context?.actorId,
|
|
44
|
+
metadata: context?.metadata,
|
|
45
|
+
signal: context?.signal
|
|
46
|
+
};
|
|
47
|
+
return await tool.handler(args, fullContext);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get MCP-compatible tool definitions.
|
|
51
|
+
*/
|
|
52
|
+
getMCPToolDefinitions() {
|
|
53
|
+
const definitions = [];
|
|
54
|
+
for (const [name, tool] of this.tools) definitions.push({
|
|
55
|
+
name,
|
|
56
|
+
description: tool.config.description ?? "",
|
|
57
|
+
inputSchema: tool.config.schema ?? {
|
|
58
|
+
type: "object",
|
|
59
|
+
properties: {}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
return definitions;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get server info for MCP.
|
|
66
|
+
*/
|
|
67
|
+
getServerInfo() {
|
|
68
|
+
return {
|
|
69
|
+
name: this.name,
|
|
70
|
+
version: this.version,
|
|
71
|
+
tools: this.tools.size,
|
|
72
|
+
running: this.running
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* ContractSpec tool consumer for external agents.
|
|
78
|
+
*/
|
|
79
|
+
var ContractSpecToolConsumer = class {
|
|
80
|
+
tools;
|
|
81
|
+
constructor(config) {
|
|
82
|
+
this.tools = /* @__PURE__ */ new Map();
|
|
83
|
+
for (const tool of config.tools) this.tools.set(tool.config.name, tool);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Create an MCP server exposing the tools.
|
|
87
|
+
*/
|
|
88
|
+
createToolServer(config) {
|
|
89
|
+
return new MCPToolServer({
|
|
90
|
+
tools: Array.from(this.tools.values()),
|
|
91
|
+
...config
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Export tools for a specific SDK format.
|
|
96
|
+
*/
|
|
97
|
+
exportToolsForSDK(format) {
|
|
98
|
+
const tools = Array.from(this.tools.values());
|
|
99
|
+
const defaultContext = {
|
|
100
|
+
agentId: "export",
|
|
101
|
+
sessionId: "export"
|
|
102
|
+
};
|
|
103
|
+
switch (format) {
|
|
104
|
+
case "claude-agent": return tools.filter((tool) => !!tool.handler).map((tool) => specToolToClaudeAgentTool(tool.config, tool.handler, defaultContext));
|
|
105
|
+
case "opencode": return tools.map((tool) => specToolToOpenCodeTool(tool.config));
|
|
106
|
+
case "mcp": return tools.map((tool) => ({
|
|
107
|
+
name: tool.config.name,
|
|
108
|
+
description: tool.config.description ?? "",
|
|
109
|
+
inputSchema: tool.config.schema ?? {
|
|
110
|
+
type: "object",
|
|
111
|
+
properties: {}
|
|
112
|
+
}
|
|
113
|
+
}));
|
|
114
|
+
case "openai": return tools.map((tool) => ({
|
|
115
|
+
type: "function",
|
|
116
|
+
function: {
|
|
117
|
+
name: tool.config.name,
|
|
118
|
+
description: tool.config.description ?? "",
|
|
119
|
+
parameters: tool.config.schema ?? {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}));
|
|
125
|
+
default: throw new Error(`Unknown export format: ${format}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Create a bridged handler for a specific SDK.
|
|
130
|
+
*/
|
|
131
|
+
createBridgedHandler(toolName, _format) {
|
|
132
|
+
const tool = this.tools.get(toolName);
|
|
133
|
+
if (!tool || !tool.handler) return;
|
|
134
|
+
const handler = tool.handler;
|
|
135
|
+
return async (args) => {
|
|
136
|
+
return handler(args, {
|
|
137
|
+
agentId: "bridge",
|
|
138
|
+
sessionId: "bridge"
|
|
139
|
+
});
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get all tools.
|
|
144
|
+
*/
|
|
145
|
+
getTools() {
|
|
146
|
+
return Array.from(this.tools.values()).map((t) => t.config);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Get a specific tool.
|
|
150
|
+
*/
|
|
151
|
+
getTool(name) {
|
|
152
|
+
return this.tools.get(name)?.config;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if a tool exists.
|
|
156
|
+
*/
|
|
157
|
+
hasTool(name) {
|
|
158
|
+
return this.tools.has(name);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Execute a tool.
|
|
162
|
+
*/
|
|
163
|
+
async executeTool(name, args, context) {
|
|
164
|
+
const tool = this.tools.get(name);
|
|
165
|
+
if (!tool) throw new Error(`Tool not found: ${name}`);
|
|
166
|
+
if (!tool.handler) throw new Error(`No handler for tool: ${name}`);
|
|
167
|
+
const fullContext = {
|
|
168
|
+
agentId: context?.agentId ?? "consumer",
|
|
169
|
+
sessionId: context?.sessionId ?? "consumer-session",
|
|
170
|
+
tenantId: context?.tenantId,
|
|
171
|
+
actorId: context?.actorId,
|
|
172
|
+
metadata: context?.metadata,
|
|
173
|
+
signal: context?.signal
|
|
174
|
+
};
|
|
175
|
+
return await tool.handler(args, fullContext);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Add a tool.
|
|
179
|
+
*/
|
|
180
|
+
addTool(config, handler) {
|
|
181
|
+
this.tools.set(config.name, {
|
|
182
|
+
config,
|
|
183
|
+
handler
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Remove a tool.
|
|
188
|
+
*/
|
|
189
|
+
removeTool(name) {
|
|
190
|
+
return this.tools.delete(name);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Get tool count.
|
|
194
|
+
*/
|
|
195
|
+
getToolCount() {
|
|
196
|
+
return this.tools.size;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* Create a new tool consumer.
|
|
201
|
+
*/
|
|
202
|
+
function createToolConsumer(config) {
|
|
203
|
+
return new ContractSpecToolConsumer(config);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Create an MCP tool server from tools.
|
|
207
|
+
*/
|
|
208
|
+
function createToolServer(config) {
|
|
209
|
+
return new MCPToolServer(config);
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Export tools to a specific SDK format.
|
|
213
|
+
*/
|
|
214
|
+
function exportToolsForExternalSDK(tools, format) {
|
|
215
|
+
return new ContractSpecToolConsumer({ tools: tools.map((config) => ({ config })) }).exportToolsForSDK(format);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
export { ContractSpecToolConsumer, createToolConsumer, createToolServer, exportToolsForExternalSDK };
|
|
220
|
+
//# sourceMappingURL=tool-consumer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-consumer.js","names":["fullContext: ToolExecutionContext","definitions: {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[]","defaultContext: Partial<ToolExecutionContext>"],"sources":["../../src/interop/tool-consumer.ts"],"sourcesContent":["/**\n * Tool consumer for external agents.\n *\n * Enables external agent SDKs to consume ContractSpec tools:\n * - Create MCP servers exposing tools\n * - Export tools for specific SDK formats\n * - Bridge tool execution\n */\nimport type { AgentToolConfig } from '../spec/spec';\nimport type { ToolHandler, ToolExecutionContext } from '../types';\nimport type {\n ToolConsumer,\n ToolConsumerConfig,\n ToolServerConfig,\n ToolServer,\n ToolExportFormat,\n} from './types';\nimport { specToolToClaudeAgentTool } from '../providers/claude-agent-sdk/tool-bridge';\nimport { specToolToOpenCodeTool } from '../providers/opencode-sdk/tool-bridge';\n\n// =============================================================================\n// Tool Server Implementation\n// =============================================================================\n\n/**\n * Simple MCP-compatible tool server.\n */\nclass MCPToolServer implements ToolServer {\n private readonly tools: Map<\n string,\n { config: AgentToolConfig; handler?: ToolHandler }\n >;\n private readonly name: string;\n private readonly version: string;\n private running = false;\n\n constructor(config: ToolServerConfig) {\n this.tools = new Map();\n this.name = config.name ?? 'contractspec-tools';\n this.version = config.version ?? '1.0.0';\n\n // Register tools\n for (const tool of config.tools) {\n this.tools.set(tool.config.name, tool);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) {\n return;\n }\n\n // In a real implementation, this would start an HTTP/stdio server\n // For now, we just mark as running\n this.running = true;\n\n console.log(\n `[MCPToolServer] Started ${this.name}@${this.version} with ${this.tools.size} tools`\n );\n }\n\n async stop(): Promise<void> {\n if (!this.running) {\n return;\n }\n\n this.running = false;\n console.log(`[MCPToolServer] Stopped ${this.name}`);\n }\n\n isRunning(): boolean {\n return this.running;\n }\n\n getTools(): AgentToolConfig[] {\n return Array.from(this.tools.values()).map((t) => t.config);\n }\n\n async executeTool(\n toolName: string,\n args: Record<string, unknown>,\n context?: ToolExecutionContext\n ): Promise<string> {\n const tool = this.tools.get(toolName);\n if (!tool) {\n throw new Error(`Tool not found: ${toolName}`);\n }\n\n if (!tool.handler) {\n throw new Error(`No handler registered for tool: ${toolName}`);\n }\n\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'mcp-server',\n sessionId: context?.sessionId ?? 'mcp-session',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n\n return await tool.handler(args, fullContext);\n }\n\n /**\n * Get MCP-compatible tool definitions.\n */\n getMCPToolDefinitions(): {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[] {\n const definitions: {\n name: string;\n description: string;\n inputSchema: Record<string, unknown>;\n }[] = [];\n\n for (const [name, tool] of this.tools) {\n definitions.push({\n name,\n description: tool.config.description ?? '',\n inputSchema: tool.config.schema ?? { type: 'object', properties: {} },\n });\n }\n\n return definitions;\n }\n\n /**\n * Get server info for MCP.\n */\n getServerInfo(): {\n name: string;\n version: string;\n tools: number;\n running: boolean;\n } {\n return {\n name: this.name,\n version: this.version,\n tools: this.tools.size,\n running: this.running,\n };\n }\n}\n\n// =============================================================================\n// Tool Consumer Implementation\n// =============================================================================\n\n/**\n * ContractSpec tool consumer for external agents.\n */\nexport class ContractSpecToolConsumer implements ToolConsumer {\n private readonly tools: Map<\n string,\n { config: AgentToolConfig; handler?: ToolHandler }\n >;\n\n constructor(config: ToolConsumerConfig) {\n this.tools = new Map();\n\n // Register tools\n for (const tool of config.tools) {\n this.tools.set(tool.config.name, tool);\n }\n }\n\n /**\n * Create an MCP server exposing the tools.\n */\n createToolServer(config?: Partial<ToolServerConfig>): ToolServer {\n return new MCPToolServer({\n tools: Array.from(this.tools.values()),\n ...config,\n });\n }\n\n /**\n * Export tools for a specific SDK format.\n */\n exportToolsForSDK(format: ToolExportFormat): unknown[] {\n const tools = Array.from(this.tools.values());\n const defaultContext: Partial<ToolExecutionContext> = {\n agentId: 'export',\n sessionId: 'export',\n };\n\n switch (format) {\n case 'claude-agent':\n return tools\n .filter(\n (\n tool\n ): tool is typeof tool & {\n handler: NonNullable<typeof tool.handler>;\n } => !!tool.handler\n )\n .map((tool) =>\n specToolToClaudeAgentTool(tool.config, tool.handler, defaultContext)\n );\n\n case 'opencode':\n return tools.map((tool) => specToolToOpenCodeTool(tool.config));\n\n case 'mcp':\n return tools.map((tool) => ({\n name: tool.config.name,\n description: tool.config.description ?? '',\n inputSchema: tool.config.schema ?? { type: 'object', properties: {} },\n }));\n\n case 'openai':\n return tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.config.name,\n description: tool.config.description ?? '',\n parameters: tool.config.schema ?? {\n type: 'object',\n properties: {},\n },\n },\n }));\n\n default:\n throw new Error(`Unknown export format: ${format}`);\n }\n }\n\n /**\n * Create a bridged handler for a specific SDK.\n */\n createBridgedHandler(\n toolName: string,\n _format: ToolExportFormat\n ): ((args: Record<string, unknown>) => Promise<unknown>) | undefined {\n const tool = this.tools.get(toolName);\n if (!tool || !tool.handler) {\n return undefined;\n }\n\n const handler = tool.handler;\n\n // Return a simple wrapper that works for any format\n return async (args: Record<string, unknown>) => {\n const context: ToolExecutionContext = {\n agentId: 'bridge',\n sessionId: 'bridge',\n };\n // ToolHandler returns Promise<string>, but bridge expects Promise<unknown>\n // The types are compatible in this direction\n return handler(args, context);\n };\n }\n\n /**\n * Get all tools.\n */\n getTools(): AgentToolConfig[] {\n return Array.from(this.tools.values()).map((t) => t.config);\n }\n\n /**\n * Get a specific tool.\n */\n getTool(name: string): AgentToolConfig | undefined {\n return this.tools.get(name)?.config;\n }\n\n /**\n * Check if a tool exists.\n */\n hasTool(name: string): boolean {\n return this.tools.has(name);\n }\n\n /**\n * Execute a tool.\n */\n async executeTool(\n name: string,\n args: Record<string, unknown>,\n context?: ToolExecutionContext\n ): Promise<string> {\n const tool = this.tools.get(name);\n if (!tool) {\n throw new Error(`Tool not found: ${name}`);\n }\n\n if (!tool.handler) {\n throw new Error(`No handler for tool: ${name}`);\n }\n\n const fullContext: ToolExecutionContext = {\n agentId: context?.agentId ?? 'consumer',\n sessionId: context?.sessionId ?? 'consumer-session',\n tenantId: context?.tenantId,\n actorId: context?.actorId,\n metadata: context?.metadata,\n signal: context?.signal,\n };\n\n return await tool.handler(args, fullContext);\n }\n\n /**\n * Add a tool.\n */\n addTool(config: AgentToolConfig, handler?: ToolHandler): void {\n this.tools.set(config.name, { config, handler });\n }\n\n /**\n * Remove a tool.\n */\n removeTool(name: string): boolean {\n return this.tools.delete(name);\n }\n\n /**\n * Get tool count.\n */\n getToolCount(): number {\n return this.tools.size;\n }\n}\n\n// =============================================================================\n// Factory Functions\n// =============================================================================\n\n/**\n * Create a new tool consumer.\n */\nexport function createToolConsumer(config: ToolConsumerConfig): ToolConsumer {\n return new ContractSpecToolConsumer(config);\n}\n\n/**\n * Create an MCP tool server from tools.\n */\nexport function createToolServer(config: ToolServerConfig): ToolServer {\n return new MCPToolServer(config);\n}\n\n/**\n * Export tools to a specific SDK format.\n */\nexport function exportToolsForExternalSDK(\n tools: AgentToolConfig[],\n format: ToolExportFormat\n): unknown[] {\n const consumer = new ContractSpecToolConsumer({\n tools: tools.map((config) => ({ config })),\n });\n return consumer.exportToolsForSDK(format);\n}\n"],"mappings":"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"}
|