diff --git a/.release-please-manifest.json b/.release-please-manifest.json index d62785c5..7d69fc3f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.136.0" + ".": "0.137.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index cbde2c71..ea058ce1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [0.137.0](https://github.com/kernel/kernel-node-sdk/compare/v0.136.0...v0.137.0) (2026-10-29) + + +### Features + +* Add request-only fingerprint beta contract ([8dfe062](https://github.com/kernel/kernel-node-sdk/commit/8dfe06253ded27d585baeca4353bace83f5eb098)) +* Read Shop Pay card status one read at a time and report outcome details ([007451f](https://github.com/kernel/kernel-node-sdk/commit/007451f806e1f64e6ed8782dae7da383704da47a)) +* Remove the projects_enabled flag from the API ([d4e4c24](https://github.com/kernel/kernel-node-sdk/commit/d4e4c24aa9b4c457542917debaa2d94f850ac31a)) +* route browser REPL and WebMCP calls directly to browser VMs ([3a21439](https://github.com/kernel/kernel-node-sdk/commit/3a21439d98d030b77a820010a99f6736af91638d)) +* Route Evervault alias payment windows through per-window upstreams ([3048bdb](https://github.com/kernel/kernel-node-sdk/commit/3048bdb506ad0f556f11dc94cf8fabd8d5f04360)) +* Wire Shop Pay into the vault API ([a34a3a2](https://github.com/kernel/kernel-node-sdk/commit/a34a3a29ca2c0e3f3b8cf710ce88a168f24cbe9f)) + ## [0.136.0](https://github.com/kernel/kernel-node-sdk/compare/v0.135.0...v0.136.0) (2026-10-28) diff --git a/api.md b/api.md index e8fb7919..8aae8901 100644 --- a/api.md +++ b/api.md @@ -100,6 +100,7 @@ Methods: Types: - BrowserAllowlistState +- BrowserFingerprint - BrowserLocation - BrowserLocationRequest - BrowserLocationSource @@ -577,6 +578,10 @@ Types: - RemovePaymentMethodVaultItemOperationRequest - RemovePaymentMethodVaultItemOperationResult - RestartVerificationVaultItemOperationRequest +- ShopPayCardState +- ShopPayCardVaultItemSpec +- ShopPayWalletState +- ShopPayWalletVaultItemSpec - VaultCardAliases - VaultCardFillField - VaultCheckoutContext diff --git a/package.json b/package.json index 3e80f659..68901ab4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@onkernel/sdk", - "version": "0.136.0", + "version": "0.137.0", "description": "The official TypeScript library for the Kernel API", "author": "Kernel <>", "types": "dist/index.d.ts", diff --git a/src/client.ts b/src/client.ts index 645e4fb7..a9d1f37a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -158,6 +158,7 @@ import { BrowserCreateResponse, BrowserCurlParams, BrowserCurlResponse, + BrowserFingerprint, BrowserListParams, BrowserListResponse, BrowserListResponsesOffsetPagination, @@ -1109,9 +1110,6 @@ export class Kernel { credentials: API.Credentials = new API.Credentials(this); /** * Create and manage projects for resource isolation within an organization. - * When projects are disabled for the organization, project operations return - * `404` with code `projects_disabled`. - * */ projects: API.Projects = new API.Projects(this); organization: API.Organization = new API.Organization(this); @@ -1230,6 +1228,7 @@ export declare namespace Kernel { export { Browsers as Browsers, type BrowserAllowlistState as BrowserAllowlistState, + type BrowserFingerprint as BrowserFingerprint, type BrowserLocation as BrowserLocation, type BrowserLocationRequest as BrowserLocationRequest, type BrowserLocationSource as BrowserLocationSource, diff --git a/src/lib/browser-routing.ts b/src/lib/browser-routing.ts index c86a72bd..3357ed06 100644 --- a/src/lib/browser-routing.ts +++ b/src/lib/browser-routing.ts @@ -49,6 +49,8 @@ const DEFAULT_BROWSER_ROUTING_SUBRESOURCES = [ 'process', 'fs', 'logs/stream', + 'repl', + 'webmcp', ]; const BROWSER_ROUTE_CACHEABLE_PATH = /^\/(?:v\d+\/)?browsers(?:\/[^/]+)?\/?$/; const BROWSER_POOL_ACQUIRE_PATH = /^\/(?:v\d+\/)?browser_pools\/[^/]+\/acquire\/?$/; diff --git a/src/resources/browsers/browsers.ts b/src/resources/browsers/browsers.ts index 8a446879..0dcb82c6 100644 --- a/src/resources/browsers/browsers.ts +++ b/src/resources/browsers/browsers.ts @@ -409,6 +409,16 @@ export interface BrowserAllowlistState { mutation_id?: string; } +/** + * Overrides for browser attributes presented to websites. + */ +export interface BrowserFingerprint { + /** + * Operating system the browser reports to websites. + */ + os: 'macos'; +} + export interface BrowserLocation { /** * Effective canonical BCP 47 formatting locale selected for the browser session. @@ -1657,6 +1667,14 @@ export interface BrowserCreateParams { */ extensions?: Array; + /** + * Closed beta: contact Kernel to enable fingerprint overrides for your + * organization. Overrides browser attributes presented to websites for this + * session. Currently supports macos and requires stealth=true, headless=false, + * gpu=false, and default memory. Omit to preserve the default browser behavior. + */ + fingerprint?: BrowserFingerprint; + /** * If true, enables GPU acceleration for the browser session. Requires Start-Up or * Enterprise plan, headless=false, and region=us-east. @@ -2260,6 +2278,7 @@ Browsers.Webmcp = Webmcp; export declare namespace Browsers { export { type BrowserAllowlistState as BrowserAllowlistState, + type BrowserFingerprint as BrowserFingerprint, type BrowserLocation as BrowserLocation, type BrowserLocationRequest as BrowserLocationRequest, type BrowserLocationSource as BrowserLocationSource, diff --git a/src/resources/browsers/index.ts b/src/resources/browsers/index.ts index 6d8e8bf8..b91400f8 100644 --- a/src/resources/browsers/index.ts +++ b/src/resources/browsers/index.ts @@ -3,6 +3,7 @@ export { Browsers, type BrowserAllowlistState, + type BrowserFingerprint, type BrowserLocation, type BrowserLocationRequest, type BrowserLocationSource, diff --git a/src/resources/browsers/telemetry.ts b/src/resources/browsers/telemetry.ts index a559c23d..ea2ef661 100644 --- a/src/resources/browsers/telemetry.ts +++ b/src/resources/browsers/telemetry.ts @@ -4470,8 +4470,9 @@ export namespace BrowserProxyErrorEvent { * network_policy_denied, provider_blacklisted, provider_unreachable, * provider_rejected, origin_tls_timeout, origin_response_incomplete, * proxy_unavailable, restricted_route_unavailable, upstream_timeout, - * upstream_dns_failure, upstream_connect_failed. A header value the browser image - * does not recognize is reported as unknown, with the header value in raw_code. + * upstream_dns_failure, upstream_connect_failed, payment_window_expired. A header + * value the browser image does not recognize is reported as unknown, with the + * header value in raw_code. */ code: | 'destination_blocked' @@ -4487,6 +4488,7 @@ export namespace BrowserProxyErrorEvent { | 'upstream_timeout' | 'upstream_dns_failure' | 'upstream_connect_failed' + | 'payment_window_expired' | 'unknown'; /** diff --git a/src/resources/index.ts b/src/resources/index.ts index 4e440460..c3caae59 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -41,6 +41,7 @@ export { export { Browsers, type BrowserAllowlistState, + type BrowserFingerprint, type BrowserLocation, type BrowserLocationRequest, type BrowserLocationSource, diff --git a/src/resources/projects/limits.ts b/src/resources/projects/limits.ts index a706d9a2..077b76b3 100644 --- a/src/resources/projects/limits.ts +++ b/src/resources/projects/limits.ts @@ -7,8 +7,6 @@ import { path } from '../../internal/utils/path'; /** * Create and manage projects for resource isolation within an organization. - * When projects are disabled for the organization, project operations return - * `404` with code `projects_disabled`. */ export class Limits extends APIResource { /** diff --git a/src/resources/projects/projects.ts b/src/resources/projects/projects.ts index 2eed7f7c..8ee086c8 100644 --- a/src/resources/projects/projects.ts +++ b/src/resources/projects/projects.ts @@ -11,8 +11,6 @@ import { path } from '../../internal/utils/path'; /** * Create and manage projects for resource isolation within an organization. - * When projects are disabled for the organization, project operations return - * `404` with code `projects_disabled`. */ export class Projects extends APIResource { limits: LimitsAPI.Limits = new LimitsAPI.Limits(this._client); diff --git a/src/resources/vaults/index.ts b/src/resources/vaults/index.ts index 603815db..2015b0f1 100644 --- a/src/resources/vaults/index.ts +++ b/src/resources/vaults/index.ts @@ -65,6 +65,10 @@ export { type RemovePaymentMethodVaultItemOperationRequest, type RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest, + type ShopPayCardState, + type ShopPayCardVaultItemSpec, + type ShopPayWalletState, + type ShopPayWalletVaultItemSpec, type VaultCardAliases, type VaultCardFillField, type VaultCheckoutContext, diff --git a/src/resources/vaults/items.ts b/src/resources/vaults/items.ts index 99a9bb0c..c9d64206 100644 --- a/src/resources/vaults/items.ts +++ b/src/resources/vaults/items.ts @@ -91,13 +91,13 @@ export class Items extends APIResource { * Unresolved payment operations normally block deletion, including operations on * child cards of a wallet. Deleting a connected Kernel wallet first blocks new * payments on it, then removes its enrolled card. If that fails, the wallet is - * kept and keeps refusing payments; retry the deletion. A Link or Kernel card in - * recovery_required for issuance, or an AgentCard card in recovery_required whose - * checkout create response returned no authorization ID, may be explicitly - * abandoned by deleting that card directly; deleting its wallet or vault remains - * blocked until the card is deleted. Deleting or recreating an item is not proof - * that a payment did not occur. Deleting a managed auth credential item leaves the - * connection and its saved credential unchanged. + * kept and keeps refusing payments; retry the deletion. A Link, Kernel or Shop Pay + * card in recovery_required for issuance, or an AgentCard card in + * recovery_required whose checkout create response returned no authorization ID, + * may be explicitly abandoned by deleting that card directly; deleting its wallet + * or vault remains blocked until the card is deleted. Deleting or recreating an + * item is not proof that a payment did not occur. Deleting a managed auth + * credential item leaves the connection and its saved credential unchanged. * * @example * ```ts @@ -383,17 +383,19 @@ export interface ArmPasskeyVaultItemOperationRequest { } /** - * Authorize a Link or Kernel card using its existing purchase specification. Use - * only after explicit user approval and when the item advertises authorize; follow - * the advertised operation's description. For a Link card, pass browser_id and - * page_url together while the browser is on the final checkout page: Kernel - * inspects that checkout, chooses how the credential is delivered, and limits fill - * to that checkout's origin in any browser with this vault attached. Omitting both - * issues a virtual card that fills any page on the merchant origin. Once approval - * has been requested, browser_id and page_url are ignored and authorize only - * re-checks the request. Browser and checkout inspection errors occur before any - * provider request and can be retried once the browser is on the checkout page. - * Kernel cards do not accept browser_id or page_url. + * Authorize a Link, Kernel or Shop Pay card using its existing purchase + * specification. Use only after explicit user approval and when the item + * advertises authorize; follow the advertised operation's description. For a Link + * or Shop Pay card, pass browser_id and page_url together while the browser is on + * the final checkout page: Kernel confirms that checkout is open, sends it to the + * provider as the merchant, and limits fill to that checkout's origin in any + * browser with this vault attached. For Link it also chooses how the credential is + * delivered. Omitting both issues a virtual card that fills any page on the + * merchant origin. Once approval has been requested, browser_id and page_url are + * ignored and authorize only re-checks the request. Browser and checkout + * inspection errors occur before any provider request and can be retried once the + * browser is on the checkout page. Kernel cards do not accept browser_id or + * page_url. */ export interface AuthorizeVaultItemOperationRequest { type: 'authorize'; @@ -421,7 +423,8 @@ export interface AuthorizeVaultItemOperationRequest { export type CardVaultItemSpec = | CardVaultItemSpec.LinkCardVaultItemSpec | CardVaultItemSpec.AgentCardCardVaultItemSpec - | KernelCardVaultItemSpec; + | KernelCardVaultItemSpec + | ShopPayCardVaultItemSpec; export namespace CardVaultItemSpec { /** @@ -604,7 +607,8 @@ export namespace CardVaultItemSpec { export type CardVaultItemState = | CardVaultItemState.LinkCardState | CardVaultItemState.AgentCardCardState - | KernelCardState; + | KernelCardState + | ShopPayCardState; export namespace CardVaultItemState { /** @@ -736,11 +740,12 @@ export interface CollectVaultItemOperationRequest { } /** - * Report a real merchant transaction outcome for an issued Kernel Visa credential. - * Never infer success from filling checkout or receiving a credential. Supply the - * observed status, transaction type, actual amount, currency and timestamp. - * Unknown outcomes require manual reconciliation, not retry. Each purchase accepts - * one report. + * Report a real merchant transaction outcome for an issued Kernel Visa or Shop Pay + * credential. Shop Pay accepts PURCHASE, AUTHORIZATION and CAPTURE. Never infer + * success from filling checkout or receiving a credential. Supply the observed + * status, transaction type, actual amount, currency and timestamp. Unknown + * outcomes require manual reconciliation, not retry. Each purchase accepts one + * report. */ export interface ConfirmTransactionVaultItemOperationRequest { /** @@ -771,6 +776,26 @@ export interface ConfirmTransactionVaultItemOperationRequest { | 'FRAUD'; type: 'confirm_transaction'; + + /** + * Why the purchase did not succeed, for any other outcome, such as 3ds_challenge, + * captcha, login_required, timeout or site_error. payment_declined goes only with + * DECLINED, which takes no other code. Shop Pay reports it; other providers ignore + * it. + */ + failure_code?: string; + + /** + * The merchant's order number, for an APPROVED outcome. Shop Pay reports it; other + * providers ignore it. + */ + order_id?: string; + + /** + * The merchant's https order page, for an APPROVED outcome. Shop Pay reports it; + * other providers ignore it. + */ + order_url?: string; } export interface CredentialAccountVaultItem { @@ -2884,6 +2909,170 @@ export interface RestartVerificationVaultItemOperationRequest { type: 'restart_verification'; } +/** + * Issued Shop Pay cards retain encrypted card material for the fill operation. + */ +export interface ShopPayCardState { + provider: 'shop_pay'; + + /** + * declined covers a request the shopper declined or that was cancelled. consumed + * means the transaction outcome was reported with confirm_transaction; the card is + * no longer stored and cannot be filled again, whatever the outcome. + * recovery_required means a provider operation has an unresolved outcome and the + * card cannot be used. When status_reason says the provider refused retrieval + * before acceptance, no card was issued and a later read retries. Otherwise follow + * status_reason: recovery for issuance can be abandoned by deleting the card and + * creating a new one, and the shopper approves the new purchase separately. + * Recovery while reporting a merchant transaction cannot be deleted and must be + * reconciled with support. + */ + status: + | 'requested' + | 'pending_authorization' + | 'ready' + | 'consumed' + | 'expired' + | 'declined' + | 'recovery_required'; + + domains?: Array; + + masks?: ShopPayCardState.Masks; + + status_reason?: string; +} + +export namespace ShopPayCardState { + export interface Masks { + brand?: string; + + last4?: string; + + /** + * Last four digits of the network token presented to the merchant. + */ + token_last4?: string; + + [k: string]: string | undefined; + } +} + +/** + * Shop Pay purchase. amount is the limit the shopper approves; totals must include + * exactly one positive total no higher than it. context is shown to the shopper + * when they approve. Authorize it with the browser at final checkout: Kernel sends + * that page to Shop as the merchant and the card fills only on its origin. Without + * browser_id and page_url it authorizes for merchant_url. authorize returns an + * approval action for the shopper, who approves the purchase in Shop; share its + * URL unchanged when present. Report the merchant outcome with + * confirm_transaction, which ends the card. + */ +export interface ShopPayCardVaultItemSpec { + /** + * Approval limit in minor currency units, at most 1000000. + */ + amount: number; + + /** + * What is being bought and why, written for the shopper. + */ + context: string; + + /** + * Shop accepts USD spend requests only. + */ + currency: string; + + merchant_name: string; + + /** + * The merchant's https URL. + */ + merchant_url: string; + + provider: 'shop_pay'; + + totals: Array; + + /** + * Connected Shop Pay wallet item key. + */ + wallet: string; + + line_items?: Array; + + /** + * ISO 3166-1 alpha-2 country of the merchant. + */ + merchant_country?: string; + + /** + * Card ID from the wallet's payment_methods expansion. Omit it to use the + * shopper's preferred card. + */ + payment_method_id?: string; +} + +export namespace ShopPayCardVaultItemSpec { + export interface Total { + /** + * Amount in minor currency units; discounts are negative. + */ + amount: number; + + /** + * For example subtotal, fulfillment, tax, discount or total. + */ + type: string; + } + + export interface LineItem { + name: string; + + quantity: number; + + /** + * Unit price in minor currency units. + */ + unit_amount: number; + } +} + +export interface ShopPayWalletState { + provider: 'shop_pay'; + + status: 'pending_authorization' | 'connected' | 'declined' | 'reconnect_required' | 'degraded'; + + status_reason?: string; +} + +/** + * Shop Pay wallet connected through Kernel's Shop app. Creation returns a + * shop_pay_oauth action: the shopper signs in to Shop and approves the connection, + * and the wallet connects. The connected wallet's payment_methods expansion lists + * the shopper's saved Shop Pay cards. + */ +export interface ShopPayWalletVaultItemSpec { + authorization: ShopPayWalletVaultItemSpec.Authorization; + + provider: 'shop_pay'; +} + +export namespace ShopPayWalletVaultItemSpec { + export interface Authorization { + client: Authorization.Client; + + method: 'oauth'; + } + + export namespace Authorization { + export interface Client { + type: 'kernel_managed'; + } + } +} + export interface VaultCardAliases { cvc: string; @@ -2907,8 +3096,10 @@ export namespace VaultCardFillField { /** * Field in the decrypted card, not an alias. Number and CVC preserve leading * zeros; month uses two digits and year uses four digits. Billing fields use the - * provider's stored billing address (name, line1, line2, city, state, postal_code, - * country) without reformatting. Request only needed billing fields. An absent or + * provider's stored billing address (name, first and last name, line1, line2, + * city, state, postal_code, country) without reformatting. First and last name are + * available only when the provider returns them separately, such as Shop Pay; + * billing_name is never split. Request only needed billing fields. An absent or * empty requested billing field returns 400 field_unavailable before any browser * writes; it does not make other card fields unavailable. */ @@ -2918,6 +3109,8 @@ export namespace VaultCardFillField { | 'exp_year' | 'cvc' | 'billing_name' + | 'billing_first_name' + | 'billing_last_name' | 'billing_line1' | 'billing_line2' | 'billing_city' @@ -3236,6 +3429,7 @@ export namespace VaultItem { export type VaultItemAction = | VaultItemAction.LinkOAuthAction + | VaultItemAction.ShopPayOAuthAction | OnePasswordOAuthAction | VaultItemAction.SpendApprovalAction | VaultItemAction.PushApprovalAction @@ -3251,6 +3445,15 @@ export namespace VaultItemAction { url: string; } + export interface ShopPayOAuthAction { + name: 'shop_pay_oauth'; + + /** + * Shop sign-in page where the shopper connects their Shop account to Kernel. + */ + url: string; + } + export interface SpendApprovalAction { name: 'spend_approval'; @@ -3643,7 +3846,8 @@ export interface VaultWebmcpBinding { export type WalletVaultItemSpec = | WalletVaultItemSpec.LinkWalletVaultItemSpec | WalletVaultItemSpec.AgentCardWalletVaultItemSpec - | KernelWalletVaultItemSpec; + | KernelWalletVaultItemSpec + | ShopPayWalletVaultItemSpec; export namespace WalletVaultItemSpec { export interface LinkWalletVaultItemSpec { @@ -3734,7 +3938,8 @@ export namespace WalletVaultItemSpec { export type WalletVaultItemState = | WalletVaultItemState.LinkWalletState | WalletVaultItemState.AgentCardWalletState - | KernelWalletState; + | KernelWalletState + | ShopPayWalletState; export namespace WalletVaultItemState { export interface LinkWalletState { @@ -4067,6 +4272,26 @@ export declare namespace ItemPerformOperationParams { * Body param */ type: 'confirm_transaction'; + + /** + * Body param: Why the purchase did not succeed, for any other outcome, such as + * 3ds_challenge, captcha, login_required, timeout or site_error. payment_declined + * goes only with DECLINED, which takes no other code. Shop Pay reports it; other + * providers ignore it. + */ + failure_code?: string; + + /** + * Body param: The merchant's order number, for an APPROVED outcome. Shop Pay + * reports it; other providers ignore it. + */ + order_id?: string; + + /** + * Body param: The merchant's https order page, for an APPROVED outcome. Shop Pay + * reports it; other providers ignore it. + */ + order_url?: string; } export interface CollectVaultItemOperationRequest { @@ -4444,7 +4669,8 @@ export declare namespace ItemUpsertParams { spec: | WalletVaultItemRequest.LinkWalletVaultItemRequestSpec | WalletVaultItemRequest.AgentCardWalletVaultItemSpec - | KernelWalletVaultItemSpec; + | KernelWalletVaultItemSpec + | ShopPayWalletVaultItemSpec; /** * Body param @@ -4752,6 +4978,10 @@ export declare namespace Items { type RemovePaymentMethodVaultItemOperationRequest as RemovePaymentMethodVaultItemOperationRequest, type RemovePaymentMethodVaultItemOperationResult as RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest as RestartVerificationVaultItemOperationRequest, + type ShopPayCardState as ShopPayCardState, + type ShopPayCardVaultItemSpec as ShopPayCardVaultItemSpec, + type ShopPayWalletState as ShopPayWalletState, + type ShopPayWalletVaultItemSpec as ShopPayWalletVaultItemSpec, type VaultCardAliases as VaultCardAliases, type VaultCardFillField as VaultCardFillField, type VaultCheckoutContext as VaultCheckoutContext, diff --git a/src/resources/vaults/vaults.ts b/src/resources/vaults/vaults.ts index 7c3660be..57b796e1 100644 --- a/src/resources/vaults/vaults.ts +++ b/src/resources/vaults/vaults.ts @@ -75,6 +75,10 @@ import { RemovePaymentMethodVaultItemOperationRequest, RemovePaymentMethodVaultItemOperationResult, RestartVerificationVaultItemOperationRequest, + ShopPayCardState, + ShopPayCardVaultItemSpec, + ShopPayWalletState, + ShopPayWalletVaultItemSpec, VaultCardAliases, VaultCardFillField, VaultCheckoutContext, @@ -343,6 +347,10 @@ export declare namespace Vaults { type RemovePaymentMethodVaultItemOperationRequest as RemovePaymentMethodVaultItemOperationRequest, type RemovePaymentMethodVaultItemOperationResult as RemovePaymentMethodVaultItemOperationResult, type RestartVerificationVaultItemOperationRequest as RestartVerificationVaultItemOperationRequest, + type ShopPayCardState as ShopPayCardState, + type ShopPayCardVaultItemSpec as ShopPayCardVaultItemSpec, + type ShopPayWalletState as ShopPayWalletState, + type ShopPayWalletVaultItemSpec as ShopPayWalletVaultItemSpec, type VaultCardAliases as VaultCardAliases, type VaultCardFillField as VaultCardFillField, type VaultCheckoutContext as VaultCheckoutContext, diff --git a/src/version.ts b/src/version.ts index 23d9082b..bbd0a12b 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.136.0'; // x-release-please-version +export const VERSION = '0.137.0'; // x-release-please-version diff --git a/tests/api-resources/browsers/browsers.test.ts b/tests/api-resources/browsers/browsers.test.ts index 56dce347..efb216d1 100644 --- a/tests/api-resources/browsers/browsers.test.ts +++ b/tests/api-resources/browsers/browsers.test.ts @@ -28,6 +28,7 @@ describe('resource browsers', () => { { chrome_policy: { foo: 'bar' }, extensions: [{ id: 'id', name: 'name' }], + fingerprint: { os: 'macos' }, gpu: false, headless: false, invocation_id: 'rr33xuugxj9h0bkf1rdt2bet', diff --git a/tests/lib/browser-routing.test.ts b/tests/lib/browser-routing.test.ts index f85cfeee..b989715d 100644 --- a/tests/lib/browser-routing.test.ts +++ b/tests/lib/browser-routing.test.ts @@ -459,6 +459,8 @@ describe('browser routing', () => { 'process', 'fs', 'logs/stream', + 'repl', + 'webmcp', ]); }); }); @@ -1145,4 +1147,48 @@ describe('browser routing', () => { ]); }); }); + + test('routes repl and webmcp to the VM, but not replays', async () => { + await withBrowserRoutingEnv(undefined, async () => { + const cache = new BrowserRouteCache(); + cache.set({ + sessionId: 'sess-1', + baseURL: 'http://browser-session.test/browser/kernel', + jwt: 'token-abc', + }); + + const routed: string[] = []; + const wrappedFetch = createRoutingFetch( + async (input) => { + routed.push(normalizeURL(input)); + return new Response(null, { status: 204 }); + }, + { + apiBaseURL: 'https://api.example/', + subresources: browserRoutingSubresourcesFromEnv(), + cache, + }, + ); + + for (const path of [ + 'repl', + 'webmcp/tools', + 'webmcp/invoke', + 'webmcp/custom-tools/ct_1', + 'replays', + 'replays/rec-1', + ]) { + await wrappedFetch(`https://api.example/browsers/sess-1/${path}`); + } + + expect(routed).toEqual([ + 'http://browser-session.test/browser/kernel/repl?jwt=token-abc', + 'http://browser-session.test/browser/kernel/webmcp/tools?jwt=token-abc', + 'http://browser-session.test/browser/kernel/webmcp/invoke?jwt=token-abc', + 'http://browser-session.test/browser/kernel/webmcp/custom-tools/ct_1?jwt=token-abc', + 'https://api.example/browsers/sess-1/replays', + 'https://api.example/browsers/sess-1/replays/rec-1', + ]); + }); + }); });