@contractspec/lib.ai-agent 0.0.0-canary-20260113162409
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/LICENSE +21 -0
- package/README.md +49 -0
- package/dist/_virtual/rolldown_runtime.js +8 -0
- package/dist/agent/agent-factory.d.ts +104 -0
- package/dist/agent/agent-factory.d.ts.map +1 -0
- package/dist/agent/agent-factory.js +103 -0
- package/dist/agent/agent-factory.js.map +1 -0
- package/dist/agent/contract-spec-agent.d.ts +75 -0
- package/dist/agent/contract-spec-agent.d.ts.map +1 -0
- package/dist/agent/contract-spec-agent.js +148 -0
- package/dist/agent/contract-spec-agent.js.map +1 -0
- package/dist/agent/index.d.ts +3 -0
- package/dist/agent/index.js +4 -0
- 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/approval/index.d.ts +2 -0
- package/dist/approval/index.js +3 -0
- package/dist/approval/workflow.d.ts +156 -0
- package/dist/approval/workflow.d.ts.map +1 -0
- package/dist/approval/workflow.js +160 -0
- package/dist/approval/workflow.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 +37 -0
- package/dist/index.js +31 -0
- 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/knowledge/index.d.ts +2 -0
- package/dist/knowledge/index.js +3 -0
- package/dist/knowledge/injector.d.ts +38 -0
- package/dist/knowledge/injector.d.ts.map +1 -0
- package/dist/knowledge/injector.js +58 -0
- package/dist/knowledge/injector.js.map +1 -0
- package/dist/memory/in-memory.d.ts +22 -0
- package/dist/memory/in-memory.d.ts.map +1 -0
- package/dist/memory/in-memory.js +48 -0
- package/dist/memory/in-memory.js.map +1 -0
- package/dist/memory/index.d.ts +3 -0
- package/dist/memory/index.js +4 -0
- package/dist/memory/manager.d.ts +42 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +80 -0
- package/dist/memory/manager.js.map +1 -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/schema/index.d.ts +3 -0
- package/dist/schema/index.js +4 -0
- package/dist/schema/json-schema-to-zod.d.ts +55 -0
- package/dist/schema/json-schema-to-zod.d.ts.map +1 -0
- package/dist/schema/json-schema-to-zod.js +124 -0
- package/dist/schema/json-schema-to-zod.js.map +1 -0
- package/dist/schema/schema-output.d.ts +77 -0
- package/dist/schema/schema-output.d.ts.map +1 -0
- package/dist/schema/schema-output.js +65 -0
- package/dist/schema/schema-output.js.map +1 -0
- package/dist/session/index.d.ts +2 -0
- package/dist/session/index.js +3 -0
- package/dist/session/store.d.ts +74 -0
- package/dist/session/store.d.ts.map +1 -0
- package/dist/session/store.js +79 -0
- package/dist/session/store.js.map +1 -0
- package/dist/spec/index.d.ts +3 -0
- package/dist/spec/index.js +4 -0
- package/dist/spec/registry.d.ts +47 -0
- package/dist/spec/registry.d.ts.map +1 -0
- package/dist/spec/registry.js +65 -0
- package/dist/spec/registry.js.map +1 -0
- package/dist/spec/spec.d.ts +127 -0
- package/dist/spec/spec.d.ts.map +1 -0
- package/dist/spec/spec.js +30 -0
- package/dist/spec/spec.js.map +1 -0
- package/dist/telemetry/adapter.d.ts +73 -0
- package/dist/telemetry/adapter.d.ts.map +1 -0
- package/dist/telemetry/adapter.js +103 -0
- package/dist/telemetry/adapter.js.map +1 -0
- package/dist/telemetry/index.d.ts +2 -0
- package/dist/telemetry/index.js +3 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/knowledge-tool.d.ts +21 -0
- package/dist/tools/knowledge-tool.d.ts.map +1 -0
- package/dist/tools/knowledge-tool.js +54 -0
- package/dist/tools/knowledge-tool.js.map +1 -0
- package/dist/tools/mcp-client.d.ts +59 -0
- package/dist/tools/mcp-client.d.ts.map +1 -0
- package/dist/tools/mcp-client.js +58 -0
- package/dist/tools/mcp-client.js.map +1 -0
- package/dist/tools/mcp-server.d.ts +46 -0
- package/dist/tools/mcp-server.d.ts.map +1 -0
- package/dist/tools/mcp-server.js +69 -0
- package/dist/tools/mcp-server.js.map +1 -0
- package/dist/tools/tool-adapter.d.ts +50 -0
- package/dist/tools/tool-adapter.d.ts.map +1 -0
- package/dist/tools/tool-adapter.js +80 -0
- package/dist/tools/tool-adapter.js.map +1 -0
- package/dist/types.d.ts +146 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +0 -0
- package/package.json +155 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Chaman Ventures, SASU
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @contractspec/lib.ai-agent
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@contractspec/lib.ai-agent)
|
|
4
|
+
[](https://www.npmjs.com/package/@contractspec/lib.ai-agent)
|
|
5
|
+
[](https://deepwiki.com/lssm-tech/contractspec)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Website: https://contractspec.io/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
**AI governance for ContractSpec** — Constrain what AI agents can change, enforce contracts they must respect.
|
|
12
|
+
|
|
13
|
+
Stateful AI agent orchestration with type-safe specs, tool execution, knowledge bindings, and per-tenant guardrails. Agents read contracts as their source of truth, enabling triage, growth experiments, and DevOps automation with contract-enforced safety.
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
- Type-safe `AgentSpec` + registry for declarative agent definitions
|
|
18
|
+
- `AgentRunner` with tool calling, iteration caps, and confidence-aware escalation
|
|
19
|
+
- Memory framework that mixes working memory with long-term persistence hooks
|
|
20
|
+
- Tool registry/executor with structured input validation and telemetry hooks
|
|
21
|
+
- Approval workflow helpers for human-in-the-loop gates (see `/approval`)
|
|
22
|
+
|
|
23
|
+
## Quickstart
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { AgentRegistry, AgentRunner, defineAgent } from '@contractspec/lib.ai-agent';
|
|
27
|
+
import { ToolExecutor } from '@contractspec/lib.ai-agent/tools';
|
|
28
|
+
import { InMemoryAgentMemory } from '@contractspec/lib.ai-agent/memory';
|
|
29
|
+
|
|
30
|
+
const SupportAgent = defineAgent({
|
|
31
|
+
meta: { name: 'support.bot', version: '1.0.0', owners: ['team-support'], domain: 'operations' },
|
|
32
|
+
instructions: 'Resolve support tickets. Escalate whenever confidence < 0.75.',
|
|
33
|
+
tools: [{ name: 'search_knowledge', description: 'Query support corpus', schema: { type: 'object', properties: { question: { type: 'string' } }, required: ['question'] } }],
|
|
34
|
+
policy: { confidence: { min: 0.75 }, escalation: { auto: true } },
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const registry = new AgentRegistry().register(SupportAgent);
|
|
38
|
+
const runner = new AgentRunner({
|
|
39
|
+
registry,
|
|
40
|
+
llm: mistralProvider,
|
|
41
|
+
toolExecutor: new ToolExecutor({ tools: [searchKnowledgeTool] }),
|
|
42
|
+
memoryManager: new InMemoryAgentMemory(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const result = await runner.run({ agent: 'support.bot', input: 'My payout failed.', tenantId: 'acme' });
|
|
46
|
+
if (result.requiresEscalation) notifyHuman(result);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
See `examples/ai-support-bot` for a full workflow including ticket ingestion and approval queues.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
|
|
3
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
4
|
+
throw Error("Calling `require` for \"" + x + "\" in an environment that doesn't expose the `require` function.");
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
//#endregion
|
|
8
|
+
export { __require };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { AgentSpec } from "../spec/spec.js";
|
|
2
|
+
import { AgentRegistry } from "../spec/registry.js";
|
|
3
|
+
import { ToolHandler } from "../types.js";
|
|
4
|
+
import { AgentSessionStore } from "../session/store.js";
|
|
5
|
+
import { TelemetryCollector } from "../telemetry/adapter.js";
|
|
6
|
+
import { ContractSpecAgent } from "./contract-spec-agent.js";
|
|
7
|
+
import { LanguageModel, Tool } from "ai";
|
|
8
|
+
import { KnowledgeRetriever } from "@contractspec/lib.knowledge/retriever";
|
|
9
|
+
|
|
10
|
+
//#region src/agent/agent-factory.d.ts
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Factory configuration for creating agents.
|
|
14
|
+
*/
|
|
15
|
+
interface AgentFactoryConfig {
|
|
16
|
+
/** Default language model to use */
|
|
17
|
+
defaultModel: LanguageModel;
|
|
18
|
+
/** Agent registry for looking up specs */
|
|
19
|
+
registry: AgentRegistry;
|
|
20
|
+
/** Global tool handlers map */
|
|
21
|
+
toolHandlers: Map<string, ToolHandler>;
|
|
22
|
+
/** Optional knowledge retriever */
|
|
23
|
+
knowledgeRetriever?: KnowledgeRetriever;
|
|
24
|
+
/** Optional session store */
|
|
25
|
+
sessionStore?: AgentSessionStore;
|
|
26
|
+
/** Optional telemetry collector */
|
|
27
|
+
telemetryCollector?: TelemetryCollector;
|
|
28
|
+
/** Additional tools to provide to all agents */
|
|
29
|
+
additionalTools?: Record<string, Tool<unknown, unknown>>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Options for creating an agent instance.
|
|
33
|
+
*/
|
|
34
|
+
interface CreateAgentOptions {
|
|
35
|
+
/** Override the default model */
|
|
36
|
+
model?: LanguageModel;
|
|
37
|
+
/** Additional tool handlers specific to this instance */
|
|
38
|
+
toolHandlers?: Map<string, ToolHandler>;
|
|
39
|
+
/** Additional tools for this instance */
|
|
40
|
+
additionalTools?: Record<string, Tool<unknown, unknown>>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Factory for creating ContractSpec agents from specs.
|
|
44
|
+
*
|
|
45
|
+
* Provides a centralized way to instantiate agents with
|
|
46
|
+
* consistent configuration.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const factory = createAgentFactory({
|
|
51
|
+
* defaultModel: mistral('mistral-large-latest'),
|
|
52
|
+
* registry: agentRegistry,
|
|
53
|
+
* toolHandlers: globalToolHandlers,
|
|
54
|
+
* sessionStore: mySessionStore,
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* const agent = await factory.create('support.bot');
|
|
58
|
+
* const result = await agent.generate({ prompt: 'Help me with...' });
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
declare class AgentFactory {
|
|
62
|
+
private readonly config;
|
|
63
|
+
private readonly cache;
|
|
64
|
+
constructor(config: AgentFactoryConfig);
|
|
65
|
+
/**
|
|
66
|
+
* Create an agent by name.
|
|
67
|
+
*
|
|
68
|
+
* @param name - Agent name (e.g., "support.bot")
|
|
69
|
+
* @param version - Optional specific version
|
|
70
|
+
* @param options - Optional creation options
|
|
71
|
+
*/
|
|
72
|
+
create(name: string, version?: string, options?: CreateAgentOptions): Promise<ContractSpecAgent>;
|
|
73
|
+
/**
|
|
74
|
+
* Create an agent from a spec directly.
|
|
75
|
+
*
|
|
76
|
+
* @param spec - Agent specification
|
|
77
|
+
* @param options - Optional creation options
|
|
78
|
+
*/
|
|
79
|
+
createFromSpec(spec: AgentSpec, options?: CreateAgentOptions): Promise<ContractSpecAgent>;
|
|
80
|
+
/**
|
|
81
|
+
* Get or create a cached agent instance.
|
|
82
|
+
*
|
|
83
|
+
* Use this when you want to reuse agent instances.
|
|
84
|
+
*
|
|
85
|
+
* @param name - Agent name
|
|
86
|
+
* @param version - Optional specific version
|
|
87
|
+
*/
|
|
88
|
+
getOrCreate(name: string, version?: string): Promise<ContractSpecAgent>;
|
|
89
|
+
/**
|
|
90
|
+
* Clear the agent cache.
|
|
91
|
+
*/
|
|
92
|
+
clearCache(): void;
|
|
93
|
+
/**
|
|
94
|
+
* List all available agent names.
|
|
95
|
+
*/
|
|
96
|
+
listAvailable(): string[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create an agent factory.
|
|
100
|
+
*/
|
|
101
|
+
declare function createAgentFactory(config: AgentFactoryConfig): AgentFactory;
|
|
102
|
+
//#endregion
|
|
103
|
+
export { AgentFactory, AgentFactoryConfig, CreateAgentOptions, createAgentFactory };
|
|
104
|
+
//# sourceMappingURL=agent-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-factory.d.ts","names":[],"sources":["../../src/agent/agent-factory.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AAYA;AAEgB,UAFC,kBAAA,CAED;EAEJ;EAEgB,YAAA,EAJZ,aAIY;EAAZ;EAEO,QAAA,EAJX,aAIW;EAEN;EAEM,YAAA,EANP,GAMO,CAAA,MAAA,EANK,WAML,CAAA;EAEY;EAAf,kBAAA,CAAA,EANG,kBAMH;EAAM;EAMT,YAAA,CAAA,EAVA,iBAUkB;EAEzB;EAEmB,kBAAA,CAAA,EAZN,kBAYM;EAAZ;EAEkB,eAAA,CAAA,EAZf,MAYe,CAAA,MAAA,EAZA,IAYA,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;;;AAsBnC;;AAkBc,UA9CG,kBAAA,CA8CH;EACD;EAAR,KAAA,CAAA,EA7CK,aA6CL;EAYK;EACI,YAAA,CAAA,EAxDG,GAwDH,CAAA,MAAA,EAxDe,WAwDf,CAAA;EACD;EAAR,eAAA,CAAA,EAvDe,MAuDf,CAAA,MAAA,EAvD8B,IAuD9B,CAAA,OAAA,EAAA,OAAA,CAAA,CAAA;;;;AAsEL;;;;;;;;;;;;;;;;;cAvGa,YAAA;;;sBAIS;;;;;;;;mDAcR,qBACT,QAAQ;;;;;;;uBAYH,qBACI,qBACT,QAAQ;;;;;;;;;+CAuCR,QAAQ;;;;;;;;;;;;;iBA+BG,kBAAA,SAA2B,qBAAqB"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { ContractSpecAgent } from "./contract-spec-agent.js";
|
|
2
|
+
|
|
3
|
+
//#region src/agent/agent-factory.ts
|
|
4
|
+
/**
|
|
5
|
+
* Factory for creating ContractSpec agents from specs.
|
|
6
|
+
*
|
|
7
|
+
* Provides a centralized way to instantiate agents with
|
|
8
|
+
* consistent configuration.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const factory = createAgentFactory({
|
|
13
|
+
* defaultModel: mistral('mistral-large-latest'),
|
|
14
|
+
* registry: agentRegistry,
|
|
15
|
+
* toolHandlers: globalToolHandlers,
|
|
16
|
+
* sessionStore: mySessionStore,
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* const agent = await factory.create('support.bot');
|
|
20
|
+
* const result = await agent.generate({ prompt: 'Help me with...' });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
var AgentFactory = class {
|
|
24
|
+
config;
|
|
25
|
+
cache = /* @__PURE__ */ new Map();
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.config = config;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create an agent by name.
|
|
31
|
+
*
|
|
32
|
+
* @param name - Agent name (e.g., "support.bot")
|
|
33
|
+
* @param version - Optional specific version
|
|
34
|
+
* @param options - Optional creation options
|
|
35
|
+
*/
|
|
36
|
+
async create(name, version, options) {
|
|
37
|
+
const spec = this.config.registry.require(name, version);
|
|
38
|
+
return this.createFromSpec(spec, options);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Create an agent from a spec directly.
|
|
42
|
+
*
|
|
43
|
+
* @param spec - Agent specification
|
|
44
|
+
* @param options - Optional creation options
|
|
45
|
+
*/
|
|
46
|
+
async createFromSpec(spec, options) {
|
|
47
|
+
const mergedHandlers = new Map(this.config.toolHandlers);
|
|
48
|
+
if (options?.toolHandlers) for (const [key, handler] of options.toolHandlers) mergedHandlers.set(key, handler);
|
|
49
|
+
const mergedTools = {
|
|
50
|
+
...this.config.additionalTools,
|
|
51
|
+
...options?.additionalTools
|
|
52
|
+
};
|
|
53
|
+
return ContractSpecAgent.create({
|
|
54
|
+
spec,
|
|
55
|
+
model: options?.model ?? this.config.defaultModel,
|
|
56
|
+
toolHandlers: mergedHandlers,
|
|
57
|
+
knowledgeRetriever: this.config.knowledgeRetriever,
|
|
58
|
+
sessionStore: this.config.sessionStore,
|
|
59
|
+
telemetryCollector: this.config.telemetryCollector,
|
|
60
|
+
additionalTools: mergedTools
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get or create a cached agent instance.
|
|
65
|
+
*
|
|
66
|
+
* Use this when you want to reuse agent instances.
|
|
67
|
+
*
|
|
68
|
+
* @param name - Agent name
|
|
69
|
+
* @param version - Optional specific version
|
|
70
|
+
*/
|
|
71
|
+
async getOrCreate(name, version) {
|
|
72
|
+
const spec = this.config.registry.require(name, version);
|
|
73
|
+
const cacheKey = `${spec.meta.key}.v${spec.meta.version}`;
|
|
74
|
+
let agent = this.cache.get(cacheKey);
|
|
75
|
+
if (!agent) {
|
|
76
|
+
agent = await this.createFromSpec(spec);
|
|
77
|
+
this.cache.set(cacheKey, agent);
|
|
78
|
+
}
|
|
79
|
+
return agent;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clear the agent cache.
|
|
83
|
+
*/
|
|
84
|
+
clearCache() {
|
|
85
|
+
this.cache.clear();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* List all available agent names.
|
|
89
|
+
*/
|
|
90
|
+
listAvailable() {
|
|
91
|
+
return this.config.registry.listNames();
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Create an agent factory.
|
|
96
|
+
*/
|
|
97
|
+
function createAgentFactory(config) {
|
|
98
|
+
return new AgentFactory(config);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { AgentFactory, createAgentFactory };
|
|
103
|
+
//# sourceMappingURL=agent-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-factory.js","names":[],"sources":["../../src/agent/agent-factory.ts"],"sourcesContent":["import type { LanguageModel, Tool } from 'ai';\nimport type { KnowledgeRetriever } from '@contractspec/lib.knowledge/retriever';\nimport type { AgentSpec } from '../spec/spec';\nimport type { AgentRegistry } from '../spec/registry';\nimport type { ToolHandler } from '../types';\nimport type { AgentSessionStore } from '../session/store';\nimport type { TelemetryCollector } from '../telemetry/adapter';\nimport { ContractSpecAgent } from './contract-spec-agent';\n\n/**\n * Factory configuration for creating agents.\n */\nexport interface AgentFactoryConfig {\n /** Default language model to use */\n defaultModel: LanguageModel;\n /** Agent registry for looking up specs */\n registry: AgentRegistry;\n /** Global tool handlers map */\n toolHandlers: Map<string, ToolHandler>;\n /** Optional knowledge retriever */\n knowledgeRetriever?: KnowledgeRetriever;\n /** Optional session store */\n sessionStore?: AgentSessionStore;\n /** Optional telemetry collector */\n telemetryCollector?: TelemetryCollector;\n /** Additional tools to provide to all agents */\n additionalTools?: Record<string, Tool<unknown, unknown>>;\n}\n\n/**\n * Options for creating an agent instance.\n */\nexport interface CreateAgentOptions {\n /** Override the default model */\n model?: LanguageModel;\n /** Additional tool handlers specific to this instance */\n toolHandlers?: Map<string, ToolHandler>;\n /** Additional tools for this instance */\n additionalTools?: Record<string, Tool<unknown, unknown>>;\n}\n\n/**\n * Factory for creating ContractSpec agents from specs.\n *\n * Provides a centralized way to instantiate agents with\n * consistent configuration.\n *\n * @example\n * ```typescript\n * const factory = createAgentFactory({\n * defaultModel: mistral('mistral-large-latest'),\n * registry: agentRegistry,\n * toolHandlers: globalToolHandlers,\n * sessionStore: mySessionStore,\n * });\n *\n * const agent = await factory.create('support.bot');\n * const result = await agent.generate({ prompt: 'Help me with...' });\n * ```\n */\nexport class AgentFactory {\n private readonly config: AgentFactoryConfig;\n private readonly cache = new Map<string, ContractSpecAgent>();\n\n constructor(config: AgentFactoryConfig) {\n this.config = config;\n }\n\n /**\n * Create an agent by name.\n *\n * @param name - Agent name (e.g., \"support.bot\")\n * @param version - Optional specific version\n * @param options - Optional creation options\n */\n async create(\n name: string,\n version?: string,\n options?: CreateAgentOptions\n ): Promise<ContractSpecAgent> {\n const spec = this.config.registry.require(name, version);\n return this.createFromSpec(spec, options);\n }\n\n /**\n * Create an agent from a spec directly.\n *\n * @param spec - Agent specification\n * @param options - Optional creation options\n */\n async createFromSpec(\n spec: AgentSpec,\n options?: CreateAgentOptions\n ): Promise<ContractSpecAgent> {\n // Merge tool handlers\n const mergedHandlers = new Map<string, ToolHandler>(\n this.config.toolHandlers\n );\n if (options?.toolHandlers) {\n for (const [key, handler] of options.toolHandlers) {\n mergedHandlers.set(key, handler);\n }\n }\n\n // Merge additional tools\n const mergedTools = {\n ...this.config.additionalTools,\n ...options?.additionalTools,\n };\n\n return ContractSpecAgent.create({\n spec,\n model: options?.model ?? this.config.defaultModel,\n toolHandlers: mergedHandlers,\n knowledgeRetriever: this.config.knowledgeRetriever,\n sessionStore: this.config.sessionStore,\n telemetryCollector: this.config.telemetryCollector,\n additionalTools: mergedTools,\n });\n }\n\n /**\n * Get or create a cached agent instance.\n *\n * Use this when you want to reuse agent instances.\n *\n * @param name - Agent name\n * @param version - Optional specific version\n */\n async getOrCreate(\n name: string,\n version?: string\n ): Promise<ContractSpecAgent> {\n const spec = this.config.registry.require(name, version);\n const cacheKey = `${spec.meta.key}.v${spec.meta.version}`;\n\n let agent = this.cache.get(cacheKey);\n if (!agent) {\n agent = await this.createFromSpec(spec);\n this.cache.set(cacheKey, agent);\n }\n\n return agent;\n }\n\n /**\n * Clear the agent cache.\n */\n clearCache(): void {\n this.cache.clear();\n }\n\n /**\n * List all available agent names.\n */\n listAvailable(): string[] {\n return this.config.registry.listNames();\n }\n}\n\n/**\n * Create an agent factory.\n */\nexport function createAgentFactory(config: AgentFactoryConfig): AgentFactory {\n return new AgentFactory(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA4DA,IAAa,eAAb,MAA0B;CACxB,AAAiB;CACjB,AAAiB,wBAAQ,IAAI,KAAgC;CAE7D,YAAY,QAA4B;AACtC,OAAK,SAAS;;;;;;;;;CAUhB,MAAM,OACJ,MACA,SACA,SAC4B;EAC5B,MAAM,OAAO,KAAK,OAAO,SAAS,QAAQ,MAAM,QAAQ;AACxD,SAAO,KAAK,eAAe,MAAM,QAAQ;;;;;;;;CAS3C,MAAM,eACJ,MACA,SAC4B;EAE5B,MAAM,iBAAiB,IAAI,IACzB,KAAK,OAAO,aACb;AACD,MAAI,SAAS,aACX,MAAK,MAAM,CAAC,KAAK,YAAY,QAAQ,aACnC,gBAAe,IAAI,KAAK,QAAQ;EAKpC,MAAM,cAAc;GAClB,GAAG,KAAK,OAAO;GACf,GAAG,SAAS;GACb;AAED,SAAO,kBAAkB,OAAO;GAC9B;GACA,OAAO,SAAS,SAAS,KAAK,OAAO;GACrC,cAAc;GACd,oBAAoB,KAAK,OAAO;GAChC,cAAc,KAAK,OAAO;GAC1B,oBAAoB,KAAK,OAAO;GAChC,iBAAiB;GAClB,CAAC;;;;;;;;;;CAWJ,MAAM,YACJ,MACA,SAC4B;EAC5B,MAAM,OAAO,KAAK,OAAO,SAAS,QAAQ,MAAM,QAAQ;EACxD,MAAM,WAAW,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK;EAEhD,IAAI,QAAQ,KAAK,MAAM,IAAI,SAAS;AACpC,MAAI,CAAC,OAAO;AACV,WAAQ,MAAM,KAAK,eAAe,KAAK;AACvC,QAAK,MAAM,IAAI,UAAU,MAAM;;AAGjC,SAAO;;;;;CAMT,aAAmB;AACjB,OAAK,MAAM,OAAO;;;;;CAMpB,gBAA0B;AACxB,SAAO,KAAK,OAAO,SAAS,WAAW;;;;;;AAO3C,SAAgB,mBAAmB,QAA0C;AAC3E,QAAO,IAAI,aAAa,OAAO"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { AgentSpec } from "../spec/spec.js";
|
|
2
|
+
import { AgentGenerateParams, AgentGenerateResult, AgentStreamParams, ToolHandler } from "../types.js";
|
|
3
|
+
import { AgentSessionStore } from "../session/store.js";
|
|
4
|
+
import { TelemetryCollector } from "../telemetry/adapter.js";
|
|
5
|
+
import * as ai0 from "ai";
|
|
6
|
+
import { LanguageModel, Tool, ToolSet } from "ai";
|
|
7
|
+
import { KnowledgeRetriever } from "@contractspec/lib.knowledge/retriever";
|
|
8
|
+
|
|
9
|
+
//#region src/agent/contract-spec-agent.d.ts
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Type for tool with execute function (compatible with AI SDK Tool)
|
|
13
|
+
* Using `any` for broad compatibility with AI SDK tool types
|
|
14
|
+
*/
|
|
15
|
+
type ExecutableTool = Tool<any, any>;
|
|
16
|
+
/**
|
|
17
|
+
* Configuration for creating a ContractSpecAgent.
|
|
18
|
+
*/
|
|
19
|
+
interface ContractSpecAgentConfig {
|
|
20
|
+
/** The agent specification */
|
|
21
|
+
spec: AgentSpec;
|
|
22
|
+
/** AI SDK language model */
|
|
23
|
+
model: LanguageModel;
|
|
24
|
+
/** Map of tool name to handler function */
|
|
25
|
+
toolHandlers: Map<string, ToolHandler>;
|
|
26
|
+
/** Optional knowledge retriever for RAG */
|
|
27
|
+
knowledgeRetriever?: KnowledgeRetriever;
|
|
28
|
+
/** Optional session store for persistence */
|
|
29
|
+
sessionStore?: AgentSessionStore;
|
|
30
|
+
/** Optional telemetry collector for evolution */
|
|
31
|
+
telemetryCollector?: TelemetryCollector;
|
|
32
|
+
/** Additional AI SDK tools (e.g., from MCP servers) */
|
|
33
|
+
additionalTools?: Record<string, ExecutableTool>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* ContractSpec Agent implementation using AI SDK v6.
|
|
37
|
+
*
|
|
38
|
+
* Integrates ContractSpec's spec-first governance with AI SDK's
|
|
39
|
+
* ToolLoopAgent, providing:
|
|
40
|
+
* - Spec-defined tools with type-safe handlers
|
|
41
|
+
* - Hybrid knowledge injection (static + dynamic RAG)
|
|
42
|
+
* - Session persistence
|
|
43
|
+
* - Telemetry for evolution
|
|
44
|
+
* - MCP interoperability
|
|
45
|
+
*/
|
|
46
|
+
declare class ContractSpecAgent {
|
|
47
|
+
readonly version = "agent-v1";
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly spec: AgentSpec;
|
|
50
|
+
readonly tools: Record<string, ExecutableTool>;
|
|
51
|
+
private readonly inner;
|
|
52
|
+
private readonly config;
|
|
53
|
+
private instructions;
|
|
54
|
+
private constructor();
|
|
55
|
+
/**
|
|
56
|
+
* Create a ContractSpecAgent instance.
|
|
57
|
+
* This is async because knowledge injection may need to fetch static content.
|
|
58
|
+
*/
|
|
59
|
+
static create(config: ContractSpecAgentConfig): Promise<ContractSpecAgent>;
|
|
60
|
+
/**
|
|
61
|
+
* Generate a response (non-streaming).
|
|
62
|
+
*/
|
|
63
|
+
generate(params: AgentGenerateParams): Promise<AgentGenerateResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Stream a response with real-time updates.
|
|
66
|
+
*/
|
|
67
|
+
stream(params: AgentStreamParams): Promise<ai0.StreamTextResult<ToolSet, never>>;
|
|
68
|
+
/**
|
|
69
|
+
* Handle step completion for persistence and telemetry.
|
|
70
|
+
*/
|
|
71
|
+
private handleStepFinish;
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
export { ContractSpecAgent, ContractSpecAgentConfig };
|
|
75
|
+
//# sourceMappingURL=contract-spec-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-spec-agent.d.ts","names":[],"sources":["../../src/agent/contract-spec-agent.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;;;AAuB+E;AAwB/E,KALK,cAAA,GAAiB,IAKL,CAAA,GAAuB,EAAA,GAAA,CAAA;;;;AAMxB,UANC,uBAAA,CAMD;EAEO;EAEN,IAAA,EART,SAQS;EAEM;EAEY,KAAA,EAV1B,aAU0B;EAAf;EAAM,YAAA,EARV,GAQU,CAAA,MAAA,EARE,WAQF,CAAA;EAcb;EAGI,kBAAA,CAAA,EAvBM,kBAuBN;EACgB;EAAf,YAAA,CAAA,EAtBD,iBAsBC;EA0CN;EACC,kBAAA,CAAA,EA/DU,kBA+DV;EAAR;EAoCoB,eAAA,CAAA,EAjGL,MAiGK,CAAA,MAAA,EAjGU,cAiGV,CAAA;;;;;;;;;;;;;cAnFZ,iBAAA;;;iBAGI;kBACC,eAAe;;;;;;;;;wBA0CrB,0BACP,QAAQ;;;;mBAoCY,sBAAsB,QAAQ;;;;iBAoEhC,oBAAiB,QAAA,GAAA,CAAA,iBAAA"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { agentKey } from "../spec/spec.js";
|
|
2
|
+
import { specToolsToAISDKTools } from "../tools/tool-adapter.js";
|
|
3
|
+
import { createKnowledgeQueryTool } from "../tools/knowledge-tool.js";
|
|
4
|
+
import { injectStaticKnowledge } from "../knowledge/injector.js";
|
|
5
|
+
import { generateSessionId } from "../session/store.js";
|
|
6
|
+
import { trackAgentStep } from "../telemetry/adapter.js";
|
|
7
|
+
import { Experimental_Agent, stepCountIs } from "ai";
|
|
8
|
+
import * as z$1 from "zod";
|
|
9
|
+
|
|
10
|
+
//#region src/agent/contract-spec-agent.ts
|
|
11
|
+
/**
|
|
12
|
+
* Call options schema for AI SDK v6.
|
|
13
|
+
* Maps ContractSpec's tenant/actor system to AI SDK callOptionsSchema.
|
|
14
|
+
*/
|
|
15
|
+
const ContractSpecCallOptionsSchema = z$1.object({
|
|
16
|
+
tenantId: z$1.string().optional(),
|
|
17
|
+
actorId: z$1.string().optional(),
|
|
18
|
+
sessionId: z$1.string().optional(),
|
|
19
|
+
metadata: z$1.record(z$1.string(), z$1.unknown()).optional()
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* ContractSpec Agent implementation using AI SDK v6.
|
|
23
|
+
*
|
|
24
|
+
* Integrates ContractSpec's spec-first governance with AI SDK's
|
|
25
|
+
* ToolLoopAgent, providing:
|
|
26
|
+
* - Spec-defined tools with type-safe handlers
|
|
27
|
+
* - Hybrid knowledge injection (static + dynamic RAG)
|
|
28
|
+
* - Session persistence
|
|
29
|
+
* - Telemetry for evolution
|
|
30
|
+
* - MCP interoperability
|
|
31
|
+
*/
|
|
32
|
+
var ContractSpecAgent = class ContractSpecAgent {
|
|
33
|
+
version = "agent-v1";
|
|
34
|
+
id;
|
|
35
|
+
spec;
|
|
36
|
+
tools;
|
|
37
|
+
inner;
|
|
38
|
+
config;
|
|
39
|
+
instructions;
|
|
40
|
+
constructor(config, instructions, tools) {
|
|
41
|
+
this.config = config;
|
|
42
|
+
this.spec = config.spec;
|
|
43
|
+
this.id = agentKey(config.spec.meta);
|
|
44
|
+
this.tools = tools;
|
|
45
|
+
this.instructions = instructions;
|
|
46
|
+
this.inner = new Experimental_Agent({
|
|
47
|
+
model: config.model,
|
|
48
|
+
instructions,
|
|
49
|
+
tools,
|
|
50
|
+
stopWhen: stepCountIs(config.spec.maxSteps ?? 10),
|
|
51
|
+
callOptionsSchema: ContractSpecCallOptionsSchema,
|
|
52
|
+
onStepFinish: async (step) => {
|
|
53
|
+
await this.handleStepFinish(step);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Create a ContractSpecAgent instance.
|
|
59
|
+
* This is async because knowledge injection may need to fetch static content.
|
|
60
|
+
*/
|
|
61
|
+
static async create(config) {
|
|
62
|
+
const instructions = await injectStaticKnowledge(config.spec.instructions, config.spec.knowledge ?? [], config.knowledgeRetriever);
|
|
63
|
+
const specTools = specToolsToAISDKTools(config.spec.tools, config.toolHandlers, { agentId: agentKey(config.spec.meta) });
|
|
64
|
+
const knowledgeTool = config.knowledgeRetriever ? createKnowledgeQueryTool(config.knowledgeRetriever, config.spec.knowledge ?? []) : null;
|
|
65
|
+
return new ContractSpecAgent(config, instructions, {
|
|
66
|
+
...specTools,
|
|
67
|
+
...knowledgeTool ? { query_knowledge: knowledgeTool } : {},
|
|
68
|
+
...config.additionalTools ?? {}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Generate a response (non-streaming).
|
|
73
|
+
*/
|
|
74
|
+
async generate(params) {
|
|
75
|
+
const sessionId = params.options?.sessionId ?? generateSessionId();
|
|
76
|
+
if (this.config.sessionStore) {
|
|
77
|
+
if (!await this.config.sessionStore.get(sessionId)) await this.config.sessionStore.create({
|
|
78
|
+
sessionId,
|
|
79
|
+
agentId: this.id,
|
|
80
|
+
tenantId: params.options?.tenantId,
|
|
81
|
+
actorId: params.options?.actorId,
|
|
82
|
+
status: "running",
|
|
83
|
+
messages: [],
|
|
84
|
+
steps: [],
|
|
85
|
+
metadata: params.options?.metadata
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
const prompt = params.systemOverride ? `${this.instructions}\n\n${params.systemOverride}\n\n${params.prompt}` : params.prompt;
|
|
89
|
+
const result = await this.inner.generate({
|
|
90
|
+
prompt,
|
|
91
|
+
abortSignal: params.signal,
|
|
92
|
+
options: {
|
|
93
|
+
tenantId: params.options?.tenantId,
|
|
94
|
+
actorId: params.options?.actorId,
|
|
95
|
+
sessionId,
|
|
96
|
+
metadata: params.options?.metadata
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
if (this.config.sessionStore) await this.config.sessionStore.update(sessionId, { status: "completed" });
|
|
100
|
+
return {
|
|
101
|
+
text: result.text,
|
|
102
|
+
steps: result.steps,
|
|
103
|
+
toolCalls: result.toolCalls.map((tc) => ({
|
|
104
|
+
type: "tool-call",
|
|
105
|
+
toolCallId: tc.toolCallId,
|
|
106
|
+
toolName: tc.toolName,
|
|
107
|
+
args: "args" in tc ? tc.args : "input" in tc ? tc.input : void 0
|
|
108
|
+
})),
|
|
109
|
+
toolResults: result.toolResults.map((tr) => ({
|
|
110
|
+
type: "tool-result",
|
|
111
|
+
toolCallId: tr.toolCallId,
|
|
112
|
+
toolName: tr.toolName,
|
|
113
|
+
output: tr.output
|
|
114
|
+
})),
|
|
115
|
+
finishReason: result.finishReason,
|
|
116
|
+
usage: result.usage
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Stream a response with real-time updates.
|
|
121
|
+
*/
|
|
122
|
+
async stream(params) {
|
|
123
|
+
const sessionId = params.options?.sessionId ?? generateSessionId();
|
|
124
|
+
const prompt = params.systemOverride ? `${this.instructions}\n\n${params.systemOverride}\n\n${params.prompt}` : params.prompt;
|
|
125
|
+
return this.inner.stream({
|
|
126
|
+
prompt,
|
|
127
|
+
abortSignal: params.signal,
|
|
128
|
+
options: {
|
|
129
|
+
tenantId: params.options?.tenantId,
|
|
130
|
+
actorId: params.options?.actorId,
|
|
131
|
+
sessionId,
|
|
132
|
+
metadata: params.options?.metadata
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Handle step completion for persistence and telemetry.
|
|
138
|
+
*/
|
|
139
|
+
async handleStepFinish(step) {
|
|
140
|
+
const sessionId = step.options?.sessionId;
|
|
141
|
+
if (sessionId && this.config.sessionStore) await this.config.sessionStore.appendStep(sessionId, step);
|
|
142
|
+
if (this.config.telemetryCollector) await trackAgentStep(this.config.telemetryCollector, this.id, step);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
//#endregion
|
|
147
|
+
export { ContractSpecAgent };
|
|
148
|
+
//# sourceMappingURL=contract-spec-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-spec-agent.js","names":["z","ToolLoopAgent"],"sources":["../../src/agent/contract-spec-agent.ts"],"sourcesContent":["import {\n Experimental_Agent as ToolLoopAgent,\n type LanguageModel,\n stepCountIs,\n type StepResult,\n type Tool,\n type ToolSet,\n} from 'ai';\nimport * as z from 'zod';\nimport type { KnowledgeRetriever } from '@contractspec/lib.knowledge/retriever';\nimport type { AgentSpec } from '../spec/spec';\nimport { agentKey } from '../spec/spec';\nimport type {\n AgentCallOptions,\n AgentGenerateParams,\n AgentGenerateResult,\n AgentStreamParams,\n ToolHandler,\n} from '../types';\nimport { specToolsToAISDKTools } from '../tools/tool-adapter';\nimport { createKnowledgeQueryTool } from '../tools/knowledge-tool';\nimport { injectStaticKnowledge } from '../knowledge/injector';\nimport { type AgentSessionStore, generateSessionId } from '../session/store';\nimport { type TelemetryCollector, trackAgentStep } from '../telemetry/adapter';\n\n/**\n * Call options schema for AI SDK v6.\n * Maps ContractSpec's tenant/actor system to AI SDK callOptionsSchema.\n */\nconst ContractSpecCallOptionsSchema = z.object({\n tenantId: z.string().optional(),\n actorId: z.string().optional(),\n sessionId: z.string().optional(),\n // Zod v4: z.record() requires both key and value schemas\n metadata: z.record(z.string(), z.unknown()).optional(),\n});\n\n/**\n * Type for tool with execute function (compatible with AI SDK Tool)\n * Using `any` for broad compatibility with AI SDK tool types\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype ExecutableTool = Tool<any, any>;\n\n/**\n * Configuration for creating a ContractSpecAgent.\n */\nexport interface ContractSpecAgentConfig {\n /** The agent specification */\n spec: AgentSpec;\n /** AI SDK language model */\n model: LanguageModel;\n /** Map of tool name to handler function */\n toolHandlers: Map<string, ToolHandler>;\n /** Optional knowledge retriever for RAG */\n knowledgeRetriever?: KnowledgeRetriever;\n /** Optional session store for persistence */\n sessionStore?: AgentSessionStore;\n /** Optional telemetry collector for evolution */\n telemetryCollector?: TelemetryCollector;\n /** Additional AI SDK tools (e.g., from MCP servers) */\n additionalTools?: Record<string, ExecutableTool>;\n}\n\n/**\n * ContractSpec Agent implementation using AI SDK v6.\n *\n * Integrates ContractSpec's spec-first governance with AI SDK's\n * ToolLoopAgent, providing:\n * - Spec-defined tools with type-safe handlers\n * - Hybrid knowledge injection (static + dynamic RAG)\n * - Session persistence\n * - Telemetry for evolution\n * - MCP interoperability\n */\nexport class ContractSpecAgent {\n readonly version = 'agent-v1';\n readonly id: string;\n readonly spec: AgentSpec;\n readonly tools: Record<string, ExecutableTool>;\n\n private readonly inner: ToolLoopAgent<\n z.infer<typeof ContractSpecCallOptionsSchema>,\n ToolSet,\n never\n >;\n private readonly config: ContractSpecAgentConfig;\n private instructions: string;\n\n private constructor(\n config: ContractSpecAgentConfig,\n instructions: string,\n tools: Record<string, ExecutableTool>\n ) {\n this.config = config;\n this.spec = config.spec;\n this.id = agentKey(config.spec.meta);\n this.tools = tools;\n this.instructions = instructions;\n\n // Create the inner ToolLoopAgent with AI SDK v6 settings\n this.inner = new ToolLoopAgent({\n model: config.model,\n instructions,\n tools: tools as ToolSet,\n // Use stopWhen instead of maxSteps (AI SDK v6 API)\n stopWhen: stepCountIs(config.spec.maxSteps ?? 10),\n // Schema for call options (tenant/actor context)\n callOptionsSchema: ContractSpecCallOptionsSchema,\n // Step-level telemetry callback\n onStepFinish: async (step: StepResult<ToolSet>) => {\n await this.handleStepFinish(step);\n },\n });\n }\n\n /**\n * Create a ContractSpecAgent instance.\n * This is async because knowledge injection may need to fetch static content.\n */\n static async create(\n config: ContractSpecAgentConfig\n ): Promise<ContractSpecAgent> {\n // 1. Inject static knowledge into instructions\n const instructions = await injectStaticKnowledge(\n config.spec.instructions,\n config.spec.knowledge ?? [],\n config.knowledgeRetriever\n );\n\n // 2. Build tools from spec\n const specTools = specToolsToAISDKTools(\n config.spec.tools,\n config.toolHandlers,\n { agentId: agentKey(config.spec.meta) }\n );\n\n // 3. Add dynamic knowledge query tool\n const knowledgeTool = config.knowledgeRetriever\n ? createKnowledgeQueryTool(\n config.knowledgeRetriever,\n config.spec.knowledge ?? []\n )\n : null;\n\n // 4. Combine all tools\n const tools: Record<string, ExecutableTool> = {\n ...specTools,\n ...(knowledgeTool ? { query_knowledge: knowledgeTool } : {}),\n ...(config.additionalTools ?? {}),\n };\n\n return new ContractSpecAgent(config, instructions, tools);\n }\n\n /**\n * Generate a response (non-streaming).\n */\n async generate(params: AgentGenerateParams): Promise<AgentGenerateResult> {\n const sessionId = params.options?.sessionId ?? generateSessionId();\n\n // Ensure session exists\n if (this.config.sessionStore) {\n const existing = await this.config.sessionStore.get(sessionId);\n if (!existing) {\n await this.config.sessionStore.create({\n sessionId,\n agentId: this.id,\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n status: 'running',\n messages: [],\n steps: [],\n metadata: params.options?.metadata,\n });\n }\n }\n\n // Build prompt with optional system override\n const prompt = params.systemOverride\n ? `${this.instructions}\\n\\n${params.systemOverride}\\n\\n${params.prompt}`\n : params.prompt;\n\n // AI SDK v6: maxSteps is controlled via stopWhen in agent settings\n const result = await this.inner.generate({\n prompt,\n abortSignal: params.signal,\n options: {\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n sessionId,\n metadata: params.options?.metadata,\n },\n });\n\n // Update session status\n if (this.config.sessionStore) {\n await this.config.sessionStore.update(sessionId, {\n status: 'completed',\n });\n }\n\n return {\n text: result.text,\n steps: result.steps,\n // Map AI SDK types to our simplified types\n toolCalls: result.toolCalls.map((tc) => ({\n type: 'tool-call' as const,\n toolCallId: tc.toolCallId,\n toolName: tc.toolName,\n args: 'args' in tc ? tc.args : 'input' in tc ? tc.input : undefined,\n })),\n toolResults: result.toolResults.map((tr) => ({\n type: 'tool-result' as const,\n toolCallId: tr.toolCallId,\n toolName: tr.toolName,\n output: tr.output,\n })),\n finishReason: result.finishReason,\n usage: result.usage,\n };\n }\n\n /**\n * Stream a response with real-time updates.\n */\n async stream(params: AgentStreamParams) {\n const sessionId = params.options?.sessionId ?? generateSessionId();\n\n const prompt = params.systemOverride\n ? `${this.instructions}\\n\\n${params.systemOverride}\\n\\n${params.prompt}`\n : params.prompt;\n\n // AI SDK v6: maxSteps is controlled via stopWhen in agent settings\n // onStepFinish callback is already set in agent construction\n return this.inner.stream({\n prompt,\n abortSignal: params.signal,\n options: {\n tenantId: params.options?.tenantId,\n actorId: params.options?.actorId,\n sessionId,\n metadata: params.options?.metadata,\n },\n });\n }\n\n /**\n * Handle step completion for persistence and telemetry.\n */\n private async handleStepFinish(step: StepResult<ToolSet>): Promise<void> {\n // 1. Persist to session store\n const sessionId = (step as { options?: AgentCallOptions }).options\n ?.sessionId;\n if (sessionId && this.config.sessionStore) {\n await this.config.sessionStore.appendStep(sessionId, step);\n }\n\n // 2. Feed telemetry to evolution engine\n if (this.config.telemetryCollector) {\n await trackAgentStep(this.config.telemetryCollector, this.id, step);\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { ContractSpecAgent, ContractSpecAgentConfig } from "./contract-spec-agent.js";
|
|
2
|
+
import { UnifiedAgent, UnifiedAgentBackend, UnifiedAgentBackendConfig, UnifiedAgentConfig, UnifiedAgentRunOptions, UnifiedAgentState, createAISDKAgent, createClaudeAgentSDKAgent, createOpenCodeSDKAgent, createUnifiedAgent, getAvailableBackends } from "./unified-agent.js";
|
|
3
|
+
export { ContractSpecAgent, ContractSpecAgentConfig, UnifiedAgent, UnifiedAgentBackend, UnifiedAgentBackendConfig, UnifiedAgentConfig, UnifiedAgentRunOptions, UnifiedAgentState, createAISDKAgent, createClaudeAgentSDKAgent, createOpenCodeSDKAgent, createUnifiedAgent, getAvailableBackends };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { ContractSpecAgent } from "./contract-spec-agent.js";
|
|
2
|
+
import { UnifiedAgent, createAISDKAgent, createClaudeAgentSDKAgent, createOpenCodeSDKAgent, createUnifiedAgent, getAvailableBackends } from "./unified-agent.js";
|
|
3
|
+
|
|
4
|
+
export { ContractSpecAgent, UnifiedAgent, createAISDKAgent, createClaudeAgentSDKAgent, createOpenCodeSDKAgent, createUnifiedAgent, getAvailableBackends };
|