@402flow/sdk 0.1.0-alpha.1

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.
@@ -0,0 +1,244 @@
1
+ import { z } from 'zod';
2
+ export const receiptAuthorizationOutcomeSchema = z.enum(['allowed']);
3
+ export const settlementEvidenceClassSchema = z.enum([
4
+ 'none',
5
+ 'inconclusive',
6
+ 'merchant_verifiable_success',
7
+ 'settled',
8
+ ]);
9
+ export const fulfillmentStatusSchema = z.enum([
10
+ 'succeeded',
11
+ 'failed',
12
+ 'inconclusive',
13
+ ]);
14
+ export const paymentProofSourceSchema = z.enum(['merchant', 'local_simulation']);
15
+ export const paidRequestProtocolSchema = z.enum(['x402', 'l402']);
16
+ export const paidRequestHttpMethodSchema = z.enum([
17
+ 'GET',
18
+ 'POST',
19
+ 'PUT',
20
+ 'PATCH',
21
+ 'DELETE',
22
+ 'HEAD',
23
+ 'OPTIONS',
24
+ ]);
25
+ export const paidRequestReasonCodeSchema = z.enum([
26
+ 'policy_allow',
27
+ 'policy_denied',
28
+ 'policy_review_required',
29
+ 'payment_execution_in_progress',
30
+ 'preflight_incompatible',
31
+ 'merchant_rejected',
32
+ 'settlement_proof_conflict',
33
+ 'merchant_transport_lost',
34
+ 'payment_rail_missing',
35
+ 'payment_rail_wrong_organization',
36
+ 'payment_rail_disabled',
37
+ 'payment_rail_incompatible',
38
+ ]);
39
+ const externalIdPattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
40
+ const decimalAmountPattern = /^\d+(?:\.\d+)?$/;
41
+ const minorUnitAmountPattern = /^\d+$/;
42
+ const currencyCodePattern = /^(?:[A-Z0-9_-]{3,10}|0x[a-fA-F0-9]{40})$/;
43
+ export const defaultMoneyPrecision = 6;
44
+ export const externalIdSchema = z
45
+ .string()
46
+ .trim()
47
+ .min(3)
48
+ .max(64)
49
+ .regex(externalIdPattern);
50
+ export const monetaryAmountSchema = z.string().regex(decimalAmountPattern);
51
+ export const currencyCodeSchema = z.string().regex(currencyCodePattern);
52
+ export const moneyUnitSchema = z.literal('minor');
53
+ function formatMonetaryAmount(amount, precision) {
54
+ if (!decimalAmountPattern.test(amount)) {
55
+ throw new Error('Invalid monetary amount format.');
56
+ }
57
+ const parts = amount.split('.');
58
+ const wholePart = parts[0] ?? '0';
59
+ const fractionalPart = parts[1] ?? '';
60
+ if (fractionalPart.length > precision) {
61
+ throw new Error('Monetary amount exceeds the declared precision.');
62
+ }
63
+ if (precision === 0) {
64
+ return wholePart;
65
+ }
66
+ return `${wholePart}.${fractionalPart.padEnd(precision, '0')}`;
67
+ }
68
+ export function monetaryAmountToMinorUnits(amount, precision) {
69
+ const normalizedAmount = formatMonetaryAmount(amount, precision);
70
+ if (precision === 0) {
71
+ return normalizedAmount;
72
+ }
73
+ const parts = normalizedAmount.split('.');
74
+ const wholePart = parts[0] ?? '0';
75
+ const fractionalPart = parts[1] ?? '';
76
+ const minorUnits = `${wholePart}${fractionalPart}`.replace(/^0+(?=\d)/, '');
77
+ return minorUnits || '0';
78
+ }
79
+ export const normalizedMoneySchema = z
80
+ .object({
81
+ asset: currencyCodeSchema,
82
+ amount: monetaryAmountSchema,
83
+ amountMinor: z.string().regex(minorUnitAmountPattern),
84
+ precision: z.number().int().min(0).max(defaultMoneyPrecision),
85
+ unit: moneyUnitSchema,
86
+ })
87
+ .superRefine((value, context) => {
88
+ try {
89
+ const normalizedAmount = formatMonetaryAmount(value.amount, value.precision);
90
+ if (normalizedAmount !== value.amount) {
91
+ context.addIssue({
92
+ code: z.ZodIssueCode.custom,
93
+ path: ['amount'],
94
+ message: 'Money amount must match the declared precision.',
95
+ });
96
+ }
97
+ if (monetaryAmountToMinorUnits(value.amount, value.precision) !==
98
+ value.amountMinor) {
99
+ context.addIssue({
100
+ code: z.ZodIssueCode.custom,
101
+ path: ['amountMinor'],
102
+ message: 'Money minor-unit amount must match the declared amount and precision.',
103
+ });
104
+ }
105
+ }
106
+ catch (error) {
107
+ context.addIssue({
108
+ code: z.ZodIssueCode.custom,
109
+ path: ['amount'],
110
+ message: error instanceof Error
111
+ ? error.message
112
+ : 'Invalid monetary amount provided.',
113
+ });
114
+ }
115
+ });
116
+ export const paidRequestContextSchema = z.object({
117
+ organization: externalIdSchema,
118
+ agent: externalIdSchema,
119
+ purpose: z.string().min(1).max(200).optional(),
120
+ metadata: z.record(z.unknown()).optional(),
121
+ });
122
+ export const paidRequestTargetSchema = z.object({
123
+ merchant: externalIdSchema,
124
+ paymentRail: externalIdSchema,
125
+ });
126
+ export const paidRequestHttpRequestSchema = z.object({
127
+ url: z.string().url(),
128
+ method: paidRequestHttpMethodSchema,
129
+ headers: z.record(z.string()).optional(),
130
+ body: z.string().optional(),
131
+ bodyHash: z.string().min(1).max(128).optional(),
132
+ });
133
+ export const paidRequestChallengeSchema = z.object({
134
+ protocol: paidRequestProtocolSchema,
135
+ money: normalizedMoneySchema,
136
+ payee: z.string().min(1).max(255).optional(),
137
+ memo: z.string().min(1).max(500).optional(),
138
+ raw: z.record(z.unknown()).default({}),
139
+ });
140
+ export const sdkPaymentDecisionRequestSchema = z.object({
141
+ context: paidRequestContextSchema,
142
+ target: paidRequestTargetSchema,
143
+ request: paidRequestHttpRequestSchema,
144
+ challenge: paidRequestChallengeSchema,
145
+ idempotencyKey: z.string().min(1).max(128).optional(),
146
+ });
147
+ export const sdkReceiptSchema = z.object({
148
+ receiptId: z.string().uuid(),
149
+ paidRequestId: z.string().uuid(),
150
+ paymentAttemptId: z.string().uuid(),
151
+ organizationId: z.string().uuid(),
152
+ agentId: z.string().uuid(),
153
+ merchantId: z.string().uuid(),
154
+ protocol: paidRequestProtocolSchema,
155
+ money: normalizedMoneySchema,
156
+ authorizationOutcome: receiptAuthorizationOutcomeSchema,
157
+ requestUrl: z.string().url(),
158
+ requestMethod: paidRequestHttpMethodSchema,
159
+ paymentReference: z.string().min(1).max(128).optional(),
160
+ evidenceSource: paymentProofSourceSchema.optional(),
161
+ settlementEvidenceClass: settlementEvidenceClassSchema.optional(),
162
+ settlementIdentifier: z.string().min(1).max(255).optional(),
163
+ fulfillmentStatus: fulfillmentStatusSchema.optional(),
164
+ createdAt: z.string().datetime(),
165
+ completedAt: z.string().datetime().optional(),
166
+ });
167
+ export const sdkMerchantResponseSchema = z.object({
168
+ status: z.number().int().min(100).max(599),
169
+ headers: z.record(z.string()).default({}),
170
+ body: z.string().default(''),
171
+ });
172
+ export const sdkPaymentDecisionAllowResponseSchema = z.object({
173
+ outcome: z.literal('allow'),
174
+ paidRequestId: z.string().uuid(),
175
+ paymentAttemptId: z.string().uuid(),
176
+ reasonCode: paidRequestReasonCodeSchema,
177
+ reason: z.string().min(1),
178
+ merchantResponse: sdkMerchantResponseSchema,
179
+ receipt: sdkReceiptSchema,
180
+ });
181
+ export const sdkPaymentDecisionPaidFulfillmentFailedResponseSchema = z.object({
182
+ outcome: z.literal('paid_fulfillment_failed'),
183
+ paidRequestId: z.string().uuid(),
184
+ paymentAttemptId: z.string().uuid(),
185
+ reasonCode: z.literal('merchant_rejected'),
186
+ reason: z.string().min(1),
187
+ merchantResponse: sdkMerchantResponseSchema,
188
+ settlementEvidenceClass: settlementEvidenceClassSchema,
189
+ fulfillmentStatus: z.literal('failed'),
190
+ receipt: sdkReceiptSchema,
191
+ evidence: z.record(z.unknown()).optional(),
192
+ });
193
+ export const sdkPaymentDecisionExecutionFailedResponseSchema = z.object({
194
+ outcome: z.literal('execution_failed'),
195
+ paidRequestId: z.string().uuid(),
196
+ paymentAttemptId: z.string().uuid(),
197
+ reasonCode: z.enum(['merchant_rejected', 'settlement_proof_conflict']),
198
+ reason: z.string().min(1),
199
+ merchantResponse: sdkMerchantResponseSchema,
200
+ evidence: z.record(z.unknown()).optional(),
201
+ });
202
+ export const sdkPaymentDecisionPreflightFailedResponseSchema = z.object({
203
+ outcome: z.literal('preflight_failed'),
204
+ paidRequestId: z.string().uuid(),
205
+ paymentAttemptId: z.string().uuid(),
206
+ reasonCode: z.literal('preflight_incompatible'),
207
+ reason: z.string().min(1),
208
+ evidence: z.record(z.unknown()).optional(),
209
+ });
210
+ export const sdkPaymentDecisionExecutingResponseSchema = z.object({
211
+ outcome: z.literal('executing'),
212
+ paidRequestId: z.string().uuid(),
213
+ paymentAttemptId: z.string().uuid(),
214
+ reasonCode: z.literal('payment_execution_in_progress'),
215
+ reason: z.string().min(1),
216
+ });
217
+ export const sdkPaymentDecisionInconclusiveResponseSchema = z.object({
218
+ outcome: z.literal('inconclusive'),
219
+ paidRequestId: z.string().uuid(),
220
+ paymentAttemptId: z.string().uuid(),
221
+ reasonCode: z.literal('merchant_transport_lost'),
222
+ reason: z.string().min(1),
223
+ evidence: z.record(z.unknown()).optional(),
224
+ });
225
+ export const sdkPaymentDecisionDenyResponseSchema = z.object({
226
+ outcome: z.literal('deny'),
227
+ paidRequestId: z.string().uuid().optional(),
228
+ reasonCode: paidRequestReasonCodeSchema,
229
+ reason: z.string().min(1),
230
+ policyReviewEventId: z.string().uuid().optional(),
231
+ });
232
+ export const sdkPaymentDecisionResponseSchema = z.discriminatedUnion('outcome', [
233
+ sdkPaymentDecisionAllowResponseSchema,
234
+ sdkPaymentDecisionPaidFulfillmentFailedResponseSchema,
235
+ sdkPaymentDecisionExecutingResponseSchema,
236
+ sdkPaymentDecisionPreflightFailedResponseSchema,
237
+ sdkPaymentDecisionExecutionFailedResponseSchema,
238
+ sdkPaymentDecisionInconclusiveResponseSchema,
239
+ sdkPaymentDecisionDenyResponseSchema,
240
+ ]);
241
+ export const sdkReceiptResponseSchema = z.object({
242
+ receipt: sdkReceiptSchema,
243
+ });
244
+ //# sourceMappingURL=contracts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { type ParsedChallenge } from './challenge-detection.js';
2
+ import { type PaidRequestContext, type PaidRequestTarget, type SdkPaymentDecisionResponse, type SdkReceipt, type SdkReceiptResponse } from './contracts.js';
3
+ export type AgentPayAuth = {
4
+ type: 'bootstrapKey';
5
+ bootstrapKey: string;
6
+ } | {
7
+ type: 'runtimeToken';
8
+ runtimeToken: string;
9
+ };
10
+ export type AgentPayClientOptions = {
11
+ controlPlaneBaseUrl: string;
12
+ auth: AgentPayAuth;
13
+ fetch?: typeof fetch;
14
+ headers?: Record<string, string>;
15
+ };
16
+ export type FetchPaidOptions = {
17
+ target: PaidRequestTarget;
18
+ challenge?: ParsedChallenge;
19
+ idempotencyKey?: string;
20
+ };
21
+ type PaidProtocol = ParsedChallenge['protocol'];
22
+ type DenyDecision = Extract<SdkPaymentDecisionResponse, {
23
+ outcome: 'deny';
24
+ }>;
25
+ type ExecutingDecision = Extract<SdkPaymentDecisionResponse, {
26
+ outcome: 'executing';
27
+ }>;
28
+ type InconclusiveDecision = Extract<SdkPaymentDecisionResponse, {
29
+ outcome: 'inconclusive';
30
+ }>;
31
+ type ExecutionFailedDecision = Extract<SdkPaymentDecisionResponse, {
32
+ outcome: 'execution_failed';
33
+ }>;
34
+ type PreflightFailedDecision = Extract<SdkPaymentDecisionResponse, {
35
+ outcome: 'preflight_failed';
36
+ }>;
37
+ type PaidFulfillmentFailedDecision = Extract<SdkPaymentDecisionResponse, {
38
+ outcome: 'paid_fulfillment_failed';
39
+ }>;
40
+ type PaidResponseBase = {
41
+ protocol: PaidProtocol | 'none';
42
+ response: Response;
43
+ };
44
+ export type PassthroughPaidResponse = PaidResponseBase & {
45
+ kind: 'passthrough';
46
+ protocol: 'none';
47
+ };
48
+ export type SuccessPaidResponse = PaidResponseBase & {
49
+ kind: 'success';
50
+ protocol: PaidProtocol;
51
+ paidRequestId: string;
52
+ paymentAttemptId: string;
53
+ receiptId: string;
54
+ receipt: SdkReceipt;
55
+ };
56
+ export type PaidFulfillmentFailedResponse = PaidResponseBase & {
57
+ kind: 'paid_fulfillment_failed';
58
+ protocol: PaidProtocol;
59
+ paidRequestId: string;
60
+ paymentAttemptId: string;
61
+ receiptId: string;
62
+ receipt: SdkReceipt;
63
+ reason: string;
64
+ decision: PaidFulfillmentFailedDecision;
65
+ };
66
+ export type DeniedPaidResponse = PaidResponseBase & {
67
+ kind: 'denied';
68
+ protocol: PaidProtocol;
69
+ paidRequestId?: string;
70
+ reason: string;
71
+ decision: DenyDecision;
72
+ policyReviewEventId?: string;
73
+ };
74
+ export type ExecutionPendingPaidResponse = PaidResponseBase & {
75
+ kind: 'execution_pending';
76
+ protocol: PaidProtocol;
77
+ paidRequestId: string;
78
+ paymentAttemptId: string;
79
+ reason: string;
80
+ decision: ExecutingDecision;
81
+ };
82
+ export type ExecutionInconclusivePaidResponse = PaidResponseBase & {
83
+ kind: 'execution_inconclusive';
84
+ protocol: PaidProtocol;
85
+ paidRequestId: string;
86
+ paymentAttemptId: string;
87
+ reason: string;
88
+ decision: InconclusiveDecision;
89
+ };
90
+ export type ExecutionFailedPaidResponse = PaidResponseBase & {
91
+ kind: 'execution_failed';
92
+ protocol: PaidProtocol;
93
+ paidRequestId: string;
94
+ paymentAttemptId: string;
95
+ reason: string;
96
+ decision: ExecutionFailedDecision;
97
+ };
98
+ export type PreflightFailedPaidResponse = PaidResponseBase & {
99
+ kind: 'preflight_failed';
100
+ protocol: PaidProtocol;
101
+ paidRequestId: string;
102
+ paymentAttemptId: string;
103
+ reason: string;
104
+ decision: PreflightFailedDecision;
105
+ };
106
+ export type PaidResponse = PassthroughPaidResponse | SuccessPaidResponse | PaidFulfillmentFailedResponse | DeniedPaidResponse | ExecutionPendingPaidResponse | ExecutionInconclusivePaidResponse | ExecutionFailedPaidResponse | PreflightFailedPaidResponse;
107
+ export declare class AgentPayClient {
108
+ private readonly controlPlaneBaseUrl;
109
+ private readonly auth;
110
+ private readonly fetchImpl;
111
+ private readonly headers;
112
+ private cachedRuntimeToken;
113
+ private pendingRuntimeToken;
114
+ constructor(options: AgentPayClientOptions);
115
+ fetchPaid(input: string, init: RequestInit | undefined, context: PaidRequestContext, options: FetchPaidOptions): Promise<PaidResponse>;
116
+ lookupReceipt(receiptId: string): Promise<SdkReceiptResponse>;
117
+ private createDecisionRequest;
118
+ private requestPaymentDecision;
119
+ private mapDecisionToPaidResponse;
120
+ private getRuntimeAuthorizationHeader;
121
+ private resolveRuntimeToken;
122
+ private requestRuntimeToken;
123
+ private controlPlaneFetch;
124
+ }
125
+ export declare function createAgentPayClient(options: AgentPayClientOptions): AgentPayClient;
126
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,290 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { detectChallengeFromResponse, } from './challenge-detection.js';
3
+ import { sdkPaymentDecisionRequestSchema, sdkPaymentDecisionResponseSchema, sdkReceiptResponseSchema, } from './contracts.js';
4
+ const defaultRuntimeTokenRefreshWindowMs = 30_000;
5
+ function trimTrailingSlash(value) {
6
+ return value.endsWith('/') ? value.slice(0, -1) : value;
7
+ }
8
+ function normalizeHeaders(headers) {
9
+ if (!headers) {
10
+ return undefined;
11
+ }
12
+ const normalizedHeaders = {};
13
+ const headerMap = new Headers(headers);
14
+ headerMap.forEach((value, key) => {
15
+ normalizedHeaders[key] = value;
16
+ });
17
+ return normalizedHeaders;
18
+ }
19
+ function createJsonResponse(status, payload) {
20
+ return new Response(JSON.stringify(payload), {
21
+ status,
22
+ headers: {
23
+ 'content-type': 'application/json',
24
+ },
25
+ });
26
+ }
27
+ function createMerchantResponse(merchantResponse) {
28
+ return new Response(merchantResponse.body, {
29
+ status: merchantResponse.status,
30
+ headers: merchantResponse.headers,
31
+ });
32
+ }
33
+ function getReplayableRequestBody(body) {
34
+ if (body === undefined || body === null) {
35
+ return undefined;
36
+ }
37
+ if (typeof body === 'string') {
38
+ return body;
39
+ }
40
+ if (body instanceof URLSearchParams) {
41
+ return body.toString();
42
+ }
43
+ throw new Error('Paid requests currently support replayable string and URLSearchParams bodies when routed through the control plane.');
44
+ }
45
+ function hashRequestBody(body) {
46
+ if (!body) {
47
+ return undefined;
48
+ }
49
+ return createHash('sha256').update(body).digest('hex');
50
+ }
51
+ function parseRuntimeTokenResponse(payload) {
52
+ if (!payload || typeof payload !== 'object') {
53
+ throw new Error('Runtime token exchange returned an invalid payload.');
54
+ }
55
+ const token = payload.token;
56
+ const expiresAt = payload.expiresAt;
57
+ if (typeof token !== 'string' || token.length === 0) {
58
+ throw new Error('Runtime token exchange response is missing token.');
59
+ }
60
+ if (typeof expiresAt !== 'string' || Number.isNaN(Date.parse(expiresAt))) {
61
+ throw new Error('Runtime token exchange response is missing expiresAt.');
62
+ }
63
+ return {
64
+ token,
65
+ expiresAt,
66
+ };
67
+ }
68
+ export class AgentPayClient {
69
+ controlPlaneBaseUrl;
70
+ auth;
71
+ fetchImpl;
72
+ headers;
73
+ cachedRuntimeToken;
74
+ pendingRuntimeToken;
75
+ constructor(options) {
76
+ this.controlPlaneBaseUrl = trimTrailingSlash(options.controlPlaneBaseUrl);
77
+ this.auth = options.auth;
78
+ this.fetchImpl = options.fetch ?? fetch;
79
+ this.headers = options.headers;
80
+ }
81
+ async fetchPaid(input, init = {}, context, options) {
82
+ let challenge = options.challenge;
83
+ if (!challenge) {
84
+ const initialResponse = await this.fetchImpl(input, init);
85
+ challenge = await detectChallengeFromResponse(initialResponse);
86
+ if (!challenge) {
87
+ return {
88
+ kind: 'passthrough',
89
+ protocol: 'none',
90
+ response: initialResponse,
91
+ };
92
+ }
93
+ }
94
+ const decisionRequest = await this.createDecisionRequest(input, init, context, options, challenge);
95
+ const decision = await this.requestPaymentDecision(decisionRequest);
96
+ return this.mapDecisionToPaidResponse(decision, challenge.protocol);
97
+ }
98
+ async lookupReceipt(receiptId) {
99
+ const response = await this.controlPlaneFetch(`/api/sdk/receipts/${receiptId}`, {
100
+ method: 'GET',
101
+ }, await this.getRuntimeAuthorizationHeader());
102
+ if (!response.ok) {
103
+ throw new Error(`Receipt lookup failed with status ${response.status}.`);
104
+ }
105
+ return sdkReceiptResponseSchema.parse(await response.json());
106
+ }
107
+ async createDecisionRequest(input, init, context, options, challenge) {
108
+ const requestBody = getReplayableRequestBody(init.body);
109
+ return sdkPaymentDecisionRequestSchema.parse({
110
+ context,
111
+ target: options.target,
112
+ request: {
113
+ url: input,
114
+ method: (init.method ?? 'GET').toUpperCase(),
115
+ headers: normalizeHeaders(init.headers),
116
+ body: requestBody,
117
+ bodyHash: hashRequestBody(requestBody),
118
+ },
119
+ challenge: {
120
+ protocol: challenge.protocol,
121
+ money: challenge.money,
122
+ raw: challenge.raw,
123
+ ...(challenge.payee ? { payee: challenge.payee } : {}),
124
+ },
125
+ idempotencyKey: options.idempotencyKey,
126
+ });
127
+ }
128
+ async requestPaymentDecision(decisionRequest) {
129
+ const decisionResponse = await this.controlPlaneFetch('/api/sdk/payment-decisions', {
130
+ method: 'POST',
131
+ headers: {
132
+ 'content-type': 'application/json',
133
+ },
134
+ body: JSON.stringify(decisionRequest),
135
+ }, await this.getRuntimeAuthorizationHeader());
136
+ if (!decisionResponse.ok) {
137
+ throw new Error(`Payment decision failed with status ${decisionResponse.status}.`);
138
+ }
139
+ return sdkPaymentDecisionResponseSchema.parse(await decisionResponse.json());
140
+ }
141
+ mapDecisionToPaidResponse(decision, protocol) {
142
+ switch (decision.outcome) {
143
+ case 'allow': {
144
+ const response = {
145
+ kind: 'success',
146
+ protocol,
147
+ response: createMerchantResponse(decision.merchantResponse),
148
+ paidRequestId: decision.paidRequestId,
149
+ paymentAttemptId: decision.paymentAttemptId,
150
+ receiptId: decision.receipt.receiptId,
151
+ receipt: decision.receipt,
152
+ };
153
+ return response;
154
+ }
155
+ case 'paid_fulfillment_failed': {
156
+ const response = {
157
+ kind: 'paid_fulfillment_failed',
158
+ protocol,
159
+ response: createMerchantResponse(decision.merchantResponse),
160
+ paidRequestId: decision.paidRequestId,
161
+ paymentAttemptId: decision.paymentAttemptId,
162
+ receiptId: decision.receipt.receiptId,
163
+ receipt: decision.receipt,
164
+ reason: decision.reason,
165
+ decision,
166
+ };
167
+ return response;
168
+ }
169
+ case 'deny': {
170
+ const response = {
171
+ kind: 'denied',
172
+ protocol,
173
+ response: createJsonResponse(403, decision),
174
+ reason: decision.reason,
175
+ decision,
176
+ ...(decision.paidRequestId
177
+ ? { paidRequestId: decision.paidRequestId }
178
+ : {}),
179
+ ...(decision.policyReviewEventId
180
+ ? { policyReviewEventId: decision.policyReviewEventId }
181
+ : {}),
182
+ };
183
+ return response;
184
+ }
185
+ case 'executing': {
186
+ const response = {
187
+ kind: 'execution_pending',
188
+ protocol,
189
+ response: createJsonResponse(202, decision),
190
+ paidRequestId: decision.paidRequestId,
191
+ paymentAttemptId: decision.paymentAttemptId,
192
+ reason: decision.reason,
193
+ decision,
194
+ };
195
+ return response;
196
+ }
197
+ case 'inconclusive': {
198
+ const response = {
199
+ kind: 'execution_inconclusive',
200
+ protocol,
201
+ response: createJsonResponse(202, decision),
202
+ paidRequestId: decision.paidRequestId,
203
+ paymentAttemptId: decision.paymentAttemptId,
204
+ reason: decision.reason,
205
+ decision,
206
+ };
207
+ return response;
208
+ }
209
+ case 'execution_failed': {
210
+ const response = {
211
+ kind: 'execution_failed',
212
+ protocol,
213
+ response: createMerchantResponse(decision.merchantResponse),
214
+ paidRequestId: decision.paidRequestId,
215
+ paymentAttemptId: decision.paymentAttemptId,
216
+ reason: decision.reason,
217
+ decision,
218
+ };
219
+ return response;
220
+ }
221
+ case 'preflight_failed': {
222
+ const response = {
223
+ kind: 'preflight_failed',
224
+ protocol,
225
+ response: createJsonResponse(502, decision),
226
+ paidRequestId: decision.paidRequestId,
227
+ paymentAttemptId: decision.paymentAttemptId,
228
+ reason: decision.reason,
229
+ decision,
230
+ };
231
+ return response;
232
+ }
233
+ }
234
+ }
235
+ async getRuntimeAuthorizationHeader() {
236
+ const runtimeToken = await this.resolveRuntimeToken();
237
+ return `Bearer ${runtimeToken}`;
238
+ }
239
+ async resolveRuntimeToken() {
240
+ if (this.auth.type === 'runtimeToken') {
241
+ return this.auth.runtimeToken;
242
+ }
243
+ if (this.cachedRuntimeToken) {
244
+ const expiresInMs = this.cachedRuntimeToken.expiresAtMs - Date.now();
245
+ if (expiresInMs > defaultRuntimeTokenRefreshWindowMs) {
246
+ return this.cachedRuntimeToken.token;
247
+ }
248
+ }
249
+ if (!this.pendingRuntimeToken) {
250
+ this.pendingRuntimeToken = this.requestRuntimeToken();
251
+ }
252
+ try {
253
+ return await this.pendingRuntimeToken;
254
+ }
255
+ finally {
256
+ this.pendingRuntimeToken = undefined;
257
+ }
258
+ }
259
+ async requestRuntimeToken() {
260
+ if (this.auth.type !== 'bootstrapKey') {
261
+ throw new Error('Runtime token exchange requires bootstrapKey auth.');
262
+ }
263
+ const response = await this.controlPlaneFetch('/api/sdk/runtime-tokens', {
264
+ method: 'POST',
265
+ }, `Bearer ${this.auth.bootstrapKey}`);
266
+ if (!response.ok) {
267
+ throw new Error(`Runtime token exchange failed with status ${response.status}.`);
268
+ }
269
+ const runtimeToken = parseRuntimeTokenResponse(await response.json());
270
+ this.cachedRuntimeToken = {
271
+ token: runtimeToken.token,
272
+ expiresAtMs: Date.parse(runtimeToken.expiresAt),
273
+ };
274
+ return runtimeToken.token;
275
+ }
276
+ async controlPlaneFetch(path, init, authorizationHeader) {
277
+ return this.fetchImpl(`${this.controlPlaneBaseUrl}${path}`, {
278
+ ...init,
279
+ headers: {
280
+ ...(this.headers ?? {}),
281
+ ...(normalizeHeaders(init.headers) ?? {}),
282
+ Authorization: authorizationHeader,
283
+ },
284
+ });
285
+ }
286
+ }
287
+ export function createAgentPayClient(options) {
288
+ return new AgentPayClient(options);
289
+ }
290
+ //# sourceMappingURL=index.js.map