@dmrlzz/davecode 0.5.3 → 0.6.0

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 (84) hide show
  1. package/README.md +1 -0
  2. package/dist/{ChatApp-IF5D7XNH.js → ChatApp-RQZ2IZFQ.js} +6 -6
  3. package/dist/{account-KBXJ5KR7.js → account-FY6THFLW.js} +3 -3
  4. package/dist/{accounts-XUJNDCFH.js → accounts-ZV3KMLC5.js} +5 -5
  5. package/dist/{budget-PHV4NRUS.js → budget-OUOEMMOM.js} +4 -4
  6. package/dist/{chat-HGTX76DU.js → chat-OHVP4BS3.js} +8 -8
  7. package/dist/{chunk-AFCQURO5.js → chunk-2MM5WT5J.js} +3 -3
  8. package/dist/{chunk-EBV5A33R.js → chunk-2P5DJWIJ.js} +4 -4
  9. package/dist/{chunk-ING5HCIO.js → chunk-2XGDILCW.js} +1677 -133
  10. package/dist/chunk-2XGDILCW.js.map +1 -0
  11. package/dist/{chunk-FZJNOG2T.js → chunk-FFB2QA5I.js} +2 -2
  12. package/dist/{goal-ETZWLVKO.js → chunk-HL4RIXPM.js} +8 -8
  13. package/dist/chunk-HL4RIXPM.js.map +1 -0
  14. package/dist/{chunk-FPSLYBLU.js → chunk-L7NEDOA3.js} +2 -2
  15. package/dist/{chunk-DFQW3MRD.js → chunk-NKRI6SYR.js} +2 -2
  16. package/dist/{chunk-YSD6W27K.js → chunk-TP3ORSHY.js} +134 -4
  17. package/dist/chunk-TP3ORSHY.js.map +1 -0
  18. package/dist/{chunk-ZVNX7CSO.js → chunk-U5CI774J.js} +3 -3
  19. package/dist/{config-DG2E4VDW.js → config-ZLO3YOUX.js} +3 -3
  20. package/dist/dashboard/assets/Accounts-CIhOt9FH.js +1 -0
  21. package/dist/dashboard/assets/{Callout-1E8Wsl9W.js → Callout-CqdcH6dC.js} +1 -1
  22. package/dist/dashboard/assets/Goals-CITP2GqG.js +1 -0
  23. package/dist/dashboard/assets/{Library-DZxBVUo_.js → Library-DnCIb76j.js} +1 -1
  24. package/dist/dashboard/assets/{Panes-C-TJekjs.js → Panes-DBqKYuaE.js} +3 -3
  25. package/dist/dashboard/assets/RoutesPage-BNVmKhyU.js +4 -0
  26. package/dist/dashboard/assets/Runner-KR35ZWUE.js +1 -0
  27. package/dist/dashboard/assets/Settings-B5qE-a5O.js +1 -0
  28. package/dist/dashboard/assets/Tasks-bJLfNJmS.js +2 -0
  29. package/dist/dashboard/assets/Traffic-CGfilrRx.js +1 -0
  30. package/dist/dashboard/assets/Workspace-Dc3cvct_.js +1 -0
  31. package/dist/dashboard/assets/format-328qIBHX.js +111 -0
  32. package/dist/dashboard/assets/index-C-bwzlsl.js +50 -0
  33. package/dist/dashboard/assets/index-D9FCfPmM.css +2 -0
  34. package/dist/dashboard/assets/task-errors-DK4-900l.js +1 -0
  35. package/dist/dashboard/index.html +3 -3
  36. package/dist/{dist-IPMBGFJD.js → dist-56V3DLJ4.js} +16 -2
  37. package/dist/{doctor-5APOWJ5D.js → doctor-DUOKUSJL.js} +3 -3
  38. package/dist/goal-WG37XHUY.js +26 -0
  39. package/dist/index.js +64 -31
  40. package/dist/index.js.map +1 -1
  41. package/dist/{init-YDLNA3GD.js → init-WW4XPFMM.js} +3 -3
  42. package/dist/orchestrate-7YQDBS3E.js +382 -0
  43. package/dist/orchestrate-7YQDBS3E.js.map +1 -0
  44. package/dist/{run-I6N7TLHV.js → run-QB4SGPEC.js} +3 -3
  45. package/dist/runtime.js +6 -2
  46. package/dist/{start-ECLELJGJ.js → start-U4RL377T.js} +3 -3
  47. package/dist/{status-QQPP67I4.js → status-GHVMGZI5.js} +4 -4
  48. package/dist/status-GHVMGZI5.js.map +1 -0
  49. package/dist/{tasks-RNMC2XFN.js → tasks-VTBJ4B2G.js} +4 -4
  50. package/package.json +4 -4
  51. package/dist/chunk-ING5HCIO.js.map +0 -1
  52. package/dist/chunk-YSD6W27K.js.map +0 -1
  53. package/dist/dashboard/assets/Accounts-DXiGsutB.js +0 -1
  54. package/dist/dashboard/assets/Badge-DUGKlx3Z.js +0 -55
  55. package/dist/dashboard/assets/Goals-kL4VAxw3.js +0 -1
  56. package/dist/dashboard/assets/RoutesPage-DWYm9tW8.js +0 -4
  57. package/dist/dashboard/assets/Runner-CmHBjECR.js +0 -1
  58. package/dist/dashboard/assets/Settings-BANphxva.js +0 -1
  59. package/dist/dashboard/assets/Tasks-cSx1PKyQ.js +0 -2
  60. package/dist/dashboard/assets/Traffic-DEAuM6jq.js +0 -1
  61. package/dist/dashboard/assets/Workspace-BQFjc1jH.js +0 -1
  62. package/dist/dashboard/assets/index-B8kld9xo.js +0 -104
  63. package/dist/dashboard/assets/index-BEmBgsbP.css +0 -2
  64. package/dist/dashboard/assets/task-errors-r-WYZ_S3.js +0 -1
  65. package/dist/goal-ETZWLVKO.js.map +0 -1
  66. /package/dist/{ChatApp-IF5D7XNH.js.map → ChatApp-RQZ2IZFQ.js.map} +0 -0
  67. /package/dist/{account-KBXJ5KR7.js.map → account-FY6THFLW.js.map} +0 -0
  68. /package/dist/{accounts-XUJNDCFH.js.map → accounts-ZV3KMLC5.js.map} +0 -0
  69. /package/dist/{budget-PHV4NRUS.js.map → budget-OUOEMMOM.js.map} +0 -0
  70. /package/dist/{chat-HGTX76DU.js.map → chat-OHVP4BS3.js.map} +0 -0
  71. /package/dist/{chunk-AFCQURO5.js.map → chunk-2MM5WT5J.js.map} +0 -0
  72. /package/dist/{chunk-EBV5A33R.js.map → chunk-2P5DJWIJ.js.map} +0 -0
  73. /package/dist/{chunk-FZJNOG2T.js.map → chunk-FFB2QA5I.js.map} +0 -0
  74. /package/dist/{chunk-FPSLYBLU.js.map → chunk-L7NEDOA3.js.map} +0 -0
  75. /package/dist/{chunk-DFQW3MRD.js.map → chunk-NKRI6SYR.js.map} +0 -0
  76. /package/dist/{chunk-ZVNX7CSO.js.map → chunk-U5CI774J.js.map} +0 -0
  77. /package/dist/{config-DG2E4VDW.js.map → config-ZLO3YOUX.js.map} +0 -0
  78. /package/dist/{dist-IPMBGFJD.js.map → dist-56V3DLJ4.js.map} +0 -0
  79. /package/dist/{doctor-5APOWJ5D.js.map → doctor-DUOKUSJL.js.map} +0 -0
  80. /package/dist/{status-QQPP67I4.js.map → goal-WG37XHUY.js.map} +0 -0
  81. /package/dist/{init-YDLNA3GD.js.map → init-WW4XPFMM.js.map} +0 -0
  82. /package/dist/{run-I6N7TLHV.js.map → run-QB4SGPEC.js.map} +0 -0
  83. /package/dist/{start-ECLELJGJ.js.map → start-U4RL377T.js.map} +0 -0
  84. /package/dist/{tasks-RNMC2XFN.js.map → tasks-VTBJ4B2G.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  brandLogo
3
- } from "./chunk-ING5HCIO.js";
3
+ } from "./chunk-2XGDILCW.js";
4
4
 
