@dmrlzz/davecode 0.5.1 → 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 (66) hide show
  1. package/dist/{ChatApp-YMHKIAAH.js → ChatApp-Z6PQIZ5J.js} +7 -6
  2. package/dist/{ChatApp-YMHKIAAH.js.map → ChatApp-Z6PQIZ5J.js.map} +1 -1
  3. package/dist/{account-5QFYCVYM.js → account-RTPS2V6O.js} +4 -3
  4. package/dist/{accounts-756BMMAL.js → accounts-IYQ4ZRL7.js} +6 -5
  5. package/dist/{budget-PGSNCVVK.js → budget-N2ZB66FF.js} +5 -4
  6. package/dist/{budget-PGSNCVVK.js.map → budget-N2ZB66FF.js.map} +1 -1
  7. package/dist/{chat-D3T4YG5D.js → chat-6TX6JX45.js} +9 -8
  8. package/dist/{chat-D3T4YG5D.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-6SHOBL2X.js → chunk-BJTXMET2.js} +2 -2
  12. package/dist/{chunk-JFWMLYV7.js → chunk-KUY3QHGS.js} +130 -89
  13. package/dist/chunk-KUY3QHGS.js.map +1 -0
  14. package/dist/{chunk-K5AA65RS.js → chunk-LEU46DGH.js} +2 -2
  15. package/dist/{chunk-HENE4DA6.js → chunk-QKY3OKVG.js} +71 -3
  16. package/dist/chunk-QKY3OKVG.js.map +1 -0
  17. package/dist/{chunk-6WUVR3R2.js → chunk-UEV5K3DH.js} +3 -3
  18. package/dist/{chunk-JSRPO2AR.js → chunk-UNK3EQD6.js} +4 -4
  19. package/dist/{chunk-IOATP7KH.js → chunk-WAARDGCZ.js} +5 -21
  20. package/dist/chunk-WAARDGCZ.js.map +1 -0
  21. package/dist/{chunk-ZNUNYYN6.js → chunk-YNAMNQLW.js} +3 -3
  22. package/dist/{config-TKGGYEN7.js → config-YQKY2AA4.js} +4 -3
  23. package/dist/{config-TKGGYEN7.js.map → config-YQKY2AA4.js.map} +1 -1
  24. package/dist/dashboard/assets/{Accounts-DciFUg4y.js → Accounts-DXiGsutB.js} +1 -1
  25. package/dist/dashboard/assets/{Callout-WgXHDPg0.js → Callout-1E8Wsl9W.js} +1 -1
  26. package/dist/dashboard/assets/{Goals-C6HL1PNE.js → Goals-kL4VAxw3.js} +1 -1
  27. package/dist/dashboard/assets/{Library-DwpBYTbK.js → Library-DZxBVUo_.js} +1 -1
  28. package/dist/dashboard/assets/{Panes-DxFSwhb7.js → Panes-C-TJekjs.js} +1 -1
  29. package/dist/dashboard/assets/{RoutesPage-Cyo0MNd7.js → RoutesPage-DWYm9tW8.js} +1 -1
  30. package/dist/dashboard/assets/{Runner-CIL7RxpN.js → Runner-CmHBjECR.js} +1 -1
  31. package/dist/dashboard/assets/{Settings-B_PEB585.js → Settings-BANphxva.js} +1 -1
  32. package/dist/dashboard/assets/{Tasks-DEfPSaE6.js → Tasks-cSx1PKyQ.js} +1 -1
  33. package/dist/dashboard/assets/{Traffic-Dcz-WhsP.js → Traffic-DEAuM6jq.js} +1 -1
  34. package/dist/dashboard/assets/{Workspace-9UCw9q7C.js → Workspace-BQFjc1jH.js} +1 -1
  35. package/dist/dashboard/assets/index-B8kld9xo.js +104 -0
  36. package/dist/dashboard/index.html +1 -1
  37. package/dist/{dist-F3NRJ5FK.js → dist-PIC255RX.js} +4 -2
  38. package/dist/{doctor-V4XXVVGK.js → doctor-PQC7JQPP.js} +4 -3
  39. package/dist/{doctor-V4XXVVGK.js.map → doctor-PQC7JQPP.js.map} +1 -1
  40. package/dist/{goal-RUHYPVPA.js → goal-STLEU7C7.js} +4 -3
  41. package/dist/{goal-RUHYPVPA.js.map → goal-STLEU7C7.js.map} +1 -1
  42. package/dist/index.js +31 -31
  43. package/dist/{init-54FKQZ2Z.js → init-NHU5LJSS.js} +4 -3
  44. package/dist/{init-54FKQZ2Z.js.map → init-NHU5LJSS.js.map} +1 -1
  45. package/dist/{run-4R25J2VN.js → run-7HWSHMRJ.js} +4 -3
  46. package/dist/{run-4R25J2VN.js.map → run-7HWSHMRJ.js.map} +1 -1
  47. package/dist/runtime.js +3 -2
  48. package/dist/{start-GRHW3TGE.js → start-WVAEAQWL.js} +4 -3
  49. package/dist/{start-GRHW3TGE.js.map → start-WVAEAQWL.js.map} +1 -1
  50. package/dist/{status-QR2HNPBK.js → status-ZRHPFLFT.js} +5 -4
  51. package/dist/{tasks-BHWDV4JS.js → tasks-JVWXUNXN.js} +5 -4
  52. package/dist/{tasks-BHWDV4JS.js.map → tasks-JVWXUNXN.js.map} +1 -1
  53. package/package.json +4 -4
  54. package/dist/chunk-HENE4DA6.js.map +0 -1
  55. package/dist/chunk-IOATP7KH.js.map +0 -1
  56. package/dist/chunk-JFWMLYV7.js.map +0 -1
  57. package/dist/dashboard/assets/index-CpztPbom.js +0 -104
  58. /package/dist/{account-5QFYCVYM.js.map → account-RTPS2V6O.js.map} +0 -0
  59. /package/dist/{accounts-756BMMAL.js.map → accounts-IYQ4ZRL7.js.map} +0 -0
  60. /package/dist/{chunk-6SHOBL2X.js.map → chunk-BJTXMET2.js.map} +0 -0
  61. /package/dist/{chunk-K5AA65RS.js.map → chunk-LEU46DGH.js.map} +0 -0
  62. /package/dist/{chunk-6WUVR3R2.js.map → chunk-UEV5K3DH.js.map} +0 -0
  63. /package/dist/{chunk-JSRPO2AR.js.map → chunk-UNK3EQD6.js.map} +0 -0
  64. /package/dist/{chunk-ZNUNYYN6.js.map → chunk-YNAMNQLW.js.map} +0 -0
  65. /package/dist/{dist-F3NRJ5FK.js.map → dist-PIC255RX.js.map} +0 -0
  66. /package/dist/{status-QR2HNPBK.js.map → status-ZRHPFLFT.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/init.ts","../src/lib/validate-detect.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { configSchema, ProjectBrain, projectPaths } from '@davecode/core';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { PromptCancelledError, type Prompter } from '../lib/prompter';\nimport {\n detectPackageManager,\n detectValidateCommands,\n readPackageJson,\n starterConfig,\n} from '../lib/validate-detect';\nimport { detectProjectRoot } from '../runtime';\n\nexport interface InitOptions {\n name?: string;\n /** `--config` writes the starter config without asking; `--no-config` skips it. */\n config?: boolean;\n}\n\nexport interface InitDeps {\n prompter?: Prompter;\n}\n\nconst LOCK_IGNORE = '.davecode/.lock';\n\n/** Make sure `.davecode/.lock` is git-ignored. Returns true when `.gitignore` changed. */\nexport function ensureLockIgnored(root: string): boolean {\n const path = join(root, '.gitignore');\n const current = existsSync(path) ? readFileSync(path, 'utf8') : '';\n const lines = current.split(/\\r?\\n/).map((l) => l.trim());\n if (lines.includes(LOCK_IGNORE) || lines.includes('.davecode/') || lines.includes('.davecode')) {\n return false;\n }\n const prefix = current === '' || current.endsWith('\\n') ? current : `${current}\\n`;\n writeFileSync(\n path,\n `${prefix}${current === '' ? '' : '\\n'}# DaveCode runtime lock\\n${LOCK_IGNORE}\\n`,\n );\n return true;\n}\n\nexport async function initCommand(\n ctx: CliContext,\n opts: InitOptions,\n deps: InitDeps = {},\n): Promise<number> {\n const root = (await detectProjectRoot(ctx.cwd, ctx.home)) ?? ctx.cwd;\n const paths = projectPaths(root);\n const pkg = readPackageJson(root);\n const name = opts.name?.trim() || pkg?.name || basename(root);\n\n const before = {\n state: existsSync(paths.state),\n architecture: existsSync(paths.architecture),\n taskGraph: existsSync(paths.taskGraph),\n };\n await ProjectBrain.init(root, { name });\n const created = Object.entries(before)\n .filter(([, existed]) => !existed)\n .map(([file]) => file);\n\n // Starter config with validation commands detected from package.json.\n const pm = detectPackageManager(root, pkg);\n const validate = detectValidateCommands(pkg, pm);\n let configWritten = false;\n let configSkipped: string | undefined;\n if (existsSync(paths.config)) {\n configSkipped = 'exists';\n } else if (opts.config === false) {\n configSkipped = 'declined';\n } else {\n let write = opts.config === true;\n if (!write && ctx.interactive) {\n const prompter =\n deps.prompter ??\n (await import('../tui/prompts')).createInkPrompter({\n stdout: ctx.io.stdout,\n stdin: ctx.io.stdin,\n theme: ctx.theme,\n });\n const summary = Object.entries(validate)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ');\n try {\n write = await prompter.confirm(\n summary\n ? `Write .davecode/config.json with runner.validate (${summary})?`\n : 'Write a starter .davecode/config.json (no lint/typecheck/test scripts found)?',\n true,\n );\n } catch (err) {\n if (!(err instanceof PromptCancelledError)) throw err;\n }\n }\n if (write) {\n const content = starterConfig(validate);\n const check = configSchema.safeParse(content);\n if (!check.success) throw new CliError('Generated config is invalid (please report a bug)');\n writeFileSync(paths.config, `${JSON.stringify(content, null, 2)}\\n`);\n configWritten = true;\n } else {\n configSkipped = ctx.interactive ? 'declined' : 'non-interactive';\n }\n }\n\n const ignoreUpdated = existsSync(join(root, '.git')) ? ensureLockIgnored(root) : false;\n\n if (ctx.json) {\n printJson(ctx, {\n root,\n name,\n created,\n config: configWritten ? paths.config : null,\n validate,\n gitignoreUpdated: ignoreUpdated,\n });\n return EXIT.ok;\n }\n\n const { theme } = ctx;\n const rel = (p: string) => relative(ctx.cwd, p) || '.';\n ctx.out(\n `${theme.ok(theme.glyph.ok)} Project brain ready for ${theme.bold(name)} ${theme.dim(rel(paths.dir))}`,\n );\n const files: Array<[string, string, boolean]> = [\n ['STATE.md', paths.state, before.state],\n ['ARCHITECTURE.md', paths.architecture, before.architecture],\n ['TASK_GRAPH.json', paths.taskGraph, before.taskGraph],\n ];\n for (const [label, , existed] of files) {\n ctx.out(` ${existed ? theme.dim('kept ') : theme.accent('created')} ${label}`);\n }\n if (configWritten) {\n ctx.out(` ${theme.accent('created')} config.json`);\n for (const [kind, command] of Object.entries(validate)) {\n ctx.out(theme.dim(` runner.validate.${kind} = ${command}`));\n }\n } else if (configSkipped === 'exists') {\n ctx.out(` ${theme.dim('kept ')} config.json`);\n } else if (configSkipped === 'non-interactive') {\n ctx.out(theme.dim(' config.json not written (pass --config to create a starter config)'));\n }\n if (ignoreUpdated)\n ctx.out(` ${theme.accent('updated')} .gitignore ${theme.dim(`(${LOCK_IGNORE})`)}`);\n\n ctx.out();\n ctx.out(theme.dim('Next:'));\n ctx.out(` ${theme.accent('davecode tasks add setup \"Describe the first task\"')}`);\n ctx.out(` ${theme.accent('davecode start')}`);\n return EXIT.ok;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';\n\nexport interface PackageJson {\n name?: string;\n packageManager?: string;\n scripts?: Record<string, string>;\n}\n\nexport function readPackageJson(root: string): PackageJson | undefined {\n try {\n const value: unknown = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));\n return value && typeof value === 'object' ? (value as PackageJson) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** From `packageManager` in package.json, then lockfiles; npm otherwise. */\nexport function detectPackageManager(root: string, pkg?: PackageJson): PackageManager {\n const declared = pkg?.packageManager?.split('@')[0];\n if (declared === 'pnpm' || declared === 'yarn' || declared === 'bun' || declared === 'npm') {\n return declared;\n }\n if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(root, 'yarn.lock'))) return 'yarn';\n if (existsSync(join(root, 'bun.lock')) || existsSync(join(root, 'bun.lockb'))) return 'bun';\n return 'npm';\n}\n\nconst CANDIDATES = {\n lint: ['lint', 'lint:check', 'check:lint'],\n typecheck: ['typecheck', 'type-check', 'check-types', 'check:types', 'types', 'tsc'],\n test: ['test', 'test:unit', 'test:ci'],\n} as const;\n\n/** npm's placeholder `test` script, which always fails. */\nconst NPM_PLACEHOLDER = /no test specified/i;\n\nexport function runScript(pm: PackageManager, script: string): string {\n if (script === 'test') return `${pm} test`;\n switch (pm) {\n case 'npm':\n return `npm run ${script}`;\n case 'bun':\n return `bun run ${script}`;\n default:\n return `${pm} ${script}`;\n }\n}\n\nexport interface ValidateCommands {\n lint?: string;\n typecheck?: string;\n test?: string;\n}\n\n/** `runner.validate` commands for the lint/typecheck/test scripts a package.json defines. */\nexport function detectValidateCommands(\n pkg: PackageJson | undefined,\n pm: PackageManager,\n): ValidateCommands {\n const scripts = pkg?.scripts ?? {};\n const found: ValidateCommands = {};\n for (const [kind, names] of Object.entries(CANDIDATES) as Array<\n [keyof ValidateCommands, readonly string[]]\n >) {\n const script = names.find((name) => {\n const body = scripts[name];\n return typeof body === 'string' && body.trim() !== '' && !NPM_PLACEHOLDER.test(body);\n });\n if (script) found[kind] = runScript(pm, script);\n }\n return found;\n}\n\n/** Starter `.davecode/config.json` content. */\nexport function starterConfig(validate: ValidateCommands): Record<string, unknown> {\n return { runner: { validate, judge: { kind: 'none' } } };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","join","existsSync","readFileSync"]}
1
+ {"version":3,"sources":["../src/commands/init.ts","../src/lib/validate-detect.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync } from 'node:fs';\nimport { basename, join, relative } from 'node:path';\nimport { configSchema, ProjectBrain, projectPaths } from '@davecode/core';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { PromptCancelledError, type Prompter } from '../lib/prompter';\nimport {\n detectPackageManager,\n detectValidateCommands,\n readPackageJson,\n starterConfig,\n} from '../lib/validate-detect';\nimport { detectProjectRoot } from '../runtime';\n\nexport interface InitOptions {\n name?: string;\n /** `--config` writes the starter config without asking; `--no-config` skips it. */\n config?: boolean;\n}\n\nexport interface InitDeps {\n prompter?: Prompter;\n}\n\nconst LOCK_IGNORE = '.davecode/.lock';\n\n/** Make sure `.davecode/.lock` is git-ignored. Returns true when `.gitignore` changed. */\nexport function ensureLockIgnored(root: string): boolean {\n const path = join(root, '.gitignore');\n const current = existsSync(path) ? readFileSync(path, 'utf8') : '';\n const lines = current.split(/\\r?\\n/).map((l) => l.trim());\n if (lines.includes(LOCK_IGNORE) || lines.includes('.davecode/') || lines.includes('.davecode')) {\n return false;\n }\n const prefix = current === '' || current.endsWith('\\n') ? current : `${current}\\n`;\n writeFileSync(\n path,\n `${prefix}${current === '' ? '' : '\\n'}# DaveCode runtime lock\\n${LOCK_IGNORE}\\n`,\n );\n return true;\n}\n\nexport async function initCommand(\n ctx: CliContext,\n opts: InitOptions,\n deps: InitDeps = {},\n): Promise<number> {\n const root = (await detectProjectRoot(ctx.cwd, ctx.home)) ?? ctx.cwd;\n const paths = projectPaths(root);\n const pkg = readPackageJson(root);\n const name = opts.name?.trim() || pkg?.name || basename(root);\n\n const before = {\n state: existsSync(paths.state),\n architecture: existsSync(paths.architecture),\n taskGraph: existsSync(paths.taskGraph),\n };\n await ProjectBrain.init(root, { name });\n const created = Object.entries(before)\n .filter(([, existed]) => !existed)\n .map(([file]) => file);\n\n // Starter config with validation commands detected from package.json.\n const pm = detectPackageManager(root, pkg);\n const validate = detectValidateCommands(pkg, pm);\n let configWritten = false;\n let configSkipped: string | undefined;\n if (existsSync(paths.config)) {\n configSkipped = 'exists';\n } else if (opts.config === false) {\n configSkipped = 'declined';\n } else {\n let write = opts.config === true;\n if (!write && ctx.interactive) {\n const prompter =\n deps.prompter ??\n (await import('../tui/prompts')).createInkPrompter({\n stdout: ctx.io.stdout,\n stdin: ctx.io.stdin,\n theme: ctx.theme,\n });\n const summary = Object.entries(validate)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ');\n try {\n write = await prompter.confirm(\n summary\n ? `Write .davecode/config.json with runner.validate (${summary})?`\n : 'Write a starter .davecode/config.json (no lint/typecheck/test scripts found)?',\n true,\n );\n } catch (err) {\n if (!(err instanceof PromptCancelledError)) throw err;\n }\n }\n if (write) {\n const content = starterConfig(validate);\n const check = configSchema.safeParse(content);\n if (!check.success) throw new CliError('Generated config is invalid (please report a bug)');\n writeFileSync(paths.config, `${JSON.stringify(content, null, 2)}\\n`);\n configWritten = true;\n } else {\n configSkipped = ctx.interactive ? 'declined' : 'non-interactive';\n }\n }\n\n const ignoreUpdated = existsSync(join(root, '.git')) ? ensureLockIgnored(root) : false;\n\n if (ctx.json) {\n printJson(ctx, {\n root,\n name,\n created,\n config: configWritten ? paths.config : null,\n validate,\n gitignoreUpdated: ignoreUpdated,\n });\n return EXIT.ok;\n }\n\n const { theme } = ctx;\n const rel = (p: string) => relative(ctx.cwd, p) || '.';\n ctx.out(\n `${theme.ok(theme.glyph.ok)} Project brain ready for ${theme.bold(name)} ${theme.dim(rel(paths.dir))}`,\n );\n const files: Array<[string, string, boolean]> = [\n ['STATE.md', paths.state, before.state],\n ['ARCHITECTURE.md', paths.architecture, before.architecture],\n ['TASK_GRAPH.json', paths.taskGraph, before.taskGraph],\n ];\n for (const [label, , existed] of files) {\n ctx.out(` ${existed ? theme.dim('kept ') : theme.accent('created')} ${label}`);\n }\n if (configWritten) {\n ctx.out(` ${theme.accent('created')} config.json`);\n for (const [kind, command] of Object.entries(validate)) {\n ctx.out(theme.dim(` runner.validate.${kind} = ${command}`));\n }\n } else if (configSkipped === 'exists') {\n ctx.out(` ${theme.dim('kept ')} config.json`);\n } else if (configSkipped === 'non-interactive') {\n ctx.out(theme.dim(' config.json not written (pass --config to create a starter config)'));\n }\n if (ignoreUpdated)\n ctx.out(` ${theme.accent('updated')} .gitignore ${theme.dim(`(${LOCK_IGNORE})`)}`);\n\n ctx.out();\n ctx.out(theme.dim('Next:'));\n ctx.out(` ${theme.accent('davecode tasks add setup \"Describe the first task\"')}`);\n ctx.out(` ${theme.accent('davecode start')}`);\n return EXIT.ok;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nexport type PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';\n\nexport interface PackageJson {\n name?: string;\n packageManager?: string;\n scripts?: Record<string, string>;\n}\n\nexport function readPackageJson(root: string): PackageJson | undefined {\n try {\n const value: unknown = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));\n return value && typeof value === 'object' ? (value as PackageJson) : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** From `packageManager` in package.json, then lockfiles; npm otherwise. */\nexport function detectPackageManager(root: string, pkg?: PackageJson): PackageManager {\n const declared = pkg?.packageManager?.split('@')[0];\n if (declared === 'pnpm' || declared === 'yarn' || declared === 'bun' || declared === 'npm') {\n return declared;\n }\n if (existsSync(join(root, 'pnpm-lock.yaml'))) return 'pnpm';\n if (existsSync(join(root, 'yarn.lock'))) return 'yarn';\n if (existsSync(join(root, 'bun.lock')) || existsSync(join(root, 'bun.lockb'))) return 'bun';\n return 'npm';\n}\n\nconst CANDIDATES = {\n lint: ['lint', 'lint:check', 'check:lint'],\n typecheck: ['typecheck', 'type-check', 'check-types', 'check:types', 'types', 'tsc'],\n test: ['test', 'test:unit', 'test:ci'],\n} as const;\n\n/** npm's placeholder `test` script, which always fails. */\nconst NPM_PLACEHOLDER = /no test specified/i;\n\nexport function runScript(pm: PackageManager, script: string): string {\n if (script === 'test') return `${pm} test`;\n switch (pm) {\n case 'npm':\n return `npm run ${script}`;\n case 'bun':\n return `bun run ${script}`;\n default:\n return `${pm} ${script}`;\n }\n}\n\nexport interface ValidateCommands {\n lint?: string;\n typecheck?: string;\n test?: string;\n}\n\n/** `runner.validate` commands for the lint/typecheck/test scripts a package.json defines. */\nexport function detectValidateCommands(\n pkg: PackageJson | undefined,\n pm: PackageManager,\n): ValidateCommands {\n const scripts = pkg?.scripts ?? {};\n const found: ValidateCommands = {};\n for (const [kind, names] of Object.entries(CANDIDATES) as Array<\n [keyof ValidateCommands, readonly string[]]\n >) {\n const script = names.find((name) => {\n const body = scripts[name];\n return typeof body === 'string' && body.trim() !== '' && !NPM_PLACEHOLDER.test(body);\n });\n if (script) found[kind] = runScript(pm, script);\n }\n return found;\n}\n\n/** Starter `.davecode/config.json` content. */\nexport function starterConfig(validate: ValidateCommands): Record<string, unknown> {\n return { runner: { validate, judge: { kind: 'none' } } };\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","join","existsSync","readFileSync"]}
@@ -18,17 +18,18 @@ import {
18
18
  detectProjectRoot,
19
19
  findGateway,
20
20
  wireProject
21
- } from "./chunk-JFWMLYV7.js";
21
+ } from "./chunk-KUY3QHGS.js";
22
22
  import {
23
23
  CliError,
24
24
  EXIT
25
25
  } from "./chunk-7XVXEO7U.js";
26
+ import "./chunk-732GIHRQ.js";
26
27
  import {
27
28
  ProjectBrain,
28
29
  RunnerError,
29
30
  createEngine,
30
31
  loadConfig
31
- } from "./chunk-HENE4DA6.js";
32
+ } from "./chunk-QKY3OKVG.js";
32
33
  import "./chunk-MC7RIPL7.js";
