@dmrlzz/davecode 0.5.0 → 0.5.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/dist/{ChatApp-CJBICQGA.js → ChatApp-YMHKIAAH.js} +6 -6
- package/dist/{account-QWDPJWAA.js → account-5QFYCVYM.js} +3 -3
- package/dist/{accounts-IQMR72FC.js → accounts-756BMMAL.js} +5 -5
- package/dist/{budget-XANOUVWO.js → budget-PGSNCVVK.js} +4 -4
- package/dist/{chat-KDDRNC5V.js → chat-D3T4YG5D.js} +8 -8
- package/dist/{chunk-AZKACMME.js → chunk-6SHOBL2X.js} +2 -2
- package/dist/{chunk-WQ7MEWDF.js → chunk-6WUVR3R2.js} +10 -4
- package/dist/chunk-6WUVR3R2.js.map +1 -0
- package/dist/{chunk-HSBJDV3O.js → chunk-HENE4DA6.js} +240 -22
- package/dist/chunk-HENE4DA6.js.map +1 -0
- package/dist/{chunk-W7GPBEBZ.js → chunk-IOATP7KH.js} +2 -2
- package/dist/{chunk-FYPMA55O.js → chunk-JFWMLYV7.js} +111 -19
- package/dist/chunk-JFWMLYV7.js.map +1 -0
- package/dist/{chunk-44AFJL2X.js → chunk-JSRPO2AR.js} +6 -5
- package/dist/chunk-JSRPO2AR.js.map +1 -0
- package/dist/{chunk-JLATEHS7.js → chunk-K5AA65RS.js} +2 -2
- package/dist/{chunk-PGAJIGUF.js → chunk-ZNUNYYN6.js} +3 -3
- package/dist/{config-YTUPIYZT.js → config-TKGGYEN7.js} +3 -3
- package/dist/dashboard/assets/Accounts-DciFUg4y.js +1 -0
- package/dist/dashboard/assets/{Badge-Z4RBdO9j.js → Badge-DUGKlx3Z.js} +1 -1
- package/dist/dashboard/assets/{Callout-w8BTYh4k.js → Callout-WgXHDPg0.js} +1 -1
- package/dist/dashboard/assets/{Goals-Bw02to72.js → Goals-C6HL1PNE.js} +1 -1
- package/dist/dashboard/assets/{Library-DK7mlpRb.js → Library-DwpBYTbK.js} +1 -1
- package/dist/dashboard/assets/Markdown-CGgIydUh.js +71 -0
- package/dist/dashboard/assets/{Panes-_KTf8pbZ.js → Panes-DxFSwhb7.js} +1 -1
- package/dist/dashboard/assets/{RoutesPage-QV0oPRW9.js → RoutesPage-Cyo0MNd7.js} +1 -1
- package/dist/dashboard/assets/{Runner-CkHBLQl0.js → Runner-CIL7RxpN.js} +1 -1
- package/dist/dashboard/assets/{Settings-BLz2gTBR.js → Settings-B_PEB585.js} +1 -1
- package/dist/dashboard/assets/{Tasks-BiUQSTpt.js → Tasks-DEfPSaE6.js} +1 -1
- package/dist/dashboard/assets/{Traffic-BVfBuC70.js → Traffic-Dcz-WhsP.js} +1 -1
- package/dist/dashboard/assets/{Workspace-CJTgiiU5.js → Workspace-9UCw9q7C.js} +1 -1
- package/dist/dashboard/assets/{index-BDBa5cb0.js → index-CpztPbom.js} +3 -3
- package/dist/dashboard/assets/{task-errors-Daqwi0ue.js → task-errors-r-WYZ_S3.js} +1 -1
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-37VQSHHA.js → dist-F3NRJ5FK.js} +18 -2
- package/dist/{doctor-PYUQRRCB.js → doctor-V4XXVVGK.js} +3 -3
- package/dist/{goal-SXZUDUCL.js → goal-RUHYPVPA.js} +3 -3
- package/dist/index.js +31 -31
- package/dist/{init-Z2AFQEEP.js → init-54FKQZ2Z.js} +3 -3
- package/dist/{run-AOS7L3RT.js → run-4R25J2VN.js} +3 -3
- package/dist/runtime.js +2 -2
- package/dist/{start-CEPXKZUE.js → start-GRHW3TGE.js} +3 -3
- package/dist/{status-WNJ3GGKU.js → status-QR2HNPBK.js} +4 -4
- package/dist/{tasks-TFUTUMWB.js → tasks-BHWDV4JS.js} +4 -4
- package/package.json +6 -6
- package/dist/chunk-44AFJL2X.js.map +0 -1
- package/dist/chunk-FYPMA55O.js.map +0 -1
- package/dist/chunk-HSBJDV3O.js.map +0 -1
- package/dist/chunk-WQ7MEWDF.js.map +0 -1
- package/dist/dashboard/assets/Accounts-cq8RLMoI.js +0 -1
- package/dist/dashboard/assets/Markdown-DCZ4Awcc.js +0 -69
- /package/dist/{ChatApp-CJBICQGA.js.map → ChatApp-YMHKIAAH.js.map} +0 -0
- /package/dist/{account-QWDPJWAA.js.map → account-5QFYCVYM.js.map} +0 -0
- /package/dist/{accounts-IQMR72FC.js.map → accounts-756BMMAL.js.map} +0 -0
- /package/dist/{budget-XANOUVWO.js.map → budget-PGSNCVVK.js.map} +0 -0
- /package/dist/{chat-KDDRNC5V.js.map → chat-D3T4YG5D.js.map} +0 -0
- /package/dist/{chunk-AZKACMME.js.map → chunk-6SHOBL2X.js.map} +0 -0
- /package/dist/{chunk-W7GPBEBZ.js.map → chunk-IOATP7KH.js.map} +0 -0
- /package/dist/{chunk-JLATEHS7.js.map → chunk-K5AA65RS.js.map} +0 -0
- /package/dist/{chunk-PGAJIGUF.js.map → chunk-ZNUNYYN6.js.map} +0 -0
- /package/dist/{config-YTUPIYZT.js.map → config-TKGGYEN7.js.map} +0 -0
- /package/dist/{dist-37VQSHHA.js.map → dist-F3NRJ5FK.js.map} +0 -0
- /package/dist/{doctor-PYUQRRCB.js.map → doctor-V4XXVVGK.js.map} +0 -0
- /package/dist/{goal-SXZUDUCL.js.map → goal-RUHYPVPA.js.map} +0 -0
- /package/dist/{init-Z2AFQEEP.js.map → init-54FKQZ2Z.js.map} +0 -0
- /package/dist/{run-AOS7L3RT.js.map → run-4R25J2VN.js.map} +0 -0
- /package/dist/{start-CEPXKZUE.js.map → start-GRHW3TGE.js.map} +0 -0
- /package/dist/{status-WNJ3GGKU.js.map → status-QR2HNPBK.js.map} +0 -0
- /package/dist/{tasks-TFUTUMWB.js.map → tasks-BHWDV4JS.js.map} +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
formatTaskTree,
|
|
3
3
|
summaryLine
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6SHOBL2X.js";
|
|
5
5
|
import {
|
|
6
6
|
brandBanner
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-K5AA65RS.js";
|
|
8
8
|
import {
|
|
9
9
|
Spinner
|
|
10
10
|
} from "./chunk-5LKOJBUL.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import {
|
|
16
16
|
emptyUsage,
|
|
17
17
|
renderAccounts
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZNUNYYN6.js";
|
|
19
19
|
import {
|
|
20
20
|
bar,
|
|
21
21
|
formatTokens,
|
|
@@ -25,9 +25,9 @@ import {
|
|
|
25
25
|
visibleWidth
|
|
26
26
|
} from "./chunk-SF5ZEAP4.js";
|
|
27
27
|
import "./chunk-QA3O6RA2.js";
|
|
28
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-JFWMLYV7.js";
|
|
29
29
|
import "./chunk-7XVXEO7U.js";
|
|
30
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-HENE4DA6.js";
|
|
31
31
|
import "./chunk-MC7RIPL7.js";
|
|
32
32
|
|
|
33
33
|
// src/tui/ChatApp.tsx
|
|
@@ -1042,4 +1042,4 @@ function ChatApp(props) {
|
|
|
1042
1042
|
export {
|
|
1043
1043
|
ChatApp
|
|
1044
1044
|
};
|
|
1045
|
-
//# sourceMappingURL=ChatApp-
|
|
1045
|
+
//# sourceMappingURL=ChatApp-YMHKIAAH.js.map
|
|
@@ -7,9 +7,9 @@ import {
|
|
|
7
7
|
loginCommand,
|
|
8
8
|
logoutCommand,
|
|
9
9
|
signIn
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IOATP7KH.js";
|
|
11
11
|
import "./chunk-7XVXEO7U.js";
|
|
12
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-HENE4DA6.js";
|
|
13
13
|
export {
|
|
14
14
|
accountCommand,
|
|
15
15
|
accountsEnabled,
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
logoutCommand,
|
|
21
21
|
signIn
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=account-
|
|
23
|
+
//# sourceMappingURL=account-5QFYCVYM.js.map
|
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
loginArgs,
|
|
12
12
|
renderAccountList,
|
|
13
13
|
subscriptionFromFlags
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-JSRPO2AR.js";
|
|
15
|
+
import "./chunk-6WUVR3R2.js";
|
|
16
16
|
import "./chunk-IC3TDONV.js";
|
|
17
17
|
import "./chunk-SF5ZEAP4.js";
|
|
18
18
|
import "./chunk-QA3O6RA2.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-JFWMLYV7.js";
|
|
20
20
|
import "./chunk-7XVXEO7U.js";
|
|
21
|
-
import "./chunk-
|
|
21
|
+
import "./chunk-HENE4DA6.js";
|
|
22
22
|
import "./chunk-MC7RIPL7.js";
|
|
23
23
|
export {
|
|
24
24
|
accountsAdd,
|
|
@@ -34,4 +34,4 @@ export {
|
|
|
34
34
|
renderAccountList,
|
|
35
35
|
subscriptionFromFlags
|
|
36
36
|
};
|
|
37
|
-
//# sourceMappingURL=accounts-
|
|
37
|
+
//# sourceMappingURL=accounts-756BMMAL.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
openAccounts
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6WUVR3R2.js";
|
|
4
4
|
import {
|
|
5
5
|
bar,
|
|
6
6
|
levelStyle,
|
|
@@ -13,11 +13,11 @@ import {
|
|
|
13
13
|
} from "./chunk-QA3O6RA2.js";
|
|
14
14
|
import {
|
|
15
15
|
detectProjectRoot
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-JFWMLYV7.js";
|
|
17
17
|
import {
|
|
18
18
|
EXIT
|
|
19
19
|
} from "./chunk-7XVXEO7U.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-HENE4DA6.js";
|
|
21
21
|
import "./chunk-MC7RIPL7.js";
|
|
22
22
|
|
|
23
23
|
// src/commands/budget.ts
|
|
@@ -112,4 +112,4 @@ export {
|
|
|
112
112
|
budgetCommand,
|
|
113
113
|
renderBudget
|
|
114
114
|
};
|
|
115
|
-
//# sourceMappingURL=budget-
|
|
115
|
+
//# sourceMappingURL=budget-PGSNCVVK.js.map
|
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
currentAccount,
|
|
5
5
|
describeUser,
|
|
6
6
|
signIn
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IOATP7KH.js";
|
|
8
8
|
import {
|
|
9
9
|
accountsLogin
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-JSRPO2AR.js";
|
|
11
11
|
import {
|
|
12
12
|
openAccounts
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-6WUVR3R2.js";
|
|
14
14
|
import {
|
|
15
15
|
PromptCancelledError
|
|
16
16
|
} from "./chunk-IC3TDONV.js";
|
|
17
17
|
import {
|
|
18
18
|
brandBanner
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-K5AA65RS.js";
|
|
20
20
|
import "./chunk-SF5ZEAP4.js";
|
|
21
21
|
import {
|
|
22
22
|
readPreferences,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
findGateway,
|
|
29
29
|
startRuntime,
|
|
30
30
|
which
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-JFWMLYV7.js";
|
|
32
32
|
import {
|
|
33
33
|
CliError,
|
|
34
34
|
EXIT
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
VERSION,
|
|
39
39
|
loadConfig,
|
|
40
40
|
writeGlobalRouting
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-HENE4DA6.js";
|
|
42
42
|
import {
|
|
43
43
|
createTheme
|
|
44
44
|
} from "./chunk-MC7RIPL7.js";
|
|
@@ -328,7 +328,7 @@ async function runChat(ctx, opts, projectRoot) {
|
|
|
328
328
|
const [{ render }, { createElement }, { ChatApp }] = await Promise.all([
|
|
329
329
|
import("ink"),
|
|
330
330
|
import("react"),
|
|
331
|
-
import("./ChatApp-
|
|
331
|
+
import("./ChatApp-YMHKIAAH.js")
|
|
332
332
|
]);
|
|
333
333
|
const instance = render(
|
|
334
334
|
createElement(ChatApp, {
|
|
@@ -356,4 +356,4 @@ async function runChat(ctx, opts, projectRoot) {
|
|
|
356
356
|
export {
|
|
357
357
|
chatCommand
|
|
358
358
|
};
|
|
359
|
-
//# sourceMappingURL=chat-
|
|
359
|
+
//# sourceMappingURL=chat-D3T4YG5D.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
nextTask,
|
|
8
8
|
summarize,
|
|
9
9
|
topologicalOrder
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-HENE4DA6.js";
|
|
11
11
|
|
|
12
12
|
// src/lib/task-tree.ts
|
|
13
13
|
function statusGlyph(theme, task, blocked) {
|
|
@@ -111,4 +111,4 @@ export {
|
|
|
111
111
|
formatTaskTree,
|
|
112
112
|
formatTaskDetail
|
|
113
113
|
};
|
|
114
|
-
//# sourceMappingURL=chunk-
|
|
114
|
+
//# sourceMappingURL=chunk-6SHOBL2X.js.map
|
|
@@ -2,13 +2,14 @@ import {
|
|
|
2
2
|
accountCreateSchema,
|
|
3
3
|
accountPatchSchema,
|
|
4
4
|
findGateway
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JFWMLYV7.js";
|
|
6
6
|
import {
|
|
7
7
|
CliError
|
|
8
8
|
} from "./chunk-7XVXEO7U.js";
|
|
9
9
|
import {
|
|
10
|
-
createEngine
|
|
11
|
-
|
|
10
|
+
createEngine,
|
|
11
|
+
endpointRebindIssue
|
|
12
|
+
} from "./chunk-HENE4DA6.js";
|
|
12
13
|
|
|
13
14
|
// src/lib/accounts-backend.ts
|
|
14
15
|
import { z } from "zod";
|
|
@@ -53,6 +54,11 @@ var LocalAccounts = class {
|
|
|
53
54
|
const existing = this.engine.accounts.get(id);
|
|
54
55
|
if (!existing) throw notFound(id);
|
|
55
56
|
const { secret, ...fields } = parsed.data;
|
|
57
|
+
const rebind = endpointRebindIssue(existing, fields.config, secret !== void 0);
|
|
58
|
+
if (rebind)
|
|
59
|
+
throw new CliError(rebind, {
|
|
60
|
+
hint: "Pass the key again with --secret-env or --secret-stdin."
|
|
61
|
+
});
|
|
56
62
|
const update = { ...fields };
|
|
57
63
|
const enabled = fields.enabled ?? existing.enabled;
|
|
58
64
|
if (!enabled) {
|
|
@@ -177,4 +183,4 @@ export {
|
|
|
177
183
|
openAccounts,
|
|
178
184
|
resolveAccount
|
|
179
185
|
};
|
|
180
|
-
//# sourceMappingURL=chunk-
|
|
186
|
+
//# sourceMappingURL=chunk-6WUVR3R2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/accounts-backend.ts"],"sourcesContent":["import {\n type Account,\n type AccountConnection,\n type AccountUpdateInput,\n type BudgetSnapshot,\n createEngine,\n type DaveConfig,\n type Engine,\n endpointRebindIssue,\n type ProviderKind,\n type QuotaLimits,\n type SubscriptionInfo,\n} from '@davecode/core';\nimport { accountCreateSchema, accountPatchSchema } from '@davecode/server';\nimport { z } from 'zod';\nimport { findGateway, type GatewayClient } from '../client';\nimport { CliError } from '../errors';\n\n/** Body of `POST /api/accounts` (secret is write-only). */\nexport interface AccountCreate {\n provider: ProviderKind;\n label: string;\n enabled?: boolean;\n priority?: number;\n weight?: number;\n limits?: QuotaLimits;\n config?: Record<string, unknown>;\n subscription?: SubscriptionInfo;\n secret?: string;\n}\n\nexport type AccountPatch = Partial<Omit<AccountCreate, 'provider' | 'subscription'>> & {\n /** Replaces the subscription details; `null` clears them. */\n subscription?: SubscriptionInfo | null;\n};\n\n/**\n * Account operations against a running gateway (so the dashboard sees the change live) or, when\n * none is running, directly against `state.db` with the same validation and audit trail.\n */\nexport interface AccountsBackend {\n readonly kind: 'gateway' | 'local';\n readonly config: DaveConfig;\n list(): Promise<Account[]>;\n get(id: string): Promise<Account | undefined>;\n create(input: AccountCreate): Promise<Account>;\n update(id: string, patch: AccountPatch): Promise<Account>;\n remove(id: string): Promise<void>;\n /** Subscription details and remaining capacity per account. */\n budget(): Promise<BudgetSnapshot>;\n /** Whether the account's API key or vendor CLI login is in place. */\n connection(id: string): Promise<AccountConnection>;\n close(): void;\n}\n\nfunction invalid(error: z.ZodError): CliError {\n return new CliError(`Invalid account: ${z.prettifyError(error)}`);\n}\n\nexport class LocalAccounts implements AccountsBackend {\n readonly kind = 'local' as const;\n\n constructor(readonly engine: Engine) {}\n\n get config(): DaveConfig {\n return this.engine.config;\n }\n\n async list(): Promise<Account[]> {\n return this.engine.accounts.list();\n }\n\n async get(id: string): Promise<Account | undefined> {\n return this.engine.accounts.get(id);\n }\n\n async create(input: AccountCreate): Promise<Account> {\n const parsed = accountCreateSchema.safeParse(input);\n if (!parsed.success) throw invalid(parsed.error);\n const { secret, ...fields } = parsed.data;\n const { accounts, keyring, audit, db } = this.engine;\n return db.transaction(() => {\n const created = accounts.create(fields);\n if (secret !== undefined) keyring.set(created.id, secret);\n audit.record({\n actor: 'cli',\n action: 'account.create',\n target: created.id,\n details: { provider: created.provider, label: created.label, hasSecret: !!secret },\n });\n return created;\n })();\n }\n\n async update(id: string, patch: AccountPatch): Promise<Account> {\n const parsed = accountPatchSchema.safeParse(patch);\n if (!parsed.success) throw invalid(parsed.error);\n const existing = this.engine.accounts.get(id);\n if (!existing) throw notFound(id);\n const { secret, ...fields } = parsed.data;\n // The machine's owner may set any config key, but a stored secret still never follows an\n // account to a different endpoint without being supplied again.\n const rebind = endpointRebindIssue(existing, fields.config, secret !== undefined);\n if (rebind)\n throw new CliError(rebind, {\n hint: 'Pass the key again with --secret-env or --secret-stdin.',\n });\n const update: AccountUpdateInput = { ...fields };\n const enabled = fields.enabled ?? existing.enabled;\n if (!enabled) {\n update.status = 'disabled';\n } else if (fields.enabled === true || secret !== undefined) {\n update.status = 'active';\n update.cooldownUntil = null;\n update.lastError = null;\n }\n const { accounts, keyring, audit, db } = this.engine;\n return db.transaction(() => {\n const updated = accounts.update(id, update)!;\n if (secret !== undefined) keyring.set(id, secret);\n audit.record({\n actor: 'cli',\n action: 'account.update',\n target: id,\n details: { fields: Object.keys(fields), secretChanged: secret !== undefined },\n });\n return updated;\n })();\n }\n\n async remove(id: string): Promise<void> {\n const { accounts, sandboxes, chromium, audit } = this.engine;\n if (!accounts.delete(id)) throw notFound(id);\n for (const cleanup of [() => sandboxes.remove(id), () => chromium.remove(id)]) {\n try {\n cleanup();\n } catch {\n // A leftover directory is harmless; the account row is gone.\n }\n }\n audit.record({ actor: 'cli', action: 'account.delete', target: id });\n }\n\n /** Quota windows are rebuilt from state.db; provider-reported limits live in the gateway only. */\n async budget(): Promise<BudgetSnapshot> {\n return this.engine.budget.snapshot();\n }\n\n async connection(id: string): Promise<AccountConnection> {\n const account = this.engine.accounts.get(id);\n if (!account) throw notFound(id);\n return this.engine.connections.check(account);\n }\n\n close(): void {\n this.engine.close();\n }\n}\n\nexport class GatewayAccounts implements AccountsBackend {\n readonly kind = 'gateway' as const;\n\n constructor(\n readonly client: GatewayClient,\n readonly config: DaveConfig,\n ) {}\n\n async list(): Promise<Account[]> {\n return (await this.client.get<{ accounts: Account[] }>('/api/accounts')).accounts;\n }\n\n async get(id: string): Promise<Account | undefined> {\n return (await this.list()).find((a) => a.id === id);\n }\n\n async create(input: AccountCreate): Promise<Account> {\n return (await this.client.post<{ account: Account }>('/api/accounts', input)).account;\n }\n\n async update(id: string, patch: AccountPatch): Promise<Account> {\n return (\n await this.client.patch<{ account: Account }>(\n `/api/accounts/${encodeURIComponent(id)}`,\n patch,\n )\n ).account;\n }\n\n async remove(id: string): Promise<void> {\n await this.client.delete(`/api/accounts/${encodeURIComponent(id)}`);\n }\n\n async budget(): Promise<BudgetSnapshot> {\n return (await this.client.get<{ budget: BudgetSnapshot }>('/api/budget')).budget;\n }\n\n async connection(id: string): Promise<AccountConnection> {\n return (\n await this.client.get<{ connection: AccountConnection }>(\n `/api/accounts/${encodeURIComponent(id)}/connection`,\n )\n ).connection;\n }\n\n close(): void {}\n}\n\nfunction notFound(id: string): CliError {\n return new CliError(`No account with id ${JSON.stringify(id)}`, {\n hint: 'List accounts with `davecode accounts list`.',\n });\n}\n\n/** Prefer the running gateway; fall back to the local database. */\nexport async function openAccounts(options: {\n home: string;\n env: NodeJS.ProcessEnv;\n projectRoot?: string;\n /** Skip the gateway probe (tests, or `--local`). */\n local?: boolean;\n}): Promise<AccountsBackend> {\n const engine = createEngine({\n home: options.home,\n env: options.env,\n ...(options.projectRoot ? { projectRoot: options.projectRoot } : {}),\n });\n if (!options.local) {\n const gateway = await findGateway(engine.config).catch(() => undefined);\n if (gateway) {\n const config = engine.config;\n engine.close();\n return new GatewayAccounts(gateway.client, config);\n }\n }\n return new LocalAccounts(engine);\n}\n\n/** Resolve an account by exact id, or by unique label/id prefix for convenience. */\nexport async function resolveAccount(backend: AccountsBackend, ref: string): Promise<Account> {\n const accounts = await backend.list();\n const exact = accounts.find((a) => a.id === ref);\n if (exact) return exact;\n const matches = accounts.filter(\n (a) => a.label.toLowerCase() === ref.toLowerCase() || a.id.startsWith(ref),\n );\n if (matches.length === 1) return matches[0]!;\n if (matches.length > 1) {\n throw new CliError(`${JSON.stringify(ref)} matches ${matches.length} accounts`, {\n hint: `Use the full id: ${matches.map((a) => a.id).join(', ')}`,\n });\n }\n throw notFound(ref);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -116,7 +116,7 @@ import { z as z8 } from "zod";
|
|
|
116
116
|
import { randomBytes as randomBytes7 } from "crypto";
|
|
117
117
|
import { createServer } from "http";
|
|
118
118
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes8 } from "crypto";
|
|
119
|
-
import { mkdirSync as mkdirSync7, readFileSync as readFileSync3, rmSync as rmSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
119
|
+
import { mkdirSync as mkdirSync7, readFileSync as readFileSync3, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
120
120
|
import { dirname as dirname6, join as join6 } from "path";
|
|
121
121
|
import { z as z9 } from "zod";
|
|
122
122
|
import { z as z10 } from "zod";
|
|
@@ -155,6 +155,8 @@ var ENDPOINTS = {
|
|
|
155
155
|
}
|
|
156
156
|
};
|
|
157
157
|
var PENDING_MS = 10 * 6e4;
|
|
158
|
+
var PENDING_MAX = 1e3;
|
|
159
|
+
var PENDING_PER_PEER = 20;
|
|
158
160
|
var SESSION_MS = 8 * 60 * 6e4;
|
|
159
161
|
var random = () => randomBytes(32).toString("base64url");
|
|
160
162
|
var digest = (value) => createHash("sha256").update(value).digest("base64url");
|
|
@@ -200,10 +202,29 @@ var LoginService = class {
|
|
|
200
202
|
logout(session) {
|
|
201
203
|
if (session) this.sessions.delete(digest(session));
|
|
202
204
|
}
|
|
203
|
-
|
|
205
|
+
/**
|
|
206
|
+
* Start a sign-in. `peer` is the connection's address as the HTTP server sees it (never a
|
|
207
|
+
* forwarded header unless the server was configured to trust its proxy). Unfinished sign-ins
|
|
208
|
+
* never block a new one: each peer keeps a few, and when the table is full the oldest goes.
|
|
209
|
+
*/
|
|
210
|
+
begin(provider, peer = "unknown") {
|
|
204
211
|
this.prune();
|
|
205
212
|
const client = this.options.providers[provider];
|
|
206
|
-
if (!client
|
|
213
|
+
if (!client) throw new LoginError();
|
|
214
|
+
let mine = 0;
|
|
215
|
+
for (const value of this.pending.values()) if (value.peer === peer) mine++;
|
|
216
|
+
for (const [key, value] of this.pending) {
|
|
217
|
+
if (mine < PENDING_PER_PEER) break;
|
|
218
|
+
if (value.peer === peer) {
|
|
219
|
+
this.pending.delete(key);
|
|
220
|
+
mine--;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
while (this.pending.size >= PENDING_MAX) {
|
|
224
|
+
const oldest = this.pending.keys().next().value;
|
|
225
|
+
if (oldest === void 0) break;
|
|
226
|
+
this.pending.delete(oldest);
|
|
227
|
+
}
|
|
207
228
|
const state = random();
|
|
208
229
|
const binding = random();
|
|
209
230
|
const verifier = random();
|
|
@@ -211,6 +232,7 @@ var LoginService = class {
|
|
|
211
232
|
provider,
|
|
212
233
|
binding: digest(binding),
|
|
213
234
|
verifier,
|
|
235
|
+
peer,
|
|
214
236
|
expires: this.now() + PENDING_MS
|
|
215
237
|
});
|
|
216
238
|
const url = new URL(ENDPOINTS[provider].authorize);
|
|
@@ -1471,6 +1493,53 @@ ${message}`, options);
|
|
|
1471
1493
|
this.source = source;
|
|
1472
1494
|
}
|
|
1473
1495
|
};
|
|
1496
|
+
var PROJECT_SETTABLE_KEYS = {
|
|
1497
|
+
logLevel: true,
|
|
1498
|
+
routing: true,
|
|
1499
|
+
goal: true,
|
|
1500
|
+
runner: {
|
|
1501
|
+
maxRepairCycles: true,
|
|
1502
|
+
branchPrefix: true,
|
|
1503
|
+
baseBranch: true,
|
|
1504
|
+
route: true,
|
|
1505
|
+
executor: true,
|
|
1506
|
+
pullRequests: true,
|
|
1507
|
+
commitBrain: true,
|
|
1508
|
+
commandTimeoutMs: true,
|
|
1509
|
+
idlePollMs: true,
|
|
1510
|
+
maxIterations: true,
|
|
1511
|
+
maxTaskTokens: true,
|
|
1512
|
+
validate: true,
|
|
1513
|
+
claudeCli: { accountId: true, model: true, timeoutMs: true },
|
|
1514
|
+
judge: { kind: true, model: true, threshold: true }
|
|
1515
|
+
}
|
|
1516
|
+
};
|
|
1517
|
+
function filterProjectLayer(layer) {
|
|
1518
|
+
const dropped = [];
|
|
1519
|
+
const walk = (value, tree, prefix) => {
|
|
1520
|
+
const out = {};
|
|
1521
|
+
for (const [key, v] of Object.entries(value)) {
|
|
1522
|
+
const rule = Object.hasOwn(tree, key) ? tree[key] : void 0;
|
|
1523
|
+
const path8 = prefix ? `${prefix}.${key}` : key;
|
|
1524
|
+
if (rule === true) {
|
|
1525
|
+
out[key] = v;
|
|
1526
|
+
} else if (rule && isPlainObject(v)) {
|
|
1527
|
+
const inner = walk(v, rule, path8);
|
|
1528
|
+
if (Object.keys(inner).length > 0) out[key] = inner;
|
|
1529
|
+
} else {
|
|
1530
|
+
dropped.push(path8);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
return out;
|
|
1534
|
+
};
|
|
1535
|
+
return { allowed: walk(layer, PROJECT_SETTABLE_KEYS, ""), dropped };
|
|
1536
|
+
}
|
|
1537
|
+
var warned = /* @__PURE__ */ new Set();
|
|
1538
|
+
function defaultWarn(message) {
|
|
1539
|
+
if (warned.has(message)) return;
|
|
1540
|
+
warned.add(message);
|
|
1541
|
+
process.emitWarning(message, "DaveCodeConfigWarning");
|
|
1542
|
+
}
|
|
1474
1543
|
function isPlainObject(value) {
|
|
1475
1544
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1476
1545
|
}
|
|
@@ -1483,7 +1552,7 @@ function deepMerge(base, override) {
|
|
|
1483
1552
|
}
|
|
1484
1553
|
return out;
|
|
1485
1554
|
}
|
|
1486
|
-
function readLayer(path8) {
|
|
1555
|
+
function readLayer(path8, project) {
|
|
1487
1556
|
let raw;
|
|
1488
1557
|
try {
|
|
1489
1558
|
raw = readFileSync(path8, "utf8");
|
|
@@ -1498,9 +1567,15 @@ function readLayer(path8) {
|
|
|
1498
1567
|
throw new ConfigError(path8, `malformed JSON: ${err.message}`, { cause: err });
|
|
1499
1568
|
}
|
|
1500
1569
|
if (!isPlainObject(parsed)) throw new ConfigError(path8, "expected a JSON object");
|
|
1501
|
-
|
|
1570
|
+
let layer = parsed;
|
|
1571
|
+
if (project) {
|
|
1572
|
+
const { allowed, dropped } = filterProjectLayer(parsed);
|
|
1573
|
+
if (dropped.length > 0) project(dropped);
|
|
1574
|
+
layer = allowed;
|
|
1575
|
+
}
|
|
1576
|
+
const result = configSchema.safeParse(layer);
|
|
1502
1577
|
if (!result.success) throw new ConfigError(path8, z4.prettifyError(result.error));
|
|
1503
|
-
return
|
|
1578
|
+
return layer;
|
|
1504
1579
|
}
|
|
1505
1580
|
var TRUE_VALUES = /* @__PURE__ */ new Set(["1", "true", "yes", "on"]);
|
|
1506
1581
|
var FALSE_VALUES = /* @__PURE__ */ new Set(["0", "false", "no", "off", ""]);
|
|
@@ -1558,7 +1633,14 @@ function loadConfig(options = {}) {
|
|
|
1558
1633
|
const globalLayer = readLayer(globalPaths(home).config);
|
|
1559
1634
|
if (globalLayer) merged = deepMerge(merged, globalLayer);
|
|
1560
1635
|
if (options.projectRoot) {
|
|
1561
|
-
const
|
|
1636
|
+
const projectFile = projectPaths(options.projectRoot).config;
|
|
1637
|
+
const warn = options.onWarning ?? defaultWarn;
|
|
1638
|
+
const projectLayer = readLayer(
|
|
1639
|
+
projectFile,
|
|
1640
|
+
(dropped) => warn(
|
|
1641
|
+
`Ignored ${dropped.join(", ")} in ${projectFile}: project config cannot set these keys. Set them in your user config (~/.davecode/config.json) or with DAVECODE_* environment variables.`
|
|
1642
|
+
)
|
|
1643
|
+
);
|
|
1562
1644
|
if (projectLayer) merged = deepMerge(merged, projectLayer);
|
|
1563
1645
|
}
|
|
1564
1646
|
merged = deepMerge(merged, envLayer(env));
|
|
@@ -3875,6 +3957,76 @@ function createProviders(options = {}) {
|
|
|
3875
3957
|
];
|
|
3876
3958
|
return new Map(providers.map((p) => [p.kind, p]));
|
|
3877
3959
|
}
|
|
3960
|
+
var ENDPOINT_CONFIG_KEYS = ["baseUrl"];
|
|
3961
|
+
var MODEL_KEYS = ["models", "defaultModel"];
|
|
3962
|
+
var API_CONFIG_KEYS = {
|
|
3963
|
+
anthropic: ["baseUrl", ...MODEL_KEYS],
|
|
3964
|
+
openai: ["baseUrl", "includeUsage", ...MODEL_KEYS],
|
|
3965
|
+
gemini: ["baseUrl", ...MODEL_KEYS],
|
|
3966
|
+
"openai-compatible": ["baseUrl", "includeUsage", ...MODEL_KEYS],
|
|
3967
|
+
"claude-cli": [...MODEL_KEYS],
|
|
3968
|
+
"codex-cli": [...MODEL_KEYS],
|
|
3969
|
+
"gemini-cli": [...MODEL_KEYS],
|
|
3970
|
+
"antigravity-cli": [...MODEL_KEYS],
|
|
3971
|
+
"gemini-web": ["models"]
|
|
3972
|
+
};
|
|
3973
|
+
function isStringList(value) {
|
|
3974
|
+
return Array.isArray(value) && value.every((v) => typeof v === "string" && v.length > 0);
|
|
3975
|
+
}
|
|
3976
|
+
function apiConfigIssues(provider, config, existing = {}) {
|
|
3977
|
+
const allowed = API_CONFIG_KEYS[provider];
|
|
3978
|
+
const issues = [];
|
|
3979
|
+
for (const [key, value] of Object.entries(config)) {
|
|
3980
|
+
if (!allowed.includes(key)) {
|
|
3981
|
+
if (key in existing && JSON.stringify(existing[key]) === JSON.stringify(value)) continue;
|
|
3982
|
+
issues.push(
|
|
3983
|
+
`config.${key} cannot be set through the API for ${provider} accounts` + (allowed.length > 0 ? ` (allowed: ${allowed.join(", ")})` : "")
|
|
3984
|
+
);
|
|
3985
|
+
continue;
|
|
3986
|
+
}
|
|
3987
|
+
if (key === "baseUrl") {
|
|
3988
|
+
if (typeof value !== "string" || !isHttpUrl(value)) {
|
|
3989
|
+
issues.push("config.baseUrl must be an http(s) URL without embedded credentials");
|
|
3990
|
+
}
|
|
3991
|
+
} else if (key === "models") {
|
|
3992
|
+
if (!isStringList(value)) issues.push("config.models must be a list of model ids");
|
|
3993
|
+
} else if (key === "defaultModel") {
|
|
3994
|
+
if (typeof value !== "string" || !value) issues.push("config.defaultModel must be a string");
|
|
3995
|
+
} else if (key === "includeUsage" && typeof value !== "boolean") {
|
|
3996
|
+
issues.push("config.includeUsage must be true or false");
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
return issues;
|
|
4000
|
+
}
|
|
4001
|
+
function isHttpUrl(value) {
|
|
4002
|
+
try {
|
|
4003
|
+
const url = new URL(value);
|
|
4004
|
+
return (url.protocol === "http:" || url.protocol === "https:") && !url.username && !url.password;
|
|
4005
|
+
} catch {
|
|
4006
|
+
return false;
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
4009
|
+
function mergeApiConfig(provider, existing, incoming) {
|
|
4010
|
+
const allowed = API_CONFIG_KEYS[provider];
|
|
4011
|
+
const kept = Object.fromEntries(
|
|
4012
|
+
Object.entries(existing).filter(([key]) => !allowed.includes(key))
|
|
4013
|
+
);
|
|
4014
|
+
return { ...kept, ...incoming };
|
|
4015
|
+
}
|
|
4016
|
+
function endpointOf(config) {
|
|
4017
|
+
return ENDPOINT_CONFIG_KEYS.map((key) => {
|
|
4018
|
+
const value = config[key];
|
|
4019
|
+
return typeof value === "string" ? value.trim().replace(/\/+$/, "") : "";
|
|
4020
|
+
}).join("\n");
|
|
4021
|
+
}
|
|
4022
|
+
function endpointChanged(existing, next) {
|
|
4023
|
+
return endpointOf(existing) !== endpointOf(next);
|
|
4024
|
+
}
|
|
4025
|
+
function endpointRebindIssue(existing, nextConfig, secretSupplied) {
|
|
4026
|
+
if (!nextConfig || secretSupplied || !existing.hasSecret) return void 0;
|
|
4027
|
+
if (!endpointChanged(existing.config, nextConfig)) return void 0;
|
|
4028
|
+
return "Changing the endpoint of an account that has a stored secret requires sending the secret again in the same request";
|
|
4029
|
+
}
|
|
3878
4030
|
var EXPERIMENTAL_PROVIDER_KINDS = ["gemini-web"];
|
|
3879
4031
|
var SUBSCRIPTION_PROVIDER_KINDS = [
|
|
3880
4032
|
"claude-cli",
|
|
@@ -3883,7 +4035,7 @@ var SUBSCRIPTION_PROVIDER_KINDS = [
|
|
|
3883
4035
|
"antigravity-cli",
|
|
3884
4036
|
"gemini-web"
|
|
3885
4037
|
];
|
|
3886
|
-
var VERSION = "0.5.
|
|
4038
|
+
var VERSION = "0.5.1";
|
|
3887
4039
|
var QUOTA_WINDOWS = ["1m", "5h", "24h"];
|
|
3888
4040
|
var WINDOW_MS = {
|
|
3889
4041
|
"1m": 6e4,
|
|
@@ -8070,12 +8222,14 @@ function accountService(env = process.env) {
|
|
|
8070
8222
|
}
|
|
8071
8223
|
var OAUTH_PROVIDERS = ["google", "github"];
|
|
8072
8224
|
var AccountError = class extends Error {
|
|
8073
|
-
constructor(message, status) {
|
|
8225
|
+
constructor(message, status, code) {
|
|
8074
8226
|
super(message);
|
|
8075
8227
|
this.status = status;
|
|
8228
|
+
this.code = code;
|
|
8076
8229
|
this.name = "AccountError";
|
|
8077
8230
|
}
|
|
8078
8231
|
status;
|
|
8232
|
+
code;
|
|
8079
8233
|
};
|
|
8080
8234
|
var userSchema = z8.object({
|
|
8081
8235
|
id: z8.string().min(1),
|
|
@@ -8211,7 +8365,8 @@ var AccountClient = class {
|
|
|
8211
8365
|
const detail = error.success ? error.data.error_description ?? error.data.msg ?? error.data.message : void 0;
|
|
8212
8366
|
throw new AccountError(
|
|
8213
8367
|
detail ?? `Sign-in failed (HTTP ${response.status}).`,
|
|
8214
|
-
response.status
|
|
8368
|
+
response.status,
|
|
8369
|
+
error.success ? error.data.error : void 0
|
|
8215
8370
|
);
|
|
8216
8371
|
}
|
|
8217
8372
|
return raw;
|
|
@@ -8299,6 +8454,16 @@ async function startAccountLogin(options) {
|
|
|
8299
8454
|
}
|
|
8300
8455
|
var AAD = Buffer.from("davecode-account", "utf8");
|
|
8301
8456
|
var REFRESH_MARGIN_MS = 6e4;
|
|
8457
|
+
var LOCK_STALE_MS = 6e4;
|
|
8458
|
+
var LOCK_WAIT_MS = 3e4;
|
|
8459
|
+
var LOCK_POLL_MS = 50;
|
|
8460
|
+
var INVALID_TOKEN_CODES = /* @__PURE__ */ new Set([
|
|
8461
|
+
"invalid_grant",
|
|
8462
|
+
"refresh_token_not_found",
|
|
8463
|
+
"refresh_token_already_used",
|
|
8464
|
+
"session_not_found",
|
|
8465
|
+
"session_expired"
|
|
8466
|
+
]);
|
|
8302
8467
|
var fileSchema = z9.object({
|
|
8303
8468
|
v: z9.literal(1),
|
|
8304
8469
|
iv: z9.string(),
|
|
@@ -8375,22 +8540,67 @@ var AccountStore = class {
|
|
|
8375
8540
|
* or when the service revoked the session; offline, an unexpired session is still returned.
|
|
8376
8541
|
*/
|
|
8377
8542
|
async current(client, now = Date.now()) {
|
|
8378
|
-
const
|
|
8379
|
-
if (!
|
|
8380
|
-
if (
|
|
8543
|
+
const first = this.load();
|
|
8544
|
+
if (!first) return void 0;
|
|
8545
|
+
if (first.expiresAt - REFRESH_MARGIN_MS > now) return first;
|
|
8546
|
+
const release = await this.lock();
|
|
8381
8547
|
try {
|
|
8382
|
-
const
|
|
8383
|
-
|
|
8384
|
-
return
|
|
8385
|
-
|
|
8386
|
-
|
|
8387
|
-
this.
|
|
8388
|
-
return
|
|
8548
|
+
const session = this.load();
|
|
8549
|
+
if (!session) return void 0;
|
|
8550
|
+
if (session.expiresAt - REFRESH_MARGIN_MS > now) return session;
|
|
8551
|
+
try {
|
|
8552
|
+
const fresh = await client.refresh(session.refreshToken);
|
|
8553
|
+
this.save(fresh);
|
|
8554
|
+
return fresh;
|
|
8555
|
+
} catch (err) {
|
|
8556
|
+
if (isInvalidToken(err)) {
|
|
8557
|
+
if (this.load()?.refreshToken === session.refreshToken) this.clear();
|
|
8558
|
+
return this.load();
|
|
8559
|
+
}
|
|
8560
|
+
return session;
|
|
8389
8561
|
}
|
|
8390
|
-
|
|
8562
|
+
} finally {
|
|
8563
|
+
release();
|
|
8564
|
+
}
|
|
8565
|
+
}
|
|
8566
|
+
/**
|
|
8567
|
+
* A cross-process lock: a file created exclusively next to account.json. A lock older than
|
|
8568
|
+
* LOCK_STALE_MS belongs to a process that died, and is taken over. After LOCK_WAIT_MS the
|
|
8569
|
+
* refresh goes ahead without it (the service tolerates two refreshes racing).
|
|
8570
|
+
*/
|
|
8571
|
+
async lock() {
|
|
8572
|
+
const path8 = `${this.path}.lock`;
|
|
8573
|
+
const owner = `${process.pid}:${randomBytes8(8).toString("hex")}`;
|
|
8574
|
+
mkdirSync7(dirname6(path8), { recursive: true });
|
|
8575
|
+
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
8576
|
+
for (; ; ) {
|
|
8577
|
+
try {
|
|
8578
|
+
writeFileSync3(path8, owner, { flag: "wx", mode: 384 });
|
|
8579
|
+
return () => {
|
|
8580
|
+
try {
|
|
8581
|
+
if (readFileSync3(path8, "utf8") === owner) rmSync3(path8, { force: true });
|
|
8582
|
+
} catch {
|
|
8583
|
+
}
|
|
8584
|
+
};
|
|
8585
|
+
} catch (err) {
|
|
8586
|
+
if (err.code !== "EEXIST" && !isWindowsBusy(err))
|
|
8587
|
+
return () => void 0;
|
|
8588
|
+
}
|
|
8589
|
+
try {
|
|
8590
|
+
if (Date.now() - statSync2(path8).mtimeMs > LOCK_STALE_MS) rmSync3(path8, { force: true });
|
|
8591
|
+
} catch {
|
|
8592
|
+
}
|
|
8593
|
+
if (Date.now() >= deadline) return () => void 0;
|
|
8594
|
+
await new Promise((resolve5) => setTimeout(resolve5, LOCK_POLL_MS));
|
|
8391
8595
|
}
|
|
8392
8596
|
}
|
|
8393
8597
|
};
|
|
8598
|
+
function isInvalidToken(err) {
|
|
8599
|
+
if (!(err instanceof AccountError) || err.status === void 0) return false;
|
|
8600
|
+
if (err.code) return INVALID_TOKEN_CODES.has(err.code);
|
|
8601
|
+
return err.status === 400 || err.status === 401;
|
|
8602
|
+
}
|
|
8603
|
+
var isWindowsBusy = (err) => ["EPERM", "EBUSY"].includes(err.code ?? "");
|
|
8394
8604
|
var BRAND_MARK_SVG = '<svg viewBox="0 0 1214 1214" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path fill="currentColor" fill-rule="evenodd" d="M324.3 1096.5C324.6 1095.4 326.5 1088.3 328.5 1080.8C341.4 1031.3 375.8 953.4 419.7 874.0C445.8 826.9 448.4 822.4 471.8 783.0C501.5 733.1 530.1 687.6 556.4 648.5C563.7 637.5 569.7 628.4 569.5 628.2C569.4 628.1 563.1 631.7 555.4 636.3C513.8 661.4 468.0 683.9 411.0 707.5C337.2 737.9 321.7 744.7 296.0 757.2C241.9 783.5 199.1 809.4 152.0 844.3C119.5 868.4 98.8 885.9 71.3 912.4C64.0 919.5 58.0 925.0 58.0 924.7C58.0 923.1 64.7 902.4 68.8 891.0C116.1 762.1 215.0 644.2 351.0 554.8C385.2 532.3 411.6 516.9 445.5 499.4C521.4 460.4 589.4 435.7 636.0 430.0C676.8 425.1 715.1 437.0 743.9 463.6C763.4 481.6 779.0 509.9 785.2 538.5C787.7 550.1 788.7 579.7 787.1 592.5C782.6 626.4 769.7 661.5 746.5 702.0C717.7 752.5 675.6 806.9 627.0 856.4C599.5 884.4 575.9 905.4 542.5 931.6C510.0 957.1 500.7 964.2 432.5 1015.0C409.4 1032.3 382.6 1052.5 373.0 1060.0C354.5 1074.4 327.4 1095.5 325.1 1097.4C324.0 1098.3 323.8 1098.1 324.3 1096.5ZM783.2 1017.8C797.1 999.5 820.2 966.0 831.7 947.5C868.5 888.3 888.8 840.5 903.4 778.5C917.9 716.9 921.2 643.7 912.0 591.0C904.6 549.3 889.7 511.9 866.7 477.5C856.6 462.3 853.1 457.8 837.4 439.6C817.4 416.6 806.6 402.0 800.5 389.5C793.6 375.5 791.7 368.1 791.7 356.0C791.7 335.3 799.3 319.6 819.0 299.9C849.7 269.2 900.2 247.9 956.8 241.9C963.0 241.2 967.7 240.3 967.3 239.9C966.1 238.8 948.5 236.3 933.0 234.9C913.6 233.2 875.2 234.3 859.0 237.0C839.7 240.2 827.8 242.9 813.0 247.5C753.9 265.9 700.6 300.9 659.2 348.5C648.9 360.4 636.6 376.5 632.4 383.5C630.3 387.1 629.0 388.2 624.7 389.6C603.8 396.4 554.6 417.6 513.5 437.5C447.6 469.4 395.4 496.8 341.5 528.1L337.5 530.4L339.5 527.9C340.6 526.6 346.2 520.3 352.0 514.0C374.4 489.6 390.2 470.8 411.2 443.5C429.3 419.9 444.6 398.2 488.5 333.5C510.5 301.0 529.1 278.0 550.9 256.3C593.0 214.1 640.3 183.6 691.5 165.5C727.7 152.8 756.5 147.7 792.5 147.7C854.3 147.8 906.4 164.9 954.1 200.6C967.5 210.8 974.1 214.6 981.5 217.0C991.4 220.1 1022.1 231.9 1038.5 238.8C1061.9 248.7 1099.0 267.4 1097.7 268.7C1097.4 268.9 1089.3 268.5 1079.7 267.9C1033.7 264.7 984.5 274.1 946.2 293.4C932.3 300.4 915.0 313.0 903.4 324.5C881.0 346.6 870.0 369.6 870.0 394.4C870.0 413.7 876.8 433.1 894.7 465.2C908.8 490.3 914.6 501.1 922.8 517.5C961.3 594.3 980.0 662.5 980.0 725.4C980.0 770.9 967.3 818.9 944.4 860.4C927.6 890.8 912.0 911.0 882.5 940.6C856.5 966.7 828.5 989.7 797.0 1010.7C779.6 1022.2 780.0 1022.0 783.2 1017.8Z"/></svg>';
|
|
8395
8605
|
var LOGO_ART = [
|
|
8396
8606
|
" \u2584\u2584\u2584\u2588\u2584\u2584\u2584",
|
|
@@ -9462,6 +9672,8 @@ export {
|
|
|
9462
9672
|
routeSchema,
|
|
9463
9673
|
configSchema,
|
|
9464
9674
|
ConfigError,
|
|
9675
|
+
PROJECT_SETTABLE_KEYS,
|
|
9676
|
+
filterProjectLayer,
|
|
9465
9677
|
deepMerge,
|
|
9466
9678
|
envLayer,
|
|
9467
9679
|
loadConfig,
|
|
@@ -9486,6 +9698,12 @@ export {
|
|
|
9486
9698
|
OpenAIProvider,
|
|
9487
9699
|
OpenAICompatibleProvider,
|
|
9488
9700
|
createProviders,
|
|
9701
|
+
ENDPOINT_CONFIG_KEYS,
|
|
9702
|
+
API_CONFIG_KEYS,
|
|
9703
|
+
apiConfigIssues,
|
|
9704
|
+
mergeApiConfig,
|
|
9705
|
+
endpointChanged,
|
|
9706
|
+
endpointRebindIssue,
|
|
9489
9707
|
EXPERIMENTAL_PROVIDER_KINDS,
|
|
9490
9708
|
SUBSCRIPTION_PROVIDER_KINDS,
|
|
9491
9709
|
VERSION,
|
|
@@ -9605,4 +9823,4 @@ export {
|
|
|
9605
9823
|
GoalStore,
|
|
9606
9824
|
createGoalService
|
|
9607
9825
|
};
|
|
9608
|
-
//# sourceMappingURL=chunk-
|
|
9826
|
+
//# sourceMappingURL=chunk-HENE4DA6.js.map
|