5
5
  // src/ui/banner.ts
6
6
  function brandBanner(theme, text, columns = 80, minColumns = 56) {
@@ -17,4 +17,4 @@ function brandBanner(theme, text, columns = 80, minColumns = 56) {
17
17
  export {
18
18
  brandBanner
19
19
  };
20
- //# sourceMappingURL=chunk-FZJNOG2T.js.map
20
+ //# sourceMappingURL=chunk-FFB2QA5I.js.map
@@ -9,19 +9,17 @@ import {
9
9
  detectProjectRoot,
10
10
  findGateway,
11
11
  wireProject
12
- } from "./chunk-YSD6W27K.js";
12
+ } from "./chunk-TP3ORSHY.js";
13
13
  import {
14
14
  CliError,
15
15
  EXIT
16
16
  } from "./chunk-7XVXEO7U.js";
17
- import "./chunk-732GIHRQ.js";
18
17
  import {
19
18
  GoalStore,
20
19
  createEngine,
21
20
  isTerminalGoal,
22
21
  loadConfig
23
- } from "./chunk-ING5HCIO.js";
24
- import "./chunk-MC7RIPL7.js";
22
+ } from "./chunk-2XGDILCW.js";
25
23
 
26
24
  // src/commands/goal.ts
27
25
  import { existsSync } from "fs";
