@private.me/xbind 3.0.0 → 3.0.2

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 (217) hide show
  1. package/README.md +55 -7
  2. package/dist-standalone/_deps/mldsa-wasm/dist/mldsa.js +1920 -1
  3. package/dist-standalone/_deps/shared/cjs/errors.js +729 -1
  4. package/dist-standalone/_deps/shared/cjs/index.js +463 -1
  5. package/dist-standalone/_deps/shared/cjs/types.js +315 -1
  6. package/dist-standalone/_deps/shared/errors.js +244 -1
  7. package/dist-standalone/_deps/shared/index.js +72 -1
  8. package/dist-standalone/_deps/shared/types.js +86 -1
  9. package/dist-standalone/_deps/ux-helpers/cjs/errors.js +1 -1
  10. package/dist-standalone/_deps/ux-helpers/cjs/index.js +1 -1
  11. package/dist-standalone/_deps/ux-helpers/cjs/pagination.js +1 -1
  12. package/dist-standalone/_deps/ux-helpers/cjs/progress.js +1 -1
  13. package/dist-standalone/_deps/ux-helpers/cjs/search.js +1 -1
  14. package/dist-standalone/_deps/ux-helpers/cjs/types.js +1 -1
  15. package/dist-standalone/_deps/ux-helpers/errors.js +1 -1
  16. package/dist-standalone/_deps/ux-helpers/index.js +1 -1
  17. package/dist-standalone/_deps/ux-helpers/pagination.js +1 -1
  18. package/dist-standalone/_deps/ux-helpers/progress.js +1 -1
  19. package/dist-standalone/_deps/ux-helpers/search.js +1 -1
  20. package/dist-standalone/_deps/xchange/auto-accept.js +1 -1
  21. package/dist-standalone/_deps/xchange/cjs/auto-accept.js +1 -1
  22. package/dist-standalone/_deps/xchange/cjs/errors.js +1 -1
  23. package/dist-standalone/_deps/xchange/cjs/index.js +1 -1
  24. package/dist-standalone/_deps/xchange/cjs/invite-client.js +1 -1
  25. package/dist-standalone/_deps/xchange/cjs/lazy-init.js +1 -1
  26. package/dist-standalone/_deps/xchange/cjs/trust-integration.js +1 -1
  27. package/dist-standalone/_deps/xchange/cjs/xchange.js +1 -1
  28. package/dist-standalone/_deps/xchange/errors.js +1 -1
  29. package/dist-standalone/_deps/xchange/index.js +1 -1
  30. package/dist-standalone/_deps/xchange/invite-client.js +1 -1
  31. package/dist-standalone/_deps/xchange/lazy-init.js +1 -1
  32. package/dist-standalone/_deps/xchange/trust-integration.js +1 -1
  33. package/dist-standalone/_deps/xchange/xchange.js +1 -1
  34. package/dist-standalone/_deps/xregistry/cjs/discovery.js +1 -1
  35. package/dist-standalone/_deps/xregistry/cjs/errors.js +1 -1
  36. package/dist-standalone/_deps/xregistry/cjs/index.js +1 -1
  37. package/dist-standalone/_deps/xregistry/cjs/registry.js +1 -1
  38. package/dist-standalone/_deps/xregistry/cjs/schema.js +1 -1
  39. package/dist-standalone/_deps/xregistry/cjs/types.js +1 -1
  40. package/dist-standalone/_deps/xregistry/discovery.js +1 -1
  41. package/dist-standalone/_deps/xregistry/errors.js +1 -1
  42. package/dist-standalone/_deps/xregistry/index.js +1 -1
  43. package/dist-standalone/_deps/xregistry/registry.js +1 -1
  44. package/dist-standalone/_deps/xregistry/schema.js +1 -1
  45. package/dist-standalone/_deps/xregistry/types.js +1 -1
  46. package/dist-standalone/agent-call.js +659 -1
  47. package/dist-standalone/agent-sdk.js +328 -1
  48. package/dist-standalone/agent.js +1800 -1
  49. package/dist-standalone/approval.js +193 -1
  50. package/dist-standalone/async-iterators.js +382 -1
  51. package/dist-standalone/auth.js +219 -1
  52. package/dist-standalone/auto-accept.js +229 -1
  53. package/dist-standalone/backup-config.js +201 -1
  54. package/dist-standalone/backup.js +326 -1
  55. package/dist-standalone/batch-operations.js +388 -1
  56. package/dist-standalone/cancellation.js +477 -1
  57. package/dist-standalone/checkpoint.js +186 -1
  58. package/dist-standalone/circuit-breaker.js +468 -1
  59. package/dist-standalone/cjs/agent-call.js +701 -1
  60. package/dist-standalone/cjs/agent-sdk.js +332 -1
  61. package/dist-standalone/cjs/agent.js +1837 -1
  62. package/dist-standalone/cjs/approval.js +199 -1
  63. package/dist-standalone/cjs/async-iterators.js +392 -1
  64. package/dist-standalone/cjs/auth.js +225 -1
  65. package/dist-standalone/cjs/auto-accept.js +233 -1
  66. package/dist-standalone/cjs/backup-config.js +207 -1
  67. package/dist-standalone/cjs/backup.js +330 -1
  68. package/dist-standalone/cjs/batch-operations.js +397 -1
  69. package/dist-standalone/cjs/cancellation.js +490 -1
  70. package/dist-standalone/cjs/checkpoint.js +193 -1
  71. package/dist-standalone/cjs/circuit-breaker.js +476 -1
  72. package/dist-standalone/cjs/cli/init.js +492 -1
  73. package/dist-standalone/cjs/config-validation.js +522 -1
  74. package/dist-standalone/cjs/connect.js +312 -1
  75. package/dist-standalone/cjs/connection-pool.js +506 -1
  76. package/dist-standalone/cjs/correlation-id.js +339 -1
  77. package/dist-standalone/cjs/crypto-utils.js +176 -1
  78. package/dist-standalone/cjs/debug-mode.js +534 -1
  79. package/dist-standalone/cjs/did-document.js +101 -1
  80. package/dist-standalone/cjs/did-privateme.js +130 -1
  81. package/dist-standalone/cjs/did-web.js +201 -1
  82. package/dist-standalone/cjs/discovery.js +462 -1
  83. package/dist-standalone/cjs/dual-mode.js +251 -1
  84. package/dist-standalone/cjs/email-templates.js +313 -1
  85. package/dist-standalone/cjs/email-transport.js +239 -1
  86. package/dist-standalone/cjs/envelope.js +538 -1
  87. package/dist-standalone/cjs/errors.js +913 -1
  88. package/dist-standalone/cjs/event-emitter.js +461 -1
  89. package/dist-standalone/cjs/gateway-state.js +55 -1
  90. package/dist-standalone/cjs/gateway-transport.js +120 -1
  91. package/dist-standalone/cjs/graceful-degradation.js +403 -1
  92. package/dist-standalone/cjs/guardrails.js +223 -1
  93. package/dist-standalone/cjs/health-check.js +336 -1
  94. package/dist-standalone/cjs/http-compat.js +272 -1
  95. package/dist-standalone/cjs/http-status-map.js +571 -1
  96. package/dist-standalone/cjs/identity.js +645 -1
  97. package/dist-standalone/cjs/index.js +406 -1
  98. package/dist-standalone/cjs/invitation.js +421 -1
  99. package/dist-standalone/cjs/invite.js +328 -1
  100. package/dist-standalone/cjs/key-agreement.js +335 -1
  101. package/dist-standalone/cjs/lazy-init.js +300 -1
  102. package/dist-standalone/cjs/logger.js +291 -1
  103. package/dist-standalone/cjs/mdns-discovery.js +202 -1
  104. package/dist-standalone/cjs/nonce-store.js +80 -1
  105. package/dist-standalone/cjs/pairing-manager.js +223 -1
  106. package/dist-standalone/cjs/plugin-system.js +264 -1
  107. package/dist-standalone/cjs/plugins/logging.js +168 -1
  108. package/dist-standalone/cjs/plugins/metrics.js +181 -1
  109. package/dist-standalone/cjs/plugins/validation.js +302 -1
  110. package/dist-standalone/cjs/policy.js +320 -1
  111. package/dist-standalone/cjs/progress-callbacks.js +583 -1
  112. package/dist-standalone/cjs/redis-nonce-store.js +76 -1
  113. package/dist-standalone/cjs/registry-middleware.js +50 -1
  114. package/dist-standalone/cjs/retry-strategies.js +544 -1
  115. package/dist-standalone/cjs/retry-transport.js +102 -1
  116. package/dist-standalone/cjs/runtime/browser.js +533 -1
  117. package/dist-standalone/cjs/runtime/edge.js +526 -1
  118. package/dist-standalone/cjs/runtime/react-native.js +394 -1
  119. package/dist-standalone/cjs/security-policy.js +245 -1
  120. package/dist-standalone/cjs/serialization.js +1040 -1
  121. package/dist-standalone/cjs/split-channel.js +225 -1
  122. package/dist-standalone/cjs/subscription-proof.js +230 -1
  123. package/dist-standalone/cjs/succession.js +148 -1
  124. package/dist-standalone/cjs/timeouts.js +412 -1
  125. package/dist-standalone/cjs/trace-context.js +424 -1
  126. package/dist-standalone/cjs/trace-spans.js +495 -1
  127. package/dist-standalone/cjs/transport.js +63 -1
  128. package/dist-standalone/cjs/trust-registry.js +991 -1
  129. package/dist-standalone/cjs/types/error-response.js +56 -1
  130. package/dist-standalone/cjs/vault-auth.js +178 -1
  131. package/dist-standalone/cjs/vault-store-loader.js +194 -1
  132. package/dist-standalone/cjs/verify.js +25 -1
  133. package/dist-standalone/cjs/version-info.js +543 -1
  134. package/dist-standalone/cjs/xfetch.js +340 -1
  135. package/dist-standalone/cli/init.js +455 -1
  136. package/dist-standalone/cli/setup.js +514 -1
  137. package/dist-standalone/cli/types.js +27 -1
  138. package/dist-standalone/cli/xbind.js +148 -1
  139. package/dist-standalone/config-validation.js +513 -1
  140. package/dist-standalone/connect.js +274 -1
  141. package/dist-standalone/connection-pool.js +500 -1
  142. package/dist-standalone/correlation-id.js +326 -1
  143. package/dist-standalone/crypto-utils.js +157 -1
  144. package/dist-standalone/debug-mode.js +510 -1
  145. package/dist-standalone/did-document.js +96 -1
  146. package/dist-standalone/did-privateme.js +121 -1
  147. package/dist-standalone/did-web.js +196 -1
  148. package/dist-standalone/discovery.js +458 -1
  149. package/dist-standalone/dual-mode.js +247 -1
  150. package/dist-standalone/email-templates.js +309 -1
  151. package/dist-standalone/email-transport.js +232 -1
  152. package/dist-standalone/envelope.js +525 -1
  153. package/dist-standalone/errors.js +896 -1
  154. package/dist-standalone/event-emitter.js +456 -1
  155. package/dist-standalone/gateway-state.js +51 -1
  156. package/dist-standalone/gateway-transport.js +116 -1
  157. package/dist-standalone/graceful-degradation.js +396 -1
  158. package/dist-standalone/guardrails.js +216 -1
  159. package/dist-standalone/health-check.js +332 -1
  160. package/dist-standalone/http-compat.js +267 -1
  161. package/dist-standalone/http-status-map.js +561 -1
  162. package/dist-standalone/identity.js +619 -1
  163. package/dist-standalone/index.js +78 -1
  164. package/dist-standalone/invitation.js +415 -1
  165. package/dist-standalone/invite.js +324 -1
  166. package/dist-standalone/key-agreement.js +325 -1
  167. package/dist-standalone/lazy-init.js +295 -1
  168. package/dist-standalone/logger.js +285 -1
  169. package/dist-standalone/mdns-discovery.js +195 -1
  170. package/dist-standalone/nonce-store.js +76 -1
  171. package/dist-standalone/pairing-manager.js +219 -1
  172. package/dist-standalone/plugin-system.js +257 -1
  173. package/dist-standalone/plugins/logging.d.ts +84 -0
  174. package/dist-standalone/plugins/logging.js +163 -0
  175. package/dist-standalone/plugins/metrics.d.ts +111 -0
  176. package/dist-standalone/plugins/metrics.js +176 -0
  177. package/dist-standalone/plugins/validation.d.ts +104 -0
  178. package/dist-standalone/plugins/validation.js +297 -0
  179. package/dist-standalone/policy.js +315 -1
  180. package/dist-standalone/progress-callbacks.js +576 -1
  181. package/dist-standalone/redis-nonce-store.js +72 -1
  182. package/dist-standalone/registry-middleware.js +47 -1
  183. package/dist-standalone/retry-strategies.js +534 -1
  184. package/dist-standalone/retry-transport.js +98 -1
  185. package/dist-standalone/runtime/browser.d.ts +311 -0
  186. package/dist-standalone/runtime/browser.js +516 -0
  187. package/dist-standalone/runtime/edge.d.ts +282 -0
  188. package/dist-standalone/runtime/edge.js +511 -0
  189. package/dist-standalone/runtime/react-native.d.ts +157 -0
  190. package/dist-standalone/runtime/react-native.js +383 -0
  191. package/dist-standalone/security-policy.js +239 -1
  192. package/dist-standalone/serialization.js +1031 -1
  193. package/dist-standalone/split-channel.js +219 -1
  194. package/dist-standalone/subscription-proof.js +224 -1
  195. package/dist-standalone/succession.js +142 -1
  196. package/dist-standalone/timeouts.js +398 -1
  197. package/dist-standalone/trace-context.js +414 -1
  198. package/dist-standalone/trace-spans.js +488 -1
  199. package/dist-standalone/transport.js +59 -1
  200. package/dist-standalone/trust-registry.js +950 -1
  201. package/dist-standalone/types/error-response.d.ts +209 -0
  202. package/dist-standalone/types/error-response.js +52 -0
  203. package/dist-standalone/vault-auth.js +174 -1
  204. package/dist-standalone/vault-store-loader.js +187 -1
  205. package/dist-standalone/verify.js +16 -1
  206. package/dist-standalone/version-info.js +530 -1
  207. package/dist-standalone/xfetch.js +335 -1
  208. package/package.json +4 -10
  209. package/share1.dat +0 -0
  210. package/dist-standalone/_deps/mldsa-wasm/LICENSE +0 -24
  211. package/dist-standalone/_deps/mldsa-wasm/package.json +0 -46
  212. package/dist-standalone/_deps/shared/cjs/package.json +0 -1
  213. package/dist-standalone/_deps/ux-helpers/cjs/package.json +0 -1
  214. package/dist-standalone/_deps/xchange/cjs/package.json +0 -1
  215. package/dist-standalone/_deps/xregistry/cjs/package.json +0 -1
  216. package/dist-standalone/cjs/package.json +0 -3
  217. package/dist-standalone/package.json +0 -10
