{"version":3,"sources":["../../src/errors.ts","../../src/integrations/_shared.ts","../../src/integrations/langchain.ts"],"names":["tool"],"mappings":"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","file":"langgraph.cjs","sourcesContent":["import type { CardVerifyResult, ToolCallResult } from \"./types\";\n\n/** Base class for all errors thrown by the SDK. */\nexport class AxioRankError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"AxioRankError\";\n  }\n}\n\n/** Thrown when the API key is missing, invalid, or revoked (HTTP 401). */\nexport class AxioRankAuthError extends AxioRankError {\n  constructor(message = \"Invalid or missing AxioRank API key\") {\n    super(message);\n    this.name = \"AxioRankAuthError\";\n  }\n}\n\n/** Thrown for malformed requests, timeouts, and other non-2xx responses. */\nexport class AxioRankRequestError extends AxioRankError {\n  status?: number;\n  constructor(message: string, status?: number) {\n    super(message);\n    this.name = \"AxioRankRequestError\";\n    this.status = status;\n  }\n}\n\n/** Thrown by {@link AxioRank.enforce} when the gateway denies the call. */\nexport class AxioRankDeniedError extends AxioRankError {\n  result: ToolCallResult;\n  constructor(result: ToolCallResult) {\n    super(`AxioRank denied tool call: ${result.reason}`);\n    this.name = \"AxioRankDeniedError\";\n    this.result = result;\n  }\n}\n\n/** Thrown by the chat guards when a prompt or completion is blocked locally. */\nexport class AxioRankGuardError extends AxioRankError {\n  /** Which side of the model call was blocked. */\n  phase: \"prompt\" | \"completion\";\n  risk: number;\n  reason: string;\n  constructor(phase: \"prompt\" | \"completion\", reason: string, risk: number) {\n    super(`AxioRank blocked the ${phase}: ${reason} (risk ${risk}).`);\n    this.name = \"AxioRankGuardError\";\n    this.phase = phase;\n    this.reason = reason;\n    this.risk = risk;\n  }\n}\n\n/** Thrown by {@link AxioRank.enforceCard} when the preflight verdict is `deny`. */\nexport class AxioRankCardDeniedError extends AxioRankError {\n  result: CardVerifyResult;\n  constructor(result: CardVerifyResult) {\n    super(`AxioRank denied card preflight: ${result.reason}`);\n    this.name = \"AxioRankCardDeniedError\";\n    this.result = result;\n  }\n}\n\n/** Thrown when the workspace is rate-limited (HTTP 429) after retries are exhausted. */\nexport class AxioRankRateLimitError extends AxioRankError {\n  retryAfterSec?: number;\n  constructor(message = \"AxioRank rate limit exceeded\", retryAfterSec?: number) {\n    super(message);\n    this.name = \"AxioRankRateLimitError\";\n    this.retryAfterSec = retryAfterSec;\n  }\n}\n\n/** Thrown by {@link constructEvent} when a webhook signature is missing, stale, or invalid. */\nexport class AxioRankWebhookSignatureError extends AxioRankError {\n  constructor(message = \"AxioRank webhook signature verification failed\") {\n    super(message);\n    this.name = \"AxioRankWebhookSignatureError\";\n  }\n}\n","/**\n * Shared core for the framework adapters. Every adapter funnels its tool calls\n * through {@link runGuarded} so the allow / deny / hold semantics stay identical\n * across frameworks - the only per-framework work is pulling out the tool name\n * and arguments and handing back the right shape.\n */\nimport { AxioRankDeniedError } from \"../errors\";\nimport type { ToolCallParams, ToolCallResult, ToolResultParams } from \"../types\";\n\n/**\n * Anything that can score a tool call: an {@link AxioRank} client or a\n * trace-bound handle from {@link AxioRank.trace}. Accepting either lets an\n * adapter share one trace id across a whole agent run - so the gateway can\n * correlate multi-step kill chains (read a secret -> exfiltrate it) - just by\n * passing `axio.trace()` instead of the bare client.\n */\nexport interface ToolCaller {\n  toolCall(params: ToolCallParams): Promise<ToolCallResult>;\n  /** Optional: report a tool result for IFC taint tracking (the client + trace handle have it). */\n  reportResult?(params: ToolResultParams): Promise<void>;\n  /** Optional: inspect a tool result and resolve with the decision (enforce-capable). */\n  inspectResult?(params: ToolResultParams): Promise<ToolCallResult>;\n}\n\n/** Tools whose OUTPUT is untrusted external data (mirrors the server classifier). */\nfunction isUntrustedSource(tool: string): boolean {\n  const t = tool.toLowerCase();\n  return (\n    /fetch|http|browse|scrape|crawl|email|gmail|imap|inbox|message/.test(t) ||\n    t.endsWith(\".read\") ||\n    t.includes(\"readfile\") ||\n    t.includes(\"file.get\") ||\n    t.startsWith(\"fs.\") ||\n    t.endsWith(\".query\") ||\n    t.endsWith(\".select\") ||\n    t.includes(\"db.read\") ||\n    t.includes(\"sql\")\n  );\n}\n\nconst MAX_RESULT_CHARS = 100_000;\n\nfunction stringifyResult(output: unknown): string {\n  let s: string;\n  if (typeof output === \"string\") s = output;\n  else {\n    try {\n      s = JSON.stringify(output) ?? String(output);\n    } catch {\n      s = String(output);\n    }\n  }\n  return s.length > MAX_RESULT_CHARS ? s.slice(0, MAX_RESULT_CHARS) : s;\n}\n\n/**\n * Fire-and-forget: after an allowed untrusted-source tool runs, report its output\n * so the gateway can taint-track it. Only when the workspace enforces IFC (the\n * `ifc` hint on the verdict) - never a wasted call otherwise. Never blocks.\n */\nfunction maybeReportResult(\n  caller: ToolCaller,\n  name: string,\n  result: ToolCallResult,\n  output: unknown,\n): void {\n  if (!result.ifc || !caller.reportResult || !isUntrustedSource(name)) return;\n  void caller.reportResult({ tool: name, resultText: stringifyResult(output) }).catch(() => {});\n}\n\n/**\n * Inspect an untrusted-source tool's OUTPUT for indirect prompt injection (and\n * leaked secrets/PII) BEFORE the agent ingests it. Unlike {@link maybeReportResult}\n * this is AWAITED - the verdict decides whether the agent sees the output - so it\n * only runs when the adapter opts in via {@link GuardOptions.inspectResults}.\n *\n * Returns the deny verdict to act on, or null to let the output through. An\n * inspection failure resolves to null: a transient gateway error must never\n * break the agent (the server is monitor-first and already audited what it saw).\n */\nasync function inspectOutput(\n  caller: ToolCaller,\n  name: string,\n  output: unknown,\n  opts: GuardOptions,\n): Promise<ToolCallResult | null> {\n  if (!opts.inspectResults || !caller.inspectResult || !isUntrustedSource(name)) {\n    return null;\n  }\n  let verdict: ToolCallResult;\n  try {\n    verdict = await caller.inspectResult({\n      tool: name,\n      resultText: stringifyResult(output),\n    });\n  } catch {\n    return null;\n  }\n  return verdict.decision === \"deny\" ? verdict : null;\n}\n\n/** What to do when AxioRank denies a tool call. */\nexport type OnDeny = \"throw\" | \"return\";\n\nexport interface GuardOptions {\n  /**\n   * On a `deny` verdict: `\"throw\"` (default) raises {@link AxioRankDeniedError}\n   * so the step fails hard; `\"return\"` returns a short, model-readable refusal\n   * string instead, so an agent sees why it was blocked and can re-plan.\n   * @default \"throw\"\n   */\n  onDeny?: OnDeny;\n  /**\n   * Observe every verdict (allow and deny) - handy for logging / metrics. Never\n   * affects control flow; an error thrown here is swallowed.\n   */\n  onDecision?: (result: ToolCallResult) => void;\n  /**\n   * Also inspect each untrusted-source tool's OUTPUT for indirect prompt\n   * injection (and leaked secrets/PII) before the agent ingests it. A `deny`\n   * verdict on the output is handled exactly like a denied call (per\n   * {@link GuardOptions.onDeny}). Adds one awaited round trip per such tool, so\n   * it's opt-in. Enforcement is gated server-side by the workspace's\n   * `inspect_tool_results` setting (monitor-first until enabled).\n   * @default false\n   */\n  inspectResults?: boolean;\n}\n\n/** The refusal a model sees when {@link GuardOptions.onDeny} is `\"return\"`. */\nexport function denialMessage(name: string, result: ToolCallResult): string {\n  return `AxioRank blocked the tool call \\`${name}\\`: ${result.reason} (risk ${result.risk}).`;\n}\n\n/**\n * Score `name(args)` through AxioRank, then either run `exec` (allow) or handle\n * the deny per `opts.onDeny`. The single chokepoint every framework adapter\n * funnels through.\n *\n * A `require_approval` hold is invisible here: {@link AxioRank.toolCall} waits\n * it out and only ever surfaces the final `allow` / `deny`.\n */\nexport async function runGuarded<T>(\n  caller: ToolCaller,\n  name: string,\n  args: Record<string, unknown>,\n  exec: () => T | Promise<T>,\n  opts: GuardOptions = {},\n): Promise<T | string> {\n  const result = await caller.toolCall({ tool: name, arguments: args });\n  if (opts.onDecision) {\n    try {\n      opts.onDecision(result);\n    } catch {\n      // An observer must never change the outcome of the call.\n    }\n  }\n  if (result.decision === \"deny\") {\n    if (opts.onDeny === \"return\") return denialMessage(name, result);\n    throw new AxioRankDeniedError(result);\n  }\n  const output = await exec();\n\n  // Opt-in: inspect the tool's OUTPUT for indirect prompt injection. A deny is\n  // handled exactly like a denied call - block the poisoned output from reaching\n  // the model (throw) or hand back a refusal string (onDeny === \"return\").\n  const outputDeny = await inspectOutput(caller, name, output, opts);\n  if (outputDeny) {\n    if (opts.onDeny === \"return\") return denialMessage(name, outputDeny);\n    throw new AxioRankDeniedError(outputDeny);\n  }\n  // inspectResult already taint-tracks server-side, so only the legacy\n  // fire-and-forget report is needed when output inspection is off.\n  if (!opts.inspectResults) maybeReportResult(caller, name, result, output);\n  return output;\n}\n\n/**\n * Wrap a tool's `execute(args, …)` handler so every invocation is scored by\n * AxioRank first. Framework-agnostic: works anywhere a tool handler takes the\n * arguments object as its first parameter (the Vercel AI SDK and the OpenAI\n * Agents SDK both fit). Any extra parameters the framework passes -\n * `toolCallId`, `context`, `abortSignal`, … - are forwarded untouched.\n */\nexport function guardExecute<Args extends Record<string, unknown>, R>(\n  name: string,\n  execute: (args: Args, ...rest: unknown[]) => R | Promise<R>,\n  caller: ToolCaller,\n  opts: GuardOptions = {},\n): (args: Args, ...rest: unknown[]) => Promise<R | string> {\n  return (args, ...rest) =>\n    runGuarded(\n      caller,\n      name,\n      (args ?? {}) as Record<string, unknown>,\n      () => execute(args, ...rest),\n      opts,\n    );\n}\n","/**\n * AxioRank adapter for LangChain.js - also covers LangGraph.js, which builds on\n * the same tools.\n *\n * Wrap your tools so each call's arguments are scored by AxioRank before the\n * tool runs:\n *\n * @example\n * ```ts\n * import { AxioRank } from \"@axiorank/sdk\";\n * import { guardTools } from \"@axiorank/sdk/langchain\";\n * import { createReactAgent } from \"@langchain/langgraph/prebuilt\";\n *\n * const axio = new AxioRank({ apiKey: process.env.AXIORANK_KEY! });\n * const agent = createReactAgent({\n *   llm,\n *   tools: guardTools(myTools, axio, { onDeny: \"return\" }),\n * });\n * ```\n *\n * Enforcement is by *wrapping the tool* (a guarded tool scores before it runs),\n * not via a callback handler: LangChain.js runs callback handlers on an async\n * queue and executes the tool regardless of a handler throwing, so a callback\n * cannot reliably block a call. `onDeny: \"return\"` is the natural choice for an\n * agent - the model sees the refusal as the tool result and can re-plan.\n */\nimport { tool } from \"@langchain/core/tools\";\nimport type { GuardOptions, ToolCaller } from \"./_shared\";\nimport { runGuarded } from \"./_shared\";\n\nexport { denialMessage, guardExecute } from \"./_shared\";\nexport type { GuardOptions, OnDeny, ToolCaller } from \"./_shared\";\n\n/** The parts of a LangChain tool the adapter needs. Typed loosely so any\n * StructuredTool / DynamicStructuredTool satisfies it. */\ninterface StructuredToolLike {\n  name: string;\n  description: string;\n  schema: unknown;\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  invoke: (input: any, ...rest: any[]) => Promise<any>;\n}\n\nfunction toArgs(input: unknown): Record<string, unknown> {\n  return input && typeof input === \"object\"\n    ? (input as Record<string, unknown>)\n    : { input };\n}\n\n/**\n * Wrap a LangChain tool so AxioRank scores its arguments before it runs. The\n * returned tool keeps the original name, description, and schema, so it is a\n * drop-in replacement anywhere the original is used (LangChain or LangGraph).\n */\nexport function guardTool(t: StructuredToolLike, caller: ToolCaller, opts: GuardOptions = {}) {\n  const name = t.name;\n  return tool(\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    async (input: any) => runGuarded(caller, name, toArgs(input), () => t.invoke(input), opts),\n    { name, description: t.description, schema: t.schema as never },\n  );\n}\n\n/** Wrap every tool in an array (LangChain agents take a tools array). */\nexport function guardTools(\n  tools: StructuredToolLike[],\n  caller: ToolCaller,\n  opts: GuardOptions = {},\n) {\n  return tools.map((t) => guardTool(t, caller, opts));\n}\n"]}