/** * Shared adapter primitives for Agent SDK integrations (and harness plugins). * * These extract the session-start sequencing and the `tool.invoke` / `tool.block` / * `tool.complete` activity boilerplate that each integration would otherwise re-implement, so * an SDK binding is a thin translation between the SDK's hook signature and these calls. * They are the TypeScript twin of `ory_argus.adapters` in the Python core. * * - {@link withHookContext} — scope session state to one lifecycle invocation. * - {@link sessionStart} — run the user + agent auth gates and write the user→agent * delegation tuple; returns whether the session may proceed. * - {@link createSessionStarter} — coalesce concurrent lazy SDK session starts. * - {@link decideTool} — normalize native/MCP policy without execution activity. * - {@link gate} — resolve the subject, run {@link gateToolCall}, record activity, and * return a normalized {@link GateResult}. * - {@link complete} / {@link fail} — record safe terminal tool activity. * - {@link registerSubagent} — resolve a sub-agent identity + agent→subagent tuple. * - {@link wrapTool} — wrap a plain `execute(args)` with gate+complete, for SDKs whose * only veto point is the tool boundary (Vercel AI SDK, etc.). * * Every primitive is best-effort and fail-open. */ import type { OryAgentClient } from "./client.js"; import { ensureAgentIdentity, ensureSubAgentIdentity } from "./agent-auth.js"; import { ensureUserAuthenticated } from "./user-login.js"; import { type ModeDecision, type PermissionDecision, type PrincipalBlockSubjects } from "./permissions.js"; import { type DenialContext } from "./denial.js"; import { type McpToolIdentifier } from "./mcp.js"; import type { RuntimeCredential } from "./runtime-credential.js"; export declare function resolveNamespace(): string; export interface HookContextOptions { sessionId?: string; runtimeCredential?: RuntimeCredential; } /** Scope ambient session state to one lifecycle invocation. */ export declare function withHookContext(client: OryAgentClient, opts: HookContextOptions, work: () => T): T; export interface SessionStartResult { proceed: boolean; userMode: string; userReason: string; agentKind: string; } export interface SessionStartOptions { harness: string; sessionId?: string; projectUrl?: string; binName?: string; /** Injectable gates (tests). */ userLogin?: typeof ensureUserAuthenticated; agentGate?: typeof ensureAgentIdentity; /** Small, privacy-safe session metadata supported by the activity API. */ activityAttributes?: Record; } /** * Run both auth gates and write the user→agent delegation tuple. The user gate * runs every session to establish/refresh the user identity, records the * `user.auth` activity event, and never blocks — enforcement is governed by * `permissionMode` at tool-call time. `SessionStartResult.proceed` is therefore * always `true`; it is retained only for a stable adapter shape. */ export declare function sessionStart(client: OryAgentClient, opts: SessionStartOptions): Promise; /** Build a concurrency-safe, retryable lazy session-start trigger. */ export declare function createSessionStarter(client: OryAgentClient, opts: SessionStartOptions): () => Promise; /** * Record the `user → agent` delegation edge through the agent-security broker * (see {@link OryAgentClient.recordDelegation}). Exported so harness plugins * that run their own session-start sequence (rather than {@link sessionStart}) * record the edge the same way. * * The plugin supplies only the delegating user identity (resolved from the live * principal, else the persisted delegation anchor) plus the harness and host; * the broker owns the Keto tuple and its join-key encoding. The node id the * broker returns (`agent:`) is persisted so a later sub-agent * registration — which may run in a separate subprocess with no live principal * — can reference it verbatim as `delegated_by`. Best-effort and fail-open: * any failure (including a 404 against the local stack, which has no broker) is * logged and swallowed. No-op when Agent Security isn't connected (there is no * broker to record against) and when no user identity resolves. */ export declare function writeUserDelegatesAgent(client: OryAgentClient, harness?: string, sessionId?: string): Promise; export interface RegisterSubagentOptions { harness: string; subAgentType: string; projectUrl?: string; subAgentGate?: typeof ensureSubAgentIdentity; /** * Identifier for this individual spawn, where the harness exposes one * (Cursor's `subagent_id`, Claude Code's `agent_id`, OpenClaw's `childRunId`). * Distinguishes two concurrent sub-agents of the same type; absent on * harnesses that expose no such id. */ perSpawnId?: string; sessionId?: string; signal?: AbortSignal; } export declare function registerSubagent(client: OryAgentClient, opts: RegisterSubagentOptions): Promise; /** * Record the `agent → subagent` delegation edge through the agent-security * broker. Exported so harness plugins that resolve the sub-agent identity * through their own event plumbing (rather than {@link registerSubagent}) * record the edge the same way. * * The broker builds the sub-agent node from the parent agent's delegation node * (`delegated_by`) and the sub-agent type — so the plugin passes the node id * the broker assigned to the `user → agent` edge (persisted at session start), * echoed verbatim, and never reconstructs the join-key encoding itself. * Best-effort and fail-open. No-op when Agent Security isn't connected and until the * `user → agent` edge has been * recorded (so the parent node id is available). */ export declare function writeAgentDelegatesSubagent(client: OryAgentClient, subAgentSubject: string, subAgentType: string, opts?: { harness?: string; sessionId?: string; perSpawnId?: string; agentToken?: string; runtimeCredential?: RuntimeCredential; signal?: AbortSignal; }): Promise; export interface GateResult { /** False only when the tool was hard-denied in enforce mode. */ proceed: boolean; /** True only for that deny (and only when `canBlock`). */ blocked: boolean; /** Discriminator: allow / observe / deny / fail_open / interactive / not_connected. */ kind: string; decision: ToolGateOutcomeLike; subject: string; namespace: string; denialMessage?: string; denialContext?: DenialContext; } type ToolGateOutcomeLike = { kind: "not_connected"; activityAttributes: Record; } | { kind: "interactive"; activityAttributes: Record; } | PermissionDecision | ModeDecision; export interface GateOptions { harness: string; toolName: string; toolArgs?: unknown; subjectFallback?: string; /** Whether the calling integration can actually stop the tool. */ canBlock?: boolean; extraActivityAttributes?: Record; /** Normalized MCP identity when this invocation targets an MCP server. */ mcpTool?: McpToolIdentifier; /** Acting sub-agent principal context for explicit machine blocks. */ principals?: PrincipalBlockSubjects; } /** * Authorize a tool call and return a normalized {@link GateResult} without * recording execution activity. Permission-ask hooks use this when the harness * separately reports actual execution; {@link gate} adds the standard events. */ export declare function decideTool(client: OryAgentClient, opts: GateOptions): Promise; export declare function gate(client: OryAgentClient, opts: GateOptions): Promise; export declare function complete(client: OryAgentClient, opts: { toolName: string; input?: unknown; output?: unknown; extraActivityAttributes?: Record; status?: "ok" | "error"; }): void; export declare function fail(client: OryAgentClient, opts: { toolName: string; input?: unknown; error?: unknown; extraActivityAttributes?: Record; }): void; export interface WrapToolOptions { harness: string; toolName: string; canBlock?: boolean; } /** * Wrap a plain `execute(args)` callable with gate + complete. On a hard deny it throws * {@link OryDenialError} (the veto mechanism for tool-boundary SDKs like Vercel AI SDK); * otherwise the tool runs and `tool.complete` is recorded. */ export declare function wrapTool(client: OryAgentClient, opts: WrapToolOptions, execute: (args: A) => R | Promise): (args: A) => Promise; export {};