@contractspec/lib.ai-agent 3.0.0 → 3.2.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.
Files changed (56) hide show
  1. package/README.md +14 -2
  2. package/dist/agent/agent-factory.d.ts +3 -0
  3. package/dist/agent/agent-factory.js +209 -27
  4. package/dist/agent/contract-spec-agent.d.ts +3 -0
  5. package/dist/agent/contract-spec-agent.js +207 -26
  6. package/dist/agent/index.js +218 -29
  7. package/dist/agent/json-runner.d.ts +3 -0
  8. package/dist/agent/json-runner.js +214 -28
  9. package/dist/agent/unified-agent.d.ts +3 -0
  10. package/dist/agent/unified-agent.js +211 -27
  11. package/dist/exporters/claude-agent-exporter.js +5 -0
  12. package/dist/exporters/index.js +5 -0
  13. package/dist/exporters/opencode-exporter.js +5 -0
  14. package/dist/index.js +5 -0
  15. package/dist/interop/index.d.ts +1 -0
  16. package/dist/interop/index.js +5 -0
  17. package/dist/interop/runtime-adapters.d.ts +36 -0
  18. package/dist/interop/runtime-adapters.js +1 -0
  19. package/dist/interop/spec-consumer.js +5 -0
  20. package/dist/node/agent/agent-factory.js +209 -27
  21. package/dist/node/agent/contract-spec-agent.js +207 -26
  22. package/dist/node/agent/index.js +218 -29
  23. package/dist/node/agent/json-runner.js +214 -28
  24. package/dist/node/agent/unified-agent.js +211 -27
  25. package/dist/node/exporters/claude-agent-exporter.js +5 -0
  26. package/dist/node/exporters/index.js +5 -0
  27. package/dist/node/exporters/opencode-exporter.js +5 -0
  28. package/dist/node/index.js +5 -0
  29. package/dist/node/interop/index.js +5 -0
  30. package/dist/node/interop/runtime-adapters.js +0 -0
  31. package/dist/node/interop/spec-consumer.js +5 -0
  32. package/dist/node/providers/claude-agent-sdk/adapter.js +5 -0
  33. package/dist/node/providers/claude-agent-sdk/index.js +5 -0
  34. package/dist/node/providers/index.js +5 -0
  35. package/dist/node/providers/opencode-sdk/adapter.js +5 -0
  36. package/dist/node/providers/opencode-sdk/index.js +5 -0
  37. package/dist/node/spec/index.js +5 -0
  38. package/dist/node/spec/spec.js +5 -0
  39. package/dist/node/tools/index.js +86 -10
  40. package/dist/node/tools/tool-adapter.js +86 -10
  41. package/dist/providers/claude-agent-sdk/adapter.js +5 -0
  42. package/dist/providers/claude-agent-sdk/index.js +5 -0
  43. package/dist/providers/index.js +5 -0
  44. package/dist/providers/opencode-sdk/adapter.js +5 -0
  45. package/dist/providers/opencode-sdk/index.js +5 -0
  46. package/dist/spec/index.js +5 -0
  47. package/dist/spec/spec.d.ts +27 -0
  48. package/dist/spec/spec.js +5 -0
  49. package/dist/spec/spec.test.d.ts +1 -0
  50. package/dist/tools/index.js +86 -10
  51. package/dist/tools/mcp-client.d.ts +6 -0
  52. package/dist/tools/mcp-server.d.ts +4 -0
  53. package/dist/tools/tool-adapter.js +86 -10
  54. package/dist/tools/tool-adapter.test.d.ts +1 -0
  55. package/dist/types.d.ts +15 -0
  56. package/package.json +26 -14
@@ -2263,21 +2263,39 @@ var init_json_schema_to_zod = () => {};
2263
2263
  // src/tools/tool-adapter.ts
2264
2264
  import { tool } from "ai";