@@ -292,12 +290,14 @@ async function goalsCancel(ctx, id, opts, deps = {}) {
292
290
  else ctx.out(`${ctx.theme.bold(goal.id)} ${goal.status}`);
293
291
  return EXIT.ok;
294
292
  }
293
+
295
294
  export {
295
+ interruptSignal,
296
296
  describeGoal,
297
- goalCommand,
298
297
  goalExitCode,
299
- goalsCancel,
298
+ goalCommand,
300
299
  goalsList,
301
- goalsShow
300
+ goalsShow,
301
+ goalsCancel
302
302
  };
303
- //# sourceMappingURL=goal-ETZWLVKO.js.map
303
+ //# sourceMappingURL=chunk-HL4RIXPM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/goal.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport {\n createEngine,\n type DaveEvent,\n type Engine,\n type Goal,\n GoalStore,\n isTerminalGoal,\n loadConfig,\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 { formatDuration } from '../ui/format';\nimport type { Theme } from '../ui/theme';\n\nexport interface GoalOptions {\n maxRounds?: number;\n maxTasks?: number;\n maxTokens?: number;\n dryRun?: boolean;\n project?: string;\n}\n\n/** Goal control used by the command: in-process `GoalService` or the gateway's `/api/goals`. */\ninterface GoalBackend {\n start(input: GoalStartBody): Promise<Goal>;\n cancel(id: string): Promise<Goal>;\n /** Resolves with the finished goal. */\n wait(id: string): Promise<Goal>;\n}\n\ninterface GoalStartBody {\n objective: string;\n maxRounds?: number;\n maxTasks?: number;\n maxTokens?: number;\n dryRun?: boolean;\n}\n\n/** Test seams. */\nexport interface GoalDeps {\n engine?: Engine;\n /** Resolves when the user asks to stop (default: SIGINT/SIGTERM). */\n interrupt?: () => Promise<void>;\n noGateway?: boolean;\n}\n\nasync function projectRoot(ctx: CliContext, project?: string): Promise<string> {\n const root = project ? resolve(ctx.cwd, project) : await detectProjectRoot(ctx.cwd, ctx.home);\n if (!root || !existsSync(root)) {\n throw new CliError('Not inside a project', {\n hint: 'Run goal mode inside a repository with a project brain (`git init` and `davecode init`).',\n });\n }\n return root;\n}\n\n/** Resolves on the first SIGINT/SIGTERM (or `deps.interrupt`); `dispose` removes the handlers. */\nexport function interruptSignal(deps: Pick<GoalDeps, 'interrupt'>): {\n promise: Promise<void>;\n dispose(): void;\n} {\n if (deps.interrupt) return { promise: deps.interrupt(), dispose: () => {} };\n let dispose = () => {};\n const promise = new Promise<void>((done) => {\n const handler = () => {\n dispose();\n done();\n };\n dispose = () => {\n process.off('SIGINT', handler);\n process.off('SIGTERM', handler);\n };\n process.on('SIGINT', handler);\n process.on('SIGTERM', handler);\n });\n return { promise, dispose };\n}\n\nfunction explainGoalError(err: unknown): unknown {\n const code =\n err instanceof GatewayError ? err.code : (err as { code?: unknown } | undefined)?.code;\n const message = err instanceof Error ? err.message : String(err);\n if (code === 'busy') {\n return new CliError(message, {\n hint: 'Wait for the runner or the other goal to finish, or stop it from the dashboard.',\n });\n }\n if (code === 'goals_unavailable') {\n return new CliError('The running gateway has no project to run goals in', {\n hint: 'Restart `davecode start` inside this repository, or stop it so `davecode goal` runs in-process.',\n });\n }\n return err;\n}\n\n// ---------------------------------------------------------------------------\n// Printing\n// ---------------------------------------------------------------------------\n\nconst STATUS_GLYPH: Record<Goal['tasks'][number]['status'], (t: Theme) => string> = {\n SUCCESS: (t) => t.ok(t.glyph.success),\n FAILED: (t) => t.error(t.glyph.failed),\n IN_PROGRESS: (t) => t.accent(t.glyph.running),\n PENDING: (t) => t.dim(t.glyph.pending),\n};\n\nfunction printEvent(ctx: CliContext, goalId: string, event: DaveEvent): void {\n if (event.type !== 'goal.log' || event.goalId !== goalId || event.level === 'debug') return;\n const theme = ctx.errTheme;\n const time = new Date(event.ts).toTimeString().slice(0, 8);\n const who = event.role ? theme.accent(`[${event.role}]`) : theme.dim('[goal]');\n const message =\n event.level === 'error'\n ? theme.error(event.message)\n : event.level === 'warn'\n ? theme.warn(event.message)\n : event.message;\n ctx.err(`${theme.dim(time)} ${who} ${message}`);\n}\n\nexport function describeGoal(theme: Theme, goal: Goal): string[] {\n const lines: string[] = [];\n const colour =\n goal.status === 'succeeded' || goal.status === 'planned'\n ? theme.ok\n : goal.status === 'cancelled' || goal.status === 'budget_exhausted'\n ? theme.warn\n : goal.status === 'failed'\n ? theme.error\n : theme.accent;\n lines.push(\n `${theme.bold(goal.id)} ${colour(goal.status)} ${theme.dim(`round ${goal.round}/${goal.limits.maxRounds}`)}`,\n );\n lines.push(` ${goal.objective}`);\n lines.push(\n theme.dim(\n ` tokens ${goal.limits.tokensUsed.toLocaleString('en-US')} / ${goal.limits.maxTokens.toLocaleString('en-US')} · tasks ${goal.tasks.length} / ${goal.limits.maxTasks}`,\n ),\n );\n if (goal.tasks.length > 0) lines.push('');\n for (const task of goal.tasks) {\n const glyph = STATUS_GLYPH[task.status](theme);\n lines.push(\n `${glyph} ${theme.bold(task.id)} ${theme.dim(`${task.role}·${task.kind}`)} ${task.title}`,\n );\n if (task.artifact) lines.push(theme.dim(` ${task.artifact}`));\n else if (task.status === 'FAILED' && task.notes) {\n lines.push(theme.dim(` ${task.notes.split('\\n')[0]?.slice(0, 160) ?? ''}`));\n }\n }\n if (goal.summary) lines.push('', goal.summary.trim());\n if (goal.lastError) lines.push('', theme.error(goal.lastError));\n return lines;\n}\n\nexport function goalExitCode(goal: Goal): number {\n if (goal.status === 'succeeded' || goal.status === 'planned') return EXIT.ok;\n if (goal.status === 'cancelled') return 130;\n return EXIT.failure;\n}\n\n// ---------------------------------------------------------------------------\n// Backends\n// ---------------------------------------------------------------------------\n\nfunction gatewayBackend(\n client: GatewayClient,\n onEvent: (e: DaveEvent) => void,\n): {\n backend: GoalBackend;\n close(): Promise<void>;\n} {\n const controller = new AbortController();\n const finished = new Map<string, (goal: Goal) => void>();\n const pump = (async () => {\n try {\n for await (const event of client.events(controller.signal)) {\n onEvent(event);\n if (event.type === 'goal.updated' && isTerminalGoal(event.goal)) {\n finished.get(event.goal.id)?.(event.goal);\n }\n }\n } catch {\n // aborted or disconnected\n }\n })();\n const backend: GoalBackend = {\n start: async (input) => (await client.post<{ goal: Goal }>('/api/goals', input)).goal,\n cancel: async (id) =>\n (\n await client.post<{ goal: Goal }>(`/api/goals/${id}/cancel`, undefined, {\n timeoutMs: 10 * 60_000,\n })\n ).goal,\n wait: (id) =>\n new Promise<Goal>((resolveGoal) => {\n finished.set(id, resolveGoal);\n // The goal may have finished before the listener was registered.\n void client\n .get<{ goal: Goal }>(`/api/goals/${id}`)\n .then(({ goal }) => {\n if (isTerminalGoal(goal)) resolveGoal(goal);\n })\n .catch(() => undefined);\n }),\n };\n return {\n backend,\n close: async () => {\n controller.abort();\n await pump;\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Commands\n// ---------------------------------------------------------------------------\n\n/** `davecode goal \"<objective>\"`: plan and run a goal with the agent team, following its log. */\nexport async function goalCommand(\n ctx: CliContext,\n words: string[],\n opts: GoalOptions,\n deps: GoalDeps = {},\n): Promise<number> {\n const objective = words.join(' ').trim();\n if (!objective)\n throw new CliError('Describe the objective', {\n hint: 'davecode goal \"Launch a landing page for my app\"',\n });\n const root = await projectRoot(ctx, opts.project);\n const input: GoalStartBody = {\n objective,\n ...(opts.maxRounds !== undefined ? { maxRounds: opts.maxRounds } : {}),\n ...(opts.maxTasks !== undefined ? { maxTasks: opts.maxTasks } : {}),\n ...(opts.maxTokens !== undefined ? { maxTokens: opts.maxTokens } : {}),\n ...(opts.dryRun ? { dryRun: true } : {}),\n };\n\n const config =\n deps.engine?.config ?? loadConfig({ home: ctx.home, env: ctx.env, projectRoot: root });\n const gateway = deps.noGateway ? undefined : await findGateway(config).catch(() => undefined);\n let goalId: string | undefined;\n const onEvent = (event: DaveEvent) => {\n if (goalId) printEvent(ctx, goalId, event);\n };\n\n let engine: Engine | undefined;\n let backend: GoalBackend;\n let close: () => Promise<void>;\n if (gateway) {\n const remote = gatewayBackend(gateway.client, onEvent);\n backend = remote.backend;\n close = remote.close;\n if (!ctx.json) ctx.err(ctx.errTheme.dim(`Using the gateway at ${gateway.client.baseUrl}`));\n } else {\n engine = deps.engine ?? createEngine({ home: ctx.home, env: ctx.env, projectRoot: root });\n const { goals } = wireProject(engine, root, { env: ctx.env });\n const unsubscribe = engine.events.subscribe(onEvent);\n backend = {\n start: (body) => goals.start(body),\n cancel: (id) => goals.cancel(id),\n wait: async (id) => {\n const goal = await goals.wait(id);\n if (!goal) throw new CliError(`Goal ${id} disappeared`);\n return goal;\n },\n };\n const owned = !deps.engine;\n const used = engine;\n close = async () => {\n unsubscribe();\n if (owned) used.close();\n };\n }\n\n const interrupt = interruptSignal(deps);\n const started = Date.now();\n try {\n let goal: Goal;\n try {\n goal = await backend.start(input);\n } catch (err) {\n throw explainGoalError(err);\n }\n goalId = goal.id;\n if (!ctx.json) {\n ctx.err(\n ctx.errTheme.dim(\n `Goal ${goal.id} started${input.dryRun ? ' (dry run: plan only)' : ''}. Ctrl+C cancels.`,\n ),\n );\n }\n let cancelling = false;\n void interrupt.promise.then(() => {\n cancelling = true;\n if (!ctx.json) ctx.err(ctx.errTheme.dim('Cancelling…'));\n void backend.cancel(goal.id).catch(() => undefined);\n });\n goal = await backend.wait(goal.id);\n if (ctx.json) printJson(ctx, { goal, cancelled: cancelling });\n else {\n ctx.out();\n for (const line of describeGoal(ctx.theme, goal)) ctx.out(line);\n ctx.out(ctx.theme.dim(` took ${formatDuration((Date.now() - started) / 1000)}`));\n if (goal.tasks.some((t) => t.artifact)) {\n ctx.out(ctx.theme.dim(` artifacts in ${root}`));\n }\n }\n return goalExitCode(goal);\n } finally {\n interrupt.dispose();\n await close();\n }\n}\n\n/** `davecode goals`: goals of this repository, newest first (read from `.davecode/goals`). */\nexport async function goalsList(ctx: CliContext, opts: { project?: string }): Promise<number> {\n const root = await projectRoot(ctx, opts.project);\n const goals = await new GoalStore(root).list();\n if (ctx.json) {\n printJson(ctx, { goals });\n return EXIT.ok;\n }\n if (goals.length === 0) {\n ctx.out(ctx.theme.dim('No goals yet. Start one with `davecode goal \"<objective>\"`.'));\n return EXIT.ok;\n }\n for (const goal of goals) {\n const done = goal.tasks.filter((t) => t.status === 'SUCCESS').length;\n ctx.out(\n `${ctx.theme.bold(goal.id)} ${goal.status.padEnd(16)} ${ctx.theme.dim(`${done}/${goal.tasks.length} tasks · ${goal.createdAt.slice(0, 16).replace('T', ' ')}`)} ${goal.objective.slice(0, 80)}`,\n );\n }\n return EXIT.ok;\n}\n\n/** `davecode goals show <id>`. */\nexport async function goalsShow(\n ctx: CliContext,\n id: string,\n opts: { project?: string },\n): Promise<number> {\n const root = await projectRoot(ctx, opts.project);\n const goal = await new GoalStore(root).load(id);\n if (!goal)\n throw new CliError(`Unknown goal \"${id}\"`, { hint: 'See `davecode goals` for the ids.' });\n if (ctx.json) printJson(ctx, { goal });\n else for (const line of describeGoal(ctx.theme, goal)) ctx.out(line);\n return EXIT.ok;\n}\n\n/** `davecode goals cancel <id>`: through the gateway when one runs it, else marks it cancelled. */\nexport async function goalsCancel(\n ctx: CliContext,\n id: string,\n opts: { project?: string },\n deps: GoalDeps = {},\n): Promise<number> {\n const root = await projectRoot(ctx, opts.project);\n const config =\n deps.engine?.config ?? loadConfig({ home: ctx.home, env: ctx.env, projectRoot: root });\n const gateway = deps.noGateway ? undefined : await findGateway(config).catch(() => undefined);\n let goal: Goal;\n if (gateway) {\n goal = (\n await gateway.client.post<{ goal: Goal }>(`/api/goals/${id}/cancel`, undefined, {\n timeoutMs: 10 * 60_000,\n })\n ).goal;\n } else {\n const store = new GoalStore(root);\n const stored = await store.load(id);\n if (!stored)\n throw new CliError(`Unknown goal \"${id}\"`, { hint: 'See `davecode goals` for the ids.' });\n goal = stored;\n if (!isTerminalGoal(goal)) {\n const stamp = new Date().toISOString();\n goal.status = 'cancelled';\n goal.updatedAt = stamp;\n goal.finishedAt = stamp;\n delete goal.activeTaskId;\n await store.save(goal);\n }\n }\n if (ctx.json) printJson(ctx, { goal });\n else ctx.out(`${ctx.theme.bold(goal.id)} ${goal.status}`);\n return EXIT.ok;\n}\n"],"mappings":"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","names":[]}
@@ -10,7 +10,7 @@ import {
10
10
  AccountStore,
11
11
  accountService,
12
12
  startAccountLogin
13
- } from "./chunk-ING5HCIO.js";
13
+ } from "./chunk-2XGDILCW.js";
14
14
 