33
34
 
34
35
  // src/commands/run.ts
@@ -373,4 +374,4 @@ export {
373
374
  explainRunnerError,
374
375
  runCommand
375
376
  };
376
- //# sourceMappingURL=run-4R25J2VN.js.map
377
+ //# sourceMappingURL=run-7HWSHMRJ.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { basename, resolve } from 'node:path';\nimport {\n type AutonomousRunner,\n createEngine,\n type DaveConfig,\n type DaveEvent,\n type Engine,\n loadConfig,\n ProjectBrain,\n RunnerError,\n type RunnerErrorCode,\n type RunnerStatus,\n type RunOnceResult,\n type TaskGraph,\n type TaskNode,\n} from '@davecode/core';\nimport { findGateway, type GatewayClient, GatewayError } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { detectProjectRoot, wireProject } from '../runtime';\nimport { logText } from '../tui/RunnerView';\nimport { initialRunnerState, isTerminal } from '../tui/runner-state';\nimport { formatDuration } from '../ui/format';\n\nexport interface RunOptions {\n once?: boolean;\n task?: string;\n project?: string;\n}\n\n/** Test seams: an injected runner/engine instead of building them from the project. */\nexport interface RunDeps {\n wire?: (\n engine: Engine,\n root: string,\n ) => {\n runner: Pick<\n AutonomousRunner,\n 'runOnce' | 'start' | 'stop' | 'pause' | 'resume' | 'status' | 'running'\n >;\n };\n engine?: Engine;\n /** Resolves when the user asks to stop (default: SIGINT/SIGTERM). */\n interrupt?: () => Promise<void>;\n /** Skip the running-gateway probe. */\n noGateway?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Friendly errors\n// ---------------------------------------------------------------------------\n\nconst HINTS: Record<RunnerErrorCode, (config: DaveConfig) => { message?: string; hint: string }> = {\n not_a_repo: () => ({\n message: 'This project is not inside a git repository',\n hint: 'The runner works on task branches: run `git init` and make a first commit.',\n }),\n no_brain: () => ({\n message: 'No project brain here',\n hint: 'Run `davecode init`, then add tasks with `davecode tasks add`.',\n }),\n no_base_branch: (config) => ({\n message: `The base branch \"${config.runner.baseBranch}\" does not exist`,\n hint: 'Create it, or set runner.baseBranch in .davecode/config.json.',\n }),\n dirty_worktree: () => ({\n hint: 'Commit or stash your changes, then run again (the runner never works on top of uncommitted edits).',\n }),\n invalid_graph: () => ({\n hint: 'Fix .davecode/TASK_GRAPH.json; `davecode tasks` shows the problem.',\n }),\n task_not_found: () => ({\n hint: 'See `davecode tasks` for the task ids.',\n }),\n task_not_runnable: () => ({\n hint: 'Only PENDING tasks can run: reopen it with `davecode tasks status <id> PENDING`.',\n }),\n task_blocked: () => ({\n hint: 'Run its dependencies first (`davecode tasks` shows what each task waits on).',\n }),\n busy: () => ({\n hint: 'Stop the runner or the running goal (dashboard, `davecode goals cancel <id>` or the other `davecode run`) first.',\n }),\n};\n\nconst CODE_PATTERNS: Array<[RunnerErrorCode, RegExp]> = [\n ['not_a_repo', /not inside a git repository/i],\n ['no_brain', /no project brain/i],\n ['no_base_branch', /base branch .* does not exist/i],\n ['dirty_worktree', /uncommitted changes/i],\n ['busy', /already running|working tree is busy/i],\n ['invalid_graph', /task graph/i],\n];\n\n/** Turn a `RunnerError` (or the gateway's 409 for one) into a CLI error with a fix. */\nexport function explainRunnerError(err: unknown, config: DaveConfig): unknown {\n const message = err instanceof Error ? err.message : String(err);\n let code: RunnerErrorCode | undefined;\n if (err instanceof RunnerError) code = err.code;\n else if (err instanceof GatewayError && err.status === 409) {\n // The gateway forwards RunnerError codes; fall back to message matching for older gateways.\n code =\n err.code in HINTS\n ? (err.code as RunnerErrorCode)\n : CODE_PATTERNS.find(([, re]) => re.test(message))?.[0];\n }\n if (!code) return err;\n const friendly = HINTS[code](config);\n return new CliError(friendly.message ?? message, { hint: friendly.hint });\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ninterface Waiter {\n promise: Promise<void>;\n dispose(): void;\n}\n\n/** Resolves on SIGINT/SIGTERM; `dispose()` removes the listeners again. */\nfunction signalWaiter(): Waiter {\n let dispose = () => {};\n const promise = new Promise<void>((resolveSignal) => {\n const done = () => {\n dispose();\n resolveSignal();\n };\n dispose = () => {\n process.off('SIGINT', done);\n process.off('SIGTERM', done);\n };\n process.on('SIGINT', done);\n process.on('SIGTERM', done);\n });\n return { promise, dispose };\n}\n\nfunction interruptFor(deps: RunDeps): Waiter {\n return deps.interrupt ? { promise: deps.interrupt(), dispose: () => {} } : signalWaiter();\n}\n\nexport function describeResult(ctx: CliContext, result: RunOnceResult): string[] {\n const { theme } = ctx;\n const task = result.task ? `${theme.bold(result.task.id)} ${result.task.title}` : '';\n const lines: string[] = [];\n switch (result.outcome) {\n case 'success':\n lines.push(`${theme.ok(theme.glyph.ok)} ${task} ${theme.ok('succeeded')}`);\n if (result.delivery?.mode === 'pr' && result.delivery.url) {\n lines.push(` pull request ${theme.accent(result.delivery.url)}`);\n } else if (result.delivery) lines.push(theme.dim(' merged into the base branch'));\n break;\n case 'failed':\n lines.push(`${theme.error(theme.glyph.fail)} ${task} ${theme.error('failed')}`);\n if (result.branch) lines.push(theme.dim(` work kept on ${result.branch}`));\n break;\n case 'idle':\n lines.push(theme.dim('Nothing to do: no task is ready (see `davecode tasks`).'));\n break;\n case 'stopped':\n lines.push(theme.warn(`${theme.glyph.warn} Stopped; the task is back to PENDING.`));\n if (result.branch) lines.push(theme.dim(` partial work kept on ${result.branch}`));\n break;\n default:\n lines.push(\n `${theme.error(theme.glyph.fail)} Runner error: ${result.error ?? 'unknown error'}`,\n );\n }\n if (result.outcome === 'success' || result.outcome === 'failed') {\n lines.push(theme.dim(` repair cycles ${result.repairCycles}`));\n if (result.validation && !result.validation.ok) {\n const failing = result.validation.steps.filter((s) => !s.ok).map((s) => s.name);\n if (failing.length > 0) lines.push(theme.dim(` failing checks: ${failing.join(', ')}`));\n }\n if (result.verdict) {\n lines.push(\n theme.dim(\n ` judge ${result.verdict.pass ? 'passed' : 'rejected'}${result.verdict.confidence !== undefined ? ` (confidence ${result.verdict.confidence.toFixed(2)})` : ''}`,\n ),\n );\n }\n if (result.summary) lines.push('', result.summary.trim());\n }\n return lines;\n}\n\nexport function exitCodeFor(result: RunOnceResult): number {\n if (result.outcome === 'success' || result.outcome === 'idle') return EXIT.ok;\n if (result.outcome === 'stopped') return 130;\n return EXIT.failure;\n}\n\nfunction printEvent(ctx: CliContext, event: DaveEvent, toStderr: boolean): void {\n const write = toStderr ? ctx.err : ctx.out;\n const theme = toStderr ? ctx.errTheme : ctx.theme;\n if (event.type === 'runner.log' && event.level !== 'debug') {\n write(\n logText(theme, { ts: event.ts, level: event.level, message: event.message }, ctx.columns),\n );\n } else if (event.type === 'runner.status') {\n const s = event.status;\n write(\n theme.dim(\n `${new Date(event.ts).toTimeString().slice(0, 8)} ${theme.glyph.arrow} ${s.state}${s.taskId ? ` · ${s.taskId}` : ''}${s.repairCycle ? ` · repair ${s.repairCycle}` : ''}`,\n ),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command\n// ---------------------------------------------------------------------------\n\nexport async function runCommand(\n ctx: CliContext,\n opts: RunOptions,\n deps: RunDeps = {},\n): Promise<number> {\n const root = opts.project\n ? resolve(ctx.cwd, opts.project)\n : await detectProjectRoot(ctx.cwd, ctx.home);\n if (!root || !existsSync(root)) {\n throw new CliError('Not inside a project', {\n hint: 'Run `davecode run` inside a git repository with a project brain (`davecode init`).',\n });\n }\n const config =\n deps.engine?.config ?? loadConfig({ home: ctx.home, env: ctx.env, projectRoot: root });\n\n // A gateway (davecode start) may already own a runner for this repository.\n const gateway = deps.noGateway ? undefined : await findGateway(config).catch(() => undefined);\n if (gateway) {\n const status = await gateway.client\n .get<{ status: RunnerStatus }>('/api/runner')\n .then((r) => r.status)\n .catch(() => undefined);\n if (status && !['idle', 'stopped', 'error'].includes(status.state)) {\n throw new CliError(`The gateway's runner is already ${status.state}`, {\n hint: `Watch it in the dashboard at ${gateway.client.baseUrl}/ or stop it there first.`,\n });\n }\n if (!opts.once) return driveGateway(ctx, gateway.client, config, root, opts.task);\n }\n\n const engine = deps.engine ?? createEngine({ home: ctx.home, env: ctx.env, projectRoot: root });\n try {\n const { runner } = (deps.wire ?? ((e, r) => wireProject(e, r, { env: ctx.env })))(engine, root);\n const graph = await new ProjectBrain(root)\n .readGraph()\n .catch(() => ({ version: 1 as const, tasks: [] }));\n return opts.once\n ? await runOnce(ctx, engine, runner, config, deps, opts.task)\n : await runContinuous(\n ctx,\n engine,\n runner,\n config,\n basename(root),\n graph.tasks,\n deps,\n opts.task,\n );\n } finally {\n if (!deps.engine) engine.close();\n }\n}\n\ntype RunnerLike = ReturnType<NonNullable<RunDeps['wire']>>['runner'];\n\nasync function runOnce(\n ctx: CliContext,\n engine: Engine,\n runner: RunnerLike,\n config: DaveConfig,\n deps: RunDeps,\n taskId?: string,\n): Promise<number> {\n const unsubscribe = engine.events.subscribe((event) => printEvent(ctx, event, ctx.json));\n let interrupted = false;\n const interrupt = interruptFor(deps);\n void interrupt.promise.then(() => {\n interrupted = true;\n if (!ctx.json) ctx.err(ctx.errTheme.dim('Stopping safely…'));\n void runner.stop();\n });\n const started = Date.now();\n let result: RunOnceResult;\n try {\n result = await runner.runOnce(taskId === undefined ? {} : { taskId });\n } catch (err) {\n throw explainRunnerError(err, config);\n } finally {\n unsubscribe();\n interrupt.dispose();\n }\n if (ctx.json) {\n printJson(ctx, { ...result, interrupted });\n } else {\n ctx.out();\n for (const line of describeResult(ctx, result)) ctx.out(line);\n ctx.out(ctx.theme.dim(` took ${formatDuration((Date.now() - started) / 1000)}`));\n }\n return exitCodeFor(result);\n}\n\nasync function runContinuous(\n ctx: CliContext,\n engine: Engine,\n runner: RunnerLike,\n config: DaveConfig,\n projectName: string,\n tasks: TaskNode[],\n deps: RunDeps,\n taskId?: string,\n): Promise<number> {\n // Buffer events emitted before the view mounts so the first log lines are not lost.\n const early: DaveEvent[] = [];\n const unsubscribeEarly = engine.events.subscribe((e) => early.push(e));\n try {\n await runner.start(taskId === undefined ? {} : { taskId });\n } catch (err) {\n unsubscribeEarly();\n throw explainRunnerError(err, config);\n }\n\n if (!ctx.interactive) {\n unsubscribeEarly();\n for (const event of early) printEvent(ctx, event, false);\n const unsubscribe = engine.events.subscribe((event) => printEvent(ctx, event, false));\n const finished = new Promise<void>((resolveDone) => {\n const timer = setInterval(() => {\n if (!runner.running) {\n clearInterval(timer);\n resolveDone();\n }\n }, 250);\n });\n const interrupt = interruptFor(deps);\n await Promise.race([interrupt.promise, finished]);\n interrupt.dispose();\n if (runner.running) {\n ctx.out(ctx.theme.dim('Stopping safely…'));\n await runner.stop();\n }\n unsubscribe();\n } else {\n const [{ render }, { createElement }, { RunnerApp }] = await Promise.all([\n import('ink'),\n import('react'),\n import('../tui/RunnerView'),\n ]);\n let initial = initialRunnerState(runner.status(), tasks);\n const { runnerReducer } = await import('../tui/runner-state');\n for (const event of early) initial = runnerReducer(initial, event);\n unsubscribeEarly();\n const instance = render(\n createElement(RunnerApp, {\n theme: ctx.theme,\n initial,\n subscribe: (onEvent: (e: DaveEvent) => void) => engine.events.subscribe(onEvent),\n maxRepairCycles: config.runner.maxRepairCycles,\n projectName,\n stop: () => runner.stop(),\n pause: () => runner.pause(),\n resume: () => runner.resume(),\n }),\n { stdout: ctx.io.stdout as NodeJS.WriteStream, exitOnCtrlC: false },\n );\n await instance.waitUntilExit();\n if (runner.running) await runner.stop();\n }\n const final = runner.status();\n if (final.state === 'error') {\n ctx.err(ctx.errTheme.error(`Runner error: ${final.lastError ?? 'unknown error'}`));\n return EXIT.failure;\n }\n return EXIT.ok;\n}\n\n/** Continuous mode against the runner of a running gateway, fed by `/api/events`. */\nasync function driveGateway(\n ctx: CliContext,\n client: GatewayClient,\n config: DaveConfig,\n root: string,\n taskId?: string,\n): Promise<number> {\n try {\n await client.post('/api/runner/start', taskId === undefined ? undefined : { taskId });\n } catch (err) {\n if (err instanceof GatewayError && err.status === 501) {\n throw new CliError('The running gateway has no project brain to work on', {\n hint: 'Restart `davecode start` inside this repository, or stop it so `davecode run` can work in-process.',\n });\n }\n throw explainRunnerError(err, config);\n }\n const stop = async () => {\n await client.post('/api/runner/stop', undefined, { timeoutMs: 10 * 60_000 });\n };\n const controller = new AbortController();\n const listeners = new Set<(e: DaveEvent) => void>();\n let latest: RunnerStatus = { state: 'selecting' };\n const pump = (async () => {\n try {\n for await (const event of client.events(controller.signal)) {\n if (event.type === 'runner.status') latest = event.status;\n for (const listener of listeners) listener(event);\n }\n } catch {\n // aborted or disconnected\n }\n })();\n\n try {\n if (!ctx.interactive) {\n const print = (e: DaveEvent) => printEvent(ctx, e, false);\n listeners.add(print);\n await signalWaiter().promise;\n ctx.out(ctx.theme.dim('Stopping safely…'));\n await stop();\n } else {\n const [{ render }, { createElement }, { RunnerApp }, { tasks }] = await Promise.all([\n import('ink'),\n import('react'),\n import('../tui/RunnerView'),\n client\n .get<{ graph: TaskGraph }>('/api/tasks')\n .then((r) => ({ tasks: r.graph.tasks }))\n .catch(() => ({ tasks: [] as TaskNode[] })),\n ]);\n const status = await client\n .get<{ status: RunnerStatus }>('/api/runner')\n .then((r) => r.status)\n .catch(() => latest);\n const instance = render(\n createElement(RunnerApp, {\n theme: ctx.theme,\n initial: initialRunnerState(status, tasks),\n subscribe: (onEvent: (e: DaveEvent) => void) => {\n listeners.add(onEvent);\n return () => listeners.delete(onEvent);\n },\n maxRepairCycles: config.runner.maxRepairCycles,\n projectName: basename(root),\n stop,\n pause: async () => {\n await client.post('/api/runner/pause');\n },\n resume: async () => {\n await client.post('/api/runner/start');\n },\n }),\n { stdout: ctx.io.stdout as NodeJS.WriteStream, exitOnCtrlC: false },\n );\n await instance.waitUntilExit();\n if (!isTerminal(latest.state)) await stop().catch(() => undefined);\n }\n } finally {\n controller.abort();\n await pump;\n }\n return latest.state === 'error' ? EXIT.failure : EXIT.ok;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { basename, resolve } from 'node:path';\nimport {\n type AutonomousRunner,\n createEngine,\n type DaveConfig,\n type DaveEvent,\n type Engine,\n loadConfig,\n ProjectBrain,\n RunnerError,\n type RunnerErrorCode,\n type RunnerStatus,\n type RunOnceResult,\n type TaskGraph,\n type TaskNode,\n} from '@davecode/core';\nimport { findGateway, type GatewayClient, GatewayError } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { detectProjectRoot, wireProject } from '../runtime';\nimport { logText } from '../tui/RunnerView';\nimport { initialRunnerState, isTerminal } from '../tui/runner-state';\nimport { formatDuration } from '../ui/format';\n\nexport interface RunOptions {\n once?: boolean;\n task?: string;\n project?: string;\n}\n\n/** Test seams: an injected runner/engine instead of building them from the project. */\nexport interface RunDeps {\n wire?: (\n engine: Engine,\n root: string,\n ) => {\n runner: Pick<\n AutonomousRunner,\n 'runOnce' | 'start' | 'stop' | 'pause' | 'resume' | 'status' | 'running'\n >;\n };\n engine?: Engine;\n /** Resolves when the user asks to stop (default: SIGINT/SIGTERM). */\n interrupt?: () => Promise<void>;\n /** Skip the running-gateway probe. */\n noGateway?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Friendly errors\n// ---------------------------------------------------------------------------\n\nconst HINTS: Record<RunnerErrorCode, (config: DaveConfig) => { message?: string; hint: string }> = {\n not_a_repo: () => ({\n message: 'This project is not inside a git repository',\n hint: 'The runner works on task branches: run `git init` and make a first commit.',\n }),\n no_brain: () => ({\n message: 'No project brain here',\n hint: 'Run `davecode init`, then add tasks with `davecode tasks add`.',\n }),\n no_base_branch: (config) => ({\n message: `The base branch \"${config.runner.baseBranch}\" does not exist`,\n hint: 'Create it, or set runner.baseBranch in .davecode/config.json.',\n }),\n dirty_worktree: () => ({\n hint: 'Commit or stash your changes, then run again (the runner never works on top of uncommitted edits).',\n }),\n invalid_graph: () => ({\n hint: 'Fix .davecode/TASK_GRAPH.json; `davecode tasks` shows the problem.',\n }),\n task_not_found: () => ({\n hint: 'See `davecode tasks` for the task ids.',\n }),\n task_not_runnable: () => ({\n hint: 'Only PENDING tasks can run: reopen it with `davecode tasks status <id> PENDING`.',\n }),\n task_blocked: () => ({\n hint: 'Run its dependencies first (`davecode tasks` shows what each task waits on).',\n }),\n busy: () => ({\n hint: 'Stop the runner or the running goal (dashboard, `davecode goals cancel <id>` or the other `davecode run`) first.',\n }),\n};\n\nconst CODE_PATTERNS: Array<[RunnerErrorCode, RegExp]> = [\n ['not_a_repo', /not inside a git repository/i],\n ['no_brain', /no project brain/i],\n ['no_base_branch', /base branch .* does not exist/i],\n ['dirty_worktree', /uncommitted changes/i],\n ['busy', /already running|working tree is busy/i],\n ['invalid_graph', /task graph/i],\n];\n\n/** Turn a `RunnerError` (or the gateway's 409 for one) into a CLI error with a fix. */\nexport function explainRunnerError(err: unknown, config: DaveConfig): unknown {\n const message = err instanceof Error ? err.message : String(err);\n let code: RunnerErrorCode | undefined;\n if (err instanceof RunnerError) code = err.code;\n else if (err instanceof GatewayError && err.status === 409) {\n // The gateway forwards RunnerError codes; fall back to message matching for older gateways.\n code =\n err.code in HINTS\n ? (err.code as RunnerErrorCode)\n : CODE_PATTERNS.find(([, re]) => re.test(message))?.[0];\n }\n if (!code) return err;\n const friendly = HINTS[code](config);\n return new CliError(friendly.message ?? message, { hint: friendly.hint });\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\ninterface Waiter {\n promise: Promise<void>;\n dispose(): void;\n}\n\n/** Resolves on SIGINT/SIGTERM; `dispose()` removes the listeners again. */\nfunction signalWaiter(): Waiter {\n let dispose = () => {};\n const promise = new Promise<void>((resolveSignal) => {\n const done = () => {\n dispose();\n resolveSignal();\n };\n dispose = () => {\n process.off('SIGINT', done);\n process.off('SIGTERM', done);\n };\n process.on('SIGINT', done);\n process.on('SIGTERM', done);\n });\n return { promise, dispose };\n}\n\nfunction interruptFor(deps: RunDeps): Waiter {\n return deps.interrupt ? { promise: deps.interrupt(), dispose: () => {} } : signalWaiter();\n}\n\nexport function describeResult(ctx: CliContext, result: RunOnceResult): string[] {\n const { theme } = ctx;\n const task = result.task ? `${theme.bold(result.task.id)} ${result.task.title}` : '';\n const lines: string[] = [];\n switch (result.outcome) {\n case 'success':\n lines.push(`${theme.ok(theme.glyph.ok)} ${task} ${theme.ok('succeeded')}`);\n if (result.delivery?.mode === 'pr' && result.delivery.url) {\n lines.push(` pull request ${theme.accent(result.delivery.url)}`);\n } else if (result.delivery) lines.push(theme.dim(' merged into the base branch'));\n break;\n case 'failed':\n lines.push(`${theme.error(theme.glyph.fail)} ${task} ${theme.error('failed')}`);\n if (result.branch) lines.push(theme.dim(` work kept on ${result.branch}`));\n break;\n case 'idle':\n lines.push(theme.dim('Nothing to do: no task is ready (see `davecode tasks`).'));\n break;\n case 'stopped':\n lines.push(theme.warn(`${theme.glyph.warn} Stopped; the task is back to PENDING.`));\n if (result.branch) lines.push(theme.dim(` partial work kept on ${result.branch}`));\n break;\n default:\n lines.push(\n `${theme.error(theme.glyph.fail)} Runner error: ${result.error ?? 'unknown error'}`,\n );\n }\n if (result.outcome === 'success' || result.outcome === 'failed') {\n lines.push(theme.dim(` repair cycles ${result.repairCycles}`));\n if (result.validation && !result.validation.ok) {\n const failing = result.validation.steps.filter((s) => !s.ok).map((s) => s.name);\n if (failing.length > 0) lines.push(theme.dim(` failing checks: ${failing.join(', ')}`));\n }\n if (result.verdict) {\n lines.push(\n theme.dim(\n ` judge ${result.verdict.pass ? 'passed' : 'rejected'}${result.verdict.confidence !== undefined ? ` (confidence ${result.verdict.confidence.toFixed(2)})` : ''}`,\n ),\n );\n }\n if (result.summary) lines.push('', result.summary.trim());\n }\n return lines;\n}\n\nexport function exitCodeFor(result: RunOnceResult): number {\n if (result.outcome === 'success' || result.outcome === 'idle') return EXIT.ok;\n if (result.outcome === 'stopped') return 130;\n return EXIT.failure;\n}\n\nfunction printEvent(ctx: CliContext, event: DaveEvent, toStderr: boolean): void {\n const write = toStderr ? ctx.err : ctx.out;\n const theme = toStderr ? ctx.errTheme : ctx.theme;\n if (event.type === 'runner.log' && event.level !== 'debug') {\n write(\n logText(theme, { ts: event.ts, level: event.level, message: event.message }, ctx.columns),\n );\n } else if (event.type === 'runner.status') {\n const s = event.status;\n write(\n theme.dim(\n `${new Date(event.ts).toTimeString().slice(0, 8)} ${theme.glyph.arrow} ${s.state}${s.taskId ? ` · ${s.taskId}` : ''}${s.repairCycle ? ` · repair ${s.repairCycle}` : ''}`,\n ),\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Command\n// ---------------------------------------------------------------------------\n\nexport async function runCommand(\n ctx: CliContext,\n opts: RunOptions,\n deps: RunDeps = {},\n): Promise<number> {\n const root = opts.project\n ? resolve(ctx.cwd, opts.project)\n : await detectProjectRoot(ctx.cwd, ctx.home);\n if (!root || !existsSync(root)) {\n throw new CliError('Not inside a project', {\n hint: 'Run `davecode run` inside a git repository with a project brain (`davecode init`).',\n });\n }\n const config =\n deps.engine?.config ?? loadConfig({ home: ctx.home, env: ctx.env, projectRoot: root });\n\n // A gateway (davecode start) may already own a runner for this repository.\n const gateway = deps.noGateway ? undefined : await findGateway(config).catch(() => undefined);\n if (gateway) {\n const status = await gateway.client\n .get<{ status: RunnerStatus }>('/api/runner')\n .then((r) => r.status)\n .catch(() => undefined);\n if (status && !['idle', 'stopped', 'error'].includes(status.state)) {\n throw new CliError(`The gateway's runner is already ${status.state}`, {\n hint: `Watch it in the dashboard at ${gateway.client.baseUrl}/ or stop it there first.`,\n });\n }\n if (!opts.once) return driveGateway(ctx, gateway.client, config, root, opts.task);\n }\n\n const engine = deps.engine ?? createEngine({ home: ctx.home, env: ctx.env, projectRoot: root });\n try {\n const { runner } = (deps.wire ?? ((e, r) => wireProject(e, r, { env: ctx.env })))(engine, root);\n const graph = await new ProjectBrain(root)\n .readGraph()\n .catch(() => ({ version: 1 as const, tasks: [] }));\n return opts.once\n ? await runOnce(ctx, engine, runner, config, deps, opts.task)\n : await runContinuous(\n ctx,\n engine,\n runner,\n config,\n basename(root),\n graph.tasks,\n deps,\n opts.task,\n );\n } finally {\n if (!deps.engine) engine.close();\n }\n}\n\ntype RunnerLike = ReturnType<NonNullable<RunDeps['wire']>>['runner'];\n\nasync function runOnce(\n ctx: CliContext,\n engine: Engine,\n runner: RunnerLike,\n config: DaveConfig,\n deps: RunDeps,\n taskId?: string,\n): Promise<number> {\n const unsubscribe = engine.events.subscribe((event) => printEvent(ctx, event, ctx.json));\n let interrupted = false;\n const interrupt = interruptFor(deps);\n void interrupt.promise.then(() => {\n interrupted = true;\n if (!ctx.json) ctx.err(ctx.errTheme.dim('Stopping safely…'));\n void runner.stop();\n });\n const started = Date.now();\n let result: RunOnceResult;\n try {\n result = await runner.runOnce(taskId === undefined ? {} : { taskId });\n } catch (err) {\n throw explainRunnerError(err, config);\n } finally {\n unsubscribe();\n interrupt.dispose();\n }\n if (ctx.json) {\n printJson(ctx, { ...result, interrupted });\n } else {\n ctx.out();\n for (const line of describeResult(ctx, result)) ctx.out(line);\n ctx.out(ctx.theme.dim(` took ${formatDuration((Date.now() - started) / 1000)}`));\n }\n return exitCodeFor(result);\n}\n\nasync function runContinuous(\n ctx: CliContext,\n engine: Engine,\n runner: RunnerLike,\n config: DaveConfig,\n projectName: string,\n tasks: TaskNode[],\n deps: RunDeps,\n taskId?: string,\n): Promise<number> {\n // Buffer events emitted before the view mounts so the first log lines are not lost.\n const early: DaveEvent[] = [];\n const unsubscribeEarly = engine.events.subscribe((e) => early.push(e));\n try {\n await runner.start(taskId === undefined ? {} : { taskId });\n } catch (err) {\n unsubscribeEarly();\n throw explainRunnerError(err, config);\n }\n\n if (!ctx.interactive) {\n unsubscribeEarly();\n for (const event of early) printEvent(ctx, event, false);\n const unsubscribe = engine.events.subscribe((event) => printEvent(ctx, event, false));\n const finished = new Promise<void>((resolveDone) => {\n const timer = setInterval(() => {\n if (!runner.running) {\n clearInterval(timer);\n resolveDone();\n }\n }, 250);\n });\n const interrupt = interruptFor(deps);\n await Promise.race([interrupt.promise, finished]);\n interrupt.dispose();\n if (runner.running) {\n ctx.out(ctx.theme.dim('Stopping safely…'));\n await runner.stop();\n }\n unsubscribe();\n } else {\n const [{ render }, { createElement }, { RunnerApp }] = await Promise.all([\n import('ink'),\n import('react'),\n import('../tui/RunnerView'),\n ]);\n let initial = initialRunnerState(runner.status(), tasks);\n const { runnerReducer } = await import('../tui/runner-state');\n for (const event of early) initial = runnerReducer(initial, event);\n unsubscribeEarly();\n const instance = render(\n createElement(RunnerApp, {\n theme: ctx.theme,\n initial,\n subscribe: (onEvent: (e: DaveEvent) => void) => engine.events.subscribe(onEvent),\n maxRepairCycles: config.runner.maxRepairCycles,\n projectName,\n stop: () => runner.stop(),\n pause: () => runner.pause(),\n resume: () => runner.resume(),\n }),\n { stdout: ctx.io.stdout as NodeJS.WriteStream, exitOnCtrlC: false },\n );\n await instance.waitUntilExit();\n if (runner.running) await runner.stop();\n }\n const final = runner.status();\n if (final.state === 'error') {\n ctx.err(ctx.errTheme.error(`Runner error: ${final.lastError ?? 'unknown error'}`));\n return EXIT.failure;\n }\n return EXIT.ok;\n}\n\n/** Continuous mode against the runner of a running gateway, fed by `/api/events`. */\nasync function driveGateway(\n ctx: CliContext,\n client: GatewayClient,\n config: DaveConfig,\n root: string,\n taskId?: string,\n): Promise<number> {\n try {\n await client.post('/api/runner/start', taskId === undefined ? undefined : { taskId });\n } catch (err) {\n if (err instanceof GatewayError && err.status === 501) {\n throw new CliError('The running gateway has no project brain to work on', {\n hint: 'Restart `davecode start` inside this repository, or stop it so `davecode run` can work in-process.',\n });\n }\n throw explainRunnerError(err, config);\n }\n const stop = async () => {\n await client.post('/api/runner/stop', undefined, { timeoutMs: 10 * 60_000 });\n };\n const controller = new AbortController();\n const listeners = new Set<(e: DaveEvent) => void>();\n let latest: RunnerStatus = { state: 'selecting' };\n const pump = (async () => {\n try {\n for await (const event of client.events(controller.signal)) {\n if (event.type === 'runner.status') latest = event.status;\n for (const listener of listeners) listener(event);\n }\n } catch {\n // aborted or disconnected\n }\n })();\n\n try {\n if (!ctx.interactive) {\n const print = (e: DaveEvent) => printEvent(ctx, e, false);\n listeners.add(print);\n await signalWaiter().promise;\n ctx.out(ctx.theme.dim('Stopping safely…'));\n await stop();\n } else {\n const [{ render }, { createElement }, { RunnerApp }, { tasks }] = await Promise.all([\n import('ink'),\n import('react'),\n import('../tui/RunnerView'),\n client\n .get<{ graph: TaskGraph }>('/api/tasks')\n .then((r) => ({ tasks: r.graph.tasks }))\n .catch(() => ({ tasks: [] as TaskNode[] })),\n ]);\n const status = await client\n .get<{ status: RunnerStatus }>('/api/runner')\n .then((r) => r.status)\n .catch(() => latest);\n const instance = render(\n createElement(RunnerApp, {\n theme: ctx.theme,\n initial: initialRunnerState(status, tasks),\n subscribe: (onEvent: (e: DaveEvent) => void) => {\n listeners.add(onEvent);\n return () => listeners.delete(onEvent);\n },\n maxRepairCycles: config.runner.maxRepairCycles,\n projectName: basename(root),\n stop,\n pause: async () => {\n await client.post('/api/runner/pause');\n },\n resume: async () => {\n await client.post('/api/runner/start');\n },\n }),\n { stdout: ctx.io.stdout as NodeJS.WriteStream, exitOnCtrlC: false },\n );\n await instance.waitUntilExit();\n if (!isTerminal(latest.state)) await stop().catch(() => undefined);\n }\n } finally {\n controller.abort();\n await pump;\n }\n return latest.state === 'error' ? EXIT.failure : EXIT.ok;\n}\n"],"mappings":"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","names":[]}
package/dist/runtime.js CHANGED
@@ -5,8 +5,9 @@ import {
5
5
  resolveProjectRoot,
6
6
  startRuntime,
7
7
  wireProject
8
- } from "./chunk-JFWMLYV7.js";
9
- import "./chunk-HENE4DA6.js";
8
+ } from "./chunk-KUY3QHGS.js";
9
+ import "./chunk-732GIHRQ.js";
10
+ import "./chunk-QKY3OKVG.js";
10
11
  export {
11
12
  detectProjectRoot,
12
13
  launchLoginTerminal,
@@ -10,16 +10,17 @@ import {
10
10
  findGateway,
11
11
  startRuntime,
12
12
  which
13
- } from "./chunk-JFWMLYV7.js";
13
+ } from "./chunk-KUY3QHGS.js";
14
14
  import {
15
15
  CliError,
16
16
  EXIT
17
17
  } from "./chunk-7XVXEO7U.js";