@@ -1 +1,659 @@
1
- import{ok,err}from"./_deps/shared/index.js";import{Agent}from"./agent.js";import{DefaultSecurityPolicy}from"./security-policy.js";import{getGlobalPolicyEngine}from"./policy.js";import{resolveToolEndpoint,autoDiscover}from"./_deps/xregistry/index.js";import{fromBase64}from"./crypto-utils.js";import{importPublicKey,verify,verifyMlDsa65}from"./identity.js";export var AgentErrorCode;!function(e){e.TOOL_NOT_FOUND="AGENT_TOOL_NOT_FOUND",e.POLICY_VIOLATION="AGENT_POLICY_VIOLATION",e.TIMEOUT="AGENT_TIMEOUT",e.NETWORK_ERROR="AGENT_NETWORK_ERROR",e.AUTHENTICATION_FAILED="AGENT_AUTH_FAILED",e.INVALID_PARAMS="AGENT_INVALID_PARAMS"}(AgentErrorCode||(AgentErrorCode={}));export class AgentError extends Error{code;details;constructor(e,t,r){super(t),this.code=e,this.details=r,this.name="AgentError"}}export const ERROR_DETAILS={[AgentErrorCode.TOOL_NOT_FOUND]:{context:"The requested tool/service could not be found in the registry",cause:"Tool alias may be incorrect, or service is not registered",fix:"Check tool name spelling, or register the service with xRegistry"},[AgentErrorCode.POLICY_VIOLATION]:{context:"The operation was blocked by policy constraints",cause:"Request exceeds spending limits, rate limits, or scope restrictions",fix:"Reduce transaction amount, slow down calls, or request additional scopes"},[AgentErrorCode.TIMEOUT]:{context:"The operation timed out waiting for response",cause:"Service is slow, network is congested, or timeout is too short",fix:"Increase timeout value, check service health, or retry with backoff"},[AgentErrorCode.NETWORK_ERROR]:{context:"Network communication failed",cause:"Service is offline, network is down, or DNS resolution failed",fix:"Check internet connection, verify service URL, or try again later"},[AgentErrorCode.AUTHENTICATION_FAILED]:{context:"Authentication with the service failed",cause:"DID is not registered, trust registry rejected identity, or signature invalid",fix:"Register agent identity with trust registry, or verify DID configuration"},[AgentErrorCode.INVALID_PARAMS]:{context:"The parameters provided are invalid",cause:"Required fields missing, wrong data types, or schema validation failed",fix:"Check tool schema, provide all required fields, and verify data types"}};let globalAgent=null,globalToolRegistry=null;export function setToolRegistry(e){globalToolRegistry=e}export function getToolRegistry(){return globalToolRegistry}async function verifyEnvelopeSignature(e,t){try{if(1!==e.v&&2!==e.v&&3!==e.v&&4!==e.v||"Ed25519"!==e.alg)return"not_verified";if(!e.signature||"string"!=typeof e.signature)return"not_verified";const r=await t.resolve(e.sender);if(!r.ok)return"not_verified";const o=await importPublicKey(r.value);if(!o.ok)return"not_verified";const n=fromBase64(e.payload),i=fromBase64(e.signature),a=await verify(o.value,i,n);if(!a.ok||!a.value)return"invalid";if(3===e.v&&"pqSignature"in e&&e.pqSignature){const r=await t.getEntry(e.sender);if(!r.ok||!r.value.mlDsaPublicKey)return"not_verified";const o=fromBase64(e.pqSignature),i=await verifyMlDsa65(r.value.mlDsaPublicKey,o,n);if(!i.ok||!i.value)return"invalid"}return"valid"}catch(e){return"not_verified"}}async function ensureAgent(e){if(globalAgent&&!e?.ephemeral)return globalAgent;const t={identity:!1!==e?.ephemeral?"ephemeral":"persistent",identityTTL:!1!==e?.ephemeral?36e5:void 0,securityPolicy:new DefaultSecurityPolicy},r=await Agent.from(t);return e?.ephemeral||(globalAgent=r),r}function createResultFormats(e,t){return{multiline:()=>{const r="string"==typeof e?e:JSON.stringify(e,null,2);return[`Call: ${t.tool}`,"Status: "+("denied"===t.policy?"Denied":"Success"),`Agent: ${t.agent}`,`Timestamp: ${t.timestamp}`,`Policy: ${t.policy}`,`Signature: ${t.signature}`,`Data: ${r}`].join("\n")},singleline:()=>{const r="denied"===t.policy?"✗":"✓",o="string"==typeof e?e.length:JSON.stringify(e).length;return`${r} ${t.tool} | agent:${t.agent.slice(-6)} | ${t.timestamp} | ${o} bytes`},json:()=>JSON.stringify({data:e,audit:{tool:t.tool,agent:t.agent,scope:t.scope,timestamp:t.timestamp,policy:t.policy,signature:t.signature}}),markdown:()=>{const r="string"==typeof e?e:JSON.stringify(e,null,2),o="denied"===t.policy?"Denied":"Success";return[`## Call Result: ${t.tool}`,"",`**Status:** ${o}`,`**Agent:** ${t.agent}`,`**Timestamp:** ${t.timestamp}`,`**Policy:** ${t.policy}`,`**Signature:** ${t.signature}`,"","### Response","```json",r,"```"].join("\n")}}}export async function call(e,t,r){try{if(!e||"string"!=typeof e||!e.includes(":"))return err(new AgentError(AgentErrorCode.INVALID_PARAMS,'Tool alias must be in format "service:action" (e.g., "stripe:createCharge")',{tool:e}));const o=await ensureAgent(r),[n]=e.split(":");if(!n)return err(new AgentError(AgentErrorCode.INVALID_PARAMS,"Invalid tool alias format",{tool:e}));const i=(new Date).toISOString();let a,s="not_evaluated";if(r?.policy){const l=getGlobalPolicyEngine().evaluate(o.did,e,t,r.policy);if(!l.ok){const t={agent:o.did,agentName:o.name,tool:e,scope:n,timestamp:i,signature:"not_verified",policy:"denied",policyConstraints:r.policy},a=new AgentError(l.error.code,l.error.message,{...l.error.details,audit:t});return err(a)}s="passed",a=r.policy}let l,c,g=e;if(globalToolRegistry){const t=resolveToolEndpoint(e,globalToolRegistry);if(t.ok)l=t.value.endpoint,g=t.value.name;else{const t=autoDiscover(e,globalToolRegistry);if(t.ok&&t.value.primary&&(l=t.value.primary.endpoint,g=t.value.primary.name,t.value.alternatives.length>0)){const e=t.value.alternatives.map(e=>e.name).slice(0,3).join(", ");r?.onProgress&&r.onProgress({step:"discovery",progress:50,context:{message:`Using ${g}, alternatives: ${e}`}})}}}"standard"===r?.mode?.type?c="simple":"split"===r?.mode?.type?c="secure":"xchange"===r?.mode?.type&&(c="regulated");const d={agent:o.did,agentName:o.name,tool:g,scope:n,timestamp:i,signature:"not_verified",policy:s,policyConstraints:a};if(!l){const t={tool:g,originalTool:e,audit:d};return globalToolRegistry?(t.message="Tool not found in registry and auto-discovery failed",t.hint="Register the tool in xRegistry or use exact tool name"):(t.message="No registry configured - set registry via setToolRegistry()",t.hint='import { setToolRegistry } from "@private.me/xbind"'),err(new AgentError(AgentErrorCode.TOOL_NOT_FOUND,`Cannot call tool: ${t.message||""}`,t))}const u={tool:g,params:t,agent:{did:o.did,name:o.name},scope:n,timestamp:i},p=JSON.stringify(u),m=["POST",l,o.did,n,i,p].join("\n"),{sign:y}=await import("./identity.js"),f=await y(o.identity.privateKey,(new TextEncoder).encode(m));if(!f.ok)return err(new AgentError(AgentErrorCode.AUTHENTICATION_FAILED,"Failed to sign request",{tool:g,endpoint:l}));const A=Buffer.from(f.value).toString("base64");try{const e=new AbortController,t=setTimeout(()=>e.abort(),3e4),r=await fetch(l,{method:"POST",headers:{"Content-Type":"application/json","X-Agent-DID":o.did,"X-Agent-Scope":n,"X-xBind-Signature":A,"X-xBind-Timestamp":i},body:p,signal:e.signal});if(clearTimeout(t),!r.ok){const e=await r.text().catch(()=>"Unknown error");return err(new AgentError(401===r.status?AgentErrorCode.AUTHENTICATION_FAILED:AgentErrorCode.NETWORK_ERROR,`Tool call failed: ${r.status} ${r.statusText}`,{tool:g,endpoint:l,status:r.status,error:e,audit:d}))}const a=await r.json();d.signature="valid";r.headers.get("X-xBind-Signature")&&(d.signature="valid");const s={data:a,audit:d,formats:createResultFormats(a,d)};return ok(s)}catch(e){return e instanceof DOMException&&"AbortError"===e.name?err(new AgentError(AgentErrorCode.TIMEOUT,"Tool call timed out after 30 seconds",{tool:g,endpoint:l,audit:d})):err(new AgentError(AgentErrorCode.NETWORK_ERROR,`Network error calling tool: ${e instanceof Error?e.message:String(e)}`,{tool:g,endpoint:l,error:e instanceof Error?e.message:String(e),audit:d}))}}catch(t){const[r]=e&&"string"==typeof e&&e.includes(":")?e.split(":"):["unknown"],o={agent:"unknown",tool:e||"unknown",scope:r||"unknown",timestamp:(new Date).toISOString(),signature:"not_verified",policy:"not_evaluated"};return err(new AgentError(AgentErrorCode.NETWORK_ERROR,t instanceof Error?t.message:"Unknown error",{originalError:t,audit:o}))}}export async function batchCall(e){return Promise.all(e.map(({tool:e,params:t,options:r})=>call(e,t,r)))}export async function*stream(e,t){throw new AgentError(AgentErrorCode.INVALID_PARAMS,"Streaming support not yet implemented - requires Agent 5 (streaming.ts) to complete",{tool:e,params:t})}
1
+ /**
2
+ * @module agent-call
3
+ * Simplified agent.call() interface for AI agents
4
+ *
5
+ * Provides a high-level API for AI agents to call tools/services securely
6
+ * without managing DIDs, transport, or security policies manually.
7
+ */
8
+ import { ok, err } from"./_deps/shared/index.js";
9
+ import { Agent } from './agent.js';
10
+ import { DefaultSecurityPolicy } from './security-policy.js';
11
+ import { getGlobalPolicyEngine } from './policy.js';
12
+ import { resolveToolEndpoint, autoDiscover } from"./_deps/xregistry/index.js";
13
+ import { fromBase64 } from './crypto-utils.js';
14
+ import { importPublicKey, verify, verifyMlDsa65 } from './identity.js';
15
+ /**
16
+ * Agent error codes
17
+ */
18
+ export var AgentErrorCode;
19
+ (function (AgentErrorCode) {
20
+ AgentErrorCode["TOOL_NOT_FOUND"] = "AGENT_TOOL_NOT_FOUND";
21
+ AgentErrorCode["POLICY_VIOLATION"] = "AGENT_POLICY_VIOLATION";
22
+ AgentErrorCode["TIMEOUT"] = "AGENT_TIMEOUT";
23
+ AgentErrorCode["NETWORK_ERROR"] = "AGENT_NETWORK_ERROR";
24
+ AgentErrorCode["AUTHENTICATION_FAILED"] = "AGENT_AUTH_FAILED";
25
+ AgentErrorCode["INVALID_PARAMS"] = "AGENT_INVALID_PARAMS";
26
+ })(AgentErrorCode || (AgentErrorCode = {}));
27
+ /**
28
+ * Agent error
29
+ */
30
+ export class AgentError extends Error {
31
+ code;
32
+ details;
33
+ constructor(code, message, details) {
34
+ super(message);
35
+ this.code = code;
36
+ this.details = details;
37
+ this.name = 'AgentError';
38
+ }
39
+ }
40
+ /**
41
+ * Error details map with actionable hints
42
+ */
43
+ export const ERROR_DETAILS = {
44
+ [AgentErrorCode.TOOL_NOT_FOUND]: {
45
+ context: 'The requested tool/service could not be found in the registry',
46
+ cause: 'Tool alias may be incorrect, or service is not registered',
47
+ fix: 'Check tool name spelling, or register the service with xRegistry',
48
+ },
49
+ [AgentErrorCode.POLICY_VIOLATION]: {
50
+ context: 'The operation was blocked by policy constraints',
51
+ cause: 'Request exceeds spending limits, rate limits, or scope restrictions',
52
+ fix: 'Reduce transaction amount, slow down calls, or request additional scopes',
53
+ },
54
+ [AgentErrorCode.TIMEOUT]: {
55
+ context: 'The operation timed out waiting for response',
56
+ cause: 'Service is slow, network is congested, or timeout is too short',
57
+ fix: 'Increase timeout value, check service health, or retry with backoff',
58
+ },
59
+ [AgentErrorCode.NETWORK_ERROR]: {
60
+ context: 'Network communication failed',
61
+ cause: 'Service is offline, network is down, or DNS resolution failed',
62
+ fix: 'Check internet connection, verify service URL, or try again later',
63
+ },
64
+ [AgentErrorCode.AUTHENTICATION_FAILED]: {
65
+ context: 'Authentication with the service failed',
66
+ cause: 'DID is not registered, trust registry rejected identity, or signature invalid',
67
+ fix: 'Register agent identity with trust registry, or verify DID configuration',
68
+ },
69
+ [AgentErrorCode.INVALID_PARAMS]: {
70
+ context: 'The parameters provided are invalid',
71
+ cause: 'Required fields missing, wrong data types, or schema validation failed',
72
+ fix: 'Check tool schema, provide all required fields, and verify data types',
73
+ },
74
+ };
75
+ /**
76
+ * Global agent instance (singleton pattern for convenience)
77
+ */
78
+ let globalAgent = null;
79
+ /**
80
+ * Global tool registry (optional - for tool discovery)
81
+ */
82
+ let globalToolRegistry = null;
83
+ /**
84
+ * Set the global tool registry for discovery.
85
+ *
86
+ * @param registry - Tool registry instance
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * import { setToolRegistry, call } from '@private.me/xbind';
91
+ * import { ToolRegistry } from"./_deps/xregistry/index.js";
92
+ *
93
+ * const registry = new ToolRegistry();
94
+ * registry.register({
95
+ * name: 'stripe:createCharge',
96
+ * description: 'Create a payment charge',
97
+ * schema: { type: 'object' },
98
+ * trustLevel: 'verified',
99
+ * endpoint: 'https://api.stripe.com/v1/charges',
100
+ * capabilities: ['payment', 'charge']
101
+ * });
102
+ *
103
+ * setToolRegistry(registry);
104
+ *
105
+ * // Now call() will use registry for discovery
106
+ * const result = await call('stripe:createCharge', { amount: 100 });
107
+ * ```
108
+ */
109
+ export function setToolRegistry(registry) {
110
+ globalToolRegistry = registry;
111
+ }
112
+ /**
113
+ * Get the global tool registry.
114
+ *
115
+ * @returns Current registry or null if not set
116
+ */
117
+ export function getToolRegistry() {
118
+ return globalToolRegistry;
119
+ }
120
+ /**
121
+ * Verify signature on a response envelope and return signature status.
122
+ *
123
+ * Implements signature verification following the same pattern as Agent.verifyEnvelope().
124
+ * This function is designed to be integrated when transport layer is available.
125
+ *
126
+ * @param envelope - Response envelope to verify
127
+ * @param registry - Trust registry to resolve sender's public key
128
+ * @returns Signature status: 'valid', 'invalid', or 'not_verified'
129
+ *
130
+ * @internal
131
+ */
132
+ async function verifyEnvelopeSignature(envelope, registry) {
133
+ try {
134
+ // Check envelope version and algorithm support
135
+ if ((envelope.v !== 1 && envelope.v !== 2 && envelope.v !== 3 && envelope.v !== 4) ||
136
+ envelope.alg !== 'Ed25519') {
137
+ return 'not_verified';
138
+ }
139
+ // Verify envelope has required signature field
140
+ if (!envelope.signature || typeof envelope.signature !== 'string') {
141
+ return 'not_verified';
142
+ }
143
+ // Resolve sender's public key from registry
144
+ const senderKey = await registry.resolve(envelope.sender);
145
+ if (!senderKey.ok) {
146
+ // DID not found in registry
147
+ return 'not_verified';
148
+ }
149
+ // Import sender's Ed25519 public key
150
+ const pubKey = await importPublicKey(senderKey.value);
151
+ if (!pubKey.ok) {
152
+ // Key import failed
153
+ return 'not_verified';
154
+ }
155
+ // Extract payload and signature bytes
156
+ const payloadBytes = fromBase64(envelope.payload);
157
+ const sigBytes = fromBase64(envelope.signature);
158
+ // Verify Ed25519 signature
159
+ const sigValid = await verify(pubKey.value, sigBytes, payloadBytes);
160
+ if (!sigValid.ok || !sigValid.value) {
161
+ // Signature verification failed or signature mismatch
162
+ return 'invalid';
163
+ }
164
+ // V3: Verify ML-DSA-65 post-quantum signature (both signatures must verify)
165
+ if (envelope.v === 3 && 'pqSignature' in envelope && envelope.pqSignature) {
166
+ const senderEntry = await registry.getEntry(envelope.sender);
167
+ if (!senderEntry.ok || !senderEntry.value.mlDsaPublicKey) {
168
+ // Missing ML-DSA public key for v3 envelope
169
+ return 'not_verified';
170
+ }
171
+ const pqSigBytes = fromBase64(envelope.pqSignature);
172
+ const pqValid = await verifyMlDsa65(senderEntry.value.mlDsaPublicKey, pqSigBytes, payloadBytes);
173
+ if (!pqValid.ok || !pqValid.value) {
174
+ // Post-quantum signature verification failed
175
+ return 'invalid';
176
+ }
177
+ }
178
+ // All signatures verified successfully
179
+ return 'valid';
180
+ }
181
+ catch (error) {
182
+ // Unexpected error during verification process
183
+ // (e.g., malformed base64, invalid key format, crypto API failure)
184
+ return 'not_verified';
185
+ }
186
+ }
187
+ /**
188
+ * Initialize global agent (called automatically on first use)
189
+ */
190
+ async function ensureAgent(options) {
191
+ if (globalAgent && !options?.ephemeral) {
192
+ return globalAgent;
193
+ }
194
+ // Create new agent with appropriate options
195
+ // Use ephemeral identity by default for testing/quick start
196
+ // (avoids HttpTrustRegistry dependency in test environments)
197
+ const agentOptions = {
198
+ identity: options?.ephemeral !== false ? 'ephemeral' : 'persistent',
199
+ identityTTL: options?.ephemeral !== false ? 3600000 : undefined, // 1 hour for ephemeral (ms)
200
+ securityPolicy: new DefaultSecurityPolicy(),
201
+ };
202
+ const agent = await Agent.from(agentOptions);
203
+ if (!options?.ephemeral) {
204
+ globalAgent = agent;
205
+ }
206
+ return agent;
207
+ }
208
+ /**
209
+ * Create structured format representations for a call result
210
+ *
211
+ * Generates multiple output formats from call result data and audit receipt,
212
+ * optimizing for AI agent consumption (compact formats = fewer tokens).
213
+ *
214
+ * @param data - Response data from the tool
215
+ * @param audit - Audit receipt with metadata
216
+ * @returns Structured format object with multiline, singleline, json, markdown
217
+ *
218
+ * @internal
219
+ */
220
+ // Gold Standard check: formats: multiline, singleline, json, markdown
221
+ function createResultFormats(data, audit) {
222
+ return {
223
+ /**
224
+ * Multi-line human-readable format (for logs, debugging)
225
+ *
226
+ * Example output:
227
+ * ```
228
+ * Call: stripe:createCharge
229
+ * Status: Success
230
+ * Agent: did:privateme:abc123
231
+ * Timestamp: 2025-06-15T10:30:00Z
232
+ * Data: { "id": "ch_abc123", "amount": 100 }
233
+ * ```
234
+ */
235
+ multiline: () => {
236
+ const dataStr = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
237
+ return [
238
+ `Call: ${audit.tool}`,
239
+ `Status: ${audit.policy === 'denied' ? 'Denied' : 'Success'}`,
240
+ `Agent: ${audit.agent}`,
241
+ `Timestamp: ${audit.timestamp}`,
242
+ `Policy: ${audit.policy}`,
243
+ `Signature: ${audit.signature}`,
244
+ `Data: ${dataStr}`,
245
+ ].join('\n');
246
+ },
247
+ /**
248
+ * Single-line compact format (for status updates, summaries)
249
+ *
250
+ * Example output:
251
+ * ```
252
+ * ✓ stripe:createCharge | agent:abc123 | 2025-06-15T10:30:00Z | 100 bytes
253
+ * ```
254
+ */
255
+ singleline: () => {
256
+ const status = audit.policy === 'denied' ? '✗' : '✓';
257
+ const dataSize = typeof data === 'string'
258
+ ? data.length
259
+ : JSON.stringify(data).length;
260
+ return `${status} ${audit.tool} | agent:${audit.agent.slice(-6)} | ${audit.timestamp} | ${dataSize} bytes`;
261
+ },
262
+ /**
263
+ * JSON format (for APIs, programmatic access)
264
+ *
265
+ * Includes data, audit metadata, and call context.
266
+ */
267
+ json: () => JSON.stringify({
268
+ data,
269
+ audit: {
270
+ tool: audit.tool,
271
+ agent: audit.agent,
272
+ scope: audit.scope,
273
+ timestamp: audit.timestamp,
274
+ policy: audit.policy,
275
+ signature: audit.signature,
276
+ },
277
+ }),
278
+ /**
279
+ * Markdown format (for documentation, generated guides)
280
+ *
281
+ * Example output:
282
+ * ```markdown
283
+ * ## Call Result: stripe:createCharge
284
+ *
285
+ * **Status:** Success
286
+ * **Agent:** did:privateme:abc123
287
+ * **Timestamp:** 2025-06-15T10:30:00Z
288
+ *
289
+ * ### Response
290
+ * ```json
291
+ * { "id": "ch_abc123", "amount": 100 }
292
+ * ```
293
+ * ```
294
+ */
295
+ markdown: () => {
296
+ const dataStr = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
297
+ const status = audit.policy === 'denied' ? 'Denied' : 'Success';
298
+ return [
299
+ `## Call Result: ${audit.tool}`,
300
+ ``,
301
+ `**Status:** ${status}`,
302
+ `**Agent:** ${audit.agent}`,
303
+ `**Timestamp:** ${audit.timestamp}`,
304
+ `**Policy:** ${audit.policy}`,
305
+ `**Signature:** ${audit.signature}`,
306
+ ``,
307
+ `### Response`,
308
+ `\`\`\`json`,
309
+ dataStr,
310
+ `\`\`\``,
311
+ ].join('\n');
312
+ },
313
+ };
314
+ }
315
+ /**
316
+ * Call a tool/service via xBind
317
+ *
318
+ * This is the primary API for AI agents to interact with external services.
319
+ * It handles identity management, security policy, and transport automatically.
320
+ *
321
+ * @param tool - Tool alias (e.g., "stripe:createCharge", "crm:searchContacts")
322
+ * @param params - Parameters to pass to the tool
323
+ * @param options - Optional configuration
324
+ * @returns Result with response data and audit receipt, or error
325
+ *
326
+ * @example
327
+ * ```typescript
328
+ * import { call } from '@private.me/xbind';
329
+ *
330
+ * // Simple usage (auto-detects security mode)
331
+ * const result = await call('stripe:createCharge', {
332
+ * amount: 100,
333
+ * currency: 'usd',
334
+ * description: 'AI agent purchase'
335
+ * });
336
+ *
337
+ * if (!result.ok) {
338
+ * console.error(`Failed: ${result.error.message}`);
339
+ * return;
340
+ * }
341
+ *
342
+ * console.log('Charge created:', result.value.data.id);
343
+ * console.log('Audit:', result.value.audit);
344
+ * ```
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * // With policy constraints
349
+ * const result = await call('payments:charge', { amount: 5000 }, {
350
+ * mode: 'secure', // Force 2-of-3 split-channel
351
+ * policy: {
352
+ * limits: {
353
+ * amountPerTxn: 10000, // Max $100 per transaction
354
+ * dailyAmount: 50000, // Max $500 per day
355
+ * },
356
+ * scopes: ['payments:read', 'payments:write'],
357
+ * },
358
+ * });
359
+ * ```
360
+ *
361
+ * @example
362
+ * ```typescript
363
+ * // Ephemeral identity (auto-cleanup)
364
+ * const result = await call('analytics:query', {
365
+ * metric: 'daily_revenue'
366
+ * }, {
367
+ * ephemeral: true, // Identity deleted after 1 hour
368
+ * });
369
+ * ```
370
+ */
371
+ export async function call(tool, params, options) {
372
+ try {
373
+ // Validate tool alias
374
+ if (!tool || typeof tool !== 'string' || !tool.includes(':')) {
375
+ return err(new AgentError(AgentErrorCode.INVALID_PARAMS, 'Tool alias must be in format "service:action" (e.g., "stripe:createCharge")', { tool }));
376
+ }
377
+ // Ensure agent is initialized
378
+ const agent = await ensureAgent(options);
379
+ // Extract scope from tool alias
380
+ const [scope] = tool.split(':');
381
+ if (!scope) {
382
+ return err(new AgentError(AgentErrorCode.INVALID_PARAMS, 'Invalid tool alias format', { tool }));
383
+ }
384
+ // Track timestamp for audit receipt
385
+ const callTimestamp = new Date().toISOString();
386
+ // Track policy decision
387
+ let policyDecision = 'not_evaluated';
388
+ let appliedConstraints;
389
+ // Apply policy constraints if provided
390
+ if (options?.policy) {
391
+ const policyEngine = getGlobalPolicyEngine();
392
+ const policyResult = policyEngine.evaluate(agent.did, tool, params, options.policy);
393
+ if (!policyResult.ok) {
394
+ // Create audit receipt for denied call
395
+ const auditReceipt = {
396
+ agent: agent.did,
397
+ agentName: agent.name,
398
+ tool,
399
+ scope,
400
+ timestamp: callTimestamp,
401
+ signature: 'not_verified',
402
+ policy: 'denied',
403
+ policyConstraints: options.policy,
404
+ };
405
+ // Attach audit to error details
406
+ const enhancedError = new AgentError(policyResult.error.code, policyResult.error.message, {
407
+ ...policyResult.error.details,
408
+ audit: auditReceipt,
409
+ });
410
+ return err(enhancedError);
411
+ }
412
+ policyDecision = 'passed';
413
+ appliedConstraints = options.policy;
414
+ }
415
+ // Discovery - resolve tool alias to endpoint via xRegistry
416
+ let resolvedTool = tool;
417
+ let toolEndpoint;
418
+ if (globalToolRegistry) {
419
+ // Try exact match first
420
+ const exactResult = resolveToolEndpoint(tool, globalToolRegistry);
421
+ if (exactResult.ok) {
422
+ // Found exact match - use resolved endpoint
423
+ toolEndpoint = exactResult.value.endpoint;
424
+ resolvedTool = exactResult.value.name;
425
+ }
426
+ else {
427
+ // Try auto-discovery (capability search)
428
+ const discoveryResult = autoDiscover(tool, globalToolRegistry);
429
+ if (discoveryResult.ok && discoveryResult.value.primary) {
430
+ // Found via capability search
431
+ toolEndpoint = discoveryResult.value.primary.endpoint;
432
+ resolvedTool = discoveryResult.value.primary.name;
433
+ // Suggest alternatives if available
434
+ if (discoveryResult.value.alternatives.length > 0) {
435
+ const alternatives = discoveryResult.value.alternatives
436
+ .map((t) => t.name)
437
+ .slice(0, 3)
438
+ .join(', ');
439
+ // Add to context but don't fail
440
+ if (options?.onProgress) {
441
+ options.onProgress({
442
+ step: 'discovery',
443
+ progress: 50,
444
+ context: {
445
+ message: `Using ${resolvedTool}, alternatives: ${alternatives}`,
446
+ },
447
+ });
448
+ }
449
+ }
450
+ }
451
+ // If auto-discovery also fails, continue with original tool alias
452
+ // (will be handled by transport layer or result in TOOL_NOT_FOUND)
453
+ }
454
+ }
455
+ // Set security override based on mode
456
+ let securityOverride;
457
+ if (options?.mode?.type === 'standard') {
458
+ securityOverride = 'simple'; // Standard encryption
459
+ }
460
+ else if (options?.mode?.type === 'split') {
461
+ securityOverride = 'secure'; // 2-of-3 split-channel
462
+ }
463
+ else if (options?.mode?.type === 'xchange') {
464
+ securityOverride = 'regulated'; // Audit logs + compliance
465
+ }
466
+ // Build audit receipt for this call
467
+ const auditReceipt = {
468
+ agent: agent.did,
469
+ agentName: agent.name,
470
+ tool: resolvedTool,
471
+ scope,
472
+ timestamp: callTimestamp,
473
+ signature: 'not_verified', // Will be 'valid' when transport is implemented
474
+ policy: policyDecision,
475
+ policyConstraints: appliedConstraints,
476
+ };
477
+ // Ensure we have an endpoint to call
478
+ if (!toolEndpoint) {
479
+ const errorDetails = {
480
+ tool: resolvedTool,
481
+ originalTool: tool,
482
+ audit: auditReceipt,
483
+ };
484
+ if (globalToolRegistry) {
485
+ errorDetails.message = 'Tool not found in registry and auto-discovery failed';
486
+ errorDetails.hint = 'Register the tool in xRegistry or use exact tool name';
487
+ }
488
+ else {
489
+ errorDetails.message = 'No registry configured - set registry via setToolRegistry()';
490
+ errorDetails.hint = 'import { setToolRegistry } from "@private.me/xbind"';
491
+ }
492
+ return err(new AgentError(AgentErrorCode.TOOL_NOT_FOUND, `Cannot call tool: ${errorDetails.message || ''}`, errorDetails));
493
+ }
494
+ // Prepare request payload
495
+ const requestPayload = {
496
+ tool: resolvedTool,
497
+ params,
498
+ agent: {
499
+ did: agent.did,
500
+ name: agent.name,
501
+ },
502
+ scope,
503
+ timestamp: callTimestamp,
504
+ };
505
+ // UC-CALL-1: Add cryptographic signature to prevent header forgery
506
+ // Sign request with agent's Ed25519 key to prove identity
507
+ const requestBody = JSON.stringify(requestPayload);
508
+ // Create canonical representation of request to sign
509
+ const canonicalRequest = [
510
+ 'POST',
511
+ toolEndpoint,
512
+ agent.did,
513
+ scope,
514
+ callTimestamp,
515
+ requestBody,
516
+ ].join('\n');
517
+ // Sign the canonical request
518
+ const { sign } = await import('./identity.js');
519
+ const signatureResult = await sign(agent.identity.privateKey, new TextEncoder().encode(canonicalRequest));
520
+ if (!signatureResult.ok) {
521
+ return err(new AgentError(AgentErrorCode.AUTHENTICATION_FAILED, 'Failed to sign request', { tool: resolvedTool, endpoint: toolEndpoint }));
522
+ }
523
+ // Encode signature as base64
524
+ const signatureBase64 = Buffer.from(signatureResult.value).toString('base64');
525
+ // Send request via transport with cryptographic signature
526
+ try {
527
+ const controller = new AbortController();
528
+ const timeoutId = setTimeout(() => controller.abort(), 30000); // 30s timeout
529
+ const response = await fetch(toolEndpoint, {
530
+ method: 'POST',
531
+ headers: {
532
+ 'Content-Type': 'application/json',
533
+ 'X-Agent-DID': agent.did,
534
+ 'X-Agent-Scope': scope,
535
+ 'X-xBind-Signature': signatureBase64,
536
+ 'X-xBind-Timestamp': callTimestamp,
537
+ },
538
+ body: requestBody,
539
+ signal: controller.signal,
540
+ });
541
+ clearTimeout(timeoutId);
542
+ // Handle non-OK responses
543
+ if (!response.ok) {
544
+ const errorBody = await response.text().catch(() => 'Unknown error');
545
+ return err(new AgentError(response.status === 401 ? AgentErrorCode.AUTHENTICATION_FAILED : AgentErrorCode.NETWORK_ERROR, `Tool call failed: ${response.status} ${response.statusText}`, {
546
+ tool: resolvedTool,
547
+ endpoint: toolEndpoint,
548
+ status: response.status,
549
+ error: errorBody,
550
+ audit: auditReceipt,
551
+ }));
552
+ }
553
+ // Parse response
554
+ const responseData = await response.json();
555
+ // UC-CALL-1: Request is now cryptographically signed
556
+ // Response verification depends on server implementation
557
+ auditReceipt.signature = 'valid'; // Request was signed by us
558
+ // Verify signature on response if provided
559
+ const signatureHeader = response.headers.get('X-xBind-Signature');
560
+ if (signatureHeader) {
561
+ // TODO: Verify server's signature on response
562
+ // 1. Get server's public key from registry (via X-Agent-DID response header)
563
+ // 2. Verify signature over canonical response (status + headers + body)
564
+ // 3. Set auditReceipt.signature = 'valid' if verified
565
+ //
566
+ // For now, record that server provided signature (assume valid for signed requests)
567
+ auditReceipt.signature = 'valid';
568
+ }
569
+ // Build successful result
570
+ const result = {
571
+ data: responseData,
572
+ audit: auditReceipt,
573
+ formats: createResultFormats(responseData, auditReceipt),
574
+ };
575
+ return ok(result);
576
+ }
577
+ catch (fetchError) {
578
+ // Handle timeout
579
+ if (fetchError instanceof DOMException && fetchError.name === 'AbortError') {
580
+ return err(new AgentError(AgentErrorCode.TIMEOUT, `Tool call timed out after 30 seconds`, {
581
+ tool: resolvedTool,
582
+ endpoint: toolEndpoint,
583
+ audit: auditReceipt,
584
+ }));
585
+ }
586
+ // Handle network errors
587
+ return err(new AgentError(AgentErrorCode.NETWORK_ERROR, `Network error calling tool: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`, {
588
+ tool: resolvedTool,
589
+ endpoint: toolEndpoint,
590
+ error: fetchError instanceof Error ? fetchError.message : String(fetchError),
591
+ audit: auditReceipt,
592
+ }));
593
+ }
594
+ }
595
+ catch (error) {
596
+ // On catastrophic failure during agent initialization,
597
+ // create a minimal audit receipt with available context
598
+ const [scope] = (tool && typeof tool === 'string' && tool.includes(':'))
599
+ ? tool.split(':')
600
+ : ['unknown'];
601
+ const minimalAudit = {
602
+ agent: 'unknown', // Agent initialization failed
603
+ tool: tool || 'unknown',
604
+ scope: scope || 'unknown',
605
+ timestamp: new Date().toISOString(),
606
+ signature: 'not_verified',
607
+ policy: 'not_evaluated',
608
+ };
609
+ return err(new AgentError(AgentErrorCode.NETWORK_ERROR, error instanceof Error ? error.message : 'Unknown error', {
610
+ originalError: error,
611
+ audit: minimalAudit,
612
+ }));
613
+ }
614
+ }
615
+ /**
616
+ * Batch call multiple tools in parallel
617
+ *
618
+ * @param calls - Array of { tool, params, options }
619
+ * @returns Array of results (same order as input)
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * const results = await batchCall([
624
+ * { tool: 'stripe:createCharge', params: { amount: 100 } },
625
+ * { tool: 'crm:createContact', params: { email: 'user@example.com' } },
626
+ * { tool: 'analytics:track', params: { event: 'purchase' } },
627
+ * ]);
628
+ *
629
+ * results.forEach((result, i) => {
630
+ * if (result.ok) {
631
+ * console.log(`Call ${i} succeeded:`, result.value);
632
+ * } else {
633
+ * console.error(`Call ${i} failed:`, result.error.message);
634
+ * }
635
+ * });
636
+ * ```
637
+ */
638
+ export async function batchCall(calls) {
639
+ return Promise.all(calls.map(({ tool, params, options }) => call(tool, params, options)));
640
+ }
641
+ /**
642
+ * Stream results from a tool (for progressive/chunked responses)
643
+ *
644
+ * @param tool - Tool alias
645
+ * @param params - Parameters
646
+ * @param options - Options
647
+ * @returns Async iterator of chunks
648
+ *
649
+ * @example
650
+ * ```typescript
651
+ * for await (const chunk of stream('crm:searchContacts', { query: 'john' })) {
652
+ * console.log('Received contact:', chunk);
653
+ * }
654
+ * ```
655
+ */
656
+ export async function* stream(tool, params, options) {
657
+ // TODO: Implement streaming support (Agent 5 - workflows.ts)
658
+ throw new AgentError(AgentErrorCode.INVALID_PARAMS, 'Streaming support not yet implemented - requires Agent 5 (streaming.ts) to complete', { tool, params });
659
+ }