@vorim/sdk 3.6.0 → 3.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/_runtime-gate-DZQTkw4J.d.cts +11 -0
  3. package/dist/_runtime-gate-DZQTkw4J.d.ts +11 -0
  4. package/dist/index.cjs +1 -1
  5. package/dist/index.d.cts +3 -233
  6. package/dist/index.d.ts +3 -233
  7. package/dist/index.js +1 -1
  8. package/dist/integrations/anthropic.cjs +38 -9
  9. package/dist/integrations/anthropic.cjs.map +1 -1
  10. package/dist/integrations/anthropic.d.cts +17 -1
  11. package/dist/integrations/anthropic.d.ts +17 -1
  12. package/dist/integrations/anthropic.js +38 -9
  13. package/dist/integrations/anthropic.js.map +1 -1
  14. package/dist/integrations/crewai.d.cts +2 -1
  15. package/dist/integrations/crewai.d.ts +2 -1
  16. package/dist/integrations/langchain.cjs +9 -10
  17. package/dist/integrations/langchain.cjs.map +1 -1
  18. package/dist/integrations/langchain.d.cts +9 -1
  19. package/dist/integrations/langchain.d.ts +9 -1
  20. package/dist/integrations/langchain.js +9 -10
  21. package/dist/integrations/langchain.js.map +1 -1
  22. package/dist/integrations/langgraph.cjs +200 -0
  23. package/dist/integrations/langgraph.cjs.map +1 -0
  24. package/dist/integrations/langgraph.d.cts +20 -0
  25. package/dist/integrations/langgraph.d.ts +20 -0
  26. package/dist/integrations/langgraph.js +162 -0
  27. package/dist/integrations/langgraph.js.map +1 -0
  28. package/dist/integrations/llamaindex.d.cts +2 -1
  29. package/dist/integrations/llamaindex.d.ts +2 -1
  30. package/dist/integrations/openai.cjs +38 -9
  31. package/dist/integrations/openai.cjs.map +1 -1
  32. package/dist/integrations/openai.d.cts +17 -1
  33. package/dist/integrations/openai.d.ts +17 -1
  34. package/dist/integrations/openai.js +38 -9
  35. package/dist/integrations/openai.js.map +1 -1
  36. package/dist/integrations/siem.cjs +128 -0
  37. package/dist/integrations/siem.cjs.map +1 -0
  38. package/dist/integrations/siem.d.cts +57 -0
  39. package/dist/integrations/siem.d.ts +57 -0
  40. package/dist/integrations/siem.js +102 -0
  41. package/dist/integrations/siem.js.map +1 -0
  42. package/dist/integrations/stripe-acp.cjs +179 -0
  43. package/dist/integrations/stripe-acp.cjs.map +1 -0
  44. package/dist/integrations/stripe-acp.d.cts +69 -0
  45. package/dist/integrations/stripe-acp.d.ts +69 -0
  46. package/dist/integrations/stripe-acp.js +153 -0
  47. package/dist/integrations/stripe-acp.js.map +1 -0
  48. package/dist/integrations/vercel-ai.cjs +252 -0
  49. package/dist/integrations/vercel-ai.cjs.map +1 -0
  50. package/dist/integrations/vercel-ai.d.cts +67 -0
  51. package/dist/integrations/vercel-ai.d.ts +67 -0
  52. package/dist/integrations/vercel-ai.js +214 -0
  53. package/dist/integrations/vercel-ai.js.map +1 -0
  54. package/dist/types-B22WnXEW.d.cts +234 -0
  55. package/dist/types-B22WnXEW.d.ts +234 -0
  56. package/package.json +41 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/integrations/anthropic.ts","../../src/replay.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — Anthropic/Claude Integration\n// Wraps Anthropic tool use with Vorim permission checks, audit trails,\n// and agent identity. Works with the Anthropic Node.js SDK (messages API\n// with tool use).\n//\n// Peer dependency: @anthropic-ai/sdk >=0.30.0\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { PermissionScope, AuditEventInput } from '../types.js';\nimport {\n prepareReplayContext,\n type ReplayInputs,\n type ReplayContext,\n type CatalogueTool,\n} from '../replay.js';\n\n// ─── Re-declared Anthropic types (peer dependency — not bundled) ──────────\n\ninterface AnthropicTool {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\ninterface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\n// ─── Configuration ────────────────────────────────────────────────────────\n\nexport interface VorimToolDefinition<TArgs = Record<string, unknown>, TResult = unknown> {\n /** Tool name (must match the tool name sent to Claude). */\n name: string;\n /** Description shown to Claude. */\n description: string;\n /** JSON Schema for the tool's input. */\n input_schema: Record<string, unknown>;\n /** The function to execute when the tool is called. */\n execute: (args: TArgs) => Promise<TResult>;\n /** Vorim permission scope required. @default 'agent:execute' */\n permission?: PermissionScope;\n}\n\nexport interface VorimAnthropicConfig {\n /** Vorim SDK instance. */\n vorim: VorimSDK;\n /** The Vorim agent_id. */\n agentId: string;\n /** Default permission scope for tools without an explicit one. @default 'agent:execute' */\n defaultPermission?: PermissionScope;\n /** Whether to emit audit events asynchronously (fire-and-forget). @default true */\n asyncAudit?: boolean;\n /**\n * Gate each tool call through the runtime-control decision API\n * (`beforeAction`) instead of the lightweight permission check. @default false\n *\n * When true, tool calls are evaluated against live policy rules and the\n * returned decisionId is linked onto each audit event's decision_id.\n * Requires the runtime_control plan feature (Growth+) and consumes decision\n * quota. When false (default) the fast permission check is used.\n */\n useRuntimeControl?: boolean;\n /**\n * Replayable agent decision evidence (VAIP -02). Hashes attached to\n * every audit event. If `replay.tools` is omitted, the registry's\n * own tool list is used automatically. Not covered by v0 canonical\n * signature form.\n */\n replay?: ReplayInputs;\n}\n\n// ─── Tool Registry ────────────────────────────────────────────────────────\n\n/**\n * Manages a set of tools with Vorim permission checks and audit logging.\n * Converts tools to Anthropic's tool format and handles execution of\n * tool_use blocks from Claude's response.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const vorim = createVorim({ apiKey: \"agid_sk_live_...\" });\n * const anthropic = new Anthropic();\n *\n * const registry = new VorimToolRegistry({\n * vorim,\n * agentId: \"agid_acme_a1b2c3d4\",\n * });\n *\n * registry.add({\n * name: \"search_docs\",\n * description: \"Search internal documents\",\n * input_schema: {\n * type: \"object\",\n * properties: { query: { type: \"string\" } },\n * required: [\"query\"],\n * },\n * execute: async ({ query }) => searchDocs(query),\n * permission: \"agent:read\",\n * });\n *\n * const response = await anthropic.messages.create({\n * model: \"claude-sonnet-4-20250514\",\n * max_tokens: 1024,\n * messages,\n * tools: registry.toAnthropicTools(),\n * });\n *\n * // Execute tool_use blocks from response\n * const toolResults = await registry.executeToolUseBlocks(\n * response.content.filter(b => b.type === \"tool_use\")\n * );\n * ```\n */\nexport class VorimToolRegistry {\n private vorim: VorimSDK;\n private agentId: string;\n private defaultPermission: PermissionScope;\n private asyncAudit: boolean;\n private useRuntimeControl: boolean;\n private tools = new Map<string, VorimToolDefinition>();\n private replayInputs: ReplayInputs | undefined;\n private replayCache: Promise<ReplayContext> | null = null;\n\n constructor(config: VorimAnthropicConfig) {\n this.vorim = config.vorim;\n this.agentId = config.agentId;\n this.defaultPermission = config.defaultPermission ?? 'agent:execute';\n this.asyncAudit = config.asyncAudit ?? true;\n this.useRuntimeControl = config.useRuntimeControl ?? false;\n this.replayInputs = config.replay;\n }\n\n /** Gate a tool call: runtime decision (with decisionId) or permission check. */\n private async gate(\n scope: PermissionScope,\n actionTarget: string,\n payload?: Record<string, unknown>,\n ): Promise<{ allowed: boolean; reason?: string; decisionId?: string }> {\n if (this.useRuntimeControl) {\n const d = await this.vorim.beforeAction(\n { agentId: this.agentId, actionType: 'tool_call', actionTarget, requiredScope: scope, payload },\n { throwOnDeny: false },\n );\n return {\n allowed: d.decision === 'allow' || d.decision === 'modify' || d.decision === 'fallback',\n reason: d.reason,\n decisionId: d.decisionId || undefined,\n };\n }\n const { allowed, reason } = await this.vorim.check(this.agentId, scope);\n return { allowed, reason };\n }\n\n private async getReplayContext(): Promise<ReplayContext> {\n if (!this.replayInputs) return {};\n if (!this.replayCache) {\n const inputs: ReplayInputs = {\n ...this.replayInputs,\n tools: this.replayInputs.tools ?? this.deriveCatalogue(),\n };\n this.replayCache = prepareReplayContext(inputs);\n }\n return this.replayCache;\n }\n\n private deriveCatalogue(): CatalogueTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n schema: t.input_schema,\n }));\n }\n\n /** Register a tool. Invalidates the cached tool-catalogue hash. */\n add<TArgs, TResult>(definition: VorimToolDefinition<TArgs, TResult>): this {\n this.tools.set(definition.name, definition as VorimToolDefinition);\n this.replayCache = null;\n return this;\n }\n\n /** Register multiple tools. */\n addAll(definitions: VorimToolDefinition[]): this {\n for (const def of definitions) this.add(def);\n return this;\n }\n\n /** Convert registered tools to Anthropic's tool format. */\n toAnthropicTools(): AnthropicTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema,\n }));\n }\n\n /**\n * Execute tool_use blocks from a Claude message response.\n * Each call is checked against Vorim permissions and audited.\n * Returns an array of tool_result blocks ready to send back to Claude.\n */\n async executeToolUseBlocks(toolUseBlocks: ToolUseBlock[]): Promise<ToolResultBlock[]> {\n return Promise.all(\n toolUseBlocks.map(block => this.executeSingleBlock(block)),\n );\n }\n\n private async executeSingleBlock(block: ToolUseBlock): Promise<ToolResultBlock> {\n const definition = this.tools.get(block.name);\n\n if (!definition) {\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Unknown tool: ${block.name}` }),\n is_error: true,\n };\n }\n\n const scope = definition.permission ?? this.defaultPermission;\n\n // 1. Gate: runtime decision (with decisionId linkage) or permission check.\n const { allowed, reason, decisionId } = await this.gate(scope, block.name, block.input as Record<string, unknown>);\n const replayCtx = await this.getReplayContext();\n\n if (!allowed) {\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'denied',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { reason, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Permission denied: ${scope}${reason ? ` — ${reason}` : ''}` }),\n is_error: true,\n };\n }\n\n // 2. Execute\n const start = Date.now();\n try {\n const result = await definition.execute(block.input as any);\n const content = typeof result === 'string' ? result : JSON.stringify(result);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'success',\n latency_ms: Date.now() - start,\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return { type: 'tool_result', tool_use_id: block.id, content };\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'error',\n latency_ms: Date.now() - start,\n error_code: err instanceof Error ? err.name : 'UNKNOWN',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { error: errMsg, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: errMsg }),\n is_error: true,\n };\n }\n }\n\n private emitAudit(event: AuditEventInput): void {\n this.vorim.emit(event).catch(() => {});\n }\n}\n\n// ─── Agent Loop ───────────────────────────────────────────────────────────\n\n/** Minimal Anthropic client interface (avoids importing the full SDK). */\ninterface AnthropicClient {\n messages: {\n create(params: any): Promise<any>;\n };\n}\n\nexport interface VorimAgentLoopConfig extends VorimAnthropicConfig {\n /** Anthropic client instance. */\n anthropic: AnthropicClient;\n /** Model to use. @default 'claude-sonnet-4-20250514' */\n model?: string;\n /** System prompt for the agent. */\n systemPrompt?: string;\n /** Maximum tool-use iterations before stopping. @default 10 */\n maxIterations?: number;\n /** Max tokens per response. @default 1024 */\n maxTokens?: number;\n}\n\n/**\n * Runs a complete agent loop with Claude tool use, Vorim\n * permission enforcement, and audit logging.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { runAgentLoop, VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const registry = new VorimToolRegistry({ vorim, agentId });\n * registry.add({ name: \"search\", ... });\n *\n * const response = await runAgentLoop({\n * vorim,\n * agentId,\n * anthropic: new Anthropic(),\n * model: \"claude-sonnet-4-20250514\",\n * systemPrompt: \"You are a helpful assistant.\",\n * registry,\n * userMessage: \"Find docs about onboarding\",\n * });\n * ```\n */\nexport async function runAgentLoop(\n config: VorimAgentLoopConfig & {\n registry: VorimToolRegistry;\n userMessage: string;\n },\n): Promise<string> {\n const {\n anthropic,\n model = 'claude-sonnet-4-20250514',\n systemPrompt,\n maxIterations = 10,\n maxTokens = 1024,\n registry,\n userMessage,\n } = config;\n\n const tools = registry.toAnthropicTools();\n const messages: any[] = [{ role: 'user', content: userMessage }];\n\n for (let i = 0; i < maxIterations; i++) {\n const response = await anthropic.messages.create({\n model,\n max_tokens: maxTokens,\n ...(systemPrompt ? { system: systemPrompt } : {}),\n messages,\n ...(tools.length > 0 ? { tools } : {}),\n });\n\n // If stop_reason is \"end_turn\" — Claude is done\n if (response.stop_reason === 'end_turn' || response.stop_reason !== 'tool_use') {\n const textBlocks = response.content.filter((b: any) => b.type === 'text');\n return textBlocks.map((b: any) => b.text).join('') || '';\n }\n\n // Extract tool_use blocks and execute\n const toolUseBlocks = response.content.filter((b: any) => b.type === 'tool_use');\n const toolResults = await registry.executeToolUseBlocks(toolUseBlocks);\n\n // Append assistant response and tool results to conversation\n messages.push({ role: 'assistant', content: response.content });\n messages.push({ role: 'user', content: toolResults });\n }\n\n return '';\n}\n\n// ─── Agent Registration Helper ───────────────────────────────────────────\n\n/**\n * Registers a new agent with Vorim and returns a ready-to-use tool registry\n * configured for Anthropic/Claude.\n *\n * @example\n * ```ts\n * const { agentId, registry } = await createVorimClaudeAgent({\n * vorim,\n * name: \"claude-assistant\",\n * capabilities: [\"search\", \"calculate\"],\n * scopes: [\"agent:read\", \"agent:execute\"],\n * tools: [searchTool, calcTool],\n * });\n * ```\n */\nexport async function createVorimClaudeAgent(config: {\n vorim: VorimSDK;\n name: string;\n description?: string;\n capabilities: string[];\n scopes: PermissionScope[];\n tools: VorimToolDefinition[];\n}) {\n const { vorim, name, description, capabilities, scopes, tools } = config;\n\n const registration = await vorim.register({\n name,\n description,\n capabilities,\n scopes,\n });\n\n const agentId = registration.agent.agent_id;\n const registry = new VorimToolRegistry({ vorim, agentId });\n registry.addAll(tools);\n\n return {\n agentId,\n registration,\n registry,\n privateKey: registration.private_key,\n };\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────\n\nfunction truncate(str: string, max: number): string {\n return str.length > max ? str.slice(0, max) + '…' : str;\n}\n","/**\n * Replayable agent decision evidence helpers.\n *\n * Canonical-form hashing for the VAIP -02 schema fields that the SDK\n * attaches to audit events. The hashes recorded in audit_events.tool_catalogue_hash\n * and audit_events.system_prompt_hash use these functions, so the bytes\n * an auditor or counterparty reconstructs must match what the SDK produced.\n *\n * These helpers are intentionally separate from the signing path. The\n * v0 canonical signature form (event_type|action|resource|input_hash|\n * output_hash|result) does NOT cover model_version, tool_catalogue_hash,\n * or system_prompt_hash. They will enter the canonical bytes in v1\n * (RFC 8785 JCS) in a follow-up release.\n *\n * Stable across SDK versions: the canonical-form version is documented\n * in CANONICAL_TOOL_CATALOGUE_VERSION. Future changes get a v2 etc;\n * never edit the existing v1 logic, or already-recorded hashes lose\n * their meaning.\n */\n\n// ─── Versioning ───────────────────────────────────────────────────────────\n\n/**\n * Canonical-form version for tool catalogue hashes produced by this SDK.\n * Recorded in tool_catalogue_canon_version on the event metadata (when\n * the metadata field is used) so verifiers know which hash recipe to\n * reproduce. Increment ONLY if the algorithm changes in a way that\n * would change the hash for the same logical catalogue.\n */\nexport const CANONICAL_TOOL_CATALOGUE_VERSION = 'v1' as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * Minimum shape a tool needs for catalogue hashing. The framework\n * integrations adapt their native tool objects to this shape before\n * calling hashToolCatalogue.\n */\nexport interface CatalogueTool {\n /** The name the model sees and calls. Required. */\n name: string;\n /** Human-readable description shown to the model. Optional; absent ↔ empty string. */\n description?: string;\n /**\n * JSON Schema describing the tool's input parameters. Optional;\n * absent ↔ empty object `{}`. The schema gets RFC 8785 JCS-canonicalised\n * before hashing so semantically-equivalent variations (key order,\n * whitespace) produce the same hash.\n */\n schema?: Record<string, unknown> | null;\n}\n\n// ─── RFC 8785 JCS subset ──────────────────────────────────────────────────\n\n/**\n * RFC 8785 JSON Canonicalization Scheme, sufficient subset for tool\n * catalogue values.\n *\n * Rules:\n * - Object keys sorted lexicographically by UTF-16 code units (which\n * is what JS string comparison does naturally).\n * - No whitespace between tokens.\n * - Numbers: integers as integers, finite floats per ECMAScript\n * Number.prototype.toString. JCS forbids NaN and Infinity.\n * - Strings: JSON-escape using minimal set per RFC 8259 § 7.\n * - null, true, false, arrays: as JSON.stringify produces them, since\n * JSON.stringify already produces the canonical form for these.\n *\n * Not vendoring a full library because tool schemas don't carry\n * non-integer numbers in practice and the JS spec for Number.toString\n * happens to coincide with JCS § 3.2.2.2 for the integer case.\n */\nexport function jcsCanonicalise(value: unknown): string {\n if (value === null) return 'null';\n if (value === true) return 'true';\n if (value === false) return 'false';\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('jcsCanonicalise: NaN and Infinity are not JCS-valid');\n }\n // For integers in safe range, .toString() matches JCS. For\n // non-integer floats, .toString() also matches in modern JS\n // engines (V8, JavaScriptCore, SpiderMonkey all use the shortest\n // round-trip representation, which is what JCS § 3.2.2.2 requires).\n return value.toString();\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return '[' + value.map(jcsCanonicalise).join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // Filter undefined-valued fields, matching @vorim/verify and\n // @vorim/shared-types. Without this the SDK throws on { a: 1, b: undefined }\n // while the verifier silently drops b — a cross-module canonical-form\n // divergence that would break signature verification on such events.\n const keys = Object.keys(obj).filter(k => obj[k] !== undefined).sort();\n const parts = keys.map(k => JSON.stringify(k) + ':' + jcsCanonicalise(obj[k]));\n return '{' + parts.join(',') + '}';\n }\n\n // undefined, function, symbol, bigint — not JSON-representable\n throw new Error(`jcsCanonicalise: unsupported value type: ${typeof value}`);\n}\n\n// ─── SHA-256 ──────────────────────────────────────────────────────────────\n\nasync function sha256Hex(input: string | Uint8Array): Promise<string> {\n const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;\n\n // Node.js Web Crypto (Node 18+) supports digest. Browser Web Crypto does too.\n // Fall back to node:crypto if Web Crypto is unavailable.\n const subtle = (globalThis as any).crypto?.subtle;\n if (subtle) {\n const buf = await subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(buf))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(bytes).digest('hex');\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────\n\n/**\n * Hash a single tool definition. Returns `sha256:<hex>`.\n *\n * Canonical form (v1):\n * JCS-canonicalised JSON of `{name, description, schema}` where\n * absent fields substitute `description: \"\"` and `schema: {}`.\n */\nexport async function hashTool(tool: CatalogueTool): Promise<string> {\n const normalised = {\n name: tool.name,\n description: tool.description ?? '',\n schema: tool.schema ?? {},\n };\n const hex = await sha256Hex(jcsCanonicalise(normalised));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash an entire tool catalogue. Returns `sha256:<hex>`.\n *\n * Reordering tools does NOT change the hash (tool hashes sorted\n * lexicographically before concatenation). Adding, removing, or\n * modifying a tool DOES change the hash.\n *\n * Per-tool hashing first means a verifier comparing two catalogue\n * hashes that differ can also be given the per-tool hashes to\n * identify which specific tool changed.\n */\nexport async function hashToolCatalogue(tools: CatalogueTool[]): Promise<string> {\n if (tools.length === 0) {\n // Empty catalogue has a deterministic, stable hash distinct from \"no field\"\n return `sha256:${await sha256Hex('[]')}`;\n }\n const perTool = await Promise.all(tools.map(hashTool));\n perTool.sort();\n const hex = await sha256Hex(perTool.join(''));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash a system prompt. Returns `sha256:<hex>`.\n *\n * The prompt is UTF-8 encoded and hashed verbatim — no normalisation.\n * If a caller wants to ignore whitespace or comment differences, they\n * should normalise before calling. The intent here is deterministic\n * reproducibility, not semantic equivalence.\n */\nexport async function hashSystemPrompt(prompt: string): Promise<string> {\n const hex = await sha256Hex(prompt);\n return `sha256:${hex}`;\n}\n\n/**\n * Convenience: hash the previous event's canonical bytes for use in\n * the prev_event_hash field of hash-chained ingest. Caller provides\n * the canonical bytes (use canonicalPayloadV0 from the main module).\n */\nexport async function hashPreviousEvent(canonicalBytes: string): Promise<string> {\n const hex = await sha256Hex(canonicalBytes);\n return `sha256:${hex}`;\n}\n\n// ─── Replay context — framework integration helper ────────────────────────\n\n/**\n * Raw inputs the integration captures from the framework. Set by the\n * integration's config; turned into hashes by {@link prepareReplayContext}.\n */\nexport interface ReplayInputs {\n /** Stable identifier for the model. E.g. `\"anthropic:claude-opus-4-8\"`. */\n modelVersion?: string;\n /** Tools available to the agent at call time. Hashed via {@link hashToolCatalogue}. */\n tools?: CatalogueTool[];\n /** System prompt active at call time. Hashed via {@link hashSystemPrompt}. */\n systemPrompt?: string;\n}\n\n/**\n * Pre-computed hashes ready to attach to audit events. The three keys\n * match the audit_events column names.\n */\nexport interface ReplayContext {\n model_version?: string;\n tool_catalogue_hash?: string;\n system_prompt_hash?: string;\n}\n\n/**\n * Compute replay context once from raw inputs. Use at integration\n * setup time so each emit can attach the hashes without re-hashing.\n *\n * Returns an object suitable for spreading into an AuditEventInput:\n * `await vorim.emit({ ...event, ...replayContext })`\n *\n * If a field is absent in the inputs, it is absent in the result\n * (not the empty string). That keeps the event lean.\n */\nexport async function prepareReplayContext(\n inputs: ReplayInputs,\n): Promise<ReplayContext> {\n const ctx: ReplayContext = {};\n if (inputs.modelVersion) ctx.model_version = inputs.modelVersion;\n if (inputs.tools) ctx.tool_catalogue_hash = await hashToolCatalogue(inputs.tools);\n if (inputs.systemPrompt) ctx.system_prompt_hash = await hashSystemPrompt(inputs.systemPrompt);\n return ctx;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/integrations/anthropic.ts","../../src/integrations/_runtime-gate.ts","../../src/replay.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — Anthropic/Claude Integration\n// Wraps Anthropic tool use with Vorim permission checks, audit trails,\n// and agent identity. Works with the Anthropic Node.js SDK (messages API\n// with tool use).\n//\n// Peer dependency: @anthropic-ai/sdk >=0.30.0\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { PermissionScope, AuditEventInput } from '../types.js';\nimport { runtimeGate, type EscalationPolicy } from './_runtime-gate.js';\nimport {\n prepareReplayContext,\n type ReplayInputs,\n type ReplayContext,\n type CatalogueTool,\n} from '../replay.js';\n\n// ─── Re-declared Anthropic types (peer dependency — not bundled) ──────────\n\ninterface AnthropicTool {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\ninterface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\n// ─── Configuration ────────────────────────────────────────────────────────\n\nexport interface VorimToolDefinition<TArgs = Record<string, unknown>, TResult = unknown> {\n /** Tool name (must match the tool name sent to Claude). */\n name: string;\n /** Description shown to Claude. */\n description: string;\n /** JSON Schema for the tool's input. */\n input_schema: Record<string, unknown>;\n /** The function to execute when the tool is called. */\n execute: (args: TArgs) => Promise<TResult>;\n /** Vorim permission scope required. @default 'agent:execute' */\n permission?: PermissionScope;\n}\n\nexport interface VorimAnthropicConfig {\n /** Vorim SDK instance. */\n vorim: VorimSDK;\n /** The Vorim agent_id. */\n agentId: string;\n /** Default permission scope for tools without an explicit one. @default 'agent:execute' */\n defaultPermission?: PermissionScope;\n /** Whether to emit audit events asynchronously (fire-and-forget). @default true */\n asyncAudit?: boolean;\n /**\n * Gate each tool call through the runtime-control decision API\n * (`beforeAction`) instead of the lightweight permission check. @default false\n *\n * When true, tool calls are evaluated against live policy rules and the\n * returned decisionId is linked onto each audit event's decision_id.\n * Requires the runtime_control plan feature (Growth+) and consumes decision\n * quota. When false (default) the fast permission check is used.\n */\n useRuntimeControl?: boolean;\n /**\n * What to do when a runtime decision returns `escalate` (a human must\n * approve). Only applies when `useRuntimeControl` is true.\n * - `wait` (default) block and poll until a human approves/denies, or the\n * timeout elapses (→ deny). Requires the `runtime:decide` scope.\n * - `deny` fail closed without waiting.\n * - `allow` proceed (fail OPEN — dev/trusted use only).\n * @default 'wait'\n */\n onEscalation?: EscalationPolicy;\n /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 */\n escalationTimeoutMs?: number;\n /**\n * Replayable agent decision evidence (VAIP -02). Hashes attached to\n * every audit event. If `replay.tools` is omitted, the registry's\n * own tool list is used automatically. Not covered by v0 canonical\n * signature form.\n */\n replay?: ReplayInputs;\n}\n\n// ─── Tool Registry ────────────────────────────────────────────────────────\n\n/**\n * Manages a set of tools with Vorim permission checks and audit logging.\n * Converts tools to Anthropic's tool format and handles execution of\n * tool_use blocks from Claude's response.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const vorim = createVorim({ apiKey: \"agid_sk_live_...\" });\n * const anthropic = new Anthropic();\n *\n * const registry = new VorimToolRegistry({\n * vorim,\n * agentId: \"agid_acme_a1b2c3d4\",\n * });\n *\n * registry.add({\n * name: \"search_docs\",\n * description: \"Search internal documents\",\n * input_schema: {\n * type: \"object\",\n * properties: { query: { type: \"string\" } },\n * required: [\"query\"],\n * },\n * execute: async ({ query }) => searchDocs(query),\n * permission: \"agent:read\",\n * });\n *\n * const response = await anthropic.messages.create({\n * model: \"claude-sonnet-4-20250514\",\n * max_tokens: 1024,\n * messages,\n * tools: registry.toAnthropicTools(),\n * });\n *\n * // Execute tool_use blocks from response\n * const toolResults = await registry.executeToolUseBlocks(\n * response.content.filter(b => b.type === \"tool_use\")\n * );\n * ```\n */\nexport class VorimToolRegistry {\n private vorim: VorimSDK;\n private agentId: string;\n private defaultPermission: PermissionScope;\n private asyncAudit: boolean;\n private useRuntimeControl: boolean;\n private onEscalation?: EscalationPolicy;\n private escalationTimeoutMs?: number;\n private tools = new Map<string, VorimToolDefinition>();\n private replayInputs: ReplayInputs | undefined;\n private replayCache: Promise<ReplayContext> | null = null;\n\n constructor(config: VorimAnthropicConfig) {\n this.vorim = config.vorim;\n this.agentId = config.agentId;\n this.defaultPermission = config.defaultPermission ?? 'agent:execute';\n this.asyncAudit = config.asyncAudit ?? true;\n this.useRuntimeControl = config.useRuntimeControl ?? false;\n this.onEscalation = config.onEscalation;\n this.escalationTimeoutMs = config.escalationTimeoutMs;\n this.replayInputs = config.replay;\n }\n\n /** Gate a tool call: runtime decision (with decisionId) or permission check. */\n private async gate(\n scope: PermissionScope,\n actionTarget: string,\n payload?: Record<string, unknown>,\n ): Promise<{ allowed: boolean; reason?: string; decisionId?: string }> {\n if (this.useRuntimeControl) {\n return runtimeGate(this.vorim, this.agentId, actionTarget, scope, payload, {\n onEscalation: this.onEscalation,\n escalationTimeoutMs: this.escalationTimeoutMs,\n });\n }\n const { allowed, reason } = await this.vorim.check(this.agentId, scope);\n return { allowed, reason };\n }\n\n private async getReplayContext(): Promise<ReplayContext> {\n if (!this.replayInputs) return {};\n if (!this.replayCache) {\n const inputs: ReplayInputs = {\n ...this.replayInputs,\n tools: this.replayInputs.tools ?? this.deriveCatalogue(),\n };\n this.replayCache = prepareReplayContext(inputs);\n }\n return this.replayCache;\n }\n\n private deriveCatalogue(): CatalogueTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n schema: t.input_schema,\n }));\n }\n\n /** Register a tool. Invalidates the cached tool-catalogue hash. */\n add<TArgs, TResult>(definition: VorimToolDefinition<TArgs, TResult>): this {\n this.tools.set(definition.name, definition as VorimToolDefinition);\n this.replayCache = null;\n return this;\n }\n\n /** Register multiple tools. */\n addAll(definitions: VorimToolDefinition[]): this {\n for (const def of definitions) this.add(def);\n return this;\n }\n\n /** Convert registered tools to Anthropic's tool format. */\n toAnthropicTools(): AnthropicTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema,\n }));\n }\n\n /**\n * Execute tool_use blocks from a Claude message response.\n * Each call is checked against Vorim permissions and audited.\n * Returns an array of tool_result blocks ready to send back to Claude.\n */\n async executeToolUseBlocks(toolUseBlocks: ToolUseBlock[]): Promise<ToolResultBlock[]> {\n return Promise.all(\n toolUseBlocks.map(block => this.executeSingleBlock(block)),\n );\n }\n\n private async executeSingleBlock(block: ToolUseBlock): Promise<ToolResultBlock> {\n const definition = this.tools.get(block.name);\n\n if (!definition) {\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Unknown tool: ${block.name}` }),\n is_error: true,\n };\n }\n\n const scope = definition.permission ?? this.defaultPermission;\n\n // 1. Gate: runtime decision (with decisionId linkage) or permission check.\n const { allowed, reason, decisionId } = await this.gate(scope, block.name, block.input as Record<string, unknown>);\n const replayCtx = await this.getReplayContext();\n\n if (!allowed) {\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'denied',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { reason, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Permission denied: ${scope}${reason ? ` — ${reason}` : ''}` }),\n is_error: true,\n };\n }\n\n // 2. Execute\n const start = Date.now();\n try {\n const result = await definition.execute(block.input as any);\n const content = typeof result === 'string' ? result : JSON.stringify(result);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'success',\n latency_ms: Date.now() - start,\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return { type: 'tool_result', tool_use_id: block.id, content };\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'error',\n latency_ms: Date.now() - start,\n error_code: err instanceof Error ? err.name : 'UNKNOWN',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { error: errMsg, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: errMsg }),\n is_error: true,\n };\n }\n }\n\n private emitAudit(event: AuditEventInput): void {\n this.vorim.emit(event).catch(() => {});\n }\n}\n\n// ─── Agent Loop ───────────────────────────────────────────────────────────\n\n/** Minimal Anthropic client interface (avoids importing the full SDK). */\ninterface AnthropicClient {\n messages: {\n create(params: any): Promise<any>;\n };\n}\n\nexport interface VorimAgentLoopConfig extends VorimAnthropicConfig {\n /** Anthropic client instance. */\n anthropic: AnthropicClient;\n /** Model to use. @default 'claude-sonnet-4-20250514' */\n model?: string;\n /** System prompt for the agent. */\n systemPrompt?: string;\n /** Maximum tool-use iterations before stopping. @default 10 */\n maxIterations?: number;\n /** Max tokens per response. @default 1024 */\n maxTokens?: number;\n}\n\n/**\n * Runs a complete agent loop with Claude tool use, Vorim\n * permission enforcement, and audit logging.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { runAgentLoop, VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const registry = new VorimToolRegistry({ vorim, agentId });\n * registry.add({ name: \"search\", ... });\n *\n * const response = await runAgentLoop({\n * vorim,\n * agentId,\n * anthropic: new Anthropic(),\n * model: \"claude-sonnet-4-20250514\",\n * systemPrompt: \"You are a helpful assistant.\",\n * registry,\n * userMessage: \"Find docs about onboarding\",\n * });\n * ```\n */\nexport async function runAgentLoop(\n config: VorimAgentLoopConfig & {\n registry: VorimToolRegistry;\n userMessage: string;\n },\n): Promise<string> {\n const {\n anthropic,\n model = 'claude-sonnet-4-20250514',\n systemPrompt,\n maxIterations = 10,\n maxTokens = 1024,\n registry,\n userMessage,\n } = config;\n\n const tools = registry.toAnthropicTools();\n const messages: any[] = [{ role: 'user', content: userMessage }];\n\n for (let i = 0; i < maxIterations; i++) {\n const response = await anthropic.messages.create({\n model,\n max_tokens: maxTokens,\n ...(systemPrompt ? { system: systemPrompt } : {}),\n messages,\n ...(tools.length > 0 ? { tools } : {}),\n });\n\n // If stop_reason is \"end_turn\" — Claude is done\n if (response.stop_reason === 'end_turn' || response.stop_reason !== 'tool_use') {\n const textBlocks = response.content.filter((b: any) => b.type === 'text');\n return textBlocks.map((b: any) => b.text).join('') || '';\n }\n\n // Extract tool_use blocks and execute\n const toolUseBlocks = response.content.filter((b: any) => b.type === 'tool_use');\n const toolResults = await registry.executeToolUseBlocks(toolUseBlocks);\n\n // Append assistant response and tool results to conversation\n messages.push({ role: 'assistant', content: response.content });\n messages.push({ role: 'user', content: toolResults });\n }\n\n return '';\n}\n\n// ─── Agent Registration Helper ───────────────────────────────────────────\n\n/**\n * Registers a new agent with Vorim and returns a ready-to-use tool registry\n * configured for Anthropic/Claude.\n *\n * @example\n * ```ts\n * const { agentId, registry } = await createVorimClaudeAgent({\n * vorim,\n * name: \"claude-assistant\",\n * capabilities: [\"search\", \"calculate\"],\n * scopes: [\"agent:read\", \"agent:execute\"],\n * tools: [searchTool, calcTool],\n * });\n * ```\n */\nexport async function createVorimClaudeAgent(config: {\n vorim: VorimSDK;\n name: string;\n description?: string;\n capabilities: string[];\n scopes: PermissionScope[];\n tools: VorimToolDefinition[];\n}) {\n const { vorim, name, description, capabilities, scopes, tools } = config;\n\n const registration = await vorim.register({\n name,\n description,\n capabilities,\n scopes,\n });\n\n const agentId = registration.agent.agent_id;\n const registry = new VorimToolRegistry({ vorim, agentId });\n registry.addAll(tools);\n\n return {\n agentId,\n registration,\n registry,\n privateKey: registration.private_key,\n };\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────\n\nfunction truncate(str: string, max: number): string {\n return str.length > max ? str.slice(0, max) + '…' : str;\n}\n","// ============================================================================\n// VORIM SDK — Shared runtime-gate helper for framework integrations\n//\n// All tool-wrapping integrations (Vercel, OpenAI, Anthropic, …) turn a\n// `beforeAction` runtime decision into a simple { allowed, reason, decisionId }\n// the wrapper can act on. The subtlety is the `escalate` verdict: it is NOT a\n// denial — it means a human must approve the action. Folding it into\n// `allowed=false` silently breaks every human-in-the-loop flow; folding it into\n// `allowed=true` is a fail-open security hole. So this helper resolves the\n// escalation explicitly, driven by the caller's `onEscalation` preference.\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { RuntimeDecision, PermissionScope } from '../types.js';\n\n/**\n * How a framework integration should treat a runtime `escalate` verdict.\n * - `wait` — block and poll {@link VorimSDK.waitForDecisionResolution} until a\n * human approves/denies (or the timeout elapses → deny). The correct\n * default for human-in-the-loop: an escalation means \"ask a human\".\n * - `deny` — treat escalate as a denial (fail closed without waiting).\n * - `allow` — treat escalate as allowed (fail OPEN — only for trusted/dev use).\n */\nexport type EscalationPolicy = 'wait' | 'deny' | 'allow';\n\nexport interface RuntimeGateOptions {\n /** What to do on an `escalate` verdict. @default 'wait' */\n onEscalation?: EscalationPolicy;\n /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 (5 min) */\n escalationTimeoutMs?: number;\n}\n\nexport interface GateResult {\n allowed: boolean;\n reason?: string;\n decisionId?: string;\n}\n\n/** True for verdicts that permit the action to proceed. `escalate` is handled separately. */\nfunction isAllowVerdict(decision: RuntimeDecision['decision']): boolean {\n return decision === 'allow' || decision === 'modify' || decision === 'fallback';\n}\n\n/**\n * Run a `beforeAction` runtime decision and collapse it to a {@link GateResult},\n * resolving `escalate` per {@link RuntimeGateOptions.onEscalation}.\n *\n * Requires (for `onEscalation: 'wait'`) an API key with the `runtime:decide`\n * scope — the same scope `beforeAction` itself uses.\n */\nexport async function runtimeGate(\n vorim: VorimSDK,\n agentId: string,\n actionTarget: string,\n scope: PermissionScope,\n payload: Record<string, unknown> | undefined,\n opts: RuntimeGateOptions = {},\n): Promise<GateResult> {\n const onEscalation = opts.onEscalation ?? 'wait';\n const d = await vorim.beforeAction(\n { agentId, actionType: 'tool_call', actionTarget, requiredScope: scope, payload },\n { throwOnDeny: false },\n );\n\n if (d.decision !== 'escalate') {\n return { allowed: isAllowVerdict(d.decision), reason: d.reason, decisionId: d.decisionId || undefined };\n }\n\n // escalate ── a human must decide.\n if (onEscalation === 'allow') {\n return { allowed: true, reason: d.reason ?? 'escalated (auto-allowed)', decisionId: d.decisionId || undefined };\n }\n if (onEscalation === 'deny') {\n return { allowed: false, reason: d.reason ?? 'escalated (auto-denied — awaiting human)', decisionId: d.decisionId || undefined };\n }\n // 'wait' — poll for the human decision. On timeout, fail closed (deny).\n if (!d.decisionId) {\n return { allowed: false, reason: 'escalated but no decisionId to poll', decisionId: undefined };\n }\n try {\n const resolved = await vorim.waitForDecisionResolution(d.decisionId, { timeoutMs: opts.escalationTimeoutMs });\n return { allowed: isAllowVerdict(resolved.decision), reason: resolved.reason, decisionId: resolved.decisionId || d.decisionId };\n } catch {\n // ESCALATION_TIMEOUT (or any poll error) → fail closed.\n return { allowed: false, reason: 'escalation not resolved before timeout', decisionId: d.decisionId };\n }\n}\n","/**\n * Replayable agent decision evidence helpers.\n *\n * Canonical-form hashing for the VAIP -02 schema fields that the SDK\n * attaches to audit events. The hashes recorded in audit_events.tool_catalogue_hash\n * and audit_events.system_prompt_hash use these functions, so the bytes\n * an auditor or counterparty reconstructs must match what the SDK produced.\n *\n * These helpers are intentionally separate from the signing path. The\n * v0 canonical signature form (event_type|action|resource|input_hash|\n * output_hash|result) does NOT cover model_version, tool_catalogue_hash,\n * or system_prompt_hash. They will enter the canonical bytes in v1\n * (RFC 8785 JCS) in a follow-up release.\n *\n * Stable across SDK versions: the canonical-form version is documented\n * in CANONICAL_TOOL_CATALOGUE_VERSION. Future changes get a v2 etc;\n * never edit the existing v1 logic, or already-recorded hashes lose\n * their meaning.\n */\n\n// ─── Versioning ───────────────────────────────────────────────────────────\n\n/**\n * Canonical-form version for tool catalogue hashes produced by this SDK.\n * Recorded in tool_catalogue_canon_version on the event metadata (when\n * the metadata field is used) so verifiers know which hash recipe to\n * reproduce. Increment ONLY if the algorithm changes in a way that\n * would change the hash for the same logical catalogue.\n */\nexport const CANONICAL_TOOL_CATALOGUE_VERSION = 'v1' as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * Minimum shape a tool needs for catalogue hashing. The framework\n * integrations adapt their native tool objects to this shape before\n * calling hashToolCatalogue.\n */\nexport interface CatalogueTool {\n /** The name the model sees and calls. Required. */\n name: string;\n /** Human-readable description shown to the model. Optional; absent ↔ empty string. */\n description?: string;\n /**\n * JSON Schema describing the tool's input parameters. Optional;\n * absent ↔ empty object `{}`. The schema gets RFC 8785 JCS-canonicalised\n * before hashing so semantically-equivalent variations (key order,\n * whitespace) produce the same hash.\n */\n schema?: Record<string, unknown> | null;\n}\n\n// ─── RFC 8785 JCS subset ──────────────────────────────────────────────────\n\n/**\n * RFC 8785 JSON Canonicalization Scheme, sufficient subset for tool\n * catalogue values.\n *\n * Rules:\n * - Object keys sorted lexicographically by UTF-16 code units (which\n * is what JS string comparison does naturally).\n * - No whitespace between tokens.\n * - Numbers: integers as integers, finite floats per ECMAScript\n * Number.prototype.toString. JCS forbids NaN and Infinity.\n * - Strings: JSON-escape using minimal set per RFC 8259 § 7.\n * - null, true, false, arrays: as JSON.stringify produces them, since\n * JSON.stringify already produces the canonical form for these.\n *\n * Not vendoring a full library because tool schemas don't carry\n * non-integer numbers in practice and the JS spec for Number.toString\n * happens to coincide with JCS § 3.2.2.2 for the integer case.\n */\nexport function jcsCanonicalise(value: unknown): string {\n if (value === null) return 'null';\n if (value === true) return 'true';\n if (value === false) return 'false';\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('jcsCanonicalise: NaN and Infinity are not JCS-valid');\n }\n // For integers in safe range, .toString() matches JCS. For\n // non-integer floats, .toString() also matches in modern JS\n // engines (V8, JavaScriptCore, SpiderMonkey all use the shortest\n // round-trip representation, which is what JCS § 3.2.2.2 requires).\n return value.toString();\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return '[' + value.map(jcsCanonicalise).join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // Filter undefined-valued fields, matching @vorim/verify and\n // @vorim/shared-types. Without this the SDK throws on { a: 1, b: undefined }\n // while the verifier silently drops b — a cross-module canonical-form\n // divergence that would break signature verification on such events.\n const keys = Object.keys(obj).filter(k => obj[k] !== undefined).sort();\n const parts = keys.map(k => JSON.stringify(k) + ':' + jcsCanonicalise(obj[k]));\n return '{' + parts.join(',') + '}';\n }\n\n // undefined, function, symbol, bigint — not JSON-representable\n throw new Error(`jcsCanonicalise: unsupported value type: ${typeof value}`);\n}\n\n// ─── SHA-256 ──────────────────────────────────────────────────────────────\n\nasync function sha256Hex(input: string | Uint8Array): Promise<string> {\n const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;\n\n // Node.js Web Crypto (Node 18+) supports digest. Browser Web Crypto does too.\n // Fall back to node:crypto if Web Crypto is unavailable.\n const subtle = (globalThis as any).crypto?.subtle;\n if (subtle) {\n const buf = await subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(buf))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(bytes).digest('hex');\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────\n\n/**\n * Hash a single tool definition. Returns `sha256:<hex>`.\n *\n * Canonical form (v1):\n * JCS-canonicalised JSON of `{name, description, schema}` where\n * absent fields substitute `description: \"\"` and `schema: {}`.\n */\nexport async function hashTool(tool: CatalogueTool): Promise<string> {\n const normalised = {\n name: tool.name,\n description: tool.description ?? '',\n schema: tool.schema ?? {},\n };\n const hex = await sha256Hex(jcsCanonicalise(normalised));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash an entire tool catalogue. Returns `sha256:<hex>`.\n *\n * Reordering tools does NOT change the hash (tool hashes sorted\n * lexicographically before concatenation). Adding, removing, or\n * modifying a tool DOES change the hash.\n *\n * Per-tool hashing first means a verifier comparing two catalogue\n * hashes that differ can also be given the per-tool hashes to\n * identify which specific tool changed.\n */\nexport async function hashToolCatalogue(tools: CatalogueTool[]): Promise<string> {\n if (tools.length === 0) {\n // Empty catalogue has a deterministic, stable hash distinct from \"no field\"\n return `sha256:${await sha256Hex('[]')}`;\n }\n const perTool = await Promise.all(tools.map(hashTool));\n perTool.sort();\n const hex = await sha256Hex(perTool.join(''));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash a system prompt. Returns `sha256:<hex>`.\n *\n * The prompt is UTF-8 encoded and hashed verbatim — no normalisation.\n * If a caller wants to ignore whitespace or comment differences, they\n * should normalise before calling. The intent here is deterministic\n * reproducibility, not semantic equivalence.\n */\nexport async function hashSystemPrompt(prompt: string): Promise<string> {\n const hex = await sha256Hex(prompt);\n return `sha256:${hex}`;\n}\n\n/**\n * Convenience: hash the previous event's canonical bytes for use in\n * the prev_event_hash field of hash-chained ingest. Caller provides\n * the canonical bytes (use canonicalPayloadV0 from the main module).\n */\nexport async function hashPreviousEvent(canonicalBytes: string): Promise<string> {\n const hex = await sha256Hex(canonicalBytes);\n return `sha256:${hex}`;\n}\n\n// ─── Replay context — framework integration helper ────────────────────────\n\n/**\n * Raw inputs the integration captures from the framework. Set by the\n * integration's config; turned into hashes by {@link prepareReplayContext}.\n */\nexport interface ReplayInputs {\n /** Stable identifier for the model. E.g. `\"anthropic:claude-opus-4-8\"`. */\n modelVersion?: string;\n /** Tools available to the agent at call time. Hashed via {@link hashToolCatalogue}. */\n tools?: CatalogueTool[];\n /** System prompt active at call time. Hashed via {@link hashSystemPrompt}. */\n systemPrompt?: string;\n}\n\n/**\n * Pre-computed hashes ready to attach to audit events. The three keys\n * match the audit_events column names.\n */\nexport interface ReplayContext {\n model_version?: string;\n tool_catalogue_hash?: string;\n system_prompt_hash?: string;\n}\n\n/**\n * Compute replay context once from raw inputs. Use at integration\n * setup time so each emit can attach the hashes without re-hashing.\n *\n * Returns an object suitable for spreading into an AuditEventInput:\n * `await vorim.emit({ ...event, ...replayContext })`\n *\n * If a field is absent in the inputs, it is absent in the result\n * (not the empty string). That keeps the event lean.\n */\nexport async function prepareReplayContext(\n inputs: ReplayInputs,\n): Promise<ReplayContext> {\n const ctx: ReplayContext = {};\n if (inputs.modelVersion) ctx.model_version = inputs.modelVersion;\n if (inputs.tools) ctx.tool_catalogue_hash = await hashToolCatalogue(inputs.tools);\n if (inputs.systemPrompt) ctx.system_prompt_hash = await hashSystemPrompt(inputs.systemPrompt);\n return ctx;\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,6 @@