15
15
  // src/commands/account.ts
16
16
  function serviceFor(ctx, deps) {
@@ -125,4 +125,4 @@ export {
125
125
  accountCommand,
126
126
  chatAccountActions
127
127
  };
128
- //# sourceMappingURL=chunk-FPSLYBLU.js.map
128
+ //# sourceMappingURL=chunk-L7NEDOA3.js.map
@@ -7,7 +7,7 @@ import {
7
7
  nextTask,
8
8
  summarize,
9
9
  topologicalOrder
10
- } from "./chunk-ING5HCIO.js";
10
+ } from "./chunk-2XGDILCW.js";
11
11
 
12
12
  // src/lib/task-tree.ts
13
13
  function statusGlyph(theme, task, blocked) {
@@ -111,4 +111,4 @@ export {
111
111
  formatTaskTree,
112
112
  formatTaskDetail
113
113
  };
114
- //# sourceMappingURL=chunk-DFQW3MRD.js.map
114
+ //# sourceMappingURL=chunk-NKRI6SYR.js.map
@@ -3,6 +3,7 @@ import {
3
3
  } from "./chunk-732GIHRQ.js";
4
4
  import {
5
5
  ConfigError,
6
+ OrchestratorError,
6
7
  PROVIDER_KINDS,
7
8
  ProjectBrain,
8
9
  ProjectBrainSource,
@@ -15,8 +16,11 @@ import {
15
16
  apiConfigIssues,
16
17
  connectionMethod,
17
18
  createAccountControl,
19
+ createCliAgentRunner,
18
20
  createEngine,
21
+ createGitWorkspace,
19
22
  createGoalService,
23
+ createOrchestratorService,
20
24
  createRunner,
21
25
  endpointRebindIssue,
22
26
  loginCommandFor,
@@ -24,10 +28,12 @@ import {
24
28
  mergeApiConfig,
25
29
  newId2,
26
30
  routeSchema,
31
+ startRunSchema,
27
32
  taskIdSchema
28
- } from "./chunk-ING5HCIO.js";
33
+ } from "./chunk-2XGDILCW.js";
29
34
 
30
35
  // src/runtime.ts
36
+ import { createHash } from "crypto";
31
37
  import { existsSync as existsSync3 } from "fs";
32
38
  import { access } from "fs/promises";
33
39
  import { createRequire } from "module";
@@ -47,8 +53,9 @@ import { z as z2 } from "zod";
47
53
  import { z as z3 } from "zod";
48
54
  import { z as z4 } from "zod";
49
55
  import { z as z6 } from "zod";
50
- import { Readable } from "stream";
51
56
  import { z as z7 } from "zod";
57
+ import { Readable } from "stream";
58
+ import { z as z8 } from "zod";
52
59
  function sendApiError(reply, status, code, message, extra = {}) {
53
60
  return reply.code(status).send({ error: { message, code, ...extra } });
54
61
  }
@@ -850,6 +857,88 @@ function registerEventRoutes(app, engine, heartbeatMs) {
850
857
  res.on("error", cleanup);
851
858
  });
852
859
  }
