@shepai/cli 1.54.0 → 1.55.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/README.md +22 -8
- package/dist/packages/core/src/application/ports/output/services/daemon-service.interface.d.ts +49 -0
- package/dist/packages/core/src/application/ports/output/services/daemon-service.interface.d.ts.map +1 -0
- package/dist/packages/core/src/application/ports/output/services/daemon-service.interface.js +7 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +1 -0
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +2 -0
- package/dist/packages/core/src/infrastructure/services/browser-opener.service.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/browser-opener.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/browser-opener.service.js +4 -0
- package/dist/packages/core/src/infrastructure/services/daemon/daemon-pid.service.d.ts +16 -0
- package/dist/packages/core/src/infrastructure/services/daemon/daemon-pid.service.d.ts.map +1 -0
- package/dist/packages/core/src/infrastructure/services/daemon/daemon-pid.service.js +72 -0
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.d.ts +7 -0
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.js +9 -0
- package/dist/src/presentation/cli/commands/_serve.command.d.ts +32 -0
- package/dist/src/presentation/cli/commands/_serve.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/_serve.command.js +91 -0
- package/dist/src/presentation/cli/commands/daemon/start-daemon.d.ts +27 -0
- package/dist/src/presentation/cli/commands/daemon/start-daemon.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/daemon/start-daemon.js +135 -0
- package/dist/src/presentation/cli/commands/start.command.d.ts +15 -0
- package/dist/src/presentation/cli/commands/start.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/start.command.js +33 -0
- package/dist/src/presentation/cli/commands/status.command.d.ts +20 -0
- package/dist/src/presentation/cli/commands/status.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/status.command.js +119 -0
- package/dist/src/presentation/cli/commands/stop.command.d.ts +22 -0
- package/dist/src/presentation/cli/commands/stop.command.d.ts.map +1 -0
- package/dist/src/presentation/cli/commands/stop.command.js +79 -0
- package/dist/src/presentation/cli/index.d.ts +5 -2
- package/dist/src/presentation/cli/index.d.ts.map +1 -1
- package/dist/src/presentation/cli/index.js +23 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/page/server-reference-manifest.json +14 -14
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6e8b5181._.js +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +15 -15
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__03a0dba7._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2d1a8e37._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6e8b5181._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +15 -15
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/{702384d364482e4b.js → 3eaa6f2966e27b8f.js} +2 -2
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- /package/web/.next/static/{RwzxYU9D2fPc_4j5RYu0v → JmDtIt3S6EfLuRKwlzJrW}/_buildManifest.js +0 -0
- /package/web/.next/static/{RwzxYU9D2fPc_4j5RYu0v → JmDtIt3S6EfLuRKwlzJrW}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{RwzxYU9D2fPc_4j5RYu0v → JmDtIt3S6EfLuRKwlzJrW}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* start Command
|
|
3
|
+
*
|
|
4
|
+
* Starts the Shep web UI as a detached background daemon.
|
|
5
|
+
* All spawn logic lives in the shared startDaemon() helper to avoid
|
|
6
|
+
* duplication between this command and the default `shep` action.
|
|
7
|
+
*
|
|
8
|
+
* Usage: shep start [--port <number>]
|
|
9
|
+
*/
|
|
10
|
+
import { Command, InvalidArgumentError } from 'commander';
|
|
11
|
+
import { startDaemon } from './daemon/start-daemon.js';
|
|
12
|
+
function parsePort(value) {
|
|
13
|
+
const port = parseInt(value, 10);
|
|
14
|
+
if (isNaN(port) || port < 1024 || port > 65535) {
|
|
15
|
+
throw new InvalidArgumentError('Port must be an integer between 1024 and 65535');
|
|
16
|
+
}
|
|
17
|
+
return port;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create the start command.
|
|
21
|
+
*/
|
|
22
|
+
export function createStartCommand() {
|
|
23
|
+
return new Command('start')
|
|
24
|
+
.description('Start the Shep web UI as a background daemon')
|
|
25
|
+
.option('-p, --port <number>', 'Port number (1024-65535)', parsePort)
|
|
26
|
+
.addHelpText('after', `
|
|
27
|
+
Examples:
|
|
28
|
+
$ shep start Start on default port (4050)
|
|
29
|
+
$ shep start --port 8080 Start on custom port`)
|
|
30
|
+
.action(async (options) => {
|
|
31
|
+
await startDaemon({ port: options.port });
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* status Command
|
|
3
|
+
*
|
|
4
|
+
* Displays live status and metrics for the running Shep web UI daemon.
|
|
5
|
+
*
|
|
6
|
+
* Metrics collected:
|
|
7
|
+
* - PID, port, URL (from daemon.json)
|
|
8
|
+
* - Uptime (computed from startedAt)
|
|
9
|
+
* - CPU%, RSS memory (from ps shell-out via execFile — injection-safe)
|
|
10
|
+
*
|
|
11
|
+
* Gracefully degrades if ps is unavailable (timeout or error).
|
|
12
|
+
*
|
|
13
|
+
* Usage: shep status
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
/**
|
|
17
|
+
* Create the status command.
|
|
18
|
+
*/
|
|
19
|
+
export declare function createStatusCommand(): Command;
|
|
20
|
+
//# sourceMappingURL=status.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/status.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+EpC;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CA2C7C"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* status Command
|
|
3
|
+
*
|
|
4
|
+
* Displays live status and metrics for the running Shep web UI daemon.
|
|
5
|
+
*
|
|
6
|
+
* Metrics collected:
|
|
7
|
+
* - PID, port, URL (from daemon.json)
|
|
8
|
+
* - Uptime (computed from startedAt)
|
|
9
|
+
* - CPU%, RSS memory (from ps shell-out via execFile — injection-safe)
|
|
10
|
+
*
|
|
11
|
+
* Gracefully degrades if ps is unavailable (timeout or error).
|
|
12
|
+
*
|
|
13
|
+
* Usage: shep status
|
|
14
|
+
*/
|
|
15
|
+
import { Command } from 'commander';
|
|
16
|
+
import { execFile } from 'node:child_process';
|
|
17
|
+
import { container } from '../../../../packages/core/src/infrastructure/di/container.js';
|
|
18
|
+
import { renderDetailView, messages } from '../ui/index.js';
|
|
19
|
+
const PS_TIMEOUT_MS = 2000;
|
|
20
|
+
/**
|
|
21
|
+
* Parse ps output: "pid cpu% rss_kb\n"
|
|
22
|
+
* Returns formatted strings for display.
|
|
23
|
+
*/
|
|
24
|
+
function parsePs(output) {
|
|
25
|
+
const parts = output.trim().split(/\s+/);
|
|
26
|
+
const cpu = parts[1] ?? '?';
|
|
27
|
+
const rssKb = parseFloat(parts[2] ?? '0');
|
|
28
|
+
const rssMb = (rssKb / 1024).toFixed(1);
|
|
29
|
+
return { cpu, rssMb };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Human-readable uptime string, e.g. "2h 14m 3s".
|
|
33
|
+
*/
|
|
34
|
+
function humanizeUptime(ms) {
|
|
35
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1000));
|
|
36
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
37
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
38
|
+
const seconds = totalSeconds % 60;
|
|
39
|
+
const parts = [];
|
|
40
|
+
if (hours > 0)
|
|
41
|
+
parts.push(`${hours}h`);
|
|
42
|
+
if (minutes > 0)
|
|
43
|
+
parts.push(`${minutes}m`);
|
|
44
|
+
parts.push(`${seconds}s`);
|
|
45
|
+
return parts.join(' ');
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Shell out to ps for CPU% and RSS, with a timeout guard.
|
|
49
|
+
* Uses execFile (not exec) — the PID is a separate array argument,
|
|
50
|
+
* preventing any possibility of shell injection.
|
|
51
|
+
*/
|
|
52
|
+
function fetchPsMetrics(pid) {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
const pidStr = String(pid);
|
|
55
|
+
let settled = false;
|
|
56
|
+
const fallback = () => ({ cpu: 'unavailable', rssMb: 'unavailable' });
|
|
57
|
+
const timer = setTimeout(() => {
|
|
58
|
+
if (!settled) {
|
|
59
|
+
settled = true;
|
|
60
|
+
child.kill();
|
|
61
|
+
resolve(fallback());
|
|
62
|
+
}
|
|
63
|
+
}, PS_TIMEOUT_MS);
|
|
64
|
+
const child = execFile('ps', ['-o', 'pid=,pcpu=,rss=', '-p', pidStr], { timeout: PS_TIMEOUT_MS }, (err, stdout) => {
|
|
65
|
+
if (settled)
|
|
66
|
+
return;
|
|
67
|
+
settled = true;
|
|
68
|
+
clearTimeout(timer);
|
|
69
|
+
if (err || !stdout.trim()) {
|
|
70
|
+
resolve(fallback());
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
resolve(parsePs(stdout));
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create the status command.
|
|
80
|
+
*/
|
|
81
|
+
export function createStatusCommand() {
|
|
82
|
+
return new Command('status')
|
|
83
|
+
.description('Show the status of the Shep web UI daemon')
|
|
84
|
+
.action(async () => {
|
|
85
|
+
const daemonService = container.resolve('IDaemonService');
|
|
86
|
+
const state = await daemonService.read();
|
|
87
|
+
if (!state || !daemonService.isAlive(state.pid)) {
|
|
88
|
+
messages.newline();
|
|
89
|
+
messages.info('Shep daemon is not running.');
|
|
90
|
+
messages.info('Run `shep start` to launch it.');
|
|
91
|
+
messages.newline();
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const { pid, port, startedAt } = state;
|
|
95
|
+
const url = `http://localhost:${port}`;
|
|
96
|
+
const uptimeMs = Date.now() - Date.parse(startedAt);
|
|
97
|
+
const uptime = humanizeUptime(uptimeMs);
|
|
98
|
+
const { cpu, rssMb } = await fetchPsMetrics(pid);
|
|
99
|
+
renderDetailView({
|
|
100
|
+
title: 'Shep Daemon Status',
|
|
101
|
+
sections: [
|
|
102
|
+
{
|
|
103
|
+
fields: [
|
|
104
|
+
{ label: 'PID', value: String(pid) },
|
|
105
|
+
{ label: 'Port', value: String(port) },
|
|
106
|
+
{ label: 'URL', value: url },
|
|
107
|
+
{ label: 'Started', value: new Date(startedAt).toLocaleString() },
|
|
108
|
+
{ label: 'Uptime', value: uptime },
|
|
109
|
+
{ label: 'CPU %', value: cpu === 'unavailable' ? 'unavailable' : `${cpu}%` },
|
|
110
|
+
{
|
|
111
|
+
label: 'Memory (RSS)',
|
|
112
|
+
value: rssMb === 'unavailable' ? 'unavailable' : `${rssMb} MB`,
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stop Command
|
|
3
|
+
*
|
|
4
|
+
* Stops the running Shep web UI daemon.
|
|
5
|
+
*
|
|
6
|
+
* Stop sequence:
|
|
7
|
+
* 1. Read daemon.json via IDaemonService
|
|
8
|
+
* 2. If no daemon / PID not alive: print clear message and exit 0
|
|
9
|
+
* 3. Validate PID is a positive finite integer
|
|
10
|
+
* 4. Send SIGTERM
|
|
11
|
+
* 5. Poll process liveness every 200ms for up to 5000ms
|
|
12
|
+
* 6. If still alive after 5s, send SIGKILL
|
|
13
|
+
* 7. Always delete daemon.json (in finally block)
|
|
14
|
+
*
|
|
15
|
+
* Usage: shep stop
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
/**
|
|
19
|
+
* Create the stop command.
|
|
20
|
+
*/
|
|
21
|
+
export declare function createStopCommand(): Command;
|
|
22
|
+
//# sourceMappingURL=stop.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.command.d.ts","sourceRoot":"","sources":["../../../../../src/presentation/cli/commands/stop.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CA+C3C"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* stop Command
|
|
3
|
+
*
|
|
4
|
+
* Stops the running Shep web UI daemon.
|
|
5
|
+
*
|
|
6
|
+
* Stop sequence:
|
|
7
|
+
* 1. Read daemon.json via IDaemonService
|
|
8
|
+
* 2. If no daemon / PID not alive: print clear message and exit 0
|
|
9
|
+
* 3. Validate PID is a positive finite integer
|
|
10
|
+
* 4. Send SIGTERM
|
|
11
|
+
* 5. Poll process liveness every 200ms for up to 5000ms
|
|
12
|
+
* 6. If still alive after 5s, send SIGKILL
|
|
13
|
+
* 7. Always delete daemon.json (in finally block)
|
|
14
|
+
*
|
|
15
|
+
* Usage: shep stop
|
|
16
|
+
*/
|
|
17
|
+
import { Command } from 'commander';
|
|
18
|
+
import { container } from '../../../../packages/core/src/infrastructure/di/container.js';
|
|
19
|
+
import { messages } from '../ui/index.js';
|
|
20
|
+
const POLL_INTERVAL_MS = 200;
|
|
21
|
+
const MAX_WAIT_MS = 5000;
|
|
22
|
+
/**
|
|
23
|
+
* Poll until the given PID is dead or the timeout expires.
|
|
24
|
+
* Returns true if the process is dead, false if it survived the timeout.
|
|
25
|
+
*/
|
|
26
|
+
async function pollUntilDead(daemonService, pid, maxMs, intervalMs) {
|
|
27
|
+
const deadline = Date.now() + maxMs;
|
|
28
|
+
while (Date.now() < deadline) {
|
|
29
|
+
await new Promise((resolve) => setTimeout(resolve, intervalMs));
|
|
30
|
+
if (!daemonService.isAlive(pid)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create the stop command.
|
|
38
|
+
*/
|
|
39
|
+
export function createStopCommand() {
|
|
40
|
+
return new Command('stop').description('Stop the running Shep web UI daemon').action(async () => {
|
|
41
|
+
const daemonService = container.resolve('IDaemonService');
|
|
42
|
+
const state = await daemonService.read();
|
|
43
|
+
// No daemon running or PID not alive
|
|
44
|
+
if (!state || !daemonService.isAlive(state.pid)) {
|
|
45
|
+
messages.info('No Shep daemon is running.');
|
|
46
|
+
await daemonService.delete();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const { pid } = state;
|
|
50
|
+
// Validate PID is a positive finite integer before kill
|
|
51
|
+
if (!Number.isFinite(pid) || !Number.isInteger(pid) || pid <= 0) {
|
|
52
|
+
messages.info('No Shep daemon is running (invalid PID in state file).');
|
|
53
|
+
await daemonService.delete();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
messages.info(`Stopping Shep daemon (PID ${pid})...`);
|
|
58
|
+
// Send SIGTERM — request graceful shutdown
|
|
59
|
+
process.kill(pid, 'SIGTERM');
|
|
60
|
+
// Poll for up to 5s waiting for the process to exit
|
|
61
|
+
const died = await pollUntilDead(daemonService, pid, MAX_WAIT_MS, POLL_INTERVAL_MS);
|
|
62
|
+
if (!died) {
|
|
63
|
+
// Graceful shutdown timed out — force kill
|
|
64
|
+
messages.info('Daemon did not stop gracefully, sending SIGKILL...');
|
|
65
|
+
try {
|
|
66
|
+
process.kill(pid, 'SIGKILL');
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Process may have exited between the check and the kill — ignore
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
messages.success('Shep daemon stopped.');
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
// Always clean up daemon.json regardless of termination path
|
|
76
|
+
await daemonService.delete();
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* shep [command] [options]
|
|
9
9
|
*
|
|
10
10
|
* Commands:
|
|
11
|
-
* shep
|
|
11
|
+
* shep Start the web UI daemon (or run onboarding on first run)
|
|
12
|
+
* shep start Start the web UI as a background daemon
|
|
13
|
+
* shep stop Stop the running web UI daemon
|
|
14
|
+
* shep status Show status and metrics of the running daemon
|
|
12
15
|
* shep version Display version information
|
|
13
|
-
* shep ui Start the web UI
|
|
16
|
+
* shep ui Start the web UI (foreground, interactive)
|
|
14
17
|
* shep run Run an AI agent workflow
|
|
15
18
|
* shep agent Manage and view agent runs
|
|
16
19
|
* shep feat Manage features through the SDLC lifecycle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/cli/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/presentation/cli/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,kBAAkB,CAAC"}
|
|
@@ -8,9 +8,12 @@
|
|
|
8
8
|
* shep [command] [options]
|
|
9
9
|
*
|
|
10
10
|
* Commands:
|
|
11
|
-
* shep
|
|
11
|
+
* shep Start the web UI daemon (or run onboarding on first run)
|
|
12
|
+
* shep start Start the web UI as a background daemon
|
|
13
|
+
* shep stop Stop the running web UI daemon
|
|
14
|
+
* shep status Show status and metrics of the running daemon
|
|
12
15
|
* shep version Display version information
|
|
13
|
-
* shep ui Start the web UI
|
|
16
|
+
* shep ui Start the web UI (foreground, interactive)
|
|
14
17
|
* shep run Run an AI agent workflow
|
|
15
18
|
* shep agent Manage and view agent runs
|
|
16
19
|
* shep feat Manage features through the SDLC lifecycle
|
|
@@ -38,6 +41,12 @@ import { createIdeOpenCommand } from './commands/ide-open.command.js';
|
|
|
38
41
|
import { createInstallCommand } from './commands/install.command.js';
|
|
39
42
|
import { createUpgradeCommand } from './commands/upgrade.command.js';
|
|
40
43
|
import { messages } from './ui/index.js';
|
|
44
|
+
// Daemon lifecycle commands
|
|
45
|
+
import { createStartCommand } from './commands/start.command.js';
|
|
46
|
+
import { createStopCommand } from './commands/stop.command.js';
|
|
47
|
+
import { createStatusCommand } from './commands/status.command.js';
|
|
48
|
+
import { createServeCommand } from './commands/_serve.command.js';
|
|
49
|
+
import { startDaemon } from './commands/daemon/start-daemon.js';
|
|
41
50
|
// DI container and settings
|
|
42
51
|
import { initializeContainer, container } from '../../../packages/core/src/infrastructure/di/container.js';
|
|
43
52
|
import { InitializeSettingsUseCase } from '../../../packages/core/src/application/use-cases/settings/initialize-settings.use-case.js';
|
|
@@ -88,8 +97,13 @@ async function bootstrap() {
|
|
|
88
97
|
.name('shep')
|
|
89
98
|
.description(description)
|
|
90
99
|
.version(version, '-v, --version', 'Display version number')
|
|
91
|
-
|
|
92
|
-
|
|
100
|
+
// task-10: Default action starts the daemon (or shows already-running URL).
|
|
101
|
+
// The onboarding gate above (lines 82-89) ensures the wizard runs on first launch;
|
|
102
|
+
// after the gate, startDaemon() is the correct next step in both cases.
|
|
103
|
+
// Commander only fires this action when no subcommand matches, so `shep start` etc.
|
|
104
|
+
// are unaffected.
|
|
105
|
+
.action(async () => {
|
|
106
|
+
await startDaemon();
|
|
93
107
|
});
|
|
94
108
|
// Register commands
|
|
95
109
|
program.addCommand(createVersionCommand());
|
|
@@ -103,6 +117,11 @@ async function bootstrap() {
|
|
|
103
117
|
program.addCommand(createIdeOpenCommand());
|
|
104
118
|
program.addCommand(createInstallCommand());
|
|
105
119
|
program.addCommand(createUpgradeCommand());
|
|
120
|
+
// Daemon lifecycle commands (task-9)
|
|
121
|
+
program.addCommand(createStartCommand());
|
|
122
|
+
program.addCommand(createStopCommand());
|
|
123
|
+
program.addCommand(createStatusCommand());
|
|
124
|
+
program.addCommand(createServeCommand()); // hidden from --help
|
|
106
125
|
// Parse arguments (parseAsync needed for async command actions like init)
|
|
107
126
|
await program.parseAsync();
|
|
108
127
|
}
|