@devflow-tools/cli 0.18.2 → 0.18.4
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/README.md +19 -4
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +12 -10
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/server.d.ts +19 -5
- package/dist/commands/server.d.ts.map +1 -1
- package/dist/commands/server.js +31 -116
- package/dist/commands/server.js.map +1 -1
- package/dist/commands/start.d.ts +4 -2
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +29 -56
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts +4 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +17 -9
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/stop.d.ts.map +1 -1
- package/dist/commands/stop.js +3 -2
- package/dist/commands/stop.js.map +1 -1
- package/dist/index.js +63 -18
- package/dist/index.js.map +1 -1
- package/dist/lib/messages.d.ts +38 -0
- package/dist/lib/messages.d.ts.map +1 -0
- package/dist/lib/messages.js +42 -0
- package/dist/lib/messages.js.map +1 -0
- package/dist/lib/with-server.d.ts.map +1 -1
- package/dist/lib/with-server.js +22 -8
- package/dist/lib/with-server.js.map +1 -1
- package/dist/plugin-files/.claude-plugin/plugin.json +1 -1
- package/dist/plugin-files/dist/command-registry.json +5 -5
- package/dist/plugin-files/dist/hooks/hook-daemon.js +28 -27
- package/dist/plugin-files/dist/hooks/post-tool-use-failure.js +2 -2
- package/dist/plugin-files/dist/hooks/post-tool-use.js +6 -6
- package/dist/plugin-files/dist/hooks/pre-compact.js +3 -3
- package/dist/plugin-files/dist/hooks/pre-tool-use.js +4 -4
- package/dist/plugin-files/dist/hooks/server-bootstrap.js +1 -109
- package/dist/plugin-files/dist/hooks/session-end.js +5 -5
- package/dist/plugin-files/dist/hooks/stop.js +9 -9
- package/dist/plugin-files/dist/hooks/user-prompt-submit.js +8 -8
- package/dist/plugin-files/package.json +13 -13
- package/dist/plugin-files/skills/start/SKILL.md +20 -34
- package/package.json +27 -27
|
@@ -1,16 +1,30 @@
|
|
|
1
|
+
import { type EnsureRuntimeInput, type RuntimeStateV2 } from '@devflow-tools/sdk';
|
|
1
2
|
export declare const DEFAULT_SERVER_PORT = 13337;
|
|
2
|
-
declare function
|
|
3
|
-
declare function
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
export declare function resolveServerLaunch(projectRoot?: string): EnsureRuntimeInput['server'];
|
|
4
|
+
export declare function getRuntimeManager(): import("@devflow-tools/sdk").RuntimeManager;
|
|
5
|
+
export interface CliRuntimeOptions {
|
|
6
|
+
reason: EnsureRuntimeInput['reason'];
|
|
7
|
+
projectRoot: string;
|
|
8
|
+
port?: number;
|
|
9
|
+
explicitPort?: boolean;
|
|
10
|
+
noStart?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function ensureCliRuntime(options: CliRuntimeOptions): Promise<import("@devflow-tools/sdk").EnsureRuntimeResult>;
|
|
13
|
+
export declare function startServer(options?: {
|
|
14
|
+
port?: number;
|
|
15
|
+
projectRoot?: string;
|
|
16
|
+
explicitPort?: boolean;
|
|
7
17
|
}): Promise<{
|
|
8
18
|
pid: number;
|
|
19
|
+
port: number;
|
|
20
|
+
state: RuntimeStateV2;
|
|
21
|
+
reused: boolean;
|
|
9
22
|
}>;
|
|
10
23
|
export declare function stopServer(): Promise<boolean>;
|
|
11
24
|
export declare function serverStatus(): Promise<{
|
|
12
25
|
running: boolean;
|
|
13
26
|
pid?: number;
|
|
14
27
|
port?: number;
|
|
28
|
+
state?: RuntimeStateV2 | null;
|
|
15
29
|
}>;
|
|
16
30
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACpB,MAAM,oBAAoB,CAAC;AAG5B,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAEzC,wBAAgB,mBAAmB,CAAC,WAAW,SAAgB,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAU7F;AAED,wBAAgB,iBAAiB,gDAAqC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,6DAShE;AAED,wBAAsB,WAAW,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC,CAI/L;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC,CAAuD;AAE3G,wBAAsB,YAAY,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,CAAA;CAAE,CAAC,CAG9H"}
|
package/dist/commands/server.js
CHANGED
|
@@ -1,126 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { createRequire } from "module";
|
|
5
|
-
import { randomUUID } from "node:crypto";
|
|
6
|
-
import { DEFAULT_DEVFLOW_SERVER_PORT, readRuntimeEndpointState, resolveRuntimeEndpoint, updateRuntimeEndpointStatus, writeRuntimeEndpointState, } from "@devflow-tools/sdk";
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { createRuntimeManager, } from '@devflow-tools/sdk';
|
|
7
4
|
const require = createRequire(import.meta.url);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
return require.resolve("./server.js");
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
// Fallback: separate npm package
|
|
5
|
+
export const DEFAULT_SERVER_PORT = 13337;
|
|
6
|
+
export function resolveServerLaunch(projectRoot = process.cwd()) {
|
|
7
|
+
const candidates = [
|
|
8
|
+
() => require.resolve('@devflow-tools/server/dist/main.js'),
|
|
9
|
+
() => join(projectRoot, 'node_modules', '@devflow-tools', 'server', 'dist', 'main.js'),
|
|
10
|
+
() => join(projectRoot, 'apps', 'server', 'dist', 'main.js'),
|
|
11
|
+
];
|
|
12
|
+
for (const candidate of candidates) {
|
|
21
13
|
try {
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
return join(process.cwd(), "apps", "server", "dist", "main.js");
|
|
14
|
+
return { command: process.execPath, args: [candidate()], cwd: projectRoot };
|
|
26
15
|
}
|
|
16
|
+
catch { }
|
|
27
17
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
function
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return null;
|
|
40
|
-
}
|
|
41
|
-
function readPid(pidFile) {
|
|
42
|
-
if (!existsSync(pidFile))
|
|
43
|
-
return null;
|
|
44
|
-
const lines = readFileSync(pidFile, "utf-8").trim().split("\n");
|
|
45
|
-
// New format: port\npid (2 lines). Old format: just pid (1 line).
|
|
46
|
-
const pidLine = lines.length >= 2 ? lines[1] : lines[0];
|
|
47
|
-
const pid = parseInt(pidLine, 10);
|
|
48
|
-
return isNaN(pid) ? null : pid;
|
|
49
|
-
}
|
|
50
|
-
export { readPort as readPortFromFile, readPid as readPidFromFile };
|
|
51
|
-
export async function startServer(opts) {
|
|
52
|
-
const script = getServerScript();
|
|
53
|
-
const pidFile = getPidFile(process.cwd());
|
|
54
|
-
const ownerToken = randomUUID();
|
|
55
|
-
const child = spawn(process.execPath, [script, '--devflow-instance-token', ownerToken], {
|
|
56
|
-
env: { ...process.env, PORT: String(opts.port) },
|
|
57
|
-
stdio: "ignore",
|
|
58
|
-
detached: true,
|
|
59
|
-
});
|
|
60
|
-
writeFileSync(pidFile, `${opts.port}\n${child.pid ?? 0}`);
|
|
61
|
-
writeRuntimeEndpointState({
|
|
62
|
-
url: `http://127.0.0.1:${opts.port}`,
|
|
63
|
-
port: opts.port,
|
|
64
|
-
pid: child.pid ?? 0,
|
|
65
|
-
ownerToken,
|
|
66
|
-
status: 'launching',
|
|
18
|
+
throw new Error('DevFlow server entry point is not installed or built');
|
|
19
|
+
}
|
|
20
|
+
export function getRuntimeManager() { return createRuntimeManager(); }
|
|
21
|
+
export async function ensureCliRuntime(options) {
|
|
22
|
+
return getRuntimeManager().ensureRunning({
|
|
23
|
+
reason: options.reason,
|
|
24
|
+
projectRoot: options.projectRoot,
|
|
25
|
+
port: options.port,
|
|
26
|
+
explicitPort: options.explicitPort,
|
|
27
|
+
noStart: options.noStart,
|
|
28
|
+
server: resolveServerLaunch(options.projectRoot),
|
|
67
29
|
});
|
|
68
|
-
child.unref();
|
|
69
|
-
const healthy = await waitForHealth(`http://127.0.0.1:${opts.port}`, 5_000);
|
|
70
|
-
updateRuntimeEndpointStatus(healthy ? 'healthy' : 'degraded');
|
|
71
|
-
return { pid: child.pid ?? 0 };
|
|
72
30
|
}
|
|
73
|
-
export async function
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
return false;
|
|
78
|
-
try {
|
|
79
|
-
process.kill(pid);
|
|
80
|
-
unlinkSync(pidFile);
|
|
81
|
-
const endpoint = readRuntimeEndpointState();
|
|
82
|
-
if (endpoint?.pid === pid)
|
|
83
|
-
updateRuntimeEndpointStatus('stopped');
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
unlinkSync(pidFile);
|
|
88
|
-
const endpoint = readRuntimeEndpointState();
|
|
89
|
-
if (endpoint?.pid === pid)
|
|
90
|
-
updateRuntimeEndpointStatus('stopped');
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
31
|
+
export async function startServer(options = {}) {
|
|
32
|
+
const root = options.projectRoot ?? process.cwd();
|
|
33
|
+
const result = await ensureCliRuntime({ reason: 'cli-start', projectRoot: root, port: options.port, explicitPort: options.explicitPort });
|
|
34
|
+
return { pid: result.state.pid, port: result.state.port, state: result.state, reused: result.reused };
|
|
93
35
|
}
|
|
36
|
+
export async function stopServer() { return (await getRuntimeManager().stop()).stopped; }
|
|
94
37
|
export async function serverStatus() {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
const port = readPort(pidFile) ?? resolved.port;
|
|
98
|
-
const { DevFlowApiClient } = await import("@devflow-tools/sdk");
|
|
99
|
-
const client = new DevFlowApiClient({ baseUrl: `http://127.0.0.1:${port}`, projectRoot: process.cwd() });
|
|
100
|
-
const reachable = await client.ping();
|
|
101
|
-
if (reachable) {
|
|
102
|
-
const pid = readPid(pidFile) ?? undefined;
|
|
103
|
-
const state = readRuntimeEndpointState();
|
|
104
|
-
if (state && (!pid || state.pid === pid))
|
|
105
|
-
updateRuntimeEndpointStatus('healthy');
|
|
106
|
-
return { running: true, pid, port };
|
|
107
|
-
}
|
|
108
|
-
const state = readRuntimeEndpointState();
|
|
109
|
-
if (state && (!readPid(pidFile) || state.pid === readPid(pidFile)))
|
|
110
|
-
updateRuntimeEndpointStatus('degraded');
|
|
111
|
-
return { running: false, port };
|
|
112
|
-
}
|
|
113
|
-
async function waitForHealth(url, timeoutMs) {
|
|
114
|
-
const deadline = Date.now() + timeoutMs;
|
|
115
|
-
while (Date.now() < deadline) {
|
|
116
|
-
try {
|
|
117
|
-
const response = await fetch(new URL('/api/health', url), { signal: AbortSignal.timeout(500) });
|
|
118
|
-
if (response.ok)
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
catch { }
|
|
122
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
123
|
-
}
|
|
124
|
-
return false;
|
|
38
|
+
const state = await getRuntimeManager().status();
|
|
39
|
+
return { running: Boolean(state?.status === 'ready' && state.dashboardAvailable), pid: state?.pid, port: state?.port, state };
|
|
125
40
|
}
|
|
126
41
|
//# sourceMappingURL=server.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/commands/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,oBAAoB,GAGrB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC;AAEzC,MAAM,UAAU,mBAAmB,CAAC,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE;IAC7D,MAAM,UAAU,GAAG;QACjB,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,oCAAoC,CAAC;QAC3D,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC;QACtF,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC;KAC7D,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC;YAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IAC/F,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,iBAAiB,KAAK,OAAO,oBAAoB,EAAE,CAAC,CAAC,CAAC;AAUtE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA0B;IAC/D,OAAO,iBAAiB,EAAE,CAAC,aAAa,CAAC;QACvC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,MAAM,EAAE,mBAAmB,CAAC,OAAO,CAAC,WAAW,CAAC;KACjD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAA2E,EAAE;IAC7G,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC1I,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;AACxG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,KAAuB,OAAO,CAAC,MAAM,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAE3G,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,KAAK,GAAG,MAAM,iBAAiB,EAAE,CAAC,MAAM,EAAE,CAAC;IACjD,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,IAAI,KAAK,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAChI,CAAC"}
|
package/dist/commands/start.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAIA,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAC;IAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3I"}
|
package/dist/commands/start.js
CHANGED
|
@@ -1,58 +1,31 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
// 3. Print status
|
|
31
|
-
console.log("");
|
|
32
|
-
console.log(chalk.green("╔═══════════════════════════════════════════════════════════╗"));
|
|
33
|
-
console.log(chalk.green("║") + " DevFlow Started! " + chalk.green("║"));
|
|
34
|
-
console.log(chalk.green("╠═══════════════════════════════════════════════════════════╣"));
|
|
35
|
-
console.log(chalk.green("║") + ` Server + Dashboard: http://localhost:${opts.port}`.padEnd(57) + chalk.green("║"));
|
|
36
|
-
console.log(chalk.green("║") + ` API: http://localhost:${opts.port}/api`.padEnd(57) + chalk.green("║"));
|
|
37
|
-
console.log(chalk.green("║") + " " + chalk.green("║"));
|
|
38
|
-
console.log(chalk.green("║") + " Press Ctrl+C to stop " + chalk.green("║"));
|
|
39
|
-
console.log(chalk.green("╚═══════════════════════════════════════════════════════════╝"));
|
|
40
|
-
// 4. If not background, wait for Ctrl+C
|
|
41
|
-
if (!opts.background) {
|
|
42
|
-
await new Promise((resolve) => {
|
|
43
|
-
let cleaned = false;
|
|
44
|
-
const cleanup = async () => {
|
|
45
|
-
if (cleaned)
|
|
46
|
-
return;
|
|
47
|
-
cleaned = true;
|
|
48
|
-
console.log(chalk.blue("\nShutting down..."));
|
|
49
|
-
await stopServer();
|
|
50
|
-
console.log(chalk.green("Server stopped."));
|
|
51
|
-
resolve();
|
|
52
|
-
};
|
|
53
|
-
process.on("SIGINT", cleanup);
|
|
54
|
-
process.on("SIGTERM", cleanup);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { getRuntimeManager, startServer } from './server.js';
|
|
3
|
+
import { runtimeMessage } from '../lib/messages.js';
|
|
4
|
+
export async function startAll(options) {
|
|
5
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
6
|
+
console.log(chalk.blue(runtimeMessage('starting')));
|
|
7
|
+
const result = await startServer({ port: options.port, projectRoot, explicitPort: options.explicitPort });
|
|
8
|
+
console.log(chalk.green(runtimeMessage('ready', { url: result.state.url })));
|
|
9
|
+
if (result.reused)
|
|
10
|
+
console.log(chalk.dim(runtimeMessage('reused')));
|
|
11
|
+
if (options.background)
|
|
12
|
+
return;
|
|
13
|
+
await new Promise(resolve => {
|
|
14
|
+
let finished = false;
|
|
15
|
+
const cleanup = async () => {
|
|
16
|
+
if (finished)
|
|
17
|
+
return;
|
|
18
|
+
finished = true;
|
|
19
|
+
process.off('SIGINT', cleanup);
|
|
20
|
+
process.off('SIGTERM', cleanup);
|
|
21
|
+
const current = getRuntimeManager().readState();
|
|
22
|
+
if (!result.reused && current?.generation === result.state.generation && current.ownerToken === result.state.ownerToken) {
|
|
23
|
+
await getRuntimeManager().stop().catch(() => undefined);
|
|
24
|
+
}
|
|
25
|
+
resolve();
|
|
26
|
+
};
|
|
27
|
+
process.once('SIGINT', cleanup);
|
|
28
|
+
process.once('SIGTERM', cleanup);
|
|
29
|
+
});
|
|
57
30
|
}
|
|
58
31
|
//# sourceMappingURL=start.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../src/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,OAA6F;IAC1H,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC1G,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7E,IAAI,MAAM,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,OAAO,CAAC,UAAU;QAAE,OAAO;IAE/B,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;QAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,MAAM,OAAO,GAAG,KAAK,IAAmB,EAAE;YACxC,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC,SAAS,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,OAAO,EAAE,UAAU,KAAK,MAAM,CAAC,KAAK,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,KAAK,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;gBACxH,MAAM,iBAAiB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC1D,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAwBA,wBAAsB,UAAU,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDtG"}
|
package/dist/commands/status.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { existsSync, statSync } from "fs";
|
|
2
2
|
import chalk from "chalk";
|
|
3
|
-
import { serverStatus
|
|
3
|
+
import { serverStatus } from "./server.js";
|
|
4
4
|
import { getGlobalDevFlowDbPath } from "@devflow-tools/database";
|
|
5
5
|
import { join } from "path";
|
|
6
6
|
import { DatabaseSync } from "node:sqlite";
|
|
7
7
|
import { homedir } from "node:os";
|
|
8
8
|
import { resolveActivePlugin, scanClaudeSkillShadowing } from "../lib/plugin-setup.js";
|
|
9
|
+
import { runtimeMessage } from "../lib/messages.js";
|
|
9
10
|
function hasDevFlowTables(path) {
|
|
10
11
|
if (!existsSync(path))
|
|
11
12
|
return false;
|
|
@@ -22,19 +23,26 @@ function hasDevFlowTables(path) {
|
|
|
22
23
|
return true;
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
|
-
export async function showStatus() {
|
|
26
|
-
|
|
26
|
+
export async function showStatus(options = {}) {
|
|
27
|
+
const server = await serverStatus();
|
|
28
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
29
|
+
if (options.json) {
|
|
30
|
+
console.log(JSON.stringify({
|
|
31
|
+
runtime: server.state ?? null,
|
|
32
|
+
running: server.running,
|
|
33
|
+
project: { root: projectRoot, initialized: existsSync(join(projectRoot, '.devflow')) },
|
|
34
|
+
}));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
console.log(chalk.blue(runtimeMessage('statusHeader')));
|
|
27
38
|
console.log(chalk.dim("──────────────"));
|
|
28
39
|
// Server status
|
|
29
|
-
const server = await serverStatus();
|
|
30
|
-
const serverPort = server.port ?? DEFAULT_SERVER_PORT;
|
|
31
40
|
if (server.running) {
|
|
32
|
-
|
|
33
|
-
console.log(
|
|
41
|
+
const state = server.state;
|
|
42
|
+
console.log(chalk.green(runtimeMessage('running', { url: state.url, pid: state.pid, generation: state.generation })));
|
|
34
43
|
}
|
|
35
44
|
else {
|
|
36
|
-
console.log(
|
|
37
|
-
console.log(`Dashboard: ${chalk.yellow("○")} not running`);
|
|
45
|
+
console.log(chalk.yellow(runtimeMessage(server.state ? 'dashboardUnavailable' : 'notRunning', { status: server.state?.status ?? 'stopped' })));
|
|
38
46
|
}
|
|
39
47
|
const home = homedir();
|
|
40
48
|
const activePlugin = resolveActivePlugin(home);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"stop.d.ts","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAIA,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAO7C"}
|
package/dist/commands/stop.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { stopServer } from "./server.js";
|
|
3
|
+
import { runtimeMessage } from "../lib/messages.js";
|
|
3
4
|
export async function stopAll() {
|
|
4
5
|
const stopped = await stopServer();
|
|
5
6
|
if (stopped) {
|
|
6
|
-
console.log(chalk.green(
|
|
7
|
+
console.log(chalk.green(runtimeMessage('stopped')));
|
|
7
8
|
}
|
|
8
9
|
else {
|
|
9
|
-
console.log(chalk.dim(
|
|
10
|
+
console.log(chalk.dim(runtimeMessage('notRunning')));
|
|
10
11
|
}
|
|
11
12
|
}
|
|
12
13
|
//# sourceMappingURL=stop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IACnC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACvD,CAAC;AACH,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from "fs";
|
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { detectMode } from "./mode.js";
|
|
7
7
|
import { createRequire } from "module";
|
|
8
|
+
import { execFile } from "node:child_process";
|
|
8
9
|
const require = createRequire(import.meta.url);
|
|
9
10
|
// Read version from package.json at runtime
|
|
10
11
|
// Installed: dist/cli.js → ../package.json = packages/devflow/package.json
|
|
@@ -22,6 +23,19 @@ catch {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
const program = new Command();
|
|
26
|
+
function openDashboardUrl(url) {
|
|
27
|
+
const parsed = new URL(url);
|
|
28
|
+
if (parsed.protocol !== 'http:' || parsed.hostname !== '127.0.0.1')
|
|
29
|
+
return Promise.reject(new Error('Only loopback Dashboard URLs can be opened.'));
|
|
30
|
+
const [command, args] = process.platform === 'darwin'
|
|
31
|
+
? ['/usr/bin/open', [url]]
|
|
32
|
+
: process.platform === 'win32'
|
|
33
|
+
? ['cmd.exe', ['/c', 'start', '', url]]
|
|
34
|
+
: ['xdg-open', [url]];
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
execFile(command, args, error => error ? reject(error) : resolve());
|
|
37
|
+
});
|
|
38
|
+
}
|
|
25
39
|
program
|
|
26
40
|
.name("devflow")
|
|
27
41
|
.description("Developer Intelligence Platform for AI Coding Agents")
|
|
@@ -821,43 +835,71 @@ serverCmd
|
|
|
821
835
|
.command("start")
|
|
822
836
|
.description("Start the DevFlow REST server")
|
|
823
837
|
.option("--port <n>", "Port number", "13337")
|
|
824
|
-
.action(async (opts) => {
|
|
825
|
-
console.log(chalk.blue("Starting DevFlow server..."));
|
|
838
|
+
.action(async (opts, command) => {
|
|
826
839
|
const { startServer } = await import("./commands/server.js");
|
|
827
|
-
const
|
|
828
|
-
console.log(chalk.
|
|
840
|
+
const { runtimeMessage } = await import('./lib/messages.js');
|
|
841
|
+
console.log(chalk.blue(runtimeMessage('starting')));
|
|
842
|
+
const result = await startServer({ port: Number(opts.port), explicitPort: command.getOptionValueSource('port') === 'cli' });
|
|
843
|
+
console.log(chalk.green(runtimeMessage('ready', { url: result.state.url })));
|
|
844
|
+
if (result.reused)
|
|
845
|
+
console.log(chalk.dim(runtimeMessage('reused')));
|
|
829
846
|
});
|
|
830
847
|
serverCmd
|
|
831
848
|
.command("stop")
|
|
832
849
|
.description("Stop the DevFlow REST server")
|
|
833
850
|
.action(async () => {
|
|
834
851
|
const { stopServer } = await import("./commands/server.js");
|
|
852
|
+
const { runtimeMessage } = await import('./lib/messages.js');
|
|
835
853
|
const ok = await stopServer();
|
|
836
854
|
if (ok)
|
|
837
|
-
console.log(chalk.green(
|
|
855
|
+
console.log(chalk.green(runtimeMessage('stopped')));
|
|
838
856
|
else
|
|
839
|
-
console.log(chalk.dim(
|
|
857
|
+
console.log(chalk.dim(runtimeMessage('notRunning')));
|
|
840
858
|
});
|
|
841
859
|
serverCmd
|
|
842
860
|
.command("status")
|
|
843
861
|
.description("Show server status")
|
|
844
862
|
.action(async () => {
|
|
845
863
|
const { serverStatus } = await import("./commands/server.js");
|
|
864
|
+
const { runtimeMessage } = await import('./lib/messages.js');
|
|
846
865
|
const status = await serverStatus();
|
|
847
|
-
if (status.running)
|
|
848
|
-
console.log(chalk.green(
|
|
866
|
+
if (status.running && status.state)
|
|
867
|
+
console.log(chalk.green(runtimeMessage('running', { url: status.state.url, pid: status.state.pid, generation: status.state.generation })));
|
|
849
868
|
else
|
|
850
|
-
console.log(chalk.yellow(
|
|
869
|
+
console.log(chalk.yellow(runtimeMessage(status.state ? 'dashboardUnavailable' : 'notRunning', { status: status.state?.status ?? 'stopped' })));
|
|
851
870
|
});
|
|
852
871
|
// --- dashboard ---
|
|
853
872
|
program
|
|
854
873
|
.command("dashboard")
|
|
855
874
|
.description("Open DevFlow Dashboard")
|
|
856
|
-
.
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
875
|
+
.option('--open', 'Open the ready Dashboard URL in the default browser')
|
|
876
|
+
.option('--no-start', 'Return an error when no ready runtime exists')
|
|
877
|
+
.option('--json', 'Print a stable JSON result')
|
|
878
|
+
.option('--project <path>', 'Project root', process.cwd())
|
|
879
|
+
.option('--port <n>', 'Runtime port')
|
|
880
|
+
.action(async (opts, command) => {
|
|
881
|
+
const { ensureCliRuntime } = await import('./commands/server.js');
|
|
882
|
+
const { runtimeMessage } = await import('./lib/messages.js');
|
|
883
|
+
const projectRoot = path.resolve(opts.project);
|
|
884
|
+
if (!fs.existsSync(projectRoot) || !fs.statSync(projectRoot).isDirectory())
|
|
885
|
+
throw new Error(runtimeMessage('projectRequired'));
|
|
886
|
+
const result = await ensureCliRuntime({ reason: 'cli-dashboard', projectRoot, port: opts.port === undefined ? undefined : Number(opts.port), explicitPort: command.getOptionValueSource('port') === 'cli', noStart: opts.start === false });
|
|
887
|
+
const document = { url: result.state.url, projectId: result.projectId, runtime: result.state, reused: result.reused };
|
|
888
|
+
if (opts.json)
|
|
889
|
+
console.log(JSON.stringify(document));
|
|
890
|
+
else {
|
|
891
|
+
console.log(chalk.green(runtimeMessage('ready', { url: result.state.url })));
|
|
892
|
+
if (result.reused)
|
|
893
|
+
console.log(chalk.dim(runtimeMessage('reused')));
|
|
894
|
+
}
|
|
895
|
+
if (opts.open) {
|
|
896
|
+
try {
|
|
897
|
+
await openDashboardUrl(result.state.url);
|
|
898
|
+
}
|
|
899
|
+
catch (error) {
|
|
900
|
+
console.error(chalk.yellow(runtimeMessage('openingFailed', { message: error instanceof Error ? error.message : String(error) })));
|
|
901
|
+
}
|
|
902
|
+
}
|
|
861
903
|
});
|
|
862
904
|
// --- start ---
|
|
863
905
|
program
|
|
@@ -865,11 +907,12 @@ program
|
|
|
865
907
|
.description("Start DevFlow server (API + Dashboard)")
|
|
866
908
|
.option("--port <n>", "Server port", "13337")
|
|
867
909
|
.option("-d, --background", "Run in background (detached)")
|
|
868
|
-
.action(async (opts) => {
|
|
910
|
+
.action(async (opts, command) => {
|
|
869
911
|
const { startAll } = await import("./commands/start.js");
|
|
870
912
|
await startAll({
|
|
871
|
-
port:
|
|
913
|
+
port: Number(opts.port),
|
|
872
914
|
background: !!opts.background,
|
|
915
|
+
explicitPort: command.getOptionValueSource('port') === 'cli',
|
|
873
916
|
});
|
|
874
917
|
});
|
|
875
918
|
// --- stop ---
|
|
@@ -884,9 +927,11 @@ program
|
|
|
884
927
|
program
|
|
885
928
|
.command("status")
|
|
886
929
|
.description("Show DevFlow services status")
|
|
887
|
-
.
|
|
930
|
+
.option('--json', 'Print a stable JSON result')
|
|
931
|
+
.option('--project <path>', 'Project root', process.cwd())
|
|
932
|
+
.action(async (opts) => {
|
|
888
933
|
const { showStatus } = await import("./commands/status.js");
|
|
889
|
-
await showStatus();
|
|
934
|
+
await showStatus({ json: Boolean(opts.json), projectRoot: path.resolve(opts.project) });
|
|
890
935
|
});
|
|
891
936
|
// --- setup ---
|
|
892
937
|
program
|