@dmrlzz/davecode 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ChatApp-CJBICQGA.js → ChatApp-Z6PQIZ5J.js} +7 -6
- package/dist/{ChatApp-CJBICQGA.js.map → ChatApp-Z6PQIZ5J.js.map} +1 -1
- package/dist/{account-QWDPJWAA.js → account-RTPS2V6O.js} +4 -3
- package/dist/{accounts-IQMR72FC.js → accounts-IYQ4ZRL7.js} +6 -5
- package/dist/{budget-XANOUVWO.js → budget-N2ZB66FF.js} +5 -4
- package/dist/{budget-XANOUVWO.js.map → budget-N2ZB66FF.js.map} +1 -1
- package/dist/{chat-KDDRNC5V.js → chat-6TX6JX45.js} +9 -8
- package/dist/{chat-KDDRNC5V.js.map → chat-6TX6JX45.js.map} +1 -1
- package/dist/chunk-732GIHRQ.js +23 -0
- package/dist/chunk-732GIHRQ.js.map +1 -0
- package/dist/{chunk-AZKACMME.js → chunk-BJTXMET2.js} +2 -2
- package/dist/{chunk-FYPMA55O.js → chunk-KUY3QHGS.js} +239 -106
- package/dist/chunk-KUY3QHGS.js.map +1 -0
- package/dist/{chunk-JLATEHS7.js → chunk-LEU46DGH.js} +2 -2
- package/dist/{chunk-HSBJDV3O.js → chunk-QKY3OKVG.js} +309 -23
- package/dist/chunk-QKY3OKVG.js.map +1 -0
- package/dist/{chunk-WQ7MEWDF.js → chunk-UEV5K3DH.js} +10 -4
- package/dist/chunk-UEV5K3DH.js.map +1 -0
- package/dist/{chunk-44AFJL2X.js → chunk-UNK3EQD6.js} +6 -5
- package/dist/chunk-UNK3EQD6.js.map +1 -0
- package/dist/{chunk-W7GPBEBZ.js → chunk-WAARDGCZ.js} +5 -21
- package/dist/chunk-WAARDGCZ.js.map +1 -0
- package/dist/{chunk-PGAJIGUF.js → chunk-YNAMNQLW.js} +3 -3
- package/dist/{config-YTUPIYZT.js → config-YQKY2AA4.js} +4 -3
- package/dist/{config-YTUPIYZT.js.map → config-YQKY2AA4.js.map} +1 -1
- package/dist/dashboard/assets/Accounts-DXiGsutB.js +1 -0
- package/dist/dashboard/assets/{Badge-Z4RBdO9j.js → Badge-DUGKlx3Z.js} +1 -1
- package/dist/dashboard/assets/{Callout-w8BTYh4k.js → Callout-1E8Wsl9W.js} +1 -1
- package/dist/dashboard/assets/{Goals-Bw02to72.js → Goals-kL4VAxw3.js} +1 -1
- package/dist/dashboard/assets/{Library-DK7mlpRb.js → Library-DZxBVUo_.js} +1 -1
- package/dist/dashboard/assets/Markdown-CGgIydUh.js +71 -0
- package/dist/dashboard/assets/{Panes-_KTf8pbZ.js → Panes-C-TJekjs.js} +1 -1
- package/dist/dashboard/assets/{RoutesPage-QV0oPRW9.js → RoutesPage-DWYm9tW8.js} +1 -1
- package/dist/dashboard/assets/{Runner-CkHBLQl0.js → Runner-CmHBjECR.js} +1 -1
- package/dist/dashboard/assets/{Settings-BLz2gTBR.js → Settings-BANphxva.js} +1 -1
- package/dist/dashboard/assets/{Tasks-BiUQSTpt.js → Tasks-cSx1PKyQ.js} +1 -1
- package/dist/dashboard/assets/{Traffic-BVfBuC70.js → Traffic-DEAuM6jq.js} +1 -1
- package/dist/dashboard/assets/{Workspace-CJTgiiU5.js → Workspace-BQFjc1jH.js} +1 -1
- package/dist/dashboard/assets/index-B8kld9xo.js +104 -0
- package/dist/dashboard/assets/{task-errors-Daqwi0ue.js → task-errors-r-WYZ_S3.js} +1 -1
- package/dist/dashboard/index.html +2 -2
- package/dist/{dist-37VQSHHA.js → dist-PIC255RX.js} +20 -2
- package/dist/{doctor-PYUQRRCB.js → doctor-PQC7JQPP.js} +4 -3
- package/dist/{doctor-PYUQRRCB.js.map → doctor-PQC7JQPP.js.map} +1 -1
- package/dist/{goal-SXZUDUCL.js → goal-STLEU7C7.js} +4 -3
- package/dist/{goal-SXZUDUCL.js.map → goal-STLEU7C7.js.map} +1 -1
- package/dist/index.js +31 -31
- package/dist/{init-Z2AFQEEP.js → init-NHU5LJSS.js} +4 -3
- package/dist/{init-Z2AFQEEP.js.map → init-NHU5LJSS.js.map} +1 -1
- package/dist/{run-AOS7L3RT.js → run-7HWSHMRJ.js} +4 -3
- package/dist/{run-AOS7L3RT.js.map → run-7HWSHMRJ.js.map} +1 -1
- package/dist/runtime.js +3 -2
- package/dist/{start-CEPXKZUE.js → start-WVAEAQWL.js} +4 -3
- package/dist/{start-CEPXKZUE.js.map → start-WVAEAQWL.js.map} +1 -1
- package/dist/{status-WNJ3GGKU.js → status-ZRHPFLFT.js} +5 -4
- package/dist/{tasks-TFUTUMWB.js → tasks-JVWXUNXN.js} +5 -4
- package/dist/{tasks-TFUTUMWB.js.map → tasks-JVWXUNXN.js.map} +1 -1
- package/package.json +6 -6
- package/dist/chunk-44AFJL2X.js.map +0 -1
- package/dist/chunk-FYPMA55O.js.map +0 -1
- package/dist/chunk-HSBJDV3O.js.map +0 -1
- package/dist/chunk-W7GPBEBZ.js.map +0 -1
- package/dist/chunk-WQ7MEWDF.js.map +0 -1
- package/dist/dashboard/assets/Accounts-cq8RLMoI.js +0 -1
- package/dist/dashboard/assets/Markdown-DCZ4Awcc.js +0 -69
- package/dist/dashboard/assets/index-BDBa5cb0.js +0 -104
- /package/dist/{account-QWDPJWAA.js.map → account-RTPS2V6O.js.map} +0 -0
- /package/dist/{accounts-IQMR72FC.js.map → accounts-IYQ4ZRL7.js.map} +0 -0
- /package/dist/{chunk-AZKACMME.js.map → chunk-BJTXMET2.js.map} +0 -0
- /package/dist/{chunk-JLATEHS7.js.map → chunk-LEU46DGH.js.map} +0 -0
- /package/dist/{chunk-PGAJIGUF.js.map → chunk-YNAMNQLW.js.map} +0 -0
- /package/dist/{dist-37VQSHHA.js.map → dist-PIC255RX.js.map} +0 -0
- /package/dist/{status-WNJ3GGKU.js.map → status-ZRHPFLFT.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./cn-BwE4cei0.js";import{ft as t,pt as n}from"./Badge-
|
|
1
|
+
import{n as e}from"./cn-BwE4cei0.js";import{ft as t,pt as n}from"./Badge-DUGKlx3Z.js";var r={name:`pencil`,size:24,node:[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}],[`path`,{d:`m15 5 4 4`,key:`1mk7zo`}]]};r.node;var i=e(r);function a(e){if(!n(e))return t(e);switch(e.code){case`brain_read_only`:return`This gateway exposes the project brain read-only, so the task graph cannot be edited here.`;case`no_brain`:return`No project is loaded. Start the gateway inside an initialised project (davecode init).`;case`cycle`:return e.cycle?`That would create a dependency cycle: ${e.cycle.join(` → `)}.`:e.message;case`has_dependents`:return e.dependents?.length?`Other tasks still depend on it: ${e.dependents.join(`, `)}. Remove those dependencies first.`:e.message;case`task_in_progress`:return`The task is in progress. Reopen it before deleting it.`;case`duplicate_id`:return`A task with this id already exists.`;case`invalid_transition`:return`The task cannot move to that status from its current one. ${e.message}`;case`config_invalid`:return`The global config file is not valid, so it was left untouched. ${e.message}`;default:return t(e)}}export{i as n,a as t};
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
document.documentElement.dataset.theme = storedTheme;
|
|
21
21
|
}
|
|
22
22
|
</script>
|
|
23
|
-
<script type="module" crossorigin src="./assets/index-
|
|
23
|
+
<script type="module" crossorigin src="./assets/index-B8kld9xo.js"></script>
|
|
24
24
|
<link rel="modulepreload" crossorigin href="./assets/cn-BwE4cei0.js">
|
|
25
|
-
<link rel="modulepreload" crossorigin href="./assets/Badge-
|
|
25
|
+
<link rel="modulepreload" crossorigin href="./assets/Badge-DUGKlx3Z.js">
|
|
26
26
|
<link rel="stylesheet" crossorigin href="./assets/index-BEmBgsbP.css">
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ACCOUNT_SERVICE,
|
|
3
|
+
API_CONFIG_KEYS,
|
|
3
4
|
AccountClient,
|
|
4
5
|
AccountError,
|
|
5
6
|
AccountRepository,
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
DEFAULT_JEV_BASE_URL,
|
|
30
31
|
DEFAULT_JEV_MODEL,
|
|
31
32
|
DEFAULT_ROLES,
|
|
33
|
+
ENDPOINT_CONFIG_KEYS,
|
|
32
34
|
EXPERIMENTAL_PROVIDER_KINDS,
|
|
33
35
|
EventBus,
|
|
34
36
|
ExecutorAbortedError,
|
|
@@ -62,6 +64,7 @@ import {
|
|
|
62
64
|
OAUTH_PROVIDERS,
|
|
63
65
|
OpenAICompatibleProvider,
|
|
64
66
|
OpenAIProvider,
|
|
67
|
+
PROJECT_SETTABLE_KEYS,
|
|
65
68
|
PROVIDER_KINDS,
|
|
66
69
|
PathEscapeError,
|
|
67
70
|
ProjectBrain,
|
|
@@ -97,6 +100,7 @@ import {
|
|
|
97
100
|
accountServes,
|
|
98
101
|
accountService,
|
|
99
102
|
addTask,
|
|
103
|
+
apiConfigIssues,
|
|
100
104
|
applySafetyGuard,
|
|
101
105
|
approximateTokens,
|
|
102
106
|
assertSafeRef,
|
|
@@ -111,6 +115,7 @@ import {
|
|
|
111
115
|
configuredModels,
|
|
112
116
|
connectionMethod,
|
|
113
117
|
countTextTokens,
|
|
118
|
+
createAccountControl,
|
|
114
119
|
createEngine,
|
|
115
120
|
createExecutor,
|
|
116
121
|
createGoalService,
|
|
@@ -121,10 +126,13 @@ import {
|
|
|
121
126
|
deepMerge,
|
|
122
127
|
defaultModelFor,
|
|
123
128
|
dependentsOf,
|
|
129
|
+
endpointChanged,
|
|
130
|
+
endpointRebindIssue,
|
|
124
131
|
envLayer,
|
|
125
132
|
errorKindFromStatus,
|
|
126
133
|
estimateTokens2,
|
|
127
134
|
extractJsonObject,
|
|
135
|
+
filterProjectLayer,
|
|
128
136
|
findCycles,
|
|
129
137
|
findProjectRoot,
|
|
130
138
|
geminiCliEnv,
|
|
@@ -144,6 +152,7 @@ import {
|
|
|
144
152
|
loginCommandFor,
|
|
145
153
|
loginEnv,
|
|
146
154
|
loginFromEnv,
|
|
155
|
+
mergeApiConfig,
|
|
147
156
|
migrate,
|
|
148
157
|
newId2,
|
|
149
158
|
nextTask,
|
|
@@ -186,9 +195,10 @@ import {
|
|
|
186
195
|
validateTaskGraph,
|
|
187
196
|
withFileLock,
|
|
188
197
|
writeGlobalRouting
|
|
189
|
-
} from "./chunk-
|
|
198
|
+
} from "./chunk-QKY3OKVG.js";
|
|
190
199
|
export {
|
|
191
200
|
ACCOUNT_SERVICE,
|
|
201
|
+
API_CONFIG_KEYS,
|
|
192
202
|
AccountClient,
|
|
193
203
|
AccountError,
|
|
194
204
|
AccountRepository,
|
|
@@ -218,6 +228,7 @@ export {
|
|
|
218
228
|
DEFAULT_JEV_BASE_URL,
|
|
219
229
|
DEFAULT_JEV_MODEL,
|
|
220
230
|
DEFAULT_ROLES,
|
|
231
|
+
ENDPOINT_CONFIG_KEYS,
|
|
221
232
|
EXPERIMENTAL_PROVIDER_KINDS,
|
|
222
233
|
EventBus,
|
|
223
234
|
ExecutorAbortedError,
|
|
@@ -251,6 +262,7 @@ export {
|
|
|
251
262
|
OAUTH_PROVIDERS,
|
|
252
263
|
OpenAICompatibleProvider,
|
|
253
264
|
OpenAIProvider,
|
|
265
|
+
PROJECT_SETTABLE_KEYS,
|
|
254
266
|
PROVIDER_KINDS,
|
|
255
267
|
PathEscapeError,
|
|
256
268
|
ProjectBrain,
|
|
@@ -286,6 +298,7 @@ export {
|
|
|
286
298
|
accountServes,
|
|
287
299
|
accountService,
|
|
288
300
|
addTask,
|
|
301
|
+
apiConfigIssues,
|
|
289
302
|
applySafetyGuard,
|
|
290
303
|
approximateTokens,
|
|
291
304
|
assertSafeRef,
|
|
@@ -300,6 +313,7 @@ export {
|
|
|
300
313
|
configuredModels,
|
|
301
314
|
connectionMethod,
|
|
302
315
|
countTextTokens,
|
|
316
|
+
createAccountControl,
|
|
303
317
|
createEngine,
|
|
304
318
|
createExecutor,
|
|
305
319
|
createGoalService,
|
|
@@ -310,10 +324,13 @@ export {
|
|
|
310
324
|
deepMerge,
|
|
311
325
|
defaultModelFor,
|
|
312
326
|
dependentsOf,
|
|
327
|
+
endpointChanged,
|
|
328
|
+
endpointRebindIssue,
|
|
313
329
|
envLayer,
|
|
314
330
|
errorKindFromStatus,
|
|
315
331
|
estimateTokens2 as estimateTokens,
|
|
316
332
|
extractJsonObject,
|
|
333
|
+
filterProjectLayer,
|
|
317
334
|
findCycles,
|
|
318
335
|
findProjectRoot,
|
|
319
336
|
geminiCliEnv,
|
|
@@ -333,6 +350,7 @@ export {
|
|
|
333
350
|
loginCommandFor,
|
|
334
351
|
loginEnv,
|
|
335
352
|
loginFromEnv,
|
|
353
|
+
mergeApiConfig,
|
|
336
354
|
migrate,
|
|
337
355
|
newId2 as newId,
|
|
338
356
|
nextTask,
|
|
@@ -376,4 +394,4 @@ export {
|
|
|
376
394
|
withFileLock,
|
|
377
395
|
writeGlobalRouting
|
|
378
396
|
};
|
|
379
|
-
//# sourceMappingURL=dist-
|
|
397
|
+
//# sourceMappingURL=dist-PIC255RX.js.map
|
|
@@ -10,14 +10,15 @@ import {
|
|
|
10
10
|
detectProjectRoot,
|
|
11
11
|
resolveDashboardDir,
|
|
12
12
|
which
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-KUY3QHGS.js";
|
|
14
14
|
import {
|
|
15
15
|
EXIT
|
|
16
16
|
} from "./chunk-7XVXEO7U.js";
|
|
17
|
+
import "./chunk-732GIHRQ.js";
|
|
17
18
|
import {
|
|
18
19
|
loadConfig,
|
|
19
20
|
openDatabase
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-QKY3OKVG.js";
|
|
21
22
|
import "./chunk-MC7RIPL7.js";
|
|
22
23
|
|
|
23
24
|
// src/commands/doctor.ts
|
|
@@ -276,4 +277,4 @@ export {
|
|
|
276
277
|
renderDoctor,
|
|
277
278
|
runDoctor
|
|
278
279
|
};
|
|
279
|
-
//# sourceMappingURL=doctor-
|
|
280
|
+
//# sourceMappingURL=doctor-PQC7JQPP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { join } from 'node:path';\nimport { type DaveConfig, loadConfig, openDatabase } from '@davecode/core';\nimport { connectHost, GatewayClient } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { EXIT } from '../errors';\nimport { which } from '../lib/proc';\nimport { detectProjectRoot, resolveDashboardDir } from '../runtime';\nimport { padEnd } from '../ui/format';\n\nexport type CheckStatus = 'ok' | 'warn' | 'fail';\n\nexport interface CheckResult {\n id: string;\n label: string;\n status: CheckStatus;\n detail: string;\n fix?: string;\n}\n\n/** Everything doctor touches outside its own logic, injectable for tests. */\nexport interface DoctorProbes {\n nodeVersion: string;\n loadConfig(): DaveConfig;\n /** Open an in-memory database; resolves with a detail string. */\n loadSqlite(): Promise<string>;\n /** Throws when `dir` cannot be created or written. */\n checkWritable(dir: string): Promise<void>;\n exists(path: string): boolean;\n portInUse(host: string, port: number): Promise<boolean>;\n /** Version of the DaveCode gateway answering on `baseUrl`, if any. */\n gatewayVersion(baseUrl: string, token?: string): Promise<string | undefined>;\n which(command: string): string | undefined;\n /** True when `url` answers with any HTTP response within the timeout. */\n reachable(url: string): Promise<boolean>;\n dashboardDir(): string | undefined;\n}\n\nexport interface DoctorInput {\n home: string;\n env: NodeJS.ProcessEnv;\n}\n\nconst MIN_NODE: [number, number] = [22, 12];\n\nexport function nodeVersionOk(version: string): boolean {\n const [major = 0, minor = 0] = version.replace(/^v/, '').split('.').map(Number);\n return major > MIN_NODE[0] || (major === MIN_NODE[0] && minor >= MIN_NODE[1]);\n}\n\nexport async function runDoctor(input: DoctorInput, probes: DoctorProbes): Promise<CheckResult[]> {\n const results: CheckResult[] = [];\n const add = (r: CheckResult) => results.push(r);\n\n add(\n nodeVersionOk(probes.nodeVersion)\n ? { id: 'node', label: 'Node.js', status: 'ok', detail: probes.nodeVersion }\n : {\n id: 'node',\n label: 'Node.js',\n status: 'fail',\n detail: `${probes.nodeVersion} (needs ${MIN_NODE.join('.')}+)`,\n fix: 'Install Node.js 22.12 or newer: https://nodejs.org',\n },\n );\n\n let config: DaveConfig | undefined;\n try {\n config = probes.loadConfig();\n add({ id: 'config', label: 'Config', status: 'ok', detail: 'valid' });\n } catch (err) {\n add({\n id: 'config',\n label: 'Config',\n status: 'fail',\n detail: (err as Error).message.split('\\n').slice(0, 3).join(' '),\n fix: 'Fix the file named above; `davecode config path` lists every config location.',\n });\n }\n\n try {\n add({ id: 'sqlite', label: 'better-sqlite3', status: 'ok', detail: await probes.loadSqlite() });\n } catch (err) {\n add({\n id: 'sqlite',\n label: 'better-sqlite3',\n status: 'fail',\n detail: `cannot load: ${(err as Error).message.split('\\n')[0]}`,\n fix: 'Rebuild the native module: pnpm rebuild better-sqlite3 (needs a C++ toolchain if no prebuilt binary matches your Node version).',\n });\n }\n\n try {\n await probes.checkWritable(input.home);\n add({ id: 'home', label: 'Home directory', status: 'ok', detail: `${input.home} is writable` });\n } catch (err) {\n add({\n id: 'home',\n label: 'Home directory',\n status: 'fail',\n detail: `${input.home} is not writable (${(err as NodeJS.ErrnoException).code ?? (err as Error).message})`,\n fix: 'Fix the permissions or point DaveCode elsewhere with --home <dir> / DAVECODE_HOME.',\n });\n }\n\n const keyPath = join(input.home, 'master.key');\n if (input.env.DAVECODE_MASTER_KEY) {\n add({\n id: 'master-key',\n label: 'Master key',\n status: 'ok',\n detail: 'from DAVECODE_MASTER_KEY',\n });\n } else if (probes.exists(keyPath)) {\n add({ id: 'master-key', label: 'Master key', status: 'ok', detail: keyPath });\n } else {\n add({\n id: 'master-key',\n label: 'Master key',\n status: 'warn',\n detail: 'not created yet',\n fix: 'It is generated on first use (davecode start or accounts add). Back it up: without it stored secrets cannot be decrypted.',\n });\n }\n\n if (config) {\n const { host, port, authToken } = config.server;\n const baseUrl = `http://${connectHost(host)}:${port}`;\n if (!(await probes.portInUse(host, port))) {\n add({ id: 'port', label: 'Gateway port', status: 'ok', detail: `${host}:${port} is free` });\n } else {\n const version = await probes.gatewayVersion(baseUrl, authToken);\n add(\n version\n ? {\n id: 'port',\n label: 'Gateway port',\n status: 'ok',\n detail: `DaveCode ${version} is already running at ${baseUrl}`,\n }\n : {\n id: 'port',\n label: 'Gateway port',\n status: 'fail',\n detail: `${host}:${port} is used by another program`,\n fix: `Stop it, or use another port: davecode start --port ${port + 1} (or DAVECODE_PORT).`,\n },\n );\n }\n }\n\n const tools: Array<{ cmd: string; label: string; required: boolean; why: string; fix: string }> =\n [\n {\n cmd: 'git',\n label: 'git',\n required: true,\n why: 'needed by the autonomous runner (task branches and merges)',\n fix: 'Install git: https://git-scm.com/downloads',\n },\n {\n cmd: 'claude',\n label: 'Claude Code CLI',\n required: false,\n why: 'only for claude-cli accounts',\n fix: 'npm install -g @anthropic-ai/claude-code',\n },\n {\n cmd: 'codex',\n label: 'Codex CLI',\n required: false,\n why: 'only for codex-cli accounts',\n fix: 'npm install -g @openai/codex',\n },\n {\n cmd: 'gemini',\n label: 'Gemini CLI',\n required: false,\n why: 'only for gemini-cli accounts',\n fix: 'npm install -g @google/gemini-cli',\n },\n {\n cmd: 'gh',\n label: 'GitHub CLI',\n required: false,\n why: 'optional, for opening pull requests',\n fix: 'Install gh: https://cli.github.com',\n },\n ];\n for (const tool of tools) {\n const path = probes.which(tool.cmd);\n add(\n path\n ? { id: tool.cmd, label: tool.label, status: 'ok', detail: path }\n : {\n id: tool.cmd,\n label: tool.label,\n status: tool.required ? 'fail' : 'warn',\n detail: `not found on PATH (${tool.why})`,\n fix: tool.fix,\n },\n );\n }\n\n const dashboard = probes.dashboardDir();\n add(\n dashboard\n ? { id: 'dashboard', label: 'Dashboard build', status: 'ok', detail: dashboard }\n : {\n id: 'dashboard',\n label: 'Dashboard build',\n status: 'warn',\n detail: 'not built (the gateway still works without it)',\n fix: 'pnpm --filter @davecode/ui build',\n },\n );\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Real probes\n// ---------------------------------------------------------------------------\n\nfunction portInUse(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer();\n server.once('error', (err: NodeJS.ErrnoException) => {\n resolve(err.code === 'EADDRINUSE' || err.code === 'EACCES');\n });\n server.listen({ host, port, exclusive: true }, () => {\n server.close(() => resolve(false));\n });\n });\n}\n\nexport function defaultProbes(\n ctx: Pick<CliContext, 'home' | 'env'>,\n projectRoot?: string,\n): DoctorProbes {\n return {\n nodeVersion: process.version,\n loadConfig: () =>\n loadConfig({ home: ctx.home, env: ctx.env, ...(projectRoot ? { projectRoot } : {}) }),\n async loadSqlite() {\n const db = openDatabase(':memory:');\n try {\n const row = db.prepare('select sqlite_version() as v').get() as { v: string };\n return `loads (SQLite ${row.v})`;\n } finally {\n db.close();\n }\n },\n async checkWritable(dir) {\n await mkdir(dir, { recursive: true });\n const probe = join(dir, `.doctor-${process.pid}.tmp`);\n await writeFile(probe, 'ok');\n await rm(probe, { force: true });\n },\n exists: existsSync,\n portInUse,\n async gatewayVersion(baseUrl, token) {\n const client = new GatewayClient({ baseUrl, ...(token ? { token } : {}) });\n try {\n return (await client.health(800))?.version;\n } catch {\n return undefined;\n }\n },\n which: (cmd) => which(cmd, ctx.env),\n async reachable(url) {\n try {\n await fetch(url, { signal: AbortSignal.timeout(800) });\n return true;\n } catch {\n return false;\n }\n },\n dashboardDir: () => resolveDashboardDir(ctx.env),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Command\n// ---------------------------------------------------------------------------\n\nexport function renderDoctor(ctx: Pick<CliContext, 'theme'>, results: CheckResult[]): string[] {\n const { theme } = ctx;\n const lines = [theme.bold(theme.accent('DaveCode doctor')), ''];\n const width = Math.max(...results.map((r) => r.label.length)) + 2;\n for (const r of results) {\n const mark =\n r.status === 'ok'\n ? theme.ok(theme.glyph.ok)\n : r.status === 'warn'\n ? theme.warn(theme.glyph.warn)\n : theme.error(theme.glyph.fail);\n const detail = r.status === 'ok' ? theme.dim(r.detail) : r.detail;\n lines.push(` ${mark} ${padEnd(r.label, width)} ${detail}`);\n if (r.fix && r.status !== 'ok')\n lines.push(` ${' '.repeat(width)}${theme.dim(`fix: ${r.fix}`)}`);\n }\n const count = (s: CheckStatus) => results.filter((r) => r.status === s).length;\n const fails = count('fail');\n const warns = count('warn');\n lines.push('');\n lines.push(\n [\n theme.ok(`${count('ok')} ok`),\n warns ? theme.warn(`${warns} warning${warns === 1 ? '' : 's'}`) : `${warns} warnings`,\n fails ? theme.error(`${fails} failure${fails === 1 ? '' : 's'}`) : '0 failures',\n ].join(theme.dim(' · ')),\n );\n return lines;\n}\n\nexport async function doctorCommand(\n ctx: CliContext,\n probes?: Partial<DoctorProbes>,\n): Promise<number> {\n const projectRoot = await detectProjectRoot(ctx.cwd, ctx.home);\n const merged: DoctorProbes = { ...defaultProbes(ctx, projectRoot), ...probes };\n const results = await runDoctor({ home: ctx.home, env: ctx.env }, merged);\n const failed = results.some((r) => r.status === 'fail');\n if (ctx.json) {\n printJson(ctx, { ok: !failed, checks: results });\n } else {\n for (const line of renderDoctor(ctx, results)) ctx.out(line);\n }\n return failed ? EXIT.failure : EXIT.ok;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, rm, writeFile } from 'node:fs/promises';\nimport { createServer } from 'node:net';\nimport { join } from 'node:path';\nimport { type DaveConfig, loadConfig, openDatabase } from '@davecode/core';\nimport { connectHost, GatewayClient } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { EXIT } from '../errors';\nimport { which } from '../lib/proc';\nimport { detectProjectRoot, resolveDashboardDir } from '../runtime';\nimport { padEnd } from '../ui/format';\n\nexport type CheckStatus = 'ok' | 'warn' | 'fail';\n\nexport interface CheckResult {\n id: string;\n label: string;\n status: CheckStatus;\n detail: string;\n fix?: string;\n}\n\n/** Everything doctor touches outside its own logic, injectable for tests. */\nexport interface DoctorProbes {\n nodeVersion: string;\n loadConfig(): DaveConfig;\n /** Open an in-memory database; resolves with a detail string. */\n loadSqlite(): Promise<string>;\n /** Throws when `dir` cannot be created or written. */\n checkWritable(dir: string): Promise<void>;\n exists(path: string): boolean;\n portInUse(host: string, port: number): Promise<boolean>;\n /** Version of the DaveCode gateway answering on `baseUrl`, if any. */\n gatewayVersion(baseUrl: string, token?: string): Promise<string | undefined>;\n which(command: string): string | undefined;\n /** True when `url` answers with any HTTP response within the timeout. */\n reachable(url: string): Promise<boolean>;\n dashboardDir(): string | undefined;\n}\n\nexport interface DoctorInput {\n home: string;\n env: NodeJS.ProcessEnv;\n}\n\nconst MIN_NODE: [number, number] = [22, 12];\n\nexport function nodeVersionOk(version: string): boolean {\n const [major = 0, minor = 0] = version.replace(/^v/, '').split('.').map(Number);\n return major > MIN_NODE[0] || (major === MIN_NODE[0] && minor >= MIN_NODE[1]);\n}\n\nexport async function runDoctor(input: DoctorInput, probes: DoctorProbes): Promise<CheckResult[]> {\n const results: CheckResult[] = [];\n const add = (r: CheckResult) => results.push(r);\n\n add(\n nodeVersionOk(probes.nodeVersion)\n ? { id: 'node', label: 'Node.js', status: 'ok', detail: probes.nodeVersion }\n : {\n id: 'node',\n label: 'Node.js',\n status: 'fail',\n detail: `${probes.nodeVersion} (needs ${MIN_NODE.join('.')}+)`,\n fix: 'Install Node.js 22.12 or newer: https://nodejs.org',\n },\n );\n\n let config: DaveConfig | undefined;\n try {\n config = probes.loadConfig();\n add({ id: 'config', label: 'Config', status: 'ok', detail: 'valid' });\n } catch (err) {\n add({\n id: 'config',\n label: 'Config',\n status: 'fail',\n detail: (err as Error).message.split('\\n').slice(0, 3).join(' '),\n fix: 'Fix the file named above; `davecode config path` lists every config location.',\n });\n }\n\n try {\n add({ id: 'sqlite', label: 'better-sqlite3', status: 'ok', detail: await probes.loadSqlite() });\n } catch (err) {\n add({\n id: 'sqlite',\n label: 'better-sqlite3',\n status: 'fail',\n detail: `cannot load: ${(err as Error).message.split('\\n')[0]}`,\n fix: 'Rebuild the native module: pnpm rebuild better-sqlite3 (needs a C++ toolchain if no prebuilt binary matches your Node version).',\n });\n }\n\n try {\n await probes.checkWritable(input.home);\n add({ id: 'home', label: 'Home directory', status: 'ok', detail: `${input.home} is writable` });\n } catch (err) {\n add({\n id: 'home',\n label: 'Home directory',\n status: 'fail',\n detail: `${input.home} is not writable (${(err as NodeJS.ErrnoException).code ?? (err as Error).message})`,\n fix: 'Fix the permissions or point DaveCode elsewhere with --home <dir> / DAVECODE_HOME.',\n });\n }\n\n const keyPath = join(input.home, 'master.key');\n if (input.env.DAVECODE_MASTER_KEY) {\n add({\n id: 'master-key',\n label: 'Master key',\n status: 'ok',\n detail: 'from DAVECODE_MASTER_KEY',\n });\n } else if (probes.exists(keyPath)) {\n add({ id: 'master-key', label: 'Master key', status: 'ok', detail: keyPath });\n } else {\n add({\n id: 'master-key',\n label: 'Master key',\n status: 'warn',\n detail: 'not created yet',\n fix: 'It is generated on first use (davecode start or accounts add). Back it up: without it stored secrets cannot be decrypted.',\n });\n }\n\n if (config) {\n const { host, port, authToken } = config.server;\n const baseUrl = `http://${connectHost(host)}:${port}`;\n if (!(await probes.portInUse(host, port))) {\n add({ id: 'port', label: 'Gateway port', status: 'ok', detail: `${host}:${port} is free` });\n } else {\n const version = await probes.gatewayVersion(baseUrl, authToken);\n add(\n version\n ? {\n id: 'port',\n label: 'Gateway port',\n status: 'ok',\n detail: `DaveCode ${version} is already running at ${baseUrl}`,\n }\n : {\n id: 'port',\n label: 'Gateway port',\n status: 'fail',\n detail: `${host}:${port} is used by another program`,\n fix: `Stop it, or use another port: davecode start --port ${port + 1} (or DAVECODE_PORT).`,\n },\n );\n }\n }\n\n const tools: Array<{ cmd: string; label: string; required: boolean; why: string; fix: string }> =\n [\n {\n cmd: 'git',\n label: 'git',\n required: true,\n why: 'needed by the autonomous runner (task branches and merges)',\n fix: 'Install git: https://git-scm.com/downloads',\n },\n {\n cmd: 'claude',\n label: 'Claude Code CLI',\n required: false,\n why: 'only for claude-cli accounts',\n fix: 'npm install -g @anthropic-ai/claude-code',\n },\n {\n cmd: 'codex',\n label: 'Codex CLI',\n required: false,\n why: 'only for codex-cli accounts',\n fix: 'npm install -g @openai/codex',\n },\n {\n cmd: 'gemini',\n label: 'Gemini CLI',\n required: false,\n why: 'only for gemini-cli accounts',\n fix: 'npm install -g @google/gemini-cli',\n },\n {\n cmd: 'gh',\n label: 'GitHub CLI',\n required: false,\n why: 'optional, for opening pull requests',\n fix: 'Install gh: https://cli.github.com',\n },\n ];\n for (const tool of tools) {\n const path = probes.which(tool.cmd);\n add(\n path\n ? { id: tool.cmd, label: tool.label, status: 'ok', detail: path }\n : {\n id: tool.cmd,\n label: tool.label,\n status: tool.required ? 'fail' : 'warn',\n detail: `not found on PATH (${tool.why})`,\n fix: tool.fix,\n },\n );\n }\n\n const dashboard = probes.dashboardDir();\n add(\n dashboard\n ? { id: 'dashboard', label: 'Dashboard build', status: 'ok', detail: dashboard }\n : {\n id: 'dashboard',\n label: 'Dashboard build',\n status: 'warn',\n detail: 'not built (the gateway still works without it)',\n fix: 'pnpm --filter @davecode/ui build',\n },\n );\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Real probes\n// ---------------------------------------------------------------------------\n\nfunction portInUse(host: string, port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = createServer();\n server.once('error', (err: NodeJS.ErrnoException) => {\n resolve(err.code === 'EADDRINUSE' || err.code === 'EACCES');\n });\n server.listen({ host, port, exclusive: true }, () => {\n server.close(() => resolve(false));\n });\n });\n}\n\nexport function defaultProbes(\n ctx: Pick<CliContext, 'home' | 'env'>,\n projectRoot?: string,\n): DoctorProbes {\n return {\n nodeVersion: process.version,\n loadConfig: () =>\n loadConfig({ home: ctx.home, env: ctx.env, ...(projectRoot ? { projectRoot } : {}) }),\n async loadSqlite() {\n const db = openDatabase(':memory:');\n try {\n const row = db.prepare('select sqlite_version() as v').get() as { v: string };\n return `loads (SQLite ${row.v})`;\n } finally {\n db.close();\n }\n },\n async checkWritable(dir) {\n await mkdir(dir, { recursive: true });\n const probe = join(dir, `.doctor-${process.pid}.tmp`);\n await writeFile(probe, 'ok');\n await rm(probe, { force: true });\n },\n exists: existsSync,\n portInUse,\n async gatewayVersion(baseUrl, token) {\n const client = new GatewayClient({ baseUrl, ...(token ? { token } : {}) });\n try {\n return (await client.health(800))?.version;\n } catch {\n return undefined;\n }\n },\n which: (cmd) => which(cmd, ctx.env),\n async reachable(url) {\n try {\n await fetch(url, { signal: AbortSignal.timeout(800) });\n return true;\n } catch {\n return false;\n }\n },\n dashboardDir: () => resolveDashboardDir(ctx.env),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Command\n// ---------------------------------------------------------------------------\n\nexport function renderDoctor(ctx: Pick<CliContext, 'theme'>, results: CheckResult[]): string[] {\n const { theme } = ctx;\n const lines = [theme.bold(theme.accent('DaveCode doctor')), ''];\n const width = Math.max(...results.map((r) => r.label.length)) + 2;\n for (const r of results) {\n const mark =\n r.status === 'ok'\n ? theme.ok(theme.glyph.ok)\n : r.status === 'warn'\n ? theme.warn(theme.glyph.warn)\n : theme.error(theme.glyph.fail);\n const detail = r.status === 'ok' ? theme.dim(r.detail) : r.detail;\n lines.push(` ${mark} ${padEnd(r.label, width)} ${detail}`);\n if (r.fix && r.status !== 'ok')\n lines.push(` ${' '.repeat(width)}${theme.dim(`fix: ${r.fix}`)}`);\n }\n const count = (s: CheckStatus) => results.filter((r) => r.status === s).length;\n const fails = count('fail');\n const warns = count('warn');\n lines.push('');\n lines.push(\n [\n theme.ok(`${count('ok')} ok`),\n warns ? theme.warn(`${warns} warning${warns === 1 ? '' : 's'}`) : `${warns} warnings`,\n fails ? theme.error(`${fails} failure${fails === 1 ? '' : 's'}`) : '0 failures',\n ].join(theme.dim(' · ')),\n );\n return lines;\n}\n\nexport async function doctorCommand(\n ctx: CliContext,\n probes?: Partial<DoctorProbes>,\n): Promise<number> {\n const projectRoot = await detectProjectRoot(ctx.cwd, ctx.home);\n const merged: DoctorProbes = { ...defaultProbes(ctx, projectRoot), ...probes };\n const results = await runDoctor({ home: ctx.home, env: ctx.env }, merged);\n const failed = results.some((r) => r.status === 'fail');\n if (ctx.json) {\n printJson(ctx, { ok: !failed, checks: results });\n } else {\n for (const line of renderDoctor(ctx, results)) ctx.out(line);\n }\n return failed ? EXIT.failure : EXIT.ok;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -9,17 +9,18 @@ import {
|
|
|
9
9
|
detectProjectRoot,
|
|
10
10
|
findGateway,
|
|
11
11
|
wireProject
|
|
12
|
-
} from "./chunk-
|
|
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
|
GoalStore,
|
|
19
20
|
createEngine,
|
|
20
21
|
isTerminalGoal,
|
|
21
22
|
loadConfig
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-QKY3OKVG.js";
|
|
23
24
|
import "./chunk-MC7RIPL7.js";
|
|
24
25
|
|
|
25
26
|
// src/commands/goal.ts
|
|
@@ -299,4 +300,4 @@ export {
|
|
|
299
300
|
goalsList,
|
|
300
301
|
goalsShow
|
|
301
302
|
};
|
|
302
|
-
//# sourceMappingURL=goal-
|
|
303
|
+
//# sourceMappingURL=goal-STLEU7C7.js.map
|
|
@@ -1 +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\nfunction interruptSignal(deps: GoalDeps): { promise: Promise<void>; dispose(): void } {\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":[]}
|
|
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\nfunction interruptSignal(deps: GoalDeps): { promise: Promise<void>; dispose(): void } {\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":[]}
|