latchkey 0.1.3 → 0.1.4
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 +17 -1
- package/dist/scripts/recordBrowserSession.js +1 -1
- package/dist/scripts/recordBrowserSession.js.map +1 -1
- package/dist/src/browserConfig.d.ts +30 -27
- package/dist/src/browserConfig.d.ts.map +1 -1
- package/dist/src/browserConfig.js +125 -94
- package/dist/src/browserConfig.js.map +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/cliCommands.d.ts.map +1 -1
- package/dist/src/cliCommands.js +54 -6
- package/dist/src/cliCommands.js.map +1 -1
- package/dist/src/config.d.ts +1 -0
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +5 -0
- package/dist/src/config.js.map +1 -1
- package/dist/src/playwrightDownload.d.ts +44 -0
- package/dist/src/playwrightDownload.d.ts.map +1 -0
- package/dist/src/playwrightDownload.js +222 -0
- package/dist/src/playwrightDownload.js.map +1 -0
- package/dist/src/playwrightUtils.d.ts +7 -1
- package/dist/src/playwrightUtils.d.ts.map +1 -1
- package/dist/src/playwrightUtils.js +14 -8
- package/dist/src/playwrightUtils.js.map +1 -1
- package/dist/src/services/base.d.ts +2 -1
- package/dist/src/services/base.d.ts.map +1 -1
- package/dist/src/services/base.js +3 -3
- package/dist/src/services/base.js.map +1 -1
- package/dist/tests/cli.test.js +16 -3
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/playwrightDownload.test.d.ts +2 -0
- package/dist/tests/playwrightDownload.test.d.ts.map +1 -0
- package/dist/tests/playwrightDownload.test.js +131 -0
- package/dist/tests/playwrightDownload.test.js.map +1 -0
- package/package.json +1 -2
- package/dist/scripts/encryptFile.d.ts +0 -21
- package/dist/scripts/encryptFile.d.ts.map +0 -1
- package/dist/scripts/encryptFile.js +0 -101
- package/dist/scripts/encryptFile.js.map +0 -1
- package/dist/src/browserState.d.ts +0 -8
- package/dist/src/browserState.d.ts.map +0 -1
- package/dist/src/browserState.js +0 -21
- package/dist/src/browserState.js.map +0 -1
package/README.md
CHANGED
|
@@ -46,8 +46,11 @@ for details.
|
|
|
46
46
|
|
|
47
47
|
```
|
|
48
48
|
npm install -g latchkey
|
|
49
|
+
latchkey ensure-browser
|
|
49
50
|
```
|
|
50
51
|
|
|
52
|
+
The `ensure-browser` command discovers and configures a browser for Latchkey to use. It searches for Chrome, Chromium, or Edge on your system. If none is found, it downloads Chromium via Playwright.
|
|
53
|
+
|
|
51
54
|
**nvm users**: Global packages are per node version. If you switch versions, reinstall with `npm install -g latchkey`
|
|
52
55
|
|
|
53
56
|
## Integrations
|
|
@@ -75,6 +78,15 @@ mkdir -p ~/.codex/skills/latchkey
|
|
|
75
78
|
cp integrations/SKILL.md ~/.codex/skills/latchkey/SKILL.md
|
|
76
79
|
```
|
|
77
80
|
|
|
81
|
+
### Passepartout
|
|
82
|
+
|
|
83
|
+
Check out our [Passepartout demo app](https://github.com/imbue-ai/passepartout) for an idea of how to build AI assistants for non-technical users on top of Latchkey.
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Demo
|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
78
90
|
|
|
79
91
|
## Direct usage
|
|
80
92
|
|
|
@@ -155,13 +167,17 @@ containing stored API credentials
|
|
|
155
167
|
containing the state (cookies, local storage, etc.) of
|
|
156
168
|
the browser used for the login popup
|
|
157
169
|
- `LATCHKEY_CURL_PATH`: path to the curl binary
|
|
170
|
+
- `LATCHKEY_CONFIG`: path to the configuration file
|
|
171
|
+
(defaults to `~/.latchkey/config.json`)
|
|
158
172
|
- `LATCHKEY_KEYRING_SERVICE_NAME`, `LATCHKEY_KEYRING_ACCOUNT_NAME`: identifiers that are used to store the encryption password in your keyring
|
|
159
173
|
|
|
160
174
|
|
|
161
175
|
## Disclaimers
|
|
162
176
|
|
|
177
|
+
- This is still a work in progress.
|
|
178
|
+
- Latchkey has been created with the help of AI-assisted coding tools with careful human curation.
|
|
163
179
|
- Invoking `latchkey curl ...` can sometimes have side effects in the form of
|
|
164
|
-
new API keys being created
|
|
180
|
+
new API keys being created in your accounts (through browser automation).
|
|
165
181
|
- Using agents for automated access may be prohibited by some services' ToS.
|
|
166
182
|
- We reserve the right to change the license of future releases of Latchkey.
|
|
167
183
|
- Latchkey was not tested on Windows.
|
|
@@ -159,7 +159,7 @@ async function record(serviceName, recordingName = DEFAULT_RECORDING_NAME) {
|
|
|
159
159
|
serviceName: CONFIG.serviceName,
|
|
160
160
|
accountName: CONFIG.accountName,
|
|
161
161
|
});
|
|
162
|
-
await withTempBrowserContext(encryptedStorage, browserStatePath, async ({ context }) => {
|
|
162
|
+
await withTempBrowserContext(encryptedStorage, { browserStatePath }, async ({ context }) => {
|
|
163
163
|
const page = await context.newPage();
|
|
164
164
|
// Register response handler to capture all requests and responses
|
|
165
165
|
page.on('response', (response) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recordBrowserSession.js","sourceRoot":"","sources":["../../scripts/recordBrowserSession.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"recordBrowserSession.js","sourceRoot":"","sources":["../../scripts/recordBrowserSession.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,iCAAiC;AACjC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,+CAA+C;AAC/C,MAAM,oBAAoB,GAAG,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAE9D,6BAA6B;AAC7B,MAAM,sBAAsB,GAAG,oBAAoB,CAAC;AAEpD,MAAM,mBAAoB,SAAQ,KAAK;IACrC,YAAY,WAAmB;QAC7B,KAAK,CAAC,oBAAoB,WAAW,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED,0DAA0D;AAC1D,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAEjF,yBAAyB;AACzB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAuB1F;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,GAAW;IACpC,IAAI,QAAgB,CAAC;IACrB,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,gCAAgC;IAChC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAElC,sDAAsD;IACtD,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACtC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,UAAkB,EAAE,UAAkB;IAC9D,IAAI,eAAuB,CAAC;IAC5B,IAAI,CAAC;QACH,eAAe,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,eAAe,KAAK,UAAU,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC;AACtF,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAC3B,QAAkB,EAClB,eAAgC,EAChC,SAA4B,EAC5B,UAAkB;IAElB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;IAEnC,0CAA0C;IAC1C,IAAI,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC;QACvD,OAAO;IACT,CAAC;IAED,oCAAoC;IACpC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC;QACjD,OAAO;IACT,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QAC1B,SAAS,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC;IAEjD,MAAM,WAAW,GAAgB;QAC/B,YAAY,EAAE,WAAW;QACzB,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;QACxB,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;QAClB,OAAO,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE;QACnC,aAAa,EAAE,OAAO,CAAC,YAAY,EAAE;KACtC,CAAC;IAEF,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QACpC,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,WAAW,CAAC,SAAS,GAAG,QAAQ,CAAC;QACnC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IAED,MAAM,YAAY,GAAiB;QACjC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE;QACzB,WAAW,EAAE,QAAQ,CAAC,UAAU,EAAE;QAClC,OAAO,EAAE,MAAM,QAAQ,CAAC,UAAU,EAAE;KACrC,CAAC;IAEF,yDAAyD;IACzD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;IAED,eAAe,CAAC,IAAI,CAAC;QACnB,OAAO,EAAE,WAAW;QACpB,QAAQ,EAAE,YAAY;KACvB,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM,CACnB,WAAmB,EACnB,gBAAwB,sBAAsB;IAE9C,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAChD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,eAAe,GAAG,IAAI,CAAC,oBAAoB,EAAE,WAAW,CAAC,CAAC;IAChE,SAAS,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;IAE1D,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;IAEjD,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEvD,OAAO,CAAC,GAAG,CAAC,gCAAgC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,cAAc,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,0BAA0B,UAAU,mBAAmB,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,qBAAqB,eAAe,EAAE,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,kBAAkB,gBAAgB,EAAE,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IAElF,MAAM,eAAe,GAAoB,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAE/B,MAAM,gBAAgB,GAAG,IAAI,gBAAgB,CAAC;QAC5C,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAC;IAEH,MAAM,sBAAsB,CAAC,gBAAgB,EAAE,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;QACzF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAErC,kEAAkE;QAClE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC/B,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC1E,qCAAqC;YACvC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAElC,qCAAqC;QACrC,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,wBAAwB;IACxB,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAEtE,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,oBAAoB,YAAY,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,yBAAyB,CAAC,CAAC;AACrF,CAAC;AAED,mBAAmB;AACnB,KAAK,UAAU,IAAI;IACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAClE,OAAO,CAAC,GAAG,CAAC,gFAAgF,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,OAAO,CAAC,GAAG,CACT,sFAAsF,CACvF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;IAC7B,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC;IAExD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,mBAAmB,EAAE,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;YACzC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;YACrC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACxC,OAAO,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
|
|
@@ -9,7 +9,16 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { z } from 'zod';
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
12
|
+
* Browser sources that can be used for discovery.
|
|
13
|
+
*/
|
|
14
|
+
export declare const BROWSER_SOURCES: readonly ["existing-config", "system-browser", "existing-playwright-browser", "download-playwright-browser"];
|
|
15
|
+
export type BrowserSource = (typeof BROWSER_SOURCES)[number];
|
|
16
|
+
/**
|
|
17
|
+
* Default order for browser source discovery.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_BROWSER_SOURCES: readonly BrowserSource[];
|
|
20
|
+
/**
|
|
21
|
+
* Schema for the browser configuration.
|
|
13
22
|
*/
|
|
14
23
|
declare const BrowserConfigSchema: z.ZodObject<{
|
|
15
24
|
executablePath: z.ZodString;
|
|
@@ -32,9 +41,9 @@ export declare class BrowserConfigError extends Error {
|
|
|
32
41
|
constructor(message: string);
|
|
33
42
|
}
|
|
34
43
|
/**
|
|
35
|
-
* Get the default path for the
|
|
44
|
+
* Get the default path for the configuration file.
|
|
36
45
|
*/
|
|
37
|
-
export declare function
|
|
46
|
+
export declare function getDefaultConfigPath(): string;
|
|
38
47
|
/**
|
|
39
48
|
* Find a system-installed Chrome/Chromium browser.
|
|
40
49
|
* Returns the path to the executable if found, null otherwise.
|
|
@@ -44,28 +53,25 @@ export declare function findSystemBrowser(): string | null;
|
|
|
44
53
|
* Find Chrome/Chromium installed by Playwright.
|
|
45
54
|
* Returns the path to the executable if found, null otherwise.
|
|
46
55
|
*/
|
|
47
|
-
export declare function findPlaywrightBrowser():
|
|
56
|
+
export declare function findPlaywrightBrowser(): string | null;
|
|
48
57
|
/**
|
|
49
|
-
* Download Chromium using
|
|
58
|
+
* Download Chromium using a direct download mechanism.
|
|
59
|
+
*
|
|
60
|
+
* This implementation downloads Chromium without using Playwright's
|
|
61
|
+
* installBrowsersForNpmInstall, which uses childProcess.fork() - a mechanism
|
|
62
|
+
* not supported when Latchkey is compiled with Bun.
|
|
63
|
+
*
|
|
50
64
|
* Returns the path to the downloaded executable.
|
|
51
65
|
*/
|
|
52
66
|
export declare function downloadPlaywrightBrowser(): Promise<string>;
|
|
53
67
|
/**
|
|
54
|
-
*
|
|
55
|
-
|
|
56
|
-
export interface DiscoverBrowserOptions {
|
|
57
|
-
/** Skip discovery of system-installed browsers. Default: false */
|
|
58
|
-
skipSystemBrowser?: boolean;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Discover a Chrome/Chromium browser using the following priority:
|
|
62
|
-
* 1. System-installed browser (unless skipSystemBrowser is true)
|
|
63
|
-
* 2. Playwright's bundled browser
|
|
64
|
-
* 3. Download via Playwright
|
|
65
|
-
*
|
|
66
|
-
* Returns the browser configuration with the discovered path.
|
|
68
|
+
* Discover a browser by trying sources in the specified order.
|
|
69
|
+
* Returns the first successful result, or throws if none succeed.
|
|
67
70
|
*/
|
|
68
|
-
export declare function
|
|
71
|
+
export declare function discoverBrowserFromSources(sources: readonly BrowserSource[], configPath: string): Promise<{
|
|
72
|
+
config: BrowserConfig;
|
|
73
|
+
source: BrowserSource;
|
|
74
|
+
}>;
|
|
69
75
|
/**
|
|
70
76
|
* Save browser configuration to disk.
|
|
71
77
|
*/
|
|
@@ -77,14 +83,11 @@ export declare function saveBrowserConfig(configPath: string, config: BrowserCon
|
|
|
77
83
|
export declare function loadBrowserConfig(configPath: string): BrowserConfig | null;
|
|
78
84
|
/**
|
|
79
85
|
* Ensure a browser is available and return its configuration.
|
|
80
|
-
*
|
|
81
|
-
* Otherwise, a new browser is discovered and the configuration is saved.
|
|
86
|
+
* Tries sources in the specified order, saves the result to the config file.
|
|
82
87
|
*/
|
|
83
|
-
export declare function ensureBrowser(configPath?: string,
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
*/
|
|
88
|
-
export declare function getBrowserExecutablePath(configPath?: string): string | null;
|
|
88
|
+
export declare function ensureBrowser(configPath?: string, sources?: readonly BrowserSource[]): Promise<{
|
|
89
|
+
config: BrowserConfig;
|
|
90
|
+
source: BrowserSource;
|
|
91
|
+
}>;
|
|
89
92
|
export {};
|
|
90
93
|
//# sourceMappingURL=browserConfig.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserConfig.d.ts","sourceRoot":"","sources":["../../src/browserConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"browserConfig.d.ts","sourceRoot":"","sources":["../../src/browserConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;GAEG;AACH,eAAO,MAAM,eAAe,8GAKlB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7D;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,SAAS,aAAa,EAK3D,CAAC;AAEF;;GAEG;AACH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;EAIvB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAShE,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAyDD;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,GAAG,IAAI,CA2BjD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,GAAG,IAAI,CAMrD;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,MAAM,CAAC,CAEjE;AA8CD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,CAS3D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAoBjF;AA+BD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAE1E;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,UAAU,GAAE,MAA+B,EAC3C,OAAO,GAAE,SAAS,aAAa,EAA4B,GAC1D,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,CAAC,CAS3D"}
|
|
@@ -10,16 +10,41 @@
|
|
|
10
10
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
11
11
|
import { homedir, platform } from 'node:os';
|
|
12
12
|
import { dirname, join } from 'node:path';
|
|
13
|
+
import { chromium } from 'playwright';
|
|
13
14
|
import { z } from 'zod';
|
|
14
|
-
import {
|
|
15
|
+
import { downloadChromium } from './playwrightDownload.js';
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* Browser sources that can be used for discovery.
|
|
18
|
+
*/
|
|
19
|
+
export const BROWSER_SOURCES = [
|
|
20
|
+
'existing-config',
|
|
21
|
+
'system-browser',
|
|
22
|
+
'existing-playwright-browser',
|
|
23
|
+
'download-playwright-browser',
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Default order for browser source discovery.
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_BROWSER_SOURCES = [
|
|
29
|
+
'existing-config',
|
|
30
|
+
'system-browser',
|
|
31
|
+
'existing-playwright-browser',
|
|
32
|
+
'download-playwright-browser',
|
|
33
|
+
];
|
|
34
|
+
/**
|
|
35
|
+
* Schema for the browser configuration.
|
|
17
36
|
*/
|
|
18
37
|
const BrowserConfigSchema = z.object({
|
|
19
38
|
executablePath: z.string(),
|
|
20
39
|
source: z.enum(['system', 'playwright', 'downloaded']),
|
|
21
40
|
discoveredAt: z.string().datetime(),
|
|
22
41
|
});
|
|
42
|
+
/**
|
|
43
|
+
* Schema for the top-level configuration file.
|
|
44
|
+
*/
|
|
45
|
+
const ConfigFileSchema = z.object({
|
|
46
|
+
browser: BrowserConfigSchema.optional(),
|
|
47
|
+
});
|
|
23
48
|
export class BrowserNotFoundError extends Error {
|
|
24
49
|
constructor(message) {
|
|
25
50
|
super(message);
|
|
@@ -33,16 +58,16 @@ export class BrowserConfigError extends Error {
|
|
|
33
58
|
}
|
|
34
59
|
}
|
|
35
60
|
/**
|
|
36
|
-
* Get the default path for the
|
|
61
|
+
* Get the default path for the configuration file.
|
|
37
62
|
*/
|
|
38
|
-
export function
|
|
39
|
-
return join(homedir(), '.latchkey', '
|
|
63
|
+
export function getDefaultConfigPath() {
|
|
64
|
+
return join(homedir(), '.latchkey', 'config.json');
|
|
40
65
|
}
|
|
41
66
|
/**
|
|
42
|
-
* System Chrome/Chromium installation paths by platform.
|
|
67
|
+
* System Chrome/Chromium/Edge installation paths by platform.
|
|
43
68
|
* These are the standard locations where browsers are installed.
|
|
44
69
|
*/
|
|
45
|
-
const
|
|
70
|
+
const SYSTEM_BROWSER_PATHS = {
|
|
46
71
|
darwin: [
|
|
47
72
|
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
48
73
|
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
|
|
@@ -89,24 +114,13 @@ function getWindowsPrefixes() {
|
|
|
89
114
|
}
|
|
90
115
|
return prefixes;
|
|
91
116
|
}
|
|
92
|
-
/**
|
|
93
|
-
* Check if a file exists and is accessible.
|
|
94
|
-
*/
|
|
95
|
-
function canAccessFile(filePath) {
|
|
96
|
-
try {
|
|
97
|
-
return existsSync(filePath);
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
117
|
/**
|
|
104
118
|
* Find a system-installed Chrome/Chromium browser.
|
|
105
119
|
* Returns the path to the executable if found, null otherwise.
|
|
106
120
|
*/
|
|
107
121
|
export function findSystemBrowser() {
|
|
108
122
|
const currentPlatform = platform();
|
|
109
|
-
const paths =
|
|
123
|
+
const paths = SYSTEM_BROWSER_PATHS[currentPlatform];
|
|
110
124
|
if (!paths) {
|
|
111
125
|
return null;
|
|
112
126
|
}
|
|
@@ -115,7 +129,7 @@ export function findSystemBrowser() {
|
|
|
115
129
|
for (const prefix of prefixes) {
|
|
116
130
|
for (const suffix of paths) {
|
|
117
131
|
const fullPath = join(prefix, suffix);
|
|
118
|
-
if (
|
|
132
|
+
if (existsSync(fullPath)) {
|
|
119
133
|
return fullPath;
|
|
120
134
|
}
|
|
121
135
|
}
|
|
@@ -123,7 +137,7 @@ export function findSystemBrowser() {
|
|
|
123
137
|
}
|
|
124
138
|
else {
|
|
125
139
|
for (const path of paths) {
|
|
126
|
-
if (
|
|
140
|
+
if (existsSync(path)) {
|
|
127
141
|
return path;
|
|
128
142
|
}
|
|
129
143
|
}
|
|
@@ -134,70 +148,77 @@ export function findSystemBrowser() {
|
|
|
134
148
|
* Find Chrome/Chromium installed by Playwright.
|
|
135
149
|
* Returns the path to the executable if found, null otherwise.
|
|
136
150
|
*/
|
|
137
|
-
export
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (executablePath && canAccessFile(executablePath)) {
|
|
142
|
-
return executablePath;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
catch {
|
|
146
|
-
// Playwright not available or browser not installed
|
|
151
|
+
export function findPlaywrightBrowser() {
|
|
152
|
+
const executablePath = chromium.executablePath();
|
|
153
|
+
if (executablePath && existsSync(executablePath)) {
|
|
154
|
+
return executablePath;
|
|
147
155
|
}
|
|
148
156
|
return null;
|
|
149
157
|
}
|
|
150
158
|
/**
|
|
151
|
-
* Download Chromium using
|
|
159
|
+
* Download Chromium using a direct download mechanism.
|
|
160
|
+
*
|
|
161
|
+
* This implementation downloads Chromium without using Playwright's
|
|
162
|
+
* installBrowsersForNpmInstall, which uses childProcess.fork() - a mechanism
|
|
163
|
+
* not supported when Latchkey is compiled with Bun.
|
|
164
|
+
*
|
|
152
165
|
* Returns the path to the downloaded executable.
|
|
153
166
|
*/
|
|
154
167
|
export async function downloadPlaywrightBrowser() {
|
|
155
|
-
|
|
156
|
-
await installBrowsersForNpmInstall(['chromium']);
|
|
157
|
-
// After installation, get the path
|
|
158
|
-
const browserPath = await findPlaywrightBrowser();
|
|
159
|
-
if (!browserPath) {
|
|
160
|
-
throw new BrowserNotFoundError('Failed to locate Chromium after download. The installation may have failed.');
|
|
161
|
-
}
|
|
162
|
-
return browserPath;
|
|
168
|
+
return downloadChromium();
|
|
163
169
|
}
|
|
164
170
|
/**
|
|
165
|
-
*
|
|
166
|
-
* 1. System-installed browser (unless skipSystemBrowser is true)
|
|
167
|
-
* 2. Playwright's bundled browser
|
|
168
|
-
* 3. Download via Playwright
|
|
169
|
-
*
|
|
170
|
-
* Returns the browser configuration with the discovered path.
|
|
171
|
+
* Try a single browser source and return the config if successful, null otherwise.
|
|
171
172
|
*/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
173
|
+
async function tryBrowserSource(source, configPath) {
|
|
174
|
+
switch (source) {
|
|
175
|
+
case 'existing-config': {
|
|
176
|
+
return loadBrowserConfigInternal(configPath);
|
|
177
|
+
}
|
|
178
|
+
case 'system-browser': {
|
|
179
|
+
const systemPath = findSystemBrowser();
|
|
180
|
+
if (systemPath) {
|
|
181
|
+
return {
|
|
182
|
+
executablePath: systemPath,
|
|
183
|
+
source: 'system',
|
|
184
|
+
discoveredAt: new Date().toISOString(),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
case 'existing-playwright-browser': {
|
|
190
|
+
const playwrightPath = findPlaywrightBrowser();
|
|
191
|
+
if (playwrightPath) {
|
|
192
|
+
return {
|
|
193
|
+
executablePath: playwrightPath,
|
|
194
|
+
source: 'playwright',
|
|
195
|
+
discoveredAt: new Date().toISOString(),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
case 'download-playwright-browser': {
|
|
201
|
+
const downloadedPath = await downloadPlaywrightBrowser();
|
|
178
202
|
return {
|
|
179
|
-
executablePath:
|
|
180
|
-
source: '
|
|
203
|
+
executablePath: downloadedPath,
|
|
204
|
+
source: 'downloaded',
|
|
181
205
|
discoveredAt: new Date().toISOString(),
|
|
182
206
|
};
|
|
183
207
|
}
|
|
184
208
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Discover a browser by trying sources in the specified order.
|
|
212
|
+
* Returns the first successful result, or throws if none succeed.
|
|
213
|
+
*/
|
|
214
|
+
export async function discoverBrowserFromSources(sources, configPath) {
|
|
215
|
+
for (const source of sources) {
|
|
216
|
+
const config = await tryBrowserSource(source, configPath);
|
|
217
|
+
if (config) {
|
|
218
|
+
return { config, source };
|
|
219
|
+
}
|
|
193
220
|
}
|
|
194
|
-
|
|
195
|
-
const downloadedPath = await downloadPlaywrightBrowser();
|
|
196
|
-
return {
|
|
197
|
-
executablePath: downloadedPath,
|
|
198
|
-
source: 'downloaded',
|
|
199
|
-
discoveredAt: new Date().toISOString(),
|
|
200
|
-
};
|
|
221
|
+
throw new BrowserNotFoundError(`No browser found after trying sources: ${sources.join(', ')}`);
|
|
201
222
|
}
|
|
202
223
|
/**
|
|
203
224
|
* Save browser configuration to disk.
|
|
@@ -207,53 +228,63 @@ export function saveBrowserConfig(configPath, config) {
|
|
|
207
228
|
if (!existsSync(directory)) {
|
|
208
229
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
209
230
|
}
|
|
210
|
-
|
|
231
|
+
// Load existing config file if it exists, to preserve other settings
|
|
232
|
+
let existingConfig = {};
|
|
233
|
+
if (existsSync(configPath)) {
|
|
234
|
+
try {
|
|
235
|
+
const existingContent = readFileSync(configPath, 'utf-8');
|
|
236
|
+
existingConfig = JSON.parse(existingContent);
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Ignore parse errors, start fresh
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const newConfig = { ...existingConfig, browser: config };
|
|
243
|
+
const content = JSON.stringify(newConfig, null, 2);
|
|
211
244
|
writeFileSync(configPath, content, { encoding: 'utf-8', mode: 0o600 });
|
|
212
245
|
}
|
|
213
246
|
/**
|
|
214
|
-
*
|
|
215
|
-
* Returns null if the file doesn't exist or
|
|
247
|
+
* Internal function to load browser configuration from disk.
|
|
248
|
+
* Returns null if the file doesn't exist, is invalid, or the browser no longer exists.
|
|
216
249
|
*/
|
|
217
|
-
|
|
250
|
+
function loadBrowserConfigInternal(configPath) {
|
|
218
251
|
if (!existsSync(configPath)) {
|
|
219
252
|
return null;
|
|
220
253
|
}
|
|
221
254
|
try {
|
|
222
255
|
const content = readFileSync(configPath, 'utf-8');
|
|
223
256
|
const data = JSON.parse(content);
|
|
224
|
-
const
|
|
257
|
+
const configFile = ConfigFileSchema.parse(data);
|
|
258
|
+
if (!configFile.browser) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
225
261
|
// Verify the browser still exists
|
|
226
|
-
if (!
|
|
262
|
+
if (!existsSync(configFile.browser.executablePath)) {
|
|
227
263
|
return null;
|
|
228
264
|
}
|
|
229
|
-
return
|
|
265
|
+
return configFile.browser;
|
|
230
266
|
}
|
|
231
267
|
catch {
|
|
232
268
|
return null;
|
|
233
269
|
}
|
|
234
270
|
}
|
|
235
271
|
/**
|
|
236
|
-
*
|
|
237
|
-
*
|
|
238
|
-
* Otherwise, a new browser is discovered and the configuration is saved.
|
|
272
|
+
* Load browser configuration from disk.
|
|
273
|
+
* Returns null if the file doesn't exist or is invalid.
|
|
239
274
|
*/
|
|
240
|
-
export
|
|
241
|
-
|
|
242
|
-
const existingConfig = loadBrowserConfig(configPath);
|
|
243
|
-
if (existingConfig) {
|
|
244
|
-
return existingConfig;
|
|
245
|
-
}
|
|
246
|
-
// Discover and save new configuration
|
|
247
|
-
const config = await discoverBrowser(options);
|
|
248
|
-
saveBrowserConfig(configPath, config);
|
|
249
|
-
return config;
|
|
275
|
+
export function loadBrowserConfig(configPath) {
|
|
276
|
+
return loadBrowserConfigInternal(configPath);
|
|
250
277
|
}
|
|
251
278
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
279
|
+
* Ensure a browser is available and return its configuration.
|
|
280
|
+
* Tries sources in the specified order, saves the result to the config file.
|
|
254
281
|
*/
|
|
255
|
-
export function
|
|
256
|
-
const
|
|
257
|
-
|
|
282
|
+
export async function ensureBrowser(configPath = getDefaultConfigPath(), sources = DEFAULT_BROWSER_SOURCES) {
|
|
283
|
+
const result = await discoverBrowserFromSources(sources, configPath);
|
|
284
|
+
// Save to config file unless we just loaded from existing config
|
|
285
|
+
if (result.source !== 'existing-config') {
|
|
286
|
+
saveBrowserConfig(configPath, result.config);
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
258
289
|
}
|
|
259
290
|
//# sourceMappingURL=browserConfig.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserConfig.js","sourceRoot":"","sources":["../../src/browserConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"browserConfig.js","sourceRoot":"","sources":["../../src/browserConfig.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
CHANGED
|
@@ -19,7 +19,7 @@ catch (error) {
|
|
|
19
19
|
program
|
|
20
20
|
.name('latchkey')
|
|
21
21
|
.description('A command-line tool that injects API credentials to curl requests to known public APIs.')
|
|
22
|
-
.version('0.1.
|
|
22
|
+
.version('0.1.4');
|
|
23
23
|
registerCommands(program, deps);
|
|
24
24
|
program.parse();
|
|
25
25
|
//# sourceMappingURL=cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cliCommands.d.ts","sourceRoot":"","sources":["../../src/cliCommands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cliCommands.d.ts","sourceRoot":"","sources":["../../src/cliCommands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAazC,OAAO,EAAE,MAAM,EAAU,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAE,QAAQ,EAAY,MAAM,eAAe,CAAC;AAOnD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,KAAK,UAAU,CAAC;IAC1D,QAAQ,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,CAAC;IACvC,QAAQ,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,eAAe,CAc3D;AAMD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAyBzE;AAyGD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI,CAkM9E"}
|