@weaccelerateinc/agent-sdk 0.0.0-stage → 0.11.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 +151 -2
- package/approved-extension-releases/0.0.0.1.json +41 -0
- package/approved-extension-releases/0.0.0.2.json +34 -0
- package/approved-extension.d.ts +24 -0
- package/approved-extension.js +90 -0
- package/browser-connector.d.ts +109 -0
- package/browser-connector.js +218 -0
- package/browser-operations.d.ts +56 -0
- package/browser-operations.js +144 -0
- package/browser-use-host.d.ts +46 -0
- package/browser-use-host.js +149 -0
- package/checkout-diagnostics.d.ts +34 -0
- package/checkout-diagnostics.js +81 -0
- package/cli.js +105 -0
- package/customer.env.example +6 -0
- package/host-adapter.d.ts +90 -0
- package/host-adapter.js +357 -0
- package/index.d.ts +253 -0
- package/index.js +504 -0
- package/linq-messaging.d.ts +45 -0
- package/linq-messaging.js +123 -0
- package/managed-mcp.d.ts +156 -0
- package/managed-mcp.js +427 -0
- package/package.json +114 -4
- package/partner-starter/.env.example +13 -0
- package/partner-starter/README.md +61 -0
- package/partner-starter/gitignore.template +5 -0
- package/partner-starter/package.json +21 -0
- package/partner-starter/runtime.mjs +33 -0
- package/partner-starter/server.mjs +13 -0
- package/partner-starter/smoke.mjs +61 -0
- package/partner-starter/synthetic.mjs +256 -0
- package/partner-starter/tests/starter.test.mjs +119 -0
- package/partner-starter/trusted-context.example.mjs +23 -0
- package/partner.d.ts +27 -0
- package/partner.js +53 -0
- package/postgres-host.d.ts +14 -0
- package/postgres-host.js +102 -0
- package/private-chat.d.ts +104 -0
- package/private-chat.js +316 -0
- package/private-ingress.d.ts +46 -0
- package/private-ingress.js +132 -0
- package/starter/.env.example +19 -0
- package/starter/README.md +82 -0
- package/starter/gitignore.template +5 -0
- package/starter/package.json +21 -0
- package/starter/runtime.mjs +66 -0
- package/starter/server.mjs +13 -0
- package/starter/smoke.mjs +55 -0
- package/starter/synthetic.mjs +163 -0
- package/starter/tests/starter.test.mjs +224 -0
- package/starter/trusted-context.example.mjs +49 -0
package/partner.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AccelerateClient } from './index.js';
|
|
2
|
+
import type { AcceleratePrivateChatClient } from './private-chat.js';
|
|
3
|
+
import type { BrowserConnector } from './browser-connector.js';
|
|
4
|
+
import type { DurableCheckoutHost, HostPersistence } from './host-adapter.js';
|
|
5
|
+
import type { ManagedCheckoutToolsOptions, ManagedMcpServer } from './managed-mcp.js';
|
|
6
|
+
import type { PrivateCheckoutIngress, PrivateMessagingAdapter, AuthenticatedPrivateMessage } from './private-ingress.js';
|
|
7
|
+
export interface PartnerCheckoutOptions<Extra = unknown, Request = unknown> {
|
|
8
|
+
client: AccelerateClient;
|
|
9
|
+
privateChat: AcceleratePrivateChatClient;
|
|
10
|
+
persistence: HostPersistence;
|
|
11
|
+
resolveContext: ManagedCheckoutToolsOptions<Extra>['resolveContext'];
|
|
12
|
+
browserConnector: BrowserConnector;
|
|
13
|
+
authenticate(request: Request, body: Uint8Array): Promise<AuthenticatedPrivateMessage | { kind: 'ignore' }>;
|
|
14
|
+
messaging: PrivateMessagingAdapter;
|
|
15
|
+
admitOrdinaryMessage(event: { binding: import('./host-adapter.js').HostOwner; message_id: string; text: string }): Promise<void>;
|
|
16
|
+
dispatchSafeProgress(progress: import('./private-chat.js').PrivateChatProgress & { binding: import('./host-adapter.js').HostOwner; checkout_id: string }): Promise<void>;
|
|
17
|
+
/** Explicitly select v2 for backend fill immediately after private CVV; legacy callers retain v1. */
|
|
18
|
+
profile?: 'managed_review_v1' | 'managed_review_v2';
|
|
19
|
+
purpose?: 'sandbox_fill_only' | 'purchase';
|
|
20
|
+
enableSubmit?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/** Registers only canonical safe tools; private ingress must run before AI/history. */
|
|
23
|
+
export function registerPartnerCheckoutTools<Extra = unknown, Request = unknown>(server: ManagedMcpServer<Extra>, options: PartnerCheckoutOptions<Extra, Request>): Readonly<{
|
|
24
|
+
tools: readonly unknown[];
|
|
25
|
+
host: DurableCheckoutHost<Extra>;
|
|
26
|
+
privateIngress: PrivateCheckoutIngress<Request>;
|
|
27
|
+
}>;
|
package/partner.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { registerManagedCheckoutTools } from './managed-mcp.js';
|
|
2
|
+
import { createDurableCheckoutHost } from './host-adapter.js';
|
|
3
|
+
import { createPrivateCheckoutIngress } from './private-ingress.js';
|
|
4
|
+
|
|
5
|
+
/** Compose the supported existing-browser profile. All callbacks are trusted
|
|
6
|
+
* backend dependencies; none are model inputs or automatically authenticated. */
|
|
7
|
+
export function registerPartnerCheckoutTools(server, options = {}) {
|
|
8
|
+
const { client, privateChat, persistence, resolveContext, browserConnector, authenticate,
|
|
9
|
+
messaging, admitOrdinaryMessage, dispatchSafeProgress,
|
|
10
|
+
purpose = 'sandbox_fill_only', enableSubmit = false, profile = 'managed_review_v1' } = options;
|
|
11
|
+
if (!['managed_review_v1', 'managed_review_v2'].includes(profile)) throw Error('Unsupported partner checkout profile.');
|
|
12
|
+
if (browserConnector?.contract !== 'accelerate_existing_browser_v1' || !privateChat?.chat) {
|
|
13
|
+
throw Error('An existing-browser connector and private chat client are required.');
|
|
14
|
+
}
|
|
15
|
+
// Accelerate never sends the final click. A purchase needs the customer's own browser host to do it once.
|
|
16
|
+
if (purpose === 'purchase' && (typeof browserConnector.performFinalClick !== 'function' || typeof browserConnector.prepareFinalClick !== 'function')) {
|
|
17
|
+
throw Error('Purchase requires a connector whose host implements performFinalClick: the customer\u2019s own browser performs the final click.');
|
|
18
|
+
}
|
|
19
|
+
const host = createDurableCheckoutHost({ persistence, resolveContext });
|
|
20
|
+
// Keep the filled browser until explicit cancel or separately authorized
|
|
21
|
+
// submit. Review delivery can be recovered without repeating the fill.
|
|
22
|
+
const ingress = createPrivateCheckoutIngress({ host, privateChat, messaging, authenticate,
|
|
23
|
+
admitOrdinaryMessage, dispatchSafeProgress, browserConnector });
|
|
24
|
+
const tools = registerManagedCheckoutTools(server, { client, resolveContext: host.resolveContext,
|
|
25
|
+
withCheckoutCreation: host.withCheckoutCreation,
|
|
26
|
+
withOwnedCheckout: async (context, id, work, operation) => {
|
|
27
|
+
const result = await host.withOwnedCheckout(context, id, work, operation);
|
|
28
|
+
if (['accelerate_checkout_status', 'accelerate_checkout_cancel'].includes(operation?.operation) && result.checkout?.diagnostics?.cleanup_status === 'confirmed') {
|
|
29
|
+
// MCP already asked the connector for independent cleanup proof.
|
|
30
|
+
await host.confirmBrowserCleanup(context, id);
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
},
|
|
34
|
+
dispatchCheckoutEvent: async (context, event) => {
|
|
35
|
+
await host.dispatchCheckoutEvent(context, event);
|
|
36
|
+
await ingress.drain(context);
|
|
37
|
+
if (event.kind !== 'review_ready') return;
|
|
38
|
+
const state = await privateChat.chat.get(event.checkout.id, {
|
|
39
|
+
customer_id: context.customer_id, workspace_id: context.workspace_id, conversation_id: context.conversation_id,
|
|
40
|
+
});
|
|
41
|
+
if (state.checkout.id !== event.checkout.id || state.checkout.revision !== event.checkout.revision ||
|
|
42
|
+
state.checkout.purpose !== purpose || state.checkout.status !== 'ready_for_submit' ||
|
|
43
|
+
state.checkout.approval_policy !== 'after_fill' || !state.checkout.quote || !event.checkout.quote ||
|
|
44
|
+
!['checkout_origin', 'amount_cents', 'currency'].every(key => state.checkout.quote[key] === event.checkout.quote[key]) ||
|
|
45
|
+
state.review?.delivered !== true || state.review.approval_window_ms !== 300000 ||
|
|
46
|
+
!(purpose === 'sandbox_fill_only' ? state.stage === 'review_delivered' : ['approval_required', 'approved_for_submit'].includes(state.stage))) {
|
|
47
|
+
throw Error('Private review delivery is unconfirmed.');
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
browserConnector, browserMode: 'customer_backend_trusted', profile, purpose, enableSubmit,
|
|
51
|
+
});
|
|
52
|
+
return Object.freeze({ tools, host, privateIngress: ingress });
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HostPersistence } from './host-adapter.js';
|
|
2
|
+
export const checkoutHostMigrationSql: string;
|
|
3
|
+
export interface CheckoutHostPostgresClient {
|
|
4
|
+
query(sql: string, values?: unknown[]): Promise<{ rows: Record<string, unknown>[]; rowCount?: number | null }>;
|
|
5
|
+
release(destroy?: boolean): void;
|
|
6
|
+
on?(event: 'error', listener: () => void): unknown;
|
|
7
|
+
removeListener?(event: 'error', listener: () => void): unknown;
|
|
8
|
+
}
|
|
9
|
+
export function createPostgresCheckoutPersistence(options: {
|
|
10
|
+
pool: { connect(): Promise<CheckoutHostPostgresClient> };
|
|
11
|
+
encryptionKey: Buffer | string;
|
|
12
|
+
namespace?: string;
|
|
13
|
+
lockTimeoutMs?: number;
|
|
14
|
+
}): Readonly<HostPersistence & { initialize(): Promise<void> }>;
|
package/postgres-host.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
export const checkoutHostMigrationSql = `CREATE TABLE IF NOT EXISTS accelerate_partner_checkout_host (
|
|
4
|
+
namespace text NOT NULL, owner_key text NOT NULL, payload bytea NOT NULL,
|
|
5
|
+
updated_at timestamptz NOT NULL DEFAULT clock_timestamp(), PRIMARY KEY(namespace,owner_key)
|
|
6
|
+
)`;
|
|
7
|
+
const unavailable = () => Error('Durable checkout host storage is unavailable.');
|
|
8
|
+
const check = value => { if (!value) throw unavailable(); };
|
|
9
|
+
const sizeLimit = 1024 * 1024;
|
|
10
|
+
/** Encrypted, independently committed records under a session advisory lock.
|
|
11
|
+
* The caller supplies its existing pg Pool. No credentials or schema changes
|
|
12
|
+
* are inferred from MCP arguments; initialize() is an explicit operator step. */
|
|
13
|
+
export function createPostgresCheckoutPersistence({ pool, encryptionKey, namespace = 'accelerate-partner-v1', lockTimeoutMs = 10000 } = {}) {
|
|
14
|
+
let key;
|
|
15
|
+
try {
|
|
16
|
+
key = Buffer.isBuffer(encryptionKey) ? Buffer.from(encryptionKey) : Buffer.from(encryptionKey ?? '', 'base64url');
|
|
17
|
+
check(key.length === 32 && (Buffer.isBuffer(encryptionKey) || key.toString('base64url') === encryptionKey) &&
|
|
18
|
+
pool && typeof pool.connect === 'function' && /^[A-Za-z0-9_.:-]{1,100}$/.test(namespace) &&
|
|
19
|
+
Number.isInteger(lockTimeoutMs) && lockTimeoutMs > 0 && lockTimeoutMs <= 30000);
|
|
20
|
+
} catch { key?.fill(0); throw unavailable(); }
|
|
21
|
+
const aad = owner => Buffer.from(JSON.stringify(['accelerate-partner-host-v1', namespace, owner]));
|
|
22
|
+
const seal = (record, owner) => {
|
|
23
|
+
let plain;
|
|
24
|
+
try {
|
|
25
|
+
plain = Buffer.from(JSON.stringify(record)); check(plain.length > 0 && plain.length <= sizeLimit);
|
|
26
|
+
const iv = randomBytes(12), cipher = createCipheriv('aes-256-gcm', key, iv); cipher.setAAD(aad(owner));
|
|
27
|
+
const encrypted = Buffer.concat([cipher.update(plain), cipher.final()]);
|
|
28
|
+
return Buffer.concat([Buffer.from([1]), iv, cipher.getAuthTag(), encrypted]);
|
|
29
|
+
} finally { plain?.fill(0); }
|
|
30
|
+
};
|
|
31
|
+
const open = (payload, owner) => {
|
|
32
|
+
let plain;
|
|
33
|
+
try {
|
|
34
|
+
check(Buffer.isBuffer(payload) && payload.length > 29 && payload.length <= sizeLimit + 29 && payload[0] === 1);
|
|
35
|
+
const cipher = createDecipheriv('aes-256-gcm', key, payload.subarray(1, 13));
|
|
36
|
+
cipher.setAAD(aad(owner)); cipher.setAuthTag(payload.subarray(13, 29));
|
|
37
|
+
plain = Buffer.concat([cipher.update(payload.subarray(29)), cipher.final()]);
|
|
38
|
+
return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(plain));
|
|
39
|
+
} finally { plain?.fill(0); }
|
|
40
|
+
};
|
|
41
|
+
return Object.freeze({
|
|
42
|
+
async initialize() {
|
|
43
|
+
let client, failed = false;
|
|
44
|
+
try { client = await pool.connect(); await client.query(checkoutHostMigrationSql); }
|
|
45
|
+
catch { failed = true; throw unavailable(); }
|
|
46
|
+
finally { client?.release(failed); }
|
|
47
|
+
},
|
|
48
|
+
async withLock(owner, work) {
|
|
49
|
+
let client, held = false, failed = false, callbackStarted = false, output, callbackError, callbackFailed = false;
|
|
50
|
+
const onError = () => { failed = true; };
|
|
51
|
+
try {
|
|
52
|
+
check(typeof owner === 'string' && /^accelerate-partner-host:[a-f0-9]{64}$/.test(owner) && typeof work === 'function');
|
|
53
|
+
client = await pool.connect(); client.on?.('error', onError);
|
|
54
|
+
const started = performance.now();
|
|
55
|
+
do {
|
|
56
|
+
check(!failed);
|
|
57
|
+
const value = await client.query('SELECT pg_try_advisory_lock(hashtextextended($1,0)) AS held', [namespace + ':' + owner]);
|
|
58
|
+
held = value.rows?.[0]?.held === true;
|
|
59
|
+
if (held) break;
|
|
60
|
+
check(performance.now() - started < lockTimeoutMs);
|
|
61
|
+
await new Promise(resolve => setTimeout(resolve, 25));
|
|
62
|
+
} while (!held);
|
|
63
|
+
const guard = () => check(held && !failed);
|
|
64
|
+
const access = Object.freeze({
|
|
65
|
+
async load() {
|
|
66
|
+
try {
|
|
67
|
+
guard(); const result = await client.query('SELECT payload FROM accelerate_partner_checkout_host WHERE namespace=$1 AND owner_key=$2', [namespace, owner]); guard();
|
|
68
|
+
check(Array.isArray(result.rows) && result.rows.length <= 1);
|
|
69
|
+
return result.rows.length ? open(result.rows[0].payload, owner) : undefined;
|
|
70
|
+
} catch { failed = true; throw unavailable(); }
|
|
71
|
+
},
|
|
72
|
+
async commit(record) {
|
|
73
|
+
guard(); let payload;
|
|
74
|
+
try {
|
|
75
|
+
payload = seal(record, owner);
|
|
76
|
+
// Deliberately no enclosing BEGIN: this commit must survive a
|
|
77
|
+
// later remote failure in the owner callback.
|
|
78
|
+
const result = await client.query(`INSERT INTO accelerate_partner_checkout_host(namespace,owner_key,payload)
|
|
79
|
+
VALUES($1,$2,$3) ON CONFLICT(namespace,owner_key) DO UPDATE SET payload=EXCLUDED.payload,updated_at=clock_timestamp()`, [namespace, owner, payload]);
|
|
80
|
+
guard(); check(result.rowCount === 1);
|
|
81
|
+
} catch { failed = true; throw unavailable(); } finally { payload?.fill(0); }
|
|
82
|
+
},
|
|
83
|
+
});
|
|
84
|
+
callbackStarted = true;
|
|
85
|
+
try { output = await work(access); } catch (error) { callbackError = error; callbackFailed = true; }
|
|
86
|
+
guard();
|
|
87
|
+
} catch { failed = true; throw unavailable(); }
|
|
88
|
+
finally {
|
|
89
|
+
if (client) {
|
|
90
|
+
if (held) try {
|
|
91
|
+
const result = await client.query('SELECT pg_advisory_unlock(hashtextextended($1,0)) AS released', [namespace + ':' + owner]);
|
|
92
|
+
if (result.rows?.[0]?.released !== true) failed = true;
|
|
93
|
+
} catch { failed = true; }
|
|
94
|
+
held = false; client.removeListener?.('error', onError); client.release(failed);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
check(callbackStarted && !failed);
|
|
98
|
+
if (callbackFailed) throw callbackError;
|
|
99
|
+
return output;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AccelerateClientOptions, AccelerateEnvironment, Checkout, CheckoutId, RequestOptions } from './index.js';
|
|
2
|
+
|
|
3
|
+
/** All values must come from authenticated server/webhook context, never model arguments. */
|
|
4
|
+
export interface PrivateChatBinding {
|
|
5
|
+
customer_id: string;
|
|
6
|
+
workspace_id: string;
|
|
7
|
+
conversation_id: string;
|
|
8
|
+
}
|
|
9
|
+
export interface PrivateChatReply extends PrivateChatBinding {
|
|
10
|
+
/** Provider-authenticated message ID. Reuse on delivery retries; never derive from message text. */
|
|
11
|
+
message_id: string;
|
|
12
|
+
/** Transient raw reply, including OTP/CVV. This field is cleared after the operation, including errors. */
|
|
13
|
+
text: string;
|
|
14
|
+
/** Authenticated provider timestamp; required for after_fill purchase approval. */
|
|
15
|
+
sent_at?: string;
|
|
16
|
+
reply_to_message_id?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface PrivateChatState {
|
|
19
|
+
checkout: Checkout;
|
|
20
|
+
stage: 'not_started' | 'identity_required' | 'otp_required' | 'selection_required' | 'preparing_checkout' | 'approval_required' | 'cvv_required' | 'verified' | 'review_delivery_required' | 'review_delivered' | 'approved_for_submit' | 'closed';
|
|
21
|
+
/** true means consume the incoming message before AI/history/analytics, even when malformed. */
|
|
22
|
+
handled: boolean;
|
|
23
|
+
/** Provider message ID was previously processed. No external operation was repeated. */
|
|
24
|
+
duplicate: boolean;
|
|
25
|
+
cards: Array<{ choice: number; last4: string | null; brand: string | null }>;
|
|
26
|
+
addresses: Array<{ choice: number; label: string | null; city?: string | null; state?: string | null; postal_code_mask?: string | null }>;
|
|
27
|
+
identity_field?: 'first_name' | 'last_name' | 'email';
|
|
28
|
+
/** Fixed feedback for an incomplete wallet selection; never contains the customer's reply. */
|
|
29
|
+
selection_error?: 'invalid_choice' | 'address_required';
|
|
30
|
+
/** Frozen quote. Legacy before_fill includes a typed code; after_fill uses a delivered private review and simple decision. */
|
|
31
|
+
approval?: { revision: number; checkout_origin: string; amount_cents: number; currency: 'USD'; approval_code?: string };
|
|
32
|
+
review?: { id: string; expires_at: string; delivered: boolean;
|
|
33
|
+
/** Qualified post-fill policy: a full five minutes starts at the provider-confirmed prompt timestamp. */
|
|
34
|
+
approval_window_ms?: 300000;
|
|
35
|
+
/** Image and exact-total prompt must be confirmed sent before this deadline. */
|
|
36
|
+
delivery_expires_at?: string };
|
|
37
|
+
}
|
|
38
|
+
export interface PrivateChatPresentationOptions {
|
|
39
|
+
/** Provider-authenticated stable ID; delivery retries must reuse it. Never pass reply text. */
|
|
40
|
+
messageId: string;
|
|
41
|
+
}
|
|
42
|
+
export interface PrivateChatPrompt {
|
|
43
|
+
/** Fixed local wording plus the validated masked wallet/quote metadata. */
|
|
44
|
+
text: string;
|
|
45
|
+
/** Deterministic provider delivery key. Original identifiers are hashed, not exposed. */
|
|
46
|
+
idempotency_key: string;
|
|
47
|
+
}
|
|
48
|
+
export interface PrivateChatProgress extends PrivateChatPrompt {
|
|
49
|
+
stage: 'preparing_checkout' | 'verified' | 'approved_for_submit' | 'closed';
|
|
50
|
+
}
|
|
51
|
+
/** Revalidates safe state. Returns undefined for ordinary unhandled messages. Does not authenticate webhooks. */
|
|
52
|
+
export function renderPrivateChatState(state: PrivateChatState, options: PrivateChatPresentationOptions): PrivateChatPrompt | undefined;
|
|
53
|
+
/** Fixed server-authored event; caller retains durable stage-transition/delivery dedupe and ownership checks. */
|
|
54
|
+
export function privateChatProgress(state: PrivateChatState, options: PrivateChatPresentationOptions): PrivateChatProgress | undefined;
|
|
55
|
+
export interface PrivateReviewImage {
|
|
56
|
+
bytes: Buffer;
|
|
57
|
+
review_id: string;
|
|
58
|
+
expires_at: string;
|
|
59
|
+
amount_cents: number;
|
|
60
|
+
currency: 'USD';
|
|
61
|
+
approval_window_ms?: 300000;
|
|
62
|
+
delivery_expires_at?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface PrivateReviewSend {
|
|
65
|
+
/** Transient safe PNG. Upload while this callback runs; the SDK wipes it afterwards. */
|
|
66
|
+
bytes: Buffer;
|
|
67
|
+
contentType: 'image/png';
|
|
68
|
+
/** Send this exact final-total question with the image in the same private message. */
|
|
69
|
+
text: string;
|
|
70
|
+
idempotency_key: string;
|
|
71
|
+
delivery_expires_at: string;
|
|
72
|
+
signal: AbortSignal;
|
|
73
|
+
}
|
|
74
|
+
/** Fetch, verify, render, send and acknowledge a private review. The host must
|
|
75
|
+
* authenticate the customer destination and obtain the receipt from its actual
|
|
76
|
+
* provider; neither destination nor receipt may come from model arguments.
|
|
77
|
+
* Requires the managed_review_v1 five-minute proof on state, image and delivery
|
|
78
|
+
* acknowledgement. Rejects missing/short legacy windows without falling back.
|
|
79
|
+
* The acknowledged deadline must equal the provider's sent_at plus 300000 ms.
|
|
80
|
+
* Keeps bytes transient and wipes them on success, timeout and errors. */
|
|
81
|
+
export function deliverPrivateCheckoutReview(options: {
|
|
82
|
+
client: AcceleratePrivateChatClient;
|
|
83
|
+
state: PrivateChatState;
|
|
84
|
+
binding: PrivateChatBinding;
|
|
85
|
+
messageId: string;
|
|
86
|
+
send(message: PrivateReviewSend): Promise<{ message_id: string; sent_at: string }>;
|
|
87
|
+
signal?: AbortSignal;
|
|
88
|
+
}): Promise<PrivateChatState>;
|
|
89
|
+
/** Use only in a private ingress handler, before message persistence, queues and model calls. */
|
|
90
|
+
export class AcceleratePrivateChatClient {
|
|
91
|
+
/** Server environment factory; same configuration/defaults as the ordinary client, private methods only. */
|
|
92
|
+
static fromEnv(env?: AccelerateEnvironment): AcceleratePrivateChatClient;
|
|
93
|
+
constructor(options: AccelerateClientOptions);
|
|
94
|
+
readonly chat: {
|
|
95
|
+
start(id: CheckoutId, input: PrivateChatBinding, options?: RequestOptions): Promise<PrivateChatState>;
|
|
96
|
+
get(id: CheckoutId, input: PrivateChatBinding, options?: RequestOptions): Promise<PrivateChatState>;
|
|
97
|
+
reply(id: CheckoutId, input: PrivateChatReply, options?: RequestOptions): Promise<PrivateChatState>;
|
|
98
|
+
cancel(id: CheckoutId, input: PrivateChatBinding, options?: RequestOptions): Promise<PrivateChatState>;
|
|
99
|
+
/** Private sender only. RAM-only safe PNG; never expose as a model tool or public URL. Clear bytes after upload. */
|
|
100
|
+
review(id: CheckoutId, input: PrivateChatBinding, options?: RequestOptions): Promise<PrivateReviewImage>;
|
|
101
|
+
/** Call only after screenshot and exact-total prompt were confirmed sent together by the provider. */
|
|
102
|
+
reviewDelivered(id: CheckoutId, input: PrivateChatBinding & { review_id: string; message_id: string; sent_at: string }, options?: RequestOptions): Promise<PrivateChatState>;
|
|
103
|
+
};
|
|
104
|
+
}
|