2265
2265
  function specToolToAISDKTool(specTool, handler, context = {}) {
2266
+ let lastInvocationAt;
2266
2267
  return tool({
2267
2268
  description: specTool.description ?? specTool.name,
2268
2269
  inputSchema: jsonSchemaToZodSafe(specTool.schema),
2269
2270
  needsApproval: specTool.requiresApproval ?? !specTool.automationSafe,
2270
2271
  execute: async (input) => {
2271
- const result = await handler(input, {
2272
- agentId: context.agentId ?? "unknown",
2273
- sessionId: context.sessionId ?? "unknown",
2274
- tenantId: context.tenantId,
2275
- actorId: context.actorId,
2276
- locale: context.locale,
2277
- metadata: context.metadata,
2278
- signal: context.signal
2279
- });
2280
- return typeof result === "string" ? result : JSON.stringify(result);
2272
+ const now = Date.now();
2273
+ const cooldownMs = normalizeDuration(specTool.cooldownMs);
2274
+ if (cooldownMs && lastInvocationAt !== undefined) {
2275
+ const elapsed = now - lastInvocationAt;
2276
+ if (elapsed < cooldownMs) {
2277
+ const retryAfterMs = cooldownMs - elapsed;
2278
+ throw createToolExecutionError(`Tool "${specTool.name}" is cooling down. Retry in ${retryAfterMs}ms.`, "TOOL_COOLDOWN_ACTIVE", retryAfterMs);
2279
+ }
2280
+ }
2281
+ const timeoutMs = normalizeDuration(specTool.timeoutMs);
2282
+ const { signal, dispose } = createTimeoutSignal(context.signal, timeoutMs);
2283
+ try {
2284
+ const execution = handler(input, {
2285
+ agentId: context.agentId ?? "unknown",
2286
+ sessionId: context.sessionId ?? "unknown",
2287
+ tenantId: context.tenantId,
2288
+ actorId: context.actorId,
2289
+ locale: context.locale,
2290
+ metadata: context.metadata,
2291
+ signal
2292
+ });
2293
+ const result = timeoutMs ? await withTimeout(execution, timeoutMs, specTool.name) : await execution;
2294
+ return typeof result === "string" ? result : JSON.stringify(result);
2295
+ } finally {
2296
+ dispose();
2297
+ lastInvocationAt = Date.now();
2298
+ }
2281
2299
  }
2282
2300
  });
2283
2301
  }
