mastracode 0.8.3 → 0.9.0-alpha.1
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 +33 -0
- package/README.md +12 -7
- package/dist/auth/storage.d.ts +20 -0
- package/dist/auth/storage.d.ts.map +1 -1
- package/dist/{chunk-S5ZLN7DR.cjs → chunk-45H2FFSL.cjs} +42 -2
- package/dist/chunk-45H2FFSL.cjs.map +1 -0
- package/dist/{chunk-PRMDKRZD.cjs → chunk-AI65TXWQ.cjs} +1664 -1031
- package/dist/chunk-AI65TXWQ.cjs.map +1 -0
- package/dist/{chunk-3ZIPVVJW.cjs → chunk-C7K52PPG.cjs} +234 -52
- package/dist/chunk-C7K52PPG.cjs.map +1 -0
- package/dist/{chunk-SM3QCOA7.js → chunk-GTRZ4DPO.js} +42 -2
- package/dist/chunk-GTRZ4DPO.js.map +1 -0
- package/dist/{chunk-7KVALECK.js → chunk-LSC42LC7.js} +1236 -603
- package/dist/chunk-LSC42LC7.js.map +1 -0
- package/dist/{chunk-MQUL5ENJ.cjs → chunk-M5VHYX23.cjs} +49 -36
- package/dist/chunk-M5VHYX23.cjs.map +1 -0
- package/dist/{chunk-ULS3HP2Y.js → chunk-O7R6WVSY.js} +20 -7
- package/dist/chunk-O7R6WVSY.js.map +1 -0
- package/dist/{chunk-BHG6IWIR.js → chunk-UUS7G74S.js} +225 -51
- package/dist/chunk-UUS7G74S.js.map +1 -0
- package/dist/cli.cjs +37 -19
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +28 -9
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/storage-HJALULMH.cjs +24 -0
- package/dist/{storage-PO4VN5NF.cjs.map → storage-HJALULMH.cjs.map} +1 -1
- package/dist/storage-R76IXKUI.js +3 -0
- package/dist/{storage-PQOHJLBI.js.map → storage-R76IXKUI.js.map} +1 -1
- package/dist/tui/command-dispatch.d.ts.map +1 -1
- package/dist/tui/commands/models-pack.d.ts.map +1 -1
- package/dist/tui/commands/om.d.ts.map +1 -1
- package/dist/tui/commands/subagents.d.ts.map +1 -1
- package/dist/tui/commands/theme.d.ts.map +1 -1
- package/dist/tui/components/api-key-dialog.d.ts +28 -0
- package/dist/tui/components/api-key-dialog.d.ts.map +1 -0
- package/dist/tui/components/ask-question-inline.d.ts +50 -6
- package/dist/tui/components/ask-question-inline.d.ts.map +1 -1
- package/dist/tui/components/assistant-message.d.ts.map +1 -1
- package/dist/tui/components/custom-editor.d.ts +5 -1
- package/dist/tui/components/custom-editor.d.ts.map +1 -1
- package/dist/tui/components/diff-output.d.ts.map +1 -1
- package/dist/tui/components/error-display.d.ts.map +1 -1
- package/dist/tui/components/help-overlay.d.ts.map +1 -1
- package/dist/tui/components/obi-loader.d.ts +1 -1
- package/dist/tui/components/obi-loader.d.ts.map +1 -1
- package/dist/tui/components/om-marker.d.ts.map +1 -1
- package/dist/tui/components/om-output.d.ts.map +1 -1
- package/dist/tui/components/om-progress.d.ts.map +1 -1
- package/dist/tui/components/om-settings.d.ts +3 -3
- package/dist/tui/components/om-settings.d.ts.map +1 -1
- package/dist/tui/components/plan-approval-inline.d.ts.map +1 -1
- package/dist/tui/components/slash-command.d.ts.map +1 -1
- package/dist/tui/components/system-reminder.d.ts.map +1 -1
- package/dist/tui/components/tool-execution-enhanced.d.ts +5 -1
- package/dist/tui/components/tool-execution-enhanced.d.ts.map +1 -1
- package/dist/tui/components/user-message.d.ts +1 -1
- package/dist/tui/components/user-message.d.ts.map +1 -1
- package/dist/tui/detect-theme.d.ts +6 -1
- package/dist/tui/detect-theme.d.ts.map +1 -1
- package/dist/tui/event-dispatch.d.ts.map +1 -1
- package/dist/tui/handlers/agent-lifecycle.d.ts.map +1 -1
- package/dist/tui/handlers/message.d.ts +6 -0
- package/dist/tui/handlers/message.d.ts.map +1 -1
- package/dist/tui/handlers/prompts.d.ts.map +1 -1
- package/dist/tui/handlers/tool.d.ts +7 -0
- package/dist/tui/handlers/tool.d.ts.map +1 -1
- package/dist/tui/handlers/types.d.ts +1 -0
- package/dist/tui/handlers/types.d.ts.map +1 -1
- package/dist/tui/mastra-tui.d.ts +1 -0
- package/dist/tui/mastra-tui.d.ts.map +1 -1
- package/dist/tui/prompt-api-key.d.ts +15 -0
- package/dist/tui/prompt-api-key.d.ts.map +1 -0
- package/dist/tui/render-messages.d.ts.map +1 -1
- package/dist/tui/setup.d.ts +1 -0
- package/dist/tui/setup.d.ts.map +1 -1
- package/dist/tui/state.d.ts +16 -4
- package/dist/tui/state.d.ts.map +1 -1
- package/dist/tui/status-line.d.ts.map +1 -1
- package/dist/tui/theme.d.ts +73 -4
- package/dist/tui/theme.d.ts.map +1 -1
- package/dist/tui.cjs +19 -19
- package/dist/tui.js +2 -2
- package/package.json +11 -11
- package/dist/chunk-3ZIPVVJW.cjs.map +0 -1
- package/dist/chunk-7KVALECK.js.map +0 -1
- package/dist/chunk-BHG6IWIR.js.map +0 -1
- package/dist/chunk-MQUL5ENJ.cjs.map +0 -1
- package/dist/chunk-PRMDKRZD.cjs.map +0 -1
- package/dist/chunk-S5ZLN7DR.cjs.map +0 -1
- package/dist/chunk-SM3QCOA7.js.map +0 -1
- package/dist/chunk-ULS3HP2Y.js.map +0 -1
- package/dist/storage-PO4VN5NF.cjs +0 -24
- package/dist/storage-PQOHJLBI.js +0 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# mastracode
|
|
2
2
|
|
|
3
|
+
## 0.9.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added adaptive light and dark terminal themes with WCAG-compliant contrast. Editor input, messages, tool output, and interactive components now automatically adjust colors and borders for readability across terminal backgrounds. ([#14337](https://github.com/mastra-ai/mastra/pull/14337))
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Fix rendering corruption in some terminal emulators by replacing the per-character gradient animation on the editor input border with a solid mode-color border. ([#14359](https://github.com/mastra-ai/mastra/pull/14359))
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`b77aa19`](https://github.com/mastra-ai/mastra/commit/b77aa1981361c021f2c881bee8f0c703687f00da), [`dd6ca1c`](https://github.com/mastra-ai/mastra/commit/dd6ca1cdea3b8b6182f4cf61df41070ba0cc0deb), [`4cb4edf`](https://github.com/mastra-ai/mastra/commit/4cb4edf3c909d197ec356c1790d13270514ffef6)]:
|
|
14
|
+
- @mastra/core@1.13.3-alpha.1
|
|
15
|
+
|
|
16
|
+
## 0.9.0-alpha.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
- Added interactive API key prompt when selecting a model without a configured key. When you choose a model from the model selector that lacks an API key, Mastra Code now displays a dialog to enter the key. The key is stored persistently in auth.json and loaded into the environment on subsequent startups. Environment variables always take priority over stored keys. Press Escape to dismiss the prompt and keep the previous behavior. ([#13573](https://github.com/mastra-ai/mastra/pull/13573))
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- Improved Mastra Code terminal queueing and slash-command behavior while the agent is busy. ([#14250](https://github.com/mastra-ai/mastra/pull/14250))
|
|
25
|
+
- Press `Enter` to send a message normally, or queue a follow-up while the current run is still streaming.
|
|
26
|
+
- Queued follow-up messages and slash commands now drain in the same FIFO order they were entered.
|
|
27
|
+
- Custom slash commands use `//command` so they stay distinct from built-in `/command` entries, including when names overlap.
|
|
28
|
+
- Slash-command autocomplete now defaults to the first visible matching entry instead of jumping to a later custom command match.
|
|
29
|
+
- `/help` and related shortcut text now reflect the updated behavior.
|
|
30
|
+
|
|
31
|
+
- Updated dependencies [[`51970b3`](https://github.com/mastra-ai/mastra/commit/51970b3828494d59a8dd4df143b194d37d31e3f5), [`bbcbbce`](https://github.com/mastra-ai/mastra/commit/bbcbbce4f0e268053cbb11ca58350f5ceba15498), [`085e371`](https://github.com/mastra-ai/mastra/commit/085e3718a7d0fe9a210fe7dd1c867b9bdfe8d16b), [`ce26fe2`](https://github.com/mastra-ai/mastra/commit/ce26fe2166dd90254f8bee5776e55977143e97de), [`b26307f`](https://github.com/mastra-ai/mastra/commit/b26307f050df39629511b0e831b8fc26973ce8b1)]:
|
|
32
|
+
- @mastra/core@1.13.3-alpha.0
|
|
33
|
+
- @mastra/mcp@1.2.2-alpha.0
|
|
34
|
+
- @mastra/memory@1.8.3-alpha.0
|
|
35
|
+
|
|
3
36
|
## 0.8.3
|
|
4
37
|
|
|
5
38
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -60,7 +60,7 @@ On Ubuntu/Debian the binary is called `fdfind` — mastracode detects both `fd`
|
|
|
60
60
|
|
|
61
61
|
### Starting a conversation
|
|
62
62
|
|
|
63
|
-
Type your message and press Enter.
|
|
63
|
+
Type your message and press Enter. If the agent is already working, Enter queues your next message and sends it after the current run finishes.
|
|
64
64
|
|
|
65
65
|
### `@` file references
|
|
66
66
|
|
|
@@ -105,12 +105,17 @@ Select a suggestion with arrow keys and press Tab to insert it.
|
|
|
105
105
|
|
|
106
106
|
### Keyboard shortcuts
|
|
107
107
|
|
|
108
|
-
| Shortcut
|
|
109
|
-
|
|
|
110
|
-
| `Ctrl+C`
|
|
111
|
-
| `Ctrl+
|
|
112
|
-
| `Ctrl+
|
|
113
|
-
| `Ctrl+
|
|
108
|
+
| Shortcut | Action |
|
|
109
|
+
| ----------- | --------------------------------------------------------------- |
|
|
110
|
+
| `Ctrl+C` | Interrupt current operation or clear input |
|
|
111
|
+
| `Ctrl+C` ×2 | Exit (double-tap) |
|
|
112
|
+
| `Ctrl+D` | Exit (when editor is empty) |
|
|
113
|
+
| `Ctrl+Z` | Suspend process (`fg` to resume) |
|
|
114
|
+
| `Alt+Z` | Undo last clear |
|
|
115
|
+
| `Ctrl+T` | Toggle thinking blocks visibility |
|
|
116
|
+
| `Ctrl+E` | Expand/collapse all tool outputs |
|
|
117
|
+
| `Enter` | Send a message, or queue a follow-up while the agent is running |
|
|
118
|
+
| `Ctrl+Y` | Toggle YOLO mode |
|
|
114
119
|
|
|
115
120
|
## Configuration
|
|
116
121
|
|
package/dist/auth/storage.d.ts
CHANGED
|
@@ -55,6 +55,26 @@ export declare class AuthStorage {
|
|
|
55
55
|
* Check if logged in via OAuth for a provider.
|
|
56
56
|
*/
|
|
57
57
|
isLoggedIn(provider: string): boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Check if a stored API key exists for a provider.
|
|
60
|
+
* Keys are stored under `apikey:<provider>` in auth.json.
|
|
61
|
+
*/
|
|
62
|
+
hasStoredApiKey(provider: string): boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Get a stored API key for a provider, if any.
|
|
65
|
+
*/
|
|
66
|
+
getStoredApiKey(provider: string): string | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Store an API key for a provider.
|
|
69
|
+
* Also sets the corresponding environment variable so model resolution can find it.
|
|
70
|
+
*/
|
|
71
|
+
setStoredApiKey(provider: string, key: string, envVar?: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* Load all stored API keys into process.env.
|
|
74
|
+
* Called at startup so model resolution can find stored keys.
|
|
75
|
+
* Only sets env vars that aren't already set (env vars take precedence).
|
|
76
|
+
*/
|
|
77
|
+
loadStoredApiKeysIntoEnv(providerEnvVars: Record<string, string | undefined>): void;
|
|
58
78
|
/**
|
|
59
79
|
* Login to an OAuth provider.
|
|
60
80
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACV,cAAc,EAEd,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAGnE,CAAC;AAQF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,eAAe,GAAG,sBAAsB,GAAG,SAAS,CAExF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,sBAAsB,EAAE,CAE5D;AAED;;GAEG;AACH,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,IAAI,CAAuB;gBAEf,QAAQ,GAAE,MAA2C;IAIzE;;OAEG;IACH,MAAM,IAAI,IAAI;IAYd;;OAEG;IACH,OAAO,CAAC,IAAI;IASZ;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIjD;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,GAAG,IAAI;IAKvD;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;IAIhB;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKrC;;OAEG;IACG,KAAK,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvF;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CA8BjE"}
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EACV,cAAc,EAEd,mBAAmB,EACnB,eAAe,EACf,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAGnE,CAAC;AAQF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,eAAe,GAAG,sBAAsB,GAAG,SAAS,CAExF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,sBAAsB,EAAE,CAE5D;AAED;;GAEG;AACH,qBAAa,WAAW;IAGV,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,IAAI,CAAuB;gBAEf,QAAQ,GAAE,MAA2C;IAIzE;;OAEG;IACH,MAAM,IAAI,IAAI;IAYd;;OAEG;IACH,OAAO,CAAC,IAAI;IASZ;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIjD;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,GAAG,IAAI;IAKvD;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK9B;;OAEG;IACH,IAAI,IAAI,MAAM,EAAE;IAIhB;;OAEG;IACH,GAAG,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI9B;;OAEG;IACH,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAKrC;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAK1C;;OAEG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAKrD;;;OAGG;IACH,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI;IAOrE;;;;OAIG;IACH,wBAAwB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI;IAWnF;;OAEG;IACG,KAAK,CAAC,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUvF;;OAEG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACG,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;CA8BjE"}
|
|
@@ -796,6 +796,46 @@ var AuthStorage = class {
|
|
|
796
796
|
const cred = this.data[provider];
|
|
797
797
|
return cred?.type === "oauth";
|
|
798
798
|
}
|
|
799
|
+
/**
|
|
800
|
+
* Check if a stored API key exists for a provider.
|
|
801
|
+
* Keys are stored under `apikey:<provider>` in auth.json.
|
|
802
|
+
*/
|
|
803
|
+
hasStoredApiKey(provider) {
|
|
804
|
+
const cred = this.data[`apikey:${provider}`];
|
|
805
|
+
return cred?.type === "api_key" && cred.key.length > 0;
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* Get a stored API key for a provider, if any.
|
|
809
|
+
*/
|
|
810
|
+
getStoredApiKey(provider) {
|
|
811
|
+
const cred = this.data[`apikey:${provider}`];
|
|
812
|
+
return cred?.type === "api_key" && cred.key.length > 0 ? cred.key : void 0;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Store an API key for a provider.
|
|
816
|
+
* Also sets the corresponding environment variable so model resolution can find it.
|
|
817
|
+
*/
|
|
818
|
+
setStoredApiKey(provider, key, envVar) {
|
|
819
|
+
this.set(`apikey:${provider}`, { type: "api_key", key });
|
|
820
|
+
if (envVar) {
|
|
821
|
+
process.env[envVar] = key;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* Load all stored API keys into process.env.
|
|
826
|
+
* Called at startup so model resolution can find stored keys.
|
|
827
|
+
* Only sets env vars that aren't already set (env vars take precedence).
|
|
828
|
+
*/
|
|
829
|
+
loadStoredApiKeysIntoEnv(providerEnvVars) {
|
|
830
|
+
for (const [key, cred] of Object.entries(this.data)) {
|
|
831
|
+
if (!key.startsWith("apikey:") || cred.type !== "api_key" || !cred.key) continue;
|
|
832
|
+
const provider = key.substring("apikey:".length);
|
|
833
|
+
const envVar = providerEnvVars[provider];
|
|
834
|
+
if (envVar && !process.env[envVar]) {
|
|
835
|
+
process.env[envVar] = cred.key;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
799
839
|
/**
|
|
800
840
|
* Login to an OAuth provider.
|
|
801
841
|
*/
|
|
@@ -853,5 +893,5 @@ exports.getOmScope = getOmScope;
|
|
|
853
893
|
exports.getResourceIdOverride = getResourceIdOverride;
|
|
854
894
|
exports.getStorageConfig = getStorageConfig;
|
|
855
895
|
exports.getUserId = getUserId;
|
|
856
|
-
//# sourceMappingURL=chunk-
|
|
857
|
-
//# sourceMappingURL=chunk-
|
|
896
|
+
//# sourceMappingURL=chunk-45H2FFSL.cjs.map
|
|
897
|
+
//# sourceMappingURL=chunk-45H2FFSL.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/project.ts","../src/auth/pkce.ts","../src/auth/providers/anthropic.ts","../src/auth/providers/openai-codex.ts","../src/auth/storage.ts"],"names":["execSync","createHash","path","os","fs","scope","rid","CLIENT_ID","AUTHORIZE_URL","TOKEN_URL","REDIRECT_URI","join","existsSync","readFileSync","dirname","mkdirSync","writeFileSync","chmodSync"],"mappings":";;;;;;;;;;;;;;;AAkCA,SAAS,GAAA,CAAI,MAAc,GAAA,EAAiC;AAC1D,EAAA,IAAI;AACF,IAAA,OAAOA,sBAAA,CAAS,CAAA,IAAA,EAAO,IAAI,CAAA,CAAA,EAAI;AAAA,MAC7B,GAAA;AAAA,MACA,QAAA,EAAU,OAAA;AAAA,MACV,KAAA,EAAO,CAAC,MAAA,EAAQ,MAAA,EAAQ,MAAM;AAAA,KAC/B,EAAE,IAAA,EAAK;AAAA,EACV,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAKA,SAAS,QAAQ,GAAA,EAAqB;AACpC,EAAA,OAAO,GAAA,CACJ,aAAY,CACZ,OAAA,CAAQ,eAAe,GAAG,CAAA,CAC1B,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA;AACzB;AAKA,SAAS,UAAU,GAAA,EAAqB;AACtC,EAAA,OAAOC,mBAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,GAAG,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,EAAE,CAAA;AACnE;AAQA,SAAS,gBAAgB,GAAA,EAAqB;AAC5C,EAAA,OAAO,GAAA,CACJ,OAAA,CAAQ,QAAA,EAAU,EAAE,CAAA,CACpB,OAAA,CAAQ,eAAA,EAAiB,aAAa,CAAA,CACtC,OAAA,CAAQ,eAAA,EAAiB,UAAU,EACnC,WAAA,EAAY;AACjB;AAKO,SAAS,cAAc,WAAA,EAAkC;AAC9D,EAAA,MAAM,YAAA,GAAeC,qBAAA,CAAK,OAAA,CAAQ,WAAW,CAAA;AAG7C,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,qBAAA,EAAuB,YAAY,CAAA;AACtD,EAAA,MAAM,YAAY,MAAA,KAAW,MAAA;AAE7B,EAAA,IAAI,QAAA,GAAW,YAAA;AACf,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,UAAA,GAAa,KAAA;AACjB,EAAA,IAAI,YAAA;AAEJ,EAAA,IAAI,SAAA,EAAW;AAEb,IAAA,QAAA,GAAW,GAAA,CAAI,2BAAA,EAA6B,YAAY,CAAA,IAAK,YAAA;AAG7D,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,4BAAA,EAA8B,YAAY,CAAA;AAChE,IAAA,IAAI,SAAA,IAAa,SAAA,KAAc,MAAA,IAAU,SAAA,KAAc,MAAA,EAAQ;AAC7D,MAAA,UAAA,GAAa,IAAA;AAEb,MAAA,YAAA,GAAeA,sBAAK,OAAA,CAAQA,qBAAA,CAAK,OAAA,CAAQ,QAAA,EAAU,SAAS,CAAC,CAAA;AAAA,IAC/D;AAGA,IAAA,MAAA,GAAS,GAAA,CAAI,yBAAyB,YAAY,CAAA;AAClD,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,OAAA,GAAU,GAAA,CAAI,QAAA,EAAU,YAAY,CAAA;AAC1C,MAAA,IAAI,OAAA,EAAS;AACX,QAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,KAAA,CAAM,IAAI,EAAE,CAAC,CAAA;AACzC,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAA,GAAS,GAAA,CAAI,CAAA,eAAA,EAAkB,WAAW,CAAA,CAAA,EAAI,YAAY,CAAA;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAGA,IAAA,SAAA,GAAY,GAAA,CAAI,+BAA+B,YAAY,CAAA;AAAA,EAC7D;AAIA,EAAA,IAAI,gBAAA;AACJ,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,gBAAA,GAAmB,gBAAgB,MAAM,CAAA;AAAA,EAC3C,WAAW,YAAA,EAAc;AACvB,IAAA,gBAAA,GAAmB,YAAA;AAAA,EACrB,CAAA,MAAO;AACL,IAAA,gBAAA,GAAmB,QAAA;AAAA,EACrB;AAIA,EAAA,MAAM,QAAA,GAAW,MAAA,GACb,MAAA,CACG,KAAA,CAAM,GAAG,CAAA,CACT,GAAA,EAAI,EACH,OAAA,CAAQ,UAAU,EAAE,CAAA,IAAK,SAAA,GAC7BA,qBAAA,CAAK,SAAS,QAAQ,CAAA;AAE1B,EAAA,MAAM,UAAA,GAAa,GAAG,OAAA,CAAQ,QAAQ,CAAC,CAAA,CAAA,EAAI,SAAA,CAAU,gBAAgB,CAAC,CAAA,CAAA;AAEtE,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA,IAAA,EAAM,QAAA;AAAA,IACN,QAAA;AAAA,IACA,MAAA;AAAA,IACA,SAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAMO,SAAS,oBAAoB,GAAA,EAAiC;AACnE,EAAA,OAAO,GAAA,CAAI,+BAA+B,GAAG,CAAA;AAC/C;AAQO,SAAS,aAAA,GAAwB;AACtC,EAAA,MAAM,QAAA,GAAWC,oBAAG,QAAA,EAAS;AAC7B,EAAA,IAAI,OAAA;AAEJ,EAAA,IAAI,aAAa,QAAA,EAAU;AACzB,IAAA,OAAA,GAAUD,sBAAK,IAAA,CAAKC,mBAAA,CAAG,OAAA,EAAQ,EAAG,WAAW,qBAAqB,CAAA;AAAA,EACpE,CAAA,MAAA,IAAW,aAAa,OAAA,EAAS;AAC/B,IAAA,OAAA,GAAU,OAAA,CAAQ,IAAI,OAAA,IAAWD,qBAAA,CAAK,KAAKC,mBAAA,CAAG,OAAA,EAAQ,EAAG,SAAA,EAAW,SAAS,CAAA;AAAA,EAC/E,CAAA,MAAO;AAEL,IAAA,OAAA,GAAU,OAAA,CAAQ,IAAI,aAAA,IAAiBD,qBAAA,CAAK,KAAKC,mBAAA,CAAG,OAAA,EAAQ,EAAG,QAAA,EAAU,OAAO,CAAA;AAAA,EAClF;AAEA,EAAA,MAAM,MAAA,GAASD,qBAAA,CAAK,IAAA,CAAK,OAAA,EAAS,YAAY,CAAA;AAG9C,EAAA,IAAI,CAACE,mBAAA,CAAG,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,IAAAA,mBAAA,CAAG,SAAA,CAAU,MAAA,EAAQ,EAAE,SAAA,EAAW,MAAM,CAAA;AAAA,EAC1C;AAEA,EAAA,OAAO,MAAA;AACT;AAKO,SAAS,eAAA,GAA0B;AACxC,EAAA,IAAI,OAAA,CAAQ,IAAI,cAAA,EAAgB;AAC9B,IAAA,OAAO,QAAQ,GAAA,CAAI,cAAA;AAAA,EACrB;AACA,EAAA,OAAOF,qBAAA,CAAK,IAAA,CAAK,aAAA,EAAc,EAAG,WAAW,CAAA;AAC/C;AAoDO,SAAS,gBAAA,CAAiB,YAAqB,eAAA,EAAkD;AAEtG,EAAA,MAAM,UAAA,GAAa,QAAQ,GAAA,CAAI,sBAAA;AAE/B,EAAA,IAAI,eAAe,IAAA,EAAM;AACvB,IAAA,OAAO,gBAAA,EAAiB;AAAA,EAC1B;AAGA,EAAA,IAAI,UAAA,KAAe,QAAA,IAAY,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe;AACxD,IAAA,OAAO,oBAAA,EAAqB;AAAA,EAC9B;AAGA,EAAA,IAAI,eAAA,IAAmB,eAAA,CAAgB,OAAA,KAAY,IAAA,EAAM;AACvD,IAAA,OAAO,sBAAsB,eAAe,CAAA;AAAA,EAC9C;AAEA,EAAA,IAAI,mBAAmB,eAAA,CAAgB,OAAA,KAAY,QAAA,IAAY,eAAA,CAAgB,OAAO,GAAA,EAAK;AACzF,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,QAAA;AAAA,MACT,GAAA,EAAK,gBAAgB,MAAA,CAAO,GAAA;AAAA,MAC5B,SAAA,EAAW,gBAAgB,MAAA,CAAO,SAAA;AAAA,MAClC,UAAU,CAAC,eAAA,CAAgB,MAAA,CAAO,GAAA,CAAI,WAAW,OAAO;AAAA,KAC1D;AAAA,EACF;AAGA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAM,gBAAgB,kBAAA,CAAmBA,qBAAA,CAAK,KAAK,UAAA,EAAY,aAAA,EAAe,eAAe,CAAC,CAAA;AAC9F,IAAA,IAAI,eAAe,OAAO,aAAA;AAAA,EAC5B;AACA,EAAA,MAAM,YAAA,GAAe,mBAAmBA,qBAAA,CAAK,IAAA,CAAKC,oBAAG,OAAA,EAAQ,EAAG,aAAA,EAAe,eAAe,CAAC,CAAA;AAC/F,EAAA,IAAI,cAAc,OAAO,YAAA;AAGzB,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA;AAAA,IACT,GAAA,EAAK,CAAA,KAAA,EAAQ,eAAA,EAAiB,CAAA,CAAA;AAAA,IAC9B,QAAA,EAAU;AAAA,GACZ;AACF;AAEA,SAAS,oBAAA,GAA4C;AACnD,EAAA,MAAM,GAAA,GAAM,QAAQ,GAAA,CAAI,aAAA;AACxB,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA;AAAA,IACT,GAAA;AAAA,IACA,SAAA,EAAW,QAAQ,GAAA,CAAI,oBAAA;AAAA,IACvB,QAAA,EAAU,CAAC,GAAA,CAAI,UAAA,CAAW,OAAO;AAAA,GACnC;AACF;AAEA,SAAS,gBAAA,GAAoC;AAC3C,EAAA,MAAM,gBAAA,GAAmB,QAAQ,GAAA,CAAI,2BAAA;AACrC,EAAA,IAAI,gBAAA,EAAkB;AACpB,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,gBAAA;AAAA,MACA,UAAA,EAAY,QAAQ,GAAA,CAAI;AAAA,KAC1B;AAAA,EACF;AAGA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,IAAA,EAAM,QAAQ,GAAA,CAAI,cAAA;AAAA,IAClB,IAAA,EAAM,QAAQ,GAAA,CAAI,cAAA,GAAiB,SAAS,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgB,EAAE,CAAA,GAAI,MAAA;AAAA,IAC9E,QAAA,EAAU,QAAQ,GAAA,CAAI,kBAAA;AAAA,IACtB,IAAA,EAAM,QAAQ,GAAA,CAAI,cAAA;AAAA,IAClB,QAAA,EAAU,QAAQ,GAAA,CAAI,kBAAA;AAAA,IACtB,UAAA,EAAY,QAAQ,GAAA,CAAI;AAAA,GAC1B;AACF;AAEA,SAAS,sBAAsB,QAAA,EAA4C;AACzE,EAAA,MAAM,KAAK,QAAA,CAAS,EAAA;AACpB,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT,kBAAkB,EAAA,CAAG,gBAAA;AAAA,IACrB,MAAM,EAAA,CAAG,IAAA;AAAA,IACT,MAAM,EAAA,CAAG,IAAA;AAAA,IACT,UAAU,EAAA,CAAG,QAAA;AAAA,IACb,MAAM,EAAA,CAAG,IAAA;AAAA,IACT,UAAU,EAAA,CAAG,QAAA;AAAA,IACb,YAAY,EAAA,CAAG,UAAA;AAAA,IACf,aAAa,EAAA,CAAG,WAAA;AAAA,IAChB,oBAAoB,EAAA,CAAG;AAAA,GACzB;AACF;AAMA,SAAS,mBAAmB,QAAA,EAA8C;AACxE,EAAA,IAAI;AACF,IAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,GAAG,OAAO,IAAA;AACrC,IAAA,MAAM,GAAA,GAAMA,mBAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,OAAO,MAAA,EAAQ,GAAA,KAAQ,QAAA,IAAY,OAAO,GAAA,EAAK;AACjD,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,KAAK,MAAA,CAAO,GAAA;AAAA,QACZ,WAAW,OAAO,MAAA,CAAO,SAAA,KAAc,QAAA,GAAW,OAAO,SAAA,GAAY,MAAA;AAAA,QACrE,QAAA,EAAU,CAAC,MAAA,CAAO,GAAA,CAAI,WAAW,OAAO;AAAA,OAC1C;AAAA,IACF;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAUO,SAAS,UAAU,UAAA,EAA6B;AAErD,EAAA,IAAI,OAAA,CAAQ,IAAI,cAAA,EAAgB;AAC9B,IAAA,OAAO,QAAQ,GAAA,CAAI,cAAA;AAAA,EACrB;AAGA,EAAA,MAAM,GAAA,GAAM,UAAA,IAAc,OAAA,CAAQ,GAAA,EAAI;AACtC,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,mBAAA,EAAqB,GAAG,CAAA;AAC1C,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,OAAOD,mBAAA,CAAG,QAAA,EAAS,CAAE,QAAA,IAAY,SAAA;AACnC;AAgBO,SAAS,WAAW,UAAA,EAA8B;AAEvD,EAAA,MAAM,QAAA,GAAW,QAAQ,GAAA,CAAI,eAAA;AAC7B,EAAA,IAAI,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,UAAA,EAAY;AACpD,IAAA,OAAO,QAAA;AAAA,EACT;AAGA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAME,SAAQ,qBAAA,CAAsBH,qBAAA,CAAK,KAAK,UAAA,EAAY,aAAA,EAAe,eAAe,CAAC,CAAA;AACzF,IAAA,IAAIG,QAAO,OAAOA,MAAAA;AAAA,EACpB;AAGA,EAAA,MAAM,KAAA,GAAQ,sBAAsBH,qBAAA,CAAK,IAAA,CAAKC,oBAAG,OAAA,EAAQ,EAAG,aAAA,EAAe,eAAe,CAAC,CAAA;AAC3F,EAAA,IAAI,OAAO,OAAO,KAAA;AAGlB,EAAA,OAAO,QAAA;AACT;AAEA,SAAS,sBAAsB,QAAA,EAAkC;AAC/D,EAAA,IAAI;AACF,IAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,GAAG,OAAO,IAAA;AACrC,IAAA,MAAM,GAAA,GAAMA,mBAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,MAAA,EAAQ,OAAA,KAAY,QAAA,IAAY,MAAA,EAAQ,YAAY,UAAA,EAAY;AAClE,MAAA,OAAO,MAAA,CAAO,OAAA;AAAA,IAChB;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAcO,SAAS,sBAAsB,UAAA,EAAoC;AAExE,EAAA,IAAI,OAAA,CAAQ,IAAI,kBAAA,EAAoB;AAClC,IAAA,OAAO,QAAQ,GAAA,CAAI,kBAAA;AAAA,EACrB;AAGA,EAAA,IAAI,UAAA,EAAY;AACd,IAAA,MAAME,IAAAA,GAAM,gBAAgBJ,qBAAA,CAAK,IAAA,CAAK,YAAY,aAAA,EAAe,eAAe,GAAG,YAAY,CAAA;AAC/F,IAAA,IAAII,MAAK,OAAOA,IAAAA;AAAA,EAClB;AAGA,EAAA,MAAM,GAAA,GAAM,eAAA,CAAgBJ,qBAAA,CAAK,IAAA,CAAKC,mBAAA,CAAG,SAAQ,EAAG,aAAA,EAAe,eAAe,CAAA,EAAG,YAAY,CAAA;AACjG,EAAA,IAAI,KAAK,OAAO,GAAA;AAEhB,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,eAAA,CAAgB,UAAkB,KAAA,EAA8B;AACvE,EAAA,IAAI;AACF,IAAA,IAAI,CAACC,mBAAA,CAAG,UAAA,CAAW,QAAQ,GAAG,OAAO,IAAA;AACrC,IAAA,MAAM,GAAA,GAAMA,mBAAA,CAAG,YAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,MAAM,KAAA,GAAQ,SAAS,KAAK,CAAA;AAC5B,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,EAAO;AACtC,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;;;AC3dA,SAAS,gBAAgB,KAAA,EAA2B;AAClD,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAA,IAAU,MAAA,CAAO,aAAa,IAAI,CAAA;AAAA,EACpC;AACA,EAAA,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,KAAA,EAAO,GAAG,CAAA,CAAE,OAAA,CAAQ,MAAM,EAAE,CAAA;AAC9E;AAMA,eAAsB,YAAA,GAGnB;AAED,EAAA,MAAM,aAAA,GAAgB,IAAI,UAAA,CAAW,EAAE,CAAA;AACvC,EAAA,MAAA,CAAO,gBAAgB,aAAa,CAAA;AACpC,EAAA,MAAM,QAAA,GAAW,gBAAgB,aAAa,CAAA;AAG9C,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAA,CAAO,QAAQ,CAAA;AACpC,EAAA,MAAM,aAAa,MAAM,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,WAAW,IAAI,CAAA;AAC7D,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,IAAI,UAAA,CAAW,UAAU,CAAC,CAAA;AAE5D,EAAA,OAAO,EAAE,UAAU,SAAA,EAAU;AAC/B;;;AC1BA,IAAM,MAAA,GAAS,CAAC,CAAA,KAAc,IAAA,CAAK,CAAC,CAAA;AACpC,IAAM,SAAA,GAAY,OAAO,kDAAkD,CAAA;AAC3E,IAAM,aAAA,GAAgB,mCAAA;AACtB,IAAM,SAAA,GAAY,8CAAA;AAClB,IAAM,YAAA,GAAe,mDAAA;AACrB,IAAM,MAAA,GAAS,gDAAA;AAKf,eAAsB,cAAA,CACpB,WACA,YAAA,EAC2B;AAC3B,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,MAAM,YAAA,EAAa;AAGnD,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,CAAgB;AAAA,IACrC,IAAA,EAAM,MAAA;AAAA,IACN,SAAA,EAAW,SAAA;AAAA,IACX,aAAA,EAAe,MAAA;AAAA,IACf,YAAA,EAAc,YAAA;AAAA,IACd,KAAA,EAAO,MAAA;AAAA,IACP,cAAA,EAAgB,SAAA;AAAA,IAChB,qBAAA,EAAuB,MAAA;AAAA,IACvB,KAAA,EAAO;AAAA,GACR,CAAA;AAED,EAAA,MAAM,UAAU,CAAA,EAAG,aAAa,CAAA,CAAA,EAAI,UAAA,CAAW,UAAU,CAAA,CAAA;AAGzD,EAAA,SAAA,CAAU,OAAO,CAAA;AAGjB,EAAA,MAAM,QAAA,GAAW,MAAM,YAAA,EAAa;AACpC,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA;AACjC,EAAA,MAAM,IAAA,GAAO,OAAO,CAAC,CAAA;AACrB,EAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AAGtB,EAAA,MAAM,aAAA,GAAgB,MAAM,KAAA,CAAM,SAAA,EAAW;AAAA,IAC3C,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS;AAAA,MACP,cAAA,EAAgB;AAAA,KAClB;AAAA,IACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAW,SAAA;AAAA,MACX,IAAA;AAAA,MACA,KAAA;AAAA,MACA,YAAA,EAAc,YAAA;AAAA,MACd,aAAA,EAAe;AAAA,KAChB;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,cAAc,EAAA,EAAI;AACrB,IAAA,MAAM,KAAA,GAAQ,MAAM,aAAA,CAAc,IAAA,EAAK;AACvC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,KAAK,CAAA,CAAE,CAAA;AAAA,EACnD;AAEA,EAAA,MAAM,SAAA,GAAa,MAAM,aAAA,CAAc,IAAA,EAAK;AAO5C,EAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI,GAAI,UAAU,UAAA,GAAa,GAAA,GAAO,IAAI,EAAA,GAAK,GAAA;AAEtE,EAAA,OAAO;AAAA,IACL,SAAS,SAAA,CAAU,aAAA;AAAA,IACnB,QAAQ,SAAA,CAAU,YAAA;AAAA,IAClB,OAAA,EAAS;AAAA,GACX;AACF;AAKA,eAAsB,sBAAsB,YAAA,EAAiD;AAC3F,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,SAAA,EAAW;AAAA,IACtC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,IAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,MACnB,UAAA,EAAY,eAAA;AAAA,MACZ,SAAA,EAAW,SAAA;AAAA,MACX,aAAA,EAAe;AAAA,KAChB;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAClC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,gCAAA,EAAmC,KAAK,CAAA,CAAE,CAAA;AAAA,EAC5D;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAMlC,EAAA,OAAO;AAAA,IACL,SAAS,IAAA,CAAK,aAAA;AAAA,IACd,QAAQ,IAAA,CAAK,YAAA;AAAA,IACb,OAAA,EAAS,KAAK,GAAA,EAAI,GAAI,KAAK,UAAA,GAAa,GAAA,GAAO,IAAI,EAAA,GAAK;AAAA,GAC1D;AACF;AAEO,IAAM,sBAAA,GAAiD;AAAA,EAC5D,EAAA,EAAI,WAAA;AAAA,EACJ,IAAA,EAAM,4BAAA;AAAA,EAEN,MAAM,MAAM,SAAA,EAA2D;AACrE,IAAA,OAAO,cAAA;AAAA,MACL,CAAA,GAAA,KAAO,SAAA,CAAU,MAAA,CAAO,EAAE,KAAK,CAAA;AAAA,MAC/B,MAAM,SAAA,CAAU,QAAA,CAAS,EAAE,OAAA,EAAS,iCAAiC;AAAA,KACvE;AAAA,EACF,CAAA;AAAA,EAEA,MAAM,aAAa,WAAA,EAA0D;AAC3E,IAAA,OAAO,qBAAA,CAAsB,YAAY,OAAO,CAAA;AAAA,EAClD,CAAA;AAAA,EAEA,UAAU,WAAA,EAAuC;AAC/C,IAAA,OAAO,WAAA,CAAY,MAAA;AAAA,EACrB;AACF,CAAA;;;AC7HA,IAAI,YAAA,GAAkD,IAAA;AAEtD,IAAI,KAAA,GAA2C,IAAA;AAC/C,IAAI,OAAO,YAAY,WAAA,KAAgB,OAAA,CAAQ,UAAU,IAAA,IAAQ,OAAA,CAAQ,UAAU,GAAA,CAAA,EAAM;AACvF,EAAA,OAAO,QAAa,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,KAAK;AAC9B,IAAA,YAAA,GAAe,CAAA,CAAE,WAAA;AAAA,EACnB,CAAC,CAAA;AACD,EAAA,OAAO,MAAW,CAAA,CAAE,IAAA,CAAK,CAAA,CAAA,KAAK;AAC5B,IAAA,KAAA,GAAQ,CAAA;AAAA,EACV,CAAC,CAAA;AACH;AAKA,IAAMG,UAAAA,GAAY,8BAAA;AAClB,IAAMC,cAAAA,GAAgB,yCAAA;AACtB,IAAMC,UAAAA,GAAY,qCAAA;AAClB,IAAMC,aAAAA,GAAe,qCAAA;AACrB,IAAM,KAAA,GAAQ,qCAAA;AACd,IAAM,cAAA,GAAiB,6BAAA;AAEvB,IAAM,YAAA,GAAe,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,OAAA,CAAA;AA4BrB,SAAS,WAAA,GAAsB;AAC7B,EAAA,IAAI,CAAC,YAAA,EAAc;AACjB,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,YAAA,CAAa,EAAE,CAAA,CAAE,QAAA,CAAS,KAAK,CAAA;AACxC;AAEA,SAAS,wBAAwB,KAAA,EAG/B;AACA,EAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,EAAK;AACzB,EAAA,IAAI,CAAC,KAAA,EAAO,OAAO,EAAC;AAEpB,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,KAAK,CAAA;AACzB,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA,IAAK,MAAA;AAAA,MACtC,KAAA,EAAO,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAO,CAAA,IAAK;AAAA,KAC1C;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AAEA,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,GAAG,CAAA,EAAG;AACvB,IAAA,MAAM,CAAC,IAAA,EAAM,KAAK,IAAI,KAAA,CAAM,KAAA,CAAM,KAAK,CAAC,CAAA;AACxC,IAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AAAA,EACvB;AAEA,EAAA,IAAI,KAAA,CAAM,QAAA,CAAS,OAAO,CAAA,EAAG;AAC3B,IAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB,KAAK,CAAA;AACxC,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,MAAM,CAAA,IAAK,MAAA;AAAA,MAC5B,KAAA,EAAO,MAAA,CAAO,GAAA,CAAI,OAAO,CAAA,IAAK;AAAA,KAChC;AAAA,EACF;AAEA,EAAA,OAAO,EAAE,MAAM,KAAA,EAAM;AACvB;AAEA,SAAS,UAAU,KAAA,EAAkC;AACnD,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA;AAC7B,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAC5B,IAAA,MAAM,OAAA,GAAU,KAAK,OAAO,CAAA;AAC5B,IAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,eAAe,yBAAA,CACb,IAAA,EACA,QAAA,EACA,WAAA,GAAsBA,aAAAA,EACA;AACtB,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAMD,UAAAA,EAAW;AAAA,IACtC,MAAA,EAAQ,MAAA;AAAA,IACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAoC;AAAA,IAC/D,IAAA,EAAM,IAAI,eAAA,CAAgB;AAAA,MACxB,UAAA,EAAY,oBAAA;AAAA,MACZ,SAAA,EAAWF,UAAAA;AAAA,MACX,IAAA;AAAA,MACA,aAAA,EAAe,QAAA;AAAA,MACf,YAAA,EAAc;AAAA,KACf;AAAA,GACF,CAAA;AAED,EAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,IAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACjD,IAAA,OAAA,CAAQ,KAAA,CAAM,oCAAA,EAAsC,QAAA,CAAS,MAAA,EAAQ,IAAI,CAAA;AACzE,IAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,EAC1B;AAEA,EAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAMlC,EAAA,IAAI,CAAC,KAAK,YAAA,IAAgB,CAAC,KAAK,aAAA,IAAiB,OAAO,IAAA,CAAK,UAAA,KAAe,QAAA,EAAU;AACpF,IAAA,OAAA,CAAQ,KAAA,CAAM,iDAAiD,IAAI,CAAA;AACnE,IAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,EAC1B;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,SAAA;AAAA,IACN,QAAQ,IAAA,CAAK,YAAA;AAAA,IACb,SAAS,IAAA,CAAK,aAAA;AAAA,IACd,OAAA,EAAS,IAAA,CAAK,GAAA,EAAI,GAAI,KAAK,UAAA,GAAa;AAAA,GAC1C;AACF;AAEA,eAAe,mBAAmB,YAAA,EAA4C;AAC5E,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAME,UAAAA,EAAW;AAAA,MACtC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS,EAAE,cAAA,EAAgB,mCAAA,EAAoC;AAAA,MAC/D,IAAA,EAAM,IAAI,eAAA,CAAgB;AAAA,QACxB,UAAA,EAAY,eAAA;AAAA,QACZ,aAAA,EAAe,YAAA;AAAA,QACf,SAAA,EAAWF;AAAA,OACZ;AAAA,KACF,CAAA;AAED,IAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,MAAA,MAAM,OAAO,MAAM,QAAA,CAAS,MAAK,CAAE,KAAA,CAAM,MAAM,EAAE,CAAA;AACjD,MAAA,OAAA,CAAQ,KAAA,CAAM,sCAAA,EAAwC,QAAA,CAAS,MAAA,EAAQ,IAAI,CAAA;AAC3E,MAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,IAC1B;AAEA,IAAA,MAAM,IAAA,GAAQ,MAAM,QAAA,CAAS,IAAA,EAAK;AAMlC,IAAA,IAAI,CAAC,KAAK,YAAA,IAAgB,CAAC,KAAK,aAAA,IAAiB,OAAO,IAAA,CAAK,UAAA,KAAe,QAAA,EAAU;AACpF,MAAA,OAAA,CAAQ,KAAA,CAAM,yDAAyD,IAAI,CAAA;AAC3E,MAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,IAC1B;AAEA,IAAA,OAAO;AAAA,MACL,IAAA,EAAM,SAAA;AAAA,MACN,QAAQ,IAAA,CAAK,YAAA;AAAA,MACb,SAAS,IAAA,CAAK,aAAA;AAAA,MACd,OAAA,EAAS,IAAA,CAAK,GAAA,EAAI,GAAI,KAAK,UAAA,GAAa;AAAA,KAC1C;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,OAAA,CAAQ,KAAA,CAAM,uCAAuC,KAAK,CAAA;AAC1D,IAAA,OAAO,EAAE,MAAM,QAAA,EAAS;AAAA,EAC1B;AACF;AAEA,eAAe,uBAAA,CACb,aAAqB,IAAA,EACsC;AAC3D,EAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAU,GAAI,MAAM,YAAA,EAAa;AACnD,EAAA,MAAM,QAAQ,WAAA,EAAY;AAE1B,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAIC,cAAa,CAAA;AACjC,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,eAAA,EAAiB,MAAM,CAAA;AAC5C,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,WAAA,EAAaD,UAAS,CAAA;AAC3C,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,cAAA,EAAgBG,aAAY,CAAA;AACjD,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAK,CAAA;AACnC,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,gBAAA,EAAkB,SAAS,CAAA;AAChD,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,uBAAA,EAAyB,MAAM,CAAA;AACpD,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAA,EAAS,KAAK,CAAA;AACnC,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,4BAAA,EAA8B,MAAM,CAAA;AACzD,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,2BAAA,EAA6B,MAAM,CAAA;AACxD,EAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,YAAA,EAAc,UAAU,CAAA;AAE7C,EAAA,OAAO,EAAE,QAAA,EAAU,KAAA,EAAO,GAAA,EAAK,GAAA,CAAI,UAAS,EAAE;AAChD;AAQA,SAAS,sBAAsB,KAAA,EAAyC;AACtE,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAAA,EAChF;AACA,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,YAAA,CAAa,CAAC,KAAK,GAAA,KAAQ;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,IAAI,GAAA,CAAI,GAAA,CAAI,GAAA,IAAO,IAAI,kBAAkB,CAAA;AACrD,MAAA,IAAI,GAAA,CAAI,aAAa,gBAAA,EAAkB;AACrC,QAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,QAAA,GAAA,CAAI,IAAI,WAAW,CAAA;AACnB,QAAA;AAAA,MACF;AACA,MAAA,IAAI,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,OAAO,MAAM,KAAA,EAAO;AAC3C,QAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,QAAA,GAAA,CAAI,IAAI,gBAAgB,CAAA;AACxB,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,MAAM,CAAA;AACxC,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,QAAA,GAAA,CAAI,IAAI,4BAA4B,CAAA;AACpC,QAAA;AAAA,MACF;AACA,MAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,MAAA,GAAA,CAAI,SAAA,CAAU,gBAAgB,0BAA0B,CAAA;AACxD,MAAA,GAAA,CAAI,IAAI,YAAY,CAAA;AACpB,MAAA,QAAA,GAAW,IAAA;AAAA,IACb,CAAA,CAAA,MAAQ;AACN,MAAA,GAAA,CAAI,UAAA,GAAa,GAAA;AACjB,MAAA,GAAA,CAAI,IAAI,gBAAgB,CAAA;AAAA,IAC1B;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,IAAI,QAAQ,CAAA,OAAA,KAAW;AAC5B,IAAA,MAAA,CACG,MAAA,CAAO,IAAA,EAAM,WAAA,EAAa,MAAM;AAC/B,MAAA,OAAA,CAAQ;AAAA,QACN,KAAA,EAAO,MAAM,MAAA,CAAO,KAAA,EAAM;AAAA,QAC1B,YAAY,MAAM;AAChB,UAAA,SAAA,GAAY,IAAA;AAAA,QACd,CAAA;AAAA,QACA,aAAa,YAAY;AACvB,UAAA,MAAM,KAAA,GAAQ,MAAM,IAAI,OAAA,CAAQ,OAAK,UAAA,CAAW,CAAA,EAAG,GAAG,CAAC,CAAA;AACvD,UAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,EAAK,KAAK,CAAA,EAAG;AAC/B,YAAA,IAAI,QAAA,EAAU,OAAO,EAAE,IAAA,EAAM,QAAA,EAAS;AACtC,YAAA,IAAI,WAAW,OAAO,IAAA;AACtB,YAAA,MAAM,KAAA,EAAM;AAAA,UACd;AACA,UAAA,OAAO,IAAA;AAAA,QACT;AAAA,OACD,CAAA;AAAA,IACH,CAAC,CAAA,CACA,EAAA,CAAG,OAAA,EAAS,CAAC,GAAA,KAA+B;AAC3C,MAAA,OAAA,CAAQ,KAAA;AAAA,QACN,uDAAA;AAAA,QACA,GAAA,CAAI,IAAA;AAAA,QACJ;AAAA,OACF;AACA,MAAA,OAAA,CAAQ;AAAA,QACN,OAAO,MAAM;AACX,UAAA,IAAI;AACF,YAAA,MAAA,CAAO,KAAA,EAAM;AAAA,UACf,CAAA,CAAA,MAAQ;AAAA,UAER;AAAA,QACF,CAAA;AAAA,QACA,YAAY,MAAM;AAAA,QAAC,CAAA;AAAA,QACnB,aAAa,YAAY;AAAA,OAC1B,CAAA;AAAA,IACH,CAAC,CAAA;AAAA,EACL,CAAC,CAAA;AACH;AAEA,SAAS,aAAa,WAAA,EAAoC;AACxD,EAAA,MAAM,OAAA,GAAU,UAAU,WAAW,CAAA;AACrC,EAAA,MAAM,IAAA,GAAO,UAAU,cAAc,CAAA;AACrC,EAAA,MAAM,YAAY,IAAA,EAAM,kBAAA;AACxB,EAAA,OAAO,OAAO,SAAA,KAAc,QAAA,IAAY,SAAA,CAAU,MAAA,GAAS,IAAI,SAAA,GAAY,IAAA;AAC7E;AAaA,eAAsB,iBAAiB,OAAA,EAMT;AAC5B,EAAA,MAAM,EAAE,UAAU,KAAA,EAAO,GAAA,KAAQ,MAAM,uBAAA,CAAwB,QAAQ,UAAU,CAAA;AACjF,EAAA,MAAM,MAAA,GAAS,MAAM,qBAAA,CAAsB,KAAK,CAAA;AAEhD,EAAA,OAAA,CAAQ,MAAA,CAAO;AAAA,IACb,GAAA;AAAA,IACA,YAAA,EAAc;AAAA,GACf,CAAA;AAED,EAAA,IAAI,IAAA;AACJ,EAAA,IAAI;AACF,IAAA,IAAI,QAAQ,iBAAA,EAAmB;AAE7B,MAAA,IAAI,UAAA;AACJ,MAAA,IAAI,WAAA;AACJ,MAAA,MAAM,aAAA,GAAgB,OAAA,CACnB,iBAAA,EAAkB,CAClB,KAAK,CAAA,KAAA,KAAS;AACb,QAAA,UAAA,GAAa,KAAA;AACb,QAAA,MAAA,CAAO,UAAA,EAAW;AAAA,MACpB,CAAC,CAAA,CACA,KAAA,CAAM,CAAA,GAAA,KAAO;AACZ,QAAA,WAAA,GAAc,eAAe,KAAA,GAAQ,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA;AAChE,QAAA,MAAA,CAAO,UAAA,EAAW;AAAA,MACpB,CAAC,CAAA;AAEH,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,WAAA,EAAY;AAGxC,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,WAAA;AAAA,MACR;AAEA,MAAA,IAAI,QAAQ,IAAA,EAAM;AAEhB,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAChB,WAAW,UAAA,EAAY;AAErB,QAAA,MAAM,MAAA,GAAS,wBAAwB,UAAU,CAAA;AACjD,QAAA,IAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,KAAA,KAAU,KAAA,EAAO;AAC1C,UAAA,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAAA,QAClC;AACA,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AAGA,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,MAAM,aAAA;AACN,QAAA,IAAI,WAAA,EAAa;AACf,UAAA,MAAM,WAAA;AAAA,QACR;AACA,QAAA,IAAI,UAAA,EAAY;AACd,UAAA,MAAM,MAAA,GAAS,wBAAwB,UAAU,CAAA;AACjD,UAAA,IAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,KAAA,KAAU,KAAA,EAAO;AAC1C,YAAA,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAAA,UAClC;AACA,UAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,QAChB;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AAEL,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,WAAA,EAAY;AACxC,MAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,QAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,MAChB;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,QAAA,CAAS;AAAA,QACnC,OAAA,EAAS;AAAA,OACV,CAAA;AACD,MAAA,MAAM,MAAA,GAAS,wBAAwB,KAAK,CAAA;AAC5C,MAAA,IAAI,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,KAAA,KAAU,KAAA,EAAO;AAC1C,QAAA,MAAM,IAAI,MAAM,gBAAgB,CAAA;AAAA,MAClC;AACA,MAAA,IAAA,GAAO,MAAA,CAAO,IAAA;AAAA,IAChB;AAEA,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,MAAM,IAAI,MAAM,4BAA4B,CAAA;AAAA,IAC9C;AAEA,IAAA,MAAM,WAAA,GAAc,MAAM,yBAAA,CAA0B,IAAA,EAAM,QAAQ,CAAA;AAClE,IAAA,IAAI,WAAA,CAAY,SAAS,SAAA,EAAW;AAClC,MAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,IACzC;AAEA,IAAA,MAAM,SAAA,GAAY,YAAA,CAAa,WAAA,CAAY,MAAM,CAAA;AACjD,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,IAC1D;AAEA,IAAA,OAAO;AAAA,MACL,QAAQ,WAAA,CAAY,MAAA;AAAA,MACpB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB,SAAS,WAAA,CAAY,OAAA;AAAA,MACrB;AAAA,KACF;AAAA,EACF,CAAA,SAAE;AACA,IAAA,MAAA,CAAO,KAAA,EAAM;AAAA,EACf;AACF;AAKA,eAAsB,wBAAwB,YAAA,EAAiD;AAC7F,EAAA,MAAM,MAAA,GAAS,MAAM,kBAAA,CAAmB,YAAY,CAAA;AACpD,EAAA,IAAI,MAAA,CAAO,SAAS,SAAA,EAAW;AAC7B,IAAA,MAAM,IAAI,MAAM,sCAAsC,CAAA;AAAA,EACxD;AAEA,EAAA,MAAM,SAAA,GAAY,YAAA,CAAa,MAAA,CAAO,MAAM,CAAA;AAC5C,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,MAAM,IAAI,MAAM,wCAAwC,CAAA;AAAA,EAC1D;AAEA,EAAA,OAAO;AAAA,IACL,QAAQ,MAAA,CAAO,MAAA;AAAA,IACf,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB,SAAS,MAAA,CAAO,OAAA;AAAA,IAChB;AAAA,GACF;AACF;AAEO,IAAM,wBAAA,GAAmD;AAAA,EAC9D,EAAA,EAAI,cAAA;AAAA,EACJ,IAAA,EAAM,uCAAA;AAAA,EACN,kBAAA,EAAoB,IAAA;AAAA,EAEpB,MAAM,MAAM,SAAA,EAA2D;AACrE,IAAA,OAAO,gBAAA,CAAiB;AAAA,MACtB,QAAQ,SAAA,CAAU,MAAA;AAAA,MAClB,UAAU,SAAA,CAAU,QAAA;AAAA,MACpB,YAAY,SAAA,CAAU,UAAA;AAAA,MACtB,mBAAmB,SAAA,CAAU;AAAA,KAC9B,CAAA;AAAA,EACH,CAAA;AAAA,EAEA,MAAM,aAAa,WAAA,EAA0D;AAC3E,IAAA,OAAO,uBAAA,CAAwB,YAAY,OAAO,CAAA;AAAA,EACpD,CAAA;AAAA,EAEA,UAAU,WAAA,EAAuC;AAC/C,IAAA,OAAO,WAAA,CAAY,MAAA;AAAA,EACrB;AACF,CAAA;;;AC/bO,IAAM,uBAAA,GAA2D;AAAA,EACtE,SAAA,EAAW,2BAAA;AAAA,EACX,cAAA,EAAgB;AAClB;AAGA,IAAM,qBAAA,uBAA4B,GAAA,CAAoC;AAAA,EACpE,CAAC,sBAAA,CAAuB,EAAA,EAAI,sBAAsB,CAAA;AAAA,EAClD,CAAC,wBAAA,CAAyB,EAAA,EAAI,wBAAwB;AACxD,CAAC,CAAA;AAKM,SAAS,iBAAiB,EAAA,EAAyD;AACxF,EAAA,OAAO,qBAAA,CAAsB,IAAI,EAAE,CAAA;AACrC;AAKO,SAAS,iBAAA,GAA8C;AAC5D,EAAA,OAAO,KAAA,CAAM,IAAA,CAAK,qBAAA,CAAsB,MAAA,EAAQ,CAAA;AAClD;AAKO,IAAM,cAAN,MAAkB;AAAA,EAGvB,YAAoB,QAAA,GAAmBC,SAAA,CAAK,aAAA,EAAc,EAAG,WAAW,CAAA,EAAG;AAAvD,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAClB,IAAA,IAAA,CAAK,MAAA,EAAO;AAAA,EACd;AAAA,EAJQ,OAAwB,EAAC;AAAA;AAAA;AAAA;AAAA,EASjC,MAAA,GAAe;AACb,IAAA,IAAI,CAACC,aAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC9B,MAAA,IAAA,CAAK,OAAO,EAAC;AACb,MAAA;AAAA,IACF;AACA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,OAAO,IAAA,CAAK,KAAA,CAAMC,gBAAa,IAAA,CAAK,QAAA,EAAU,OAAO,CAAC,CAAA;AAAA,IAC7D,CAAA,CAAA,MAAQ;AACN,MAAA,IAAA,CAAK,OAAO,EAAC;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,IAAA,GAAa;AACnB,IAAA,MAAM,GAAA,GAAMC,YAAA,CAAQ,IAAA,CAAK,QAAQ,CAAA;AACjC,IAAA,IAAI,CAACF,aAAA,CAAW,GAAG,CAAA,EAAG;AACpB,MAAAG,YAAA,CAAU,KAAK,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,KAAO,CAAA;AAAA,IACjD;AACA,IAAAC,gBAAA,CAAc,IAAA,CAAK,UAAU,IAAA,CAAK,SAAA,CAAU,KAAK,IAAA,EAAM,IAAA,EAAM,CAAC,CAAA,EAAG,OAAO,CAAA;AACxE,IAAAC,YAAA,CAAU,IAAA,CAAK,UAAU,GAAK,CAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAA,EAA8C;AAChD,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,IAAK,MAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,GAAA,CAAI,UAAkB,UAAA,EAAkC;AACtD,IAAA,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA,GAAI,UAAA;AACtB,IAAA,IAAA,CAAK,IAAA,EAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAA,EAAwB;AAC7B,IAAA,OAAO,IAAA,CAAK,KAAK,QAAQ,CAAA;AACzB,IAAA,IAAA,CAAK,IAAA,EAAK;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKA,IAAA,GAAiB;AACf,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,QAAA,EAA2B;AAC7B,IAAA,OAAO,YAAY,IAAA,CAAK,IAAA;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,QAAA,EAA2B;AACpC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,QAAQ,CAAA;AAC/B,IAAA,OAAO,MAAM,IAAA,KAAS,OAAA;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,QAAA,EAA2B;AACzC,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,CAAA,OAAA,EAAU,QAAQ,CAAA,CAAE,CAAA;AAC3C,IAAA,OAAO,IAAA,EAAM,IAAA,KAAS,SAAA,IAAa,IAAA,CAAK,IAAI,MAAA,GAAS,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAAA,EAAsC;AACpD,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,CAAA,OAAA,EAAU,QAAQ,CAAA,CAAE,CAAA;AAC3C,IAAA,OAAO,IAAA,EAAM,SAAS,SAAA,IAAa,IAAA,CAAK,IAAI,MAAA,GAAS,CAAA,GAAI,KAAK,GAAA,GAAM,MAAA;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAA,CAAgB,QAAA,EAAkB,GAAA,EAAa,MAAA,EAAuB;AACpE,IAAA,IAAA,CAAK,GAAA,CAAI,UAAU,QAAQ,CAAA,CAAA,EAAI,EAAE,IAAA,EAAM,SAAA,EAAW,KAAK,CAAA;AACvD,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,GAAI,GAAA;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,yBAAyB,eAAA,EAA2D;AAClF,IAAA,KAAA,MAAW,CAAC,KAAK,IAAI,CAAA,IAAK,OAAO,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA,EAAG;AACnD,MAAA,IAAI,CAAC,GAAA,CAAI,UAAA,CAAW,SAAS,CAAA,IAAK,KAAK,IAAA,KAAS,SAAA,IAAa,CAAC,IAAA,CAAK,GAAA,EAAK;AACxE,MAAA,MAAM,QAAA,GAAW,GAAA,CAAI,SAAA,CAAU,SAAA,CAAU,MAAM,CAAA;AAC/C,MAAA,MAAM,MAAA,GAAS,gBAAgB,QAAQ,CAAA;AACvC,MAAA,IAAI,MAAA,IAAU,CAAC,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,EAAG;AAClC,QAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAA,CAAM,UAAA,EAA6B,SAAA,EAA+C;AACtF,IAAA,MAAM,QAAA,GAAW,iBAAiB,UAAU,CAAA;AAC5C,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,UAAU,CAAA,CAAE,CAAA;AAAA,IACzD;AAEA,IAAA,MAAM,WAAA,GAAc,MAAM,QAAA,CAAS,KAAA,CAAM,SAAS,CAAA;AAClD,IAAA,IAAA,CAAK,IAAI,UAAA,EAAY,EAAE,MAAM,OAAA,EAAS,GAAG,aAAa,CAAA;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,QAAA,EAAwB;AAC7B,IAAA,IAAA,CAAK,OAAO,QAAQ,CAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,UAAA,EAAiD;AAC/D,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,UAAU,CAAA;AAEjC,IAAA,IAAI,IAAA,EAAM,SAAS,SAAA,EAAW;AAC5B,MAAA,OAAO,IAAA,CAAK,GAAA;AAAA,IACd;AAEA,IAAA,IAAI,IAAA,EAAM,SAAS,OAAA,EAAS;AAC1B,MAAA,MAAM,QAAA,GAAW,iBAAiB,UAAU,CAAA;AAC5C,MAAA,IAAI,CAAC,QAAA,EAAU;AACb,QAAA,OAAO,MAAA;AAAA,MACT;AAGA,MAAA,IAAI,IAAA,CAAK,GAAA,EAAI,IAAK,IAAA,CAAK,OAAA,EAAS;AAC9B,QAAA,IAAI;AACF,UAAA,MAAM,QAAA,GAAW,MAAM,QAAA,CAAS,YAAA,CAAa,IAAI,CAAA;AACjD,UAAA,IAAA,CAAK,IAAI,UAAA,EAAY,EAAE,MAAM,OAAA,EAAS,GAAG,UAAU,CAAA;AACnD,UAAA,OAAO,QAAA,CAAS,UAAU,QAAQ,CAAA;AAAA,QACpC,CAAA,CAAA,MAAQ;AAEN,UAAA,OAAO,MAAA;AAAA,QACT;AAAA,MACF;AAEA,MAAA,OAAO,QAAA,CAAS,UAAU,IAAI,CAAA;AAAA,IAChC;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AACF","file":"chunk-45H2FFSL.cjs","sourcesContent":["/**\n * Project detection utilities\n *\n * Detects project identity from git repo or filesystem path.\n * Handles git worktrees by finding the main repository.\n */\n\nimport { execSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nexport interface ProjectInfo {\n /** Unique resource ID for this project (used for thread grouping) */\n resourceId: string;\n /** Human-readable project name */\n name: string;\n /** Absolute path to the project root */\n rootPath: string;\n /** Git remote URL if available */\n gitUrl?: string;\n /** Current git branch */\n gitBranch?: string;\n /** Whether this is a git worktree */\n isWorktree: boolean;\n /** Path to main git repo (different from rootPath if worktree) */\n mainRepoPath?: string;\n /** Whether the resourceId was explicitly overridden (env var or config) */\n resourceIdOverride?: boolean;\n}\n\n/**\n * Run a git command and return stdout, or undefined if it fails\n */\nfunction git(args: string, cwd: string): string | undefined {\n try {\n return execSync(`git ${args}`, {\n cwd,\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n }).trim();\n } catch {\n return undefined;\n }\n}\n\n/**\n * Slugify a string for use in IDs\n */\nfunction slugify(str: string): string {\n return str\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\n/**\n * Create a short hash of a string\n */\nfunction shortHash(str: string): string {\n return createHash('sha256').update(str).digest('hex').slice(0, 12);\n}\n\n/**\n * Normalize a git URL to a canonical form for comparison\n * - Removes .git suffix\n * - Converts SSH to HTTPS format for consistency\n * - Lowercases\n */\nfunction normalizeGitUrl(url: string): string {\n return url\n .replace(/\\.git$/, '')\n .replace(/^git@([^:]+):/, 'https://$1/')\n .replace(/^ssh:\\/\\/git@/, 'https://')\n .toLowerCase();\n}\n\n/**\n * Detect project info from a directory path\n */\nexport function detectProject(projectPath: string): ProjectInfo {\n const absolutePath = path.resolve(projectPath);\n\n // Check if this is a git repo\n const gitDir = git('rev-parse --git-dir', absolutePath);\n const isGitRepo = gitDir !== undefined;\n\n let rootPath = absolutePath;\n let gitUrl: string | undefined;\n let gitBranch: string | undefined;\n let isWorktree = false;\n let mainRepoPath: string | undefined;\n\n if (isGitRepo) {\n // Get the repo root (handles being in a subdirectory)\n rootPath = git('rev-parse --show-toplevel', absolutePath) || absolutePath;\n\n // Check for worktree - git-common-dir differs from git-dir in worktrees\n const commonDir = git('rev-parse --git-common-dir', absolutePath);\n if (commonDir && commonDir !== '.git' && commonDir !== gitDir) {\n isWorktree = true;\n // The common dir is inside the main repo's .git folder\n mainRepoPath = path.dirname(path.resolve(rootPath, commonDir));\n }\n\n // Get remote URL (prefer origin, fall back to first remote)\n gitUrl = git('remote get-url origin', absolutePath);\n if (!gitUrl) {\n const remotes = git('remote', absolutePath);\n if (remotes) {\n const firstRemote = remotes.split('\\n')[0];\n if (firstRemote) {\n gitUrl = git(`remote get-url ${firstRemote}`, absolutePath);\n }\n }\n }\n\n // Get current branch\n gitBranch = git('rev-parse --abbrev-ref HEAD', absolutePath);\n }\n\n // Generate resource ID\n // Priority: normalized git URL > main repo path (for worktrees) > absolute path\n let resourceIdSource: string;\n if (gitUrl) {\n resourceIdSource = normalizeGitUrl(gitUrl);\n } else if (mainRepoPath) {\n resourceIdSource = mainRepoPath;\n } else {\n resourceIdSource = rootPath;\n }\n\n // Create a readable but unique resource ID\n // Format: slugified-name-shorthash\n const baseName = gitUrl\n ? gitUrl\n .split('/')\n .pop()\n ?.replace(/\\.git$/, '') || 'project'\n : path.basename(rootPath);\n\n const resourceId = `${slugify(baseName)}-${shortHash(resourceIdSource)}`;\n\n return {\n resourceId,\n name: baseName,\n rootPath,\n gitUrl,\n gitBranch,\n isWorktree,\n mainRepoPath,\n };\n}\n\n/**\n * Get the current git branch for a given directory.\n * Lightweight alternative to detectProject() for refreshing just the branch.\n */\nexport function getCurrentGitBranch(cwd: string): string | undefined {\n return git('rev-parse --abbrev-ref HEAD', cwd);\n}\n\n/**\n * Get the application data directory for mastracode\n * - macOS: ~/Library/Application Support/mastracode\n * - Linux: ~/.local/share/mastracode\n * - Windows: %APPDATA%/mastracode\n */\nexport function getAppDataDir(): string {\n const platform = os.platform();\n let baseDir: string;\n\n if (platform === 'darwin') {\n baseDir = path.join(os.homedir(), 'Library', 'Application Support');\n } else if (platform === 'win32') {\n baseDir = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');\n } else {\n // Linux and others - follow XDG spec\n baseDir = process.env.XDG_DATA_HOME || path.join(os.homedir(), '.local', 'share');\n }\n\n const appDir = path.join(baseDir, 'mastracode');\n\n // Ensure directory exists\n if (!fs.existsSync(appDir)) {\n fs.mkdirSync(appDir, { recursive: true });\n }\n\n return appDir;\n}\n/**\n * Get the database path for mastracode\n * Can be overridden with the MASTRA_DB_PATH environment variable for debugging.\n */\nexport function getDatabasePath(): string {\n if (process.env.MASTRA_DB_PATH) {\n return process.env.MASTRA_DB_PATH;\n }\n return path.join(getAppDataDir(), 'mastra.db');\n}\n\nimport type { StorageBackend, StorageSettings } from '../onboarding/settings.js';\n\n/**\n * LibSQL storage configuration.\n */\nexport interface LibSQLStorageConfig {\n backend: 'libsql';\n url: string;\n authToken?: string;\n isRemote: boolean;\n}\n\n/**\n * PostgreSQL storage configuration.\n */\nexport interface PgStorageConfig {\n backend: 'pg';\n connectionString?: string;\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n password?: string;\n schemaName?: string;\n disableInit?: boolean;\n skipDefaultIndexes?: boolean;\n}\n\n/**\n * Resolved storage configuration for either backend.\n */\nexport type StorageConfig = LibSQLStorageConfig | PgStorageConfig;\n\n/**\n * Get the resolved storage configuration.\n *\n * Priority (highest to lowest):\n * 1. Environment variables: MASTRA_STORAGE_BACKEND + backend-specific vars\n * 2. Global settings (from /settings): settings.storage\n * 3. Legacy config files: .mastracode/database.json (LibSQL only)\n * 4. Local file database (LibSQL default)\n *\n * For PG, the env vars are:\n * MASTRA_STORAGE_BACKEND=pg\n * MASTRA_PG_CONNECTION_STRING or MASTRA_PG_HOST/PORT/DATABASE/USER/PASSWORD\n * MASTRA_PG_SCHEMA_NAME (optional)\n *\n * For LibSQL, the legacy env vars still work:\n * MASTRA_DB_URL + MASTRA_DB_AUTH_TOKEN\n */\nexport function getStorageConfig(projectDir?: string, storageSettings?: StorageSettings): StorageConfig {\n // 1. Environment variable — explicit backend selection\n const envBackend = process.env.MASTRA_STORAGE_BACKEND as StorageBackend | undefined;\n\n if (envBackend === 'pg') {\n return resolvePgFromEnv();\n }\n\n // Legacy LibSQL env vars (MASTRA_DB_URL) — treat as explicit libsql\n if (envBackend === 'libsql' || process.env.MASTRA_DB_URL) {\n return resolveLibSQLFromEnv();\n }\n\n // 2. Global settings (from /settings)\n if (storageSettings && storageSettings.backend === 'pg') {\n return resolvePgFromSettings(storageSettings);\n }\n\n if (storageSettings && storageSettings.backend === 'libsql' && storageSettings.libsql.url) {\n return {\n backend: 'libsql',\n url: storageSettings.libsql.url,\n authToken: storageSettings.libsql.authToken,\n isRemote: !storageSettings.libsql.url.startsWith('file:'),\n };\n }\n\n // 3. Legacy project/global config files (.mastracode/database.json)\n if (projectDir) {\n const projectConfig = loadDatabaseConfig(path.join(projectDir, '.mastracode', 'database.json'));\n if (projectConfig) return projectConfig;\n }\n const globalConfig = loadDatabaseConfig(path.join(os.homedir(), '.mastracode', 'database.json'));\n if (globalConfig) return globalConfig;\n\n // 4. Default: local LibSQL file database\n return {\n backend: 'libsql',\n url: `file:${getDatabasePath()}`,\n isRemote: false,\n };\n}\n\nfunction resolveLibSQLFromEnv(): LibSQLStorageConfig {\n const url = process.env.MASTRA_DB_URL!;\n return {\n backend: 'libsql',\n url,\n authToken: process.env.MASTRA_DB_AUTH_TOKEN,\n isRemote: !url.startsWith('file:'),\n };\n}\n\nfunction resolvePgFromEnv(): PgStorageConfig {\n const connectionString = process.env.MASTRA_PG_CONNECTION_STRING;\n if (connectionString) {\n return {\n backend: 'pg',\n connectionString,\n schemaName: process.env.MASTRA_PG_SCHEMA_NAME,\n };\n }\n\n // Host/port style\n return {\n backend: 'pg',\n host: process.env.MASTRA_PG_HOST,\n port: process.env.MASTRA_PG_PORT ? parseInt(process.env.MASTRA_PG_PORT, 10) : undefined,\n database: process.env.MASTRA_PG_DATABASE,\n user: process.env.MASTRA_PG_USER,\n password: process.env.MASTRA_PG_PASSWORD,\n schemaName: process.env.MASTRA_PG_SCHEMA_NAME,\n };\n}\n\nfunction resolvePgFromSettings(settings: StorageSettings): PgStorageConfig {\n const pg = settings.pg;\n return {\n backend: 'pg',\n connectionString: pg.connectionString,\n host: pg.host,\n port: pg.port,\n database: pg.database,\n user: pg.user,\n password: pg.password,\n schemaName: pg.schemaName,\n disableInit: pg.disableInit,\n skipDefaultIndexes: pg.skipDefaultIndexes,\n };\n}\n\n/**\n * Load database config from a legacy JSON file.\n * Expected format: { \"url\": \"libsql://...\", \"authToken\": \"...\" }\n */\nfunction loadDatabaseConfig(filePath: string): LibSQLStorageConfig | null {\n try {\n if (!fs.existsSync(filePath)) return null;\n const raw = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (typeof parsed?.url === 'string' && parsed.url) {\n return {\n backend: 'libsql',\n url: parsed.url,\n authToken: typeof parsed.authToken === 'string' ? parsed.authToken : undefined,\n isRemote: !parsed.url.startsWith('file:'),\n };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the current user identity.\n *\n * Priority:\n * 1. MASTRA_USER_ID environment variable\n * 2. git config user.email (from project dir or global)\n * 3. OS username as fallback\n */\nexport function getUserId(projectDir?: string): string {\n // 1. Environment variable override\n if (process.env.MASTRA_USER_ID) {\n return process.env.MASTRA_USER_ID;\n }\n\n // 2. git user.email\n const cwd = projectDir || process.cwd();\n const email = git('config user.email', cwd);\n if (email) {\n return email;\n }\n\n // 3. OS username fallback\n return os.userInfo().username || 'unknown';\n}\n\n/**\n * Observational memory scope: \"thread\" (per-conversation) or \"resource\" (shared across threads).\n */\nexport type OmScope = 'thread' | 'resource';\n\n/**\n * Get the configured observational memory scope.\n *\n * Priority:\n * 1. MASTRA_OM_SCOPE environment variable (\"thread\" or \"resource\")\n * 2. Project config: .mastracode/database.json → omScope\n * 3. Global config: ~/.mastracode/database.json → omScope\n * 4. Default: \"thread\"\n */\nexport function getOmScope(projectDir?: string): OmScope {\n // 1. Environment variable\n const envScope = process.env.MASTRA_OM_SCOPE;\n if (envScope === 'thread' || envScope === 'resource') {\n return envScope;\n }\n\n // 2. Project-level config\n if (projectDir) {\n const scope = loadOmScopeFromConfig(path.join(projectDir, '.mastracode', 'database.json'));\n if (scope) return scope;\n }\n\n // 3. Global config\n const scope = loadOmScopeFromConfig(path.join(os.homedir(), '.mastracode', 'database.json'));\n if (scope) return scope;\n\n // 4. Default\n return 'thread';\n}\n\nfunction loadOmScopeFromConfig(filePath: string): OmScope | null {\n try {\n if (!fs.existsSync(filePath)) return null;\n const raw = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (parsed?.omScope === 'thread' || parsed?.omScope === 'resource') {\n return parsed.omScope;\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get an explicit resource ID override, if configured.\n *\n * Resource IDs act as shared tags — two users who set the same resourceId\n * will share threads and observations for that resource.\n *\n * Priority:\n * 1. MASTRA_RESOURCE_ID environment variable\n * 2. Project config: .mastracode/database.json → resourceId\n * 3. Global config: ~/.mastracode/database.json → resourceId\n * 4. null (use auto-detected value)\n */\nexport function getResourceIdOverride(projectDir?: string): string | null {\n // 1. Environment variable\n if (process.env.MASTRA_RESOURCE_ID) {\n return process.env.MASTRA_RESOURCE_ID;\n }\n\n // 2. Project-level config\n if (projectDir) {\n const rid = loadStringField(path.join(projectDir, '.mastracode', 'database.json'), 'resourceId');\n if (rid) return rid;\n }\n\n // 3. Global config\n const rid = loadStringField(path.join(os.homedir(), '.mastracode', 'database.json'), 'resourceId');\n if (rid) return rid;\n\n return null;\n}\n\nfunction loadStringField(filePath: string, field: string): string | null {\n try {\n if (!fs.existsSync(filePath)) return null;\n const raw = fs.readFileSync(filePath, 'utf-8');\n const parsed = JSON.parse(raw);\n const value = parsed?.[field];\n if (typeof value === 'string' && value) {\n return value;\n }\n return null;\n } catch {\n return null;\n }\n}\n","/**\n * PKCE utilities using Web Crypto API.\n * Works in both Node.js 20+ and browsers.\n */\n\n/**\n * Encode bytes as base64url string.\n */\nfunction base64urlEncode(bytes: Uint8Array): string {\n let binary = '';\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Generate PKCE code verifier and challenge.\n * Uses Web Crypto API for cross-platform compatibility.\n */\nexport async function generatePKCE(): Promise<{\n verifier: string;\n challenge: string;\n}> {\n // Generate random verifier\n const verifierBytes = new Uint8Array(32);\n crypto.getRandomValues(verifierBytes);\n const verifier = base64urlEncode(verifierBytes);\n\n // Compute SHA-256 challenge\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hashBuffer = await crypto.subtle.digest('SHA-256', data);\n const challenge = base64urlEncode(new Uint8Array(hashBuffer));\n\n return { verifier, challenge };\n}\n","/**\n * Anthropic OAuth flow (Claude Pro/Max)\n *\n * Inspired by pi-mono's OAuth implementation:\n * https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/utils/oauth/anthropic.ts\n */\n\nimport { generatePKCE } from '../pkce.js';\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthProviderInterface } from '../types.js';\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode('OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl');\nconst AUTHORIZE_URL = 'https://claude.ai/oauth/authorize';\nconst TOKEN_URL = 'https://console.anthropic.com/v1/oauth/token';\nconst REDIRECT_URI = 'https://console.anthropic.com/oauth/code/callback';\nconst SCOPES = 'org:create_api_key user:profile user:inference';\n\n/**\n * Login with Anthropic OAuth (device code flow)\n */\nexport async function loginAnthropic(\n onAuthUrl: (url: string) => void,\n onPromptCode: () => Promise<string>,\n): Promise<OAuthCredentials> {\n const { verifier, challenge } = await generatePKCE();\n\n // Build authorization URL\n const authParams = new URLSearchParams({\n code: 'true',\n client_id: CLIENT_ID,\n response_type: 'code',\n redirect_uri: REDIRECT_URI,\n scope: SCOPES,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n state: verifier,\n });\n\n const authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;\n\n // Notify caller with URL to open\n onAuthUrl(authUrl);\n\n // Wait for user to paste authorization code (format: code#state)\n const authCode = await onPromptCode();\n const splits = authCode.split('#');\n const code = splits[0];\n const state = splits[1];\n\n // Exchange code for tokens\n const tokenResponse = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n grant_type: 'authorization_code',\n client_id: CLIENT_ID,\n code: code,\n state: state,\n redirect_uri: REDIRECT_URI,\n code_verifier: verifier,\n }),\n });\n\n if (!tokenResponse.ok) {\n const error = await tokenResponse.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n const tokenData = (await tokenResponse.json()) as {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n };\n\n // Calculate expiry time (current time + expires_in seconds - 5 min buffer)\n const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;\n\n return {\n refresh: tokenData.refresh_token,\n access: tokenData.access_token,\n expires: expiresAt,\n };\n}\n\n/**\n * Refresh Anthropic OAuth token\n */\nexport async function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials> {\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n grant_type: 'refresh_token',\n client_id: CLIENT_ID,\n refresh_token: refreshToken,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Anthropic token refresh failed: ${error}`);\n }\n\n const data = (await response.json()) as {\n access_token: string;\n refresh_token: string;\n expires_in: number;\n };\n\n return {\n refresh: data.refresh_token,\n access: data.access_token,\n expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n };\n}\n\nexport const anthropicOAuthProvider: OAuthProviderInterface = {\n id: 'anthropic',\n name: 'Anthropic (Claude Pro/Max)',\n\n async login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n return loginAnthropic(\n url => callbacks.onAuth({ url }),\n () => callbacks.onPrompt({ message: 'Paste the authorization code:' }),\n );\n },\n\n async refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n return refreshAnthropicToken(credentials.refresh);\n },\n\n getApiKey(credentials: OAuthCredentials): string {\n return credentials.access;\n },\n};\n","/**\n * OpenAI Codex (ChatGPT OAuth) flow\n *\n * Inspired by pi-mono's OAuth implementation:\n * https://github.com/badlogic/pi-mono/blob/main/packages/ai/src/utils/oauth/openai-codex.ts\n *\n * NOTE: This module uses Node.js crypto and http for the OAuth callback.\n * It is only intended for CLI use, not browser environments.\n */\n\n// NEVER convert to top-level imports - breaks browser/Vite builds (web-ui)\nlet _randomBytes: ((size: number) => Buffer) | null = null;\n// eslint-disable-next-line @typescript-eslint/consistent-type-imports\nlet _http: typeof import('node:http') | null = null;\nif (typeof process !== 'undefined' && (process.versions?.node || process.versions?.bun)) {\n import('node:crypto').then(m => {\n _randomBytes = m.randomBytes;\n });\n import('node:http').then(m => {\n _http = m;\n });\n}\n\nimport { generatePKCE } from '../pkce.js';\nimport type { OAuthCredentials, OAuthLoginCallbacks, OAuthPrompt, OAuthProviderInterface } from '../types.js';\n\nconst CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';\nconst AUTHORIZE_URL = 'https://auth.openai.com/oauth/authorize';\nconst TOKEN_URL = 'https://auth.openai.com/oauth/token';\nconst REDIRECT_URI = 'http://localhost:1455/auth/callback';\nconst SCOPE = 'openid profile email offline_access';\nconst JWT_CLAIM_PATH = 'https://api.openai.com/auth';\n\nconst SUCCESS_HTML = `<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>Authentication successful</title>\n</head>\n<body>\n <p>Authentication successful. Return to your terminal to continue.</p>\n</body>\n</html>`;\n\ntype TokenSuccess = {\n type: 'success';\n access: string;\n refresh: string;\n expires: number;\n};\ntype TokenFailure = { type: 'failed' };\ntype TokenResult = TokenSuccess | TokenFailure;\n\ntype JwtPayload = {\n [JWT_CLAIM_PATH]?: {\n chatgpt_account_id?: string;\n };\n [key: string]: unknown;\n};\n\nfunction createState(): string {\n if (!_randomBytes) {\n throw new Error('OpenAI Codex OAuth is only available in Node.js environments');\n }\n return _randomBytes(16).toString('hex');\n}\n\nfunction parseAuthorizationInput(input: string): {\n code?: string;\n state?: string;\n} {\n const value = input.trim();\n if (!value) return {};\n\n try {\n const url = new URL(value);\n return {\n code: url.searchParams.get('code') ?? undefined,\n state: url.searchParams.get('state') ?? undefined,\n };\n } catch {\n // not a URL\n }\n\n if (value.includes('#')) {\n const [code, state] = value.split('#', 2);\n return { code, state };\n }\n\n if (value.includes('code=')) {\n const params = new URLSearchParams(value);\n return {\n code: params.get('code') ?? undefined,\n state: params.get('state') ?? undefined,\n };\n }\n\n return { code: value };\n}\n\nfunction decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n const payload = parts[1] ?? '';\n const decoded = atob(payload);\n return JSON.parse(decoded) as JwtPayload;\n } catch {\n return null;\n }\n}\n\nasync function exchangeAuthorizationCode(\n code: string,\n verifier: string,\n redirectUri: string = REDIRECT_URI,\n): Promise<TokenResult> {\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: CLIENT_ID,\n code,\n code_verifier: verifier,\n redirect_uri: redirectUri,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n console.error('[openai-codex] code->token failed:', response.status, text);\n return { type: 'failed' };\n }\n\n const json = (await response.json()) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n\n if (!json.access_token || !json.refresh_token || typeof json.expires_in !== 'number') {\n console.error('[openai-codex] token response missing fields:', json);\n return { type: 'failed' };\n }\n\n return {\n type: 'success',\n access: json.access_token,\n refresh: json.refresh_token,\n expires: Date.now() + json.expires_in * 1000,\n };\n}\n\nasync function refreshAccessToken(refreshToken: string): Promise<TokenResult> {\n try {\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: CLIENT_ID,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n console.error('[openai-codex] Token refresh failed:', response.status, text);\n return { type: 'failed' };\n }\n\n const json = (await response.json()) as {\n access_token?: string;\n refresh_token?: string;\n expires_in?: number;\n };\n\n if (!json.access_token || !json.refresh_token || typeof json.expires_in !== 'number') {\n console.error('[openai-codex] Token refresh response missing fields:', json);\n return { type: 'failed' };\n }\n\n return {\n type: 'success',\n access: json.access_token,\n refresh: json.refresh_token,\n expires: Date.now() + json.expires_in * 1000,\n };\n } catch (error) {\n console.error('[openai-codex] Token refresh error:', error);\n return { type: 'failed' };\n }\n}\n\nasync function createAuthorizationFlow(\n originator: string = 'pi',\n): Promise<{ verifier: string; state: string; url: string }> {\n const { verifier, challenge } = await generatePKCE();\n const state = createState();\n\n const url = new URL(AUTHORIZE_URL);\n url.searchParams.set('response_type', 'code');\n url.searchParams.set('client_id', CLIENT_ID);\n url.searchParams.set('redirect_uri', REDIRECT_URI);\n url.searchParams.set('scope', SCOPE);\n url.searchParams.set('code_challenge', challenge);\n url.searchParams.set('code_challenge_method', 'S256');\n url.searchParams.set('state', state);\n url.searchParams.set('id_token_add_organizations', 'true');\n url.searchParams.set('codex_cli_simplified_flow', 'true');\n url.searchParams.set('originator', originator);\n\n return { verifier, state, url: url.toString() };\n}\n\ntype OAuthServerInfo = {\n close: () => void;\n cancelWait: () => void;\n waitForCode: () => Promise<{ code: string } | null>;\n};\n\nfunction startLocalOAuthServer(state: string): Promise<OAuthServerInfo> {\n if (!_http) {\n throw new Error('OpenAI Codex OAuth is only available in Node.js environments');\n }\n let lastCode: string | null = null;\n let cancelled = false;\n const server = _http.createServer((req, res) => {\n try {\n const url = new URL(req.url || '', 'http://localhost');\n if (url.pathname !== '/auth/callback') {\n res.statusCode = 404;\n res.end('Not found');\n return;\n }\n if (url.searchParams.get('state') !== state) {\n res.statusCode = 400;\n res.end('State mismatch');\n return;\n }\n const code = url.searchParams.get('code');\n if (!code) {\n res.statusCode = 400;\n res.end('Missing authorization code');\n return;\n }\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.end(SUCCESS_HTML);\n lastCode = code;\n } catch {\n res.statusCode = 500;\n res.end('Internal error');\n }\n });\n\n return new Promise(resolve => {\n server\n .listen(1455, '127.0.0.1', () => {\n resolve({\n close: () => server.close(),\n cancelWait: () => {\n cancelled = true;\n },\n waitForCode: async () => {\n const sleep = () => new Promise(r => setTimeout(r, 100));\n for (let i = 0; i < 600; i += 1) {\n if (lastCode) return { code: lastCode };\n if (cancelled) return null;\n await sleep();\n }\n return null;\n },\n });\n })\n .on('error', (err: NodeJS.ErrnoException) => {\n console.error(\n '[openai-codex] Failed to bind http://127.0.0.1:1455 (',\n err.code,\n ') Falling back to manual paste.',\n );\n resolve({\n close: () => {\n try {\n server.close();\n } catch {\n // ignore\n }\n },\n cancelWait: () => {},\n waitForCode: async () => null,\n });\n });\n });\n}\n\nfunction getAccountId(accessToken: string): string | null {\n const payload = decodeJwt(accessToken);\n const auth = payload?.[JWT_CLAIM_PATH];\n const accountId = auth?.chatgpt_account_id;\n return typeof accountId === 'string' && accountId.length > 0 ? accountId : null;\n}\n\n/**\n * Login with OpenAI Codex OAuth\n *\n * @param options.onAuth - Called with URL and instructions when auth starts\n * @param options.onPrompt - Called to prompt user for manual code paste (fallback if no onManualCodeInput)\n * @param options.onProgress - Optional progress messages\n * @param options.onManualCodeInput - Optional promise that resolves with user-pasted code.\n * Races with browser callback - whichever completes first wins.\n * Useful for showing paste input immediately alongside browser flow.\n * @param options.originator - OAuth originator parameter (defaults to \"pi\")\n */\nexport async function loginOpenAICodex(options: {\n onAuth: (info: { url: string; instructions?: string }) => void;\n onPrompt: (prompt: OAuthPrompt) => Promise<string>;\n onProgress?: (message: string) => void;\n onManualCodeInput?: () => Promise<string>;\n originator?: string;\n}): Promise<OAuthCredentials> {\n const { verifier, state, url } = await createAuthorizationFlow(options.originator);\n const server = await startLocalOAuthServer(state);\n\n options.onAuth({\n url,\n instructions: 'A browser window should open. Complete login to finish.',\n });\n\n let code: string | undefined;\n try {\n if (options.onManualCodeInput) {\n // Race between browser callback and manual input\n let manualCode: string | undefined;\n let manualError: Error | undefined;\n const manualPromise = options\n .onManualCodeInput()\n .then(input => {\n manualCode = input;\n server.cancelWait();\n })\n .catch(err => {\n manualError = err instanceof Error ? err : new Error(String(err));\n server.cancelWait();\n });\n\n const result = await server.waitForCode();\n\n // If manual input was cancelled, throw that error\n if (manualError) {\n throw manualError;\n }\n\n if (result?.code) {\n // Browser callback won\n code = result.code;\n } else if (manualCode) {\n // Manual input won (or callback timed out and user had entered code)\n const parsed = parseAuthorizationInput(manualCode);\n if (parsed.state && parsed.state !== state) {\n throw new Error('State mismatch');\n }\n code = parsed.code;\n }\n\n // If still no code, wait for manual promise to complete and try that\n if (!code) {\n await manualPromise;\n if (manualError) {\n throw manualError;\n }\n if (manualCode) {\n const parsed = parseAuthorizationInput(manualCode);\n if (parsed.state && parsed.state !== state) {\n throw new Error('State mismatch');\n }\n code = parsed.code;\n }\n }\n } else {\n // Original flow: wait for callback, then prompt if needed\n const result = await server.waitForCode();\n if (result?.code) {\n code = result.code;\n }\n }\n\n // Fallback to onPrompt if still no code\n if (!code) {\n const input = await options.onPrompt({\n message: 'Paste the authorization code (or full redirect URL):',\n });\n const parsed = parseAuthorizationInput(input);\n if (parsed.state && parsed.state !== state) {\n throw new Error('State mismatch');\n }\n code = parsed.code;\n }\n\n if (!code) {\n throw new Error('Missing authorization code');\n }\n\n const tokenResult = await exchangeAuthorizationCode(code, verifier);\n if (tokenResult.type !== 'success') {\n throw new Error('Token exchange failed');\n }\n\n const accountId = getAccountId(tokenResult.access);\n if (!accountId) {\n throw new Error('Failed to extract accountId from token');\n }\n\n return {\n access: tokenResult.access,\n refresh: tokenResult.refresh,\n expires: tokenResult.expires,\n accountId,\n };\n } finally {\n server.close();\n }\n}\n\n/**\n * Refresh OpenAI Codex OAuth token\n */\nexport async function refreshOpenAICodexToken(refreshToken: string): Promise<OAuthCredentials> {\n const result = await refreshAccessToken(refreshToken);\n if (result.type !== 'success') {\n throw new Error('Failed to refresh OpenAI Codex token');\n }\n\n const accountId = getAccountId(result.access);\n if (!accountId) {\n throw new Error('Failed to extract accountId from token');\n }\n\n return {\n access: result.access,\n refresh: result.refresh,\n expires: result.expires,\n accountId,\n };\n}\n\nexport const openaiCodexOAuthProvider: OAuthProviderInterface = {\n id: 'openai-codex',\n name: 'ChatGPT Plus/Pro (Codex Subscription)',\n usesCallbackServer: true,\n\n async login(callbacks: OAuthLoginCallbacks): Promise<OAuthCredentials> {\n return loginOpenAICodex({\n onAuth: callbacks.onAuth,\n onPrompt: callbacks.onPrompt,\n onProgress: callbacks.onProgress,\n onManualCodeInput: callbacks.onManualCodeInput,\n });\n },\n\n async refreshToken(credentials: OAuthCredentials): Promise<OAuthCredentials> {\n return refreshOpenAICodexToken(credentials.refresh);\n },\n\n getApiKey(credentials: OAuthCredentials): string {\n return credentials.access;\n },\n};\n","/**\n * Credential storage for API keys and OAuth tokens.\n * Handles loading, saving, and refreshing credentials from auth.json.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { getAppDataDir } from '../utils/project.js';\nimport { anthropicOAuthProvider } from './providers/anthropic.js';\nimport { openaiCodexOAuthProvider } from './providers/openai-codex.js';\nimport type {\n AuthCredential,\n AuthStorageData,\n OAuthLoginCallbacks,\n OAuthProviderId,\n OAuthProviderInterface,\n} from './types.js';\n\n/**\n * Best/default models for each OAuth provider.\n * Used when auto-selecting a model after login.\n */\nexport const PROVIDER_DEFAULT_MODELS: Record<OAuthProviderId, string> = {\n anthropic: 'anthropic/claude-opus-4-6',\n 'openai-codex': 'openai/gpt-5.2-codex',\n};\n\n// Provider registry\nconst oauthProviderRegistry = new Map<string, OAuthProviderInterface>([\n [anthropicOAuthProvider.id, anthropicOAuthProvider],\n [openaiCodexOAuthProvider.id, openaiCodexOAuthProvider],\n]);\n\n/**\n * Get an OAuth provider by ID\n */\nexport function getOAuthProvider(id: OAuthProviderId): OAuthProviderInterface | undefined {\n return oauthProviderRegistry.get(id);\n}\n\n/**\n * Get all registered OAuth providers\n */\nexport function getOAuthProviders(): OAuthProviderInterface[] {\n return Array.from(oauthProviderRegistry.values());\n}\n\n/**\n * Credential storage backed by a JSON file.\n */\nexport class AuthStorage {\n private data: AuthStorageData = {};\n\n constructor(private authPath: string = join(getAppDataDir(), 'auth.json')) {\n this.reload();\n }\n\n /**\n * Reload credentials from disk.\n */\n reload(): void {\n if (!existsSync(this.authPath)) {\n this.data = {};\n return;\n }\n try {\n this.data = JSON.parse(readFileSync(this.authPath, 'utf-8'));\n } catch {\n this.data = {};\n }\n }\n\n /**\n * Save credentials to disk.\n */\n private save(): void {\n const dir = dirname(this.authPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 });\n }\n writeFileSync(this.authPath, JSON.stringify(this.data, null, 2), 'utf-8');\n chmodSync(this.authPath, 0o600);\n }\n\n /**\n * Get credential for a provider.\n */\n get(provider: string): AuthCredential | undefined {\n return this.data[provider] ?? undefined;\n }\n\n /**\n * Set credential for a provider.\n */\n set(provider: string, credential: AuthCredential): void {\n this.data[provider] = credential;\n this.save();\n }\n\n /**\n * Remove credential for a provider.\n */\n remove(provider: string): void {\n delete this.data[provider];\n this.save();\n }\n\n /**\n * List all providers with credentials.\n */\n list(): string[] {\n return Object.keys(this.data);\n }\n\n /**\n * Check if credentials exist for a provider.\n */\n has(provider: string): boolean {\n return provider in this.data;\n }\n\n /**\n * Check if logged in via OAuth for a provider.\n */\n isLoggedIn(provider: string): boolean {\n const cred = this.data[provider];\n return cred?.type === 'oauth';\n }\n\n /**\n * Check if a stored API key exists for a provider.\n * Keys are stored under `apikey:<provider>` in auth.json.\n */\n hasStoredApiKey(provider: string): boolean {\n const cred = this.data[`apikey:${provider}`];\n return cred?.type === 'api_key' && cred.key.length > 0;\n }\n\n /**\n * Get a stored API key for a provider, if any.\n */\n getStoredApiKey(provider: string): string | undefined {\n const cred = this.data[`apikey:${provider}`];\n return cred?.type === 'api_key' && cred.key.length > 0 ? cred.key : undefined;\n }\n\n /**\n * Store an API key for a provider.\n * Also sets the corresponding environment variable so model resolution can find it.\n */\n setStoredApiKey(provider: string, key: string, envVar?: string): void {\n this.set(`apikey:${provider}`, { type: 'api_key', key });\n if (envVar) {\n process.env[envVar] = key;\n }\n }\n\n /**\n * Load all stored API keys into process.env.\n * Called at startup so model resolution can find stored keys.\n * Only sets env vars that aren't already set (env vars take precedence).\n */\n loadStoredApiKeysIntoEnv(providerEnvVars: Record<string, string | undefined>): void {\n for (const [key, cred] of Object.entries(this.data)) {\n if (!key.startsWith('apikey:') || cred.type !== 'api_key' || !cred.key) continue;\n const provider = key.substring('apikey:'.length);\n const envVar = providerEnvVars[provider];\n if (envVar && !process.env[envVar]) {\n process.env[envVar] = cred.key;\n }\n }\n }\n\n /**\n * Login to an OAuth provider.\n */\n async login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void> {\n const provider = getOAuthProvider(providerId);\n if (!provider) {\n throw new Error(`Unknown OAuth provider: ${providerId}`);\n }\n\n const credentials = await provider.login(callbacks);\n this.set(providerId, { type: 'oauth', ...credentials });\n }\n\n /**\n * Logout from a provider.\n */\n logout(provider: string): void {\n this.remove(provider);\n }\n\n /**\n * Get API key for a provider, auto-refreshing OAuth tokens if needed.\n */\n async getApiKey(providerId: string): Promise<string | undefined> {\n const cred = this.data[providerId];\n\n if (cred?.type === 'api_key') {\n return cred.key;\n }\n\n if (cred?.type === 'oauth') {\n const provider = getOAuthProvider(providerId);\n if (!provider) {\n return undefined;\n }\n\n // Check if token needs refresh\n if (Date.now() >= cred.expires) {\n try {\n const newCreds = await provider.refreshToken(cred);\n this.set(providerId, { type: 'oauth', ...newCreds });\n return provider.getApiKey(newCreds);\n } catch {\n // Refresh failed - user needs to re-login\n return undefined;\n }\n }\n\n return provider.getApiKey(cred);\n }\n\n return undefined;\n }\n}\n"]}
|