18
+ import "./chunk-732GIHRQ.js";
18
19
  import {
19
20
  VERSION,
20
21
  loadConfig,
21
22
  summarize
22
- } from "./chunk-HENE4DA6.js";
23
+ } from "./chunk-QKY3OKVG.js";
23
24
  import "./chunk-MC7RIPL7.js";
24
25
 
25
26
  // src/commands/start.ts
@@ -282,4 +283,4 @@ async function startCommand(ctx, opts, deps = {}) {
282
283
  export {
283
284
  startCommand
284
285
  };
285
- //# sourceMappingURL=start-GRHW3TGE.js.map
286
+ //# sourceMappingURL=start-WVAEAQWL.js.map
@@ -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":";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;;;ACDxB,SAAS,aAAa;AACtB,SAAS,YAAY;AAIrB,eAAsB,cACpB,KACA,MAAyB,QAAQ,KACf;AAClB,QAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,MACE,CAAC,CAAC,SAAS,QAAQ,EAAE,SAAS,OAAO,QAAQ,KAC7C,CAAC,CAAC,aAAa,aAAa,OAAO,EAAE,SAAS,OAAO,QAAQ,KAC7D,OAAO,YACP,OAAO,YACP,OAAO,UACP,OAAO;AAEP,UAAM,IAAI,MAAM,mEAAmE;AACrF,QAAM,MAAM,QAAQ,aAAa;AACjC,QAAM,aAAa,MACf;AAAA,IACE;AAAA,MACE,IAAI,mBAAmB,KAAK;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,MACE,IAAI,gBAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,GAAI,IAAI,eACJ;AAAA,MACE,KAAK,IAAI,cAAc,aAAa,QAAQ,eAAe,YAAY;AAAA,MACvE,KAAK,IAAI,cAAc,UAAU,UAAU,eAAe,YAAY;AAAA,IACxE,IACA,CAAC;AAAA,EACP,IACA,QAAQ,aAAa,WACnB;AAAA,IACE;AAAA,IACA;AAAA,EACF,IACA,CAAC,iBAAiB,YAAY,oBAAoB,gBAAgB;AACxE,QAAM,aAAa,WAAW,IAAI,CAAC,cAAc,MAAM,WAAW,GAAG,CAAC,EAAE,KAAK,OAAO;AACpF,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,IAAI,QAAQ,CAACA,aAAY;AAC9B,UAAM,QAAQ,MAAM,YAAY,CAAC,SAAS,OAAO,MAAM,GAAG,GAAG;AAAA,MAC3D;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,UAAM,KAAK,SAAS,MAAMA,SAAQ,KAAK,CAAC;AACxC,UAAM,KAAK,SAAS,MAAM;AACxB,YAAM,MAAM;AACZ,MAAAA,SAAQ,IAAI;AAAA,IACd,CAAC;AAAA,EACH,CAAC;AACH;;;AC5DO,SAAS,kBAAkB,UAA6B;AAC7D,MAAI,SAAS,WAAW,EAAG,QAAO;AAClC,QAAM,UAAU,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO;AAChD,QAAM,aAAa,oBAAI,IAAoB;AAC3C,aAAW,WAAW,SAAS;AAC7B,eAAW,IAAI,QAAQ,WAAW,WAAW,IAAI,QAAQ,QAAQ,KAAK,KAAK,CAAC;AAAA,EAC9E;AACA,QAAM,QAAQ,CAAC,GAAG,WAAW,QAAQ,CAAC,EACnC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EACrC,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,QAAQ,IAAI,CAAC,EAAE;AAC5C,QAAM,OACJ,QAAQ,WAAW,SAAS,SACxB,GAAG,SAAS,MAAM,aAClB,GAAG,QAAQ,MAAM,eAAe,SAAS,MAAM;AACrD,QAAM,WAAW,SAAS,OAAO,CAAC,MAAM,EAAE,WAAW,WAAW,EAAE,WAAW,UAAU,EAAE;AACzF,SAAO,CAAC,MAAM,GAAG,OAAO,GAAI,WAAW,IAAI,CAAC,GAAG,QAAQ,iBAAiB,IAAI,CAAC,CAAE,EAAE,KAAK,QAAK;AAC7F;AAGO,SAAS,gBAAgB,QAAoB,MAAwB;AAC1E,QAAM,WAAqB,CAAC;AAC5B,MAAI,OAAO,aAAa,WAAW;AACjC,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACA,MAAI,OAAO,aAAa,sBAAsB;AAC5C,aAAS;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACA,QAAM,WAAW,CAAC,aAAa,OAAO,WAAW,EAAE,SAAS,IAAI;AAChE,MAAI,CAAC,YAAY,CAAC,OAAO,OAAO,WAAW;AACzC,aAAS;AAAA,MACP,gBAAgB,IAAI;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,MAAM,IAAoB;AACjC,SAAO,IAAI,KAAK,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,CAAC;AAC/C;AAMO,SAAS,gBACd,OACA,OACA,UAAyC,CAAC,OAAO,IAC7B;AACpB,QAAM,OAAO,MAAM,IAAI,MAAM,MAAM,EAAE,CAAC;AACtC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,qBAAqB;AACxB,YAAM,SAAS,aAAa,MAAM,eAAe,MAAM,gBAAgB;AACvE,aAAO,GAAG,IAAI,KAAK,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC,IAAI,MAAM,KAAK,KAAK,MAAM;AAAA,QACnE,GAAG,QAAQ,MAAM,SAAS,CAAC,SAAM,MAAM,aAAU,MAAM,SAAS;AAAA,MAClE,CAAC;AAAA,IACH;AAAA,IACA,KAAK;AACH,aAAO,GAAG,IAAI,KAAK,MAAM,MAAM,MAAM,MAAM,IAAI,CAAC,IAAI,QAAQ,MAAM,SAAS,CAAC,KAAK,MAAM;AAAA,QACrF,GAAG,MAAM,MAAM,IAAI,GAAG,MAAM,MAAM,SAAS,IAAI,MAAM,MAAM,MAAM,KAAK,EAAE,KAAK,MAAM,MAAM,OAAO;AAAA,MAClG,CAAC;AAAA,IACH,KAAK;AACH,aAAO,GAAG,IAAI,KAAK,MAAM,KAAK,MAAM,MAAM,KAAK,CAAC,aAAa,QAAQ,MAAM,aAAa,CAAC,IACvF,MAAM,MAAM,KACd,IAAI,MAAM,cAAc,QAAQ,MAAM,WAAW,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,MAAM,CAAC;AAAA,IACzF,KAAK;AACH,aAAO,GAAG,IAAI,KAAK,MAAM,IAAI,WAAW,MAAM,SAAS,UAAU,CAAC;AAAA,IACpE,KAAK;AACH,aAAO,GAAG,IAAI,KAAK,MAAM,OAAO,QAAQ,CAAC,IAAI,MAAM,OAAO,KAAK,GAC7D,MAAM,OAAO,SAAS,MAAM,IAAI,SAAM,MAAM,OAAO,MAAM,EAAE,IAAI,EACjE;AAAA,IACF,KAAK;AACH,aAAO,GAAG,IAAI,KAAK,MAAM,IAAI,IAAI,MAAM,KAAK,GAAG,CAAC,IAAI,MAAM,OAAO;AAAA,IACnE,KAAK;AACH,aAAO,MAAM,UAAU,UAAU,MAAM,UAAU,UAC7C,GAAG,IAAI,KAAK,MAAM,UAAU,UAAU,MAAM,MAAM,MAAM,KAAK,IAAI,MAAM,KAAK,MAAM,KAAK,CAAC,IAAI,MAAM,IAAI,MAAM,KAAK,CAAC,IAAI,MAAM,OAAO,KACnI;AAAA,IACN;AACE,aAAO;AAAA,EACX;AACF;;;AF9DA,eAAe,iBAAiB,OAAqD;AACnF,MAAI;AACF,WAAQ,MAAM,MAAM,cAAc,IAAK,MAAM,MAAM,UAAU,IAAI;AAAA,EACnE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,gBAA+B;AACtC,SAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,UAAM,OAAO,MAAM;AACjB,cAAQ,IAAI,UAAU,IAAI;AAC1B,cAAQ,IAAI,WAAW,IAAI;AAC3B,MAAAA,SAAQ;AAAA,IACV;AACA,YAAQ,GAAG,UAAU,IAAI;AACzB,YAAQ,GAAG,WAAW,IAAI;AAAA,EAC5B,CAAC;AACH;AAEA,eAAsB,aACpB,KACA,MACA,OAAkB,CAAC,GACF;AACjB,QAAM,UAAU,YAAY,IAAI;AAChC,QAAM,cAAc,KAAK,UACrB,QAAQ,IAAI,KAAK,KAAK,OAAO,IAC7B,MAAM,kBAAkB,IAAI,KAAK,IAAI,IAAI;AAC7C,MAAI,eAAe,KAAK,WAAW,CAAC,WAAW,WAAW,GAAG;AAC3D,UAAM,IAAI,SAAS,gCAAgC,WAAW,EAAE;AAAA,EAClE;AACA,QAAM,SAAS,WAAW;AAAA,IACxB,MAAM,IAAI;AAAA,IACV,KAAK,IAAI;AAAA,IACT,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,EACvC,CAAC;AACD,QAAM,OAAO,KAAK,QAAQ,OAAO,OAAO;AAExC,MAAI,SAAS,GAAG;AACd,UAAM,UAAU,MAAM,YAAY,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzE,QAAI,SAAS;AACX,YAAM,IAAI,SAAS,4CAA4C,QAAQ,OAAO,OAAO,IAAI;AAAA,QACvF,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,aAAa;AAAA,MAC3B,MAAM,IAAI;AAAA,MACV,KAAK,IAAI;AAAA,MACT,KAAK,IAAI;AAAA,MACT,GAAI,cAAc,EAAE,YAAY,YAAY,IAAI,EAAE,WAAW,KAAK;AAAA,MAClE,GAAI,KAAK,SAAS,SAAY,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,MACrD;AAAA,MACA,WAAW,KAAK,cAAc;AAAA,MAC9B,GAAI,KAAK,UAAU,EAAE,QAAQ,EAAE,OAAO,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,UAAM,OAAQ,IAA8B;AAC5C,QAAI,SAAS,cAAc;AACzB,YAAM,IAAI,SAAS,QAAQ,IAAI,sBAAsB;AAAA,QACnD,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,QAAI,SAAS,UAAU;AACrB,YAAM,IAAI,SAAS,6BAA6B,KAAK,QAAQ,OAAO,OAAO,IAAI,IAAI,IAAI,IAAI;AAAA,QACzF,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAEA,QAAM,EAAE,OAAO,IAAI;AACnB,MAAI,KAAK,OAAO,CAAC,IAAI,MAAM;AACzB,UAAM,SAAS,QAAQ,eACnB,MAAM,cAAc,QAAQ,KAAK,IAAI,GAAG,EAAE,MAAM,MAAM,KAAK,IAC3D;AACJ,QAAI,CAAC;AACH,UAAI;AAAA,QACF,QAAQ,QAAQ,GAAG;AAAA,MACrB;AAAA,EACJ;AACA,QAAM,WAAW,OAAO,SAAS,KAAK;AACtC,QAAM,WAAW,gBAAgB,OAAO,QAAQ,QAAQ,IAAI;AAC5D,QAAM,QAAQ,QAAQ,QAAQ,MAAM,iBAAiB,QAAQ,KAAK,IAAI;AAEtE,MAAI,IAAI,MAAM;AACZ,cAAU,KAAK;AAAA,MACb,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,KAAK,QAAQ;AAAA,MACb,KAAK,GAAG,QAAQ,GAAG;AAAA,MACnB,WAAW,QAAQ,eAAe,GAAG,QAAQ,GAAG,MAAM;AAAA,MACtD,SAAS,QAAQ,WAAW;AAAA,MAC5B,UAAU,SAAS;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH,OAAO;AACL,UAAM,EAAE,MAAM,IAAI;AAClB,UAAM,KAAK,KAAK,MAAM,YAAY,IAAI,IAAI,OAAO;AACjD,UAAM,MAAM,CAAC,OAAe,UAC1B,IAAI,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,EAAE,CAAC,CAAC,IAAI,KAAK,EAAE;AACtD,QAAI,IAAI;AACR,QAAI;AAAA,MACF,KAAK,MAAM,KAAK,MAAM,OAAO,UAAU,CAAC,CAAC,IAAI,MAAM,IAAI,IAAI,OAAO,kBAAe,EAAE,IAAI,CAAC;AAAA,IAC1F;AACA,QAAI,IAAI;AACR,QAAI,OAAO,MAAM,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAC5C;AAAA,MACE;AAAA,MACA,QAAQ,eACJ,MAAM,OAAO,GAAG,QAAQ,GAAG,GAAG,IAC9B,MAAM;AAAA,QACJ,KAAK,cAAc,SAAS,CAAC,OAAO,OAAO,OAAO,YAC9C,aACA;AAAA,MACN;AAAA,IACN;AACA,QAAI,UAAU,MAAM,IAAI,GAAG,QAAQ,GAAG,aAAa,CAAC;AACpD,QAAI,QAAQ,SAAS;AACnB,YAAM,OAAO,QAAQ,UAAU,KAAK,IAAI;AACxC,YAAM,WAAW,OACb,MAAM,IAAI,SAAM,KAAK,OAAO,OAAO,IAAI,KAAK,KAAK,aAAa,IAC9D,MAAM,IAAI,oCAAiC;AAC/C,UAAI,WAAW,GAAG,QAAQ,QAAQ,IAAI,GAAG,QAAQ,EAAE;AACnD,UAAI,QAAQ,QAAQ;AAClB;AAAA,UACE;AAAA,UACA,GAAG,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG,MAAM,IAAI,0DAAuD,CAAC;AAAA,QACvG;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,WAAW,MAAM,IAAI,oCAAoC,CAAC;AAAA,IAChE;AACA;AAAA,MACE;AAAA,MACA,SAAS,SAAS,IACd,kBAAkB,QAAQ,IAC1B,MAAM,KAAK,uCAAuC;AAAA,IACxD;AACA,eAAW,WAAW,SAAU,KAAI,IAAI,KAAK,MAAM,KAAK,GAAG,MAAM,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC,EAAE;AAC3F,QAAI,IAAI;AACR,QAAI,IAAI,MAAM,IAAI,yBAAyB,CAAC;AAC5C,QAAI,IAAI;AAAA,EACV;AAEA,MAAI;AACJ,MAAI,CAAC,IAAI,QAAQ,CAAC,KAAK,SAAS,CAAC,KAAK,SAAS;AAC7C,UAAM,UAAU,CAAC,OAAe,OAAO,SAAS,IAAI,EAAE,GAAG,SAAS;AAClE,kBAAc,OAAO,OAAO,UAAU,CAAC,UAAU;AAC/C,YAAM,OAAO,gBAAgB,IAAI,OAAO,OAAO,OAAO;AACtD,UAAI,KAAM,KAAI,IAAI,KAAK,IAAI,EAAE;AAAA,IAC/B,CAAC;AAAA,EACH;AAEA,SAAO,KAAK,SAAS,eAAe,OAAO;AAC3C,gBAAc;AACd,MAAI,CAAC,IAAI,KAAM,KAAI,IAAI,IAAI,MAAM,IAAI,2BAAsB,CAAC;AAC5D,QAAM,QAAQ,MAAM;AACpB,SAAO,KAAK;AACd;","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-ZNUNYYN6.js";
9
+ } from "./chunk-YNAMNQLW.js";
10
10
  import "./chunk-SF5ZEAP4.js";
11
11
  import "./chunk-QA3O6RA2.js";
12
- import "./chunk-JFWMLYV7.js";
12
+ import "./chunk-KUY3QHGS.js";
13
13
  import "./chunk-7XVXEO7U.js";
14
- import "./chunk-HENE4DA6.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-QR2HNPBK.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-6SHOBL2X.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-JFWMLYV7.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-HENE4DA6.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-BHWDV4JS.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.1",
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",
@@ -64,9 +64,9 @@
64
64
  "devDependencies": {
65
65
  "@types/react": "^19.3.0",
66
66
  "ink-testing-library": "^4.0.0",
67
- "@davecode/core": "0.5.1",
68
- "@davecode/server": "0.5.1",
69
- "@davecode/ui": "0.5.1"
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",