@@ -2302,6 +2320,64 @@ function createToolHandler(handler) {
2302
2320
  function buildToolHandlers(handlersObj) {
2303
2321
  return new Map(Object.entries(handlersObj));
2304
2322
  }
2323
+ function normalizeDuration(value) {
2324
+ if (value === undefined) {
2325
+ return;
2326
+ }
2327
+ if (!Number.isFinite(value)) {
2328
+ return;
2329
+ }
2330
+ if (value <= 0) {
2331
+ return;
2332
+ }
2333
+ return Math.round(value);
2334
+ }
2335
+ function withTimeout(execution, timeoutMs, toolName) {
2336
+ return new Promise((resolve, reject) => {
2337
+ const timeoutHandle = setTimeout(() => {
2338
+ reject(createToolExecutionError(`Tool "${toolName}" timed out after ${timeoutMs}ms.`, "TOOL_EXECUTION_TIMEOUT"));
2339
+ }, timeoutMs);
2340
+ execution.then((result) => {
2341
+ clearTimeout(timeoutHandle);
2342
+ resolve(result);
2343
+ }).catch((error) => {
2344
+ clearTimeout(timeoutHandle);
2345
+ reject(error);
2346
+ });
2347
+ });
2348
+ }
2349
+ function createTimeoutSignal(signal, timeoutMs) {
2350
+ const controller = new AbortController;
2351
+ const abortFromSource = () => controller.abort();
2352
+ if (signal) {
2353
+ if (signal.aborted) {
2354
+ controller.abort();
2355
+ } else {
2356
+ signal.addEventListener("abort", abortFromSource);
2357
+ }
2358
+ }
2359
+ const timeoutHandle = timeoutMs !== undefined ? setTimeout(() => {
2360
+ controller.abort();
2361
+ }, timeoutMs) : undefined;
2362
+ return {
2363
+ signal: controller.signal,
2364
+ dispose: () => {
2365
+ if (timeoutHandle !== undefined) {
2366
+ clearTimeout(timeoutHandle);
2367
+ }
2368
+ if (signal) {
2369
+ signal.removeEventListener("abort", abortFromSource);
2370
+ }
2371
+ }
2372
+ };
2373
+ }
2374
+ function createToolExecutionError(message, code, retryAfterMs) {
2375
+ return Object.assign(new Error(message), {
2376
+ code,
2377
+ kind: "retryable",
2378
+ retryAfterMs
2379
+ });
2380
+ }
2305
2381
  var init_tool_adapter = __esm(() => {
2306
2382
  init_json_schema_to_zod();
2307
2383
  init_i18n();
@@ -0,0 +1 @@
1
+ export {};
package/dist/types.d.ts CHANGED
@@ -36,6 +36,13 @@ export interface AgentMessage {
36
36
  export type AgentStatus = 'idle' | 'running' | 'waiting' | 'completed' | 'failed' | 'escalated';
37
37
  export type AgentEventName = 'agent.session.created' | 'agent.session.updated' | 'agent.step.started' | 'agent.step.completed' | 'agent.tool.called' | 'agent.tool.completed' | 'agent.tool.failed' | 'agent.tool.approval_requested' | 'agent.escalated' | 'agent.completed' | 'agent.failed';
38
38
  export type AgentFinishReason = 'stop' | 'tool-calls' | 'length' | 'content-filter' | 'error' | 'other' | 'unknown';
39
+ export type AgentExecutionErrorKind = 'fatal' | 'retryable' | 'timeout' | 'guard_rejected' | 'policy_blocked';
40
+ export interface AgentExecutionError {
41
+ kind: AgentExecutionErrorKind;
42
+ message: string;
43
+ code?: string;
44
+ retryAfterMs?: number;
45
+ }
39
46
  export interface AgentEventPayload {
40
47
  sessionId: string;
41
48
  agentId: string;
@@ -59,6 +66,14 @@ export interface AgentCallOptions {
59
66
  metadata?: Record<string, string>;
60
67
  /** Locale override for this call */
61
68
  locale?: string;
69
+ /** Model selection context for ranking-driven model routing */
70
+ selectionContext?: import('@contractspec/lib.ai-providers/selector-types').ModelSelectionContext;
71
+ /** Transport preference for provider calls. */
72
+ transport?: 'rest' | 'mcp' | 'sdk';
73
+ /** Auth method to use for provider calls. */
74
+ authMethod?: 'api-key' | 'oauth2' | 'bearer';
75
+ /** Custom auth headers for provider calls. */
76
+ authHeaders?: Record<string, string>;
62
77
  }
63
78
  export interface AgentSessionState {
64
79
  sessionId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.ai-agent",
3
- "version": "3.0.0",
3
+ "version": "3.2.0",
4
4
  "description": "AI agent orchestration with MCP and tool support",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -33,18 +33,18 @@
33
33
  "typecheck": "tsc --noEmit"
34
34
  },
35
35
  "dependencies": {
36
- "ai": "6.0.103",
37
- "@ai-sdk/mcp": "1.0.21",
38
- "@ai-sdk/anthropic": "3.0.48",
39
- "@ai-sdk/google": "3.0.33",
40
- "@ai-sdk/mistral": "3.0.20",
41
- "@ai-sdk/openai": "3.0.36",
36
+ "ai": "6.0.116",
37
+ "@ai-sdk/mcp": "1.0.25",
38
+ "@ai-sdk/anthropic": "3.0.58",
39
+ "@ai-sdk/google": "3.0.43",
40
+ "@ai-sdk/mistral": "3.0.24",
41
+ "@ai-sdk/openai": "3.0.41",
42
42
  "@modelcontextprotocol/sdk": "^1.27.1",
43
- "@posthog/react": "^1.8.1",
44
- "@posthog/ai": "latest",
45
- "@contractspec/lib.contracts-spec": "3.0.0",
46
- "@contractspec/lib.ai-providers": "3.0.0",
47
- "@contractspec/lib.knowledge": "3.0.0",
43
+ "@posthog/react": "^1.8.2",
44
+ "@posthog/ai": "7.9.5",
45
+ "@contractspec/lib.contracts-spec": "3.2.0",
46
+ "@contractspec/lib.ai-providers": "3.2.0",
47
+ "@contractspec/lib.knowledge": "3.2.0",
48
48
  "compare-versions": "^6.1.1",
49
49
  "zod": "^4.3.5"
50
50
  },
@@ -68,9 +68,9 @@
68
68
  }
69
69
  },
70
70
  "devDependencies": {
71
- "@contractspec/tool.typescript": "3.0.0",
71
+ "@contractspec/tool.typescript": "3.2.0",
72
72
  "typescript": "^5.9.3",
73
- "@contractspec/tool.bun": "3.0.0"
73
+ "@contractspec/tool.bun": "3.2.0"
74
74
  },
75
75
  "exports": {
76
76
  ".": {
@@ -235,6 +235,12 @@
235
235
  "node": "./dist/node/interop/index.js",
236
236
  "default": "./dist/interop/index.js"
237
237
  },
238
+ "./interop/runtime-adapters": {
239
+ "types": "./dist/interop/runtime-adapters.d.ts",
240
+ "bun": "./dist/interop/runtime-adapters.js",
241
+ "node": "./dist/node/interop/runtime-adapters.js",
242
+ "default": "./dist/interop/runtime-adapters.js"
243
+ },
238
244
  "./interop/spec-consumer": {
239
245
  "types": "./dist/interop/spec-consumer.d.ts",
240
246
  "bun": "./dist/interop/spec-consumer.js",
@@ -689,6 +695,12 @@
689
695
  "node": "./dist/node/interop/index.js",
690
696
  "default": "./dist/interop/index.js"
691
697
  },
698
+ "./interop/runtime-adapters": {
699
+ "types": "./dist/interop/runtime-adapters.d.ts",
700
+ "bun": "./dist/interop/runtime-adapters.js",
701
+ "node": "./dist/node/interop/runtime-adapters.js",
702
+ "default": "./dist/interop/runtime-adapters.js"
703
+ },
692
704
  "./interop/spec-consumer": {
693
705
  "types": "./dist/interop/spec-consumer.d.ts",
694
706
  "bun": "./dist/interop/spec-consumer.js",