@amalgm/browser 0.1.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/CHANGELOG.md +16 -0
- package/LICENSE +5 -0
- package/PURPOSE.md +117 -0
- package/README.md +120 -0
- package/SECURITY.md +49 -0
- package/dist/bin/amalgm-browser-mcp.d.ts +2 -0
- package/dist/bin/amalgm-browser-mcp.js +5 -0
- package/dist/bin/amalgm-browser-mcp.js.map +1 -0
- package/dist/bin/amalgm-browser-rest.d.ts +2 -0
- package/dist/bin/amalgm-browser-rest.js +20 -0
- package/dist/bin/amalgm-browser-rest.js.map +1 -0
- package/dist/bin/amalgm-browser.d.ts +2 -0
- package/dist/bin/amalgm-browser.js +4 -0
- package/dist/bin/amalgm-browser.js.map +1 -0
- package/dist/src/action.d.ts +5 -0
- package/dist/src/action.js +42 -0
- package/dist/src/action.js.map +1 -0
- package/dist/src/adapters/actions.d.ts +10 -0
- package/dist/src/adapters/actions.js +41 -0
- package/dist/src/adapters/actions.js.map +1 -0
- package/dist/src/adapters/cli/actions.d.ts +7 -0
- package/dist/src/adapters/cli/actions.js +63 -0
- package/dist/src/adapters/cli/actions.js.map +1 -0
- package/dist/src/adapters/cli/args.d.ts +8 -0
- package/dist/src/adapters/cli/args.js +41 -0
- package/dist/src/adapters/cli/args.js.map +1 -0
- package/dist/src/adapters/cli/help.d.ts +1 -0
- package/dist/src/adapters/cli/help.js +29 -0
- package/dist/src/adapters/cli/help.js.map +1 -0
- package/dist/src/adapters/cli/resources.d.ts +4 -0
- package/dist/src/adapters/cli/resources.js +116 -0
- package/dist/src/adapters/cli/resources.js.map +1 -0
- package/dist/src/adapters/cli/run.d.ts +7 -0
- package/dist/src/adapters/cli/run.js +108 -0
- package/dist/src/adapters/cli/run.js.map +1 -0
- package/dist/src/adapters/execute.d.ts +4 -0
- package/dist/src/adapters/execute.js +91 -0
- package/dist/src/adapters/execute.js.map +1 -0
- package/dist/src/adapters/http/auth-routes.d.ts +2 -0
- package/dist/src/adapters/http/auth-routes.js +93 -0
- package/dist/src/adapters/http/auth-routes.js.map +1 -0
- package/dist/src/adapters/http/events.d.ts +3 -0
- package/dist/src/adapters/http/events.js +20 -0
- package/dist/src/adapters/http/events.js.map +1 -0
- package/dist/src/adapters/http/internal-routes.d.ts +2 -0
- package/dist/src/adapters/http/internal-routes.js +35 -0
- package/dist/src/adapters/http/internal-routes.js.map +1 -0
- package/dist/src/adapters/http/openapi.d.ts +1 -0
- package/dist/src/adapters/http/openapi.js +78 -0
- package/dist/src/adapters/http/openapi.js.map +1 -0
- package/dist/src/adapters/http/profile-routes.d.ts +2 -0
- package/dist/src/adapters/http/profile-routes.js +42 -0
- package/dist/src/adapters/http/profile-routes.js.map +1 -0
- package/dist/src/adapters/http/recording-routes.d.ts +2 -0
- package/dist/src/adapters/http/recording-routes.js +41 -0
- package/dist/src/adapters/http/recording-routes.js.map +1 -0
- package/dist/src/adapters/http/request.d.ts +4 -0
- package/dist/src/adapters/http/request.js +44 -0
- package/dist/src/adapters/http/request.js.map +1 -0
- package/dist/src/adapters/http/server.d.ts +2 -0
- package/dist/src/adapters/http/server.js +114 -0
- package/dist/src/adapters/http/server.js.map +1 -0
- package/dist/src/adapters/http/session-routes.d.ts +2 -0
- package/dist/src/adapters/http/session-routes.js +54 -0
- package/dist/src/adapters/http/session-routes.js.map +1 -0
- package/dist/src/adapters/http/types.d.ts +29 -0
- package/dist/src/adapters/http/types.js +2 -0
- package/dist/src/adapters/http/types.js.map +1 -0
- package/dist/src/adapters/mcp/server.d.ts +3 -0
- package/dist/src/adapters/mcp/server.js +74 -0
- package/dist/src/adapters/mcp/server.js.map +1 -0
- package/dist/src/adapters/mcp/tools.d.ts +3 -0
- package/dist/src/adapters/mcp/tools.js +45 -0
- package/dist/src/adapters/mcp/tools.js.map +1 -0
- package/dist/src/adapters/mcp/types.d.ts +17 -0
- package/dist/src/adapters/mcp/types.js +2 -0
- package/dist/src/adapters/mcp/types.js.map +1 -0
- package/dist/src/adapters/toolbox/aliases.d.ts +5 -0
- package/dist/src/adapters/toolbox/aliases.js +14 -0
- package/dist/src/adapters/toolbox/aliases.js.map +1 -0
- package/dist/src/adapters/toolbox/executor.d.ts +6 -0
- package/dist/src/adapters/toolbox/executor.js +13 -0
- package/dist/src/adapters/toolbox/executor.js.map +1 -0
- package/dist/src/adapters/toolbox/manifest.d.ts +15 -0
- package/dist/src/adapters/toolbox/manifest.js +24 -0
- package/dist/src/adapters/toolbox/manifest.js.map +1 -0
- package/dist/src/artifacts.d.ts +14 -0
- package/dist/src/artifacts.js +28 -0
- package/dist/src/artifacts.js.map +1 -0
- package/dist/src/auth/filter.d.ts +3 -0
- package/dist/src/auth/filter.js +60 -0
- package/dist/src/auth/filter.js.map +1 -0
- package/dist/src/auth/login.d.ts +41 -0
- package/dist/src/auth/login.js +145 -0
- package/dist/src/auth/login.js.map +1 -0
- package/dist/src/auth/portable.d.ts +18 -0
- package/dist/src/auth/portable.js +48 -0
- package/dist/src/auth/portable.js.map +1 -0
- package/dist/src/auth/service.d.ts +29 -0
- package/dist/src/auth/service.js +104 -0
- package/dist/src/auth/service.js.map +1 -0
- package/dist/src/auth/transport.d.ts +8 -0
- package/dist/src/auth/transport.js +45 -0
- package/dist/src/auth/transport.js.map +1 -0
- package/dist/src/auth/vault.d.ts +10 -0
- package/dist/src/auth/vault.js +27 -0
- package/dist/src/auth/vault.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +3 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/cookies/coordinator.d.ts +17 -0
- package/dist/src/cookies/coordinator.js +93 -0
- package/dist/src/cookies/coordinator.js.map +1 -0
- package/dist/src/cookies/jar.d.ts +21 -0
- package/dist/src/cookies/jar.js +146 -0
- package/dist/src/cookies/jar.js.map +1 -0
- package/dist/src/cookies/policy.d.ts +6 -0
- package/dist/src/cookies/policy.js +58 -0
- package/dist/src/cookies/policy.js.map +1 -0
- package/dist/src/cookies/secret-file.d.ts +10 -0
- package/dist/src/cookies/secret-file.js +80 -0
- package/dist/src/cookies/secret-file.js.map +1 -0
- package/dist/src/cookies/types.d.ts +64 -0
- package/dist/src/cookies/types.js +2 -0
- package/dist/src/cookies/types.js.map +1 -0
- package/dist/src/cookies.d.ts +5 -0
- package/dist/src/cookies.js +5 -0
- package/dist/src/cookies.js.map +1 -0
- package/dist/src/defaults.d.ts +24 -0
- package/dist/src/defaults.js +107 -0
- package/dist/src/defaults.js.map +1 -0
- package/dist/src/drivers/cdp/capture.d.ts +5 -0
- package/dist/src/drivers/cdp/capture.js +39 -0
- package/dist/src/drivers/cdp/capture.js.map +1 -0
- package/dist/src/drivers/cdp/client.d.ts +8 -0
- package/dist/src/drivers/cdp/client.js +88 -0
- package/dist/src/drivers/cdp/client.js.map +1 -0
- package/dist/src/drivers/cdp/input.d.ts +2 -0
- package/dist/src/drivers/cdp/input.js +15 -0
- package/dist/src/drivers/cdp/input.js.map +1 -0
- package/dist/src/drivers/cdp/screencast.d.ts +2 -0
- package/dist/src/drivers/cdp/screencast.js +39 -0
- package/dist/src/drivers/cdp/screencast.js.map +1 -0
- package/dist/src/drivers/cdp/target.d.ts +4 -0
- package/dist/src/drivers/cdp/target.js +34 -0
- package/dist/src/drivers/cdp/target.js.map +1 -0
- package/dist/src/drivers/electron/advertisement.d.ts +12 -0
- package/dist/src/drivers/electron/advertisement.js +57 -0
- package/dist/src/drivers/electron/advertisement.js.map +1 -0
- package/dist/src/drivers/electron/contracts.d.ts +45 -0
- package/dist/src/drivers/electron/contracts.js +10 -0
- package/dist/src/drivers/electron/contracts.js.map +1 -0
- package/dist/src/drivers/electron/cookie-adapter.d.ts +17 -0
- package/dist/src/drivers/electron/cookie-adapter.js +69 -0
- package/dist/src/drivers/electron/cookie-adapter.js.map +1 -0
- package/dist/src/drivers/electron/driver.d.ts +19 -0
- package/dist/src/drivers/electron/driver.js +115 -0
- package/dist/src/drivers/electron/driver.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/cache.d.ts +4 -0
- package/dist/src/drivers/electron/native/adblock/cache.js +54 -0
- package/dist/src/drivers/electron/native/adblock/cache.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/cosmetics.d.ts +11 -0
- package/dist/src/drivers/electron/native/adblock/cosmetics.js +45 -0
- package/dist/src/drivers/electron/native/adblock/cosmetics.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/index.d.ts +44 -0
- package/dist/src/drivers/electron/native/adblock/index.js +153 -0
- package/dist/src/drivers/electron/native/adblock/index.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/policy.d.ts +2 -0
- package/dist/src/drivers/electron/native/adblock/policy.js +12 -0
- package/dist/src/drivers/electron/native/adblock/policy.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/preload.d.ts +1 -0
- package/dist/src/drivers/electron/native/adblock/preload.js +131 -0
- package/dist/src/drivers/electron/native/adblock/preload.js.map +1 -0
- package/dist/src/drivers/electron/native/adblock/settings.d.ts +9 -0
- package/dist/src/drivers/electron/native/adblock/settings.js +37 -0
- package/dist/src/drivers/electron/native/adblock/settings.js.map +1 -0
- package/dist/src/drivers/electron/native/config.d.ts +4 -0
- package/dist/src/drivers/electron/native/config.js +9 -0
- package/dist/src/drivers/electron/native/config.js.map +1 -0
- package/dist/src/drivers/electron/native/contracts.d.ts +174 -0
- package/dist/src/drivers/electron/native/contracts.js +20 -0
- package/dist/src/drivers/electron/native/contracts.js.map +1 -0
- package/dist/src/drivers/electron/native/policy.d.ts +7 -0
- package/dist/src/drivers/electron/native/policy.js +43 -0
- package/dist/src/drivers/electron/native/policy.js.map +1 -0
- package/dist/src/drivers/electron/native/session.d.ts +4 -0
- package/dist/src/drivers/electron/native/session.js +11 -0
- package/dist/src/drivers/electron/native/session.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/adblock-ipc.d.ts +10 -0
- package/dist/src/drivers/electron/native/shell/adblock-ipc.js +44 -0
- package/dist/src/drivers/electron/native/shell/adblock-ipc.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/context-menu.d.ts +11 -0
- package/dist/src/drivers/electron/native/shell/context-menu.js +129 -0
- package/dist/src/drivers/electron/native/shell/context-menu.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/downloads.d.ts +11 -0
- package/dist/src/drivers/electron/native/shell/downloads.js +90 -0
- package/dist/src/drivers/electron/native/shell/downloads.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/helpers.d.ts +5 -0
- package/dist/src/drivers/electron/native/shell/helpers.js +53 -0
- package/dist/src/drivers/electron/native/shell/helpers.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/permissions.d.ts +16 -0
- package/dist/src/drivers/electron/native/shell/permissions.js +107 -0
- package/dist/src/drivers/electron/native/shell/permissions.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/sites.d.ts +24 -0
- package/dist/src/drivers/electron/native/shell/sites.js +119 -0
- package/dist/src/drivers/electron/native/shell/sites.js.map +1 -0
- package/dist/src/drivers/electron/native/shell/types.d.ts +13 -0
- package/dist/src/drivers/electron/native/shell/types.js +2 -0
- package/dist/src/drivers/electron/native/shell/types.js.map +1 -0
- package/dist/src/drivers/electron/native/shell.d.ts +14 -0
- package/dist/src/drivers/electron/native/shell.js +115 -0
- package/dist/src/drivers/electron/native/shell.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/commands.d.ts +4 -0
- package/dist/src/drivers/electron/native/surface/commands.js +49 -0
- package/dist/src/drivers/electron/native/surface/commands.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/create.d.ts +4 -0
- package/dist/src/drivers/electron/native/surface/create.js +46 -0
- package/dist/src/drivers/electron/native/surface/create.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/events.d.ts +3 -0
- package/dist/src/drivers/electron/native/surface/events.js +55 -0
- package/dist/src/drivers/electron/native/surface/events.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/presentation.d.ts +15 -0
- package/dist/src/drivers/electron/native/surface/presentation.js +87 -0
- package/dist/src/drivers/electron/native/surface/presentation.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/state.d.ts +7 -0
- package/dist/src/drivers/electron/native/surface/state.js +45 -0
- package/dist/src/drivers/electron/native/surface/state.js.map +1 -0
- package/dist/src/drivers/electron/native/surface/types.d.ts +39 -0
- package/dist/src/drivers/electron/native/surface/types.js +2 -0
- package/dist/src/drivers/electron/native/surface/types.js.map +1 -0
- package/dist/src/drivers/electron/native/surface-controller.d.ts +6 -0
- package/dist/src/drivers/electron/native/surface-controller.js +138 -0
- package/dist/src/drivers/electron/native/surface-controller.js.map +1 -0
- package/dist/src/drivers/electron/policy.d.ts +4 -0
- package/dist/src/drivers/electron/policy.js +39 -0
- package/dist/src/drivers/electron/policy.js.map +1 -0
- package/dist/src/drivers/electron/session.d.ts +4 -0
- package/dist/src/drivers/electron/session.js +5 -0
- package/dist/src/drivers/electron/session.js.map +1 -0
- package/dist/src/drivers/headless/command.d.ts +25 -0
- package/dist/src/drivers/headless/command.js +114 -0
- package/dist/src/drivers/headless/command.js.map +1 -0
- package/dist/src/drivers/headless/cookie-adapter.d.ts +16 -0
- package/dist/src/drivers/headless/cookie-adapter.js +59 -0
- package/dist/src/drivers/headless/cookie-adapter.js.map +1 -0
- package/dist/src/drivers/headless/driver.d.ts +31 -0
- package/dist/src/drivers/headless/driver.js +238 -0
- package/dist/src/drivers/headless/driver.js.map +1 -0
- package/dist/src/drivers/headless/executable.d.ts +8 -0
- package/dist/src/drivers/headless/executable.js +56 -0
- package/dist/src/drivers/headless/executable.js.map +1 -0
- package/dist/src/drivers/headless/screencast.d.ts +3 -0
- package/dist/src/drivers/headless/screencast.js +21 -0
- package/dist/src/drivers/headless/screencast.js.map +1 -0
- package/dist/src/electron.d.ts +14 -0
- package/dist/src/electron.js +15 -0
- package/dist/src/electron.js.map +1 -0
- package/dist/src/errors.d.ts +9 -0
- package/dist/src/errors.js +25 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/events.d.ts +13 -0
- package/dist/src/events.js +32 -0
- package/dist/src/events.js.map +1 -0
- package/dist/src/headless.d.ts +3 -0
- package/dist/src/headless.js +4 -0
- package/dist/src/headless.js.map +1 -0
- package/dist/src/http.d.ts +3 -0
- package/dist/src/http.js +3 -0
- package/dist/src/http.js.map +1 -0
- package/dist/src/ids.d.ts +2 -0
- package/dist/src/ids.js +9 -0
- package/dist/src/ids.js.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/interaction/delta.d.ts +25 -0
- package/dist/src/interaction/delta.js +102 -0
- package/dist/src/interaction/delta.js.map +1 -0
- package/dist/src/interaction/typing.d.ts +39 -0
- package/dist/src/interaction/typing.js +189 -0
- package/dist/src/interaction/typing.js.map +1 -0
- package/dist/src/mcp.d.ts +3 -0
- package/dist/src/mcp.js +3 -0
- package/dist/src/mcp.js.map +1 -0
- package/dist/src/migration/legacy-cookies.d.ts +2 -0
- package/dist/src/migration/legacy-cookies.js +60 -0
- package/dist/src/migration/legacy-cookies.js.map +1 -0
- package/dist/src/migration/legacy-crypto.d.ts +1 -0
- package/dist/src/migration/legacy-crypto.js +35 -0
- package/dist/src/migration/legacy-crypto.js.map +1 -0
- package/dist/src/migration/legacy-migration.d.ts +20 -0
- package/dist/src/migration/legacy-migration.js +81 -0
- package/dist/src/migration/legacy-migration.js.map +1 -0
- package/dist/src/migration/legacy-rows.d.ts +5 -0
- package/dist/src/migration/legacy-rows.js +72 -0
- package/dist/src/migration/legacy-rows.js.map +1 -0
- package/dist/src/persistence/sqlite-registry.d.ts +32 -0
- package/dist/src/persistence/sqlite-registry.js +136 -0
- package/dist/src/persistence/sqlite-registry.js.map +1 -0
- package/dist/src/ports.d.ts +93 -0
- package/dist/src/ports.js +4 -0
- package/dist/src/ports.js.map +1 -0
- package/dist/src/process.d.ts +4 -0
- package/dist/src/process.js +63 -0
- package/dist/src/process.js.map +1 -0
- package/dist/src/product-service.d.ts +30 -0
- package/dist/src/product-service.js +38 -0
- package/dist/src/product-service.js.map +1 -0
- package/dist/src/profiles/directories.d.ts +9 -0
- package/dist/src/profiles/directories.js +57 -0
- package/dist/src/profiles/directories.js.map +1 -0
- package/dist/src/profiles/service.d.ts +30 -0
- package/dist/src/profiles/service.js +89 -0
- package/dist/src/profiles/service.js.map +1 -0
- package/dist/src/recording/encoder.d.ts +22 -0
- package/dist/src/recording/encoder.js +89 -0
- package/dist/src/recording/encoder.js.map +1 -0
- package/dist/src/recording/sampler.d.ts +18 -0
- package/dist/src/recording/sampler.js +33 -0
- package/dist/src/recording/sampler.js.map +1 -0
- package/dist/src/recording/service.d.ts +27 -0
- package/dist/src/recording/service.js +180 -0
- package/dist/src/recording/service.js.map +1 -0
- package/dist/src/recording/source.d.ts +1 -0
- package/dist/src/recording/source.js +21 -0
- package/dist/src/recording/source.js.map +1 -0
- package/dist/src/recording.d.ts +3 -0
- package/dist/src/recording.js +4 -0
- package/dist/src/recording.js.map +1 -0
- package/dist/src/registry.d.ts +15 -0
- package/dist/src/registry.js +46 -0
- package/dist/src/registry.js.map +1 -0
- package/dist/src/runtime-selector.d.ts +12 -0
- package/dist/src/runtime-selector.js +78 -0
- package/dist/src/runtime-selector.js.map +1 -0
- package/dist/src/service-options.d.ts +19 -0
- package/dist/src/service-options.js +2 -0
- package/dist/src/service-options.js.map +1 -0
- package/dist/src/service.d.ts +39 -0
- package/dist/src/service.js +204 -0
- package/dist/src/service.js.map +1 -0
- package/dist/src/sessions/leases.d.ts +10 -0
- package/dist/src/sessions/leases.js +41 -0
- package/dist/src/sessions/leases.js.map +1 -0
- package/dist/src/sessions/prune.d.ts +2 -0
- package/dist/src/sessions/prune.js +8 -0
- package/dist/src/sessions/prune.js.map +1 -0
- package/dist/src/testing.d.ts +18 -0
- package/dist/src/testing.js +21 -0
- package/dist/src/testing.js.map +1 -0
- package/dist/src/toolbox.d.ts +3 -0
- package/dist/src/toolbox.js +4 -0
- package/dist/src/toolbox.js.map +1 -0
- package/dist/src/types.d.ts +273 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/docs/ACTIONS.md +27 -0
- package/docs/ARCHITECTURE.md +71 -0
- package/docs/AUTHENTICATION.md +56 -0
- package/docs/AXIOMS.md +20 -0
- package/docs/CLI.md +61 -0
- package/docs/COMPATIBILITY.md +45 -0
- package/docs/COOKIES.md +61 -0
- package/docs/ELECTRON_INTEGRATION.md +87 -0
- package/docs/ENGINE_INTEGRATION.md +73 -0
- package/docs/EVENTS.md +30 -0
- package/docs/HEADLESS_RUNTIME.md +58 -0
- package/docs/MCP.md +36 -0
- package/docs/MIGRATION.md +64 -0
- package/docs/OPERATIONS.md +69 -0
- package/docs/README.md +21 -0
- package/docs/REALTIME_BOUNDARY.md +33 -0
- package/docs/RECORDING.md +55 -0
- package/docs/REST.md +69 -0
- package/docs/SDK.md +101 -0
- package/docs/TESTING.md +57 -0
- package/docs/TOOLBOX_INTEGRATION.md +34 -0
- package/docs/TROUBLESHOOTING.md +67 -0
- package/examples/basic.ts +7 -0
- package/examples/custom-driver.ts +45 -0
- package/package.json +78 -0
- package/skills/use-amalgm-browser/SKILL.md +42 -0
- package/skills/use-amalgm-browser/agents/openai.yaml +4 -0
- package/skills/use-amalgm-browser/references/actions.md +40 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
2
|
+
import { asText, unwrap } from '../drivers/headless/command.js';
|
|
3
|
+
const KEY_COUNTER = ['eval', `(() => {
|
|
4
|
+
if (!window.__amalgmKeyGuard) {
|
|
5
|
+
window.__amalgmKeyGuard = { count: 0 };
|
|
6
|
+
document.addEventListener('keydown', () => { window.__amalgmKeyGuard.count += 1; }, true);
|
|
7
|
+
}
|
|
8
|
+
return window.__amalgmKeyGuard.count;
|
|
9
|
+
})()`];
|
|
10
|
+
export class HeadlessActionEvidence {
|
|
11
|
+
command;
|
|
12
|
+
pages = new Map();
|
|
13
|
+
constructor(command) {
|
|
14
|
+
this.command = command;
|
|
15
|
+
}
|
|
16
|
+
remember(session, value) {
|
|
17
|
+
if (value.url)
|
|
18
|
+
this.pages.set(session, value);
|
|
19
|
+
}
|
|
20
|
+
async before(session, action, context) {
|
|
21
|
+
const page = this.pages.get(session);
|
|
22
|
+
const before = { ...(page ? { page } : {}) };
|
|
23
|
+
const target = 'target' in action ? action.target : undefined;
|
|
24
|
+
if (target && !target.startsWith('text=') && ['click', 'fill', 'select'].includes(action.type)) {
|
|
25
|
+
const enabled = await this.run(session, ['is', 'enabled', target], context);
|
|
26
|
+
if (enabled !== null)
|
|
27
|
+
before.enabled = Boolean(value(enabled, 'enabled'));
|
|
28
|
+
}
|
|
29
|
+
if (action.type === 'fill' && target && !target.startsWith('text=')) {
|
|
30
|
+
const current = await this.run(session, ['get', 'value', target], context);
|
|
31
|
+
if (current !== null)
|
|
32
|
+
before.value = String(value(current, 'value') ?? '');
|
|
33
|
+
}
|
|
34
|
+
if (action.type === 'press') {
|
|
35
|
+
const count = await this.run(session, KEY_COUNTER, context);
|
|
36
|
+
if (count !== null)
|
|
37
|
+
before.keyCount = Number(value(count)) || 0;
|
|
38
|
+
}
|
|
39
|
+
return before;
|
|
40
|
+
}
|
|
41
|
+
async after(session, action, before, context) {
|
|
42
|
+
await delay(150, undefined, context.signal ? { signal: context.signal } : {}).catch(() => undefined);
|
|
43
|
+
const evidence = { warnings: [], page: {} };
|
|
44
|
+
if (before.enabled !== undefined)
|
|
45
|
+
evidence.targetEnabled = before.enabled;
|
|
46
|
+
if (before.enabled === false)
|
|
47
|
+
evidence.warnings.push('Target was disabled when the action ran.');
|
|
48
|
+
const target = 'target' in action ? action.target : undefined;
|
|
49
|
+
if ((action.type === 'fill' || action.type === 'select') && target && !target.startsWith('text=')) {
|
|
50
|
+
const current = await this.run(session, ['get', 'value', target], context);
|
|
51
|
+
if (current !== null) {
|
|
52
|
+
const after = String(value(current, 'value') ?? '');
|
|
53
|
+
evidence.value = { ...(before.value !== undefined ? { before: before.value, changed: before.value !== after } : {}), after };
|
|
54
|
+
if (action.type === 'fill' && after !== action.text)
|
|
55
|
+
evidence.warnings.push('Field value differs from the requested text.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (action.type === 'press' && before.keyCount !== undefined) {
|
|
59
|
+
const count = await this.run(session, KEY_COUNTER, context);
|
|
60
|
+
const dispatched = Math.max(0, (Number(value(count)) || 0) - before.keyCount);
|
|
61
|
+
evidence.keys = { dispatched };
|
|
62
|
+
if (dispatched > 15) {
|
|
63
|
+
await delay(200).catch(() => undefined);
|
|
64
|
+
const later = Number(value(await this.run(session, KEY_COUNTER, context))) || 0;
|
|
65
|
+
if (later > before.keyCount + dispatched) {
|
|
66
|
+
evidence.keys.flood = true;
|
|
67
|
+
evidence.warnings.push('Runaway keyboard input is still firing.');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const page = await this.page(session, context);
|
|
72
|
+
if (page) {
|
|
73
|
+
evidence.page = { ...page, ...(before.page ? { urlChanged: before.page.url !== page.url } : {}) };
|
|
74
|
+
this.remember(session, page);
|
|
75
|
+
}
|
|
76
|
+
return evidence;
|
|
77
|
+
}
|
|
78
|
+
async page(session, context) {
|
|
79
|
+
const result = await this.run(session, ['eval', 'JSON.stringify({url: location.href, title: document.title})'], context);
|
|
80
|
+
try {
|
|
81
|
+
return JSON.parse(String(value(result)));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async run(session, args, context) {
|
|
88
|
+
try {
|
|
89
|
+
return await this.command.run(session, args, { signal: context.signal, timeoutMs: 5_000 });
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function value(input, key) {
|
|
97
|
+
const unwrapped = unwrap(input);
|
|
98
|
+
if (key && unwrapped && typeof unwrapped === 'object' && key in unwrapped)
|
|
99
|
+
return unwrapped[key];
|
|
100
|
+
return typeof unwrapped === 'object' && unwrapped && 'text' in unwrapped ? asText(unwrapped) : unwrapped;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=delta.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delta.js","sourceRoot":"","sources":["../../../src/interaction/delta.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-page typing — the scripts behind fill and press in attached mode.
|
|
3
|
+
*
|
|
4
|
+
* In the desktop app the agent and the user share one chromium window, and
|
|
5
|
+
* synthesized keystrokes (CDP Input events) are routed by *window focus* —
|
|
6
|
+
* an agent "typing" while the user's caret sits in the chat box lands the
|
|
7
|
+
* text in the chat box (observed live). These scripts act inside the
|
|
8
|
+
* session's page instead, through the same stamp-guarded transport as every
|
|
9
|
+
* other command, so agent input physically cannot reach anything but the
|
|
10
|
+
* page it was meant for.
|
|
11
|
+
*
|
|
12
|
+
* The boundary: page-level semantics work (value setting with real
|
|
13
|
+
* input/change events, key handlers, Enter activating buttons and
|
|
14
|
+
* submitting forms); OS-level editing defaults (Tab focus traversal,
|
|
15
|
+
* arrow-key scrolling) are real-input territory — that is what the cua_*
|
|
16
|
+
* verbs are for, and they stay focus-dependent by design.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Set the focused field's value the way the page expects: through the
|
|
20
|
+
* native prototype setter (so frameworks tracking the value descriptor —
|
|
21
|
+
* React — see the change), followed by real input/change events.
|
|
22
|
+
*/
|
|
23
|
+
export declare function setValueScript(text: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Insert text at the focused field/caret without using browser-window
|
|
26
|
+
* keyboard focus. This is the attached-mode implementation for cua_type and
|
|
27
|
+
* CLI keyboard typing: if the page did not focus an editable element, fail
|
|
28
|
+
* closed instead of letting real keystrokes leak into Amalgm's own UI.
|
|
29
|
+
*/
|
|
30
|
+
export declare function insertTextScript(text: string): string;
|
|
31
|
+
/** "KeyA" for letters, "Digit1" for digits, the key's own name otherwise. */
|
|
32
|
+
export declare function codeFor(key: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Dispatch a key combination ("Enter", "Escape", "Control+a") to the focused
|
|
35
|
+
* element, mirroring the browser's own Enter defaults when no handler
|
|
36
|
+
* prevents them: buttons and links activate, single-line form fields submit
|
|
37
|
+
* their form (through requestSubmit, so submit handlers and validation run).
|
|
38
|
+
*/
|
|
39
|
+
export declare function keyScript(combo: string): string;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-page typing — the scripts behind fill and press in attached mode.
|
|
3
|
+
*
|
|
4
|
+
* In the desktop app the agent and the user share one chromium window, and
|
|
5
|
+
* synthesized keystrokes (CDP Input events) are routed by *window focus* —
|
|
6
|
+
* an agent "typing" while the user's caret sits in the chat box lands the
|
|
7
|
+
* text in the chat box (observed live). These scripts act inside the
|
|
8
|
+
* session's page instead, through the same stamp-guarded transport as every
|
|
9
|
+
* other command, so agent input physically cannot reach anything but the
|
|
10
|
+
* page it was meant for.
|
|
11
|
+
*
|
|
12
|
+
* The boundary: page-level semantics work (value setting with real
|
|
13
|
+
* input/change events, key handlers, Enter activating buttons and
|
|
14
|
+
* submitting forms); OS-level editing defaults (Tab focus traversal,
|
|
15
|
+
* arrow-key scrolling) are real-input territory — that is what the cua_*
|
|
16
|
+
* verbs are for, and they stay focus-dependent by design.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Set the focused field's value the way the page expects: through the
|
|
20
|
+
* native prototype setter (so frameworks tracking the value descriptor —
|
|
21
|
+
* React — see the change), followed by real input/change events.
|
|
22
|
+
*/
|
|
23
|
+
export function setValueScript(text) {
|
|
24
|
+
return `(() => {
|
|
25
|
+
const el = document.activeElement;
|
|
26
|
+
if (!el || el === document.body) throw new Error('focus did not land on a field');
|
|
27
|
+
const text = ${JSON.stringify(String(text))};
|
|
28
|
+
if (el.isContentEditable) {
|
|
29
|
+
el.textContent = text;
|
|
30
|
+
} else {
|
|
31
|
+
const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype
|
|
32
|
+
: el instanceof HTMLInputElement ? HTMLInputElement.prototype
|
|
33
|
+
: null;
|
|
34
|
+
if (!proto && !('value' in el)) {
|
|
35
|
+
throw new Error('focused element <' + el.tagName.toLowerCase() + '> is not fillable');
|
|
36
|
+
}
|
|
37
|
+
const setter = proto && Object.getOwnPropertyDescriptor(proto, 'value').set;
|
|
38
|
+
if (setter) setter.call(el, text); else el.value = text;
|
|
39
|
+
}
|
|
40
|
+
el.dispatchEvent(new InputEvent('input', { bubbles: true, data: text, inputType: 'insertReplacementText' }));
|
|
41
|
+
el.dispatchEvent(new Event('change', { bubbles: true }));
|
|
42
|
+
return true;
|
|
43
|
+
})()`;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Insert text at the focused field/caret without using browser-window
|
|
47
|
+
* keyboard focus. This is the attached-mode implementation for cua_type and
|
|
48
|
+
* CLI keyboard typing: if the page did not focus an editable element, fail
|
|
49
|
+
* closed instead of letting real keystrokes leak into Amalgm's own UI.
|
|
50
|
+
*/
|
|
51
|
+
export function insertTextScript(text) {
|
|
52
|
+
return `(() => {
|
|
53
|
+
const el = document.activeElement;
|
|
54
|
+
if (!el || el === document.body || el === document.documentElement) {
|
|
55
|
+
throw new Error('focus did not land on an editable field');
|
|
56
|
+
}
|
|
57
|
+
const text = ${JSON.stringify(String(text))};
|
|
58
|
+
const inputEvent = (inputType, data = text) => new InputEvent('input', {
|
|
59
|
+
bubbles: true,
|
|
60
|
+
data,
|
|
61
|
+
inputType,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (el.isContentEditable) {
|
|
65
|
+
const selection = window.getSelection();
|
|
66
|
+
if (selection && selection.rangeCount) {
|
|
67
|
+
const range = selection.getRangeAt(0);
|
|
68
|
+
range.deleteContents();
|
|
69
|
+
const node = document.createTextNode(text);
|
|
70
|
+
range.insertNode(node);
|
|
71
|
+
range.setStartAfter(node);
|
|
72
|
+
range.setEndAfter(node);
|
|
73
|
+
selection.removeAllRanges();
|
|
74
|
+
selection.addRange(range);
|
|
75
|
+
} else {
|
|
76
|
+
el.textContent = (el.textContent || '') + text;
|
|
77
|
+
}
|
|
78
|
+
el.dispatchEvent(inputEvent('insertText'));
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype
|
|
83
|
+
: el instanceof HTMLInputElement ? HTMLInputElement.prototype
|
|
84
|
+
: null;
|
|
85
|
+
if (!proto && !('value' in el)) {
|
|
86
|
+
throw new Error('focused element <' + el.tagName.toLowerCase() + '> is not editable');
|
|
87
|
+
}
|
|
88
|
+
const value = String(el.value || '');
|
|
89
|
+
const start = typeof el.selectionStart === 'number' ? el.selectionStart : value.length;
|
|
90
|
+
const end = typeof el.selectionEnd === 'number' ? el.selectionEnd : start;
|
|
91
|
+
const next = value.slice(0, start) + text + value.slice(end);
|
|
92
|
+
const setter = proto && Object.getOwnPropertyDescriptor(proto, 'value').set;
|
|
93
|
+
if (setter) setter.call(el, next); else el.value = next;
|
|
94
|
+
const caret = start + text.length;
|
|
95
|
+
if (typeof el.setSelectionRange === 'function') {
|
|
96
|
+
try { el.setSelectionRange(caret, caret); } catch {}
|
|
97
|
+
}
|
|
98
|
+
el.dispatchEvent(inputEvent('insertText'));
|
|
99
|
+
return true;
|
|
100
|
+
})()`;
|
|
101
|
+
}
|
|
102
|
+
/** "KeyA" for letters, "Digit1" for digits, the key's own name otherwise. */
|
|
103
|
+
export function codeFor(key) {
|
|
104
|
+
if (/^[a-z]$/i.test(key))
|
|
105
|
+
return `Key${key.toUpperCase()}`;
|
|
106
|
+
if (/^[0-9]$/.test(key))
|
|
107
|
+
return `Digit${key}`;
|
|
108
|
+
if (key === ' ')
|
|
109
|
+
return 'Space';
|
|
110
|
+
return key;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Dispatch a key combination ("Enter", "Escape", "Control+a") to the focused
|
|
114
|
+
* element, mirroring the browser's own Enter defaults when no handler
|
|
115
|
+
* prevents them: buttons and links activate, single-line form fields submit
|
|
116
|
+
* their form (through requestSubmit, so submit handlers and validation run).
|
|
117
|
+
*/
|
|
118
|
+
export function keyScript(combo) {
|
|
119
|
+
const parts = String(combo).split('+');
|
|
120
|
+
const key = parts.pop() || '';
|
|
121
|
+
const mods = parts.map((part) => part.toLowerCase());
|
|
122
|
+
const init = {
|
|
123
|
+
key,
|
|
124
|
+
code: codeFor(key),
|
|
125
|
+
bubbles: true,
|
|
126
|
+
cancelable: true,
|
|
127
|
+
ctrlKey: mods.includes('control') || mods.includes('ctrl'),
|
|
128
|
+
shiftKey: mods.includes('shift'),
|
|
129
|
+
altKey: mods.includes('alt') || mods.includes('option'),
|
|
130
|
+
metaKey: mods.includes('meta') || mods.includes('cmd') || mods.includes('command'),
|
|
131
|
+
};
|
|
132
|
+
return `(() => {
|
|
133
|
+
const el = document.activeElement || document.body;
|
|
134
|
+
const init = ${JSON.stringify(init)};
|
|
135
|
+
const isInput = el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement;
|
|
136
|
+
const isEditable = isInput || el.isContentEditable;
|
|
137
|
+
const inputEvent = (inputType, data = null) => new InputEvent('input', {
|
|
138
|
+
bubbles: true,
|
|
139
|
+
data,
|
|
140
|
+
inputType,
|
|
141
|
+
});
|
|
142
|
+
const setValue = (next, start, end = start) => {
|
|
143
|
+
const proto = el instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype
|
|
144
|
+
: el instanceof HTMLInputElement ? HTMLInputElement.prototype
|
|
145
|
+
: null;
|
|
146
|
+
const setter = proto && Object.getOwnPropertyDescriptor(proto, 'value').set;
|
|
147
|
+
if (setter) setter.call(el, next); else el.value = next;
|
|
148
|
+
if (typeof el.setSelectionRange === 'function') {
|
|
149
|
+
try { el.setSelectionRange(start, end); } catch {}
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const proceed = el.dispatchEvent(new KeyboardEvent('keydown', init));
|
|
153
|
+
if (proceed) {
|
|
154
|
+
el.dispatchEvent(new KeyboardEvent('keypress', init));
|
|
155
|
+
if ((init.ctrlKey || init.metaKey) && init.key.toLowerCase() === 'a' && isEditable) {
|
|
156
|
+
if (isInput && typeof el.select === 'function') {
|
|
157
|
+
el.select();
|
|
158
|
+
} else {
|
|
159
|
+
const range = document.createRange();
|
|
160
|
+
range.selectNodeContents(el);
|
|
161
|
+
const selection = window.getSelection();
|
|
162
|
+
selection.removeAllRanges();
|
|
163
|
+
selection.addRange(range);
|
|
164
|
+
}
|
|
165
|
+
} else if ((init.key === 'Backspace' || init.key === 'Delete') && isInput) {
|
|
166
|
+
const value = String(el.value || '');
|
|
167
|
+
const selectionStart = typeof el.selectionStart === 'number' ? el.selectionStart : value.length;
|
|
168
|
+
const selectionEnd = typeof el.selectionEnd === 'number' ? el.selectionEnd : selectionStart;
|
|
169
|
+
let start = selectionStart;
|
|
170
|
+
let end = selectionEnd;
|
|
171
|
+
if (start === end && init.key === 'Backspace' && start > 0) start -= 1;
|
|
172
|
+
if (start === end && init.key === 'Delete' && end < value.length) end += 1;
|
|
173
|
+
if (start !== end) {
|
|
174
|
+
setValue(value.slice(0, start) + value.slice(end), start);
|
|
175
|
+
el.dispatchEvent(inputEvent(init.key === 'Backspace' ? 'deleteContentBackward' : 'deleteContentForward'));
|
|
176
|
+
}
|
|
177
|
+
} else if (init.key === 'Enter') {
|
|
178
|
+
if (el instanceof HTMLButtonElement || el instanceof HTMLAnchorElement) {
|
|
179
|
+
el.click();
|
|
180
|
+
} else if (el instanceof HTMLInputElement && el.form) {
|
|
181
|
+
if (el.form.requestSubmit) el.form.requestSubmit(); else el.form.submit();
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
el.dispatchEvent(new KeyboardEvent('keyup', init));
|
|
186
|
+
return true;
|
|
187
|
+
})()`;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=typing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typing.js","sourceRoot":"","sources":["../../../src/interaction/typing.ts"],"names":[],"mappings":"AACA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,OAAO;;;mBAGU,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;;;;;;;;;;;;;;;OAgBxC,CAAC;AACR,CAAC;AACD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO;;;;;mBAKU,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CxC,CAAC;AACR,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;IAC3D,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,GAAG,EAAE,CAAC;IAC9C,IAAI,GAAG,KAAK,GAAG;QAAE,OAAO,OAAO,CAAC;IAChC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;IAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG;QACX,GAAG;QACH,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;QAClB,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI;QAChB,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC1D,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAChC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACvD,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;KACnF,CAAC;IACF,OAAO;;mBAEU,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqDhC,CAAC;AACR,CAAC"}
|
package/dist/src/mcp.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export function importLegacyCookies(payload, jar) {
|
|
2
|
+
if (!payload || typeof payload !== 'object')
|
|
3
|
+
return 0;
|
|
4
|
+
const source = payload;
|
|
5
|
+
const stored = source.cookieJar;
|
|
6
|
+
let imported = 0;
|
|
7
|
+
for (const record of stored?.records || []) {
|
|
8
|
+
if (!record.cookie)
|
|
9
|
+
continue;
|
|
10
|
+
const cookie = normalizePartition(record.cookie);
|
|
11
|
+
jar.merge({ sourceId: record.sourceId || 'legacy', ...(record.updatedAt ? { changedAt: record.updatedAt } : {}), upserts: [cookie] });
|
|
12
|
+
imported += 1;
|
|
13
|
+
}
|
|
14
|
+
for (const tombstone of stored?.tombstones || []) {
|
|
15
|
+
const deletion = parseLegacyKey(tombstone.key || '');
|
|
16
|
+
if (!deletion)
|
|
17
|
+
continue;
|
|
18
|
+
jar.merge({ sourceId: tombstone.sourceId || 'legacy', ...(tombstone.deletedAt ? { changedAt: tombstone.deletedAt } : {}), deletes: [deletion] });
|
|
19
|
+
imported += 1;
|
|
20
|
+
}
|
|
21
|
+
if (!stored && source.state && typeof source.state === 'object') {
|
|
22
|
+
const cookies = source.state.cookies;
|
|
23
|
+
if (Array.isArray(cookies)) {
|
|
24
|
+
for (const cookie of cookies) {
|
|
25
|
+
if (!cookie || typeof cookie !== 'object')
|
|
26
|
+
continue;
|
|
27
|
+
jar.merge({ sourceId: 'legacy-cookie-source', upserts: [normalizePartition(cookie)] });
|
|
28
|
+
imported += 1;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return imported;
|
|
33
|
+
}
|
|
34
|
+
function parseLegacyKey(value) {
|
|
35
|
+
const [domain, _scope, path, name, rawPartition] = value.split('\0');
|
|
36
|
+
if (!domain || !path || !name)
|
|
37
|
+
return null;
|
|
38
|
+
const partitionKey = parsePartition(rawPartition);
|
|
39
|
+
return { domain, path, name, ...(partitionKey ? { partitionKey } : {}) };
|
|
40
|
+
}
|
|
41
|
+
function normalizePartition(cookie) {
|
|
42
|
+
const partitionKey = typeof cookie.partitionKey === 'string'
|
|
43
|
+
? parsePartition(JSON.stringify(cookie.partitionKey)) : cookie.partitionKey;
|
|
44
|
+
return { ...cookie, ...(partitionKey ? { partitionKey } : { partitionKey: undefined }) };
|
|
45
|
+
}
|
|
46
|
+
function parsePartition(value) {
|
|
47
|
+
if (!value)
|
|
48
|
+
return undefined;
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(value);
|
|
51
|
+
if (typeof parsed === 'string')
|
|
52
|
+
return { topLevelSite: parsed };
|
|
53
|
+
if (parsed && typeof parsed === 'object' && typeof parsed.topLevelSite === 'string') {
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch { }
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=legacy-cookies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-cookies.js","sourceRoot":"","sources":["../../../src/migration/legacy-cookies.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,mBAAmB,CAAC,OAAgB,EAAE,GAAqB;IACzE,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,OAAkC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,CAAC,SAA2F,CAAC;IAClH,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,OAAO,IAAI,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,MAAM;YAAE,SAAS;QAC7B,MAAM,MAAM,GAAG,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACjD,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtI,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,UAAU,IAAI,EAAE,EAAE,CAAC;QACjD,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ;YAAE,SAAS;QACxB,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,SAAS,CAAC,QAAQ,IAAI,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QACjJ,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChE,MAAM,OAAO,GAAI,MAAM,CAAC,KAAiC,CAAC,OAAO,CAAC;QAClE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;oBAAE,SAAS;gBACpD,GAAG,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,EAAE,CAAC,kBAAkB,CAAC,MAAuB,CAAC,CAAC,EAAE,CAAC,CAAC;gBACxG,QAAQ,IAAI,CAAC,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,KAAa;IACnC,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAClD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED,SAAS,kBAAkB,CAAsF,MAAS;IACxH,MAAM,YAAY,GAAG,OAAO,MAAM,CAAC,YAAY,KAAK,QAAQ;QAC1D,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;IAC9E,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAAmB,CAAC;AAC5G,CAAC;AAED,SAAS,cAAc,CAAC,KAAyB;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAY,CAAC;QAC5C,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;QAChE,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAQ,MAAkC,CAAC,YAAY,KAAK,QAAQ,EAAE,CAAC;YACjH,OAAO,MAAgC,CAAC;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function readLegacyBundle(file: string, browserRoot: string, expectedHash?: string): unknown;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { BrowserError } from '../errors.js';
|
|
5
|
+
export function readLegacyBundle(file, browserRoot, expectedHash) {
|
|
6
|
+
const raw = fs.readFileSync(file, 'utf8');
|
|
7
|
+
if (expectedHash && sha256(raw) !== expectedHash) {
|
|
8
|
+
throw new BrowserError('PROCESS_FAILED', `Legacy Browser bundle ${path.basename(file)} failed integrity verification.`);
|
|
9
|
+
}
|
|
10
|
+
const envelope = JSON.parse(raw);
|
|
11
|
+
if (envelope.version !== 1 || envelope.alg !== 'aes-256-gcm') {
|
|
12
|
+
throw new BrowserError('PROCESS_FAILED', 'Unsupported legacy Browser bundle format.');
|
|
13
|
+
}
|
|
14
|
+
const decipher = crypto.createDecipheriv('aes-256-gcm', legacyKey(browserRoot), Buffer.from(envelope.iv, 'base64url'));
|
|
15
|
+
decipher.setAuthTag(Buffer.from(envelope.tag, 'base64url'));
|
|
16
|
+
return JSON.parse(Buffer.concat([
|
|
17
|
+
decipher.update(Buffer.from(envelope.data, 'base64url')),
|
|
18
|
+
decipher.final(),
|
|
19
|
+
]).toString('utf8'));
|
|
20
|
+
}
|
|
21
|
+
function legacyKey(root) {
|
|
22
|
+
const environment = String(process.env.AMALGM_BROWSER_AUTH_KEY || '').trim();
|
|
23
|
+
if (/^[a-f\d]{64}$/i.test(environment))
|
|
24
|
+
return Buffer.from(environment, 'hex');
|
|
25
|
+
const file = path.join(root, 'auth-bundles', 'keys', 'local-device.key');
|
|
26
|
+
try {
|
|
27
|
+
const value = fs.readFileSync(file, 'utf8').trim();
|
|
28
|
+
if (/^[a-f\d]{64}$/i.test(value))
|
|
29
|
+
return Buffer.from(value, 'hex');
|
|
30
|
+
}
|
|
31
|
+
catch { }
|
|
32
|
+
throw new BrowserError('PROCESS_FAILED', 'Legacy Browser encryption key is unavailable.');
|
|
33
|
+
}
|
|
34
|
+
function sha256(value) { return crypto.createHash('sha256').update(value).digest('hex'); }
|
|
35
|
+
//# sourceMappingURL=legacy-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-crypto.js","sourceRoot":"","sources":["../../../src/migration/legacy-crypto.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAW5C,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,WAAmB,EAAE,YAAqB;IACvF,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,YAAY,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,YAAY,EAAE,CAAC;QACjD,MAAM,IAAI,YAAY,CAAC,gBAAgB,EAAE,yBAAyB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC1H,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC;IACnD,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC,IAAI,QAAQ,CAAC,GAAG,KAAK,aAAa,EAAE,CAAC;QAC7D,MAAM,IAAI,YAAY,CAAC,gBAAgB,EAAE,2CAA2C,CAAC,CAAC;IACxF,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IACvH,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;QAC9B,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACxD,QAAQ,CAAC,KAAK,EAAE;KACjB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAY,CAAC;AAClC,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7E,IAAI,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC;QAAE,OAAO,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACzE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IACV,MAAM,IAAI,YAAY,CAAC,gBAAgB,EAAE,+CAA+C,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,MAAM,CAAC,KAAa,IAAY,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { BrowserAuthVault } from '../auth/vault.js';
|
|
2
|
+
import type { BrowserCookieJar } from '../cookies/jar.js';
|
|
3
|
+
import type { EncryptedSecretFile } from '../cookies/secret-file.js';
|
|
4
|
+
import type { SqliteBrowserRegistry } from '../persistence/sqlite-registry.js';
|
|
5
|
+
export interface LegacyBrowserMigrationOptions {
|
|
6
|
+
browserRoot: string;
|
|
7
|
+
databaseFile: string;
|
|
8
|
+
registry: SqliteBrowserRegistry;
|
|
9
|
+
authVault: BrowserAuthVault;
|
|
10
|
+
cookieJar: BrowserCookieJar;
|
|
11
|
+
loginSecrets: EncryptedSecretFile;
|
|
12
|
+
}
|
|
13
|
+
export interface LegacyBrowserMigrationResult {
|
|
14
|
+
status: 'absent' | 'already-migrated' | 'migrated';
|
|
15
|
+
profiles: number;
|
|
16
|
+
authBundles: number;
|
|
17
|
+
loginSessions: number;
|
|
18
|
+
cookieRecords: number;
|
|
19
|
+
}
|
|
20
|
+
export declare function migrateLegacyBrowserState(options: LegacyBrowserMigrationOptions): LegacyBrowserMigrationResult;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
|
+
import { importLegacyCookies } from './legacy-cookies.js';
|
|
5
|
+
import { readLegacyBundle } from './legacy-crypto.js';
|
|
6
|
+
import { legacyAuthBundle, legacyLogin, legacyProfile } from './legacy-rows.js';
|
|
7
|
+
const MIGRATION = 'engine-browser-v1';
|
|
8
|
+
const COOKIE_SOURCE_ID = 'browser-cookie-source';
|
|
9
|
+
export function migrateLegacyBrowserState(options) {
|
|
10
|
+
const empty = { profiles: 0, authBundles: 0, loginSessions: 0, cookieRecords: 0 };
|
|
11
|
+
if (!fs.existsSync(options.databaseFile))
|
|
12
|
+
return { status: 'absent', ...empty };
|
|
13
|
+
if (options.registry.getMeta(MIGRATION) === path.resolve(options.databaseFile)) {
|
|
14
|
+
return { status: 'already-migrated', ...empty };
|
|
15
|
+
}
|
|
16
|
+
const legacy = new Database(options.databaseFile, { readonly: true, fileMustExist: true });
|
|
17
|
+
legacy.pragma('query_only = ON');
|
|
18
|
+
const result = { ...empty };
|
|
19
|
+
try {
|
|
20
|
+
options.registry.transaction(() => {
|
|
21
|
+
if (hasTable(legacy, 'browser_profiles')) {
|
|
22
|
+
for (const row of rows(legacy, 'browser_profiles')) {
|
|
23
|
+
options.registry.putProfile(legacyProfile(row));
|
|
24
|
+
result.profiles += 1;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (hasTable(legacy, 'browser_auth_bundles')) {
|
|
28
|
+
for (const row of rows(legacy, 'browser_auth_bundles')) {
|
|
29
|
+
const id = String(row.id);
|
|
30
|
+
const blob = text(row.blob_path)
|
|
31
|
+
|| path.join(options.browserRoot, 'auth-bundles', `${id}.json.enc`);
|
|
32
|
+
if (!fs.existsSync(blob))
|
|
33
|
+
continue;
|
|
34
|
+
const payload = readLegacyBundle(blob, options.browserRoot, text(row.blob_sha256));
|
|
35
|
+
if (id === COOKIE_SOURCE_ID) {
|
|
36
|
+
result.cookieRecords += importLegacyCookies(payload, options.cookieJar);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
options.authVault.write(id, stateFrom(payload));
|
|
40
|
+
options.registry.putAuthBundle(legacyAuthBundle(row));
|
|
41
|
+
result.authBundles += 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (hasTable(legacy, 'browser_login_sessions')) {
|
|
46
|
+
const secretData = options.loginSecrets.read()
|
|
47
|
+
|| { schemaVersion: 1, hashes: {} };
|
|
48
|
+
for (const row of rows(legacy, 'browser_login_sessions')) {
|
|
49
|
+
const login = legacyLogin(row);
|
|
50
|
+
options.registry.putLoginSession(login);
|
|
51
|
+
if (['pending', 'active'].includes(login.status) && text(row.token_hash)) {
|
|
52
|
+
secretData.hashes[login.id] = text(row.token_hash);
|
|
53
|
+
}
|
|
54
|
+
result.loginSessions += 1;
|
|
55
|
+
}
|
|
56
|
+
if (result.loginSessions)
|
|
57
|
+
options.loginSecrets.write(secretData);
|
|
58
|
+
}
|
|
59
|
+
options.registry.setMeta(MIGRATION, path.resolve(options.databaseFile));
|
|
60
|
+
});
|
|
61
|
+
return { status: 'migrated', ...result };
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
legacy.close();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function hasTable(database, table) {
|
|
68
|
+
return Boolean(database.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name = ?").get(table));
|
|
69
|
+
}
|
|
70
|
+
function rows(database, table) {
|
|
71
|
+
if (!['browser_profiles', 'browser_auth_bundles', 'browser_login_sessions'].includes(table))
|
|
72
|
+
return [];
|
|
73
|
+
return database.prepare(`SELECT * FROM ${table}`).all();
|
|
74
|
+
}
|
|
75
|
+
function text(value) { return typeof value === 'string' ? value : ''; }
|
|
76
|
+
function stateFrom(payload) {
|
|
77
|
+
if (!payload || typeof payload !== 'object')
|
|
78
|
+
return payload;
|
|
79
|
+
return payload.state ?? payload;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=legacy-migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-migration.js","sourceRoot":"","sources":["../../../src/migration/legacy-migration.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAKtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAEhG,MAAM,SAAS,GAAG,mBAAmB,CAAC;AACtC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAmBjD,MAAM,UAAU,yBAAyB,CAAC,OAAsC;IAC9E,MAAM,KAAK,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAClF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,YAAY,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,CAAC;IAChF,IAAI,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,GAAG,KAAK,EAAE,CAAC;IAClD,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3F,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC5B,IAAI,CAAC;QACH,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,EAAE;YAChC,IAAI,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAC;gBACzC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,EAAE,CAAC;oBACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAAE,CAAC;gBAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,sBAAsB,CAAC,EAAE,CAAC;oBACvD,MAAM,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;2BAC3B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;oBACtE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;wBAAE,SAAS;oBACnC,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;oBACnF,IAAI,EAAE,KAAK,gBAAgB,EAAE,CAAC;wBAC5B,MAAM,CAAC,aAAa,IAAI,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;oBAC1E,CAAC;yBAAM,CAAC;wBACN,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;wBAChD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;wBACtD,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC;oBAC1B,CAAC;gBACH,CAAC;YACH,CAAC;YACD,IAAI,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC,EAAE,CAAC;gBAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,IAAI,EAAwD;uBAC/F,EAAE,aAAa,EAAE,CAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;gBAC/C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE,wBAAwB,CAAC,EAAE,CAAC;oBACzD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;oBAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;oBACxC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;wBACzE,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBACrD,CAAC;oBACD,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC;gBAC5B,CAAC;gBACD,IAAI,MAAM,CAAC,aAAa;oBAAE,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACnE,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAAC;IAC3C,CAAC;YAAS,CAAC;QAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IAAC,CAAC;AAC/B,CAAC;AAED,SAAS,QAAQ,CAAC,QAA2B,EAAE,KAAa;IAC1D,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,6DAA6D,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;AAC7G,CAAC;AACD,SAAS,IAAI,CAAC,QAA2B,EAAE,KAAa;IACtD,IAAI,CAAC,CAAC,kBAAkB,EAAE,sBAAsB,EAAE,wBAAwB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACvG,OAAO,QAAQ,CAAC,OAAO,CAAC,iBAAiB,KAAK,EAAE,CAAC,CAAC,GAAG,EAAiB,CAAC;AACzE,CAAC;AACD,SAAS,IAAI,CAAC,KAAc,IAAY,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACxF,SAAS,SAAS,CAAC,OAAgB;IACjC,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC;IAC5D,OAAQ,OAAmC,CAAC,KAAK,IAAI,OAAO,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BrowserAuthBundle, BrowserLoginSession, BrowserProfile } from '../types.js';
|
|
2
|
+
export type LegacyRow = Record<string, unknown>;
|
|
3
|
+
export declare function legacyProfile(row: LegacyRow): BrowserProfile;
|
|
4
|
+
export declare function legacyAuthBundle(row: LegacyRow): BrowserAuthBundle;
|
|
5
|
+
export declare function legacyLogin(row: LegacyRow): BrowserLoginSession;
|