@agentpress/sdk 0.2.109 → 0.2.111
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 +123 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +168 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +168 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +123 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -146,7 +146,10 @@ var ActionsClient = class {
|
|
|
146
146
|
* @throws TimeoutError if request exceeds timeout
|
|
147
147
|
*/
|
|
148
148
|
async approve(actionId, params) {
|
|
149
|
-
|
|
149
|
+
const body = {};
|
|
150
|
+
if (params.editedToolCall !== void 0) body.editedToolCall = params.editedToolCall;
|
|
151
|
+
if (params.remember !== void 0) body.remember = params.remember;
|
|
152
|
+
return this.manage(actionId, params.action, "approve", body);
|
|
150
153
|
}
|
|
151
154
|
/**
|
|
152
155
|
* Reject a staged action.
|
|
@@ -231,6 +234,121 @@ var HttpClient = class {
|
|
|
231
234
|
}
|
|
232
235
|
};
|
|
233
236
|
//#endregion
|
|
237
|
+
//#region src/userApprovals/client.ts
|
|
238
|
+
/**
|
|
239
|
+
* Client for managing per-user auto-approval rules — the SDK equivalent of the
|
|
240
|
+
* console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing
|
|
241
|
+
* (Svix-compatible), identical to {@link ActionsClient.manage}.
|
|
242
|
+
*
|
|
243
|
+
* Each call is scoped to a single webhook (identified by `webhookIdentifier`),
|
|
244
|
+
* which both selects the signing secret and scopes which approvals are visible.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* const client = new AgentPress({ webhookSecret: "whsec_...", org: "my-org" });
|
|
249
|
+
*
|
|
250
|
+
* // Provision consent so future "sendEmail" triggers skip the approval prompt
|
|
251
|
+
* await client.userApprovals.create({
|
|
252
|
+
* webhookIdentifier: "reviews",
|
|
253
|
+
* userId: "user-uuid",
|
|
254
|
+
* actionWebhookId: "webhook-uuid",
|
|
255
|
+
* toolName: "sendEmail",
|
|
256
|
+
* mode: "always_allow",
|
|
257
|
+
* });
|
|
258
|
+
*
|
|
259
|
+
* // List rules (optionally filtered by userId)
|
|
260
|
+
* const { approvals } = await client.userApprovals.list({
|
|
261
|
+
* webhookIdentifier: "reviews",
|
|
262
|
+
* });
|
|
263
|
+
*
|
|
264
|
+
* // Revoke
|
|
265
|
+
* await client.userApprovals.delete(approvalId, { webhookIdentifier: "reviews" });
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
var UserApprovalsClient = class {
|
|
269
|
+
options;
|
|
270
|
+
http;
|
|
271
|
+
constructor(options, http) {
|
|
272
|
+
this.options = options;
|
|
273
|
+
this.http = http;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* List auto-approval rules for a webhook. Optionally filter by `userId`.
|
|
277
|
+
*
|
|
278
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
279
|
+
* @throws HttpError on non-2xx response
|
|
280
|
+
* @throws TimeoutError if request exceeds timeout
|
|
281
|
+
*/
|
|
282
|
+
async list(params) {
|
|
283
|
+
const body = {};
|
|
284
|
+
if (params.userId !== void 0) body.userId = params.userId;
|
|
285
|
+
if (params.authProvider !== void 0) body.authProvider = params.authProvider;
|
|
286
|
+
return this.send(params.webhookIdentifier, "list", body);
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Create (or upsert) an auto-approval rule. If a rule with the same
|
|
290
|
+
* `(userId, actionWebhookId, toolName)` triple already exists, it is
|
|
291
|
+
* updated in place.
|
|
292
|
+
*
|
|
293
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
294
|
+
* @throws HttpError on non-2xx response
|
|
295
|
+
* @throws TimeoutError if request exceeds timeout
|
|
296
|
+
*/
|
|
297
|
+
async create(params) {
|
|
298
|
+
const body = {
|
|
299
|
+
userId: params.userId,
|
|
300
|
+
actionWebhookId: params.actionWebhookId,
|
|
301
|
+
toolName: params.toolName,
|
|
302
|
+
mode: params.mode ?? "always_allow"
|
|
303
|
+
};
|
|
304
|
+
if (params.authProvider !== void 0) body.authProvider = params.authProvider;
|
|
305
|
+
if (params.expiresAt !== void 0) body.expiresAt = params.expiresAt === null ? null : params.expiresAt.toISOString();
|
|
306
|
+
return this.send(params.webhookIdentifier, "create", body);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Patch an existing auto-approval rule (change mode or expiry).
|
|
310
|
+
*
|
|
311
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
312
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
313
|
+
* @throws TimeoutError if request exceeds timeout
|
|
314
|
+
*/
|
|
315
|
+
async update(id, params) {
|
|
316
|
+
const body = {};
|
|
317
|
+
if (params.mode !== void 0) body.mode = params.mode;
|
|
318
|
+
if (params.expiresAt !== void 0) body.expiresAt = params.expiresAt === null ? null : params.expiresAt.toISOString();
|
|
319
|
+
return this.send(params.webhookIdentifier, `update/${id}`, body);
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Revoke an auto-approval rule. Future triggers of the corresponding
|
|
323
|
+
* `(user, webhook, tool)` combination will once again stage for approval.
|
|
324
|
+
*
|
|
325
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
326
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
327
|
+
* @throws TimeoutError if request exceeds timeout
|
|
328
|
+
*/
|
|
329
|
+
async delete(id, params) {
|
|
330
|
+
return this.send(params.webhookIdentifier, `delete/${id}`, {});
|
|
331
|
+
}
|
|
332
|
+
/** Internal: HMAC-sign and POST the body to the scoped path. */
|
|
333
|
+
async send(webhookIdentifier, operation, body) {
|
|
334
|
+
if (!this.options.webhookSecret) throw new ConfigurationError("webhookSecret is required for user approval management operations");
|
|
335
|
+
const path = `/webhooks/user-approvals/${this.options.org}/${webhookIdentifier}/${operation}`;
|
|
336
|
+
const bodyStr = JSON.stringify(body);
|
|
337
|
+
const msgId = randomMessageId();
|
|
338
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
339
|
+
const signature = sign(this.options.webhookSecret, msgId, timestamp, bodyStr);
|
|
340
|
+
return this.http.request(path, {
|
|
341
|
+
method: "POST",
|
|
342
|
+
body: bodyStr,
|
|
343
|
+
headers: {
|
|
344
|
+
"svix-id": msgId,
|
|
345
|
+
"svix-timestamp": String(timestamp),
|
|
346
|
+
"svix-signature": signature
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
//#endregion
|
|
234
352
|
//#region src/webhooks/client.ts
|
|
235
353
|
var WebhooksClient = class {
|
|
236
354
|
options;
|
|
@@ -325,6 +443,8 @@ var AgentPress = class {
|
|
|
325
443
|
webhooks;
|
|
326
444
|
/** Action management: approve or reject staged actions. */
|
|
327
445
|
actions;
|
|
446
|
+
/** Per-user auto-approval rules (read / create / update / delete). */
|
|
447
|
+
userApprovals;
|
|
328
448
|
/**
|
|
329
449
|
* @param options - SDK configuration. All fields are optional with sensible defaults.
|
|
330
450
|
* @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.
|
|
@@ -334,6 +454,7 @@ var AgentPress = class {
|
|
|
334
454
|
const http = new HttpClient(resolved);
|
|
335
455
|
this.webhooks = new WebhooksClient(resolved, http);
|
|
336
456
|
this.actions = new ActionsClient(resolved, http);
|
|
457
|
+
this.userApprovals = new UserApprovalsClient(resolved, http);
|
|
337
458
|
}
|
|
338
459
|
};
|
|
339
460
|
function resolveOptions(options) {
|
|
@@ -359,6 +480,7 @@ exports.AgentPressError = AgentPressError;
|
|
|
359
480
|
exports.ConfigurationError = ConfigurationError;
|
|
360
481
|
exports.HttpError = HttpError;
|
|
361
482
|
exports.TimeoutError = TimeoutError;
|
|
483
|
+
exports.UserApprovalsClient = UserApprovalsClient;
|
|
362
484
|
exports.WebhookSignatureError = WebhookSignatureError;
|
|
363
485
|
|
|
364
486
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["verifySig"],"sources":["../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":["/**\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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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["verifySig"],"sources":["../src/errors.ts","../src/utils.ts","../src/webhooks/signing.ts","../src/actions/client.ts","../src/http.ts","../src/userApprovals/client.ts","../src/webhooks/client.ts","../src/client.ts"],"sourcesContent":["/**\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 const body: Record<string, unknown> = {};\n if (params.editedToolCall !== undefined) {\n body.editedToolCall = params.editedToolCall;\n }\n if (params.remember !== undefined) {\n body.remember = params.remember;\n }\n return this.manage(actionId, params.action, \"approve\", body);\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 { ConfigurationError } from \"../errors\";\nimport type { HttpClient } from \"../http\";\nimport type {\n CreateUserApprovalParams,\n DeleteUserApprovalParams,\n ListUserApprovalsParams,\n ListUserApprovalsResponse,\n ResolvedOptions,\n UpdateUserApprovalParams,\n UserToolApproval,\n} from \"../types\";\nimport { randomMessageId } from \"../utils\";\nimport { sign } from \"../webhooks/signing\";\n\n/**\n * Client for managing per-user auto-approval rules — the SDK equivalent of the\n * console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing\n * (Svix-compatible), identical to {@link ActionsClient.manage}.\n *\n * Each call is scoped to a single webhook (identified by `webhookIdentifier`),\n * which both selects the signing secret and scopes which approvals are visible.\n *\n * @example\n * ```ts\n * const client = new AgentPress({ webhookSecret: \"whsec_...\", org: \"my-org\" });\n *\n * // Provision consent so future \"sendEmail\" triggers skip the approval prompt\n * await client.userApprovals.create({\n * webhookIdentifier: \"reviews\",\n * userId: \"user-uuid\",\n * actionWebhookId: \"webhook-uuid\",\n * toolName: \"sendEmail\",\n * mode: \"always_allow\",\n * });\n *\n * // List rules (optionally filtered by userId)\n * const { approvals } = await client.userApprovals.list({\n * webhookIdentifier: \"reviews\",\n * });\n *\n * // Revoke\n * await client.userApprovals.delete(approvalId, { webhookIdentifier: \"reviews\" });\n * ```\n */\nexport class UserApprovalsClient {\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 * List auto-approval rules for a webhook. Optionally filter by `userId`.\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 list(\n params: ListUserApprovalsParams,\n ): Promise<ListUserApprovalsResponse> {\n const body: Record<string, unknown> = {};\n if (params.userId !== undefined) body.userId = params.userId;\n if (params.authProvider !== undefined)\n body.authProvider = params.authProvider;\n return this.send<ListUserApprovalsResponse>(\n params.webhookIdentifier,\n \"list\",\n body,\n );\n }\n\n /**\n * Create (or upsert) an auto-approval rule. If a rule with the same\n * `(userId, actionWebhookId, toolName)` triple already exists, it is\n * updated in place.\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 create(params: CreateUserApprovalParams): Promise<UserToolApproval> {\n const body: Record<string, unknown> = {\n userId: params.userId,\n actionWebhookId: params.actionWebhookId,\n toolName: params.toolName,\n mode: params.mode ?? \"always_allow\",\n };\n if (params.authProvider !== undefined)\n body.authProvider = params.authProvider;\n if (params.expiresAt !== undefined) {\n body.expiresAt =\n params.expiresAt === null ? null : params.expiresAt.toISOString();\n }\n return this.send<UserToolApproval>(\n params.webhookIdentifier,\n \"create\",\n body,\n );\n }\n\n /**\n * Patch an existing auto-approval rule (change mode or expiry).\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)\n * @throws TimeoutError if request exceeds timeout\n */\n async update(\n id: string,\n params: UpdateUserApprovalParams,\n ): Promise<UserToolApproval> {\n const body: Record<string, unknown> = {};\n if (params.mode !== undefined) body.mode = params.mode;\n if (params.expiresAt !== undefined) {\n body.expiresAt =\n params.expiresAt === null ? null : params.expiresAt.toISOString();\n }\n return this.send<UserToolApproval>(\n params.webhookIdentifier,\n `update/${id}`,\n body,\n );\n }\n\n /**\n * Revoke an auto-approval rule. Future triggers of the corresponding\n * `(user, webhook, tool)` combination will once again stage for approval.\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)\n * @throws TimeoutError if request exceeds timeout\n */\n async delete(\n id: string,\n params: DeleteUserApprovalParams,\n ): Promise<{ success: boolean }> {\n return this.send<{ success: boolean }>(\n params.webhookIdentifier,\n `delete/${id}`,\n {},\n );\n }\n\n /** Internal: HMAC-sign and POST the body to the scoped path. */\n private async send<T>(\n webhookIdentifier: string,\n operation: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n if (!this.options.webhookSecret) {\n throw new ConfigurationError(\n \"webhookSecret is required for user approval management operations\",\n );\n }\n\n const path = `/webhooks/user-approvals/${this.options.org}/${webhookIdentifier}/${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<T>(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 {\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 { UserApprovalsClient } from \"./userApprovals/client\";\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 /** Per-user auto-approval rules (read / create / update / delete). */\n public readonly userApprovals: UserApprovalsClient;\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 this.userApprovals = new UserApprovalsClient(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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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -61,6 +61,15 @@ interface ApproveActionParams {
|
|
|
61
61
|
toolName: string;
|
|
62
62
|
arguments: Record<string, unknown>;
|
|
63
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* If `"webhook"`, also auto-approves future triggers of the same
|
|
66
|
+
* `(user, webhook, tool)` combination — same effect as the UI's
|
|
67
|
+
* "Always allow for this webhook" option.
|
|
68
|
+
*
|
|
69
|
+
* - `"once"` — approve only this action (default behavior).
|
|
70
|
+
* - `"webhook"` — approve and remember for future triggers.
|
|
71
|
+
*/
|
|
72
|
+
remember?: "once" | "webhook";
|
|
64
73
|
}
|
|
65
74
|
/** Parameters for {@link ActionsClient.reject}. */
|
|
66
75
|
interface RejectActionParams {
|
|
@@ -123,6 +132,86 @@ interface ActionCallbackPayload {
|
|
|
123
132
|
/** Additional custom fields from post-event configuration. */
|
|
124
133
|
[key: string]: unknown;
|
|
125
134
|
}
|
|
135
|
+
/** Mode of a user tool approval rule. */
|
|
136
|
+
type ApprovalMode = "always_allow" | "always_deny";
|
|
137
|
+
/**
|
|
138
|
+
* A persisted rule that auto-approves (or auto-denies) a specific
|
|
139
|
+
* `(user, webhook, tool)` triple, bypassing the per-action approval prompt.
|
|
140
|
+
* Dates are ISO 8601 strings on the wire.
|
|
141
|
+
*/
|
|
142
|
+
interface UserToolApproval {
|
|
143
|
+
id: string;
|
|
144
|
+
orgId: string;
|
|
145
|
+
userId: string;
|
|
146
|
+
actionWebhookId: string;
|
|
147
|
+
toolName: string;
|
|
148
|
+
mode: ApprovalMode;
|
|
149
|
+
/** ISO 8601 timestamp. `null` means never expires. */
|
|
150
|
+
expiresAt: string | null;
|
|
151
|
+
/** ISO 8601 timestamp. */
|
|
152
|
+
createdAt: string;
|
|
153
|
+
/** ISO 8601 timestamp. */
|
|
154
|
+
updatedAt: string;
|
|
155
|
+
}
|
|
156
|
+
/** Parameters for {@link UserApprovalsClient.list}. */
|
|
157
|
+
interface ListUserApprovalsParams {
|
|
158
|
+
/** Webhook identifier (slug) — required to scope the signing secret and the result. */
|
|
159
|
+
webhookIdentifier: string;
|
|
160
|
+
/**
|
|
161
|
+
* Filter to a single user's approvals. Accepts either an internal AgentPress
|
|
162
|
+
* user UUID, or — when paired with {@link authProvider} — an external user ID
|
|
163
|
+
* from a custom auth provider (e.g. LocalFalcon).
|
|
164
|
+
*/
|
|
165
|
+
userId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Name of the registered external auth provider. When provided, `userId` is
|
|
168
|
+
* treated as the external user ID and resolved to the internal user via
|
|
169
|
+
* `users.external_auth_id`.
|
|
170
|
+
*/
|
|
171
|
+
authProvider?: string;
|
|
172
|
+
}
|
|
173
|
+
/** Response from {@link UserApprovalsClient.list}. */
|
|
174
|
+
interface ListUserApprovalsResponse {
|
|
175
|
+
approvals: UserToolApproval[];
|
|
176
|
+
}
|
|
177
|
+
/** Parameters for {@link UserApprovalsClient.create}. */
|
|
178
|
+
interface CreateUserApprovalParams {
|
|
179
|
+
/** Webhook identifier (slug) — required to scope the signing secret. */
|
|
180
|
+
webhookIdentifier: string;
|
|
181
|
+
/**
|
|
182
|
+
* User identifier this rule applies to. Accepts either an internal AgentPress
|
|
183
|
+
* user UUID, or — when paired with {@link authProvider} — an external user ID
|
|
184
|
+
* from a custom auth provider (e.g. LocalFalcon).
|
|
185
|
+
*/
|
|
186
|
+
userId: string;
|
|
187
|
+
/**
|
|
188
|
+
* Name of the registered external auth provider. When provided, `userId` is
|
|
189
|
+
* treated as the external user ID and resolved to the internal user via
|
|
190
|
+
* `users.external_auth_id`. The user must have authenticated through the
|
|
191
|
+
* provider at least once for resolution to succeed.
|
|
192
|
+
*/
|
|
193
|
+
authProvider?: string;
|
|
194
|
+
/** UUID of the `action_webhooks` row. Must match the webhook identified by `webhookIdentifier`. */
|
|
195
|
+
actionWebhookId: string;
|
|
196
|
+
/** Name of the tool this rule covers. */
|
|
197
|
+
toolName: string;
|
|
198
|
+
/** @default "always_allow" */
|
|
199
|
+
mode?: ApprovalMode;
|
|
200
|
+
/** `null` or omitted = never expires. */
|
|
201
|
+
expiresAt?: Date | null;
|
|
202
|
+
}
|
|
203
|
+
/** Parameters for {@link UserApprovalsClient.update}. */
|
|
204
|
+
interface UpdateUserApprovalParams {
|
|
205
|
+
/** Webhook identifier (slug) the approval belongs to — required for signing. */
|
|
206
|
+
webhookIdentifier: string;
|
|
207
|
+
mode?: ApprovalMode;
|
|
208
|
+
expiresAt?: Date | null;
|
|
209
|
+
}
|
|
210
|
+
/** Parameters for {@link UserApprovalsClient.delete}. */
|
|
211
|
+
interface DeleteUserApprovalParams {
|
|
212
|
+
/** Webhook identifier (slug) the approval belongs to — required for signing. */
|
|
213
|
+
webhookIdentifier: string;
|
|
214
|
+
}
|
|
126
215
|
/** @internal Resolved (validated, defaulted) options. Not exported from the public API. */
|
|
127
216
|
interface ResolvedOptions {
|
|
128
217
|
baseUrl: string;
|
|
@@ -202,6 +291,82 @@ declare class ActionsClient {
|
|
|
202
291
|
private manage;
|
|
203
292
|
}
|
|
204
293
|
//#endregion
|
|
294
|
+
//#region src/userApprovals/client.d.ts
|
|
295
|
+
/**
|
|
296
|
+
* Client for managing per-user auto-approval rules — the SDK equivalent of the
|
|
297
|
+
* console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing
|
|
298
|
+
* (Svix-compatible), identical to {@link ActionsClient.manage}.
|
|
299
|
+
*
|
|
300
|
+
* Each call is scoped to a single webhook (identified by `webhookIdentifier`),
|
|
301
|
+
* which both selects the signing secret and scopes which approvals are visible.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* const client = new AgentPress({ webhookSecret: "whsec_...", org: "my-org" });
|
|
306
|
+
*
|
|
307
|
+
* // Provision consent so future "sendEmail" triggers skip the approval prompt
|
|
308
|
+
* await client.userApprovals.create({
|
|
309
|
+
* webhookIdentifier: "reviews",
|
|
310
|
+
* userId: "user-uuid",
|
|
311
|
+
* actionWebhookId: "webhook-uuid",
|
|
312
|
+
* toolName: "sendEmail",
|
|
313
|
+
* mode: "always_allow",
|
|
314
|
+
* });
|
|
315
|
+
*
|
|
316
|
+
* // List rules (optionally filtered by userId)
|
|
317
|
+
* const { approvals } = await client.userApprovals.list({
|
|
318
|
+
* webhookIdentifier: "reviews",
|
|
319
|
+
* });
|
|
320
|
+
*
|
|
321
|
+
* // Revoke
|
|
322
|
+
* await client.userApprovals.delete(approvalId, { webhookIdentifier: "reviews" });
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
declare class UserApprovalsClient {
|
|
326
|
+
private readonly options;
|
|
327
|
+
private readonly http;
|
|
328
|
+
constructor(options: ResolvedOptions, http: HttpClient);
|
|
329
|
+
/**
|
|
330
|
+
* List auto-approval rules for a webhook. Optionally filter by `userId`.
|
|
331
|
+
*
|
|
332
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
333
|
+
* @throws HttpError on non-2xx response
|
|
334
|
+
* @throws TimeoutError if request exceeds timeout
|
|
335
|
+
*/
|
|
336
|
+
list(params: ListUserApprovalsParams): Promise<ListUserApprovalsResponse>;
|
|
337
|
+
/**
|
|
338
|
+
* Create (or upsert) an auto-approval rule. If a rule with the same
|
|
339
|
+
* `(userId, actionWebhookId, toolName)` triple already exists, it is
|
|
340
|
+
* updated in place.
|
|
341
|
+
*
|
|
342
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
343
|
+
* @throws HttpError on non-2xx response
|
|
344
|
+
* @throws TimeoutError if request exceeds timeout
|
|
345
|
+
*/
|
|
346
|
+
create(params: CreateUserApprovalParams): Promise<UserToolApproval>;
|
|
347
|
+
/**
|
|
348
|
+
* Patch an existing auto-approval rule (change mode or expiry).
|
|
349
|
+
*
|
|
350
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
351
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
352
|
+
* @throws TimeoutError if request exceeds timeout
|
|
353
|
+
*/
|
|
354
|
+
update(id: string, params: UpdateUserApprovalParams): Promise<UserToolApproval>;
|
|
355
|
+
/**
|
|
356
|
+
* Revoke an auto-approval rule. Future triggers of the corresponding
|
|
357
|
+
* `(user, webhook, tool)` combination will once again stage for approval.
|
|
358
|
+
*
|
|
359
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
360
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
361
|
+
* @throws TimeoutError if request exceeds timeout
|
|
362
|
+
*/
|
|
363
|
+
delete(id: string, params: DeleteUserApprovalParams): Promise<{
|
|
364
|
+
success: boolean;
|
|
365
|
+
}>;
|
|
366
|
+
/** Internal: HMAC-sign and POST the body to the scoped path. */
|
|
367
|
+
private send;
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
205
370
|
//#region src/webhooks/client.d.ts
|
|
206
371
|
declare class WebhooksClient {
|
|
207
372
|
private readonly options;
|
|
@@ -264,6 +429,8 @@ declare class AgentPress {
|
|
|
264
429
|
readonly webhooks: WebhooksClient;
|
|
265
430
|
/** Action management: approve or reject staged actions. */
|
|
266
431
|
readonly actions: ActionsClient;
|
|
432
|
+
/** Per-user auto-approval rules (read / create / update / delete). */
|
|
433
|
+
readonly userApprovals: UserApprovalsClient;
|
|
267
434
|
/**
|
|
268
435
|
* @param options - SDK configuration. All fields are optional with sensible defaults.
|
|
269
436
|
* @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.
|
|
@@ -309,5 +476,5 @@ declare class WebhookSignatureError extends AgentPressError {
|
|
|
309
476
|
constructor(message: string);
|
|
310
477
|
}
|
|
311
478
|
//#endregion
|
|
312
|
-
export { type ActionCallbackPayload, type ActionEventType, type ActionManageResponse, type ActionStatus, ActionsClient, AgentPress, AgentPressError, type AgentPressOptions, type AgentResponse, type ApproveActionParams, ConfigurationError, HttpError, type RejectActionParams, type StagedToolCall, TimeoutError, type ToolCallResult, type WebhookResponse, type WebhookSendParams, WebhookSignatureError, type WebhookVerifyParams };
|
|
479
|
+
export { type ActionCallbackPayload, type ActionEventType, type ActionManageResponse, type ActionStatus, ActionsClient, AgentPress, AgentPressError, type AgentPressOptions, type AgentResponse, type ApprovalMode, type ApproveActionParams, ConfigurationError, type CreateUserApprovalParams, type DeleteUserApprovalParams, HttpError, type ListUserApprovalsParams, type ListUserApprovalsResponse, type RejectActionParams, type StagedToolCall, TimeoutError, type ToolCallResult, type UpdateUserApprovalParams, UserApprovalsClient, type UserToolApproval, type WebhookResponse, type WebhookSendParams, WebhookSignatureError, type WebhookVerifyParams };
|
|
313
480
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/http.ts","../src/actions/client.ts","../src/webhooks/client.ts","../src/client.ts","../src/errors.ts"],"mappings":";;UACiB,iBAAA;EAAiB;EAEhC,aAAA;EAY6C;EAV7C,MAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA;EAIA;EAFA,GAAA;EAEgC;EAAhC,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,WAAA;EAEhC;EAAA,UAAA,IAAc,GAAA,UAAa,QAAA,EAAU,QAAA;AAAA;;UAItB,iBAAA;EAJ8B;EAM7C,MAAA;EAFgC;EAIhC,OAAA,EAAS,MAAA;AAAA;;UAIM,mBAAA;EAJN;EAMT,OAAA,WAAkB,MAAA;EANH;EAQf,OAAA;IACE,SAAA;IACA,gBAAA;IACA,gBAAA;EAAA;AAAA;;UAKa,eAAA;EACf,OAAA;EANE;EAQF,QAAA;EARkB;EAUlB,aAAA;EACA,OAAA;EACA,IAAA,GAAO,MAAA;AAAA;;KAMG,eAAA;;UASK,cAAA;EACf,QAAA;EACA,UAAA;EACA,SAAA,EAAW,MAAA;AAAA;AAZb;AAAA,UAgBiB,mBAAA;;EAEf,MAAA;EAlByB;EAoBzB,cAAA;IACE,QAAA;IACA,SAAA,EAAW,MAAA;EAAA;AAAA;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/types.ts","../src/http.ts","../src/actions/client.ts","../src/userApprovals/client.ts","../src/webhooks/client.ts","../src/client.ts","../src/errors.ts"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -61,6 +61,15 @@ interface ApproveActionParams {
|
|
|
61
61
|
toolName: string;
|
|
62
62
|
arguments: Record<string, unknown>;
|
|
63
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* If `"webhook"`, also auto-approves future triggers of the same
|
|
66
|
+
* `(user, webhook, tool)` combination — same effect as the UI's
|
|
67
|
+
* "Always allow for this webhook" option.
|
|
68
|
+
*
|
|
69
|
+
* - `"once"` — approve only this action (default behavior).
|
|
70
|
+
* - `"webhook"` — approve and remember for future triggers.
|
|
71
|
+
*/
|
|
72
|
+
remember?: "once" | "webhook";
|
|
64
73
|
}
|
|
65
74
|
/** Parameters for {@link ActionsClient.reject}. */
|
|
66
75
|
interface RejectActionParams {
|
|
@@ -123,6 +132,86 @@ interface ActionCallbackPayload {
|
|
|
123
132
|
/** Additional custom fields from post-event configuration. */
|
|
124
133
|
[key: string]: unknown;
|
|
125
134
|
}
|
|
135
|
+
/** Mode of a user tool approval rule. */
|
|
136
|
+
type ApprovalMode = "always_allow" | "always_deny";
|
|
137
|
+
/**
|
|
138
|
+
* A persisted rule that auto-approves (or auto-denies) a specific
|
|
139
|
+
* `(user, webhook, tool)` triple, bypassing the per-action approval prompt.
|
|
140
|
+
* Dates are ISO 8601 strings on the wire.
|
|
141
|
+
*/
|
|
142
|
+
interface UserToolApproval {
|
|
143
|
+
id: string;
|
|
144
|
+
orgId: string;
|
|
145
|
+
userId: string;
|
|
146
|
+
actionWebhookId: string;
|
|
147
|
+
toolName: string;
|
|
148
|
+
mode: ApprovalMode;
|
|
149
|
+
/** ISO 8601 timestamp. `null` means never expires. */
|
|
150
|
+
expiresAt: string | null;
|
|
151
|
+
/** ISO 8601 timestamp. */
|
|
152
|
+
createdAt: string;
|
|
153
|
+
/** ISO 8601 timestamp. */
|
|
154
|
+
updatedAt: string;
|
|
155
|
+
}
|
|
156
|
+
/** Parameters for {@link UserApprovalsClient.list}. */
|
|
157
|
+
interface ListUserApprovalsParams {
|
|
158
|
+
/** Webhook identifier (slug) — required to scope the signing secret and the result. */
|
|
159
|
+
webhookIdentifier: string;
|
|
160
|
+
/**
|
|
161
|
+
* Filter to a single user's approvals. Accepts either an internal AgentPress
|
|
162
|
+
* user UUID, or — when paired with {@link authProvider} — an external user ID
|
|
163
|
+
* from a custom auth provider (e.g. LocalFalcon).
|
|
164
|
+
*/
|
|
165
|
+
userId?: string;
|
|
166
|
+
/**
|
|
167
|
+
* Name of the registered external auth provider. When provided, `userId` is
|
|
168
|
+
* treated as the external user ID and resolved to the internal user via
|
|
169
|
+
* `users.external_auth_id`.
|
|
170
|
+
*/
|
|
171
|
+
authProvider?: string;
|
|
172
|
+
}
|
|
173
|
+
/** Response from {@link UserApprovalsClient.list}. */
|
|
174
|
+
interface ListUserApprovalsResponse {
|
|
175
|
+
approvals: UserToolApproval[];
|
|
176
|
+
}
|
|
177
|
+
/** Parameters for {@link UserApprovalsClient.create}. */
|
|
178
|
+
interface CreateUserApprovalParams {
|
|
179
|
+
/** Webhook identifier (slug) — required to scope the signing secret. */
|
|
180
|
+
webhookIdentifier: string;
|
|
181
|
+
/**
|
|
182
|
+
* User identifier this rule applies to. Accepts either an internal AgentPress
|
|
183
|
+
* user UUID, or — when paired with {@link authProvider} — an external user ID
|
|
184
|
+
* from a custom auth provider (e.g. LocalFalcon).
|
|
185
|
+
*/
|
|
186
|
+
userId: string;
|
|
187
|
+
/**
|
|
188
|
+
* Name of the registered external auth provider. When provided, `userId` is
|
|
189
|
+
* treated as the external user ID and resolved to the internal user via
|
|
190
|
+
* `users.external_auth_id`. The user must have authenticated through the
|
|
191
|
+
* provider at least once for resolution to succeed.
|
|
192
|
+
*/
|
|
193
|
+
authProvider?: string;
|
|
194
|
+
/** UUID of the `action_webhooks` row. Must match the webhook identified by `webhookIdentifier`. */
|
|
195
|
+
actionWebhookId: string;
|
|
196
|
+
/** Name of the tool this rule covers. */
|
|
197
|
+
toolName: string;
|
|
198
|
+
/** @default "always_allow" */
|
|
199
|
+
mode?: ApprovalMode;
|
|
200
|
+
/** `null` or omitted = never expires. */
|
|
201
|
+
expiresAt?: Date | null;
|
|
202
|
+
}
|
|
203
|
+
/** Parameters for {@link UserApprovalsClient.update}. */
|
|
204
|
+
interface UpdateUserApprovalParams {
|
|
205
|
+
/** Webhook identifier (slug) the approval belongs to — required for signing. */
|
|
206
|
+
webhookIdentifier: string;
|
|
207
|
+
mode?: ApprovalMode;
|
|
208
|
+
expiresAt?: Date | null;
|
|
209
|
+
}
|
|
210
|
+
/** Parameters for {@link UserApprovalsClient.delete}. */
|
|
211
|
+
interface DeleteUserApprovalParams {
|
|
212
|
+
/** Webhook identifier (slug) the approval belongs to — required for signing. */
|
|
213
|
+
webhookIdentifier: string;
|
|
214
|
+
}
|
|
126
215
|
/** @internal Resolved (validated, defaulted) options. Not exported from the public API. */
|
|
127
216
|
interface ResolvedOptions {
|
|
128
217
|
baseUrl: string;
|
|
@@ -202,6 +291,82 @@ declare class ActionsClient {
|
|
|
202
291
|
private manage;
|
|
203
292
|
}
|
|
204
293
|
//#endregion
|
|
294
|
+
//#region src/userApprovals/client.d.ts
|
|
295
|
+
/**
|
|
296
|
+
* Client for managing per-user auto-approval rules — the SDK equivalent of the
|
|
297
|
+
* console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing
|
|
298
|
+
* (Svix-compatible), identical to {@link ActionsClient.manage}.
|
|
299
|
+
*
|
|
300
|
+
* Each call is scoped to a single webhook (identified by `webhookIdentifier`),
|
|
301
|
+
* which both selects the signing secret and scopes which approvals are visible.
|
|
302
|
+
*
|
|
303
|
+
* @example
|
|
304
|
+
* ```ts
|
|
305
|
+
* const client = new AgentPress({ webhookSecret: "whsec_...", org: "my-org" });
|
|
306
|
+
*
|
|
307
|
+
* // Provision consent so future "sendEmail" triggers skip the approval prompt
|
|
308
|
+
* await client.userApprovals.create({
|
|
309
|
+
* webhookIdentifier: "reviews",
|
|
310
|
+
* userId: "user-uuid",
|
|
311
|
+
* actionWebhookId: "webhook-uuid",
|
|
312
|
+
* toolName: "sendEmail",
|
|
313
|
+
* mode: "always_allow",
|
|
314
|
+
* });
|
|
315
|
+
*
|
|
316
|
+
* // List rules (optionally filtered by userId)
|
|
317
|
+
* const { approvals } = await client.userApprovals.list({
|
|
318
|
+
* webhookIdentifier: "reviews",
|
|
319
|
+
* });
|
|
320
|
+
*
|
|
321
|
+
* // Revoke
|
|
322
|
+
* await client.userApprovals.delete(approvalId, { webhookIdentifier: "reviews" });
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
declare class UserApprovalsClient {
|
|
326
|
+
private readonly options;
|
|
327
|
+
private readonly http;
|
|
328
|
+
constructor(options: ResolvedOptions, http: HttpClient);
|
|
329
|
+
/**
|
|
330
|
+
* List auto-approval rules for a webhook. Optionally filter by `userId`.
|
|
331
|
+
*
|
|
332
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
333
|
+
* @throws HttpError on non-2xx response
|
|
334
|
+
* @throws TimeoutError if request exceeds timeout
|
|
335
|
+
*/
|
|
336
|
+
list(params: ListUserApprovalsParams): Promise<ListUserApprovalsResponse>;
|
|
337
|
+
/**
|
|
338
|
+
* Create (or upsert) an auto-approval rule. If a rule with the same
|
|
339
|
+
* `(userId, actionWebhookId, toolName)` triple already exists, it is
|
|
340
|
+
* updated in place.
|
|
341
|
+
*
|
|
342
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
343
|
+
* @throws HttpError on non-2xx response
|
|
344
|
+
* @throws TimeoutError if request exceeds timeout
|
|
345
|
+
*/
|
|
346
|
+
create(params: CreateUserApprovalParams): Promise<UserToolApproval>;
|
|
347
|
+
/**
|
|
348
|
+
* Patch an existing auto-approval rule (change mode or expiry).
|
|
349
|
+
*
|
|
350
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
351
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
352
|
+
* @throws TimeoutError if request exceeds timeout
|
|
353
|
+
*/
|
|
354
|
+
update(id: string, params: UpdateUserApprovalParams): Promise<UserToolApproval>;
|
|
355
|
+
/**
|
|
356
|
+
* Revoke an auto-approval rule. Future triggers of the corresponding
|
|
357
|
+
* `(user, webhook, tool)` combination will once again stage for approval.
|
|
358
|
+
*
|
|
359
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
360
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
361
|
+
* @throws TimeoutError if request exceeds timeout
|
|
362
|
+
*/
|
|
363
|
+
delete(id: string, params: DeleteUserApprovalParams): Promise<{
|
|
364
|
+
success: boolean;
|
|
365
|
+
}>;
|
|
366
|
+
/** Internal: HMAC-sign and POST the body to the scoped path. */
|
|
367
|
+
private send;
|
|
368
|
+
}
|
|
369
|
+
//#endregion
|
|
205
370
|
//#region src/webhooks/client.d.ts
|
|
206
371
|
declare class WebhooksClient {
|
|
207
372
|
private readonly options;
|
|
@@ -264,6 +429,8 @@ declare class AgentPress {
|
|
|
264
429
|
readonly webhooks: WebhooksClient;
|
|
265
430
|
/** Action management: approve or reject staged actions. */
|
|
266
431
|
readonly actions: ActionsClient;
|
|
432
|
+
/** Per-user auto-approval rules (read / create / update / delete). */
|
|
433
|
+
readonly userApprovals: UserApprovalsClient;
|
|
267
434
|
/**
|
|
268
435
|
* @param options - SDK configuration. All fields are optional with sensible defaults.
|
|
269
436
|
* @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.
|
|
@@ -309,5 +476,5 @@ declare class WebhookSignatureError extends AgentPressError {
|
|
|
309
476
|
constructor(message: string);
|
|
310
477
|
}
|
|
311
478
|
//#endregion
|
|
312
|
-
export { type ActionCallbackPayload, type ActionEventType, type ActionManageResponse, type ActionStatus, ActionsClient, AgentPress, AgentPressError, type AgentPressOptions, type AgentResponse, type ApproveActionParams, ConfigurationError, HttpError, type RejectActionParams, type StagedToolCall, TimeoutError, type ToolCallResult, type WebhookResponse, type WebhookSendParams, WebhookSignatureError, type WebhookVerifyParams };
|
|
479
|
+
export { type ActionCallbackPayload, type ActionEventType, type ActionManageResponse, type ActionStatus, ActionsClient, AgentPress, AgentPressError, type AgentPressOptions, type AgentResponse, type ApprovalMode, type ApproveActionParams, ConfigurationError, type CreateUserApprovalParams, type DeleteUserApprovalParams, HttpError, type ListUserApprovalsParams, type ListUserApprovalsResponse, type RejectActionParams, type StagedToolCall, TimeoutError, type ToolCallResult, type UpdateUserApprovalParams, UserApprovalsClient, type UserToolApproval, type WebhookResponse, type WebhookSendParams, WebhookSignatureError, type WebhookVerifyParams };
|
|
313
480
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/http.ts","../src/actions/client.ts","../src/webhooks/client.ts","../src/client.ts","../src/errors.ts"],"mappings":";;UACiB,iBAAA;EAAiB;EAEhC,aAAA;EAY6C;EAV7C,MAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA;EAIA;EAFA,GAAA;EAEgC;EAAhC,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,WAAA;EAEhC;EAAA,UAAA,IAAc,GAAA,UAAa,QAAA,EAAU,QAAA;AAAA;;UAItB,iBAAA;EAJ8B;EAM7C,MAAA;EAFgC;EAIhC,OAAA,EAAS,MAAA;AAAA;;UAIM,mBAAA;EAJN;EAMT,OAAA,WAAkB,MAAA;EANH;EAQf,OAAA;IACE,SAAA;IACA,gBAAA;IACA,gBAAA;EAAA;AAAA;;UAKa,eAAA;EACf,OAAA;EANE;EAQF,QAAA;EARkB;EAUlB,aAAA;EACA,OAAA;EACA,IAAA,GAAO,MAAA;AAAA;;KAMG,eAAA;;UASK,cAAA;EACf,QAAA;EACA,UAAA;EACA,SAAA,EAAW,MAAA;AAAA;AAZb;AAAA,UAgBiB,mBAAA;;EAEf,MAAA;EAlByB;EAoBzB,cAAA;IACE,QAAA;IACA,SAAA,EAAW,MAAA;EAAA;AAAA;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/http.ts","../src/actions/client.ts","../src/userApprovals/client.ts","../src/webhooks/client.ts","../src/client.ts","../src/errors.ts"],"mappings":";;UACiB,iBAAA;EAAiB;EAEhC,aAAA;EAY6C;EAV7C,MAAA;EAAA;EAEA,OAAA;EAEA;EAAA,OAAA;EAIA;EAFA,GAAA;EAEgC;EAAhC,SAAA,IAAa,GAAA,UAAa,IAAA,EAAM,WAAA;EAEhC;EAAA,UAAA,IAAc,GAAA,UAAa,QAAA,EAAU,QAAA;AAAA;;UAItB,iBAAA;EAJ8B;EAM7C,MAAA;EAFgC;EAIhC,OAAA,EAAS,MAAA;AAAA;;UAIM,mBAAA;EAJN;EAMT,OAAA,WAAkB,MAAA;EANH;EAQf,OAAA;IACE,SAAA;IACA,gBAAA;IACA,gBAAA;EAAA;AAAA;;UAKa,eAAA;EACf,OAAA;EANE;EAQF,QAAA;EARkB;EAUlB,aAAA;EACA,OAAA;EACA,IAAA,GAAO,MAAA;AAAA;;KAMG,eAAA;;UASK,cAAA;EACf,QAAA;EACA,UAAA;EACA,SAAA,EAAW,MAAA;AAAA;AAZb;AAAA,UAgBiB,mBAAA;;EAEf,MAAA;EAlByB;EAoBzB,cAAA;IACE,QAAA;IACA,SAAA,EAAW,MAAA;EAAA;EAZb;;;;;;AAMF;;EAgBE,QAAA;AAAA;;UAIe,kBAAA;EAfb;EAiBF,MAAA;EAhBa;EAkBb,MAAA;AAAA;;UAIe,oBAAA;EACf,OAAA;EACA,QAAA;EACA,MAAA,EAAQ,YAAA;AAAA;AAHV;AAAA,KASY,YAAA;;UAUK,cAAA;EACf,QAAA;EACA,SAAA,EAAW,MAAA;EACX,MAAA;AAAA;;UAIe,aAAA;EAjBL;EAmBV,IAAA;;EAEA,SAAA,EAAW,cAAA;AAAA;AAXb;;;;AAAA,UAkBiB,qBAAA;EACf,QAAA;EACA,MAAA,EAAQ,YAAA;EACR,UAAA;EAlBM;EAoBN,SAAA,EAAW,eAAA;EAhBI;EAkBf,aAAA;;EAEA,cAAA,EAAgB,cAAA;EAlBhB;EAoBA,WAAA;EAlBW;EAoBX,UAAA,EAAY,MAAA;EApBa;EAsBzB,UAAA;EAfoC;EAiBpC,MAAA;EAfQ;EAiBR,QAAA;EAVgB;EAYhB,aAAA,EAAe,aAAA;EAAA;EAEf,YAAA;EAF4B;EAI5B,eAAA;EAvBA;EAAA,CAyBC,GAAA;AAAA;;KAMS,YAAA;;;;;;UAOK,gBAAA;EACf,EAAA;EACA,KAAA;EACA,MAAA;EACA,eAAA;EACA,QAAA;EACA,IAAA,EAAM,YAAA;EArBN;EAuBA,SAAA;EArBY;EAuBZ,SAAA;EAjBU;EAmBV,SAAA;AAAA;;UAIe,uBAAA;EAhBA;EAkBf,iBAAA;;;;;;EAMA,MAAA;EAnBA;;;;;EAyBA,YAAA;AAAA;;UAIe,yBAAA;EACf,SAAA,EAAW,gBAAA;AAAA;;UAII,wBAAA;EAff;EAiBA,iBAAA;EAXY;;AAId;;;EAaE,MAAA;EAZ2B;AAI7B;;;;;EAeE,YAAA;EAAA;EAEA,eAAA;EAEA;EAAA,QAAA;EAEO;EAAP,IAAA,GAAO,YAAA;EAEK;EAAZ,SAAA,GAAY,IAAA;AAAA;AAId;AAAA,UAAiB,wBAAA;;EAEf,iBAAA;EACA,IAAA,GAAO,YAAA;EACP,SAAA,GAAY,IAAA;AAAA;;UAIG,wBAAA;EAJC;EAMhB,iBAAA;AAAA;;UAIe,eAAA;EACf,OAAA;EACA,OAAA;EACA,GAAA;EACA,aAAA;EACA,MAAA;EACA,SAAA,GAAY,iBAAA;EACZ,UAAA,GAAa,iBAAA;AAAA;;;AAnQf;;;;;AAAA,cCOa,UAAA;EAAA,iBACM,OAAA;EAAA,iBACA,OAAA;EAAA,iBACA,SAAA;EAAA,iBACA,UAAA;cAEL,OAAA,EAAS,eAAA;EDDW;;;;;;;;AAMlC;ECWQ,OAAA,GAAA,CAAW,IAAA,UAAc,IAAA,EAAM,WAAA,GAAc,OAAA,CAAQ,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;ADX7D;;cEYa,aAAA;EAAA,iBACM,OAAA;EAAA,iBACA,IAAA;cAEL,OAAA,EAAS,eAAA,EAAiB,IAAA,EAAM,UAAA;EFZnC;;;AAIX;;;;EEoBQ,OAAA,CACJ,QAAA,UACA,MAAA,EAAQ,mBAAA,GACP,OAAA,CAAQ,oBAAA;EFrBO;;;;;;;EEuCZ,MAAA,CACJ,QAAA,UACA,MAAA,EAAQ,kBAAA,GACP,OAAA,CAAQ,oBAAA;EAAA,QAMG,MAAA;AAAA;;;;;;;;;;;;;;;;;;;;;AF1DhB;;;;;;;;;AAQA;;;cGiBa,mBAAA;EAAA,iBACM,OAAA;EAAA,iBACA,IAAA;cAEL,OAAA,EAAS,eAAA,EAAiB,IAAA,EAAM,UAAA;EHhB1C;;;;;AAOJ;;EGqBQ,IAAA,CACJ,MAAA,EAAQ,uBAAA,GACP,OAAA,CAAQ,yBAAA;EHhBE;;;;;;;;;EGqCP,MAAA,CAAO,MAAA,EAAQ,wBAAA,GAA2B,OAAA,CAAQ,gBAAA;EH/B/B;;;;AAS3B;;;EGiDQ,MAAA,CACJ,EAAA,UACA,MAAA,EAAQ,wBAAA,GACP,OAAA,CAAQ,gBAAA;EHnDX;;;;;;AAMF;;EGmEQ,MAAA,CACJ,EAAA,UACA,MAAA,EAAQ,wBAAA,GACP,OAAA;IAAU,OAAA;EAAA;EHlEb;EAAA,QG2Ec,IAAA;AAAA;;;cCnIH,cAAA;EAAA,iBACM,OAAA;EAAA,iBACA,IAAA;cAEL,OAAA,EAAS,eAAA,EAAiB,IAAA,EAAM,UAAA;EJf5C;;;;;;;;EI4BM,IAAA,CAAK,MAAA,EAAQ,iBAAA,GAAoB,OAAA,CAAQ,eAAA;EJlBjC;;;;;AAIhB;EI4CE,MAAA,CAAO,MAAA,EAAQ,mBAAA;;;;;;;;EAqBf,aAAA,CAAc,MAAA,EAAQ,mBAAA;EJzDY;;;;;;;;;EIwElC,cAAA,CAAe,MAAA,EAAQ,mBAAA,GAAsB,qBAAA;AAAA;;;;;;;;;;;;;;;;;;cC7ElC,UAAA;ELHI;EAAA,SKKC,QAAA,EAAU,cAAA;;WAEV,OAAA,EAAS,aAAA;ELLzB;EAAA,SKOgB,aAAA,EAAe,mBAAA;ELLtB;;;AAIX;cKOc,OAAA,GAAS,iBAAA;AAAA;;;;ALjCvB;;;cMGa,eAAA,SAAwB,KAAA;cACvB,OAAA;AAAA;;;;;cAWD,kBAAA,SAA2B,eAAA;cAC1B,OAAA;AAAA;;;;;;;ANEd;;cMaa,SAAA,SAAkB,eAAA;EAAA,SACb,UAAA;EAAA,SACA,YAAA;EAAA,SACA,GAAA;cAEJ,UAAA,UAAoB,YAAA,UAAsB,GAAA;AAAA;;cAW3C,YAAA,SAAqB,eAAA;cACpB,GAAA,UAAa,OAAA;AAAA;;cAQd,qBAAA,SAA8B,eAAA;cAC7B,OAAA;AAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -145,7 +145,10 @@ var ActionsClient = class {
|
|
|
145
145
|
* @throws TimeoutError if request exceeds timeout
|
|
146
146
|
*/
|
|
147
147
|
async approve(actionId, params) {
|
|
148
|
-
|
|
148
|
+
const body = {};
|
|
149
|
+
if (params.editedToolCall !== void 0) body.editedToolCall = params.editedToolCall;
|
|
150
|
+
if (params.remember !== void 0) body.remember = params.remember;
|
|
151
|
+
return this.manage(actionId, params.action, "approve", body);
|
|
149
152
|
}
|
|
150
153
|
/**
|
|
151
154
|
* Reject a staged action.
|
|
@@ -230,6 +233,121 @@ var HttpClient = class {
|
|
|
230
233
|
}
|
|
231
234
|
};
|
|
232
235
|
//#endregion
|
|
236
|
+
//#region src/userApprovals/client.ts
|
|
237
|
+
/**
|
|
238
|
+
* Client for managing per-user auto-approval rules — the SDK equivalent of the
|
|
239
|
+
* console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing
|
|
240
|
+
* (Svix-compatible), identical to {@link ActionsClient.manage}.
|
|
241
|
+
*
|
|
242
|
+
* Each call is scoped to a single webhook (identified by `webhookIdentifier`),
|
|
243
|
+
* which both selects the signing secret and scopes which approvals are visible.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* const client = new AgentPress({ webhookSecret: "whsec_...", org: "my-org" });
|
|
248
|
+
*
|
|
249
|
+
* // Provision consent so future "sendEmail" triggers skip the approval prompt
|
|
250
|
+
* await client.userApprovals.create({
|
|
251
|
+
* webhookIdentifier: "reviews",
|
|
252
|
+
* userId: "user-uuid",
|
|
253
|
+
* actionWebhookId: "webhook-uuid",
|
|
254
|
+
* toolName: "sendEmail",
|
|
255
|
+
* mode: "always_allow",
|
|
256
|
+
* });
|
|
257
|
+
*
|
|
258
|
+
* // List rules (optionally filtered by userId)
|
|
259
|
+
* const { approvals } = await client.userApprovals.list({
|
|
260
|
+
* webhookIdentifier: "reviews",
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* // Revoke
|
|
264
|
+
* await client.userApprovals.delete(approvalId, { webhookIdentifier: "reviews" });
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
var UserApprovalsClient = class {
|
|
268
|
+
options;
|
|
269
|
+
http;
|
|
270
|
+
constructor(options, http) {
|
|
271
|
+
this.options = options;
|
|
272
|
+
this.http = http;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* List auto-approval rules for a webhook. Optionally filter by `userId`.
|
|
276
|
+
*
|
|
277
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
278
|
+
* @throws HttpError on non-2xx response
|
|
279
|
+
* @throws TimeoutError if request exceeds timeout
|
|
280
|
+
*/
|
|
281
|
+
async list(params) {
|
|
282
|
+
const body = {};
|
|
283
|
+
if (params.userId !== void 0) body.userId = params.userId;
|
|
284
|
+
if (params.authProvider !== void 0) body.authProvider = params.authProvider;
|
|
285
|
+
return this.send(params.webhookIdentifier, "list", body);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Create (or upsert) an auto-approval rule. If a rule with the same
|
|
289
|
+
* `(userId, actionWebhookId, toolName)` triple already exists, it is
|
|
290
|
+
* updated in place.
|
|
291
|
+
*
|
|
292
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
293
|
+
* @throws HttpError on non-2xx response
|
|
294
|
+
* @throws TimeoutError if request exceeds timeout
|
|
295
|
+
*/
|
|
296
|
+
async create(params) {
|
|
297
|
+
const body = {
|
|
298
|
+
userId: params.userId,
|
|
299
|
+
actionWebhookId: params.actionWebhookId,
|
|
300
|
+
toolName: params.toolName,
|
|
301
|
+
mode: params.mode ?? "always_allow"
|
|
302
|
+
};
|
|
303
|
+
if (params.authProvider !== void 0) body.authProvider = params.authProvider;
|
|
304
|
+
if (params.expiresAt !== void 0) body.expiresAt = params.expiresAt === null ? null : params.expiresAt.toISOString();
|
|
305
|
+
return this.send(params.webhookIdentifier, "create", body);
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Patch an existing auto-approval rule (change mode or expiry).
|
|
309
|
+
*
|
|
310
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
311
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
312
|
+
* @throws TimeoutError if request exceeds timeout
|
|
313
|
+
*/
|
|
314
|
+
async update(id, params) {
|
|
315
|
+
const body = {};
|
|
316
|
+
if (params.mode !== void 0) body.mode = params.mode;
|
|
317
|
+
if (params.expiresAt !== void 0) body.expiresAt = params.expiresAt === null ? null : params.expiresAt.toISOString();
|
|
318
|
+
return this.send(params.webhookIdentifier, `update/${id}`, body);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Revoke an auto-approval rule. Future triggers of the corresponding
|
|
322
|
+
* `(user, webhook, tool)` combination will once again stage for approval.
|
|
323
|
+
*
|
|
324
|
+
* @throws ConfigurationError if webhookSecret is not configured
|
|
325
|
+
* @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)
|
|
326
|
+
* @throws TimeoutError if request exceeds timeout
|
|
327
|
+
*/
|
|
328
|
+
async delete(id, params) {
|
|
329
|
+
return this.send(params.webhookIdentifier, `delete/${id}`, {});
|
|
330
|
+
}
|
|
331
|
+
/** Internal: HMAC-sign and POST the body to the scoped path. */
|
|
332
|
+
async send(webhookIdentifier, operation, body) {
|
|
333
|
+
if (!this.options.webhookSecret) throw new ConfigurationError("webhookSecret is required for user approval management operations");
|
|
334
|
+
const path = `/webhooks/user-approvals/${this.options.org}/${webhookIdentifier}/${operation}`;
|
|
335
|
+
const bodyStr = JSON.stringify(body);
|
|
336
|
+
const msgId = randomMessageId();
|
|
337
|
+
const timestamp = Math.floor(Date.now() / 1e3);
|
|
338
|
+
const signature = sign(this.options.webhookSecret, msgId, timestamp, bodyStr);
|
|
339
|
+
return this.http.request(path, {
|
|
340
|
+
method: "POST",
|
|
341
|
+
body: bodyStr,
|
|
342
|
+
headers: {
|
|
343
|
+
"svix-id": msgId,
|
|
344
|
+
"svix-timestamp": String(timestamp),
|
|
345
|
+
"svix-signature": signature
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
//#endregion
|
|
233
351
|
//#region src/webhooks/client.ts
|
|
234
352
|
var WebhooksClient = class {
|
|
235
353
|
options;
|
|
@@ -324,6 +442,8 @@ var AgentPress = class {
|
|
|
324
442
|
webhooks;
|
|
325
443
|
/** Action management: approve or reject staged actions. */
|
|
326
444
|
actions;
|
|
445
|
+
/** Per-user auto-approval rules (read / create / update / delete). */
|
|
446
|
+
userApprovals;
|
|
327
447
|
/**
|
|
328
448
|
* @param options - SDK configuration. All fields are optional with sensible defaults.
|
|
329
449
|
* @throws {ConfigurationError} If `timeout` is non-positive or `webhookSecret` has an invalid prefix.
|
|
@@ -333,6 +453,7 @@ var AgentPress = class {
|
|
|
333
453
|
const http = new HttpClient(resolved);
|
|
334
454
|
this.webhooks = new WebhooksClient(resolved, http);
|
|
335
455
|
this.actions = new ActionsClient(resolved, http);
|
|
456
|
+
this.userApprovals = new UserApprovalsClient(resolved, http);
|
|
336
457
|
}
|
|
337
458
|
};
|
|
338
459
|
function resolveOptions(options) {
|
|
@@ -352,6 +473,6 @@ function resolveOptions(options) {
|
|
|
352
473
|
};
|
|
353
474
|
}
|
|
354
475
|
//#endregion
|
|
355
|
-
export { ActionsClient, AgentPress, AgentPressError, ConfigurationError, HttpError, TimeoutError, WebhookSignatureError };
|
|
476
|
+
export { ActionsClient, AgentPress, AgentPressError, ConfigurationError, HttpError, TimeoutError, UserApprovalsClient, WebhookSignatureError };
|
|
356
477
|
|
|
357
478
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["verifySig"],"sources":["../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":["/**\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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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["verifySig"],"sources":["../src/errors.ts","../src/utils.ts","../src/webhooks/signing.ts","../src/actions/client.ts","../src/http.ts","../src/userApprovals/client.ts","../src/webhooks/client.ts","../src/client.ts"],"sourcesContent":["/**\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 const body: Record<string, unknown> = {};\n if (params.editedToolCall !== undefined) {\n body.editedToolCall = params.editedToolCall;\n }\n if (params.remember !== undefined) {\n body.remember = params.remember;\n }\n return this.manage(actionId, params.action, \"approve\", body);\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 { ConfigurationError } from \"../errors\";\nimport type { HttpClient } from \"../http\";\nimport type {\n CreateUserApprovalParams,\n DeleteUserApprovalParams,\n ListUserApprovalsParams,\n ListUserApprovalsResponse,\n ResolvedOptions,\n UpdateUserApprovalParams,\n UserToolApproval,\n} from \"../types\";\nimport { randomMessageId } from \"../utils\";\nimport { sign } from \"../webhooks/signing\";\n\n/**\n * Client for managing per-user auto-approval rules — the SDK equivalent of the\n * console's `/account/auto-approvals` settings page. Uses HMAC-SHA256 signing\n * (Svix-compatible), identical to {@link ActionsClient.manage}.\n *\n * Each call is scoped to a single webhook (identified by `webhookIdentifier`),\n * which both selects the signing secret and scopes which approvals are visible.\n *\n * @example\n * ```ts\n * const client = new AgentPress({ webhookSecret: \"whsec_...\", org: \"my-org\" });\n *\n * // Provision consent so future \"sendEmail\" triggers skip the approval prompt\n * await client.userApprovals.create({\n * webhookIdentifier: \"reviews\",\n * userId: \"user-uuid\",\n * actionWebhookId: \"webhook-uuid\",\n * toolName: \"sendEmail\",\n * mode: \"always_allow\",\n * });\n *\n * // List rules (optionally filtered by userId)\n * const { approvals } = await client.userApprovals.list({\n * webhookIdentifier: \"reviews\",\n * });\n *\n * // Revoke\n * await client.userApprovals.delete(approvalId, { webhookIdentifier: \"reviews\" });\n * ```\n */\nexport class UserApprovalsClient {\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 * List auto-approval rules for a webhook. Optionally filter by `userId`.\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 list(\n params: ListUserApprovalsParams,\n ): Promise<ListUserApprovalsResponse> {\n const body: Record<string, unknown> = {};\n if (params.userId !== undefined) body.userId = params.userId;\n if (params.authProvider !== undefined)\n body.authProvider = params.authProvider;\n return this.send<ListUserApprovalsResponse>(\n params.webhookIdentifier,\n \"list\",\n body,\n );\n }\n\n /**\n * Create (or upsert) an auto-approval rule. If a rule with the same\n * `(userId, actionWebhookId, toolName)` triple already exists, it is\n * updated in place.\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 create(params: CreateUserApprovalParams): Promise<UserToolApproval> {\n const body: Record<string, unknown> = {\n userId: params.userId,\n actionWebhookId: params.actionWebhookId,\n toolName: params.toolName,\n mode: params.mode ?? \"always_allow\",\n };\n if (params.authProvider !== undefined)\n body.authProvider = params.authProvider;\n if (params.expiresAt !== undefined) {\n body.expiresAt =\n params.expiresAt === null ? null : params.expiresAt.toISOString();\n }\n return this.send<UserToolApproval>(\n params.webhookIdentifier,\n \"create\",\n body,\n );\n }\n\n /**\n * Patch an existing auto-approval rule (change mode or expiry).\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)\n * @throws TimeoutError if request exceeds timeout\n */\n async update(\n id: string,\n params: UpdateUserApprovalParams,\n ): Promise<UserToolApproval> {\n const body: Record<string, unknown> = {};\n if (params.mode !== undefined) body.mode = params.mode;\n if (params.expiresAt !== undefined) {\n body.expiresAt =\n params.expiresAt === null ? null : params.expiresAt.toISOString();\n }\n return this.send<UserToolApproval>(\n params.webhookIdentifier,\n `update/${id}`,\n body,\n );\n }\n\n /**\n * Revoke an auto-approval rule. Future triggers of the corresponding\n * `(user, webhook, tool)` combination will once again stage for approval.\n *\n * @throws ConfigurationError if webhookSecret is not configured\n * @throws HttpError on non-2xx response (404 if the rule does not belong to this webhook)\n * @throws TimeoutError if request exceeds timeout\n */\n async delete(\n id: string,\n params: DeleteUserApprovalParams,\n ): Promise<{ success: boolean }> {\n return this.send<{ success: boolean }>(\n params.webhookIdentifier,\n `delete/${id}`,\n {},\n );\n }\n\n /** Internal: HMAC-sign and POST the body to the scoped path. */\n private async send<T>(\n webhookIdentifier: string,\n operation: string,\n body: Record<string, unknown>,\n ): Promise<T> {\n if (!this.options.webhookSecret) {\n throw new ConfigurationError(\n \"webhookSecret is required for user approval management operations\",\n );\n }\n\n const path = `/webhooks/user-approvals/${this.options.org}/${webhookIdentifier}/${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<T>(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 {\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 { UserApprovalsClient } from \"./userApprovals/client\";\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 /** Per-user auto-approval rules (read / create / update / delete). */\n public readonly userApprovals: UserApprovalsClient;\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 this.userApprovals = new UserApprovalsClient(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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"}
|