860
+ var STATUS = {
861
+ not_found: 404,
862
+ no_agents: 409,
863
+ not_a_repository: 409,
864
+ busy: 409,
865
+ not_appliable: 409
866
+ };
867
+ function orchestratorError(error) {
868
+ if (error instanceof OrchestratorError) return error;
869
+ if (!(error instanceof Error) || error.name !== "OrchestratorError") return void 0;
870
+ const { code } = error;
871
+ return typeof code === "string" && Object.hasOwn(STATUS, code) ? error : void 0;
872
+ }
873
+ function registerOrchestratorRoutes(app, engine, orchestrator) {
874
+ if (!orchestrator) return;
875
+ const { audit } = engine;
876
+ const guarded = async (reply, work) => {
877
+ try {
878
+ return { ok: true, value: await work() };
879
+ } catch (error) {
880
+ const known = orchestratorError(error);
881
+ if (!known) throw error;
882
+ return {
883
+ ok: false,
884
+ reply: sendApiError(reply, STATUS[known.code], known.code, known.message)
885
+ };
886
+ }
887
+ };
888
+ const unknownRun = (reply, id) => sendApiError(reply, 404, "not_found", `unknown run "${id}"`);
889
+ app.get("/api/orchestrator/agents", async (_request, reply) => {
890
+ reply.header("Cache-Control", "no-store");
891
+ return { agents: await orchestrator.agents() };
892
+ });
893
+ app.get("/api/orchestrator/runs", async (_request, reply) => {
894
+ reply.header("Cache-Control", "no-store");
895
+ return { runs: orchestrator.list() };
896
+ });
897
+ app.post("/api/orchestrator/runs", async (request, reply) => {
898
+ const parsed = startRunSchema.safeParse(request.body);
899
+ if (!parsed.success) {
900
+ return sendApiError(reply, 400, "invalid_body", z7.prettifyError(parsed.error));
901
+ }
902
+ const result = await guarded(reply, () => orchestrator.start(parsed.data));
903
+ if (!result.ok) return result.reply;
904
+ audit.record({
905
+ actor: "api",
906
+ action: "orchestrator.start",
907
+ target: result.value.id,
908
+ details: { agents: result.value.agents }
909
+ });
910
+ return reply.code(202).send(result.value);
911
+ });
912
+ app.get("/api/orchestrator/runs/:id", async (request, reply) => {
913
+ reply.header("Cache-Control", "no-store");
914
+ const run = orchestrator.get(request.params.id);
915
+ if (!run) return unknownRun(reply, request.params.id);
916
+ return run;
917
+ });
918
+ app.post(
919
+ "/api/orchestrator/runs/:id/cancel",
920
+ async (request, reply) => {
921
+ const { id } = request.params;
922
+ if (orchestrator.cancel(id)) {
923
+ audit.record({ actor: "api", action: "orchestrator.cancel", target: id });
924
+ return reply.code(204).send();
925
+ }
926
+ const run = orchestrator.get(id);
927
+ if (!run) return unknownRun(reply, id);
928
+ return sendApiError(reply, 409, "not_active", `run "${id}" is already ${run.status}`);
929
+ }
930
+ );
931
+ app.post(
932
+ "/api/orchestrator/runs/:id/apply",
933
+ async (request, reply) => {
934
+ const { id } = request.params;
935
+ const result = await guarded(reply, () => orchestrator.apply(id));
936
+ if (!result.ok) return result.reply;
937
+ audit.record({ actor: "api", action: "orchestrator.apply", target: id });
938
+ return result.value;
939
+ }
940
+ );
941
+ }
853
942
  function setRoutingHeaders(reply, meta) {
854
943
  reply.header("x-davecode-request-id", meta.requestId).header("x-davecode-account", meta.accountId).header("x-davecode-provider", meta.provider).header("x-davecode-failovers", String(meta.failovers));
855
944
  }
