@clampd/sdk 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # Clampd TypeScript SDK
2
+
3
+ Runtime security for AI agents. Guard every tool call — OpenAI, Anthropic, LangChain.js — in 1 line.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install clampd
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import clampd from "clampd";
15
+ import OpenAI from "openai";
16
+
17
+ // Configure once at startup
18
+ clampd.init({
19
+ agentId: "my-agent",
20
+ secret: "ags_...", // from dashboard → Agent → Secret
21
+ gatewayUrl: "http://localhost:8080",
22
+ apiKey: "ag_live_...",
23
+ });
24
+
25
+ // Wrap your OpenAI client — done
26
+ const client = clampd.openai(new OpenAI());
27
+
28
+ // Use it exactly like before. Clampd intercepts every tool call.
29
+ const response = await client.chat.completions.create({
30
+ model: "gpt-4o",
31
+ messages: [{ role: "user", content: "Look up active users" }],
32
+ tools: [...],
33
+ });
34
+ // Dangerous tool calls → blocked before execution
35
+ // Safe tool calls → proceed normally
36
+ ```
37
+
38
+ ## Configuration
39
+
40
+ Three ways to configure (pick one):
41
+
42
+ ```typescript
43
+ // Option 1: Environment variables
44
+ // CLAMPD_GATEWAY_URL=http://localhost:8080
45
+ // CLAMPD_API_KEY=ag_live_...
46
+ // CLAMPD_AGENT_ID=my-agent
47
+ // CLAMPD_AGENT_SECRET=ags_...
48
+
49
+ // Option 2: Global init (recommended)
50
+ clampd.init({ agentId: "my-agent", secret: "ags_...", gatewayUrl: "...", apiKey: "..." });
51
+
52
+ // Option 3: Inline per-call
53
+ const safeFn = clampd.guard(myFn, {
54
+ toolName: "db.query",
55
+ agentId: "my-agent",
56
+ secret: "ags_...",
57
+ });
58
+ ```
59
+
60
+ ## Anthropic / Claude
61
+
62
+ ```typescript
63
+ import clampd from "clampd";
64
+ import Anthropic from "@anthropic-ai/sdk";
65
+
66
+ clampd.init({ agentId: "my-agent", secret: "ags_..." });
67
+ const client = clampd.anthropic(new Anthropic());
68
+
69
+ const response = await client.messages.create({
70
+ model: "claude-sonnet-4-20250514",
71
+ max_tokens: 1024,
72
+ messages: [{ role: "user", content: "..." }],
73
+ tools: [...],
74
+ });
75
+ ```
76
+
77
+ ## Direct Guard (any function)
78
+
79
+ ```typescript
80
+ import clampd from "clampd";
81
+
82
+ clampd.init({ agentId: "my-agent", secret: "ags_..." });
83
+
84
+ const safeQuery = clampd.guard(runQuery, {
85
+ toolName: "database.query",
86
+ });
87
+
88
+ // With response checking (opt-in)
89
+ const safeRead = clampd.guard(readFile, {
90
+ toolName: "file_read",
91
+ checkResponse: true,
92
+ });
93
+
94
+ await safeQuery("SELECT * FROM users"); // allowed
95
+ await safeQuery("DROP TABLE users"); // throws ClampdBlockedError
96
+ ```
97
+
98
+ ## Tool Definitions Wrapper
99
+
100
+ ```typescript
101
+ import clampd from "clampd";
102
+
103
+ // Wrap OpenAI-style tool definitions
104
+ const safeTools = clampd.tools(myToolDefs, { agentId: "my-agent", secret: "ags_..." });
105
+ ```
106
+
107
+ ## Error Handling
108
+
109
+ ```typescript
110
+ import { ClampdBlockedError } from "clampd";
111
+
112
+ try {
113
+ await safeQuery("DROP TABLE users");
114
+ } catch (e) {
115
+ if (e instanceof ClampdBlockedError) {
116
+ console.log(`Blocked: ${e.message}`);
117
+ // e.response.risk_score, e.response.denial_reason
118
+ }
119
+ }
120
+ ```
121
+
122
+ ## API Reference
123
+
124
+ | Function | Description |
125
+ |----------|-------------|
126
+ | `clampd.init(opts)` | Configure global client (once at startup) |
127
+ | `clampd.openai(client)` | Wrap OpenAI client |
128
+ | `clampd.anthropic(client)` | Wrap Anthropic client |
129
+ | `clampd.guard(fn, opts)` | Wrap any async function |
130
+ | `clampd.tools(defs, opts)` | Wrap OpenAI tool definitions |
131
+
132
+ ## Requirements
133
+
134
+ - Node.js 18+
135
+ - A running [Clampd](https://clampd.dev) gateway
136
+
137
+ ## License
138
+
139
+ BUSL-1.1
package/dist/auth.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * JWT helper for Clampd agent authentication.
3
+ *
4
+ * Uses HMAC-SHA256 when `secret` is provided or `CLAMPD_JWT_SECRET` env var
5
+ * is set. Throws an error if no signing secret is available — unsigned JWTs
6
+ * (alg: none) are NOT supported.
7
+ */
8
+ /**
9
+ * Create a JWT with `sub` = agentId.
10
+ *
11
+ * @param agentId Agent identifier (becomes the `sub` claim).
12
+ * @param opts.secret HMAC-SHA256 signing key. Falls back to
13
+ * `CLAMPD_JWT_SECRET` env var. If unset, creates an unsigned JWT.
14
+ * @param opts.scopes Optional scopes to include in the token.
15
+ * @param opts.ttlSeconds Token TTL in seconds (default: 3600).
16
+ */
17
+ export declare function makeAgentJwt(agentId: string, opts?: {
18
+ secret?: string;
19
+ scopes?: string[];
20
+ ttlSeconds?: number;
21
+ }): string;
22
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GACjE,MAAM,CAqCR"}
package/dist/auth.js ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * JWT helper for Clampd agent authentication.
3
+ *
4
+ * Uses HMAC-SHA256 when `secret` is provided or `CLAMPD_JWT_SECRET` env var
5
+ * is set. Throws an error if no signing secret is available — unsigned JWTs
6
+ * (alg: none) are NOT supported.
7
+ */
8
+ import { createHmac, createHash } from "node:crypto";
9
+ function b64url(data) {
10
+ const bytes = typeof data === "string" ? Buffer.from(data) : Buffer.from(data);
11
+ return bytes.toString("base64url");
12
+ }
13
+ /**
14
+ * Create a JWT with `sub` = agentId.
15
+ *
16
+ * @param agentId Agent identifier (becomes the `sub` claim).
17
+ * @param opts.secret HMAC-SHA256 signing key. Falls back to
18
+ * `CLAMPD_JWT_SECRET` env var. If unset, creates an unsigned JWT.
19
+ * @param opts.scopes Optional scopes to include in the token.
20
+ * @param opts.ttlSeconds Token TTL in seconds (default: 3600).
21
+ */
22
+ export function makeAgentJwt(agentId, opts) {
23
+ const rawSecret = opts?.secret || process.env.CLAMPD_AGENT_SECRET || process.env.CLAMPD_JWT_SECRET || "";
24
+ const ttl = opts?.ttlSeconds ?? 3600;
25
+ const now = Math.floor(Date.now() / 1000);
26
+ const payloadObj = {
27
+ sub: agentId,
28
+ iss: "clampd-sdk",
29
+ iat: now,
30
+ exp: now + ttl,
31
+ };
32
+ if (opts?.scopes?.length) {
33
+ payloadObj.scopes = opts.scopes;
34
+ }
35
+ if (rawSecret) {
36
+ // Derive signing key: if agent secret (ags_ prefix), hash with SHA-256
37
+ // so the HMAC key matches the credential_hash stored server-side.
38
+ // Otherwise use as-is (legacy global JWT_SECRET).
39
+ const signingKey = rawSecret.startsWith("ags_")
40
+ ? createHash("sha256").update(rawSecret).digest("hex")
41
+ : rawSecret;
42
+ const header = b64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
43
+ const payload = b64url(JSON.stringify(payloadObj));
44
+ const signingInput = `${header}.${payload}`;
45
+ const sig = createHmac("sha256", signingKey).update(signingInput).digest();
46
+ const signature = Buffer.from(sig).toString("base64url");
47
+ return `${header}.${payload}.${signature}`;
48
+ }
49
+ // Fail-closed: unsigned JWTs are not supported
50
+ throw new Error("[clampd] No signing secret available. " +
51
+ "Set CLAMPD_JWT_SECRET env var or pass { secret } to makeAgentJwt(). " +
52
+ "Unsigned JWTs (alg: none) are not supported — gateways require JWT_SECRET.");
53
+ }
54
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,SAAS,MAAM,CAAC,IAAyB;IACvC,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,OAAO,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,IAAkE;IAElE,MAAM,SAAS,GAAG,IAAI,EAAE,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC;IACzG,MAAM,GAAG,GAAG,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAE1C,MAAM,UAAU,GAA4B;QAC1C,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,YAAY;QACjB,GAAG,EAAE,GAAG;QACR,GAAG,EAAE,GAAG,GAAG,GAAG;KACf,CAAC;IACF,IAAI,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QACzB,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAClC,CAAC;IAED,IAAI,SAAS,EAAE,CAAC;QACd,uEAAuE;QACvE,kEAAkE;QAClE,kDAAkD;QAClD,MAAM,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC;YAC7C,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YACtD,CAAC,CAAC,SAAS,CAAC;QAEd,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;QACpE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;QACnD,MAAM,YAAY,GAAG,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC;QAC3E,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACzD,OAAO,GAAG,MAAM,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;IAC7C,CAAC;IAED,+CAA+C;IAC/C,MAAM,IAAI,KAAK,CACb,wCAAwC;QACxC,sEAAsE;QACtE,4EAA4E,CAC7E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * ClampdClient — thin wrapper around the ag-gateway HTTP API.
3
+ */
4
+ export interface ProxyResponse {
5
+ request_id: string;
6
+ allowed: boolean;
7
+ /** Intent action: "pass", "flag", or "block". */
8
+ action?: string;
9
+ risk_score: number;
10
+ scope_granted?: string | null;
11
+ tool_response?: unknown | null;
12
+ denial_reason?: string | null;
13
+ /** Human-readable explanation of the risk assessment. */
14
+ reasoning?: string | null;
15
+ /** Rule IDs that matched this request (e.g. ["R001", "R005"]). */
16
+ matched_rules?: string[];
17
+ latency_ms: number;
18
+ degraded_stages: string[];
19
+ session_flags: string[];
20
+ /** HMAC scope token binding this approval to response scanning. */
21
+ scope_token?: string | null;
22
+ }
23
+ export interface ScanResponse {
24
+ allowed: boolean;
25
+ risk_score: number;
26
+ denial_reason?: string;
27
+ matched_rules: string[];
28
+ latency_ms: number;
29
+ }
30
+ export interface ScanOutputResponse extends ScanResponse {
31
+ pii_found: Array<{
32
+ pii_type: string;
33
+ count: number;
34
+ }>;
35
+ secrets_found: Array<{
36
+ secret_type: string;
37
+ count: number;
38
+ }>;
39
+ }
40
+ export interface ProxyRequest {
41
+ tool: string;
42
+ params: Record<string, unknown>;
43
+ target_url: string;
44
+ prompt_context?: string;
45
+ }
46
+ export interface VerifyRequest {
47
+ tool: string;
48
+ params: Record<string, unknown>;
49
+ target_url?: string;
50
+ }
51
+ export interface ClampdClientOptions {
52
+ gatewayUrl?: string;
53
+ agentId: string;
54
+ apiKey?: string;
55
+ secret?: string;
56
+ timeoutMs?: number;
57
+ }
58
+ /**
59
+ * Synchronous-style (async/await) client for the Clampd gateway proxy API.
60
+ *
61
+ * Uses the built-in `fetch` available in Node 18+.
62
+ */
63
+ export declare class ClampdClient {
64
+ private readonly gatewayUrl;
65
+ readonly agentId: string;
66
+ private readonly apiKey;
67
+ private readonly jwt;
68
+ private readonly timeoutMs;
69
+ constructor(opts: ClampdClientOptions);
70
+ private headers;
71
+ /**
72
+ * Send a tool call through the Clampd gateway for evaluation.
73
+ *
74
+ * When targetUrl is empty (default), the gateway runs evaluate-only mode:
75
+ * classify + policy check, no token exchange or forwarding. The tool
76
+ * executes locally in the agent's runtime.
77
+ *
78
+ * When targetUrl is set, the gateway also exchanges a micro-token and
79
+ * forwards the request to the target, inspecting the response.
80
+ */
81
+ proxy(tool: string, params: Record<string, unknown>, targetUrl?: string, promptContext?: string, toolDescriptorHash?: string): Promise<ProxyResponse>;
82
+ /**
83
+ * Get delegation headers for cross-service HTTP propagation.
84
+ * Static convenience method.
85
+ */
86
+ static delegationHeaders(): Record<string, string>;
87
+ /**
88
+ * Inspect a tool response for PII, anomalies, or policy violations.
89
+ *
90
+ * When scopeToken is provided (from a prior proxy() call),
91
+ * the gateway can verify this response came from a Clampd-approved call.
92
+ */
93
+ inspect(tool: string, responseData: unknown, requestId?: string, scopeToken?: string): Promise<ProxyResponse>;
94
+ /**
95
+ * Dry-run: stages 1-6 only — no token exchange or forwarding.
96
+ */
97
+ verify(tool: string, params: Record<string, unknown>, targetUrl?: string): Promise<ProxyResponse>;
98
+ /**
99
+ * Scan input text (prompt) for injection attacks, jailbreaks, etc.
100
+ * Unlike proxy/verify, this throws on network errors so callers can
101
+ * implement fail-open vs fail-closed logic.
102
+ */
103
+ scanInput(text: string, messageCount?: number): Promise<ScanResponse>;
104
+ /**
105
+ * Scan output text (LLM response) for PII, secrets, policy violations.
106
+ * Unlike proxy/verify, this throws on network errors so callers can
107
+ * implement fail-open vs fail-closed logic.
108
+ */
109
+ scanOutput(text: string, requestId?: string): Promise<ScanOutputResponse>;
110
+ private post;
111
+ /**
112
+ * Like `post`, but throws on network errors and non-OK responses
113
+ * instead of synthesizing a blocked response. Used by scan methods
114
+ * so callers can distinguish gateway errors from policy decisions.
115
+ */
116
+ private postOrThrow;
117
+ }
118
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
package/dist/client.js ADDED
@@ -0,0 +1,191 @@
1
+ /**
2
+ * ClampdClient — thin wrapper around the ag-gateway HTTP API.
3
+ */
4
+ import { makeAgentJwt } from "./auth.js";
5
+ import { getDelegation, delegationHeaders } from "./delegation.js";
6
+ // ── Synthesized error response ─────────────────────────────────────
7
+ function blockedResponse(reason) {
8
+ return {
9
+ request_id: "error",
10
+ allowed: false,
11
+ risk_score: 1.0,
12
+ denial_reason: reason,
13
+ matched_rules: [],
14
+ latency_ms: 0,
15
+ degraded_stages: [],
16
+ session_flags: [],
17
+ };
18
+ }
19
+ // ── Client ─────────────────────────────────────────────────────────
20
+ /**
21
+ * Synchronous-style (async/await) client for the Clampd gateway proxy API.
22
+ *
23
+ * Uses the built-in `fetch` available in Node 18+.
24
+ */
25
+ export class ClampdClient {
26
+ gatewayUrl;
27
+ agentId;
28
+ apiKey;
29
+ jwt;
30
+ timeoutMs;
31
+ constructor(opts) {
32
+ this.gatewayUrl = (opts.gatewayUrl ?? "http://localhost:8080").replace(/\/$/, "");
33
+ this.agentId = opts.agentId;
34
+ this.apiKey = opts.apiKey ?? process.env.CLAMPD_API_KEY ?? "";
35
+ this.jwt = makeAgentJwt(this.agentId, { secret: opts.secret });
36
+ this.timeoutMs = opts.timeoutMs ?? 30_000;
37
+ }
38
+ headers() {
39
+ return {
40
+ Authorization: `Bearer ${this.jwt}`,
41
+ "X-AG-Key": this.apiKey,
42
+ "Content-Type": "application/json",
43
+ ...delegationHeaders(),
44
+ };
45
+ }
46
+ /**
47
+ * Send a tool call through the Clampd gateway for evaluation.
48
+ *
49
+ * When targetUrl is empty (default), the gateway runs evaluate-only mode:
50
+ * classify + policy check, no token exchange or forwarding. The tool
51
+ * executes locally in the agent's runtime.
52
+ *
53
+ * When targetUrl is set, the gateway also exchanges a micro-token and
54
+ * forwards the request to the target, inspecting the response.
55
+ */
56
+ async proxy(tool, params, targetUrl = "", promptContext, toolDescriptorHash) {
57
+ const body = {
58
+ tool,
59
+ params,
60
+ target_url: targetUrl,
61
+ };
62
+ if (promptContext) {
63
+ body.prompt_context = promptContext;
64
+ }
65
+ if (toolDescriptorHash) {
66
+ body.tool_descriptor_hash = toolDescriptorHash;
67
+ }
68
+ // Auto-include delegation context if present
69
+ const delegation = getDelegation();
70
+ if (delegation && delegation.chain.length > 1) {
71
+ body.caller_agent_id = delegation.chain[delegation.chain.length - 2];
72
+ body.delegation_chain = delegation.chain;
73
+ body.delegation_trace_id = delegation.traceId;
74
+ }
75
+ return this.post("/v1/proxy", body);
76
+ }
77
+ /**
78
+ * Get delegation headers for cross-service HTTP propagation.
79
+ * Static convenience method.
80
+ */
81
+ static delegationHeaders() {
82
+ return delegationHeaders();
83
+ }
84
+ /**
85
+ * Inspect a tool response for PII, anomalies, or policy violations.
86
+ *
87
+ * When scopeToken is provided (from a prior proxy() call),
88
+ * the gateway can verify this response came from a Clampd-approved call.
89
+ */
90
+ async inspect(tool, responseData, requestId, scopeToken) {
91
+ const body = { tool, response_data: responseData };
92
+ if (requestId)
93
+ body.request_id = requestId;
94
+ if (scopeToken)
95
+ body.scope_token = scopeToken;
96
+ return this.post("/v1/inspect", body);
97
+ }
98
+ /**
99
+ * Dry-run: stages 1-6 only — no token exchange or forwarding.
100
+ */
101
+ async verify(tool, params, targetUrl = "") {
102
+ const body = {
103
+ tool,
104
+ params,
105
+ target_url: targetUrl,
106
+ };
107
+ return this.post("/v1/verify", body);
108
+ }
109
+ /**
110
+ * Scan input text (prompt) for injection attacks, jailbreaks, etc.
111
+ * Unlike proxy/verify, this throws on network errors so callers can
112
+ * implement fail-open vs fail-closed logic.
113
+ */
114
+ async scanInput(text, messageCount) {
115
+ const body = { text };
116
+ if (messageCount)
117
+ body.message_count = messageCount;
118
+ return this.postOrThrow("/v1/scan-input", body);
119
+ }
120
+ /**
121
+ * Scan output text (LLM response) for PII, secrets, policy violations.
122
+ * Unlike proxy/verify, this throws on network errors so callers can
123
+ * implement fail-open vs fail-closed logic.
124
+ */
125
+ async scanOutput(text, requestId) {
126
+ const body = { text };
127
+ if (requestId)
128
+ body.request_id = requestId;
129
+ return this.postOrThrow("/v1/scan-output", body);
130
+ }
131
+ // ── Internal ────────────────────────────────────────────────────
132
+ async post(path, body) {
133
+ const url = `${this.gatewayUrl}${path}`;
134
+ let resp;
135
+ try {
136
+ resp = await fetch(url, {
137
+ method: "POST",
138
+ headers: this.headers(),
139
+ body: JSON.stringify(body),
140
+ signal: AbortSignal.timeout(this.timeoutMs),
141
+ });
142
+ }
143
+ catch (err) {
144
+ const message = err instanceof Error ? err.message : "Unknown fetch error";
145
+ return blockedResponse(`Fetch error: ${message}`);
146
+ }
147
+ if (resp.ok) {
148
+ const json = (await resp.json());
149
+ // Ensure array fields are always present for ProxyResponse shape
150
+ if (typeof json === "object" && json !== null && "degraded_stages" in json) {
151
+ const pr = json;
152
+ return {
153
+ ...json,
154
+ degraded_stages: pr.degraded_stages ?? [],
155
+ session_flags: pr.session_flags ?? [],
156
+ };
157
+ }
158
+ return json;
159
+ }
160
+ // Gateway returned an error — synthesize a blocked response
161
+ const text = await resp.text().catch(() => `HTTP ${resp.status}`);
162
+ return blockedResponse(text);
163
+ }
164
+ /**
165
+ * Like `post`, but throws on network errors and non-OK responses
166
+ * instead of synthesizing a blocked response. Used by scan methods
167
+ * so callers can distinguish gateway errors from policy decisions.
168
+ */
169
+ async postOrThrow(path, body) {
170
+ const url = `${this.gatewayUrl}${path}`;
171
+ let resp;
172
+ try {
173
+ resp = await fetch(url, {
174
+ method: "POST",
175
+ headers: this.headers(),
176
+ body: JSON.stringify(body),
177
+ signal: AbortSignal.timeout(this.timeoutMs),
178
+ });
179
+ }
180
+ catch (err) {
181
+ const message = err instanceof Error ? err.message : String(err);
182
+ throw new Error(`Scan fetch error: ${message}`);
183
+ }
184
+ if (!resp.ok) {
185
+ const text = await resp.text().catch(() => `HTTP ${resp.status}`);
186
+ throw new Error(`Scan request failed: ${text}`);
187
+ }
188
+ return (await resp.json());
189
+ }
190
+ }
191
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export interface DelegationContext {
2
+ traceId: string;
3
+ chain: string[];
4
+ confidence: "verified" | "inferred" | "declared";
5
+ }
6
+ export declare const MAX_DELEGATION_DEPTH = 5;
7
+ /**
8
+ * Get the current delegation context, if any.
9
+ */
10
+ export declare function getDelegation(): DelegationContext | undefined;
11
+ /**
12
+ * Get the caller (parent) agent ID from the delegation chain.
13
+ * Returns undefined if there is no parent (single agent or no context).
14
+ */
15
+ export declare function getCallerAgentId(): string | undefined;
16
+ /**
17
+ * Check whether a chain contains a cycle (duplicate agent ID).
18
+ */
19
+ export declare function hasCycle(chain: string[]): boolean;
20
+ /**
21
+ * Run a function within a delegation context.
22
+ * If already inside a delegation, extends the chain.
23
+ * If not, starts a new chain.
24
+ */
25
+ export declare function withDelegation<T>(agentId: string, fn: () => T): T;
26
+ /**
27
+ * Get delegation headers for cross-service HTTP propagation.
28
+ * Returns an empty object when called outside a delegation context.
29
+ */
30
+ export declare function delegationHeaders(): Record<string, string>;
31
+ //# sourceMappingURL=delegation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation.d.ts","sourceRoot":"","sources":["../src/delegation.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,CAAC;CAClD;AAID,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;GAEG;AACH,wBAAgB,aAAa,IAAI,iBAAiB,GAAG,SAAS,CAE7D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAIrD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAEjD;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAgCjE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ1D"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Automatic delegation chain tracking via AsyncLocalStorage.
3
+ * Propagates through async/await, Promises, and callbacks automatically.
4
+ *
5
+ * When Agent A's guarded tool calls Agent B's guarded tool in the same
6
+ * process, the SDK auto-detects the cross-agent hop and includes
7
+ * delegation metadata in proxy requests.
8
+ */
9
+ import { AsyncLocalStorage } from "node:async_hooks";
10
+ import { randomUUID } from "node:crypto";
11
+ const delegationStore = new AsyncLocalStorage();
12
+ export const MAX_DELEGATION_DEPTH = 5;
13
+ /**
14
+ * Get the current delegation context, if any.
15
+ */
16
+ export function getDelegation() {
17
+ return delegationStore.getStore();
18
+ }
19
+ /**
20
+ * Get the caller (parent) agent ID from the delegation chain.
21
+ * Returns undefined if there is no parent (single agent or no context).
22
+ */
23
+ export function getCallerAgentId() {
24
+ const ctx = delegationStore.getStore();
25
+ if (!ctx || ctx.chain.length < 2)
26
+ return undefined;
27
+ return ctx.chain[ctx.chain.length - 2];
28
+ }
29
+ /**
30
+ * Check whether a chain contains a cycle (duplicate agent ID).
31
+ */
32
+ export function hasCycle(chain) {
33
+ return new Set(chain).size !== chain.length;
34
+ }
35
+ /**
36
+ * Run a function within a delegation context.
37
+ * If already inside a delegation, extends the chain.
38
+ * If not, starts a new chain.
39
+ */
40
+ export function withDelegation(agentId, fn) {
41
+ const parent = delegationStore.getStore();
42
+ let ctx;
43
+ if (parent) {
44
+ ctx = {
45
+ traceId: parent.traceId,
46
+ chain: [...parent.chain, agentId],
47
+ confidence: parent.confidence,
48
+ };
49
+ }
50
+ else {
51
+ ctx = {
52
+ traceId: randomUUID().replace(/-/g, "").slice(0, 16),
53
+ chain: [agentId],
54
+ confidence: "verified",
55
+ };
56
+ }
57
+ if (ctx.chain.length > MAX_DELEGATION_DEPTH) {
58
+ throw new Error(`Delegation depth ${ctx.chain.length} exceeds maximum ${MAX_DELEGATION_DEPTH}. ` +
59
+ `Chain: ${ctx.chain.join(" \u2192 ")}`);
60
+ }
61
+ if (hasCycle(ctx.chain)) {
62
+ throw new Error(`Circular delegation detected: ${ctx.chain.join(" \u2192 ")}`);
63
+ }
64
+ return delegationStore.run(ctx, fn);
65
+ }
66
+ /**
67
+ * Get delegation headers for cross-service HTTP propagation.
68
+ * Returns an empty object when called outside a delegation context.
69
+ */
70
+ export function delegationHeaders() {
71
+ const ctx = delegationStore.getStore();
72
+ if (!ctx)
73
+ return {};
74
+ return {
75
+ "X-Clampd-Delegation-Trace": ctx.traceId,
76
+ "X-Clampd-Delegation-Chain": ctx.chain.join(","),
77
+ "X-Clampd-Delegation-Confidence": ctx.confidence,
78
+ };
79
+ }
80
+ //# sourceMappingURL=delegation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation.js","sourceRoot":"","sources":["../src/delegation.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzC,MAAM,eAAe,GAAG,IAAI,iBAAiB,EAAqB,CAAC;AAEnE,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,eAAe,CAAC,QAAQ,EAAE,CAAC;AACpC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IACnD,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAe;IACtC,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC;AAC9C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAI,OAAe,EAAE,EAAW;IAC5D,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;IAE1C,IAAI,GAAsB,CAAC;IAC3B,IAAI,MAAM,EAAE,CAAC;QACX,GAAG,GAAG;YACJ,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC;YACjC,UAAU,EAAE,MAAM,CAAC,UAAU;SAC9B,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,GAAG,GAAG;YACJ,OAAO,EAAE,UAAU,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YACpD,KAAK,EAAE,CAAC,OAAO,CAAC;YAChB,UAAU,EAAE,UAAU;SACvB,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,oBAAoB,GAAG,CAAC,KAAK,CAAC,MAAM,oBAAoB,oBAAoB,IAAI;YAC9E,UAAU,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CACzC,CAAC;IACJ,CAAC;IAED,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,iCAAiC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAC9D,CAAC;IACJ,CAAC;IAED,OAAO,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,GAAG,GAAG,eAAe,CAAC,QAAQ,EAAE,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,CAAC;IACpB,OAAO;QACL,2BAA2B,EAAE,GAAG,CAAC,OAAO;QACxC,2BAA2B,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;QAChD,gCAAgC,EAAE,GAAG,CAAC,UAAU;KACjD,CAAC;AACJ,CAAC"}