@agentpress/sdk 0.2.70

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/dist/index.cjs ADDED
@@ -0,0 +1,368 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ActionsClient: () => ActionsClient,
24
+ AgentPress: () => AgentPress,
25
+ AgentPressError: () => AgentPressError,
26
+ ConfigurationError: () => ConfigurationError,
27
+ HttpError: () => HttpError,
28
+ TimeoutError: () => TimeoutError,
29
+ WebhookSignatureError: () => WebhookSignatureError
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // src/errors.ts
34
+ var AgentPressError = class extends Error {
35
+ constructor(message) {
36
+ super(message);
37
+ this.name = "AgentPressError";
38
+ Object.setPrototypeOf(this, new.target.prototype);
39
+ }
40
+ };
41
+ var ConfigurationError = class extends AgentPressError {
42
+ constructor(message) {
43
+ super(message);
44
+ this.name = "ConfigurationError";
45
+ Object.setPrototypeOf(this, new.target.prototype);
46
+ }
47
+ };
48
+ var HttpError = class extends AgentPressError {
49
+ statusCode;
50
+ responseBody;
51
+ url;
52
+ constructor(statusCode, responseBody, url) {
53
+ super(`HTTP ${statusCode} from ${url}`);
54
+ this.name = "HttpError";
55
+ this.statusCode = statusCode;
56
+ this.responseBody = responseBody;
57
+ this.url = url;
58
+ Object.setPrototypeOf(this, new.target.prototype);
59
+ }
60
+ };
61
+ var TimeoutError = class extends AgentPressError {
62
+ constructor(url, timeout) {
63
+ super(`Request to ${url} timed out after ${timeout}ms`);
64
+ this.name = "TimeoutError";
65
+ Object.setPrototypeOf(this, new.target.prototype);
66
+ }
67
+ };
68
+ var WebhookSignatureError = class extends AgentPressError {
69
+ constructor(message) {
70
+ super(message);
71
+ this.name = "WebhookSignatureError";
72
+ Object.setPrototypeOf(this, new.target.prototype);
73
+ }
74
+ };
75
+
76
+ // src/utils.ts
77
+ var import_node_crypto = require("crypto");
78
+ function randomMessageId() {
79
+ return `msg_${(0, import_node_crypto.randomUUID)()}`;
80
+ }
81
+
82
+ // src/webhooks/signing.ts
83
+ var import_node_crypto2 = require("crypto");
84
+ var SIGNATURE_PREFIX = "v1,";
85
+ var DEFAULT_TOLERANCE_SECONDS = 5 * 60;
86
+ function sign(secret, msgId, timestamp, body) {
87
+ const secretBytes = Buffer.from(secret.replace(/^whsec_/, ""), "base64");
88
+ const message = `${msgId}.${timestamp}.${body}`;
89
+ const signature = (0, import_node_crypto2.createHmac)("sha256", secretBytes).update(message).digest("base64");
90
+ return `${SIGNATURE_PREFIX}${signature}`;
91
+ }
92
+ function verify(secret, payload, headers, toleranceSeconds = DEFAULT_TOLERANCE_SECONDS) {
93
+ const msgId = headers["svix-id"];
94
+ const timestampStr = headers["svix-timestamp"];
95
+ const signatureHeader = headers["svix-signature"];
96
+ const timestamp = parseInt(timestampStr, 10);
97
+ if (Number.isNaN(timestamp)) return false;
98
+ const now = Math.floor(Date.now() / 1e3);
99
+ if (Math.abs(now - timestamp) > toleranceSeconds) return false;
100
+ const body = typeof payload === "string" ? payload : payload.toString("utf-8");
101
+ const expected = sign(secret, msgId, timestamp, body);
102
+ const signatures = signatureHeader.split(" ");
103
+ const expectedBuf = Buffer.from(expected);
104
+ for (const sig of signatures) {
105
+ const sigBuf = Buffer.from(sig);
106
+ if (sigBuf.length === expectedBuf.length && (0, import_node_crypto2.timingSafeEqual)(sigBuf, expectedBuf)) {
107
+ return true;
108
+ }
109
+ }
110
+ return false;
111
+ }
112
+
113
+ // src/actions/client.ts
114
+ var ActionsClient = class {
115
+ options;
116
+ http;
117
+ constructor(options, http) {
118
+ this.options = options;
119
+ this.http = http;
120
+ }
121
+ /**
122
+ * Approve a staged action, optionally modifying the tool call.
123
+ *
124
+ * @throws ConfigurationError if webhookSecret is not configured
125
+ * @throws HttpError on non-2xx response
126
+ * @throws TimeoutError if request exceeds timeout
127
+ */
128
+ async approve(actionId, params) {
129
+ return this.manage(actionId, params.action, "approve", {
130
+ editedToolCall: params.editedToolCall
131
+ });
132
+ }
133
+ /**
134
+ * Reject a staged action.
135
+ *
136
+ * @throws ConfigurationError if webhookSecret is not configured
137
+ * @throws HttpError on non-2xx response
138
+ * @throws TimeoutError if request exceeds timeout
139
+ */
140
+ async reject(actionId, params) {
141
+ return this.manage(actionId, params.action, "reject", {
142
+ reason: params.reason
143
+ });
144
+ }
145
+ async manage(actionId, webhookAction, operation, body) {
146
+ if (!this.options.webhookSecret) {
147
+ throw new ConfigurationError(
148
+ "webhookSecret is required for action management operations"
149
+ );
150
+ }
151
+ const path = `/webhooks/actions/${this.options.org}/${webhookAction}/manage/${actionId}/${operation}`;
152
+ const bodyStr = JSON.stringify(body);
153
+ const msgId = randomMessageId();
154
+ const timestamp = Math.floor(Date.now() / 1e3);
155
+ const signature = sign(
156
+ this.options.webhookSecret,
157
+ msgId,
158
+ timestamp,
159
+ bodyStr
160
+ );
161
+ return this.http.request(path, {
162
+ method: "POST",
163
+ body: bodyStr,
164
+ headers: {
165
+ "svix-id": msgId,
166
+ "svix-timestamp": String(timestamp),
167
+ "svix-signature": signature
168
+ }
169
+ });
170
+ }
171
+ };
172
+
173
+ // src/http.ts
174
+ var HttpClient = class {
175
+ baseUrl;
176
+ timeout;
177
+ onRequest;
178
+ onResponse;
179
+ constructor(options) {
180
+ this.baseUrl = options.baseUrl;
181
+ this.timeout = options.timeout;
182
+ this.onRequest = options.onRequest;
183
+ this.onResponse = options.onResponse;
184
+ }
185
+ /**
186
+ * Send an HTTP request to the API. Constructs the full URL from `baseUrl` + `path`,
187
+ * applies the configured timeout via `AbortSignal`, fires `onRequest`/`onResponse`
188
+ * hooks, and parses the JSON response.
189
+ *
190
+ * @throws {TimeoutError} If the request exceeds the configured timeout.
191
+ * @throws {HttpError} If the API returns a non-2xx status code.
192
+ * @throws {AgentPressError} On network failures or non-JSON responses.
193
+ */
194
+ async request(path, init) {
195
+ const url = `${this.baseUrl}${path}`;
196
+ const headers = new Headers(init.headers);
197
+ if (!headers.has("Content-Type")) {
198
+ headers.set("Content-Type", "application/json");
199
+ }
200
+ const requestInit = {
201
+ ...init,
202
+ headers,
203
+ signal: AbortSignal.timeout(this.timeout)
204
+ };
205
+ this.onRequest?.(url, requestInit);
206
+ let response;
207
+ try {
208
+ response = await fetch(url, requestInit);
209
+ } catch (error) {
210
+ if (error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError")) {
211
+ throw new TimeoutError(url, this.timeout);
212
+ }
213
+ const message = error instanceof Error ? error.message : "Unknown fetch error";
214
+ throw new AgentPressError(`Request to ${url} failed: ${message}`);
215
+ }
216
+ this.onResponse?.(url, response.clone());
217
+ const text = await response.text();
218
+ if (!response.ok) {
219
+ throw new HttpError(response.status, text, url);
220
+ }
221
+ try {
222
+ return JSON.parse(text);
223
+ } catch {
224
+ throw new AgentPressError(
225
+ `Expected JSON response from ${url} but received: ${text.slice(0, 200)}`
226
+ );
227
+ }
228
+ }
229
+ };
230
+
231
+ // src/webhooks/client.ts
232
+ var WebhooksClient = class {
233
+ options;
234
+ http;
235
+ constructor(options, http) {
236
+ this.options = options;
237
+ this.http = http;
238
+ }
239
+ /**
240
+ * Send an arbitrary webhook payload to AgentPress.
241
+ * Signs the payload with HMAC-SHA256 (Svix-compatible).
242
+ *
243
+ * @throws ConfigurationError if webhookSecret is not configured
244
+ * @throws HttpError on non-2xx response
245
+ * @throws TimeoutError if request exceeds timeout
246
+ */
247
+ async send(params) {
248
+ if (!this.options.webhookSecret) {
249
+ throw new ConfigurationError(
250
+ "webhookSecret is required for webhook operations"
251
+ );
252
+ }
253
+ const path = `/webhooks/actions/${this.options.org}/${params.action}`;
254
+ const body = JSON.stringify(params.payload);
255
+ const msgId = randomMessageId();
256
+ const timestamp = Math.floor(Date.now() / 1e3);
257
+ const signature = sign(this.options.webhookSecret, msgId, timestamp, body);
258
+ return this.http.request(path, {
259
+ method: "POST",
260
+ body,
261
+ headers: {
262
+ "svix-id": msgId,
263
+ "svix-timestamp": String(timestamp),
264
+ "svix-signature": signature
265
+ }
266
+ });
267
+ }
268
+ /**
269
+ * Verify an inbound Svix webhook signature.
270
+ *
271
+ * @returns true if valid, false if invalid or expired
272
+ * @throws ConfigurationError if webhookSecret is not configured
273
+ */
274
+ verify(params) {
275
+ if (!this.options.webhookSecret) {
276
+ throw new ConfigurationError(
277
+ "webhookSecret is required for webhook verification"
278
+ );
279
+ }
280
+ return verify(
281
+ this.options.webhookSecret,
282
+ params.payload,
283
+ params.headers
284
+ );
285
+ }
286
+ /**
287
+ * Verify an inbound Svix webhook signature, throwing on failure.
288
+ * Useful for middleware patterns where invalid signatures should halt processing.
289
+ *
290
+ * @throws WebhookSignatureError if signature is invalid or expired
291
+ * @throws ConfigurationError if webhookSecret is not configured
292
+ */
293
+ verifyOrThrow(params) {
294
+ if (!this.verify(params)) {
295
+ throw new WebhookSignatureError("Invalid webhook signature");
296
+ }
297
+ }
298
+ /**
299
+ * Verify and parse an inbound webhook from AgentPress.
300
+ * Combines signature verification with JSON parsing and type casting.
301
+ * This is the recommended way to handle incoming webhooks.
302
+ *
303
+ * @throws WebhookSignatureError if signature is invalid or expired
304
+ * @throws ConfigurationError if webhookSecret is not configured
305
+ * @throws AgentPressError if payload is not valid JSON
306
+ */
307
+ constructEvent(params) {
308
+ this.verifyOrThrow(params);
309
+ const body = typeof params.payload === "string" ? params.payload : params.payload.toString("utf-8");
310
+ try {
311
+ return JSON.parse(body);
312
+ } catch {
313
+ throw new AgentPressError("Webhook payload is not valid JSON");
314
+ }
315
+ }
316
+ };
317
+
318
+ // src/client.ts
319
+ var AgentPress = class {
320
+ /** Webhook operations: send outbound webhooks and verify inbound signatures. */
321
+ webhooks;
322
+ /** Action management: approve or reject staged actions. */
323
+ actions;
324
+ /**
325
+ * @param options - SDK configuration. All fields are optional with sensible defaults.
326
+ * @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.
327
+ */
328
+ constructor(options = {}) {
329
+ const resolved = resolveOptions(options);
330
+ const http = new HttpClient(resolved);
331
+ this.webhooks = new WebhooksClient(resolved, http);
332
+ this.actions = new ActionsClient(resolved, http);
333
+ }
334
+ };
335
+ function resolveOptions(options) {
336
+ const baseUrl = (options.baseUrl ?? "https://api.agent.press").replace(
337
+ /\/+$/,
338
+ ""
339
+ );
340
+ const timeout = options.timeout ?? 3e4;
341
+ const org = options.org ?? "default-org";
342
+ if (timeout <= 0 || !Number.isFinite(timeout)) {
343
+ throw new ConfigurationError("timeout must be a positive number");
344
+ }
345
+ if (options.webhookSecret !== void 0 && !options.webhookSecret.startsWith("whsec_")) {
346
+ throw new ConfigurationError('webhookSecret must start with "whsec_"');
347
+ }
348
+ return {
349
+ baseUrl,
350
+ timeout,
351
+ org,
352
+ webhookSecret: options.webhookSecret,
353
+ apiKey: options.apiKey,
354
+ onRequest: options.onRequest,
355
+ onResponse: options.onResponse
356
+ };
357
+ }
358
+ // Annotate the CommonJS export names for ESM import in node:
359
+ 0 && (module.exports = {
360
+ ActionsClient,
361
+ AgentPress,
362
+ AgentPressError,
363
+ ConfigurationError,
364
+ HttpError,
365
+ TimeoutError,
366
+ WebhookSignatureError
367
+ });
368
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/utils.ts","../src/webhooks/signing.ts","../src/actions/client.ts","../src/http.ts","../src/webhooks/client.ts","../src/client.ts"],"sourcesContent":["export { ActionsClient } from \"./actions/client\";\nexport { AgentPress } from \"./client\";\nexport {\n AgentPressError,\n ConfigurationError,\n HttpError,\n TimeoutError,\n WebhookSignatureError,\n} from \"./errors\";\nexport type {\n ActionCallbackPayload,\n ActionEventType,\n ActionManageResponse,\n ActionStatus,\n AgentPressOptions,\n AgentResponse,\n ApproveActionParams,\n RejectActionParams,\n StagedToolCall,\n ToolCallResult,\n WebhookResponse,\n WebhookSendParams,\n WebhookVerifyParams,\n} from \"./types\";\n","/**\n * Base error class for all SDK errors. Catch this to handle any error\n * thrown by the AgentPress SDK regardless of specific type.\n */\nexport class AgentPressError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AgentPressError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown at construction time when `AgentPressOptions` contains invalid values\n * (e.g., non-positive timeout, malformed `webhookSecret`).\n */\nexport class ConfigurationError extends AgentPressError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when the API returns a non-2xx HTTP response.\n *\n * Properties:\n * - `statusCode` - HTTP status code (e.g., 401, 404, 500)\n * - `responseBody` - Raw response body text for debugging\n * - `url` - The full request URL that failed\n */\nexport class HttpError extends AgentPressError {\n public readonly statusCode: number;\n public readonly responseBody: string;\n public readonly url: string;\n\n constructor(statusCode: number, responseBody: string, url: string) {\n super(`HTTP ${statusCode} from ${url}`);\n this.name = \"HttpError\";\n this.statusCode = statusCode;\n this.responseBody = responseBody;\n this.url = url;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown when a request exceeds the configured `timeout` (default 30s). */\nexport class TimeoutError extends AgentPressError {\n constructor(url: string, timeout: number) {\n super(`Request to ${url} timed out after ${timeout}ms`);\n this.name = \"TimeoutError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/** Thrown by {@link WebhooksClient.verifyOrThrow} when an inbound webhook signature is invalid or expired. */\nexport class WebhookSignatureError extends AgentPressError {\n constructor(message: string) {\n super(message);\n this.name = \"WebhookSignatureError\";\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","import { randomUUID } from \"node:crypto\";\n\nexport function randomMessageId(): string {\n return `msg_${randomUUID()}`;\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nconst SIGNATURE_PREFIX = \"v1,\";\nconst DEFAULT_TOLERANCE_SECONDS = 5 * 60; // 5 minutes\n\n/**\n * Sign a webhook payload using Svix-compatible HMAC-SHA256.\n *\n * @param secret - The webhook secret (with \"whsec_\" prefix)\n * @param msgId - Unique message ID (e.g., \"msg_<uuid>\")\n * @param timestamp - Unix timestamp in seconds\n * @param body - JSON stringified payload\n * @returns Signature string in format \"v1,<base64>\"\n */\nexport function sign(\n secret: string,\n msgId: string,\n timestamp: number,\n body: string,\n): string {\n const secretBytes = Buffer.from(secret.replace(/^whsec_/, \"\"), \"base64\");\n const message = `${msgId}.${timestamp}.${body}`;\n const signature = createHmac(\"sha256\", secretBytes)\n .update(message)\n .digest(\"base64\");\n return `${SIGNATURE_PREFIX}${signature}`;\n}\n\n/**\n * Verify a Svix webhook signature.\n *\n * @param secret - The webhook secret (with \"whsec_\" prefix)\n * @param payload - Raw request body (string or Buffer)\n * @param headers - Svix headers object\n * @param toleranceSeconds - Max age of signature in seconds (default: 5 min)\n * @returns true if valid, false if invalid or expired\n */\nexport function verify(\n secret: string,\n payload: string | Buffer,\n headers: {\n \"svix-id\": string;\n \"svix-timestamp\": string;\n \"svix-signature\": string;\n },\n toleranceSeconds: number = DEFAULT_TOLERANCE_SECONDS,\n): boolean {\n const msgId = headers[\"svix-id\"];\n const timestampStr = headers[\"svix-timestamp\"];\n const signatureHeader = headers[\"svix-signature\"];\n\n const timestamp = parseInt(timestampStr, 10);\n if (Number.isNaN(timestamp)) return false;\n\n const now = Math.floor(Date.now() / 1000);\n if (Math.abs(now - timestamp) > toleranceSeconds) return false;\n\n const body =\n typeof payload === \"string\" ? payload : payload.toString(\"utf-8\");\n const expected = sign(secret, msgId, timestamp, body);\n\n const signatures = signatureHeader.split(\" \");\n const expectedBuf = Buffer.from(expected);\n\n for (const sig of signatures) {\n const sigBuf = Buffer.from(sig);\n if (\n sigBuf.length === expectedBuf.length &&\n timingSafeEqual(sigBuf, expectedBuf)\n ) {\n return true;\n }\n }\n\n return false;\n}\n","import { ConfigurationError } from \"../errors\";\nimport type { HttpClient } from \"../http\";\nimport type {\n ActionManageResponse,\n ApproveActionParams,\n RejectActionParams,\n ResolvedOptions,\n} from \"../types\";\nimport { randomMessageId } from \"../utils\";\nimport { sign } from \"../webhooks/signing\";\n\n/**\n * Client for programmatically approving or rejecting staged actions.\n * Uses HMAC-SHA256 signing (Svix-compatible), identical to {@link WebhooksClient}.\n *\n * @example\n * ```ts\n * const client = new AgentPress({ webhookSecret: \"whsec_...\", org: \"my-org\" });\n *\n * // Approve a staged action\n * await client.actions.approve(\"act_123\", {\n * action: \"my_webhook_action\",\n * });\n *\n * // Reject with a reason\n * await client.actions.reject(\"act_456\", {\n * action: \"my_webhook_action\",\n * reason: \"Insufficient data\",\n * });\n * ```\n */\nexport class ActionsClient {\n private readonly options: ResolvedOptions;\n private readonly http: HttpClient;\n\n constructor(options: ResolvedOptions, http: HttpClient) {\n this.options = options;\n this.http = http;\n }\n\n /**\n * Approve a staged action, optionally modifying the tool call.\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response\n * @throws TimeoutError if request exceeds timeout\n */\n async approve(\n actionId: string,\n params: ApproveActionParams,\n ): Promise<ActionManageResponse> {\n return this.manage(actionId, params.action, \"approve\", {\n editedToolCall: params.editedToolCall,\n });\n }\n\n /**\n * Reject a staged action.\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response\n * @throws TimeoutError if request exceeds timeout\n */\n async reject(\n actionId: string,\n params: RejectActionParams,\n ): Promise<ActionManageResponse> {\n return this.manage(actionId, params.action, \"reject\", {\n reason: params.reason,\n });\n }\n\n private async manage(\n actionId: string,\n webhookAction: string,\n operation: \"approve\" | \"reject\",\n body: Record<string, unknown>,\n ): Promise<ActionManageResponse> {\n if (!this.options.webhookSecret) {\n throw new ConfigurationError(\n \"webhookSecret is required for action management operations\",\n );\n }\n\n const path = `/webhooks/actions/${this.options.org}/${webhookAction}/manage/${actionId}/${operation}`;\n const bodyStr = JSON.stringify(body);\n const msgId = randomMessageId();\n const timestamp = Math.floor(Date.now() / 1000);\n const signature = sign(\n this.options.webhookSecret,\n msgId,\n timestamp,\n bodyStr,\n );\n\n return this.http.request<ActionManageResponse>(path, {\n method: \"POST\",\n body: bodyStr,\n headers: {\n \"svix-id\": msgId,\n \"svix-timestamp\": String(timestamp),\n \"svix-signature\": signature,\n },\n });\n }\n}\n","import { AgentPressError, HttpError, TimeoutError } from \"./errors\";\nimport type { ResolvedOptions } from \"./types\";\n\n/**\n * Internal shared HTTP client. Not part of the public API -- used by\n * namespace clients (e.g., `WebhooksClient`) to make authenticated requests.\n * @internal\n */\nexport class HttpClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly onRequest?: ResolvedOptions[\"onRequest\"];\n private readonly onResponse?: ResolvedOptions[\"onResponse\"];\n\n constructor(options: ResolvedOptions) {\n this.baseUrl = options.baseUrl;\n this.timeout = options.timeout;\n this.onRequest = options.onRequest;\n this.onResponse = options.onResponse;\n }\n\n /**\n * Send an HTTP request to the API. Constructs the full URL from `baseUrl` + `path`,\n * applies the configured timeout via `AbortSignal`, fires `onRequest`/`onResponse`\n * hooks, and parses the JSON response.\n *\n * @throws {TimeoutError} If the request exceeds the configured timeout.\n * @throws {HttpError} If the API returns a non-2xx status code.\n * @throws {AgentPressError} On network failures or non-JSON responses.\n */\n async request<T>(path: string, init: RequestInit): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n const headers = new Headers(init.headers);\n if (!headers.has(\"Content-Type\")) {\n headers.set(\"Content-Type\", \"application/json\");\n }\n\n const requestInit: RequestInit = {\n ...init,\n headers,\n signal: AbortSignal.timeout(this.timeout),\n };\n\n this.onRequest?.(url, requestInit);\n\n let response: Response;\n try {\n // biome-ignore lint/style/noRestrictedGlobals: SDK is a standalone package that uses raw fetch\n response = await fetch(url, requestInit);\n } catch (error: unknown) {\n if (\n error instanceof Error &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\")\n ) {\n throw new TimeoutError(url, this.timeout);\n }\n const message =\n error instanceof Error ? error.message : \"Unknown fetch error\";\n throw new AgentPressError(`Request to ${url} failed: ${message}`);\n }\n\n this.onResponse?.(url, response.clone());\n\n const text = await response.text();\n\n if (!response.ok) {\n throw new HttpError(response.status, text, url);\n }\n\n try {\n return JSON.parse(text) as T;\n } catch {\n throw new AgentPressError(\n `Expected JSON response from ${url} but received: ${text.slice(0, 200)}`,\n );\n }\n }\n}\n","import {\n AgentPressError,\n ConfigurationError,\n WebhookSignatureError,\n} from \"../errors\";\nimport type { HttpClient } from \"../http\";\nimport type {\n ActionCallbackPayload,\n ResolvedOptions,\n WebhookResponse,\n WebhookSendParams,\n WebhookVerifyParams,\n} from \"../types\";\nimport { randomMessageId } from \"../utils\";\nimport { sign, verify as verifySig } from \"./signing\";\n\nexport class WebhooksClient {\n private readonly options: ResolvedOptions;\n private readonly http: HttpClient;\n\n constructor(options: ResolvedOptions, http: HttpClient) {\n this.options = options;\n this.http = http;\n }\n\n /**\n * Send an arbitrary webhook payload to AgentPress.\n * Signs the payload with HMAC-SHA256 (Svix-compatible).\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response\n * @throws TimeoutError if request exceeds timeout\n */\n async send(params: WebhookSendParams): Promise<WebhookResponse> {\n if (!this.options.webhookSecret) {\n throw new ConfigurationError(\n \"webhookSecret is required for webhook operations\",\n );\n }\n\n const path = `/webhooks/actions/${this.options.org}/${params.action}`;\n const body = JSON.stringify(params.payload);\n const msgId = randomMessageId();\n const timestamp = Math.floor(Date.now() / 1000);\n const signature = sign(this.options.webhookSecret, msgId, timestamp, body);\n\n return this.http.request<WebhookResponse>(path, {\n method: \"POST\",\n body,\n headers: {\n \"svix-id\": msgId,\n \"svix-timestamp\": String(timestamp),\n \"svix-signature\": signature,\n },\n });\n }\n\n /**\n * Verify an inbound Svix webhook signature.\n *\n * @returns true if valid, false if invalid or expired\n * @throws ConfigurationError if webhookSecret is not configured\n */\n verify(params: WebhookVerifyParams): boolean {\n if (!this.options.webhookSecret) {\n throw new ConfigurationError(\n \"webhookSecret is required for webhook verification\",\n );\n }\n\n return verifySig(\n this.options.webhookSecret,\n params.payload,\n params.headers,\n );\n }\n\n /**\n * Verify an inbound Svix webhook signature, throwing on failure.\n * Useful for middleware patterns where invalid signatures should halt processing.\n *\n * @throws WebhookSignatureError if signature is invalid or expired\n * @throws ConfigurationError if webhookSecret is not configured\n */\n verifyOrThrow(params: WebhookVerifyParams): void {\n if (!this.verify(params)) {\n throw new WebhookSignatureError(\"Invalid webhook signature\");\n }\n }\n\n /**\n * Verify and parse an inbound webhook from AgentPress.\n * Combines signature verification with JSON parsing and type casting.\n * This is the recommended way to handle incoming webhooks.\n *\n * @throws WebhookSignatureError if signature is invalid or expired\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws AgentPressError if payload is not valid JSON\n */\n constructEvent(params: WebhookVerifyParams): ActionCallbackPayload {\n this.verifyOrThrow(params);\n const body =\n typeof params.payload === \"string\"\n ? params.payload\n : params.payload.toString(\"utf-8\");\n try {\n return JSON.parse(body) as ActionCallbackPayload;\n } catch {\n throw new AgentPressError(\"Webhook payload is not valid JSON\");\n }\n }\n}\n","import { ActionsClient } from \"./actions/client\";\nimport { ConfigurationError } from \"./errors\";\nimport { HttpClient } from \"./http\";\nimport type { AgentPressOptions, ResolvedOptions } from \"./types\";\nimport { WebhooksClient } from \"./webhooks/client\";\n\n/**\n * Main entry point for the AgentPress SDK. Provides namespaced access to API\n * resources (e.g., `client.webhooks.send()`, `client.actions.approve()`).\n * Validates all configuration options at construction time, so invalid config fails fast.\n *\n * @example\n * ```ts\n * const client = new AgentPress({\n * apiKey: \"ak_...\",\n * webhookSecret: \"whsec_...\",\n * });\n * await client.webhooks.send({ action: \"my_action\", payload: { ... } });\n * await client.actions.approve(\"act_123\", { action: \"my_action\" });\n * ```\n */\nexport class AgentPress {\n /** Webhook operations: send outbound webhooks and verify inbound signatures. */\n public readonly webhooks: WebhooksClient;\n /** Action management: approve or reject staged actions. */\n public readonly actions: ActionsClient;\n\n /**\n * @param options - SDK configuration. All fields are optional with sensible defaults.\n * @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.\n */\n constructor(options: AgentPressOptions = {}) {\n const resolved = resolveOptions(options);\n const http = new HttpClient(resolved);\n this.webhooks = new WebhooksClient(resolved, http);\n this.actions = new ActionsClient(resolved, http);\n }\n}\n\nfunction resolveOptions(options: AgentPressOptions): ResolvedOptions {\n const baseUrl = (options.baseUrl ?? \"https://api.agent.press\").replace(\n /\\/+$/,\n \"\",\n );\n const timeout = options.timeout ?? 30_000;\n const org = options.org ?? \"default-org\";\n\n if (timeout <= 0 || !Number.isFinite(timeout)) {\n throw new ConfigurationError(\"timeout must be a positive number\");\n }\n\n if (\n options.webhookSecret !== undefined &&\n !options.webhookSecret.startsWith(\"whsec_\")\n ) {\n throw new ConfigurationError('webhookSecret must start with \"whsec_\"');\n }\n\n return {\n baseUrl,\n timeout,\n org,\n webhookSecret: options.webhookSecret,\n apiKey: options.apiKey,\n onRequest: options.onRequest,\n onResponse: options.onResponse,\n };\n}\n"],"mappings":"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","names":["import_node_crypto"]}