@dmrlzz/davecode 0.0.0-stage → 0.4.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.
- package/LICENSE +21 -0
- package/README.md +34 -2
- package/bin/davecode.js +2 -0
- package/dist/ChatApp-BO7QMBWD.js +1045 -0
- package/dist/ChatApp-BO7QMBWD.js.map +1 -0
- package/dist/RunnerView-A7JSPUW5.js +18 -0
- package/dist/RunnerView-A7JSPUW5.js.map +1 -0
- package/dist/account-UGNLJPQ4.js +23 -0
- package/dist/account-UGNLJPQ4.js.map +1 -0
- package/dist/accounts-NM7IWP53.js +37 -0
- package/dist/accounts-NM7IWP53.js.map +1 -0
- package/dist/budget-INAW6FXD.js +115 -0
- package/dist/budget-INAW6FXD.js.map +1 -0
- package/dist/chat-U4QJQ7M6.js +359 -0
- package/dist/chat-U4QJQ7M6.js.map +1 -0
- package/dist/chunk-3Q2KCXLN.js +9608 -0
- package/dist/chunk-3Q2KCXLN.js.map +1 -0
- package/dist/chunk-5LKOJBUL.js +20 -0
- package/dist/chunk-5LKOJBUL.js.map +1 -0
- package/dist/chunk-7XVXEO7U.js +23 -0
- package/dist/chunk-7XVXEO7U.js.map +1 -0
- package/dist/chunk-CWBVNS3L.js +731 -0
- package/dist/chunk-CWBVNS3L.js.map +1 -0
- package/dist/chunk-DZ2FDABF.js +1614 -0
- package/dist/chunk-DZ2FDABF.js.map +1 -0
- package/dist/chunk-FRFSJMN4.js +79 -0
- package/dist/chunk-FRFSJMN4.js.map +1 -0
- package/dist/chunk-GE22VBCY.js +200 -0
- package/dist/chunk-GE22VBCY.js.map +1 -0
- package/dist/chunk-GHDOUII5.js +144 -0
- package/dist/chunk-GHDOUII5.js.map +1 -0
- package/dist/chunk-GZJ6JSO7.js +213 -0
- package/dist/chunk-GZJ6JSO7.js.map +1 -0
- package/dist/chunk-IC3TDONV.js +12 -0
- package/dist/chunk-IC3TDONV.js.map +1 -0
- package/dist/chunk-MC7RIPL7.js +116 -0
- package/dist/chunk-MC7RIPL7.js.map +1 -0
- package/dist/chunk-MOK5D3XJ.js +114 -0
- package/dist/chunk-MOK5D3XJ.js.map +1 -0
- package/dist/chunk-PGPXE6LF.js +20 -0
- package/dist/chunk-PGPXE6LF.js.map +1 -0
- package/dist/chunk-QA3O6RA2.js +81 -0
- package/dist/chunk-QA3O6RA2.js.map +1 -0
- package/dist/chunk-ROIUTNQV.js +20 -0
- package/dist/chunk-ROIUTNQV.js.map +1 -0
- package/dist/chunk-SF5ZEAP4.js +105 -0
- package/dist/chunk-SF5ZEAP4.js.map +1 -0
- package/dist/chunk-Z6NQDJEN.js +180 -0
- package/dist/chunk-Z6NQDJEN.js.map +1 -0
- package/dist/config-YEAPBMBX.js +158 -0
- package/dist/config-YEAPBMBX.js.map +1 -0
- package/dist/dashboard/assets/Accounts-CeVyX4a3.js +1 -0
- package/dist/dashboard/assets/Badge-CGY6DgGx.js +55 -0
- package/dist/dashboard/assets/Callout-DauCk_cW.js +1 -0
- package/dist/dashboard/assets/Field-OXMnT9Tb.js +1 -0
- package/dist/dashboard/assets/Goals-DH-KDh8M.js +1 -0
- package/dist/dashboard/assets/Library-C15szLjZ.js +1 -0
- package/dist/dashboard/assets/Markdown-Xhao3sgL.js +69 -0
- package/dist/dashboard/assets/Panel-Du40pM7n.js +1 -0
- package/dist/dashboard/assets/RoutesPage-Cj1OelGO.js +4 -0
- package/dist/dashboard/assets/Runner-BK1-ZF7h.js +1 -0
- package/dist/dashboard/assets/Settings-C1nzQQhe.js +1 -0
- package/dist/dashboard/assets/Switch-bwtIJ00H.js +1 -0
- package/dist/dashboard/assets/Tasks-x4s8IiPG.js +2 -0
- package/dist/dashboard/assets/Traffic-CV7TaTid.js +1 -0
- package/dist/dashboard/assets/Workspace-DAL-MBc0.js +1 -0
- package/dist/dashboard/assets/arrow-up-goM9r-I9.js +1 -0
- package/dist/dashboard/assets/forms-DtpfI65-.js +1 -0
- package/dist/dashboard/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/dist/dashboard/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/dist/dashboard/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/dist/dashboard/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
- package/dist/dashboard/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
- package/dist/dashboard/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/dist/dashboard/assets/index-BCi-Vuvh.js +104 -0
- package/dist/dashboard/assets/index-CcJFhc98.css +2 -0
- package/dist/dashboard/assets/task-errors-B2pgjUGN.js +1 -0
- package/dist/dashboard/assets/trash-BVojETtF.js +1 -0
- package/dist/dashboard/favicon.svg +1 -0
- package/dist/dashboard/github.svg +1 -0
- package/dist/dashboard/index.html +31 -0
- package/dist/dist-RRQGUBL3.js +379 -0
- package/dist/dist-RRQGUBL3.js.map +1 -0
- package/dist/doctor-MQYK44S2.js +279 -0
- package/dist/doctor-MQYK44S2.js.map +1 -0
- package/dist/goal-6NUX4AIT.js +302 -0
- package/dist/goal-6NUX4AIT.js.map +1 -0
- package/dist/index.js +399 -0
- package/dist/index.js.map +1 -0
- package/dist/init-AXYIWAB3.js +194 -0
- package/dist/init-AXYIWAB3.js.map +1 -0
- package/dist/prompts-TZ7UC42M.js +219 -0
- package/dist/prompts-TZ7UC42M.js.map +1 -0
- package/dist/run-QRTLHFB3.js +376 -0
- package/dist/run-QRTLHFB3.js.map +1 -0
- package/dist/runner-state-QFU3LJVJ.js +17 -0
- package/dist/runner-state-QFU3LJVJ.js.map +1 -0
- package/dist/runtime.js +18 -0
- package/dist/runtime.js.map +1 -0
- package/dist/start-O5I5TSO2.js +285 -0
- package/dist/start-O5I5TSO2.js.map +1 -0
- package/dist/status-LEA3RVUX.js +25 -0
- package/dist/status-LEA3RVUX.js.map +1 -0
- package/dist/tasks-XOTVICVZ.js +184 -0
- package/dist/tasks-XOTVICVZ.js.map +1 -0
- package/package.json +73 -3
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatTokens,
|
|
3
|
+
padEnd
|
|
4
|
+
} from "./chunk-SF5ZEAP4.js";
|
|
5
|
+
import {
|
|
6
|
+
printJson
|
|
7
|
+
} from "./chunk-QA3O6RA2.js";
|
|
8
|
+
import {
|
|
9
|
+
detectProjectRoot,
|
|
10
|
+
findGateway,
|
|
11
|
+
startRuntime,
|
|
12
|
+
which
|
|
13
|
+
} from "./chunk-DZ2FDABF.js";
|
|
14
|
+
import {
|
|
15
|
+
CliError,
|
|
16
|
+
EXIT
|
|
17
|
+
} from "./chunk-7XVXEO7U.js";
|
|
18
|
+
import {
|
|
19
|
+
VERSION,
|
|
20
|
+
loadConfig,
|
|
21
|
+
summarize
|
|
22
|
+
} from "./chunk-3Q2KCXLN.js";
|
|
23
|
+
import "./chunk-MC7RIPL7.js";
|
|
24
|
+
|
|
25
|
+
// src/commands/start.ts
|
|
26
|
+
import { existsSync } from "fs";
|
|
27
|
+
import { resolve } from "path";
|
|
28
|
+
|
|
29
|
+
// src/lib/app-window.ts
|
|
30
|
+
import { spawn } from "child_process";
|
|
31
|
+
import { join } from "path";
|
|
32
|
+
async function openAppWindow(url, env = process.env) {
|
|
33
|
+
const target = new URL(url);
|
|
34
|
+
if (!["http:", "https:"].includes(target.protocol) || !["127.0.0.1", "localhost", "[::1]"].includes(target.hostname) || target.username || target.password || target.search || target.hash)
|
|
35
|
+
throw new Error("App windows require a loopback workspace URL without credentials.");
|
|
36
|
+
const win = process.platform === "win32";
|
|
37
|
+
const candidates = win ? [
|
|
38
|
+
join(
|
|
39
|
+
env["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)",
|
|
40
|
+
"Microsoft",
|
|
41
|
+
"Edge",
|
|
42
|
+
"Application",
|
|
43
|
+
"msedge.exe"
|
|
44
|
+
),
|
|
45
|
+
join(
|
|
46
|
+
env.ProgramFiles ?? "C:\\Program Files",
|
|
47
|
+
"Google",
|
|
48
|
+
"Chrome",
|
|
49
|
+
"Application",
|
|
50
|
+
"chrome.exe"
|
|
51
|
+
),
|
|
52
|
+
...env.LOCALAPPDATA ? [
|
|
53
|
+
join(env.LOCALAPPDATA, "Microsoft", "Edge", "Application", "msedge.exe"),
|
|
54
|
+
join(env.LOCALAPPDATA, "Google", "Chrome", "Application", "chrome.exe")
|
|
55
|
+
] : []
|
|
56
|
+
] : process.platform === "darwin" ? [
|
|
57
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
58
|
+
"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge"
|
|
59
|
+
] : ["google-chrome", "chromium", "chromium-browser", "microsoft-edge"];
|
|
60
|
+
const executable = candidates.map((candidate) => which(candidate, env)).find(Boolean);
|
|
61
|
+
if (!executable) return false;
|
|
62
|
+
return new Promise((resolve2) => {
|
|
63
|
+
const child = spawn(executable, [`--app=${target.origin}/`], {
|
|
64
|
+
env,
|
|
65
|
+
shell: false,
|
|
66
|
+
windowsHide: true,
|
|
67
|
+
detached: true,
|
|
68
|
+
stdio: "ignore"
|
|
69
|
+
});
|
|
70
|
+
child.once("error", () => resolve2(false));
|
|
71
|
+
child.once("spawn", () => {
|
|
72
|
+
child.unref();
|
|
73
|
+
resolve2(true);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/lib/summary.ts
|
|
79
|
+
function summarizeAccounts(accounts) {
|
|
80
|
+
if (accounts.length === 0) return "none";
|
|
81
|
+
const enabled = accounts.filter((a) => a.enabled);
|
|
82
|
+
const byProvider = /* @__PURE__ */ new Map();
|
|
83
|
+
for (const account of enabled) {
|
|
84
|
+
byProvider.set(account.provider, (byProvider.get(account.provider) ?? 0) + 1);
|
|
85
|
+
}
|
|
86
|
+
const parts = [...byProvider.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([provider, n]) => `${provider} ${n}`);
|
|
87
|
+
const head = enabled.length === accounts.length ? `${accounts.length} enabled` : `${enabled.length} enabled of ${accounts.length}`;
|
|
88
|
+
const problems = accounts.filter((a) => a.status === "error" || a.status === "cooldown").length;
|
|
89
|
+
return [head, ...parts, ...problems > 0 ? [`${problems} need attention`] : []].join(" \xB7 ");
|
|
90
|
+
}
|
|
91
|
+
function runtimeWarnings(config, host) {
|
|
92
|
+
const warnings = [];
|
|
93
|
+
if (config.experimental.geminiWeb) {
|
|
94
|
+
warnings.push(
|
|
95
|
+
"experimental.geminiWeb is ON: automating the Gemini web app may violate Google\u2019s Terms of Service."
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (config.experimental.multiAccountRotation) {
|
|
99
|
+
warnings.push(
|
|
100
|
+
"experimental.multiAccountRotation is ON: rotating subscription logins may violate provider terms."
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
const loopback = ["127.0.0.1", "::1", "localhost"].includes(host);
|
|
104
|
+
if (!loopback && !config.server.authToken) {
|
|
105
|
+
warnings.push(
|
|
106
|
+
`Listening on ${host} without server.authToken: anyone on your network can use your accounts.`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
return warnings;
|
|
110
|
+
}
|
|
111
|
+
function clock(ts) {
|
|
112
|
+
return new Date(ts).toTimeString().slice(0, 8);
|
|
113
|
+
}
|
|
114
|
+
function formatEventLine(theme, event, labelOf = (id) => id) {
|
|
115
|
+
const time = theme.dim(clock(event.ts));
|
|
116
|
+
switch (event.type) {
|
|
117
|
+
case "request.completed": {
|
|
118
|
+
const tokens = formatTokens(event.promptTokens + event.completionTokens);
|
|
119
|
+
return `${time} ${theme.ok(theme.glyph.ok)} ${event.model} ${theme.dim(
|
|
120
|
+
`${labelOf(event.accountId)} \xB7 ${tokens} tok \xB7 ${event.latencyMs}ms`
|
|
121
|
+
)}`;
|
|
122
|
+
}
|
|
123
|
+
case "request.failed":
|
|
124
|
+
return `${time} ${theme.error(theme.glyph.fail)} ${labelOf(event.accountId)} ${theme.dim(
|
|
125
|
+
`${event.error.kind}${event.error.status ? ` ${event.error.status}` : ""}: ${event.error.message}`
|
|
126
|
+
)}`;
|
|
127
|
+
case "router.failover":
|
|
128
|
+
return `${time} ${theme.warn(theme.glyph.arrow)} failover ${labelOf(event.fromAccountId)} ${theme.glyph.arrow} ${event.toAccountId ? labelOf(event.toAccountId) : "none"} ${theme.dim(event.reason)}`;
|
|
129
|
+
case "account.removed":
|
|
130
|
+
return `${time} ${theme.dim(`account ${event.accountId} removed`)}`;
|
|
131
|
+
case "runner.status":
|
|
132
|
+
return `${time} ${theme.accent("runner")} ${event.status.state}${event.status.taskId ? theme.dim(` \xB7 ${event.status.taskId}`) : ""}`;
|
|
133
|
+
case "runner.log":
|
|
134
|
+
return `${time} ${theme.dim(`[${event.level}]`)} ${event.message}`;
|
|
135
|
+
case "log":
|
|
136
|
+
return event.level === "warn" || event.level === "error" ? `${time} ${event.level === "error" ? theme.error(event.level) : theme.warn(event.level)} ${theme.dim(event.scope)} ${event.message}` : void 0;
|
|
137
|
+
default:
|
|
138
|
+
return void 0;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/commands/start.ts
|
|
143
|
+
async function readGraphQuietly(brain) {
|
|
144
|
+
try {
|
|
145
|
+
return await brain.isInitialised() ? await brain.readGraph() : void 0;
|
|
146
|
+
} catch {
|
|
147
|
+
return void 0;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function waitForSignal() {
|
|
151
|
+
return new Promise((resolve2) => {
|
|
152
|
+
const done = () => {
|
|
153
|
+
process.off("SIGINT", done);
|
|
154
|
+
process.off("SIGTERM", done);
|
|
155
|
+
resolve2();
|
|
156
|
+
};
|
|
157
|
+
process.on("SIGINT", done);
|
|
158
|
+
process.on("SIGTERM", done);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async function startCommand(ctx, opts, deps = {}) {
|
|
162
|
+
const started = performance.now();
|
|
163
|
+
const projectRoot = opts.project ? resolve(ctx.cwd, opts.project) : await detectProjectRoot(ctx.cwd, ctx.home);
|
|
164
|
+
if (projectRoot && opts.project && !existsSync(projectRoot)) {
|
|
165
|
+
throw new CliError(`Project directory not found: ${projectRoot}`);
|
|
166
|
+
}
|
|
167
|
+
const config = loadConfig({
|
|
168
|
+
home: ctx.home,
|
|
169
|
+
env: ctx.env,
|
|
170
|
+
...projectRoot ? { projectRoot } : {}
|
|
171
|
+
});
|
|
172
|
+
const port = opts.port ?? config.server.port;
|
|
173
|
+
if (port !== 0) {
|
|
174
|
+
const running = await findGateway(config, { port }).catch(() => void 0);
|
|
175
|
+
if (running) {
|
|
176
|
+
throw new CliError(`A DaveCode gateway is already running at ${running.client.baseUrl}`, {
|
|
177
|
+
hint: "Use `davecode status` to inspect it, or pick another port with --port."
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
let runtime;
|
|
182
|
+
try {
|
|
183
|
+
runtime = await startRuntime({
|
|
184
|
+
home: ctx.home,
|
|
185
|
+
env: ctx.env,
|
|
186
|
+
cwd: ctx.cwd,
|
|
187
|
+
...projectRoot ? { projectDir: projectRoot } : { noProject: true },
|
|
188
|
+
...opts.host !== void 0 ? { host: opts.host } : {},
|
|
189
|
+
port,
|
|
190
|
+
dashboard: opts.dashboard !== false,
|
|
191
|
+
...opts.verbose ? { logger: { level: config.logLevel } } : {}
|
|
192
|
+
});
|
|
193
|
+
} catch (err) {
|
|
194
|
+
const code = err.code;
|
|
195
|
+
if (code === "EADDRINUSE") {
|
|
196
|
+
throw new CliError(`Port ${port} is already in use`, {
|
|
197
|
+
hint: "Stop the other process or choose a port: davecode start --port 4041"
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
if (code === "EACCES") {
|
|
201
|
+
throw new CliError(`Permission denied binding ${opts.host ?? config.server.host}:${port}`, {
|
|
202
|
+
hint: "Use a port above 1024 or another --host."
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
const { engine } = runtime;
|
|
208
|
+
if (opts.app && !ctx.json) {
|
|
209
|
+
const opened = runtime.dashboardDir ? await openAppWindow(runtime.url, ctx.env).catch(() => false) : false;
|
|
210
|
+
if (!opened)
|
|
211
|
+
ctx.err(
|
|
212
|
+
`Open ${runtime.url}/ in your browser. An installed Chrome or Edge enables an app window.`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
const accounts = engine.accounts.list();
|
|
216
|
+
const warnings = runtimeWarnings(engine.config, runtime.host);
|
|
217
|
+
const graph = runtime.brain ? await readGraphQuietly(runtime.brain) : void 0;
|
|
218
|
+
if (ctx.json) {
|
|
219
|
+
printJson(ctx, {
|
|
220
|
+
status: "running",
|
|
221
|
+
version: VERSION,
|
|
222
|
+
url: runtime.url,
|
|
223
|
+
api: `${runtime.url}/v1`,
|
|
224
|
+
dashboard: runtime.dashboardDir ? `${runtime.url}/` : null,
|
|
225
|
+
project: runtime.project ?? null,
|
|
226
|
+
accounts: accounts.length,
|
|
227
|
+
warnings
|
|
228
|
+
});
|
|
229
|
+
} else {
|
|
230
|
+
const { theme } = ctx;
|
|
231
|
+
const ms = Math.round(performance.now() - started);
|
|
232
|
+
const row = (label, value) => ctx.out(` ${theme.dim(padEnd(label, 10))} ${value}`);
|
|
233
|
+
ctx.out();
|
|
234
|
+
ctx.out(
|
|
235
|
+
` ${theme.bold(theme.accent("DaveCode"))} ${theme.dim(`v${VERSION} \xB7 ready in ${ms}ms`)}`
|
|
236
|
+
);
|
|
237
|
+
ctx.out();
|
|
238
|
+
row("API", theme.accent(`${runtime.url}/v1`));
|
|
239
|
+
row(
|
|
240
|
+
"Dashboard",
|
|
241
|
+
runtime.dashboardDir ? theme.accent(`${runtime.url}/`) : theme.dim(
|
|
242
|
+
opts.dashboard === false || !engine.config.server.dashboard ? "disabled" : "not built (pnpm --filter @davecode/ui build)"
|
|
243
|
+
)
|
|
244
|
+
);
|
|
245
|
+
row("Events", theme.dim(`${runtime.url}/api/events`));
|
|
246
|
+
if (runtime.project) {
|
|
247
|
+
const done = graph ? summarize(graph) : void 0;
|
|
248
|
+
const progress = done ? theme.dim(` \xB7 ${done.counts.SUCCESS}/${done.total} tasks done`) : theme.dim(" \xB7 no brain yet (davecode init)");
|
|
249
|
+
row("Project", `${runtime.project.name}${progress}`);
|
|
250
|
+
if (runtime.runner) {
|
|
251
|
+
row(
|
|
252
|
+
"Runner",
|
|
253
|
+
`${runtime.runner.status().state}${theme.dim(" \xB7 start it from the dashboard or with `davecode run`")}`
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
} else {
|
|
257
|
+
row("Project", theme.dim("none (run inside a git repository)"));
|
|
258
|
+
}
|
|
259
|
+
row(
|
|
260
|
+
"Accounts",
|
|
261
|
+
accounts.length > 0 ? summarizeAccounts(accounts) : theme.warn("none yet: run `davecode accounts add`")
|
|
262
|
+
);
|
|
263
|
+
for (const warning of warnings) ctx.out(` ${theme.warn(`${theme.glyph.warn} ${warning}`)}`);
|
|
264
|
+
ctx.out();
|
|
265
|
+
ctx.out(theme.dim(" Press Ctrl+C to stop."));
|
|
266
|
+
ctx.out();
|
|
267
|
+
}
|
|
268
|
+
let unsubscribe;
|
|
269
|
+
if (!ctx.json && !opts.quiet && !opts.verbose) {
|
|
270
|
+
const labelOf = (id) => engine.accounts.get(id)?.label ?? id;
|
|
271
|
+
unsubscribe = engine.events.subscribe((event) => {
|
|
272
|
+
const line = formatEventLine(ctx.theme, event, labelOf);
|
|
273
|
+
if (line) ctx.out(` ${line}`);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
await (deps.until ?? waitForSignal)(runtime);
|
|
277
|
+
unsubscribe?.();
|
|
278
|
+
if (!ctx.json) ctx.out(ctx.theme.dim(" Stopping DaveCode\u2026"));
|
|
279
|
+
await runtime.close();
|
|
280
|
+
return EXIT.ok;
|
|
281
|
+
}
|
|
282
|
+
export {
|
|
283
|
+
startCommand
|
|
284
|
+
};
|
|
285
|
+
//# sourceMappingURL=start-O5I5TSO2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/start.ts","../src/lib/app-window.ts","../src/lib/summary.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { loadConfig, type ProjectBrain, summarize, type TaskGraph, VERSION } from '@davecode/core';\nimport { findGateway } from '../client';\nimport { type CliContext, printJson } from '../context';\nimport { CliError, EXIT } from '../errors';\nimport { openAppWindow } from '../lib/app-window';\nimport { formatEventLine, runtimeWarnings, summarizeAccounts } from '../lib/summary';\nimport { detectProjectRoot, type Runtime, startRuntime } from '../runtime';\nimport { padEnd } from '../ui/format';\n\nexport interface StartOptions {\n app?: boolean;\n port?: number;\n host?: string;\n /** commander's `--no-dashboard` sets this to false. */\n dashboard?: boolean;\n project?: string;\n verbose?: boolean;\n quiet?: boolean;\n}\n\nexport interface StartDeps {\n /** Resolves when the gateway should stop (default: SIGINT/SIGTERM). */\n until?: (runtime: Runtime) => Promise<void>;\n}\n\nasync function readGraphQuietly(brain: ProjectBrain): Promise<TaskGraph | undefined> {\n try {\n return (await brain.isInitialised()) ? await brain.readGraph() : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction waitForSignal(): Promise<void> {\n return new Promise((resolve) => {\n const done = () => {\n process.off('SIGINT', done);\n process.off('SIGTERM', done);\n resolve();\n };\n process.on('SIGINT', done);\n process.on('SIGTERM', done);\n });\n}\n\nexport async function startCommand(\n ctx: CliContext,\n opts: StartOptions,\n deps: StartDeps = {},\n): Promise<number> {\n const started = performance.now();\n const projectRoot = opts.project\n ? resolve(ctx.cwd, opts.project)\n : await detectProjectRoot(ctx.cwd, ctx.home);\n if (projectRoot && opts.project && !existsSync(projectRoot)) {\n throw new CliError(`Project directory not found: ${projectRoot}`);\n }\n const config = loadConfig({\n home: ctx.home,\n env: ctx.env,\n ...(projectRoot ? { projectRoot } : {}),\n });\n const port = opts.port ?? config.server.port;\n\n if (port !== 0) {\n const running = await findGateway(config, { port }).catch(() => undefined);\n if (running) {\n throw new CliError(`A DaveCode gateway is already running at ${running.client.baseUrl}`, {\n hint: 'Use `davecode status` to inspect it, or pick another port with --port.',\n });\n }\n }\n\n let runtime: Runtime;\n try {\n runtime = await startRuntime({\n home: ctx.home,\n env: ctx.env,\n cwd: ctx.cwd,\n ...(projectRoot ? { projectDir: projectRoot } : { noProject: true }),\n ...(opts.host !== undefined ? { host: opts.host } : {}),\n port,\n dashboard: opts.dashboard !== false,\n ...(opts.verbose ? { logger: { level: config.logLevel } } : {}),\n });\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'EADDRINUSE') {\n throw new CliError(`Port ${port} is already in use`, {\n hint: 'Stop the other process or choose a port: davecode start --port 4041',\n });\n }\n if (code === 'EACCES') {\n throw new CliError(`Permission denied binding ${opts.host ?? config.server.host}:${port}`, {\n hint: 'Use a port above 1024 or another --host.',\n });\n }\n throw err;\n }\n\n const { engine } = runtime;\n if (opts.app && !ctx.json) {\n const opened = runtime.dashboardDir\n ? await openAppWindow(runtime.url, ctx.env).catch(() => false)\n : false;\n if (!opened)\n ctx.err(\n `Open ${runtime.url}/ in your browser. An installed Chrome or Edge enables an app window.`,\n );\n }\n const accounts = engine.accounts.list();\n const warnings = runtimeWarnings(engine.config, runtime.host);\n const graph = runtime.brain ? await readGraphQuietly(runtime.brain) : undefined;\n\n if (ctx.json) {\n printJson(ctx, {\n status: 'running',\n version: VERSION,\n url: runtime.url,\n api: `${runtime.url}/v1`,\n dashboard: runtime.dashboardDir ? `${runtime.url}/` : null,\n project: runtime.project ?? null,\n accounts: accounts.length,\n warnings,\n });\n } else {\n const { theme } = ctx;\n const ms = Math.round(performance.now() - started);\n const row = (label: string, value: string) =>\n ctx.out(` ${theme.dim(padEnd(label, 10))} ${value}`);\n ctx.out();\n ctx.out(\n ` ${theme.bold(theme.accent('DaveCode'))} ${theme.dim(`v${VERSION} · ready in ${ms}ms`)}`,\n );\n ctx.out();\n row('API', theme.accent(`${runtime.url}/v1`));\n row(\n 'Dashboard',\n runtime.dashboardDir\n ? theme.accent(`${runtime.url}/`)\n : theme.dim(\n opts.dashboard === false || !engine.config.server.dashboard\n ? 'disabled'\n : 'not built (pnpm --filter @davecode/ui build)',\n ),\n );\n row('Events', theme.dim(`${runtime.url}/api/events`));\n if (runtime.project) {\n const done = graph ? summarize(graph) : undefined;\n const progress = done\n ? theme.dim(` · ${done.counts.SUCCESS}/${done.total} tasks done`)\n : theme.dim(' · no brain yet (davecode init)');\n row('Project', `${runtime.project.name}${progress}`);\n if (runtime.runner) {\n row(\n 'Runner',\n `${runtime.runner.status().state}${theme.dim(' · start it from the dashboard or with `davecode run`')}`,\n );\n }\n } else {\n row('Project', theme.dim('none (run inside a git repository)'));\n }\n row(\n 'Accounts',\n accounts.length > 0\n ? summarizeAccounts(accounts)\n : theme.warn('none yet: run `davecode accounts add`'),\n );\n for (const warning of warnings) ctx.out(` ${theme.warn(`${theme.glyph.warn} ${warning}`)}`);\n ctx.out();\n ctx.out(theme.dim(' Press Ctrl+C to stop.'));\n ctx.out();\n }\n\n let unsubscribe: (() => void) | undefined;\n if (!ctx.json && !opts.quiet && !opts.verbose) {\n const labelOf = (id: string) => engine.accounts.get(id)?.label ?? id;\n unsubscribe = engine.events.subscribe((event) => {\n const line = formatEventLine(ctx.theme, event, labelOf);\n if (line) ctx.out(` ${line}`);\n });\n }\n\n await (deps.until ?? waitForSignal)(runtime);\n unsubscribe?.();\n if (!ctx.json) ctx.out(ctx.theme.dim(' Stopping DaveCode…'));\n await runtime.close();\n return EXIT.ok;\n}\n","import { spawn } from 'node:child_process';\nimport { join } from 'node:path';\nimport { which } from './proc';\n\n/** Open only a loopback workspace, without a shell or credentials in the URL. */\nexport async function openAppWindow(\n url: string,\n env: NodeJS.ProcessEnv = process.env,\n): Promise<boolean> {\n const target = new URL(url);\n if (\n !['http:', 'https:'].includes(target.protocol) ||\n !['127.0.0.1', 'localhost', '[::1]'].includes(target.hostname) ||\n target.username ||\n target.password ||\n target.search ||\n target.hash\n )\n throw new Error('App windows require a loopback workspace URL without credentials.');\n const win = process.platform === 'win32';\n const candidates = win\n ? [\n join(\n env['ProgramFiles(x86)'] ?? 'C:\\\\Program Files (x86)',\n 'Microsoft',\n 'Edge',\n 'Application',\n 'msedge.exe',\n ),\n join(\n env.ProgramFiles ?? 'C:\\\\Program Files',\n 'Google',\n 'Chrome',\n 'Application',\n 'chrome.exe',\n ),\n ...(env.LOCALAPPDATA\n ? [\n join(env.LOCALAPPDATA, 'Microsoft', 'Edge', 'Application', 'msedge.exe'),\n join(env.LOCALAPPDATA, 'Google', 'Chrome', 'Application', 'chrome.exe'),\n ]\n : []),\n ]\n : process.platform === 'darwin'\n ? [\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n ]\n : ['google-chrome', 'chromium', 'chromium-browser', 'microsoft-edge'];\n const executable = candidates.map((candidate) => which(candidate, env)).find(Boolean);\n if (!executable) return false;\n return new Promise((resolve) => {\n const child = spawn(executable, [`--app=${target.origin}/`], {\n env,\n shell: false,\n windowsHide: true,\n detached: true,\n stdio: 'ignore',\n });\n child.once('error', () => resolve(false));\n child.once('spawn', () => {\n child.unref();\n resolve(true);\n });\n });\n}\n","import type { Account, DaveConfig, DaveEvent } from '@davecode/core';\nimport { formatTokens } from '../ui/format';\nimport type { Theme } from '../ui/theme';\n\n/** One-line accounts summary, e.g. `3 enabled of 4 · anthropic 1 · claude-cli 2`. */\nexport function summarizeAccounts(accounts: Account[]): string {\n if (accounts.length === 0) return 'none';\n const enabled = accounts.filter((a) => a.enabled);\n const byProvider = new Map<string, number>();\n for (const account of enabled) {\n byProvider.set(account.provider, (byProvider.get(account.provider) ?? 0) + 1);\n }\n const parts = [...byProvider.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([provider, n]) => `${provider} ${n}`);\n const head =\n enabled.length === accounts.length\n ? `${accounts.length} enabled`\n : `${enabled.length} enabled of ${accounts.length}`;\n const problems = accounts.filter((a) => a.status === 'error' || a.status === 'cooldown').length;\n return [head, ...parts, ...(problems > 0 ? [`${problems} need attention`] : [])].join(' · ');\n}\n\n/** Warnings for Terms-of-Service-sensitive flags and risky bindings. */\nexport function runtimeWarnings(config: DaveConfig, host: string): string[] {\n const warnings: string[] = [];\n if (config.experimental.geminiWeb) {\n warnings.push(\n 'experimental.geminiWeb is ON: automating the Gemini web app may violate Google’s Terms of Service.',\n );\n }\n if (config.experimental.multiAccountRotation) {\n warnings.push(\n 'experimental.multiAccountRotation is ON: rotating subscription logins may violate provider terms.',\n );\n }\n const loopback = ['127.0.0.1', '::1', 'localhost'].includes(host);\n if (!loopback && !config.server.authToken) {\n warnings.push(\n `Listening on ${host} without server.authToken: anyone on your network can use your accounts.`,\n );\n }\n return warnings;\n}\n\nfunction clock(ts: number): string {\n return new Date(ts).toTimeString().slice(0, 8);\n}\n\n/**\n * Compact activity line for `davecode start`, or `undefined` for events that are not worth a\n * line (quota ticks, request starts). Account ids are shown by label when known.\n */\nexport function formatEventLine(\n theme: Theme,\n event: DaveEvent,\n labelOf: (accountId: string) => string = (id) => id,\n): string | undefined {\n const time = theme.dim(clock(event.ts));\n switch (event.type) {\n case 'request.completed': {\n const tokens = formatTokens(event.promptTokens + event.completionTokens);\n return `${time} ${theme.ok(theme.glyph.ok)} ${event.model} ${theme.dim(\n `${labelOf(event.accountId)} · ${tokens} tok · ${event.latencyMs}ms`,\n )}`;\n }\n case 'request.failed':\n return `${time} ${theme.error(theme.glyph.fail)} ${labelOf(event.accountId)} ${theme.dim(\n `${event.error.kind}${event.error.status ? ` ${event.error.status}` : ''}: ${event.error.message}`,\n )}`;\n case 'router.failover':\n return `${time} ${theme.warn(theme.glyph.arrow)} failover ${labelOf(event.fromAccountId)} ${\n theme.glyph.arrow\n } ${event.toAccountId ? labelOf(event.toAccountId) : 'none'} ${theme.dim(event.reason)}`;\n case 'account.removed':\n return `${time} ${theme.dim(`account ${event.accountId} removed`)}`;\n case 'runner.status':\n return `${time} ${theme.accent('runner')} ${event.status.state}${\n event.status.taskId ? theme.dim(` · ${event.status.taskId}`) : ''\n }`;\n case 'runner.log':\n return `${time} ${theme.dim(`[${event.level}]`)} ${event.message}`;\n case 'log':\n return event.level === 'warn' || event.level === 'error'\n ? `${time} ${event.level === 'error' ? theme.error(event.level) : theme.warn(event.level)} ${theme.dim(event.scope)} ${event.message}`\n : undefined;\n default:\n return undefined;\n }\n}\n"],"mappings":"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","names":["resolve","resolve"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
emptyUsage,
|
|
3
|
+
gatherStatus,
|
|
4
|
+
localStatus,
|
|
5
|
+
renderAccounts,
|
|
6
|
+
renderStatus,
|
|
7
|
+
statusCommand,
|
|
8
|
+
windowCell
|
|
9
|
+
} from "./chunk-GZJ6JSO7.js";
|
|
10
|
+
import "./chunk-SF5ZEAP4.js";
|
|
11
|
+
import "./chunk-QA3O6RA2.js";
|
|
12
|
+
import "./chunk-DZ2FDABF.js";
|
|
13
|
+
import "./chunk-7XVXEO7U.js";
|
|
14
|
+
import "./chunk-3Q2KCXLN.js";
|
|
15
|
+
import "./chunk-MC7RIPL7.js";
|
|
16
|
+
export {
|
|
17
|
+
emptyUsage,
|
|
18
|
+
gatherStatus,
|
|
19
|
+
localStatus,
|
|
20
|
+
renderAccounts,
|
|
21
|
+
renderStatus,
|
|
22
|
+
statusCommand,
|
|
23
|
+
windowCell
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=status-LEA3RVUX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatTaskDetail,
|
|
3
|
+
formatTaskTree,
|
|
4
|
+
summaryLine
|
|
5
|
+
} from "./chunk-MOK5D3XJ.js";
|
|
6
|
+
import "./chunk-SF5ZEAP4.js";
|
|
7
|
+
import {
|
|
8
|
+
printJson
|
|
9
|
+
} from "./chunk-QA3O6RA2.js";
|
|
10
|
+
import {
|
|
11
|
+
detectProjectRoot
|
|
12
|
+
} from "./chunk-DZ2FDABF.js";
|
|
13
|
+
import {
|
|
14
|
+
CliError,
|
|
15
|
+
EXIT
|
|
16
|
+
} from "./chunk-7XVXEO7U.js";
|
|
17
|
+
import {
|
|
18
|
+
ProjectBrain,
|
|
19
|
+
TASK_STATUSES,
|
|
20
|
+
TaskGraphError,
|
|
21
|
+
blockedTasks,
|
|
22
|
+
nextTask,
|
|
23
|
+
parseTaskGraph,
|
|
24
|
+
summarize
|
|
25
|
+
} from "./chunk-3Q2KCXLN.js";
|
|
26
|
+
import "./chunk-MC7RIPL7.js";
|
|
27
|
+
|
|
28
|
+
// src/commands/tasks.ts
|
|
29
|
+
import { rename, writeFile } from "fs/promises";
|
|
30
|
+
import { basename } from "path";
|
|
31
|
+
async function openBrain(ctx) {
|
|
32
|
+
const root = await detectProjectRoot(ctx.cwd, ctx.home);
|
|
33
|
+
const brain = root ? new ProjectBrain(root) : void 0;
|
|
34
|
+
if (!brain || !await brain.isInitialised()) {
|
|
35
|
+
throw new CliError("No project brain here", {
|
|
36
|
+
hint: "Run `davecode init` in your repository first."
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return brain;
|
|
40
|
+
}
|
|
41
|
+
async function graphErrors(fn) {
|
|
42
|
+
try {
|
|
43
|
+
return await fn();
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err instanceof TaskGraphError) {
|
|
46
|
+
throw new CliError(err.issues.map((i) => i.message).join("\n"), {
|
|
47
|
+
hint: "TASK_GRAPH.json was left unchanged."
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function tasksList(ctx) {
|
|
54
|
+
const brain = await openBrain(ctx);
|
|
55
|
+
const graph = await graphErrors(() => brain.readGraph());
|
|
56
|
+
if (ctx.json) {
|
|
57
|
+
printJson(ctx, {
|
|
58
|
+
root: brain.root,
|
|
59
|
+
summary: summarize(graph),
|
|
60
|
+
next: nextTask(graph)?.id ?? null,
|
|
61
|
+
blocked: blockedTasks(graph).map((b) => ({
|
|
62
|
+
id: b.task.id,
|
|
63
|
+
reason: b.reason,
|
|
64
|
+
blockedBy: b.blockedBy
|
|
65
|
+
})),
|
|
66
|
+
graph
|
|
67
|
+
});
|
|
68
|
+
return EXIT.ok;
|
|
69
|
+
}
|
|
70
|
+
const { theme } = ctx;
|
|
71
|
+
ctx.out(`${theme.bold(theme.accent("Tasks"))} ${theme.dim(basename(brain.root))}`);
|
|
72
|
+
if (graph.tasks.length > 0) ctx.out(summaryLine(theme, graph));
|
|
73
|
+
ctx.out();
|
|
74
|
+
for (const line of formatTaskTree(theme, graph, { width: ctx.columns })) ctx.out(line);
|
|
75
|
+
if (graph.tasks.length === 0) {
|
|
76
|
+
ctx.out(`Add one with ${theme.accent('davecode tasks add <id> "<title>"')}.`);
|
|
77
|
+
}
|
|
78
|
+
return EXIT.ok;
|
|
79
|
+
}
|
|
80
|
+
async function tasksNext(ctx) {
|
|
81
|
+
const brain = await openBrain(ctx);
|
|
82
|
+
const graph = await graphErrors(() => brain.readGraph());
|
|
83
|
+
const task = nextTask(graph);
|
|
84
|
+
if (ctx.json) {
|
|
85
|
+
printJson(ctx, { next: task ?? null });
|
|
86
|
+
return EXIT.ok;
|
|
87
|
+
}
|
|
88
|
+
if (!task) {
|
|
89
|
+
const blocked = blockedTasks(graph);
|
|
90
|
+
const running = graph.tasks.filter((t) => t.status === "IN_PROGRESS");
|
|
91
|
+
ctx.out(ctx.theme.dim("Nothing is ready to run."));
|
|
92
|
+
for (const t of running) ctx.out(` ${ctx.theme.accent(t.id)} is in progress`);
|
|
93
|
+
for (const b of blocked) {
|
|
94
|
+
ctx.out(
|
|
95
|
+
` ${b.task.id} ${ctx.theme.dim(
|
|
96
|
+
b.reason === "failed-dependency" ? `blocked: ${b.blockedBy.join(", ")} failed` : `waiting on ${b.blockedBy.join(", ")}`
|
|
97
|
+
)}`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
return EXIT.ok;
|
|
101
|
+
}
|
|
102
|
+
for (const line of formatTaskDetail(ctx.theme, task)) ctx.out(line);
|
|
103
|
+
return EXIT.ok;
|
|
104
|
+
}
|
|
105
|
+
async function tasksAdd(ctx, id, titleWords, opts) {
|
|
106
|
+
const title = titleWords.join(" ").trim();
|
|
107
|
+
if (!title) throw new CliError("A task needs a title: davecode tasks add <id> <title\u2026>");
|
|
108
|
+
const brain = await openBrain(ctx);
|
|
109
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
110
|
+
const task = {
|
|
111
|
+
id,
|
|
112
|
+
title,
|
|
113
|
+
status: "PENDING",
|
|
114
|
+
dependsOn: opts.depends ?? [],
|
|
115
|
+
createdAt: now,
|
|
116
|
+
updatedAt: now
|
|
117
|
+
};
|
|
118
|
+
if (opts.priority !== void 0) task.priority = opts.priority;
|
|
119
|
+
if (opts.description) task.description = opts.description;
|
|
120
|
+
if (opts.acceptance && opts.acceptance.length > 0) task.acceptance = opts.acceptance;
|
|
121
|
+
await graphErrors(
|
|
122
|
+
() => (
|
|
123
|
+
// Read-modify-write under the shared .davecode/.lock (the runner and dashboard use it too).
|
|
124
|
+
brain.withLock(async () => {
|
|
125
|
+
const graph = await brain.readGraph();
|
|
126
|
+
if (graph.tasks.some((t) => t.id === id)) {
|
|
127
|
+
throw new CliError(`Task ${JSON.stringify(id)} already exists`, {
|
|
128
|
+
hint: `Change it with: davecode tasks status ${id} <STATUS>`
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
const next = parseTaskGraph({ ...graph, tasks: [...graph.tasks, task] });
|
|
132
|
+
const tmp = `${brain.paths.taskGraph}.${process.pid}.tmp`;
|
|
133
|
+
await writeFile(tmp, `${JSON.stringify(next, null, 2)}
|
|
134
|
+
`);
|
|
135
|
+
await rename(tmp, brain.paths.taskGraph);
|
|
136
|
+
})
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
if (ctx.json) {
|
|
140
|
+
printJson(ctx, { task });
|
|
141
|
+
return EXIT.ok;
|
|
142
|
+
}
|
|
143
|
+
ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} Added ${ctx.theme.bold(id)} ${title}`);
|
|
144
|
+
if (task.dependsOn.length > 0)
|
|
145
|
+
ctx.out(ctx.theme.dim(` depends on ${task.dependsOn.join(", ")}`));
|
|
146
|
+
return EXIT.ok;
|
|
147
|
+
}
|
|
148
|
+
function parseStatus(value) {
|
|
149
|
+
const normalized = value.trim().toUpperCase().replace(/[-\s]/g, "_");
|
|
150
|
+
const aliases = {
|
|
151
|
+
DONE: "SUCCESS",
|
|
152
|
+
RUNNING: "IN_PROGRESS",
|
|
153
|
+
TODO: "PENDING",
|
|
154
|
+
FAIL: "FAILED"
|
|
155
|
+
};
|
|
156
|
+
const status = aliases[normalized] ?? normalized;
|
|
157
|
+
if (!TASK_STATUSES.includes(status)) {
|
|
158
|
+
throw new CliError(`Unknown status ${JSON.stringify(value)}`, {
|
|
159
|
+
hint: `Use one of: ${TASK_STATUSES.join(", ")}`
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return status;
|
|
163
|
+
}
|
|
164
|
+
async function tasksStatus(ctx, id, statusArg, opts) {
|
|
165
|
+
const status = parseStatus(statusArg);
|
|
166
|
+
const brain = await openBrain(ctx);
|
|
167
|
+
const task = await graphErrors(
|
|
168
|
+
() => brain.setTaskStatus(id, status, opts.notes !== void 0 ? { notes: opts.notes } : {})
|
|
169
|
+
);
|
|
170
|
+
if (ctx.json) {
|
|
171
|
+
printJson(ctx, { task });
|
|
172
|
+
return EXIT.ok;
|
|
173
|
+
}
|
|
174
|
+
ctx.out(`${ctx.theme.ok(ctx.theme.glyph.ok)} ${ctx.theme.bold(task.id)} is now ${task.status}`);
|
|
175
|
+
return EXIT.ok;
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
parseStatus,
|
|
179
|
+
tasksAdd,
|
|
180
|
+
tasksList,
|
|
181
|
+
tasksNext,
|
|
182
|
+
tasksStatus
|
|
183
|
+
};
|
|
184
|
+
//# sourceMappingURL=tasks-XOTVICVZ.js.map
|
|
@@ -0,0 +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":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,76 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dmrlzz/davecode",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "DaveCode CLI & TUI: run the gateway, manage accounts and drive the autonomous engine from your terminal.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./runtime": {
|
|
9
|
+
"source": "./src/runtime.ts",
|
|
10
|
+
"default": "./dist/runtime.js"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"bin": {
|
|
14
|
+
"davecode": "bin/davecode.js"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"bin",
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"homepage": "https://github.com/DMRLZZ/DaveCode#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/DMRLZZ/DaveCode/issues"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/DMRLZZ/DaveCode.git",
|
|
29
|
+
"directory": "packages/cli"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"ai",
|
|
33
|
+
"agent",
|
|
34
|
+
"llm",
|
|
35
|
+
"gateway",
|
|
36
|
+
"claude",
|
|
37
|
+
"openai",
|
|
38
|
+
"gemini",
|
|
39
|
+
"cli",
|
|
40
|
+
"tui"
|
|
41
|
+
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22.12.0"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"@fastify/cors": "^11.3.1",
|
|
47
|
+
"@fastify/static": "^10.1.7",
|
|
48
|
+
"better-sqlite3": "^13.0.3",
|
|
49
|
+
"commander": "^15.0.0",
|
|
50
|
+
"fastify": "^5.12.5",
|
|
51
|
+
"ink": "^8.0.0",
|
|
52
|
+
"js-tiktoken": "^1.0.21",
|
|
53
|
+
"react": "^19.3.1",
|
|
54
|
+
"zod": "^4.6.7"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"playwright-core": ">=1.50.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"playwright-core": {
|
|
61
|
+
"optional": true
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/react": "^19.3.0",
|
|
66
|
+
"ink-testing-library": "^4.0.0",
|
|
67
|
+
"@davecode/core": "0.4.0",
|
|
68
|
+
"@davecode/server": "0.4.0",
|
|
69
|
+
"@davecode/ui": "0.4.0"
|
|
70
|
+
},
|
|
71
|
+
"scripts": {
|
|
72
|
+
"build": "tsup",
|
|
73
|
+
"dev": "tsx --conditions=source src/index.ts",
|
|
74
|
+
"typecheck": "tsc --noEmit"
|
|
75
|
+
}
|
|
6
76
|
}
|