@weaccelerateinc/agent-sdk 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/approved-extension-releases/0.0.0.1.json +3 -1
- package/approved-extension-releases/0.0.0.2.json +3 -1
- package/approved-extension.js +1 -1
- package/browser-use-host.d.ts +4 -4
- package/browser-use-host.js +12 -20
- package/index.d.ts +16 -1
- package/index.js +18 -3
- package/package.json +1 -1
- package/partner-starter/README.md +3 -3
- package/partner-starter/package.json +1 -1
- package/partner-starter/synthetic.mjs +1 -1
- package/private-chat.d.ts +5 -1
- package/private-chat.js +6 -4
- package/starter/README.md +2 -2
- package/starter/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
# @weaccelerateinc/agent-sdk 0.
|
|
1
|
+
# @weaccelerateinc/agent-sdk 0.14.0
|
|
2
2
|
|
|
3
|
-
SDK 0.
|
|
3
|
+
SDK 0.14.0 adds `client.checkouts.erase(id, binding)` for account deletion and negotiated `number_required` hints in private chat. Erasure retains cleanup ownership until browser retirement succeeds. A false or absent card hint does not establish readiness; verification can still require CVV or full card details.
|
|
4
|
+
|
|
5
|
+
SDK 0.14.0 also lets authenticated integrations attach their customer-owned Browser Use browser without a separate merchant opt-in or an inventory of other installed extensions. Accelerate verifies its own extension, ownership and run binding. The run-created flow remains fill-only with private verification, durable scheduling/viewer fences, replay protection and cleanup. The approved extension ZIP is unchanged; its compatibility metadata includes 0.14.0.
|
|
6
|
+
|
|
7
|
+
The browser-attachment baseline requires migration 004 and its matching gateway/reaper. For the 0.14.0 card hint, deploy the updated managed service before the wallet card-number passthrough and deploy the API flag in the same target environment. Then install this SDK. SDK 0.12.0 retains its original opt-in and inventory checks. The customer controls its browser and other extensions; Accelerate does not claim isolation from them.
|
|
4
8
|
|
|
5
9
|
Version 0.11.0 is a breaking release: **Accelerate never sends the final payment click.** A purchase arms one short click, the customer's agent performs it once through its own browser connection (`BrowserConnectorHost.performFinalClick`) in the customer's existing browser, then Accelerate observes the outcome. Purchase requires `final_click_actor:'customer'` and that host; the managed Kernel browser is fill-only. `client.checkouts.submit` rejects locally with `customer_click_required`. See [customer-owned final click](../../docs/customer-final-click.md). Release 0.10.3 keeps its existing behavior. Merchant layouts remain limited to the qualified sandbox page; this SDK release does not by itself qualify any merchant layout, a service deployment or production payments.
|
|
6
10
|
|
|
7
|
-
Server-only ESM SDK with TypeScript declarations, Node 22+, zero runtime dependencies. New partners use their existing browser and explicitly select `managed_review_v2`, which continues an armed fill immediately after private CVV verification. Existing callers keep `managed_review_v1` unless they opt in. Public npm releases use `@weaccelerateinc/agent-sdk`; install an exact available version with `npm install @weaccelerateinc/agent-sdk@0.
|
|
11
|
+
Server-only ESM SDK with TypeScript declarations, Node 22+, zero runtime dependencies. New partners use their existing browser and explicitly select `managed_review_v2`, which continues an armed fill immediately after private CVV verification. Existing callers keep `managed_review_v1` unless they opt in. Public npm releases use `@weaccelerateinc/agent-sdk`; install an exact available version with `npm install @weaccelerateinc/agent-sdk@0.14.0`. Check `npm view @weaccelerateinc/agent-sdk@0.14.0 version` to confirm registry availability. The package remains `UNLICENSED`.
|
|
8
12
|
|
|
9
13
|
```sh
|
|
10
|
-
npm install --ignore-scripts @weaccelerateinc/agent-sdk@0.
|
|
14
|
+
npm install --ignore-scripts @weaccelerateinc/agent-sdk@0.14.0
|
|
11
15
|
npx --no-install accelerate-agent init ./partner-demo --browser existing
|
|
12
16
|
```
|
|
13
17
|
|
package/approved-extension.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
|
|
3
|
-
const SDK_VERSION = '0.
|
|
3
|
+
const SDK_VERSION = '0.14.0';
|
|
4
4
|
const EXECUTOR_CONTRACT = 'accelerate_manual_checkout_v1';
|
|
5
5
|
const BRIDGE_PROTOCOL = 'accelerate_extension_bridge_v1';
|
|
6
6
|
const LEGACY_SHA256 = '65574cbb27ab344687963f72a136f2653551b57458b284e486946b27699099c8';
|
package/browser-use-host.d.ts
CHANGED
|
@@ -42,14 +42,14 @@ export function createBrowserUseHost(options: {
|
|
|
42
42
|
merchantId: string;
|
|
43
43
|
extensionId: string;
|
|
44
44
|
/** Primary runtime ID pinned in durable operator installation configuration.
|
|
45
|
-
* Required
|
|
45
|
+
* Required when the resolved browser has run provenance; stable across host restarts. */
|
|
46
46
|
extensionRuntimeId?: string;
|
|
47
47
|
extensionRelease: ApprovedExtensionRelease;
|
|
48
48
|
host: BrowserUsePlatformHost;
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
49
|
+
/** @deprecated Ignored. Run-created browsers require a durable owned reservation,
|
|
50
|
+
* a pinned extensionRuntimeId and a fence covering all session runs and queued work. */
|
|
51
51
|
allowRunCreatedBrowsers?: boolean;
|
|
52
|
-
/**
|
|
52
|
+
/** @deprecated Ignored. The customer manages its other browser extensions. */
|
|
53
53
|
additionalExtensions?: ReadonlyArray<Readonly<{ id: string; runtimeId: string; version: string }>>;
|
|
54
54
|
fetchImpl?: typeof fetch;
|
|
55
55
|
/** Test clock only. */
|
package/browser-use-host.js
CHANGED
|
@@ -45,23 +45,14 @@ const freeze = value => {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
export function createBrowserUseHost(configuration = {}) {
|
|
48
|
+
// Legacy opt-in and extension-inventory options remain accepted but have no effect.
|
|
48
49
|
exact(configuration, ['apiKey', 'merchantId', 'extensionId', 'extensionRelease', 'host'], ['fetchImpl', 'now', 'allowRunCreatedBrowsers', 'additionalExtensions', 'extensionRuntimeId']);
|
|
49
|
-
const { apiKey, merchantId, extensionId, host, fetchImpl = fetch, now = Date.now,
|
|
50
|
-
allowRunCreatedBrowsers = false, additionalExtensions = [], extensionRuntimeId } = configuration;
|
|
50
|
+
const { apiKey, merchantId, extensionId, host, fetchImpl = fetch, now = Date.now, extensionRuntimeId } = configuration;
|
|
51
51
|
check(typeof apiKey === 'string' && apiKey.length >= 16 && apiKey.length <= 500 && !/[\u0000-\u0020\u007f]/u.test(apiKey) &&
|
|
52
52
|
UUID.test(merchantId) && UUID.test(extensionId) && typeof fetchImpl === 'function' && typeof now === 'function' && host &&
|
|
53
53
|
['resolveOwnedBrowser', 'drainAndFence', 'bindCheckout', 'resolveCheckoutBrowser', 'inspectDocument', 'confirmLocalCleanup']
|
|
54
54
|
.every(key => typeof host[key] === 'function'), 'configuration_invalid');
|
|
55
|
-
check(typeof allowRunCreatedBrowsers === 'boolean' && Array.isArray(additionalExtensions) && additionalExtensions.length <= 2, 'configuration_invalid');
|
|
56
55
|
check(extensionRuntimeId === undefined || RUNTIME.test(extensionRuntimeId), 'configuration_invalid');
|
|
57
|
-
check(!(allowRunCreatedBrowsers || additionalExtensions.length) || RUNTIME.test(extensionRuntimeId ?? ''), 'configuration_invalid');
|
|
58
|
-
const extensionIds = new Set([extensionId]), runtimes = new Set();
|
|
59
|
-
const extras = additionalExtensions.map(value => {
|
|
60
|
-
exact(value, ['id', 'runtimeId', 'version']);
|
|
61
|
-
check(UUID.test(value.id) && RUNTIME.test(value.runtimeId) && typeof value.version === 'string' &&
|
|
62
|
-
/^\d+(?:\.\d+){0,3}$/u.test(value.version) && !extensionIds.has(value.id) && !runtimes.has(value.runtimeId), 'configuration_invalid');
|
|
63
|
-
extensionIds.add(value.id); runtimes.add(value.runtimeId); return Object.freeze({ ...value });
|
|
64
|
-
});
|
|
65
56
|
let release;
|
|
66
57
|
try { release = validateApprovedExtensionRelease(configuration.extensionRelease); }
|
|
67
58
|
catch { throw new AccelerateError('configuration_invalid'); }
|
|
@@ -81,7 +72,8 @@ export function createBrowserUseHost(configuration = {}) {
|
|
|
81
72
|
catch { throw new AccelerateError('permission_denied'); }
|
|
82
73
|
let provenance;
|
|
83
74
|
if (Object.hasOwn(document.browser, 'provenance')) {
|
|
84
|
-
check(
|
|
75
|
+
check(RUNTIME.test(extensionRuntimeId ?? ''), 'configuration_invalid');
|
|
76
|
+
check(!cleanup || typeof document.fence_id === 'string' && document.fence_id.length > 0, 'permission_denied');
|
|
85
77
|
try { provenance = browserUseRunProvenance(document.browser.provenance); }
|
|
86
78
|
catch { throw new AccelerateError('permission_denied'); }
|
|
87
79
|
}
|
|
@@ -139,23 +131,23 @@ export function createBrowserUseHost(configuration = {}) {
|
|
|
139
131
|
metadata.accelerate_extension_sha256 === release.artifact.sha256 && metadata.accelerate_extension_version === release.extension_version) &&
|
|
140
132
|
typeof value.timeoutAt === 'string' && Number.isFinite(Date.parse(value.timeoutAt)) &&
|
|
141
133
|
(requiredStatus === 'stopped' || Date.parse(value.timeoutAt) > now()) &&
|
|
142
|
-
Array.isArray(value.extensions)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const primary =
|
|
146
|
-
check(primary
|
|
147
|
-
|
|
134
|
+
Array.isArray(value.extensions));
|
|
135
|
+
const primaries = value.extensions.filter(item => item?.id === extensionId);
|
|
136
|
+
check(primaries.length === 1);
|
|
137
|
+
const primary = primaries[0];
|
|
138
|
+
check(primary.version === release.extension_version && RUNTIME.test(primary.runtimeId ?? '') &&
|
|
139
|
+
!value.extensions.some(item => item !== primary && item?.runtimeId === primary.runtimeId));
|
|
148
140
|
check(extensionRuntimeId === undefined || primary.runtimeId === extensionRuntimeId);
|
|
149
141
|
// Deliberately project away provider CDP/viewer URLs and unknown response fields.
|
|
150
142
|
const read = freeze({ expires_at: value.timeoutAt, runtime_id: primary.runtimeId });
|
|
151
143
|
if (!options.withConnection) return read;
|
|
152
144
|
check(typeof value.cdpUrl === 'string' && value.cdpUrl.length <= 2048 && typeof value.startedAt === 'string');
|
|
153
145
|
return freeze({ ...read, connection: freeze({ id: value.id, status: value.status, cdpUrl: value.cdpUrl, startedAt: value.startedAt,
|
|
154
|
-
timeoutAt: value.timeoutAt, recordingAvailable: false,
|
|
146
|
+
timeoutAt: value.timeoutAt, recordingAvailable: false, accelerate_extension_id: extensionId,
|
|
155
147
|
metadata: binding.provenance ? {} : Object.fromEntries(['accelerate_merchant_id', 'accelerate_owner_user_id',
|
|
156
148
|
'accelerate_workspace_id', 'accelerate_custody_mode', 'accelerate_agent_extension_id',
|
|
157
149
|
'accelerate_extension_sha256', 'accelerate_extension_version'].map(key => [key, metadata[key]])),
|
|
158
|
-
extensions:
|
|
150
|
+
extensions: [{ id: extensionId, runtimeId: primary.runtimeId, version: primary.version }],
|
|
159
151
|
...runEvidence }) });
|
|
160
152
|
} catch {
|
|
161
153
|
throw new AccelerateError(options.signal?.aborted ? 'request_cancelled' : 'integration_unavailable');
|
package/index.d.ts
CHANGED
|
@@ -81,6 +81,12 @@ export type CheckoutReconciliationRequest = {
|
|
|
81
81
|
currency?: 'USD';
|
|
82
82
|
source: string;
|
|
83
83
|
};
|
|
84
|
+
/** Derive from your server's authenticated owner, never model input. */
|
|
85
|
+
export interface CheckoutErasureRequest {
|
|
86
|
+
customer_id: string;
|
|
87
|
+
workspace_id: string;
|
|
88
|
+
conversation_id?: string;
|
|
89
|
+
}
|
|
84
90
|
/** Server-owned existing browser, resolved from the authenticated application's
|
|
85
91
|
* durable browser record. Never accept this binding from model arguments.
|
|
86
92
|
* The customer backend retains provider access; this is not private-from-creation custody. */
|
|
@@ -166,9 +172,13 @@ export interface CreateCheckout {
|
|
|
166
172
|
* Send it on every create. It is held in memory for this checkout and never stored. */
|
|
167
173
|
browser_resource?: ClientBrowserResource;
|
|
168
174
|
}
|
|
169
|
-
/**
|
|
175
|
+
/** Private projection of Browser Use `GET /api/v4/browsers/{id}`, with the
|
|
176
|
+
* Accelerate extension selected by the authenticated backend. */
|
|
170
177
|
export interface ClientBrowserResource {
|
|
171
178
|
id: string;
|
|
179
|
+
/** Accelerate extension selected from the backend's durable installation configuration.
|
|
180
|
+
* Other extensions in the customer-owned browser are outside this projection. */
|
|
181
|
+
accelerate_extension_id?: string;
|
|
172
182
|
status: 'active';
|
|
173
183
|
cdpUrl: string;
|
|
174
184
|
startedAt: string;
|
|
@@ -261,6 +271,11 @@ export class AccelerateClient {
|
|
|
261
271
|
/** Backend only: observe the customer's click once. Dispatch claims are not sent; never retry. */
|
|
262
272
|
completeFinalClick(id: CheckoutId, input: { revision: number; arm_id: string }, options?: RequestOptions): Promise<Checkout>;
|
|
263
273
|
cancel(id: CheckoutId, options?: RequestOptions): Promise<Checkout>;
|
|
274
|
+
/** Server only, for a deleted customer: erase a closed checkout's encrypted record, idempotency key and review binding.
|
|
275
|
+
* The binding must match creation; chat checkouts also need conversation_id. An open checkout is refused with
|
|
276
|
+
* checkout_active unless it has expired, and an unreconciled purchase submit with reconciliation_required.
|
|
277
|
+
* A checkout that is already gone reports erased. Hash-only browser run claims are kept. */
|
|
278
|
+
erase(id: CheckoutId, input: CheckoutErasureRequest, options?: RequestOptions): Promise<{ erased: true }>;
|
|
264
279
|
/** Records one merchant result after submit. Repeating the same input returns the same result; different input is refused. */
|
|
265
280
|
reconcile(id: CheckoutId, input: CheckoutReconciliationRequest, options?: RequestOptions): Promise<ReconciledCheckout>;
|
|
266
281
|
};
|
package/index.js
CHANGED
|
@@ -22,7 +22,8 @@ const ERROR_CODES = new Set(['invalid_input', 'unauthorized', 'permission_denied
|
|
|
22
22
|
'checkout_busy', 'store_unavailable', 'store_integrity_error', 'selection_rejected', 'upstream_invalid',
|
|
23
23
|
'upstream_request_invalid', 'upstream_response_invalid', 'configuration_error', 'configuration_invalid',
|
|
24
24
|
'route_not_found', 'method_not_allowed', 'json_required', 'invalid_json', 'request_too_large', 'checkout_event_unconfirmed',
|
|
25
|
-
'reconciliation_unavailable', 'reconciliation_mismatch', 'reconciliation_conflict', 'customer_click_required', 'final_click_in_progress'
|
|
25
|
+
'reconciliation_unavailable', 'reconciliation_mismatch', 'reconciliation_conflict', 'customer_click_required', 'final_click_in_progress',
|
|
26
|
+
'checkout_active', 'reconciliation_required']);
|
|
26
27
|
const MESSAGES = {
|
|
27
28
|
invalid_input: 'Invalid Accelerate client request.',
|
|
28
29
|
invalid_response: 'Accelerate returned an unrecognized private response.',
|
|
@@ -76,6 +77,10 @@ for (const [codes, message, nextAction] of [
|
|
|
76
77
|
'The order does not match the approved quote. Nothing was recorded. Check the merchant order.', 'reconcile_order'],
|
|
77
78
|
[['reconciliation_conflict'],
|
|
78
79
|
'A different result is already recorded for this checkout. It cannot be replaced.', 'check_status'],
|
|
80
|
+
[['checkout_active'],
|
|
81
|
+
'This checkout is still open and was not erased. Cancel it, then erase it.', 'check_status'],
|
|
82
|
+
[['reconciliation_required'],
|
|
83
|
+
'This purchase has an unreconciled submit outcome and was kept. Reconcile the merchant order before erasing it.', 'reconcile_order'],
|
|
79
84
|
]) for (const code of codes) GUIDANCE[code] = Object.freeze({ message, nextAction });
|
|
80
85
|
|
|
81
86
|
/** Safe diagnostics only: no response body, URL, credentials, cause or provider stack. */
|
|
@@ -269,6 +274,10 @@ function retirementInspectionInput(input) {
|
|
|
269
274
|
const { revision, ...scope } = input;
|
|
270
275
|
return { ...creationInspectionInput(scope), revision: integer(revision, 1, 2147483647) };
|
|
271
276
|
}
|
|
277
|
+
function erasureResponse(value) {
|
|
278
|
+
keys(value, ['erased'], ['erased'], 'invalid_response'); check(value.erased === true, 'invalid_response');
|
|
279
|
+
return Object.freeze({ erased: true });
|
|
280
|
+
}
|
|
272
281
|
function retirementInspectionResponse(value, id, input) {
|
|
273
282
|
if (value?.confirmed === false) { keys(value, ['confirmed'], undefined, 'invalid_response'); return value; }
|
|
274
283
|
keys(value, ['confirmed', 'checkout_id', 'revision', 'status', 'purpose', 'approval_policy', 'submit_allowed',
|
|
@@ -398,6 +407,12 @@ export class AccelerateClient {
|
|
|
398
407
|
return result;
|
|
399
408
|
},
|
|
400
409
|
cancel: async (id, options) => this.#request('POST', checkoutId(id), '/cancel', {}, options),
|
|
410
|
+
erase: async (id, input, options) => {
|
|
411
|
+
keys(input, ['customer_id', 'workspace_id', 'conversation_id'], ['customer_id', 'workspace_id']);
|
|
412
|
+
string(input.customer_id, 500); string(input.workspace_id, 500);
|
|
413
|
+
if (input.conversation_id !== undefined) string(input.conversation_id, 500);
|
|
414
|
+
return this.#request('POST', checkoutId(id), '/erase', { ...input }, options);
|
|
415
|
+
},
|
|
401
416
|
reconcile: async (id, input, options) => {
|
|
402
417
|
const body = reconciliationInput(input);
|
|
403
418
|
const result = await this.#request('POST', checkoutId(id), '/reconcile', body, options);
|
|
@@ -480,7 +495,7 @@ export class AccelerateClient {
|
|
|
480
495
|
check(options.signal === undefined || options.signal instanceof AbortSignal);
|
|
481
496
|
const controller = new AbortController();
|
|
482
497
|
const milliseconds = connection ? 45000 : ['/inspect-creation', '/inspect-retirement'].includes(suffix) ? 60000 : id === null ? 245000 : ({ '/fill': 235000, '/details': 125000, '/verify-quote': 125000, '/approval': 125000,
|
|
483
|
-
'/final-click/arm': 20000, '/final-click/complete': 125000, '/browser': 85000, '/cancel': 45000, '/reconcile': 45000, '': 45000 })[suffix];
|
|
498
|
+
'/final-click/arm': 20000, '/final-click/complete': 125000, '/browser': 85000, '/cancel': 45000, '/erase': 45000, '/reconcile': 45000, '': 45000 })[suffix];
|
|
484
499
|
const timer = setTimeout(() => controller.abort(), milliseconds); timer.unref?.();
|
|
485
500
|
const signal = AbortSignal.any([controller.signal, ...(options.signal ? [options.signal] : [])]);
|
|
486
501
|
const url = connection ? `${this.#origin}/v1/connection` :
|
|
@@ -500,7 +515,7 @@ export class AccelerateClient {
|
|
|
500
515
|
if (!response.ok) throw new AccelerateError(ERROR_CODES.has(value?.error?.code) ? value.error.code : 'request_failed', response.status,
|
|
501
516
|
response.headers.get('x-accelerate-support-reference'));
|
|
502
517
|
return connection ? connectionResponse(value, this.#merchantId) : suffix === '/browser' ? browserResponse(value) :
|
|
503
|
-
suffix === '/verify-quote' ? verifiedQuoteResponse(value, id, body) : suffix === '/final-click/arm' ? finalClickArmResponse(value, body) : suffix === '/inspect-creation' ? creationInspectionResponse(value, body) : suffix === '/inspect-retirement' ? retirementInspectionResponse(value, id, body) : statusResponse(value, id, {
|
|
518
|
+
suffix === '/verify-quote' ? verifiedQuoteResponse(value, id, body) : suffix === '/final-click/arm' ? finalClickArmResponse(value, body) : suffix === '/inspect-creation' ? creationInspectionResponse(value, body) : suffix === '/inspect-retirement' ? retirementInspectionResponse(value, id, body) : suffix === '/erase' ? erasureResponse(value) : statusResponse(value, id, {
|
|
504
519
|
create: id === null, origin: this.#origin, loopback: this.#loopback });
|
|
505
520
|
} catch (error) {
|
|
506
521
|
Promise.resolve(response?.body?.cancel()).catch(() => {});
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Existing-browser payment starter
|
|
2
2
|
|
|
3
|
-
SDK 0.
|
|
3
|
+
SDK 0.14.0, explicit `managed_review_v2`, `customer_backend_trusted`. Newly generated existing-browser apps default to `purpose:'purchase'` with the submit tool enabled. The matching service must support this profile; publishing the SDK does not deploy the service or qualify a merchant layout. Your platform creates its browser and installs the approved extension. This starter attaches that same browser at payment; it never creates a replacement. The older `accelerate-agent init <dir>` starter still selects Accelerate-managed Kernel custody and its fill-only default.
|
|
4
4
|
|
|
5
5
|
## Run without credentials
|
|
6
6
|
|
|
7
|
-
Once Accelerate supplies the matching verified 0.
|
|
7
|
+
Once Accelerate supplies the matching verified 0.14.0 archive, install it, then:
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npx --no-install accelerate-agent init ./partner-demo --browser existing
|
|
11
11
|
cd partner-demo
|
|
12
|
-
npm install /secure/downloads/weaccelerateinc-agent-sdk-0.
|
|
12
|
+
npm install /secure/downloads/weaccelerateinc-agent-sdk-0.14.0.tgz
|
|
13
13
|
npm test
|
|
14
14
|
npm run smoke
|
|
15
15
|
```
|
|
@@ -225,7 +225,7 @@ export function createSyntheticDependencies({ purpose = 'sandbox_fill_only', pro
|
|
|
225
225
|
artifact: { format: 'zip', sha256: 'a'.repeat(64), bytes: 1234 },
|
|
226
226
|
bridge: { protocol: 'accelerate_extension_bridge_v1', sha256: 'b'.repeat(64) },
|
|
227
227
|
capabilities: { manual_card_fill: true, document_bound_single_use: true, autosave_disabled: true, automatic_submit: false, maximum_retention_ms: 480000 },
|
|
228
|
-
compatibility: { sdk_versions: ['0.10.1', '0.10.2', '0.10.3', '0.10.4', '0.11.0', '0.12.0'], executor_contract: 'accelerate_manual_checkout_v1' },
|
|
228
|
+
compatibility: { sdk_versions: ['0.10.1', '0.10.2', '0.10.3', '0.10.4', '0.11.0', '0.12.0', '0.13.0', '0.14.0'], executor_contract: 'accelerate_manual_checkout_v1' },
|
|
229
229
|
qualifications: [{ provider: 'connector', scope: 'synthetic_only', evidence: 'docs/evidence/synthetic-starter.json' }],
|
|
230
230
|
}; // Fake metadata for this in-process fixture only; never load it in live mode.
|
|
231
231
|
const browser = { owner: context, browser: { provider: 'connector', connector_id: 'synthetic_cdp', browser_id: 'existing:browser:1', custody_mode: 'customer_backend_trusted' },
|
package/private-chat.d.ts
CHANGED
|
@@ -22,7 +22,11 @@ export interface PrivateChatState {
|
|
|
22
22
|
handled: boolean;
|
|
23
23
|
/** Provider message ID was previously processed. No external operation was repeated. */
|
|
24
24
|
duplicate: boolean;
|
|
25
|
-
cards: Array<{ choice: number; last4: string | null; brand: string | null
|
|
25
|
+
cards: Array<{ choice: number; last4: string | null; brand: string | null;
|
|
26
|
+
/** Customer number entry is known to be required. The customer adds it in their Accelerate wallet, then replies refresh.
|
|
27
|
+
* A false or omitted flag does not establish readiness. Saved-card verification may require CVV alone or full card details.
|
|
28
|
+
* Present only when true; older services never send it. */
|
|
29
|
+
number_required?: boolean }>;
|
|
26
30
|
addresses: Array<{ choice: number; label: string | null; city?: string | null; state?: string | null; postal_code_mask?: string | null }>;
|
|
27
31
|
identity_field?: 'first_name' | 'last_name' | 'email';
|
|
28
32
|
/** Fixed feedback for an incomplete wallet selection; never contains the customer's reply. */
|
package/private-chat.js
CHANGED
|
@@ -58,8 +58,9 @@ function state(value, expectedId) {
|
|
|
58
58
|
if (checkout.card !== undefined) card(checkout.card); if (checkout.address !== undefined) address(checkout.address); if (checkout.quote !== undefined) quote(checkout.quote);
|
|
59
59
|
check(stages.has(value.stage) && typeof value.handled === 'boolean' && typeof value.duplicate === 'boolean' &&
|
|
60
60
|
Array.isArray(value.cards) && value.cards.length <= 100 && Array.isArray(value.addresses) && value.addresses.length <= 100, 'invalid_response');
|
|
61
|
-
for (const [index, choice] of value.cards.entries()) { keys(choice, ['choice', 'last4', 'brand'],
|
|
62
|
-
check(choice.choice === index + 1
|
|
61
|
+
for (const [index, choice] of value.cards.entries()) { keys(choice, ['choice', 'last4', 'brand', 'number_required'], ['choice', 'last4', 'brand'], 'invalid_response');
|
|
62
|
+
check(choice.choice === index + 1 && (choice.number_required === undefined || typeof choice.number_required === 'boolean'), 'invalid_response');
|
|
63
|
+
card({ last4: choice.last4, brand: choice.brand }); }
|
|
63
64
|
for (const [index, choice] of value.addresses.entries()) { keys(choice, ['choice', 'label', 'city', 'state', 'postal_code_mask'], ['choice', 'label'], 'invalid_response');
|
|
64
65
|
check(choice.choice === index + 1, 'invalid_response'); const { choice: _, ...mask } = choice; address(mask); }
|
|
65
66
|
check(value.stage === 'selection_required' || value.cards.length === 0 && value.addresses.length === 0, 'invalid_response');
|
|
@@ -138,7 +139,7 @@ export function renderPrivateChatState(value, options) {
|
|
|
138
139
|
response.selection_error
|
|
139
140
|
? addressRequired ? 'Choose which saved address to use with your card. Include both choice numbers.' : 'That card or address choice is unavailable. Choose from the previous list.'
|
|
140
141
|
: multiple ? 'Choose your Accelerate wallet details:' : 'Choose your Accelerate wallet card:',
|
|
141
|
-
...(!response.selection_error ? response.cards.map(choice => `Card ${choice.choice}: ${choice.brand ?? 'Card'} •••• ${choice.last4 ?? 'unavailable'}`) : []),
|
|
142
|
+
...(!response.selection_error ? response.cards.map(choice => `Card ${choice.choice}: ${choice.brand ?? 'Card'} •••• ${choice.last4 ?? 'unavailable'}${choice.number_required ? ' (add its card number in your Accelerate wallet first, then reply refresh)' : ''}`) : []),
|
|
142
143
|
...(!response.selection_error || addressRequired ? addressChoices : []), instructions,
|
|
143
144
|
'Reply cancel to stop. Do not send card numbers or expiration dates.',
|
|
144
145
|
].join('\n'); break;
|
|
@@ -279,7 +280,8 @@ export class AcceleratePrivateChatClient {
|
|
|
279
280
|
try {
|
|
280
281
|
signal.throwIfAborted();
|
|
281
282
|
response = await bounded(this.#fetch(url, { method: 'POST', redirect: 'error', cache: 'no-store', credentials: 'omit', referrerPolicy: 'no-referrer', signal,
|
|
282
|
-
headers: { Authorization: `Bearer ${this.#apiKey}`, 'X-Accelerate-Merchant-Id': this.#merchantId,
|
|
283
|
+
headers: { Authorization: `Bearer ${this.#apiKey}`, 'X-Accelerate-Merchant-Id': this.#merchantId, 'X-Accelerate-Card-Requirements': 'v1',
|
|
284
|
+
Accept: 'application/json', 'Content-Type': 'application/json' }, body }));
|
|
283
285
|
body = '';
|
|
284
286
|
if (action === 'review' && response.ok) {
|
|
285
287
|
check(!response.redirected && response.status === 200 && (!response.url || response.url === url) && /^image\/png(?:\s*;|$)/i.test(response.headers.get('content-type') ?? ''), 'invalid_response');
|
package/starter/README.md
CHANGED
|
@@ -6,12 +6,12 @@ The default runnable mode is **synthetic**. It uses the real SDK, managed MCP ad
|
|
|
6
6
|
|
|
7
7
|
## Install and run
|
|
8
8
|
|
|
9
|
-
Requires Node.js 22 or newer. Install the exact SDK 0.
|
|
9
|
+
Requires Node.js 22 or newer. Install the exact SDK 0.14.0 archive and checksum supplied by Accelerate; [release distribution](https://github.com/weaccelerateinc/accelerate/blob/main/products/agent-sdk/docs/releases.md) records verified availability. Do not assume npm publication.
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
12
|
npx --no-install accelerate-agent init ./accelerate-demo
|
|
13
13
|
cd accelerate-demo
|
|
14
|
-
npm install /absolute/path/to/
|
|
14
|
+
npm install /absolute/path/to/weaccelerateinc-agent-sdk-0.14.0.tgz
|
|
15
15
|
npm test
|
|
16
16
|
npm run smoke
|
|
17
17
|
```
|
package/starter/package.json
CHANGED