@dmrlzz/davecode 0.5.0 → 0.5.2

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.
Files changed (73) hide show
  1. package/dist/{ChatApp-CJBICQGA.js → ChatApp-Z6PQIZ5J.js} +7 -6
  2. package/dist/{ChatApp-CJBICQGA.js.map → ChatApp-Z6PQIZ5J.js.map} +1 -1
  3. package/dist/{account-QWDPJWAA.js → account-RTPS2V6O.js} +4 -3
  4. package/dist/{accounts-IQMR72FC.js → accounts-IYQ4ZRL7.js} +6 -5
  5. package/dist/{budget-XANOUVWO.js → budget-N2ZB66FF.js} +5 -4
  6. package/dist/{budget-XANOUVWO.js.map → budget-N2ZB66FF.js.map} +1 -1
  7. package/dist/{chat-KDDRNC5V.js → chat-6TX6JX45.js} +9 -8
  8. package/dist/{chat-KDDRNC5V.js.map → chat-6TX6JX45.js.map} +1 -1
  9. package/dist/chunk-732GIHRQ.js +23 -0
  10. package/dist/chunk-732GIHRQ.js.map +1 -0
  11. package/dist/{chunk-AZKACMME.js → chunk-BJTXMET2.js} +2 -2
  12. package/dist/{chunk-FYPMA55O.js → chunk-KUY3QHGS.js} +239 -106
  13. package/dist/chunk-KUY3QHGS.js.map +1 -0
  14. package/dist/{chunk-JLATEHS7.js → chunk-LEU46DGH.js} +2 -2
  15. package/dist/{chunk-HSBJDV3O.js → chunk-QKY3OKVG.js} +309 -23
  16. package/dist/chunk-QKY3OKVG.js.map +1 -0
  17. package/dist/{chunk-WQ7MEWDF.js → chunk-UEV5K3DH.js} +10 -4
  18. package/dist/chunk-UEV5K3DH.js.map +1 -0
  19. package/dist/{chunk-44AFJL2X.js → chunk-UNK3EQD6.js} +6 -5
  20. package/dist/chunk-UNK3EQD6.js.map +1 -0
  21. package/dist/{chunk-W7GPBEBZ.js → chunk-WAARDGCZ.js} +5 -21
  22. package/dist/chunk-WAARDGCZ.js.map +1 -0
  23. package/dist/{chunk-PGAJIGUF.js → chunk-YNAMNQLW.js} +3 -3
  24. package/dist/{config-YTUPIYZT.js → config-YQKY2AA4.js} +4 -3
  25. package/dist/{config-YTUPIYZT.js.map → config-YQKY2AA4.js.map} +1 -1
  26. package/dist/dashboard/assets/Accounts-DXiGsutB.js +1 -0
  27. package/dist/dashboard/assets/{Badge-Z4RBdO9j.js → Badge-DUGKlx3Z.js} +1 -1
  28. package/dist/dashboard/assets/{Callout-w8BTYh4k.js → Callout-1E8Wsl9W.js} +1 -1
  29. package/dist/dashboard/assets/{Goals-Bw02to72.js → Goals-kL4VAxw3.js} +1 -1
  30. package/dist/dashboard/assets/{Library-DK7mlpRb.js → Library-DZxBVUo_.js} +1 -1
  31. package/dist/dashboard/assets/Markdown-CGgIydUh.js +71 -0
  32. package/dist/dashboard/assets/{Panes-_KTf8pbZ.js → Panes-C-TJekjs.js} +1 -1
  33. package/dist/dashboard/assets/{RoutesPage-QV0oPRW9.js → RoutesPage-DWYm9tW8.js} +1 -1
  34. package/dist/dashboard/assets/{Runner-CkHBLQl0.js → Runner-CmHBjECR.js} +1 -1
  35. package/dist/dashboard/assets/{Settings-BLz2gTBR.js → Settings-BANphxva.js} +1 -1
  36. package/dist/dashboard/assets/{Tasks-BiUQSTpt.js → Tasks-cSx1PKyQ.js} +1 -1
  37. package/dist/dashboard/assets/{Traffic-BVfBuC70.js → Traffic-DEAuM6jq.js} +1 -1
  38. package/dist/dashboard/assets/{Workspace-CJTgiiU5.js → Workspace-BQFjc1jH.js} +1 -1
  39. package/dist/dashboard/assets/index-B8kld9xo.js +104 -0
  40. package/dist/dashboard/assets/{task-errors-Daqwi0ue.js → task-errors-r-WYZ_S3.js} +1 -1
  41. package/dist/dashboard/index.html +2 -2
  42. package/dist/{dist-37VQSHHA.js → dist-PIC255RX.js} +20 -2
  43. package/dist/{doctor-PYUQRRCB.js → doctor-PQC7JQPP.js} +4 -3
  44. package/dist/{doctor-PYUQRRCB.js.map → doctor-PQC7JQPP.js.map} +1 -1
  45. package/dist/{goal-SXZUDUCL.js → goal-STLEU7C7.js} +4 -3
  46. package/dist/{goal-SXZUDUCL.js.map → goal-STLEU7C7.js.map} +1 -1
  47. package/dist/index.js +31 -31
  48. package/dist/{init-Z2AFQEEP.js → init-NHU5LJSS.js} +4 -3
  49. package/dist/{init-Z2AFQEEP.js.map → init-NHU5LJSS.js.map} +1 -1
  50. package/dist/{run-AOS7L3RT.js → run-7HWSHMRJ.js} +4 -3
  51. package/dist/{run-AOS7L3RT.js.map → run-7HWSHMRJ.js.map} +1 -1
  52. package/dist/runtime.js +3 -2
  53. package/dist/{start-CEPXKZUE.js → start-WVAEAQWL.js} +4 -3
  54. package/dist/{start-CEPXKZUE.js.map → start-WVAEAQWL.js.map} +1 -1
  55. package/dist/{status-WNJ3GGKU.js → status-ZRHPFLFT.js} +5 -4
  56. package/dist/{tasks-TFUTUMWB.js → tasks-JVWXUNXN.js} +5 -4
  57. package/dist/{tasks-TFUTUMWB.js.map → tasks-JVWXUNXN.js.map} +1 -1
  58. package/package.json +6 -6
  59. package/dist/chunk-44AFJL2X.js.map +0 -1
  60. package/dist/chunk-FYPMA55O.js.map +0 -1
  61. package/dist/chunk-HSBJDV3O.js.map +0 -1
  62. package/dist/chunk-W7GPBEBZ.js.map +0 -1
  63. package/dist/chunk-WQ7MEWDF.js.map +0 -1
  64. package/dist/dashboard/assets/Accounts-cq8RLMoI.js +0 -1
  65. package/dist/dashboard/assets/Markdown-DCZ4Awcc.js +0 -69
  66. package/dist/dashboard/assets/index-BDBa5cb0.js +0 -104
  67. /package/dist/{account-QWDPJWAA.js.map → account-RTPS2V6O.js.map} +0 -0
  68. /package/dist/{accounts-IQMR72FC.js.map → accounts-IYQ4ZRL7.js.map} +0 -0
  69. /package/dist/{chunk-AZKACMME.js.map → chunk-BJTXMET2.js.map} +0 -0
  70. /package/dist/{chunk-JLATEHS7.js.map → chunk-LEU46DGH.js.map} +0 -0
  71. /package/dist/{chunk-PGAJIGUF.js.map → chunk-YNAMNQLW.js.map} +0 -0
  72. /package/dist/{dist-37VQSHHA.js.map → dist-PIC255RX.js.map} +0 -0
  73. /package/dist/{status-WNJ3GGKU.js.map → status-ZRHPFLFT.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/start.ts","../src/lib/app-window.ts","../src/lib/summary.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { loadConfig, type ProjectBrain, summarize, type TaskGraph, VERSION } from '@davecode/core';\nimport { findGateway } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { openAppWindow } from '../lib/app-window';\nimport { formatEventLine, runtimeWarnings, summarizeAccounts } from '../lib/summary';\nimport { detectProjectRoot, type Runtime, startRuntime } from '../runtime';\nimport { padEnd } from '../ui/format';\n\nexport interface StartOptions {\n app?: boolean;\n port?: number;\n host?: string;\n /** commander's `--no-dashboard` sets this to false. */\n dashboard?: boolean;\n project?: string;\n verbose?: boolean;\n quiet?: boolean;\n}\n\nexport interface StartDeps {\n /** Resolves when the gateway should stop (default: SIGINT/SIGTERM). */\n until?: (runtime: Runtime) => Promise<void>;\n}\n\nasync function readGraphQuietly(brain: ProjectBrain): Promise<TaskGraph | undefined> {\n try {\n return (await brain.isInitialised()) ? await brain.readGraph() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction waitForSignal(): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n process.off('SIGINT', done);\n process.off('SIGTERM', done);\n resolve();\n };\n process.on('SIGINT', done);\n process.on('SIGTERM', done);\n });\n}\n\nexport async function startCommand(\n ctx: CliContext,\n opts: StartOptions,\n deps: StartDeps = {},\n): Promise<number> {\n const started = performance.now();\n const projectRoot = opts.project\n ? resolve(ctx.cwd, opts.project)\n : await detectProjectRoot(ctx.cwd, ctx.home);\n if (projectRoot && opts.project && !existsSync(projectRoot)) {\n throw new CliError(`Project directory not found: ${projectRoot}`);\n }\n const config = loadConfig({\n home: ctx.home,\n env: ctx.env,\n ...(projectRoot ? { projectRoot } : {}),\n });\n const port = opts.port ?? config.server.port;\n\n if (port !== 0) {\n const running = await findGateway(config, { port }).catch(() => undefined);\n if (running) {\n throw new CliError(`A DaveCode gateway is already running at ${running.client.baseUrl}`, {\n hint: 'Use `davecode status` to inspect it, or pick another port with --port.',\n });\n }\n }\n\n let runtime: Runtime;\n try {\n runtime = await startRuntime({\n home: ctx.home,\n env: ctx.env,\n cwd: ctx.cwd,\n ...(projectRoot ? { projectDir: projectRoot } : { noProject: true }),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n port,\n dashboard: opts.dashboard !== false,\n ...(opts.verbose ? { logger: { level: config.logLevel } } : {}),\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EADDRINUSE') {\n throw new CliError(`Port ${port} is already in use`, {\n hint: 'Stop the other process or choose a port: davecode start --port 4041',\n });\n }\n if (code === 'EACCES') {\n throw new CliError(`Permission denied binding ${opts.host ?? config.server.host}:${port}`, {\n hint: 'Use a port above 1024 or another --host.',\n });\n }\n throw err;\n }\n\n const { engine } = runtime;\n if (opts.app && !ctx.json) {\n const opened = runtime.dashboardDir\n ? await openAppWindow(runtime.url, ctx.env).catch(() => false)\n : false;\n if (!opened)\n ctx.err(\n `Open ${runtime.url}/ in your browser. An installed Chrome or Edge enables an app window.`,\n );\n }\n const accounts = engine.accounts.list();\n const warnings = runtimeWarnings(engine.config, runtime.host);\n const graph = runtime.brain ? await readGraphQuietly(runtime.brain) : undefined;\n\n if (ctx.json) {\n printJson(ctx, {\n status: 'running',\n version: VERSION,\n url: runtime.url,\n api: `${runtime.url}/v1`,\n dashboard: runtime.dashboardDir ? `${runtime.url}/` : null,\n project: runtime.project ?? null,\n accounts: accounts.length,\n warnings,\n });\n } else {\n const { theme } = ctx;\n const ms = Math.round(performance.now() - started);\n const row = (label: string, value: string) =>\n ctx.out(` ${theme.dim(padEnd(label, 10))} ${value}`);\n ctx.out();\n ctx.out(\n ` ${theme.bold(theme.accent('DaveCode'))} ${theme.dim(`v${VERSION} · ready in ${ms}ms`)}`,\n );\n ctx.out();\n row('API', theme.accent(`${runtime.url}/v1`));\n row(\n 'Dashboard',\n runtime.dashboardDir\n ? theme.accent(`${runtime.url}/`)\n : theme.dim(\n opts.dashboard === false || !engine.config.server.dashboard\n ? 'disabled'\n : 'not built (pnpm --filter @davecode/ui build)',\n ),\n );\n row('Events', theme.dim(`${runtime.url}/api/events`));\n if (runtime.project) {\n const done = graph ? summarize(graph) : undefined;\n const progress = done\n ? theme.dim(` · ${done.counts.SUCCESS}/${done.total} tasks done`)\n : theme.dim(' · no brain yet (davecode init)');\n row('Project', `${runtime.project.name}${progress}`);\n if (runtime.runner) {\n row(\n 'Runner',\n `${runtime.runner.status().state}${theme.dim(' · start it from the dashboard or with `davecode run`')}`,\n );\n }\n } else {\n row('Project', theme.dim('none (run inside a git repository)'));\n }\n row(\n 'Accounts',\n accounts.length > 0\n ? summarizeAccounts(accounts)\n : theme.warn('none yet: run `davecode accounts add`'),\n );\n for (const warning of warnings) ctx.out(` ${theme.warn(`${theme.glyph.warn} ${warning}`)}`);\n ctx.out();\n ctx.out(theme.dim(' Press Ctrl+C to stop.'));\n ctx.out();\n }\n\n let unsubscribe: (() => void) | undefined;\n if (!ctx.json && !opts.quiet && !opts.verbose) {\n const labelOf = (id: string) => engine.accounts.get(id)?.label ?? id;\n unsubscribe = engine.events.subscribe((event) => {\n const line = formatEventLine(ctx.theme, event, labelOf);\n if (line) ctx.out(` ${line}`);\n });\n }\n\n await (deps.until ?? waitForSignal)(runtime);\n unsubscribe?.();\n if (!ctx.json) ctx.out(ctx.theme.dim(' Stopping DaveCode…'));\n await runtime.close();\n return EXIT.ok;\n}\n","import { spawn } from 'node:child_process';\nimport { join } from 'node:path';\nimport { which } from './proc';\n\n/** Open only a loopback workspace, without a shell or credentials in the URL. */\nexport async function openAppWindow(\n url: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<boolean> {\n const target = new URL(url);\n if (\n !['http:', 'https:'].includes(target.protocol) ||\n !['127.0.0.1', 'localhost', '[::1]'].includes(target.hostname) ||\n target.username ||\n target.password ||\n target.search ||\n target.hash\n )\n throw new Error('App windows require a loopback workspace URL without credentials.');\n const win = process.platform === 'win32';\n const candidates = win\n ? [\n join(\n env['ProgramFiles(x86)'] ?? 'C:\\\\Program Files (x86)',\n 'Microsoft',\n 'Edge',\n 'Application',\n 'msedge.exe',\n ),\n join(\n env.ProgramFiles ?? 'C:\\\\Program Files',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n ...(env.LOCALAPPDATA\n ? [\n join(env.LOCALAPPDATA, 'Microsoft', 'Edge', 'Application', 'msedge.exe'),\n join(env.LOCALAPPDATA, 'Google', 'Chrome', 'Application', 'chrome.exe'),\n ]\n : []),\n ]\n : process.platform === 'darwin'\n ? [\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n ]\n : ['google-chrome', 'chromium', 'chromium-browser', 'microsoft-edge'];\n const executable = candidates.map((candidate) => which(candidate, env)).find(Boolean);\n if (!executable) return false;\n return new Promise((resolve) => {\n const child = spawn(executable, [`--app=${target.origin}/`], {\n env,\n shell: false,\n windowsHide: true,\n detached: true,\n stdio: 'ignore',\n });\n child.once('error', () => resolve(false));\n child.once('spawn', () => {\n child.unref();\n resolve(true);\n });\n });\n}\n","import type { Account, DaveConfig, DaveEvent } from '@davecode/core';\nimport { formatTokens } from '../ui/format';\nimport type { Theme } from '../ui/theme';\n\n/** One-line accounts summary, e.g. `3 enabled of 4 · anthropic 1 · claude-cli 2`. */\nexport function summarizeAccounts(accounts: Account[]): string {\n if (accounts.length === 0) return 'none';\n const enabled = accounts.filter((a) => a.enabled);\n const byProvider = new Map<string, number>();\n for (const account of enabled) {\n byProvider.set(account.provider, (byProvider.get(account.provider) ?? 0) + 1);\n }\n const parts = [...byProvider.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([provider, n]) => `${provider} ${n}`);\n const head =\n enabled.length === accounts.length\n ? `${accounts.length} enabled`\n : `${enabled.length} enabled of ${accounts.length}`;\n const problems = accounts.filter((a) => a.status === 'error' || a.status === 'cooldown').length;\n return [head, ...parts, ...(problems > 0 ? [`${problems} need attention`] : [])].join(' · ');\n}\n\n/** Warnings for Terms-of-Service-sensitive flags and risky bindings. */\nexport function runtimeWarnings(config: DaveConfig, host: string): string[] {\n const warnings: string[] = [];\n if (config.experimental.geminiWeb) {\n warnings.push(\n 'experimental.geminiWeb is ON: automating the Gemini web app may violate Google’s Terms of Service.',\n );\n }\n if (config.experimental.multiAccountRotation) {\n warnings.push(\n 'experimental.multiAccountRotation is ON: rotating subscription logins may violate provider terms.',\n );\n }\n const loopback = ['127.0.0.1', '::1', 'localhost'].includes(host);\n if (!loopback && !config.server.authToken) {\n warnings.push(\n `Listening on ${host} without server.authToken: anyone on your network can use your accounts.`,\n );\n }\n return warnings;\n}\n\nfunction clock(ts: number): string {\n return new Date(ts).toTimeString().slice(0, 8);\n}\n\n/**\n * Compact activity line for `davecode start`, or `undefined` for events that are not worth a\n * line (quota ticks, request starts). Account ids are shown by label when known.\n */\nexport function formatEventLine(\n theme: Theme,\n event: DaveEvent,\n labelOf: (accountId: string) => string = (id) => id,\n): string | undefined {\n const time = theme.dim(clock(event.ts));\n switch (event.type) {\n case 'request.completed': {\n const tokens = formatTokens(event.promptTokens + event.completionTokens);\n return `${time} ${theme.ok(theme.glyph.ok)} ${event.model} ${theme.dim(\n `${labelOf(event.accountId)} · ${tokens} tok · ${event.latencyMs}ms`,\n )}`;\n }\n case 'request.failed':\n return `${time} ${theme.error(theme.glyph.fail)} ${labelOf(event.accountId)} ${theme.dim(\n `${event.error.kind}${event.error.status ? ` ${event.error.status}` : ''}: ${event.error.message}`,\n )}`;\n case 'router.failover':\n return `${time} ${theme.warn(theme.glyph.arrow)} failover ${labelOf(event.fromAccountId)} ${\n theme.glyph.arrow\n } ${event.toAccountId ? labelOf(event.toAccountId) : 'none'} ${theme.dim(event.reason)}`;\n case 'account.removed':\n return `${time} ${theme.dim(`account ${event.accountId} removed`)}`;\n case 'runner.status':\n return `${time} ${theme.accent('runner')} ${event.status.state}${\n event.status.taskId ? theme.dim(` · ${event.status.taskId}`) : ''\n }`;\n case 'runner.log':\n return `${time} ${theme.dim(`[${event.level}]`)} ${event.message}`;\n case 'log':\n return event.level === 'warn' || event.level === 'error'\n ? `${time} ${event.level === 'error' ? theme.error(event.level) : theme.warn(event.level)} ${theme.dim(event.scope)} ${event.message}`\n : undefined;\n default:\n return undefined;\n }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
1
+ {"version":3,"sources":["../src/commands/start.ts","../src/lib/app-window.ts","../src/lib/summary.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { loadConfig, type ProjectBrain, summarize, type TaskGraph, VERSION } from '@davecode/core';\nimport { findGateway } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { openAppWindow } from '../lib/app-window';\nimport { formatEventLine, runtimeWarnings, summarizeAccounts } from '../lib/summary';\nimport { detectProjectRoot, type Runtime, startRuntime } from '../runtime';\nimport { padEnd } from '../ui/format';\n\nexport interface StartOptions {\n app?: boolean;\n port?: number;\n host?: string;\n /** commander's `--no-dashboard` sets this to false. */\n dashboard?: boolean;\n project?: string;\n verbose?: boolean;\n quiet?: boolean;\n}\n\nexport interface StartDeps {\n /** Resolves when the gateway should stop (default: SIGINT/SIGTERM). */\n until?: (runtime: Runtime) => Promise<void>;\n}\n\nasync function readGraphQuietly(brain: ProjectBrain): Promise<TaskGraph | undefined> {\n try {\n return (await brain.isInitialised()) ? await brain.readGraph() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction waitForSignal(): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n process.off('SIGINT', done);\n process.off('SIGTERM', done);\n resolve();\n };\n process.on('SIGINT', done);\n process.on('SIGTERM', done);\n });\n}\n\nexport async function startCommand(\n ctx: CliContext,\n opts: StartOptions,\n deps: StartDeps = {},\n): Promise<number> {\n const started = performance.now();\n const projectRoot = opts.project\n ? resolve(ctx.cwd, opts.project)\n : await detectProjectRoot(ctx.cwd, ctx.home);\n if (projectRoot && opts.project && !existsSync(projectRoot)) {\n throw new CliError(`Project directory not found: ${projectRoot}`);\n }\n const config = loadConfig({\n home: ctx.home,\n env: ctx.env,\n ...(projectRoot ? { projectRoot } : {}),\n });\n const port = opts.port ?? config.server.port;\n\n if (port !== 0) {\n const running = await findGateway(config, { port }).catch(() => undefined);\n if (running) {\n throw new CliError(`A DaveCode gateway is already running at ${running.client.baseUrl}`, {\n hint: 'Use `davecode status` to inspect it, or pick another port with --port.',\n });\n }\n }\n\n let runtime: Runtime;\n try {\n runtime = await startRuntime({\n home: ctx.home,\n env: ctx.env,\n cwd: ctx.cwd,\n ...(projectRoot ? { projectDir: projectRoot } : { noProject: true }),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n port,\n dashboard: opts.dashboard !== false,\n ...(opts.verbose ? { logger: { level: config.logLevel } } : {}),\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EADDRINUSE') {\n throw new CliError(`Port ${port} is already in use`, {\n hint: 'Stop the other process or choose a port: davecode start --port 4041',\n });\n }\n if (code === 'EACCES') {\n throw new CliError(`Permission denied binding ${opts.host ?? config.server.host}:${port}`, {\n hint: 'Use a port above 1024 or another --host.',\n });\n }\n throw err;\n }\n\n const { engine } = runtime;\n if (opts.app && !ctx.json) {\n const opened = runtime.dashboardDir\n ? await openAppWindow(runtime.url, ctx.env).catch(() => false)\n : false;\n if (!opened)\n ctx.err(\n `Open ${runtime.url}/ in your browser. An installed Chrome or Edge enables an app window.`,\n );\n }\n const accounts = engine.accounts.list();\n const warnings = runtimeWarnings(engine.config, runtime.host);\n const graph = runtime.brain ? await readGraphQuietly(runtime.brain) : undefined;\n\n if (ctx.json) {\n printJson(ctx, {\n status: 'running',\n version: VERSION,\n url: runtime.url,\n api: `${runtime.url}/v1`,\n dashboard: runtime.dashboardDir ? `${runtime.url}/` : null,\n project: runtime.project ?? null,\n accounts: accounts.length,\n warnings,\n });\n } else {\n const { theme } = ctx;\n const ms = Math.round(performance.now() - started);\n const row = (label: string, value: string) =>\n ctx.out(` ${theme.dim(padEnd(label, 10))} ${value}`);\n ctx.out();\n ctx.out(\n ` ${theme.bold(theme.accent('DaveCode'))} ${theme.dim(`v${VERSION} · ready in ${ms}ms`)}`,\n );\n ctx.out();\n row('API', theme.accent(`${runtime.url}/v1`));\n row(\n 'Dashboard',\n runtime.dashboardDir\n ? theme.accent(`${runtime.url}/`)\n : theme.dim(\n opts.dashboard === false || !engine.config.server.dashboard\n ? 'disabled'\n : 'not built (pnpm --filter @davecode/ui build)',\n ),\n );\n row('Events', theme.dim(`${runtime.url}/api/events`));\n if (runtime.project) {\n const done = graph ? summarize(graph) : undefined;\n const progress = done\n ? theme.dim(` · ${done.counts.SUCCESS}/${done.total} tasks done`)\n : theme.dim(' · no brain yet (davecode init)');\n row('Project', `${runtime.project.name}${progress}`);\n if (runtime.runner) {\n row(\n 'Runner',\n `${runtime.runner.status().state}${theme.dim(' · start it from the dashboard or with `davecode run`')}`,\n );\n }\n } else {\n row('Project', theme.dim('none (run inside a git repository)'));\n }\n row(\n 'Accounts',\n accounts.length > 0\n ? summarizeAccounts(accounts)\n : theme.warn('none yet: run `davecode accounts add`'),\n );\n for (const warning of warnings) ctx.out(` ${theme.warn(`${theme.glyph.warn} ${warning}`)}`);\n ctx.out();\n ctx.out(theme.dim(' Press Ctrl+C to stop.'));\n ctx.out();\n }\n\n let unsubscribe: (() => void) | undefined;\n if (!ctx.json && !opts.quiet && !opts.verbose) {\n const labelOf = (id: string) => engine.accounts.get(id)?.label ?? id;\n unsubscribe = engine.events.subscribe((event) => {\n const line = formatEventLine(ctx.theme, event, labelOf);\n if (line) ctx.out(` ${line}`);\n });\n }\n\n await (deps.until ?? waitForSignal)(runtime);\n unsubscribe?.();\n if (!ctx.json) ctx.out(ctx.theme.dim(' Stopping DaveCode…'));\n await runtime.close();\n return EXIT.ok;\n}\n","import { spawn } from 'node:child_process';\nimport { join } from 'node:path';\nimport { which } from './proc';\n\n/** Open only a loopback workspace, without a shell or credentials in the URL. */\nexport async function openAppWindow(\n url: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<boolean> {\n const target = new URL(url);\n if (\n !['http:', 'https:'].includes(target.protocol) ||\n !['127.0.0.1', 'localhost', '[::1]'].includes(target.hostname) ||\n target.username ||\n target.password ||\n target.search ||\n target.hash\n )\n throw new Error('App windows require a loopback workspace URL without credentials.');\n const win = process.platform === 'win32';\n const candidates = win\n ? [\n join(\n env['ProgramFiles(x86)'] ?? 'C:\\\\Program Files (x86)',\n 'Microsoft',\n 'Edge',\n 'Application',\n 'msedge.exe',\n ),\n join(\n env.ProgramFiles ?? 'C:\\\\Program Files',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n ...(env.LOCALAPPDATA\n ? [\n join(env.LOCALAPPDATA, 'Microsoft', 'Edge', 'Application', 'msedge.exe'),\n join(env.LOCALAPPDATA, 'Google', 'Chrome', 'Application', 'chrome.exe'),\n ]\n : []),\n ]\n : process.platform === 'darwin'\n ? [\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n ]\n : ['google-chrome', 'chromium', 'chromium-browser', 'microsoft-edge'];\n const executable = candidates.map((candidate) => which(candidate, env)).find(Boolean);\n if (!executable) return false;\n return new Promise((resolve) => {\n const child = spawn(executable, [`--app=${target.origin}/`], {\n env,\n shell: false,\n windowsHide: true,\n detached: true,\n stdio: 'ignore',\n });\n child.once('error', () => resolve(false));\n child.once('spawn', () => {\n child.unref();\n resolve(true);\n });\n });\n}\n","import type { Account, DaveConfig, DaveEvent } from '@davecode/core';\nimport { formatTokens } from '../ui/format';\nimport type { Theme } from '../ui/theme';\n\n/** One-line accounts summary, e.g. `3 enabled of 4 · anthropic 1 · claude-cli 2`. */\nexport function summarizeAccounts(accounts: Account[]): string {\n if (accounts.length === 0) return 'none';\n const enabled = accounts.filter((a) => a.enabled);\n const byProvider = new Map<string, number>();\n for (const account of enabled) {\n byProvider.set(account.provider, (byProvider.get(account.provider) ?? 0) + 1);\n }\n const parts = [...byProvider.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([provider, n]) => `${provider} ${n}`);\n const head =\n enabled.length === accounts.length\n ? `${accounts.length} enabled`\n : `${enabled.length} enabled of ${accounts.length}`;\n const problems = accounts.filter((a) => a.status === 'error' || a.status === 'cooldown').length;\n return [head, ...parts, ...(problems > 0 ? [`${problems} need attention`] : [])].join(' · ');\n}\n\n/** Warnings for Terms-of-Service-sensitive flags and risky bindings. */\nexport function runtimeWarnings(config: DaveConfig, host: string): string[] {\n const warnings: string[] = [];\n if (config.experimental.geminiWeb) {\n warnings.push(\n 'experimental.geminiWeb is ON: automating the Gemini web app may violate Google’s Terms of Service.',\n );\n }\n if (config.experimental.multiAccountRotation) {\n warnings.push(\n 'experimental.multiAccountRotation is ON: rotating subscription logins may violate provider terms.',\n );\n }\n const loopback = ['127.0.0.1', '::1', 'localhost'].includes(host);\n if (!loopback && !config.server.authToken) {\n warnings.push(\n `Listening on ${host} without server.authToken: anyone on your network can use your accounts.`,\n );\n }\n return warnings;\n}\n\nfunction clock(ts: number): string {\n return new Date(ts).toTimeString().slice(0, 8);\n}\n\n/**\n * Compact activity line for `davecode start`, or `undefined` for events that are not worth a\n * line (quota ticks, request starts). Account ids are shown by label when known.\n */\nexport function formatEventLine(\n theme: Theme,\n event: DaveEvent,\n labelOf: (accountId: string) => string = (id) => id,\n): string | undefined {\n const time = theme.dim(clock(event.ts));\n switch (event.type) {\n case 'request.completed': {\n const tokens = formatTokens(event.promptTokens + event.completionTokens);\n return `${time} ${theme.ok(theme.glyph.ok)} ${event.model} ${theme.dim(\n `${labelOf(event.accountId)} · ${tokens} tok · ${event.latencyMs}ms`,\n )}`;\n }\n case 'request.failed':\n return `${time} ${theme.error(theme.glyph.fail)} ${labelOf(event.accountId)} ${theme.dim(\n `${event.error.kind}${event.error.status ? ` ${event.error.status}` : ''}: ${event.error.message}`,\n )}`;\n case 'router.failover':\n return `${time} ${theme.warn(theme.glyph.arrow)} failover ${labelOf(event.fromAccountId)} ${\n theme.glyph.arrow\n } ${event.toAccountId ? labelOf(event.toAccountId) : 'none'} ${theme.dim(event.reason)}`;\n case 'account.removed':\n return `${time} ${theme.dim(`account ${event.accountId} removed`)}`;\n case 'runner.status':\n return `${time} ${theme.accent('runner')} ${event.status.state}${\n event.status.taskId ? theme.dim(` · ${event.status.taskId}`) : ''\n }`;\n case 'runner.log':\n return `${time} ${theme.dim(`[${event.level}]`)} ${event.message}`;\n case 'log':\n return event.level === 'warn' || event.level === 'error'\n ? `${time} ${event.level === 'error' ? theme.error(event.level) : theme.warn(event.level)} ${theme.dim(event.scope)} ${event.message}`\n : undefined;\n default:\n return undefined;\n }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
@@ -6,12 +6,13 @@ import {
6
6
  renderStatus,
7
7
  statusCommand,
8
8
  windowCell
9
- } from "./chunk-PGAJIGUF.js";
9
+ } from "./chunk-YNAMNQLW.js";
10
10
  import "./chunk-SF5ZEAP4.js";
11
11
  import "./chunk-QA3O6RA2.js";
12
- import "./chunk-FYPMA55O.js";
12
+ import "./chunk-KUY3QHGS.js";
13
13
  import "./chunk-7XVXEO7U.js";
14
- import "./chunk-HSBJDV3O.js";
14
+ import "./chunk-732GIHRQ.js";
15
+ import "./chunk-QKY3OKVG.js";
15
16
  import "./chunk-MC7RIPL7.js";
16
17
  export {
17
18
  emptyUsage,
@@ -22,4 +23,4 @@ export {
22
23
  statusCommand,
23
24
  windowCell
24
25
  };
25
- //# sourceMappingURL=status-WNJ3GGKU.js.map
26
+ //# sourceMappingURL=status-ZRHPFLFT.js.map
@@ -2,18 +2,19 @@ import {
2
2
  formatTaskDetail,
3
3
  formatTaskTree,
4
4
  summaryLine
5
- } from "./chunk-AZKACMME.js";
5
+ } from "./chunk-BJTXMET2.js";
6
6
  import "./chunk-SF5ZEAP4.js";
7
7
  import {
8
8
  printJson
9
9
  } from "./chunk-QA3O6RA2.js";
10
10
  import {
11
11
  detectProjectRoot
12
- } from "./chunk-FYPMA55O.js";
12
+ } from "./chunk-KUY3QHGS.js";
13
13
  import {
14
14
  CliError,
15
15
  EXIT
16
16
  } from "./chunk-7XVXEO7U.js";
17
+ import "./chunk-732GIHRQ.js";
17
18
  import {
18
19
  ProjectBrain,
19
20
  TASK_STATUSES,
@@ -22,7 +23,7 @@ import {
22
23
  nextTask,
23
24
  parseTaskGraph,
24
25
  summarize
25
- } from "./chunk-HSBJDV3O.js";
26
+ } from "./chunk-QKY3OKVG.js";
26
27
  import "./chunk-MC7RIPL7.js";
27
28
 
28
29
  // src/commands/tasks.ts
@@ -181,4 +182,4 @@ export {
181
182
  tasksNext,
182
183
  tasksStatus
183
184
  };
184
- //# sourceMappingURL=tasks-TFUTUMWB.js.map
185
+ //# sourceMappingURL=tasks-JVWXUNXN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/tasks.ts"],"sourcesContent":["import { rename, writeFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\nimport {\n blockedTasks,\n nextTask,\n ProjectBrain,\n parseTaskGraph,\n summarize,\n TASK_STATUSES,\n TaskGraphError,\n type TaskNode,\n type TaskStatus,\n} from '@davecode/core';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { formatTaskDetail, formatTaskTree, summaryLine } from '../lib/task-tree';\nimport { detectProjectRoot } from '../runtime';\n\nasync function openBrain(ctx: CliContext): Promise<ProjectBrain> {\n const root = await detectProjectRoot(ctx.cwd, ctx.home);\n const brain = root ? new ProjectBrain(root) : undefined;\n if (!brain || !(await brain.isInitialised())) {\n throw new CliError('No project brain here', {\n hint: 'Run `davecode init` in your repository first.',\n });\n }\n return brain;\n}\n\n/** Turn graph validation failures into readable CLI errors. */\nasync function graphErrors<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n if (err instanceof TaskGraphError) {\n throw new CliError(err.issues.map((i) => i.message).join('\\n'), {\n hint: 'TASK_GRAPH.json was left unchanged.',\n });\n }\n throw err;\n }\n}\n\nexport async function tasksList(ctx: CliContext): Promise<number> {\n const brain = await openBrain(ctx);\n const graph = await graphErrors(() => brain.readGraph());\n if (ctx.json) {\n printJson(ctx, {\n root: brain.root,\n summary: summarize(graph),\n next: nextTask(graph)?.id ?? null,\n blocked: blockedTasks(graph).map((b) => ({\n id: b.task.id,\n reason: b.reason,\n blockedBy: b.blockedBy,\n })),\n graph,\n });\n return EXIT.ok;\n }\n const { theme } = ctx;\n ctx.out(`${theme.bold(theme.accent('Tasks'))} ${theme.dim(basename(brain.root))}`);\n if (graph.tasks.length > 0) ctx.out(summaryLine(theme, graph));\n ctx.out();\n for (const line of formatTaskTree(theme, graph, { width: ctx.columns })) ctx.out(line);\n if (graph.tasks.length === 0) {\n ctx.out(`Add one with ${theme.accent('davecode tasks add <id> \"<title>\"')}.`);\n }\n return EXIT.ok;\n}\n\nexport async function tasksNext(ctx: CliContext): Promise<number> {\n const brain = await openBrain(ctx);\n const graph = await graphErrors(() => brain.readGraph());\n const task = nextTask(graph);\n if (ctx.json) {\n printJson(ctx, { next: task ?? null });\n return EXIT.ok;\n }\n if (!task) {\n const blocked = blockedTasks(graph);\n const running = graph.tasks.filter((t) => t.status === 'IN_PROGRESS');\n ctx.out(ctx.theme.dim('Nothing is ready to run.'));\n for (const t of running) ctx.out(` ${ctx.theme.accent(t.id)} is in progress`);\n for (const b of blocked) {\n ctx.out(\n ` ${b.task.id} ${ctx.theme.dim(\n b.reason === 'failed-dependency'\n ? `blocked: ${b.blockedBy.join(', ')} failed`\n : `waiting on ${b.blockedBy.join(', ')}`,\n )}`,\n );\n }\n return EXIT.ok;\n }\n for (const line of formatTaskDetail(ctx.theme, task)) ctx.out(line);\n return EXIT.ok;\n}\n\nexport interface AddTaskOptions {\n depends?: string[];\n priority?: number;\n description?: string;\n acceptance?: string[];\n}\n\nexport async function tasksAdd(\n ctx: CliContext,\n id: string,\n titleWords: string[],\n opts: AddTaskOptions,\n): Promise<number> {\n const title = titleWords.join(' ').trim();\n if (!title) throw new CliError('A task needs a title: davecode tasks add <id> <title…>');\n const brain = await openBrain(ctx);\n const now = new Date().toISOString();\n const task: TaskNode = {\n id,\n title,\n status: 'PENDING',\n dependsOn: opts.depends ?? [],\n createdAt: now,\n updatedAt: now,\n };\n if (opts.priority !== undefined) task.priority = opts.priority;\n if (opts.description) task.description = opts.description;\n if (opts.acceptance && opts.acceptance.length > 0) task.acceptance = opts.acceptance;\n\n await graphErrors(() =>\n // Read-modify-write under the shared .davecode/.lock (the runner and dashboard use it too).\n brain.withLock(async () => {\n const graph = await brain.readGraph();\n if (graph.tasks.some((t) => t.id === id)) {\n throw new CliError(`Task ${JSON.stringify(id)} already exists`, {\n hint: `Change it with: davecode tasks status ${id} <STATUS>`,\n });\n }\n const next = parseTaskGraph({ ...graph, tasks: [...graph.tasks, task] });\n const tmp = `${brain.paths.taskGraph}.${process.pid}.tmp`;\n await writeFile(tmp, `${JSON.stringify(next, null, 2)}\\n`);\n await rename(tmp, brain.paths.taskGraph);\n }),\n );\n\n if (ctx.json) {\n printJson(ctx, { task });\n return EXIT.ok;\n }\n ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} Added ${ctx.theme.bold(id)} ${title}`);\n if (task.dependsOn.length > 0)\n ctx.out(ctx.theme.dim(` depends on ${task.dependsOn.join(', ')}`));\n return EXIT.ok;\n}\n\nexport function parseStatus(value: string): TaskStatus {\n const normalized = value.trim().toUpperCase().replace(/[-\\s]/g, '_');\n const aliases: Record<string, TaskStatus> = {\n DONE: 'SUCCESS',\n RUNNING: 'IN_PROGRESS',\n TODO: 'PENDING',\n FAIL: 'FAILED',\n };\n const status = (aliases[normalized] ?? normalized) as TaskStatus;\n if (!(TASK_STATUSES as readonly string[]).includes(status)) {\n throw new CliError(`Unknown status ${JSON.stringify(value)}`, {\n hint: `Use one of: ${TASK_STATUSES.join(', ')}`,\n });\n }\n return status;\n}\n\nexport async function tasksStatus(\n ctx: CliContext,\n id: string,\n statusArg: string,\n opts: { notes?: string },\n): Promise<number> {\n const status = parseStatus(statusArg);\n const brain = await openBrain(ctx);\n const task = await graphErrors(() =>\n brain.setTaskStatus(id, status, opts.notes !== undefined ? { notes: opts.notes } : {}),\n );\n if (ctx.json) {\n printJson(ctx, { task });\n return EXIT.ok;\n }\n ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} ${ctx.theme.bold(task.id)} is now ${task.status}`);\n return EXIT.ok;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/tasks.ts"],"sourcesContent":["import { rename, writeFile } from 'node:fs/promises';\nimport { basename } from 'node:path';\nimport {\n blockedTasks,\n nextTask,\n ProjectBrain,\n parseTaskGraph,\n summarize,\n TASK_STATUSES,\n TaskGraphError,\n type TaskNode,\n type TaskStatus,\n} from '@davecode/core';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { formatTaskDetail, formatTaskTree, summaryLine } from '../lib/task-tree';\nimport { detectProjectRoot } from '../runtime';\n\nasync function openBrain(ctx: CliContext): Promise<ProjectBrain> {\n const root = await detectProjectRoot(ctx.cwd, ctx.home);\n const brain = root ? new ProjectBrain(root) : undefined;\n if (!brain || !(await brain.isInitialised())) {\n throw new CliError('No project brain here', {\n hint: 'Run `davecode init` in your repository first.',\n });\n }\n return brain;\n}\n\n/** Turn graph validation failures into readable CLI errors. */\nasync function graphErrors<T>(fn: () => Promise<T>): Promise<T> {\n try {\n return await fn();\n } catch (err) {\n if (err instanceof TaskGraphError) {\n throw new CliError(err.issues.map((i) => i.message).join('\\n'), {\n hint: 'TASK_GRAPH.json was left unchanged.',\n });\n }\n throw err;\n }\n}\n\nexport async function tasksList(ctx: CliContext): Promise<number> {\n const brain = await openBrain(ctx);\n const graph = await graphErrors(() => brain.readGraph());\n if (ctx.json) {\n printJson(ctx, {\n root: brain.root,\n summary: summarize(graph),\n next: nextTask(graph)?.id ?? null,\n blocked: blockedTasks(graph).map((b) => ({\n id: b.task.id,\n reason: b.reason,\n blockedBy: b.blockedBy,\n })),\n graph,\n });\n return EXIT.ok;\n }\n const { theme } = ctx;\n ctx.out(`${theme.bold(theme.accent('Tasks'))} ${theme.dim(basename(brain.root))}`);\n if (graph.tasks.length > 0) ctx.out(summaryLine(theme, graph));\n ctx.out();\n for (const line of formatTaskTree(theme, graph, { width: ctx.columns })) ctx.out(line);\n if (graph.tasks.length === 0) {\n ctx.out(`Add one with ${theme.accent('davecode tasks add <id> \"<title>\"')}.`);\n }\n return EXIT.ok;\n}\n\nexport async function tasksNext(ctx: CliContext): Promise<number> {\n const brain = await openBrain(ctx);\n const graph = await graphErrors(() => brain.readGraph());\n const task = nextTask(graph);\n if (ctx.json) {\n printJson(ctx, { next: task ?? null });\n return EXIT.ok;\n }\n if (!task) {\n const blocked = blockedTasks(graph);\n const running = graph.tasks.filter((t) => t.status === 'IN_PROGRESS');\n ctx.out(ctx.theme.dim('Nothing is ready to run.'));\n for (const t of running) ctx.out(` ${ctx.theme.accent(t.id)} is in progress`);\n for (const b of blocked) {\n ctx.out(\n ` ${b.task.id} ${ctx.theme.dim(\n b.reason === 'failed-dependency'\n ? `blocked: ${b.blockedBy.join(', ')} failed`\n : `waiting on ${b.blockedBy.join(', ')}`,\n )}`,\n );\n }\n return EXIT.ok;\n }\n for (const line of formatTaskDetail(ctx.theme, task)) ctx.out(line);\n return EXIT.ok;\n}\n\nexport interface AddTaskOptions {\n depends?: string[];\n priority?: number;\n description?: string;\n acceptance?: string[];\n}\n\nexport async function tasksAdd(\n ctx: CliContext,\n id: string,\n titleWords: string[],\n opts: AddTaskOptions,\n): Promise<number> {\n const title = titleWords.join(' ').trim();\n if (!title) throw new CliError('A task needs a title: davecode tasks add <id> <title…>');\n const brain = await openBrain(ctx);\n const now = new Date().toISOString();\n const task: TaskNode = {\n id,\n title,\n status: 'PENDING',\n dependsOn: opts.depends ?? [],\n createdAt: now,\n updatedAt: now,\n };\n if (opts.priority !== undefined) task.priority = opts.priority;\n if (opts.description) task.description = opts.description;\n if (opts.acceptance && opts.acceptance.length > 0) task.acceptance = opts.acceptance;\n\n await graphErrors(() =>\n // Read-modify-write under the shared .davecode/.lock (the runner and dashboard use it too).\n brain.withLock(async () => {\n const graph = await brain.readGraph();\n if (graph.tasks.some((t) => t.id === id)) {\n throw new CliError(`Task ${JSON.stringify(id)} already exists`, {\n hint: `Change it with: davecode tasks status ${id} <STATUS>`,\n });\n }\n const next = parseTaskGraph({ ...graph, tasks: [...graph.tasks, task] });\n const tmp = `${brain.paths.taskGraph}.${process.pid}.tmp`;\n await writeFile(tmp, `${JSON.stringify(next, null, 2)}\\n`);\n await rename(tmp, brain.paths.taskGraph);\n }),\n );\n\n if (ctx.json) {\n printJson(ctx, { task });\n return EXIT.ok;\n }\n ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} Added ${ctx.theme.bold(id)} ${title}`);\n if (task.dependsOn.length > 0)\n ctx.out(ctx.theme.dim(` depends on ${task.dependsOn.join(', ')}`));\n return EXIT.ok;\n}\n\nexport function parseStatus(value: string): TaskStatus {\n const normalized = value.trim().toUpperCase().replace(/[-\\s]/g, '_');\n const aliases: Record<string, TaskStatus> = {\n DONE: 'SUCCESS',\n RUNNING: 'IN_PROGRESS',\n TODO: 'PENDING',\n FAIL: 'FAILED',\n };\n const status = (aliases[normalized] ?? normalized) as TaskStatus;\n if (!(TASK_STATUSES as readonly string[]).includes(status)) {\n throw new CliError(`Unknown status ${JSON.stringify(value)}`, {\n hint: `Use one of: ${TASK_STATUSES.join(', ')}`,\n });\n }\n return status;\n}\n\nexport async function tasksStatus(\n ctx: CliContext,\n id: string,\n statusArg: string,\n opts: { notes?: string },\n): Promise<number> {\n const status = parseStatus(statusArg);\n const brain = await openBrain(ctx);\n const task = await graphErrors(() =>\n brain.setTaskStatus(id, status, opts.notes !== undefined ? { notes: opts.notes } : {}),\n );\n if (ctx.json) {\n printJson(ctx, { task });\n return EXIT.ok;\n }\n ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} ${ctx.theme.bold(task.id)} is now ${task.status}`);\n return EXIT.ok;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dmrlzz/davecode",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
4
4
  "description": "DaveCode CLI & TUI: run the gateway, manage accounts and drive the autonomous engine from your terminal.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,10 +44,10 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@fastify/cors": "^11.3.1",
47
- "@fastify/static": "^10.1.7",
47
+ "@fastify/static": "^10.1.8",
48
48
  "better-sqlite3": "^13.0.3",
49
49
  "commander": "^15.0.0",
50
- "fastify": "^5.12.5",
50
+ "fastify": "^5.12.7",
51
51
  "ink": "^8.0.0",
52
52
  "js-tiktoken": "^1.0.21",
53
53
  "react": "^19.3.1",
@@ -64,9 +64,9 @@
64
64
  "devDependencies": {
65
65
  "@types/react": "^19.3.0",
66
66
  "ink-testing-library": "^4.0.0",
67
- "@davecode/server": "0.5.0",
68
- "@davecode/ui": "0.5.0",
69
- "@davecode/core": "0.5.0"
67
+ "@davecode/core": "0.5.2",
68
+ "@davecode/server": "0.5.2",
69
+ "@davecode/ui": "0.5.2"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsup",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/accounts.ts","../src/lib/account-flow.ts"],"sourcesContent":["import { createInterface } from 'node:readline';\nimport {\n type Account,\n type AccountConnection,\n CLI_LOGINS,\n cliBinaryFor,\n globalPaths,\n loginEnv,\n type ProviderKind,\n SandboxManager,\n type SubscriptionInfo,\n} from '@davecode/core';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport {\n type AddFlags,\n accountFromFlags,\n accountInteractively,\n accountPolicy,\n describeCreate,\n providerInfo,\n} from '../lib/account-flow';\nimport { type AccountsBackend, openAccounts, resolveAccount } from '../lib/accounts-backend';\nimport { type SpawnFn, spawnInteractive, which } from '../lib/proc';\nimport { PromptCancelledError, type Prompter } from '../lib/prompter';\nimport { detectProjectRoot } from '../runtime';\nimport { type Column, table, truncate } from '../ui/format';\nimport type { Theme } from '../ui/theme';\n\nexport interface AccountsDeps {\n /** Override the backend (tests). */\n backend?: AccountsBackend;\n prompter?: Prompter;\n readStdin?: () => Promise<string>;\n spawn?: SpawnFn;\n /** Used by `accounts login --hold` (tests). */\n waitForEnter?: () => Promise<void>;\n}\n\nexport interface BackendFlags {\n /** Write to state.db even if a gateway is running. */\n local?: boolean;\n}\n\nasync function backendFor(\n ctx: CliContext,\n flags: BackendFlags,\n deps: AccountsDeps,\n): Promise<AccountsBackend> {\n if (deps.backend) return deps.backend;\n const projectRoot = await detectProjectRoot(ctx.cwd, ctx.home);\n return openAccounts({\n home: ctx.home,\n env: ctx.env,\n ...(projectRoot ? { projectRoot } : {}),\n ...(flags.local ? { local: true } : {}),\n });\n}\n\nasync function withBackend<T>(\n ctx: CliContext,\n flags: BackendFlags,\n deps: AccountsDeps,\n fn: (backend: AccountsBackend) => Promise<T>,\n): Promise<T> {\n const backend = await backendFor(ctx, flags, deps);\n try {\n return await fn(backend);\n } finally {\n if (!deps.backend) backend.close();\n }\n}\n\nasync function prompterFor(ctx: CliContext, deps: AccountsDeps): Promise<Prompter> {\n if (deps.prompter) return deps.prompter;\n const { createInkPrompter } = await import('../tui/prompts');\n return createInkPrompter({ stdout: ctx.io.stdout, stdin: ctx.io.stdin, theme: ctx.theme });\n}\n\nfunction readAllStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = '';\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => {\n data += chunk;\n });\n process.stdin.on('end', () => resolve(data));\n process.stdin.on('error', reject);\n });\n}\n\n// ---------------------------------------------------------------------------\n// list\n// ---------------------------------------------------------------------------\n\nfunction statusText(theme: Theme, account: Account): string {\n switch (account.status) {\n case 'active':\n return theme.ok('active');\n case 'cooldown':\n return theme.warn('cooldown');\n case 'error':\n return theme.error('error');\n default:\n return theme.dim('disabled');\n }\n}\n\nfunction detail(account: Account): string {\n const config = account.config;\n const parts: string[] = [];\n if (typeof config.baseUrl === 'string') parts.push(config.baseUrl);\n if (Array.isArray(config.models) && config.models.length > 0) {\n parts.push(config.models.slice(0, 3).join(', ') + (config.models.length > 3 ? ', …' : ''));\n }\n if (typeof config.binaryPath === 'string') parts.push(config.binaryPath);\n return parts.join(' · ');\n}\n\nexport function renderAccountList(theme: Theme, accounts: Account[], columns: number): string[] {\n const cols: Column[] = [\n { header: 'ID' },\n { header: 'LABEL' },\n { header: 'PROVIDER' },\n { header: 'STATUS' },\n { header: 'PRI', align: 'right', drop: 2 },\n { header: 'WEIGHT', align: 'right', drop: 3 },\n { header: 'DETAILS', drop: 4 },\n ];\n const rows = accounts.map((a) => [\n theme.accent(a.id),\n truncate(a.label, 28),\n a.provider,\n statusText(theme, a),\n String(a.priority),\n String(a.weight),\n theme.dim(truncate(detail(a), 40)),\n ]);\n return table(theme, cols, rows, columns);\n}\n\nexport async function accountsList(\n ctx: CliContext,\n flags: BackendFlags = {},\n deps: AccountsDeps = {},\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const accounts = await backend.list();\n if (ctx.json) {\n printJson(ctx, { source: backend.kind, accounts });\n return EXIT.ok;\n }\n if (accounts.length === 0) {\n ctx.out(ctx.theme.dim('No accounts yet.'));\n ctx.out(`Add one with ${ctx.theme.accent('davecode accounts add')}.`);\n return EXIT.ok;\n }\n for (const line of renderAccountList(ctx.theme, accounts, ctx.columns)) ctx.out(line);\n ctx.out();\n ctx.out(\n ctx.theme.dim(backend.kind === 'gateway' ? 'source: running gateway' : 'source: local state'),\n );\n return EXIT.ok;\n });\n}\n\n// ---------------------------------------------------------------------------\n// add\n// ---------------------------------------------------------------------------\n\nexport interface AddCommandFlags extends AddFlags, BackendFlags {\n /** Never prompt; everything comes from flags. */\n yes?: boolean;\n /** commander's `--no-login`. */\n login?: boolean;\n}\n\nexport async function accountsAdd(\n ctx: CliContext,\n flags: AddCommandFlags,\n deps: AccountsDeps = {},\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const existing = await backend.list();\n const interactive = ctx.interactive && !flags.yes && !flags.secretStdin;\n const { theme, errTheme } = ctx;\n\n let create: Awaited<ReturnType<typeof accountFromFlags>> | undefined;\n if (interactive) {\n try {\n create = await accountInteractively(flags, {\n prompter: await prompterFor(ctx, deps),\n config: backend.config,\n existing,\n say: (line) => ctx.out(line),\n warn: theme.warn,\n });\n } catch (err) {\n if (err instanceof PromptCancelledError) {\n ctx.err(errTheme.dim('Cancelled.'));\n return EXIT.failure;\n }\n throw err;\n }\n if (!create) {\n ctx.err(errTheme.dim('Nothing added.'));\n return EXIT.failure;\n }\n } else {\n create = await accountFromFlags(flags, {\n env: ctx.env,\n readStdin: deps.readStdin ?? readAllStdin,\n });\n const policy = accountPolicy(create.provider, backend.config, existing);\n if (policy.blocked) {\n throw new CliError(policy.blocked.message, { hint: policy.blocked.hint });\n }\n for (const warning of policy.warnings) {\n ctx.err(errTheme.warn(`${errTheme.glyph.warn} ${warning}`));\n }\n if (flags.secret !== undefined) {\n ctx.err(\n errTheme.dim(\n 'Note: --secret is visible in shell history and process lists; prefer --secret-env or --secret-stdin.',\n ),\n );\n }\n }\n\n const account = await backend.create(create);\n if (ctx.json) {\n printJson(ctx, { account });\n return EXIT.ok;\n }\n ctx.out(\n `${theme.ok(theme.glyph.ok)} Added ${theme.bold(account.label)} ${theme.dim(`(${account.id}, ${account.provider})`)}`,\n );\n if (!interactive) {\n for (const line of describeCreate(create)) ctx.out(theme.dim(` ${line}`));\n }\n\n const info = providerInfo(account.provider);\n if (info?.auth === 'cli-login') {\n const loginNow =\n interactive &&\n flags.login !== false &&\n (await (\n await prompterFor(ctx, deps)\n ).confirm(`Log in to ${info.binary} for this account now?`, true));\n if (loginNow) return accountsLogin(ctx, account.id, [], flags, { ...deps, backend });\n ctx.out(\n theme.dim(`Next: log in with ${theme.accent(`davecode accounts login ${account.id}`)}`),\n );\n }\n return EXIT.ok;\n });\n}\n\n// ---------------------------------------------------------------------------\n// remove / enable / disable\n// ---------------------------------------------------------------------------\n\nexport async function accountsRemove(\n ctx: CliContext,\n ref: string,\n flags: BackendFlags & { yes?: boolean },\n deps: AccountsDeps = {},\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const account = await resolveAccount(backend, ref);\n if (!flags.yes) {\n if (!ctx.interactive) {\n throw new CliError(`Refusing to remove ${account.id} without confirmation`, {\n hint: 'Pass --yes to remove it non-interactively.',\n });\n }\n const ok = await (await prompterFor(ctx, deps))\n .confirm(`Remove ${account.label} (${account.id}) and its sandbox?`, false)\n .catch((err: unknown) => {\n if (err instanceof PromptCancelledError) return false;\n throw err;\n });\n if (!ok) {\n ctx.err(ctx.errTheme.dim('Nothing removed.'));\n return EXIT.failure;\n }\n }\n await backend.remove(account.id);\n if (ctx.json) printJson(ctx, { removed: account.id });\n else ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} Removed ${account.label} (${account.id})`);\n return EXIT.ok;\n });\n}\n\nexport async function accountsSetEnabled(\n ctx: CliContext,\n ref: string,\n enabled: boolean,\n flags: BackendFlags = {},\n deps: AccountsDeps = {},\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const account = await resolveAccount(backend, ref);\n const updated = await backend.update(account.id, { enabled });\n if (ctx.json) printJson(ctx, { account: updated });\n else {\n ctx.out(\n `${ctx.theme.ok(ctx.theme.glyph.ok)} ${updated.label} is now ${enabled ? 'enabled' : 'disabled'} ${ctx.theme.dim(`(${updated.status})`)}`,\n );\n }\n return EXIT.ok;\n });\n}\n\n// ---------------------------------------------------------------------------\n// plan (subscription details)\n// ---------------------------------------------------------------------------\n\nexport interface PlanFlags extends BackendFlags {\n plan?: string;\n paid?: string;\n renews?: string;\n price?: string;\n currency?: string;\n period?: string;\n notes?: string;\n clear?: boolean;\n}\n\nexport function describeSubscription(subscription: SubscriptionInfo | undefined): string {\n if (!subscription) return 'no plan recorded';\n const parts: string[] = [];\n if (subscription.plan) parts.push(subscription.plan);\n if (subscription.price) {\n const { amount, currency, period } = subscription.price;\n parts.push(`${amount} ${currency}/${period}`);\n }\n if (subscription.paidAt) parts.push(`paid ${subscription.paidAt}`);\n if (subscription.renewsAt) parts.push(`renews ${subscription.renewsAt}`);\n if (subscription.notes) parts.push(subscription.notes);\n return parts.length > 0 ? parts.join(' · ') : 'no plan recorded';\n}\n\n/** Merge plan flags into the existing subscription details (validated by the backend). */\nexport function subscriptionFromFlags(\n existing: SubscriptionInfo | undefined,\n flags: PlanFlags,\n): SubscriptionInfo {\n const next: SubscriptionInfo = { ...existing };\n if (flags.plan !== undefined) next.plan = flags.plan;\n if (flags.paid !== undefined) next.paidAt = flags.paid;\n if (flags.renews !== undefined) next.renewsAt = flags.renews;\n if (flags.notes !== undefined) next.notes = flags.notes;\n if (flags.price !== undefined || flags.currency !== undefined || flags.period !== undefined) {\n const amount = flags.price !== undefined ? Number(flags.price) : existing?.price?.amount;\n if (amount === undefined || !Number.isFinite(amount)) {\n throw new CliError('--price needs a number, e.g. --price 20', {\n hint: 'Set the amount with --price, and optionally --currency USD --period month.',\n });\n }\n const period = flags.period ?? existing?.price?.period ?? 'month';\n if (period !== 'month' && period !== 'year') {\n throw new CliError('--period must be \"month\" or \"year\"');\n }\n next.price = { amount, currency: flags.currency ?? existing?.price?.currency ?? 'USD', period };\n }\n return next;\n}\n\nexport async function accountsPlan(\n ctx: CliContext,\n ref: string,\n flags: PlanFlags = {},\n deps: AccountsDeps = {},\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const account = await resolveAccount(backend, ref);\n const { theme } = ctx;\n const changes = ['plan', 'paid', 'renews', 'price', 'currency', 'period', 'notes'] as const;\n const editing = flags.clear || changes.some((key) => flags[key] !== undefined);\n if (!editing) {\n if (ctx.json)\n printJson(ctx, { account: account.id, subscription: account.subscription ?? null });\n else ctx.out(`${theme.bold(account.label)}: ${describeSubscription(account.subscription)}`);\n return EXIT.ok;\n }\n const subscription = flags.clear ? null : subscriptionFromFlags(account.subscription, flags);\n const updated = await backend.update(account.id, { subscription });\n if (ctx.json) printJson(ctx, { account: updated });\n else {\n ctx.out(\n `${theme.ok(theme.glyph.ok)} ${updated.label}: ${describeSubscription(updated.subscription)}`,\n );\n }\n return EXIT.ok;\n });\n}\n\n// ---------------------------------------------------------------------------\n// login\n// ---------------------------------------------------------------------------\n\n/** Arguments that start each CLI's own official login flow. */\nexport function loginArgs(provider: ProviderKind): string[] {\n return CLI_LOGINS[provider]?.loginArgs ?? [];\n}\n\nexport interface LoginFlags extends BackendFlags {\n /** Wait for Enter before exiting (used when the dashboard opened this in a new window). */\n hold?: boolean;\n}\n\nfunction waitForEnter(): Promise<void> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question('Press Enter to close this window.', () => {\n rl.close();\n resolve();\n });\n rl.once('close', resolve);\n });\n}\n\nexport function describeConnection(theme: Theme, connection: AccountConnection): string {\n const label: Record<AccountConnection['status'], string> = {\n connected: theme.ok(`${theme.glyph.ok} connected`),\n not_connected: theme.warn(`${theme.glyph.warn} not connected`),\n unknown: theme.dim('? unknown'),\n };\n return `${label[connection.status]}${connection.detail ? theme.dim(` — ${connection.detail}`) : ''}`;\n}\n\nexport async function accountsLogin(\n ctx: CliContext,\n ref: string,\n extraArgs: string[] = [],\n flags: LoginFlags = {},\n deps: AccountsDeps = {},\n): Promise<number> {\n if (!flags.hold) return runLogin(ctx, ref, extraArgs, flags, deps);\n try {\n return await runLogin(ctx, ref, extraArgs, flags, deps);\n } catch (err) {\n ctx.err(ctx.errTheme.warn(err instanceof Error ? err.message : String(err)));\n return EXIT.failure;\n } finally {\n await (deps.waitForEnter ?? waitForEnter)();\n }\n}\n\nfunction runLogin(\n ctx: CliContext,\n ref: string,\n extraArgs: string[],\n flags: LoginFlags,\n deps: AccountsDeps,\n): Promise<number> {\n return withBackend(ctx, flags, deps, async (backend) => {\n const account = await resolveAccount(backend, ref);\n const spec = CLI_LOGINS[account.provider];\n if (!spec) {\n const info = providerInfo(account.provider);\n throw new CliError(`${account.provider} accounts do not use a CLI login`, {\n hint:\n info?.auth === 'api-key' || info?.auth === 'optional-key'\n ? `Rotate the key with: davecode accounts add … or PATCH /api/accounts/${account.id}`\n : undefined,\n });\n }\n const binary = cliBinaryFor(account) ?? spec.binary;\n const resolved = which(binary, ctx.env);\n if (!resolved) {\n throw new CliError(`Cannot find \\`${binary}\\` on PATH`, { hint: spec.installHint });\n }\n\n const sandboxes = new SandboxManager(globalPaths(ctx.home).sandboxes);\n const dir = sandboxes.prepare(account);\n const isolation = loginEnv(account, sandboxes);\n const env = { ...ctx.env, ...isolation };\n const [variable] = Object.keys(isolation);\n const { theme } = ctx;\n\n ctx.out(\n `${theme.accent(theme.glyph.arrow)} Logging in ${theme.bold(account.label)} ${theme.dim(`(${account.id})`)}`,\n );\n ctx.out(theme.dim(` ${variable}=${dir}`));\n ctx.out(theme.dim(` ${spec.instructions}`));\n ctx.out(theme.dim(' DaveCode never sees your password; the vendor CLI keeps the login.'));\n ctx.out();\n\n const args = extraArgs.length > 0 ? extraArgs : spec.loginArgs;\n const exit = await spawnInteractive(resolved, args, {\n env,\n cwd: dir,\n ...(deps.spawn ? { spawn: deps.spawn } : {}),\n });\n ctx.out();\n if (exit !== 0) {\n ctx.err(ctx.errTheme.warn(`${binary} exited with code ${exit}`));\n return exit;\n }\n if (account.status === 'error' && account.enabled) {\n // A fresh login fixes auth errors; reset the account so the router tries it again.\n await backend.update(account.id, { enabled: true });\n }\n const connection = await backend.connection(account.id).catch(() => undefined);\n if (connection) ctx.out(` ${describeConnection(theme, connection)}`);\n ctx.out(\n `${theme.ok(theme.glyph.ok)} ${account.label} is ready. Its login lives only in ${dir}`,\n );\n return EXIT.ok;\n });\n}\n\nexport interface ConnectFlags extends BackendFlags {\n /** Only report the connection state. */\n check?: boolean;\n}\n\n/**\n * \"Connect subscription\" from the terminal: show the account's connection state and, for\n * CLI-login accounts that are not connected, run the vendor's official login.\n */\nexport async function accountsConnect(\n ctx: CliContext,\n ref: string,\n flags: ConnectFlags = {},\n deps: AccountsDeps = {},\n): Promise<number> {\n const { account, connection } = await withBackend(ctx, flags, deps, async (backend) => {\n const account = await resolveAccount(backend, ref);\n return { account, connection: await backend.connection(account.id) };\n });\n if (ctx.json) {\n printJson(ctx, { connection });\n return connection.status === 'connected' || flags.check ? EXIT.ok : EXIT.failure;\n }\n const { theme } = ctx;\n ctx.out(`${theme.bold(account.label)} ${theme.dim(`(${account.id}, ${account.provider})`)}`);\n ctx.out(` ${describeConnection(theme, connection)}`);\n if (flags.check || connection.status === 'connected') return EXIT.ok;\n if (connection.method === 'api-key') {\n ctx.out(\n theme.dim(\n ` Store a key in the dashboard (Accounts → ${account.label}) or re-add the account with --secret-env.`,\n ),\n );\n return EXIT.failure;\n }\n if (connection.method !== 'cli-login') return EXIT.failure;\n ctx.out();\n return accountsLogin(ctx, account.id, [], flags, deps);\n}\n","import {\n type Account,\n type DaveConfig,\n EXPERIMENTAL_PROVIDER_KINDS,\n type ProviderKind,\n type QuotaLimits,\n SUBSCRIPTION_PROVIDER_KINDS,\n} from '@davecode/core';\nimport { CliError } from '../errors';\nimport type { AccountCreate } from './accounts-backend';\nimport type { Prompter } from './prompter';\n\n// ---------------------------------------------------------------------------\n// Provider catalogue\n// ---------------------------------------------------------------------------\n\nexport type AuthKind = 'api-key' | 'optional-key' | 'cli-login' | 'browser';\n\nexport interface ProviderInfo {\n kind: ProviderKind;\n name: string;\n auth: AuthKind;\n defaultLabel: string;\n /** Default CLI binary for `cli-login` providers. */\n binary?: string;\n}\n\nexport const PROVIDERS: readonly ProviderInfo[] = [\n { kind: 'anthropic', name: 'Anthropic API', auth: 'api-key', defaultLabel: 'Anthropic' },\n { kind: 'openai', name: 'OpenAI API', auth: 'api-key', defaultLabel: 'OpenAI' },\n { kind: 'gemini', name: 'Google Gemini API', auth: 'api-key', defaultLabel: 'Gemini' },\n {\n kind: 'openai-compatible',\n name: 'OpenRouter or another OpenAI-compatible provider',\n auth: 'optional-key',\n defaultLabel: 'OpenRouter',\n },\n {\n kind: 'claude-cli',\n name: 'Claude Code CLI (your Claude login)',\n auth: 'cli-login',\n defaultLabel: 'Claude Code',\n binary: 'claude',\n },\n {\n kind: 'codex-cli',\n name: 'Codex CLI (your ChatGPT/OpenAI login)',\n auth: 'cli-login',\n defaultLabel: 'Codex',\n binary: 'codex',\n },\n {\n kind: 'antigravity-cli',\n name: 'Antigravity CLI (your Google sign-in in agy)',\n auth: 'cli-login',\n defaultLabel: 'Antigravity',\n binary: 'agy',\n },\n {\n kind: 'gemini-cli',\n name: 'Gemini CLI (your Google login)',\n auth: 'cli-login',\n defaultLabel: 'Gemini CLI',\n binary: 'gemini',\n },\n {\n kind: 'gemini-web',\n name: 'Gemini web session (experimental)',\n auth: 'browser',\n defaultLabel: 'Gemini web',\n },\n];\n\nexport function providerInfo(kind: string): ProviderInfo | undefined {\n return PROVIDERS.find((p) => p.kind === kind);\n}\n\nexport const DEFAULT_COMPATIBLE_URL = 'https://openrouter.ai/api/v1';\n\n// ---------------------------------------------------------------------------\n// Terms-of-Service policy\n// ---------------------------------------------------------------------------\n\nexport const GEMINI_WEB_TOS =\n 'gemini-web automates the consumer Gemini web app through a browser profile. This likely ' +\n 'violates Google’s Terms of Service and your account can be rate-limited or suspended.';\n\nexport const ROTATION_TOS =\n 'Rotating several subscription logins of the same provider to get around per-account limits ' +\n 'may violate the provider’s consumer terms; accounts can be rate-limited or suspended.';\n\nexport interface Policy {\n /** The account cannot be added with the current flags. */\n blocked?: { message: string; hint: string };\n /** Shown (and, interactively, confirmed) before adding. */\n warnings: string[];\n}\n\n/** Experimental-flag rules for adding an account of `provider`. */\nexport function accountPolicy(\n provider: ProviderKind,\n config: Pick<DaveConfig, 'experimental'>,\n existing: Pick<Account, 'provider'>[],\n): Policy {\n const warnings: string[] = [];\n if (EXPERIMENTAL_PROVIDER_KINDS.includes(provider)) {\n if (!config.experimental.geminiWeb) {\n return {\n warnings,\n blocked: {\n message: `${provider} is experimental and disabled. ${GEMINI_WEB_TOS}`,\n hint: 'If you accept the risk, set \"experimental\": { \"geminiWeb\": true } in ~/.davecode/config.json (or DAVECODE_EXPERIMENTAL_GEMINI_WEB=1).',\n },\n };\n }\n warnings.push(GEMINI_WEB_TOS);\n }\n const sameProvider = existing.filter((a) => a.provider === provider).length;\n if (SUBSCRIPTION_PROVIDER_KINDS.includes(provider) && sameProvider > 0) {\n if (!config.experimental.multiAccountRotation) {\n return {\n warnings,\n blocked: {\n message: `You already have a ${provider} account. ${ROTATION_TOS}`,\n hint: 'If you accept the risk, set \"experimental\": { \"multiAccountRotation\": true } in ~/.davecode/config.json (or DAVECODE_EXPERIMENTAL_MULTI_ACCOUNT_ROTATION=1).',\n },\n };\n }\n warnings.push(ROTATION_TOS);\n }\n return { warnings };\n}\n\n// ---------------------------------------------------------------------------\n// Flags → AccountCreate\n// ---------------------------------------------------------------------------\n\nexport interface AddFlags {\n provider?: string;\n label?: string;\n priority?: number;\n weight?: number;\n /** Discouraged: visible in shell history and process listings. */\n secret?: string;\n /** Read the secret from this environment variable. */\n secretEnv?: string;\n /** Read the secret from stdin. */\n secretStdin?: boolean;\n baseUrl?: string;\n model?: string[];\n defaultModel?: string;\n binaryPath?: string;\n /** `key=value` quota limits, e.g. `tokens5h=500000`. */\n limit?: string[];\n /** commander's `--disabled`. */\n disabled?: boolean;\n}\n\nconst LIMIT_KEYS = [\n 'tpm',\n 'rpm',\n 'tokens5h',\n 'requests5h',\n 'tokensDaily',\n 'requestsDaily',\n] as const;\n\nexport function parseLimits(pairs: string[] = []): QuotaLimits {\n const limits: QuotaLimits = {};\n for (const pair of pairs) {\n const [rawKey, rawValue] = pair.split('=', 2);\n const key = LIMIT_KEYS.find((k) => k.toLowerCase() === rawKey?.trim().toLowerCase());\n const value = Number(rawValue);\n if (!key) {\n throw new CliError(`Unknown limit ${JSON.stringify(rawKey)}`, {\n hint: `Use one of: ${LIMIT_KEYS.join(', ')} (e.g. --limit tokens5h=500000)`,\n });\n }\n if (!Number.isInteger(value) || value <= 0) {\n throw new CliError(\n `Limit ${key} must be a positive integer, got ${JSON.stringify(rawValue)}`,\n );\n }\n limits[key] = value;\n }\n return limits;\n}\n\nexport function validateUrl(value: string): string | undefined {\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:'\n ? undefined\n : 'must be an http(s) URL';\n } catch {\n return 'must be a valid URL, e.g. http://localhost:11434/v1';\n }\n}\n\nfunction requireProvider(value: string | undefined): ProviderInfo {\n if (!value) {\n throw new CliError('Missing --provider', {\n hint: `One of: ${PROVIDERS.map((p) => p.kind).join(', ')}`,\n });\n }\n const info = providerInfo(value);\n if (!info) {\n throw new CliError(`Unknown provider ${JSON.stringify(value)}`, {\n hint: `One of: ${PROVIDERS.map((p) => p.kind).join(', ')}`,\n });\n }\n return info;\n}\n\nexport interface SecretSources {\n env: NodeJS.ProcessEnv;\n readStdin: () => Promise<string>;\n}\n\nasync function secretFromFlags(\n flags: AddFlags,\n sources: SecretSources,\n): Promise<string | undefined> {\n const chosen = [flags.secret !== undefined, !!flags.secretEnv, !!flags.secretStdin].filter(\n Boolean,\n );\n if (chosen.length > 1) {\n throw new CliError('Use only one of --secret, --secret-env and --secret-stdin');\n }\n if (flags.secretStdin) {\n const value = (await sources.readStdin()).trim();\n if (!value) throw new CliError('No secret received on stdin');\n return value;\n }\n if (flags.secretEnv) {\n const value = sources.env[flags.secretEnv]?.trim();\n if (!value) throw new CliError(`Environment variable ${flags.secretEnv} is empty or unset`);\n return value;\n }\n const value = flags.secret?.trim();\n return value ? value : undefined;\n}\n\nfunction providerConfig(\n info: ProviderInfo,\n values: { baseUrl?: string; models?: string[]; defaultModel?: string; binaryPath?: string },\n): Record<string, unknown> {\n const config: Record<string, unknown> = {};\n if (values.baseUrl) config.baseUrl = values.baseUrl.replace(/\\/+$/, '');\n if (values.models && values.models.length > 0) config.models = [...new Set(values.models)];\n if (values.defaultModel) config.defaultModel = values.defaultModel;\n if (values.binaryPath && info.auth === 'cli-login') config.binaryPath = values.binaryPath;\n return config;\n}\n\n/** Build an account from flags only (scripts, CI). Never prompts. */\nexport async function accountFromFlags(\n flags: AddFlags,\n sources: SecretSources,\n): Promise<AccountCreate> {\n const info = requireProvider(flags.provider);\n const secret = await secretFromFlags(flags, sources);\n if (info.auth === 'api-key' && !secret) {\n throw new CliError(`${info.name} needs an API key`, {\n hint: 'Pass it with --secret-env <VAR> or pipe it with --secret-stdin.',\n });\n }\n if (secret && (info.auth === 'cli-login' || info.auth === 'browser')) {\n throw new CliError(`${info.kind} accounts do not take a secret`, {\n hint:\n info.auth === 'cli-login'\n ? 'Log in with `davecode accounts login <id>` after adding the account.'\n : 'The browser profile holds the session.',\n });\n }\n if (info.kind === 'openai-compatible') {\n if (!flags.baseUrl) {\n throw new CliError('openai-compatible accounts need --base-url', {\n hint: `e.g. --base-url ${DEFAULT_COMPATIBLE_URL} for OpenRouter`,\n });\n }\n }\n if (flags.baseUrl) {\n const problem = validateUrl(flags.baseUrl);\n if (problem) throw new CliError(`--base-url ${problem}`);\n }\n const create: AccountCreate = {\n provider: info.kind,\n label: flags.label?.trim() || info.defaultLabel,\n config: providerConfig(info, {\n ...(flags.baseUrl ? { baseUrl: flags.baseUrl } : {}),\n ...(flags.model ? { models: flags.model } : {}),\n ...(flags.defaultModel ? { defaultModel: flags.defaultModel } : {}),\n ...(flags.binaryPath ? { binaryPath: flags.binaryPath } : {}),\n }),\n };\n if (flags.priority !== undefined) create.priority = flags.priority;\n if (flags.weight !== undefined) create.weight = flags.weight;\n const limits = parseLimits(flags.limit);\n if (Object.keys(limits).length > 0) create.limits = limits;\n if (flags.disabled) create.enabled = false;\n if (secret) create.secret = secret;\n return create;\n}\n\n// ---------------------------------------------------------------------------\n// Interactive flow\n// ---------------------------------------------------------------------------\n\nexport interface InteractiveDeps {\n prompter: Prompter;\n config: Pick<DaveConfig, 'experimental'>;\n existing: Pick<Account, 'provider' | 'label'>[];\n /** Print a line (warnings, summary). */\n say: (line: string) => void;\n /** Style ToS warnings. */\n warn?: (text: string) => string;\n}\n\nfunction uniqueLabel(base: string, existing: Pick<Account, 'label'>[]): string {\n const taken = new Set(existing.map((a) => a.label.toLowerCase()));\n if (!taken.has(base.toLowerCase())) return base;\n for (let n = 2; ; n++) {\n const candidate = `${base} ${n}`;\n if (!taken.has(candidate.toLowerCase())) return candidate;\n }\n}\n\n/**\n * Ask for whatever the flags did not provide. Returns `undefined` when the user declines a\n * Terms-of-Service warning or the final confirmation.\n */\nexport async function accountInteractively(\n flags: AddFlags,\n deps: InteractiveDeps,\n): Promise<AccountCreate | undefined> {\n const { prompter, say } = deps;\n const warn = deps.warn ?? ((t: string) => t);\n\n const kind = flags.provider\n ? requireProvider(flags.provider).kind\n : await prompter.select(\n 'Provider',\n PROVIDERS.map((p) => ({ value: p.kind, label: p.name, hint: authHint(p.auth) })),\n 'anthropic',\n );\n const info = requireProvider(kind);\n\n const policy = accountPolicy(info.kind, deps.config, deps.existing);\n if (policy.blocked) throw new CliError(policy.blocked.message, { hint: policy.blocked.hint });\n for (const warning of policy.warnings) {\n say(warn(`! ${warning}`));\n if (!(await prompter.confirm('I understand the risk. Continue?', false))) return undefined;\n }\n\n const label =\n flags.label?.trim() ||\n (await prompter.text('Label', {\n initial: uniqueLabel(info.defaultLabel, deps.existing),\n validate: (v) => (v.trim() ? undefined : 'a label is required'),\n }));\n\n const priority =\n flags.priority ??\n Number(\n await prompter.text('Priority (lower is tried first)', {\n initial: '100',\n validate: (v) => (/^\\d+$/.test(v.trim()) ? undefined : 'enter a non-negative integer'),\n }),\n );\n\n let baseUrl = flags.baseUrl;\n let models = flags.model;\n if (info.kind === 'openai-compatible') {\n baseUrl ??= await prompter.text('Base URL', {\n initial: DEFAULT_COMPATIBLE_URL,\n validate: validateUrl,\n });\n if (!models) {\n const answer = await prompter.text('Models (comma-separated, empty to discover)', {\n initial: '',\n });\n models = answer\n .split(',')\n .map((m) => m.trim())\n .filter(Boolean);\n }\n }\n\n let secret: string | undefined;\n if (info.auth === 'api-key' || info.auth === 'optional-key') {\n const optional = info.auth === 'optional-key';\n const answer = await prompter.secret(\n optional ? 'API key (optional, input hidden)' : `${info.name} key (input hidden)`,\n { optional },\n );\n secret = answer.trim() || undefined;\n if (!secret && !optional) throw new CliError(`${info.name} needs an API key`);\n }\n\n const create: AccountCreate = {\n provider: info.kind,\n label: label.trim(),\n priority,\n config: providerConfig(info, {\n ...(baseUrl ? { baseUrl } : {}),\n ...(models ? { models } : {}),\n ...(flags.defaultModel ? { defaultModel: flags.defaultModel } : {}),\n ...(flags.binaryPath ? { binaryPath: flags.binaryPath } : {}),\n }),\n };\n if (flags.weight !== undefined) create.weight = flags.weight;\n const limits = parseLimits(flags.limit);\n if (Object.keys(limits).length > 0) create.limits = limits;\n if (flags.disabled) create.enabled = false;\n if (secret) create.secret = secret;\n\n say('');\n for (const line of describeCreate(create)) say(` ${line}`);\n say('');\n if (!(await prompter.confirm('Add this account?', true))) return undefined;\n return create;\n}\n\nfunction authHint(auth: AuthKind): string {\n switch (auth) {\n case 'api-key':\n return 'API key';\n case 'optional-key':\n return 'base URL, optional key';\n case 'cli-login':\n return 'local CLI login, isolated per account';\n default:\n return 'experimental, ToS risk';\n }\n}\n\n/** Summary lines for an account about to be created. Secrets are shown only as \"set\". */\nexport function describeCreate(create: AccountCreate): string[] {\n const lines = [\n `provider ${create.provider}`,\n `label ${create.label}`,\n `priority ${create.priority ?? 100}`,\n ];\n const config = create.config ?? {};\n if (typeof config.baseUrl === 'string') lines.push(`base URL ${config.baseUrl}`);\n if (Array.isArray(config.models) && config.models.length > 0) {\n lines.push(`models ${config.models.join(', ')}`);\n }\n if (create.limits && Object.keys(create.limits).length > 0) {\n lines.push(\n `limits ${Object.entries(create.limits)\n .map(([k, v]) => `${k}=${v}`)\n .join(' ')}`,\n );\n }\n if (create.secret !== undefined) lines.push('secret set (stored encrypted)');\n return lines;\n}\n"],"mappings":"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","names":["value","account"]}