@@ -879,7 +968,7 @@ function registerV1Routes(app, engine) {
879
968
  const parsed = chatRequestSchema.safeParse(request.body);
880
969
  if (!parsed.success) {
881
970
  return sendOpenAIError(reply, 400, {
882
- message: z7.prettifyError(parsed.error),
971
+ message: z8.prettifyError(parsed.error),
883
972
  type: "invalid_request_error",
884
973
  code: "invalid_body"
885
974
  });
@@ -1127,6 +1216,7 @@ async function buildGateway(engine, options = {}) {
1127
1216
  registerV1Routes(app, engine);
1128
1217
  registerAuthRoutes(app, login);
1129
1218
  registerAccountRoutes(app, options.account);
1219
+ registerOrchestratorRoutes(app, engine, options.orchestrator);
1130
1220
  registerApiRoutes(app, engine, options);
1131
1221
  registerEventRoutes(app, engine, options.heartbeatMs ?? 15e3);
1132
1222
  return app;
@@ -1629,6 +1719,23 @@ function wireProject(engine, root, options = {}) {
1629
1719
  lock
1630
1720
  };
1631
1721
  }
1722
+ function orchestratorWorktreesDir(home, projectDir) {
1723
+ const key = createHash("sha256").update(resolve2(projectDir)).digest("hex").slice(0, 16);
1724
+ return join(home, "worktrees", key);
1725
+ }
1726
+ function createProjectOrchestrator(options) {
1727
+ const projectDir = resolve2(options.projectDir);
1728
+ return createOrchestratorService({
1729
+ projectDir,
1730
+ home: options.home,
1731
+ events: options.events,
1732
+ runner: createCliAgentRunner({ env: options.env }),
1733
+ workspace: createGitWorkspace({
1734
+ projectDir,
1735
+ worktreesDir: orchestratorWorktreesDir(options.home, projectDir)
1736
+ })
1737
+ });
1738
+ }
1632
1739
  function isDashboard(dir) {
1633
1740
  return dir !== void 0 && existsSync3(join(dir, "index.html"));
1634
1741
  }
@@ -1666,6 +1773,7 @@ async function startRuntime(options) {
1666
1773
  ...options.config ? { config: options.config } : {}
1667
1774
  });
1668
1775
  let account;
1776
+ let orchestrator;
1669
1777
  try {
1670
1778
  const project = projectRoot ? wireProject(engine, projectRoot, { env: options.env }) : void 0;
1671
1779
  const wantDashboard = options.dashboard !== false && engine.config.server.dashboard;
@@ -1681,9 +1789,26 @@ async function startRuntime(options) {
1681
1789
  env: options.env,
1682
1790
  open: (url) => openBrowser(url)
1683
1791
  }) : void 0;
1792
+ if (options.orchestrator !== void 0) {
1793
+ orchestrator = options.orchestrator || void 0;
1794
+ } else if (projectRoot && LOOPBACK_HOSTS.has(bindHost)) {
1795
+ try {
1796
+ orchestrator = createProjectOrchestrator({
1797
+ projectDir: projectRoot,
1798
+ home: options.home,
1799
+ env: options.env,
1800
+ events: engine.events
1801
+ });
1802
+ } catch {
1803
+ const message = "The pane orchestrator could not start; continuing without it.";
1804
+ engine.events.emit({ type: "log", level: "warn", scope: "orchestrator", message });
1805
+ options.onWarning?.(message);
1806
+ }
1807
+ }
1684
1808
  const app = await startGateway(engine, {
1685
1809
  logger: options.logger ?? false,
1686
1810
  ...account ? { account } : {},
1811
+ ...orchestrator ? { orchestrator } : {},
1687
1812
  ...options.loginLauncher ?? loginLauncher ? { loginLauncher: options.loginLauncher ?? loginLauncher } : {},
1688
1813
  ...dashboardDir ? { dashboardDir } : {},
1689
1814
  ...project ? { brain: project.source, runner: project.runner, goals: project.goals } : {},
@@ -1702,6 +1827,7 @@ async function startRuntime(options) {
1702
1827
  project: project?.source.project(),
1703
1828
  runner,
1704
1829
  goals,
1830
+ orchestrator,
1705
1831
  url: `http://${connectHost(host)}:${port}`,
1706
1832
  host,
1707
1833
  port,
@@ -1713,6 +1839,7 @@ async function startRuntime(options) {
1713
1839
  const active = goals?.activeGoalId;
1714
1840
  if (active) await goals?.cancel(active);
1715
1841
  await runner?.stop();
1842
+ await orchestrator?.close().catch(() => void 0);
1716
1843
  await account?.close();
1717
1844
  await app.close();
1718
1845
  } finally {
@@ -1721,6 +1848,7 @@ async function startRuntime(options) {
1721
1848
  }
1722
1849
  };
1723
1850
  } catch (err) {
1851
+ await orchestrator?.close().catch(() => void 0);
1724
1852
  await account?.close();
1725
1853
  engine.close();
1726
1854
  throw err;
@@ -1740,8 +1868,10 @@ export {
1740
1868
  launchLoginTerminal,
1741
1869
  detectProjectRoot,
1742
1870
  wireProject,
1871
+ orchestratorWorktreesDir,
1872
+ createProjectOrchestrator,
1743
1873
  resolveDashboardDir,
1744
1874
  resolveProjectRoot,
1745
1875
  startRuntime
1746
1876
  };
1747
- //# sourceMappingURL=chunk-YSD6W27K.js.map
1877
+ //# sourceMappingURL=chunk-TP3ORSHY.js.map