1
- import { VorimSDK, PermissionScope, ReplayInputs, AgentRegistrationResult } from '../index.cjs';
1
+ import { P as PermissionScope, A as AgentRegistrationResult } from '../types-B22WnXEW.cjs';
2
+ import { VorimSDK, ReplayInputs } from '../index.cjs';
3
+ import { E as EscalationPolicy } from '../_runtime-gate-DZQTkw4J.cjs';
2
4
 
3
5
  interface AnthropicTool {
4
6
  name: string;
@@ -48,6 +50,18 @@ interface VorimAnthropicConfig {
48
50
  * quota. When false (default) the fast permission check is used.
49
51
  */
50
52
  useRuntimeControl?: boolean;
53
+ /**
54
+ * What to do when a runtime decision returns `escalate` (a human must
55
+ * approve). Only applies when `useRuntimeControl` is true.
56
+ * - `wait` (default) block and poll until a human approves/denies, or the
57
+ * timeout elapses (→ deny). Requires the `runtime:decide` scope.
58
+ * - `deny` fail closed without waiting.
59
+ * - `allow` proceed (fail OPEN — dev/trusted use only).
60
+ * @default 'wait'
61
+ */
62
+ onEscalation?: EscalationPolicy;
63
+ /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 */
64
+ escalationTimeoutMs?: number;
51
65
  /**
52
66
  * Replayable agent decision evidence (VAIP -02). Hashes attached to
53
67
  * every audit event. If `replay.tools` is omitted, the registry's
@@ -106,6 +120,8 @@ declare class VorimToolRegistry {
106
120
  private defaultPermission;
107
121
  private asyncAudit;
108
122
  private useRuntimeControl;
123
+ private onEscalation?;
124
+ private escalationTimeoutMs?;
109
125
  private tools;
110
126
  private replayInputs;
111
127
  private replayCache;
@@ -1,4 +1,6 @@
1
- import { VorimSDK, PermissionScope, ReplayInputs, AgentRegistrationResult } from '../index.js';
1
+ import { P as PermissionScope, A as AgentRegistrationResult } from '../types-B22WnXEW.js';
2
+ import { VorimSDK, ReplayInputs } from '../index.js';
3
+ import { E as EscalationPolicy } from '../_runtime-gate-DZQTkw4J.js';
2
4
 
3
5
  interface AnthropicTool {
4
6
  name: string;
@@ -48,6 +50,18 @@ interface VorimAnthropicConfig {
48
50
  * quota. When false (default) the fast permission check is used.
49
51
  */
50
52
  useRuntimeControl?: boolean;
53
+ /**
54
+ * What to do when a runtime decision returns `escalate` (a human must
55
+ * approve). Only applies when `useRuntimeControl` is true.
56
+ * - `wait` (default) block and poll until a human approves/denies, or the
57
+ * timeout elapses (→ deny). Requires the `runtime:decide` scope.
58
+ * - `deny` fail closed without waiting.
59
+ * - `allow` proceed (fail OPEN — dev/trusted use only).
60
+ * @default 'wait'
61
+ */
62
+ onEscalation?: EscalationPolicy;
63
+ /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 */
64
+ escalationTimeoutMs?: number;
51
65
  /**
52
66
  * Replayable agent decision evidence (VAIP -02). Hashes attached to
53
67
  * every audit event. If `replay.tools` is omitted, the registry's
@@ -106,6 +120,8 @@ declare class VorimToolRegistry {
106
120
  private defaultPermission;
107
121
  private asyncAudit;
108
122
  private useRuntimeControl;
123
+ private onEscalation?;
124
+ private escalationTimeoutMs?;
109
125
  private tools;
110
126
  private replayInputs;
111
127
  private replayCache;
@@ -1,3 +1,33 @@
1
+ // src/integrations/_runtime-gate.ts
2
+ function isAllowVerdict(decision) {
3
+ return decision === "allow" || decision === "modify" || decision === "fallback";
4
+ }
5
+ async function runtimeGate(vorim, agentId, actionTarget, scope, payload, opts = {}) {
6
+ const onEscalation = opts.onEscalation ?? "wait";
7
+ const d = await vorim.beforeAction(
8
+ { agentId, actionType: "tool_call", actionTarget, requiredScope: scope, payload },
9
+ { throwOnDeny: false }
10
+ );
11
+ if (d.decision !== "escalate") {
12
+ return { allowed: isAllowVerdict(d.decision), reason: d.reason, decisionId: d.decisionId || void 0 };
13
+ }
14
+ if (onEscalation === "allow") {
15
+ return { allowed: true, reason: d.reason ?? "escalated (auto-allowed)", decisionId: d.decisionId || void 0 };
16
+ }
17
+ if (onEscalation === "deny") {
18
+ return { allowed: false, reason: d.reason ?? "escalated (auto-denied \u2014 awaiting human)", decisionId: d.decisionId || void 0 };
19
+ }
20
+ if (!d.decisionId) {
21
+ return { allowed: false, reason: "escalated but no decisionId to poll", decisionId: void 0 };
22
+ }
23
+ try {
24
+ const resolved = await vorim.waitForDecisionResolution(d.decisionId, { timeoutMs: opts.escalationTimeoutMs });
25
+ return { allowed: isAllowVerdict(resolved.decision), reason: resolved.reason, decisionId: resolved.decisionId || d.decisionId };
26
+ } catch {
27
+ return { allowed: false, reason: "escalation not resolved before timeout", decisionId: d.decisionId };
28
+ }
29
+ }
30
+
1
31
  // src/replay.ts
2
32
  function jcsCanonicalise(value) {
3
33
  if (value === null) return "null";
@@ -70,6 +100,8 @@ var VorimToolRegistry = class {
70
100
  defaultPermission;
71
101
  asyncAudit;
72
102
  useRuntimeControl;
103
+ onEscalation;
104
+ escalationTimeoutMs;
73
105
  tools = /* @__PURE__ */ new Map();
74
106
  replayInputs;
75
107
  replayCache = null;
@@ -79,20 +111,17 @@ var VorimToolRegistry = class {
79
111
  this.defaultPermission = config.defaultPermission ?? "agent:execute";
80
112
  this.asyncAudit = config.asyncAudit ?? true;
81
113
  this.useRuntimeControl = config.useRuntimeControl ?? false;
114
+ this.onEscalation = config.onEscalation;
115
+ this.escalationTimeoutMs = config.escalationTimeoutMs;
82
116
  this.replayInputs = config.replay;
83
117
  }
84
118
  /** Gate a tool call: runtime decision (with decisionId) or permission check. */
85
119
  async gate(scope, actionTarget, payload) {
86
120
  if (this.useRuntimeControl) {
87
- const d = await this.vorim.beforeAction(
88
- { agentId: this.agentId, actionType: "tool_call", actionTarget, requiredScope: scope, payload },
89
- { throwOnDeny: false }
90
- );
91
- return {
92
- allowed: d.decision === "allow" || d.decision === "modify" || d.decision === "fallback",
93
- reason: d.reason,
94
- decisionId: d.decisionId || void 0
95
- };
121
+ return runtimeGate(this.vorim, this.agentId, actionTarget, scope, payload, {
122
+ onEscalation: this.onEscalation,
123
+ escalationTimeoutMs: this.escalationTimeoutMs
124
+ });
96
125
  }
97
126
  const { allowed, reason } = await this.vorim.check(this.agentId, scope);
98
127
  return { allowed, reason };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/replay.ts","../../src/integrations/anthropic.ts"],"sourcesContent":["/**\n * Replayable agent decision evidence helpers.\n *\n * Canonical-form hashing for the VAIP -02 schema fields that the SDK\n * attaches to audit events. The hashes recorded in audit_events.tool_catalogue_hash\n * and audit_events.system_prompt_hash use these functions, so the bytes\n * an auditor or counterparty reconstructs must match what the SDK produced.\n *\n * These helpers are intentionally separate from the signing path. The\n * v0 canonical signature form (event_type|action|resource|input_hash|\n * output_hash|result) does NOT cover model_version, tool_catalogue_hash,\n * or system_prompt_hash. They will enter the canonical bytes in v1\n * (RFC 8785 JCS) in a follow-up release.\n *\n * Stable across SDK versions: the canonical-form version is documented\n * in CANONICAL_TOOL_CATALOGUE_VERSION. Future changes get a v2 etc;\n * never edit the existing v1 logic, or already-recorded hashes lose\n * their meaning.\n */\n\n// ─── Versioning ───────────────────────────────────────────────────────────\n\n/**\n * Canonical-form version for tool catalogue hashes produced by this SDK.\n * Recorded in tool_catalogue_canon_version on the event metadata (when\n * the metadata field is used) so verifiers know which hash recipe to\n * reproduce. Increment ONLY if the algorithm changes in a way that\n * would change the hash for the same logical catalogue.\n */\nexport const CANONICAL_TOOL_CATALOGUE_VERSION = 'v1' as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * Minimum shape a tool needs for catalogue hashing. The framework\n * integrations adapt their native tool objects to this shape before\n * calling hashToolCatalogue.\n */\nexport interface CatalogueTool {\n /** The name the model sees and calls. Required. */\n name: string;\n /** Human-readable description shown to the model. Optional; absent ↔ empty string. */\n description?: string;\n /**\n * JSON Schema describing the tool's input parameters. Optional;\n * absent ↔ empty object `{}`. The schema gets RFC 8785 JCS-canonicalised\n * before hashing so semantically-equivalent variations (key order,\n * whitespace) produce the same hash.\n */\n schema?: Record<string, unknown> | null;\n}\n\n// ─── RFC 8785 JCS subset ──────────────────────────────────────────────────\n\n/**\n * RFC 8785 JSON Canonicalization Scheme, sufficient subset for tool\n * catalogue values.\n *\n * Rules:\n * - Object keys sorted lexicographically by UTF-16 code units (which\n * is what JS string comparison does naturally).\n * - No whitespace between tokens.\n * - Numbers: integers as integers, finite floats per ECMAScript\n * Number.prototype.toString. JCS forbids NaN and Infinity.\n * - Strings: JSON-escape using minimal set per RFC 8259 § 7.\n * - null, true, false, arrays: as JSON.stringify produces them, since\n * JSON.stringify already produces the canonical form for these.\n *\n * Not vendoring a full library because tool schemas don't carry\n * non-integer numbers in practice and the JS spec for Number.toString\n * happens to coincide with JCS § 3.2.2.2 for the integer case.\n */\nexport function jcsCanonicalise(value: unknown): string {\n if (value === null) return 'null';\n if (value === true) return 'true';\n if (value === false) return 'false';\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('jcsCanonicalise: NaN and Infinity are not JCS-valid');\n }\n // For integers in safe range, .toString() matches JCS. For\n // non-integer floats, .toString() also matches in modern JS\n // engines (V8, JavaScriptCore, SpiderMonkey all use the shortest\n // round-trip representation, which is what JCS § 3.2.2.2 requires).\n return value.toString();\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return '[' + value.map(jcsCanonicalise).join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // Filter undefined-valued fields, matching @vorim/verify and\n // @vorim/shared-types. Without this the SDK throws on { a: 1, b: undefined }\n // while the verifier silently drops b — a cross-module canonical-form\n // divergence that would break signature verification on such events.\n const keys = Object.keys(obj).filter(k => obj[k] !== undefined).sort();\n const parts = keys.map(k => JSON.stringify(k) + ':' + jcsCanonicalise(obj[k]));\n return '{' + parts.join(',') + '}';\n }\n\n // undefined, function, symbol, bigint — not JSON-representable\n throw new Error(`jcsCanonicalise: unsupported value type: ${typeof value}`);\n}\n\n// ─── SHA-256 ──────────────────────────────────────────────────────────────\n\nasync function sha256Hex(input: string | Uint8Array): Promise<string> {\n const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;\n\n // Node.js Web Crypto (Node 18+) supports digest. Browser Web Crypto does too.\n // Fall back to node:crypto if Web Crypto is unavailable.\n const subtle = (globalThis as any).crypto?.subtle;\n if (subtle) {\n const buf = await subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(buf))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(bytes).digest('hex');\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────\n\n/**\n * Hash a single tool definition. Returns `sha256:<hex>`.\n *\n * Canonical form (v1):\n * JCS-canonicalised JSON of `{name, description, schema}` where\n * absent fields substitute `description: \"\"` and `schema: {}`.\n */\nexport async function hashTool(tool: CatalogueTool): Promise<string> {\n const normalised = {\n name: tool.name,\n description: tool.description ?? '',\n schema: tool.schema ?? {},\n };\n const hex = await sha256Hex(jcsCanonicalise(normalised));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash an entire tool catalogue. Returns `sha256:<hex>`.\n *\n * Reordering tools does NOT change the hash (tool hashes sorted\n * lexicographically before concatenation). Adding, removing, or\n * modifying a tool DOES change the hash.\n *\n * Per-tool hashing first means a verifier comparing two catalogue\n * hashes that differ can also be given the per-tool hashes to\n * identify which specific tool changed.\n */\nexport async function hashToolCatalogue(tools: CatalogueTool[]): Promise<string> {\n if (tools.length === 0) {\n // Empty catalogue has a deterministic, stable hash distinct from \"no field\"\n return `sha256:${await sha256Hex('[]')}`;\n }\n const perTool = await Promise.all(tools.map(hashTool));\n perTool.sort();\n const hex = await sha256Hex(perTool.join(''));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash a system prompt. Returns `sha256:<hex>`.\n *\n * The prompt is UTF-8 encoded and hashed verbatim — no normalisation.\n * If a caller wants to ignore whitespace or comment differences, they\n * should normalise before calling. The intent here is deterministic\n * reproducibility, not semantic equivalence.\n */\nexport async function hashSystemPrompt(prompt: string): Promise<string> {\n const hex = await sha256Hex(prompt);\n return `sha256:${hex}`;\n}\n\n/**\n * Convenience: hash the previous event's canonical bytes for use in\n * the prev_event_hash field of hash-chained ingest. Caller provides\n * the canonical bytes (use canonicalPayloadV0 from the main module).\n */\nexport async function hashPreviousEvent(canonicalBytes: string): Promise<string> {\n const hex = await sha256Hex(canonicalBytes);\n return `sha256:${hex}`;\n}\n\n// ─── Replay context — framework integration helper ────────────────────────\n\n/**\n * Raw inputs the integration captures from the framework. Set by the\n * integration's config; turned into hashes by {@link prepareReplayContext}.\n */\nexport interface ReplayInputs {\n /** Stable identifier for the model. E.g. `\"anthropic:claude-opus-4-8\"`. */\n modelVersion?: string;\n /** Tools available to the agent at call time. Hashed via {@link hashToolCatalogue}. */\n tools?: CatalogueTool[];\n /** System prompt active at call time. Hashed via {@link hashSystemPrompt}. */\n systemPrompt?: string;\n}\n\n/**\n * Pre-computed hashes ready to attach to audit events. The three keys\n * match the audit_events column names.\n */\nexport interface ReplayContext {\n model_version?: string;\n tool_catalogue_hash?: string;\n system_prompt_hash?: string;\n}\n\n/**\n * Compute replay context once from raw inputs. Use at integration\n * setup time so each emit can attach the hashes without re-hashing.\n *\n * Returns an object suitable for spreading into an AuditEventInput:\n * `await vorim.emit({ ...event, ...replayContext })`\n *\n * If a field is absent in the inputs, it is absent in the result\n * (not the empty string). That keeps the event lean.\n */\nexport async function prepareReplayContext(\n inputs: ReplayInputs,\n): Promise<ReplayContext> {\n const ctx: ReplayContext = {};\n if (inputs.modelVersion) ctx.model_version = inputs.modelVersion;\n if (inputs.tools) ctx.tool_catalogue_hash = await hashToolCatalogue(inputs.tools);\n if (inputs.systemPrompt) ctx.system_prompt_hash = await hashSystemPrompt(inputs.systemPrompt);\n return ctx;\n}\n","// ============================================================================\n// VORIM SDK — Anthropic/Claude Integration\n// Wraps Anthropic tool use with Vorim permission checks, audit trails,\n// and agent identity. Works with the Anthropic Node.js SDK (messages API\n// with tool use).\n//\n// Peer dependency: @anthropic-ai/sdk >=0.30.0\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { PermissionScope, AuditEventInput } from '../types.js';\nimport {\n prepareReplayContext,\n type ReplayInputs,\n type ReplayContext,\n type CatalogueTool,\n} from '../replay.js';\n\n// ─── Re-declared Anthropic types (peer dependency — not bundled) ──────────\n\ninterface AnthropicTool {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\ninterface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\n// ─── Configuration ────────────────────────────────────────────────────────\n\nexport interface VorimToolDefinition<TArgs = Record<string, unknown>, TResult = unknown> {\n /** Tool name (must match the tool name sent to Claude). */\n name: string;\n /** Description shown to Claude. */\n description: string;\n /** JSON Schema for the tool's input. */\n input_schema: Record<string, unknown>;\n /** The function to execute when the tool is called. */\n execute: (args: TArgs) => Promise<TResult>;\n /** Vorim permission scope required. @default 'agent:execute' */\n permission?: PermissionScope;\n}\n\nexport interface VorimAnthropicConfig {\n /** Vorim SDK instance. */\n vorim: VorimSDK;\n /** The Vorim agent_id. */\n agentId: string;\n /** Default permission scope for tools without an explicit one. @default 'agent:execute' */\n defaultPermission?: PermissionScope;\n /** Whether to emit audit events asynchronously (fire-and-forget). @default true */\n asyncAudit?: boolean;\n /**\n * Gate each tool call through the runtime-control decision API\n * (`beforeAction`) instead of the lightweight permission check. @default false\n *\n * When true, tool calls are evaluated against live policy rules and the\n * returned decisionId is linked onto each audit event's decision_id.\n * Requires the runtime_control plan feature (Growth+) and consumes decision\n * quota. When false (default) the fast permission check is used.\n */\n useRuntimeControl?: boolean;\n /**\n * Replayable agent decision evidence (VAIP -02). Hashes attached to\n * every audit event. If `replay.tools` is omitted, the registry's\n * own tool list is used automatically. Not covered by v0 canonical\n * signature form.\n */\n replay?: ReplayInputs;\n}\n\n// ─── Tool Registry ────────────────────────────────────────────────────────\n\n/**\n * Manages a set of tools with Vorim permission checks and audit logging.\n * Converts tools to Anthropic's tool format and handles execution of\n * tool_use blocks from Claude's response.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const vorim = createVorim({ apiKey: \"agid_sk_live_...\" });\n * const anthropic = new Anthropic();\n *\n * const registry = new VorimToolRegistry({\n * vorim,\n * agentId: \"agid_acme_a1b2c3d4\",\n * });\n *\n * registry.add({\n * name: \"search_docs\",\n * description: \"Search internal documents\",\n * input_schema: {\n * type: \"object\",\n * properties: { query: { type: \"string\" } },\n * required: [\"query\"],\n * },\n * execute: async ({ query }) => searchDocs(query),\n * permission: \"agent:read\",\n * });\n *\n * const response = await anthropic.messages.create({\n * model: \"claude-sonnet-4-20250514\",\n * max_tokens: 1024,\n * messages,\n * tools: registry.toAnthropicTools(),\n * });\n *\n * // Execute tool_use blocks from response\n * const toolResults = await registry.executeToolUseBlocks(\n * response.content.filter(b => b.type === \"tool_use\")\n * );\n * ```\n */\nexport class VorimToolRegistry {\n private vorim: VorimSDK;\n private agentId: string;\n private defaultPermission: PermissionScope;\n private asyncAudit: boolean;\n private useRuntimeControl: boolean;\n private tools = new Map<string, VorimToolDefinition>();\n private replayInputs: ReplayInputs | undefined;\n private replayCache: Promise<ReplayContext> | null = null;\n\n constructor(config: VorimAnthropicConfig) {\n this.vorim = config.vorim;\n this.agentId = config.agentId;\n this.defaultPermission = config.defaultPermission ?? 'agent:execute';\n this.asyncAudit = config.asyncAudit ?? true;\n this.useRuntimeControl = config.useRuntimeControl ?? false;\n this.replayInputs = config.replay;\n }\n\n /** Gate a tool call: runtime decision (with decisionId) or permission check. */\n private async gate(\n scope: PermissionScope,\n actionTarget: string,\n payload?: Record<string, unknown>,\n ): Promise<{ allowed: boolean; reason?: string; decisionId?: string }> {\n if (this.useRuntimeControl) {\n const d = await this.vorim.beforeAction(\n { agentId: this.agentId, actionType: 'tool_call', actionTarget, requiredScope: scope, payload },\n { throwOnDeny: false },\n );\n return {\n allowed: d.decision === 'allow' || d.decision === 'modify' || d.decision === 'fallback',\n reason: d.reason,\n decisionId: d.decisionId || undefined,\n };\n }\n const { allowed, reason } = await this.vorim.check(this.agentId, scope);\n return { allowed, reason };\n }\n\n private async getReplayContext(): Promise<ReplayContext> {\n if (!this.replayInputs) return {};\n if (!this.replayCache) {\n const inputs: ReplayInputs = {\n ...this.replayInputs,\n tools: this.replayInputs.tools ?? this.deriveCatalogue(),\n };\n this.replayCache = prepareReplayContext(inputs);\n }\n return this.replayCache;\n }\n\n private deriveCatalogue(): CatalogueTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n schema: t.input_schema,\n }));\n }\n\n /** Register a tool. Invalidates the cached tool-catalogue hash. */\n add<TArgs, TResult>(definition: VorimToolDefinition<TArgs, TResult>): this {\n this.tools.set(definition.name, definition as VorimToolDefinition);\n this.replayCache = null;\n return this;\n }\n\n /** Register multiple tools. */\n addAll(definitions: VorimToolDefinition[]): this {\n for (const def of definitions) this.add(def);\n return this;\n }\n\n /** Convert registered tools to Anthropic's tool format. */\n toAnthropicTools(): AnthropicTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema,\n }));\n }\n\n /**\n * Execute tool_use blocks from a Claude message response.\n * Each call is checked against Vorim permissions and audited.\n * Returns an array of tool_result blocks ready to send back to Claude.\n */\n async executeToolUseBlocks(toolUseBlocks: ToolUseBlock[]): Promise<ToolResultBlock[]> {\n return Promise.all(\n toolUseBlocks.map(block => this.executeSingleBlock(block)),\n );\n }\n\n private async executeSingleBlock(block: ToolUseBlock): Promise<ToolResultBlock> {\n const definition = this.tools.get(block.name);\n\n if (!definition) {\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Unknown tool: ${block.name}` }),\n is_error: true,\n };\n }\n\n const scope = definition.permission ?? this.defaultPermission;\n\n // 1. Gate: runtime decision (with decisionId linkage) or permission check.\n const { allowed, reason, decisionId } = await this.gate(scope, block.name, block.input as Record<string, unknown>);\n const replayCtx = await this.getReplayContext();\n\n if (!allowed) {\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'denied',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { reason, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Permission denied: ${scope}${reason ? ` — ${reason}` : ''}` }),\n is_error: true,\n };\n }\n\n // 2. Execute\n const start = Date.now();\n try {\n const result = await definition.execute(block.input as any);\n const content = typeof result === 'string' ? result : JSON.stringify(result);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'success',\n latency_ms: Date.now() - start,\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return { type: 'tool_result', tool_use_id: block.id, content };\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'error',\n latency_ms: Date.now() - start,\n error_code: err instanceof Error ? err.name : 'UNKNOWN',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { error: errMsg, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: errMsg }),\n is_error: true,\n };\n }\n }\n\n private emitAudit(event: AuditEventInput): void {\n this.vorim.emit(event).catch(() => {});\n }\n}\n\n// ─── Agent Loop ───────────────────────────────────────────────────────────\n\n/** Minimal Anthropic client interface (avoids importing the full SDK). */\ninterface AnthropicClient {\n messages: {\n create(params: any): Promise<any>;\n };\n}\n\nexport interface VorimAgentLoopConfig extends VorimAnthropicConfig {\n /** Anthropic client instance. */\n anthropic: AnthropicClient;\n /** Model to use. @default 'claude-sonnet-4-20250514' */\n model?: string;\n /** System prompt for the agent. */\n systemPrompt?: string;\n /** Maximum tool-use iterations before stopping. @default 10 */\n maxIterations?: number;\n /** Max tokens per response. @default 1024 */\n maxTokens?: number;\n}\n\n/**\n * Runs a complete agent loop with Claude tool use, Vorim\n * permission enforcement, and audit logging.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { runAgentLoop, VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const registry = new VorimToolRegistry({ vorim, agentId });\n * registry.add({ name: \"search\", ... });\n *\n * const response = await runAgentLoop({\n * vorim,\n * agentId,\n * anthropic: new Anthropic(),\n * model: \"claude-sonnet-4-20250514\",\n * systemPrompt: \"You are a helpful assistant.\",\n * registry,\n * userMessage: \"Find docs about onboarding\",\n * });\n * ```\n */\nexport async function runAgentLoop(\n config: VorimAgentLoopConfig & {\n registry: VorimToolRegistry;\n userMessage: string;\n },\n): Promise<string> {\n const {\n anthropic,\n model = 'claude-sonnet-4-20250514',\n systemPrompt,\n maxIterations = 10,\n maxTokens = 1024,\n registry,\n userMessage,\n } = config;\n\n const tools = registry.toAnthropicTools();\n const messages: any[] = [{ role: 'user', content: userMessage }];\n\n for (let i = 0; i < maxIterations; i++) {\n const response = await anthropic.messages.create({\n model,\n max_tokens: maxTokens,\n ...(systemPrompt ? { system: systemPrompt } : {}),\n messages,\n ...(tools.length > 0 ? { tools } : {}),\n });\n\n // If stop_reason is \"end_turn\" — Claude is done\n if (response.stop_reason === 'end_turn' || response.stop_reason !== 'tool_use') {\n const textBlocks = response.content.filter((b: any) => b.type === 'text');\n return textBlocks.map((b: any) => b.text).join('') || '';\n }\n\n // Extract tool_use blocks and execute\n const toolUseBlocks = response.content.filter((b: any) => b.type === 'tool_use');\n const toolResults = await registry.executeToolUseBlocks(toolUseBlocks);\n\n // Append assistant response and tool results to conversation\n messages.push({ role: 'assistant', content: response.content });\n messages.push({ role: 'user', content: toolResults });\n }\n\n return '';\n}\n\n// ─── Agent Registration Helper ───────────────────────────────────────────\n\n/**\n * Registers a new agent with Vorim and returns a ready-to-use tool registry\n * configured for Anthropic/Claude.\n *\n * @example\n * ```ts\n * const { agentId, registry } = await createVorimClaudeAgent({\n * vorim,\n * name: \"claude-assistant\",\n * capabilities: [\"search\", \"calculate\"],\n * scopes: [\"agent:read\", \"agent:execute\"],\n * tools: [searchTool, calcTool],\n * });\n * ```\n */\nexport async function createVorimClaudeAgent(config: {\n vorim: VorimSDK;\n name: string;\n description?: string;\n capabilities: string[];\n scopes: PermissionScope[];\n tools: VorimToolDefinition[];\n}) {\n const { vorim, name, description, capabilities, scopes, tools } = config;\n\n const registration = await vorim.register({\n name,\n description,\n capabilities,\n scopes,\n });\n\n const agentId = registration.agent.agent_id;\n const registry = new VorimToolRegistry({ vorim, agentId });\n registry.addAll(tools);\n\n return {\n agentId,\n registration,\n registry,\n privateKey: registration.private_key,\n };\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────\n\nfunction truncate(str: string, max: number): string {\n return str.length > max ? str.slice(0, max) + '…' : str;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/integrations/_runtime-gate.ts","../../src/replay.ts","../../src/integrations/anthropic.ts"],"sourcesContent":["// ============================================================================\n// VORIM SDK — Shared runtime-gate helper for framework integrations\n//\n// All tool-wrapping integrations (Vercel, OpenAI, Anthropic, …) turn a\n// `beforeAction` runtime decision into a simple { allowed, reason, decisionId }\n// the wrapper can act on. The subtlety is the `escalate` verdict: it is NOT a\n// denial — it means a human must approve the action. Folding it into\n// `allowed=false` silently breaks every human-in-the-loop flow; folding it into\n// `allowed=true` is a fail-open security hole. So this helper resolves the\n// escalation explicitly, driven by the caller's `onEscalation` preference.\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { RuntimeDecision, PermissionScope } from '../types.js';\n\n/**\n * How a framework integration should treat a runtime `escalate` verdict.\n * - `wait` — block and poll {@link VorimSDK.waitForDecisionResolution} until a\n * human approves/denies (or the timeout elapses → deny). The correct\n * default for human-in-the-loop: an escalation means \"ask a human\".\n * - `deny` — treat escalate as a denial (fail closed without waiting).\n * - `allow` — treat escalate as allowed (fail OPEN — only for trusted/dev use).\n */\nexport type EscalationPolicy = 'wait' | 'deny' | 'allow';\n\nexport interface RuntimeGateOptions {\n /** What to do on an `escalate` verdict. @default 'wait' */\n onEscalation?: EscalationPolicy;\n /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 (5 min) */\n escalationTimeoutMs?: number;\n}\n\nexport interface GateResult {\n allowed: boolean;\n reason?: string;\n decisionId?: string;\n}\n\n/** True for verdicts that permit the action to proceed. `escalate` is handled separately. */\nfunction isAllowVerdict(decision: RuntimeDecision['decision']): boolean {\n return decision === 'allow' || decision === 'modify' || decision === 'fallback';\n}\n\n/**\n * Run a `beforeAction` runtime decision and collapse it to a {@link GateResult},\n * resolving `escalate` per {@link RuntimeGateOptions.onEscalation}.\n *\n * Requires (for `onEscalation: 'wait'`) an API key with the `runtime:decide`\n * scope — the same scope `beforeAction` itself uses.\n */\nexport async function runtimeGate(\n vorim: VorimSDK,\n agentId: string,\n actionTarget: string,\n scope: PermissionScope,\n payload: Record<string, unknown> | undefined,\n opts: RuntimeGateOptions = {},\n): Promise<GateResult> {\n const onEscalation = opts.onEscalation ?? 'wait';\n const d = await vorim.beforeAction(\n { agentId, actionType: 'tool_call', actionTarget, requiredScope: scope, payload },\n { throwOnDeny: false },\n );\n\n if (d.decision !== 'escalate') {\n return { allowed: isAllowVerdict(d.decision), reason: d.reason, decisionId: d.decisionId || undefined };\n }\n\n // escalate ── a human must decide.\n if (onEscalation === 'allow') {\n return { allowed: true, reason: d.reason ?? 'escalated (auto-allowed)', decisionId: d.decisionId || undefined };\n }\n if (onEscalation === 'deny') {\n return { allowed: false, reason: d.reason ?? 'escalated (auto-denied — awaiting human)', decisionId: d.decisionId || undefined };\n }\n // 'wait' — poll for the human decision. On timeout, fail closed (deny).\n if (!d.decisionId) {\n return { allowed: false, reason: 'escalated but no decisionId to poll', decisionId: undefined };\n }\n try {\n const resolved = await vorim.waitForDecisionResolution(d.decisionId, { timeoutMs: opts.escalationTimeoutMs });\n return { allowed: isAllowVerdict(resolved.decision), reason: resolved.reason, decisionId: resolved.decisionId || d.decisionId };\n } catch {\n // ESCALATION_TIMEOUT (or any poll error) → fail closed.\n return { allowed: false, reason: 'escalation not resolved before timeout', decisionId: d.decisionId };\n }\n}\n","/**\n * Replayable agent decision evidence helpers.\n *\n * Canonical-form hashing for the VAIP -02 schema fields that the SDK\n * attaches to audit events. The hashes recorded in audit_events.tool_catalogue_hash\n * and audit_events.system_prompt_hash use these functions, so the bytes\n * an auditor or counterparty reconstructs must match what the SDK produced.\n *\n * These helpers are intentionally separate from the signing path. The\n * v0 canonical signature form (event_type|action|resource|input_hash|\n * output_hash|result) does NOT cover model_version, tool_catalogue_hash,\n * or system_prompt_hash. They will enter the canonical bytes in v1\n * (RFC 8785 JCS) in a follow-up release.\n *\n * Stable across SDK versions: the canonical-form version is documented\n * in CANONICAL_TOOL_CATALOGUE_VERSION. Future changes get a v2 etc;\n * never edit the existing v1 logic, or already-recorded hashes lose\n * their meaning.\n */\n\n// ─── Versioning ───────────────────────────────────────────────────────────\n\n/**\n * Canonical-form version for tool catalogue hashes produced by this SDK.\n * Recorded in tool_catalogue_canon_version on the event metadata (when\n * the metadata field is used) so verifiers know which hash recipe to\n * reproduce. Increment ONLY if the algorithm changes in a way that\n * would change the hash for the same logical catalogue.\n */\nexport const CANONICAL_TOOL_CATALOGUE_VERSION = 'v1' as const;\n\n// ─── Types ────────────────────────────────────────────────────────────────\n\n/**\n * Minimum shape a tool needs for catalogue hashing. The framework\n * integrations adapt their native tool objects to this shape before\n * calling hashToolCatalogue.\n */\nexport interface CatalogueTool {\n /** The name the model sees and calls. Required. */\n name: string;\n /** Human-readable description shown to the model. Optional; absent ↔ empty string. */\n description?: string;\n /**\n * JSON Schema describing the tool's input parameters. Optional;\n * absent ↔ empty object `{}`. The schema gets RFC 8785 JCS-canonicalised\n * before hashing so semantically-equivalent variations (key order,\n * whitespace) produce the same hash.\n */\n schema?: Record<string, unknown> | null;\n}\n\n// ─── RFC 8785 JCS subset ──────────────────────────────────────────────────\n\n/**\n * RFC 8785 JSON Canonicalization Scheme, sufficient subset for tool\n * catalogue values.\n *\n * Rules:\n * - Object keys sorted lexicographically by UTF-16 code units (which\n * is what JS string comparison does naturally).\n * - No whitespace between tokens.\n * - Numbers: integers as integers, finite floats per ECMAScript\n * Number.prototype.toString. JCS forbids NaN and Infinity.\n * - Strings: JSON-escape using minimal set per RFC 8259 § 7.\n * - null, true, false, arrays: as JSON.stringify produces them, since\n * JSON.stringify already produces the canonical form for these.\n *\n * Not vendoring a full library because tool schemas don't carry\n * non-integer numbers in practice and the JS spec for Number.toString\n * happens to coincide with JCS § 3.2.2.2 for the integer case.\n */\nexport function jcsCanonicalise(value: unknown): string {\n if (value === null) return 'null';\n if (value === true) return 'true';\n if (value === false) return 'false';\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) {\n throw new Error('jcsCanonicalise: NaN and Infinity are not JCS-valid');\n }\n // For integers in safe range, .toString() matches JCS. For\n // non-integer floats, .toString() also matches in modern JS\n // engines (V8, JavaScriptCore, SpiderMonkey all use the shortest\n // round-trip representation, which is what JCS § 3.2.2.2 requires).\n return value.toString();\n }\n\n if (typeof value === 'string') {\n return JSON.stringify(value);\n }\n\n if (Array.isArray(value)) {\n return '[' + value.map(jcsCanonicalise).join(',') + ']';\n }\n\n if (typeof value === 'object') {\n const obj = value as Record<string, unknown>;\n // Filter undefined-valued fields, matching @vorim/verify and\n // @vorim/shared-types. Without this the SDK throws on { a: 1, b: undefined }\n // while the verifier silently drops b — a cross-module canonical-form\n // divergence that would break signature verification on such events.\n const keys = Object.keys(obj).filter(k => obj[k] !== undefined).sort();\n const parts = keys.map(k => JSON.stringify(k) + ':' + jcsCanonicalise(obj[k]));\n return '{' + parts.join(',') + '}';\n }\n\n // undefined, function, symbol, bigint — not JSON-representable\n throw new Error(`jcsCanonicalise: unsupported value type: ${typeof value}`);\n}\n\n// ─── SHA-256 ──────────────────────────────────────────────────────────────\n\nasync function sha256Hex(input: string | Uint8Array): Promise<string> {\n const bytes = typeof input === 'string' ? new TextEncoder().encode(input) : input;\n\n // Node.js Web Crypto (Node 18+) supports digest. Browser Web Crypto does too.\n // Fall back to node:crypto if Web Crypto is unavailable.\n const subtle = (globalThis as any).crypto?.subtle;\n if (subtle) {\n const buf = await subtle.digest('SHA-256', bytes);\n return Array.from(new Uint8Array(buf))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n }\n\n // Node fallback\n const nodeCrypto = await import('node:crypto');\n return nodeCrypto.createHash('sha256').update(bytes).digest('hex');\n}\n\n// ─── Public API ───────────────────────────────────────────────────────────\n\n/**\n * Hash a single tool definition. Returns `sha256:<hex>`.\n *\n * Canonical form (v1):\n * JCS-canonicalised JSON of `{name, description, schema}` where\n * absent fields substitute `description: \"\"` and `schema: {}`.\n */\nexport async function hashTool(tool: CatalogueTool): Promise<string> {\n const normalised = {\n name: tool.name,\n description: tool.description ?? '',\n schema: tool.schema ?? {},\n };\n const hex = await sha256Hex(jcsCanonicalise(normalised));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash an entire tool catalogue. Returns `sha256:<hex>`.\n *\n * Reordering tools does NOT change the hash (tool hashes sorted\n * lexicographically before concatenation). Adding, removing, or\n * modifying a tool DOES change the hash.\n *\n * Per-tool hashing first means a verifier comparing two catalogue\n * hashes that differ can also be given the per-tool hashes to\n * identify which specific tool changed.\n */\nexport async function hashToolCatalogue(tools: CatalogueTool[]): Promise<string> {\n if (tools.length === 0) {\n // Empty catalogue has a deterministic, stable hash distinct from \"no field\"\n return `sha256:${await sha256Hex('[]')}`;\n }\n const perTool = await Promise.all(tools.map(hashTool));\n perTool.sort();\n const hex = await sha256Hex(perTool.join(''));\n return `sha256:${hex}`;\n}\n\n/**\n * Hash a system prompt. Returns `sha256:<hex>`.\n *\n * The prompt is UTF-8 encoded and hashed verbatim — no normalisation.\n * If a caller wants to ignore whitespace or comment differences, they\n * should normalise before calling. The intent here is deterministic\n * reproducibility, not semantic equivalence.\n */\nexport async function hashSystemPrompt(prompt: string): Promise<string> {\n const hex = await sha256Hex(prompt);\n return `sha256:${hex}`;\n}\n\n/**\n * Convenience: hash the previous event's canonical bytes for use in\n * the prev_event_hash field of hash-chained ingest. Caller provides\n * the canonical bytes (use canonicalPayloadV0 from the main module).\n */\nexport async function hashPreviousEvent(canonicalBytes: string): Promise<string> {\n const hex = await sha256Hex(canonicalBytes);\n return `sha256:${hex}`;\n}\n\n// ─── Replay context — framework integration helper ────────────────────────\n\n/**\n * Raw inputs the integration captures from the framework. Set by the\n * integration's config; turned into hashes by {@link prepareReplayContext}.\n */\nexport interface ReplayInputs {\n /** Stable identifier for the model. E.g. `\"anthropic:claude-opus-4-8\"`. */\n modelVersion?: string;\n /** Tools available to the agent at call time. Hashed via {@link hashToolCatalogue}. */\n tools?: CatalogueTool[];\n /** System prompt active at call time. Hashed via {@link hashSystemPrompt}. */\n systemPrompt?: string;\n}\n\n/**\n * Pre-computed hashes ready to attach to audit events. The three keys\n * match the audit_events column names.\n */\nexport interface ReplayContext {\n model_version?: string;\n tool_catalogue_hash?: string;\n system_prompt_hash?: string;\n}\n\n/**\n * Compute replay context once from raw inputs. Use at integration\n * setup time so each emit can attach the hashes without re-hashing.\n *\n * Returns an object suitable for spreading into an AuditEventInput:\n * `await vorim.emit({ ...event, ...replayContext })`\n *\n * If a field is absent in the inputs, it is absent in the result\n * (not the empty string). That keeps the event lean.\n */\nexport async function prepareReplayContext(\n inputs: ReplayInputs,\n): Promise<ReplayContext> {\n const ctx: ReplayContext = {};\n if (inputs.modelVersion) ctx.model_version = inputs.modelVersion;\n if (inputs.tools) ctx.tool_catalogue_hash = await hashToolCatalogue(inputs.tools);\n if (inputs.systemPrompt) ctx.system_prompt_hash = await hashSystemPrompt(inputs.systemPrompt);\n return ctx;\n}\n","// ============================================================================\n// VORIM SDK — Anthropic/Claude Integration\n// Wraps Anthropic tool use with Vorim permission checks, audit trails,\n// and agent identity. Works with the Anthropic Node.js SDK (messages API\n// with tool use).\n//\n// Peer dependency: @anthropic-ai/sdk >=0.30.0\n// ============================================================================\n\nimport type { VorimSDK } from '../index.js';\nimport type { PermissionScope, AuditEventInput } from '../types.js';\nimport { runtimeGate, type EscalationPolicy } from './_runtime-gate.js';\nimport {\n prepareReplayContext,\n type ReplayInputs,\n type ReplayContext,\n type CatalogueTool,\n} from '../replay.js';\n\n// ─── Re-declared Anthropic types (peer dependency — not bundled) ──────────\n\ninterface AnthropicTool {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\ninterface ToolUseBlock {\n type: 'tool_use';\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n\ninterface ToolResultBlock {\n type: 'tool_result';\n tool_use_id: string;\n content: string;\n is_error?: boolean;\n}\n\n// ─── Configuration ────────────────────────────────────────────────────────\n\nexport interface VorimToolDefinition<TArgs = Record<string, unknown>, TResult = unknown> {\n /** Tool name (must match the tool name sent to Claude). */\n name: string;\n /** Description shown to Claude. */\n description: string;\n /** JSON Schema for the tool's input. */\n input_schema: Record<string, unknown>;\n /** The function to execute when the tool is called. */\n execute: (args: TArgs) => Promise<TResult>;\n /** Vorim permission scope required. @default 'agent:execute' */\n permission?: PermissionScope;\n}\n\nexport interface VorimAnthropicConfig {\n /** Vorim SDK instance. */\n vorim: VorimSDK;\n /** The Vorim agent_id. */\n agentId: string;\n /** Default permission scope for tools without an explicit one. @default 'agent:execute' */\n defaultPermission?: PermissionScope;\n /** Whether to emit audit events asynchronously (fire-and-forget). @default true */\n asyncAudit?: boolean;\n /**\n * Gate each tool call through the runtime-control decision API\n * (`beforeAction`) instead of the lightweight permission check. @default false\n *\n * When true, tool calls are evaluated against live policy rules and the\n * returned decisionId is linked onto each audit event's decision_id.\n * Requires the runtime_control plan feature (Growth+) and consumes decision\n * quota. When false (default) the fast permission check is used.\n */\n useRuntimeControl?: boolean;\n /**\n * What to do when a runtime decision returns `escalate` (a human must\n * approve). Only applies when `useRuntimeControl` is true.\n * - `wait` (default) block and poll until a human approves/denies, or the\n * timeout elapses (→ deny). Requires the `runtime:decide` scope.\n * - `deny` fail closed without waiting.\n * - `allow` proceed (fail OPEN — dev/trusted use only).\n * @default 'wait'\n */\n onEscalation?: EscalationPolicy;\n /** Timeout (ms) for `onEscalation: 'wait'`. @default 300000 */\n escalationTimeoutMs?: number;\n /**\n * Replayable agent decision evidence (VAIP -02). Hashes attached to\n * every audit event. If `replay.tools` is omitted, the registry's\n * own tool list is used automatically. Not covered by v0 canonical\n * signature form.\n */\n replay?: ReplayInputs;\n}\n\n// ─── Tool Registry ────────────────────────────────────────────────────────\n\n/**\n * Manages a set of tools with Vorim permission checks and audit logging.\n * Converts tools to Anthropic's tool format and handles execution of\n * tool_use blocks from Claude's response.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const vorim = createVorim({ apiKey: \"agid_sk_live_...\" });\n * const anthropic = new Anthropic();\n *\n * const registry = new VorimToolRegistry({\n * vorim,\n * agentId: \"agid_acme_a1b2c3d4\",\n * });\n *\n * registry.add({\n * name: \"search_docs\",\n * description: \"Search internal documents\",\n * input_schema: {\n * type: \"object\",\n * properties: { query: { type: \"string\" } },\n * required: [\"query\"],\n * },\n * execute: async ({ query }) => searchDocs(query),\n * permission: \"agent:read\",\n * });\n *\n * const response = await anthropic.messages.create({\n * model: \"claude-sonnet-4-20250514\",\n * max_tokens: 1024,\n * messages,\n * tools: registry.toAnthropicTools(),\n * });\n *\n * // Execute tool_use blocks from response\n * const toolResults = await registry.executeToolUseBlocks(\n * response.content.filter(b => b.type === \"tool_use\")\n * );\n * ```\n */\nexport class VorimToolRegistry {\n private vorim: VorimSDK;\n private agentId: string;\n private defaultPermission: PermissionScope;\n private asyncAudit: boolean;\n private useRuntimeControl: boolean;\n private onEscalation?: EscalationPolicy;\n private escalationTimeoutMs?: number;\n private tools = new Map<string, VorimToolDefinition>();\n private replayInputs: ReplayInputs | undefined;\n private replayCache: Promise<ReplayContext> | null = null;\n\n constructor(config: VorimAnthropicConfig) {\n this.vorim = config.vorim;\n this.agentId = config.agentId;\n this.defaultPermission = config.defaultPermission ?? 'agent:execute';\n this.asyncAudit = config.asyncAudit ?? true;\n this.useRuntimeControl = config.useRuntimeControl ?? false;\n this.onEscalation = config.onEscalation;\n this.escalationTimeoutMs = config.escalationTimeoutMs;\n this.replayInputs = config.replay;\n }\n\n /** Gate a tool call: runtime decision (with decisionId) or permission check. */\n private async gate(\n scope: PermissionScope,\n actionTarget: string,\n payload?: Record<string, unknown>,\n ): Promise<{ allowed: boolean; reason?: string; decisionId?: string }> {\n if (this.useRuntimeControl) {\n return runtimeGate(this.vorim, this.agentId, actionTarget, scope, payload, {\n onEscalation: this.onEscalation,\n escalationTimeoutMs: this.escalationTimeoutMs,\n });\n }\n const { allowed, reason } = await this.vorim.check(this.agentId, scope);\n return { allowed, reason };\n }\n\n private async getReplayContext(): Promise<ReplayContext> {\n if (!this.replayInputs) return {};\n if (!this.replayCache) {\n const inputs: ReplayInputs = {\n ...this.replayInputs,\n tools: this.replayInputs.tools ?? this.deriveCatalogue(),\n };\n this.replayCache = prepareReplayContext(inputs);\n }\n return this.replayCache;\n }\n\n private deriveCatalogue(): CatalogueTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n schema: t.input_schema,\n }));\n }\n\n /** Register a tool. Invalidates the cached tool-catalogue hash. */\n add<TArgs, TResult>(definition: VorimToolDefinition<TArgs, TResult>): this {\n this.tools.set(definition.name, definition as VorimToolDefinition);\n this.replayCache = null;\n return this;\n }\n\n /** Register multiple tools. */\n addAll(definitions: VorimToolDefinition[]): this {\n for (const def of definitions) this.add(def);\n return this;\n }\n\n /** Convert registered tools to Anthropic's tool format. */\n toAnthropicTools(): AnthropicTool[] {\n return [...this.tools.values()].map(t => ({\n name: t.name,\n description: t.description,\n input_schema: t.input_schema,\n }));\n }\n\n /**\n * Execute tool_use blocks from a Claude message response.\n * Each call is checked against Vorim permissions and audited.\n * Returns an array of tool_result blocks ready to send back to Claude.\n */\n async executeToolUseBlocks(toolUseBlocks: ToolUseBlock[]): Promise<ToolResultBlock[]> {\n return Promise.all(\n toolUseBlocks.map(block => this.executeSingleBlock(block)),\n );\n }\n\n private async executeSingleBlock(block: ToolUseBlock): Promise<ToolResultBlock> {\n const definition = this.tools.get(block.name);\n\n if (!definition) {\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Unknown tool: ${block.name}` }),\n is_error: true,\n };\n }\n\n const scope = definition.permission ?? this.defaultPermission;\n\n // 1. Gate: runtime decision (with decisionId linkage) or permission check.\n const { allowed, reason, decisionId } = await this.gate(scope, block.name, block.input as Record<string, unknown>);\n const replayCtx = await this.getReplayContext();\n\n if (!allowed) {\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'denied',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { reason, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: `Permission denied: ${scope}${reason ? ` — ${reason}` : ''}` }),\n is_error: true,\n };\n }\n\n // 2. Execute\n const start = Date.now();\n try {\n const result = await definition.execute(block.input as any);\n const content = typeof result === 'string' ? result : JSON.stringify(result);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'success',\n latency_ms: Date.now() - start,\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return { type: 'tool_result', tool_use_id: block.id, content };\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n\n const event: AuditEventInput = {\n agent_id: this.agentId,\n event_type: 'tool_call',\n action: block.name,\n resource: truncate(JSON.stringify(block.input), 500),\n permission: scope,\n result: 'error',\n latency_ms: Date.now() - start,\n error_code: err instanceof Error ? err.name : 'UNKNOWN',\n ...(decisionId ? { decision_id: decisionId } : {}),\n metadata: { error: errMsg, framework: 'anthropic' },\n ...replayCtx,\n };\n this.emitAudit(event);\n\n return {\n type: 'tool_result',\n tool_use_id: block.id,\n content: JSON.stringify({ error: errMsg }),\n is_error: true,\n };\n }\n }\n\n private emitAudit(event: AuditEventInput): void {\n this.vorim.emit(event).catch(() => {});\n }\n}\n\n// ─── Agent Loop ───────────────────────────────────────────────────────────\n\n/** Minimal Anthropic client interface (avoids importing the full SDK). */\ninterface AnthropicClient {\n messages: {\n create(params: any): Promise<any>;\n };\n}\n\nexport interface VorimAgentLoopConfig extends VorimAnthropicConfig {\n /** Anthropic client instance. */\n anthropic: AnthropicClient;\n /** Model to use. @default 'claude-sonnet-4-20250514' */\n model?: string;\n /** System prompt for the agent. */\n systemPrompt?: string;\n /** Maximum tool-use iterations before stopping. @default 10 */\n maxIterations?: number;\n /** Max tokens per response. @default 1024 */\n maxTokens?: number;\n}\n\n/**\n * Runs a complete agent loop with Claude tool use, Vorim\n * permission enforcement, and audit logging.\n *\n * @example\n * ```ts\n * import Anthropic from \"@anthropic-ai/sdk\";\n * import createVorim from \"@vorim/sdk\";\n * import { runAgentLoop, VorimToolRegistry } from \"@vorim/sdk/integrations/anthropic\";\n *\n * const registry = new VorimToolRegistry({ vorim, agentId });\n * registry.add({ name: \"search\", ... });\n *\n * const response = await runAgentLoop({\n * vorim,\n * agentId,\n * anthropic: new Anthropic(),\n * model: \"claude-sonnet-4-20250514\",\n * systemPrompt: \"You are a helpful assistant.\",\n * registry,\n * userMessage: \"Find docs about onboarding\",\n * });\n * ```\n */\nexport async function runAgentLoop(\n config: VorimAgentLoopConfig & {\n registry: VorimToolRegistry;\n userMessage: string;\n },\n): Promise<string> {\n const {\n anthropic,\n model = 'claude-sonnet-4-20250514',\n systemPrompt,\n maxIterations = 10,\n maxTokens = 1024,\n registry,\n userMessage,\n } = config;\n\n const tools = registry.toAnthropicTools();\n const messages: any[] = [{ role: 'user', content: userMessage }];\n\n for (let i = 0; i < maxIterations; i++) {\n const response = await anthropic.messages.create({\n model,\n max_tokens: maxTokens,\n ...(systemPrompt ? { system: systemPrompt } : {}),\n messages,\n ...(tools.length > 0 ? { tools } : {}),\n });\n\n // If stop_reason is \"end_turn\" — Claude is done\n if (response.stop_reason === 'end_turn' || response.stop_reason !== 'tool_use') {\n const textBlocks = response.content.filter((b: any) => b.type === 'text');\n return textBlocks.map((b: any) => b.text).join('') || '';\n }\n\n // Extract tool_use blocks and execute\n const toolUseBlocks = response.content.filter((b: any) => b.type === 'tool_use');\n const toolResults = await registry.executeToolUseBlocks(toolUseBlocks);\n\n // Append assistant response and tool results to conversation\n messages.push({ role: 'assistant', content: response.content });\n messages.push({ role: 'user', content: toolResults });\n }\n\n return '';\n}\n\n// ─── Agent Registration Helper ───────────────────────────────────────────\n\n/**\n * Registers a new agent with Vorim and returns a ready-to-use tool registry\n * configured for Anthropic/Claude.\n *\n * @example\n * ```ts\n * const { agentId, registry } = await createVorimClaudeAgent({\n * vorim,\n * name: \"claude-assistant\",\n * capabilities: [\"search\", \"calculate\"],\n * scopes: [\"agent:read\", \"agent:execute\"],\n * tools: [searchTool, calcTool],\n * });\n * ```\n */\nexport async function createVorimClaudeAgent(config: {\n vorim: VorimSDK;\n name: string;\n description?: string;\n capabilities: string[];\n scopes: PermissionScope[];\n tools: VorimToolDefinition[];\n}) {\n const { vorim, name, description, capabilities, scopes, tools } = config;\n\n const registration = await vorim.register({\n name,\n description,\n capabilities,\n scopes,\n });\n\n const agentId = registration.agent.agent_id;\n const registry = new VorimToolRegistry({ vorim, agentId });\n registry.addAll(tools);\n\n return {\n agentId,\n registration,\n registry,\n privateKey: registration.private_key,\n };\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────\n\nfunction truncate(str: string, max: number): string {\n return str.length > max ? str.slice(0, max) + '…' : str;\n}\n"],"mappings":"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","names":[]}
@@ -1,4 +1,5 @@
1
- import { PermissionScope, AgentRegistrationResult, VorimSDK } from '../index.cjs';
1
+ import { VorimSDK } from '../index.cjs';
2
+ import { P as PermissionScope, A as AgentRegistrationResult } from '../types-B22WnXEW.cjs';
2
3
 
3
4
  interface CrewMemberConfig {
4
5
  /** Unique role name within the crew (e.g. "researcher", "writer"). */
@@ -1,4 +1,5 @@
1
- import { PermissionScope, AgentRegistrationResult, VorimSDK } from '../index.js';
1
+ import { VorimSDK } from '../index.js';
2
+ import { P as PermissionScope, A as AgentRegistrationResult } from '../types-B22WnXEW.js';
2
3
 
3
4
  interface CrewMemberConfig {
4
5
  /** Unique role name within the crew (e.g. "researcher", "writer"). */
@@ -104,7 +104,7 @@ async function prepareReplayContext(inputs) {
104
104
 
105
105
  // src/integrations/langchain.ts
106
106
  function wrapTool(tool, config) {
107
- const { vorim, agentId, permissionMap = {}, defaultPermission = "agent:execute", asyncAudit = true, replay } = config;
107
+ const { vorim, agentId, permissionMap = {}, defaultPermission = "agent:execute", asyncAudit = true, replay, framework = "langchain" } = config;
108
108
  const originalCall = tool._call.bind(tool);
109
109
  const getReplayCtx = makeReplayContextGetter(replay);
110
110
  tool._call = async function vorimGuardedCall(arg, runManager, parentConfig) {
@@ -119,10 +119,10 @@ function wrapTool(tool, config) {
119
119
  resource: truncate(JSON.stringify(arg), 500),
120
120
  permission: scope,
121
121
  result: "denied",
122
- metadata: { reason, framework: "langchain" },
122
+ metadata: { reason, framework },
123
123
  ...replayCtx
124
124
  };
125
- emitAudit(vorim, event2, asyncAudit);
125
+ await emitAudit(vorim, event2, asyncAudit);
126
126
  throw new Error(`Vorim: permission denied for "${tool.name}" \u2014 scope "${scope}"${reason ? `: ${reason}` : ""}`);
127
127
  }
128
128
  const start = Date.now();
@@ -139,10 +139,10 @@ function wrapTool(tool, config) {
139
139
  result: "error",
140
140
  latency_ms: Date.now() - start,
141
141
  error_code: err instanceof Error ? err.name : "UNKNOWN",
142
- metadata: { error: err instanceof Error ? err.message : String(err), framework: "langchain" },
142
+ metadata: { error: err instanceof Error ? err.message : String(err), framework },
143
143
  ...replayCtx
144
144
  };
145
- emitAudit(vorim, event2, asyncAudit);
145
+ await emitAudit(vorim, event2, asyncAudit);
146
146
  throw err;
147
147
  }
148
148
  const event = {
@@ -153,10 +153,10 @@ function wrapTool(tool, config) {
153
153
  permission: scope,
154
154
  result: "success",
155
155
  latency_ms: Date.now() - start,
156
- metadata: { framework: "langchain" },
156
+ metadata: { framework },
157
157
  ...replayCtx
158
158
  };
159
- emitAudit(vorim, event, asyncAudit);
159
+ await emitAudit(vorim, event, asyncAudit);
160
160
  return result;
161
161
  };
162
162
  return tool;
@@ -293,10 +293,9 @@ function emitAudit(vorim, event, async) {
293
293
  if (async) {
294
294
  vorim.emit(event).catch(() => {
295
295
  });
296
- } else {
297
- vorim.emit(event).catch(() => {
298
- });
296
+ return;
299
297
  }
298
+ return vorim.emit(event).then(() => void 0).catch(() => void 0);
300
299
  }
301
300
  function deriveCatalogueFromLangChainTools(tools) {
302
301
  return tools.map((t) => {