@heysummon/app 0.1.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 +226 -0
- package/bin/CLAUDE.md +11 -0
- package/bin/cli.js +5 -0
- package/dist/__tests__/cli.test.js +81 -0
- package/dist/__tests__/config.test.js +99 -0
- package/dist/__tests__/secrets.test.js +60 -0
- package/dist/commands/init.js +155 -0
- package/dist/commands/start.js +138 -0
- package/dist/commands/status.js +91 -0
- package/dist/commands/stop.js +38 -0
- package/dist/commands/uninstall.js +139 -0
- package/dist/commands/update.js +33 -0
- package/dist/index.js +93 -0
- package/dist/lib/config.js +134 -0
- package/dist/lib/database.js +72 -0
- package/dist/lib/download.js +126 -0
- package/dist/lib/prompts.js +89 -0
- package/dist/lib/secrets.js +46 -0
- package/dist/lib/ui.js +176 -0
- package/package.json +39 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.startDaemon = startDaemon;
|
|
37
|
+
exports.startForeground = startForeground;
|
|
38
|
+
exports.start = start;
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const config_1 = require("../lib/config");
|
|
43
|
+
const ui_1 = require("../lib/ui");
|
|
44
|
+
function copyEnvToApp() {
|
|
45
|
+
const envFile = (0, config_1.getEnvFile)();
|
|
46
|
+
const appEnv = path.join((0, config_1.getAppDir)(), ".env");
|
|
47
|
+
if (fs.existsSync(envFile)) {
|
|
48
|
+
fs.copyFileSync(envFile, appEnv);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function hasPm2() {
|
|
52
|
+
try {
|
|
53
|
+
(0, child_process_1.execSync)("pm2 --version", { stdio: "pipe" });
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function getServerScript(appDir) {
|
|
61
|
+
// Prefer standalone server (next build with output: standalone)
|
|
62
|
+
const standaloneServer = path.join(appDir, ".next", "standalone", "server.js");
|
|
63
|
+
if (fs.existsSync(standaloneServer)) {
|
|
64
|
+
return { cmd: "node", args: [standaloneServer] };
|
|
65
|
+
}
|
|
66
|
+
// Fallback: npm start
|
|
67
|
+
return { cmd: "npm", args: ["start"] };
|
|
68
|
+
}
|
|
69
|
+
async function startDaemon(port) {
|
|
70
|
+
const appDir = (0, config_1.getAppDir)();
|
|
71
|
+
copyEnvToApp();
|
|
72
|
+
const env = {
|
|
73
|
+
...process.env,
|
|
74
|
+
NODE_ENV: "production",
|
|
75
|
+
...(port ? { PORT: String(port) } : {}),
|
|
76
|
+
};
|
|
77
|
+
if (hasPm2()) {
|
|
78
|
+
const { cmd, args } = getServerScript(appDir);
|
|
79
|
+
const startCmd = `pm2 start ${cmd} --name heysummon -- ${args.join(" ")}`;
|
|
80
|
+
(0, child_process_1.execSync)(startCmd, { cwd: appDir, stdio: "pipe", env });
|
|
81
|
+
(0, ui_1.printSuccess)(`Started with pm2 ${ui_1.color.dim("(heysummon)")}`);
|
|
82
|
+
(0, ui_1.printInfo)(`Logs: ${ui_1.color.cyan("pm2 logs heysummon")}`);
|
|
83
|
+
(0, ui_1.printInfo)(`Stop: ${ui_1.color.cyan("heysummon stop")}`);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Fallback: detached process
|
|
87
|
+
const { cmd, args } = getServerScript(appDir);
|
|
88
|
+
const child = (0, child_process_1.spawn)(cmd, args, {
|
|
89
|
+
cwd: appDir,
|
|
90
|
+
stdio: "ignore",
|
|
91
|
+
detached: true,
|
|
92
|
+
env,
|
|
93
|
+
});
|
|
94
|
+
child.unref();
|
|
95
|
+
(0, config_1.writePid)(child.pid);
|
|
96
|
+
(0, ui_1.printSuccess)(`Started in background ${ui_1.color.dim(`(PID: ${child.pid})`)}`);
|
|
97
|
+
(0, ui_1.printWarning)(`Install pm2 for better process management: ${ui_1.color.cyan("npm install -g pm2")}`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function startForeground(port) {
|
|
101
|
+
const appDir = (0, config_1.getAppDir)();
|
|
102
|
+
copyEnvToApp();
|
|
103
|
+
const env = {
|
|
104
|
+
...process.env,
|
|
105
|
+
NODE_ENV: "production",
|
|
106
|
+
...(port ? { PORT: String(port) } : {}),
|
|
107
|
+
};
|
|
108
|
+
const { cmd, args } = getServerScript(appDir);
|
|
109
|
+
(0, ui_1.printInfo)(`Starting ${ui_1.color.cyan(`${cmd} ${args.join(" ")}`)}`);
|
|
110
|
+
(0, ui_1.printInfo)("Press Ctrl+C to stop\n");
|
|
111
|
+
const child = (0, child_process_1.spawn)(cmd, args, {
|
|
112
|
+
cwd: appDir,
|
|
113
|
+
stdio: "inherit",
|
|
114
|
+
env,
|
|
115
|
+
});
|
|
116
|
+
(0, config_1.writePid)(child.pid);
|
|
117
|
+
child.on("close", (code) => process.exit(code ?? 0));
|
|
118
|
+
process.on("SIGINT", () => child.kill("SIGINT"));
|
|
119
|
+
process.on("SIGTERM", () => child.kill("SIGTERM"));
|
|
120
|
+
}
|
|
121
|
+
async function start(args) {
|
|
122
|
+
if (!(0, config_1.isInitialized)()) {
|
|
123
|
+
console.log(`\n HeySummon is not installed. Run ${ui_1.color.cyan("npm install -g heysummon")} first.\n`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
const existingPid = (0, config_1.readPid)();
|
|
127
|
+
if (existingPid && (0, config_1.isProcessRunning)(existingPid)) {
|
|
128
|
+
(0, ui_1.printInfo)(`Already running (PID: ${existingPid})`);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const daemon = args.includes("--daemon") || args.includes("-d");
|
|
132
|
+
if (daemon) {
|
|
133
|
+
await startDaemon();
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
startForeground();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.status = status;
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const config_1 = require("../lib/config");
|
|
41
|
+
const ui_1 = require("../lib/ui");
|
|
42
|
+
function checkHealth(port) {
|
|
43
|
+
return new Promise((resolve) => {
|
|
44
|
+
const req = http.get(`http://localhost:${port}/api/v1/health`, { timeout: 3000 }, (res) => resolve(res.statusCode === 200));
|
|
45
|
+
req.on("error", () => resolve(false));
|
|
46
|
+
req.on("timeout", () => { req.destroy(); resolve(false); });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function readPort() {
|
|
50
|
+
try {
|
|
51
|
+
const envFile = path.join((0, config_1.getAppDir)(), ".env");
|
|
52
|
+
const fallback = (0, config_1.getEnvFile)();
|
|
53
|
+
const file = fs.existsSync(envFile) ? envFile : fallback;
|
|
54
|
+
const content = fs.readFileSync(file, "utf8");
|
|
55
|
+
const match = content.match(/^PORT=(\d+)/m);
|
|
56
|
+
return match ? parseInt(match[1], 10) : null;
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function status() {
|
|
63
|
+
console.log("");
|
|
64
|
+
if (!(0, config_1.isInitialized)()) {
|
|
65
|
+
console.log(` ${ui_1.color.yellow("○")} Not installed`);
|
|
66
|
+
console.log(` ${ui_1.color.dim("Run")} ${ui_1.color.cyan("npx heysummon")} ${ui_1.color.dim("to get started.")}`);
|
|
67
|
+
console.log("");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const pid = (0, config_1.readPid)();
|
|
71
|
+
const running = pid !== null && (0, config_1.isProcessRunning)(pid);
|
|
72
|
+
const port = readPort() || 3435;
|
|
73
|
+
(0, ui_1.printDivider)();
|
|
74
|
+
console.log(` ${ui_1.color.bold("HeySummon Status")}`);
|
|
75
|
+
(0, ui_1.printDivider)();
|
|
76
|
+
console.log("");
|
|
77
|
+
if (running) {
|
|
78
|
+
const healthy = await checkHealth(port);
|
|
79
|
+
console.log(` ${ui_1.color.green("●")} ${ui_1.color.bold("Running")} ${ui_1.color.dim(`(PID: ${pid})`)}`);
|
|
80
|
+
console.log(` ${ui_1.color.dim("Health:")} ${healthy ? ui_1.color.green("ok") : ui_1.color.yellow("unreachable")}`);
|
|
81
|
+
console.log(` ${ui_1.color.dim("URL:")} ${ui_1.color.cyan(`http://localhost:${port}`)}`);
|
|
82
|
+
console.log(` ${ui_1.color.dim("Logs:")} ${ui_1.color.cyan("pm2 logs heysummon")}`);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.log(` ${ui_1.color.dim("○")} ${ui_1.color.bold("Stopped")}`);
|
|
86
|
+
console.log(` ${ui_1.color.dim("Run")} ${ui_1.color.cyan("heysummon start -d")} ${ui_1.color.dim("to start.")}`);
|
|
87
|
+
}
|
|
88
|
+
console.log("");
|
|
89
|
+
(0, ui_1.printDivider)();
|
|
90
|
+
console.log("");
|
|
91
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stop = stop;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const config_1 = require("../lib/config");
|
|
6
|
+
async function stop() {
|
|
7
|
+
// Check for pm2 first
|
|
8
|
+
try {
|
|
9
|
+
(0, child_process_1.execSync)("pm2 describe heysummon", { stdio: "pipe" });
|
|
10
|
+
console.log(" Stopping HeySummon (pm2)...");
|
|
11
|
+
(0, child_process_1.execSync)("pm2 stop heysummon", { stdio: "inherit" });
|
|
12
|
+
(0, child_process_1.execSync)("pm2 delete heysummon", { stdio: "inherit" });
|
|
13
|
+
console.log(" HeySummon stopped");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Not managed by pm2, check PID file
|
|
18
|
+
}
|
|
19
|
+
const pid = (0, config_1.readPid)();
|
|
20
|
+
if (!pid) {
|
|
21
|
+
console.log(" HeySummon is not running (no PID file found)");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (!(0, config_1.isProcessRunning)(pid)) {
|
|
25
|
+
console.log(" HeySummon is not running (stale PID file)");
|
|
26
|
+
(0, config_1.removePid)();
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
process.kill(pid, "SIGTERM");
|
|
31
|
+
console.log(` HeySummon stopped (PID: ${pid})`);
|
|
32
|
+
(0, config_1.removePid)();
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error(` Failed to stop HeySummon (PID: ${pid}):`, err);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.uninstall = uninstall;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const child_process_1 = require("child_process");
|
|
40
|
+
const p = __importStar(require("@clack/prompts"));
|
|
41
|
+
const config_1 = require("../lib/config");
|
|
42
|
+
const prompts_1 = require("../lib/prompts");
|
|
43
|
+
const ui_1 = require("../lib/ui");
|
|
44
|
+
function stopServer() {
|
|
45
|
+
// Try pm2 first
|
|
46
|
+
try {
|
|
47
|
+
(0, child_process_1.execSync)("pm2 describe heysummon", { stdio: "pipe" });
|
|
48
|
+
(0, ui_1.printInfo)("Stopping HeySummon (pm2)...");
|
|
49
|
+
(0, child_process_1.execSync)("pm2 stop heysummon", { stdio: "pipe" });
|
|
50
|
+
(0, child_process_1.execSync)("pm2 delete heysummon", { stdio: "pipe" });
|
|
51
|
+
(0, ui_1.printSuccess)("Server stopped");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
// Not managed by pm2
|
|
56
|
+
}
|
|
57
|
+
// Fall back to PID file
|
|
58
|
+
const pid = (0, config_1.readPid)();
|
|
59
|
+
if (!pid)
|
|
60
|
+
return;
|
|
61
|
+
if ((0, config_1.isProcessRunning)(pid)) {
|
|
62
|
+
(0, ui_1.printInfo)(`Stopping HeySummon (PID: ${pid})...`);
|
|
63
|
+
try {
|
|
64
|
+
process.kill(pid, "SIGTERM");
|
|
65
|
+
(0, config_1.removePid)();
|
|
66
|
+
(0, ui_1.printSuccess)("Server stopped");
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
(0, ui_1.printWarning)(`Could not stop process ${pid} — you may need to stop it manually.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
(0, config_1.removePid)();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function backupDatabase(heysummonDir) {
|
|
77
|
+
const dbSource = path.join(heysummonDir, "app", "prisma", "heysummon.db");
|
|
78
|
+
if (!fs.existsSync(dbSource)) {
|
|
79
|
+
(0, ui_1.printWarning)("No database found to back up.");
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
83
|
+
const backupPath = path.join(process.env.HOME || "~", `heysummon-backup-${timestamp}.db`);
|
|
84
|
+
fs.copyFileSync(dbSource, backupPath);
|
|
85
|
+
(0, ui_1.printSuccess)(`Database backed up to: ${ui_1.color.cyan(backupPath)}`);
|
|
86
|
+
}
|
|
87
|
+
async function uninstall() {
|
|
88
|
+
p.intro(ui_1.color.red("heysummon uninstall"));
|
|
89
|
+
const heysummonDir = (0, config_1.getHeysummonDir)();
|
|
90
|
+
if (!(0, config_1.isInitialized)()) {
|
|
91
|
+
p.log.info("HeySummon does not appear to be installed.");
|
|
92
|
+
p.log.info(`Nothing found at ${ui_1.color.cyan(heysummonDir)}`);
|
|
93
|
+
p.outro("Nothing to do.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Show exactly what will be deleted
|
|
97
|
+
p.note([
|
|
98
|
+
`${ui_1.color.red("✗")} ${ui_1.color.cyan(heysummonDir)}`,
|
|
99
|
+
` ${ui_1.color.dim("├── app/ (Next.js server + build)")}`,
|
|
100
|
+
` ${ui_1.color.dim("├── .env (config & secrets)")}`,
|
|
101
|
+
` ${ui_1.color.dim("└── app/prisma/heysummon.db (all your data)")}`,
|
|
102
|
+
].join("\n"), "This will permanently delete");
|
|
103
|
+
p.log.warn("Your accounts, API keys, and request history will be lost.");
|
|
104
|
+
// Offer database backup
|
|
105
|
+
const wantsBackup = await (0, prompts_1.askYesNo)("Back up your database before uninstalling?", true);
|
|
106
|
+
if (wantsBackup) {
|
|
107
|
+
backupDatabase(heysummonDir);
|
|
108
|
+
}
|
|
109
|
+
// Explicit confirmation — user must type "uninstall"
|
|
110
|
+
const confirmed = await (0, prompts_1.askConfirmText)(`Type ${ui_1.color.bold(ui_1.color.red("uninstall"))} to confirm`, "uninstall");
|
|
111
|
+
if (!confirmed) {
|
|
112
|
+
p.cancel("Cancelled — nothing was removed.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// Step 1: Stop server
|
|
116
|
+
stopServer();
|
|
117
|
+
// Step 2: Delete ~/.heysummon/
|
|
118
|
+
const rmSpinner = p.spinner();
|
|
119
|
+
rmSpinner.start(`Removing ${heysummonDir}...`);
|
|
120
|
+
try {
|
|
121
|
+
const appDir = (0, config_1.getAppDir)();
|
|
122
|
+
if (fs.existsSync(appDir)) {
|
|
123
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
124
|
+
}
|
|
125
|
+
fs.rmSync(heysummonDir, { recursive: true, force: true });
|
|
126
|
+
rmSpinner.stop("Application data removed");
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
rmSpinner.stop("Failed to remove application data.");
|
|
130
|
+
if (err instanceof Error) {
|
|
131
|
+
(0, ui_1.printError)(err.message);
|
|
132
|
+
}
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
// Done
|
|
136
|
+
p.log.info(`The ${ui_1.color.cyan("heysummon")} CLI binary is still installed.`);
|
|
137
|
+
p.log.info(`To remove it: ${ui_1.color.cyan("npm uninstall -g heysummon")}`);
|
|
138
|
+
p.outro("HeySummon has been uninstalled.");
|
|
139
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.update = update;
|
|
4
|
+
const config_1 = require("../lib/config");
|
|
5
|
+
const download_1 = require("../lib/download");
|
|
6
|
+
const database_1 = require("../lib/database");
|
|
7
|
+
const stop_1 = require("./stop");
|
|
8
|
+
const start_1 = require("./start");
|
|
9
|
+
async function update() {
|
|
10
|
+
if (!(0, config_1.isInitialized)()) {
|
|
11
|
+
console.log(" HeySummon is not initialized. Run 'heysummon init' first.");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const wasRunning = (() => {
|
|
15
|
+
const pid = (0, config_1.readPid)();
|
|
16
|
+
return pid !== null && (0, config_1.isProcessRunning)(pid);
|
|
17
|
+
})();
|
|
18
|
+
if (wasRunning) {
|
|
19
|
+
console.log("\n Stopping HeySummon...");
|
|
20
|
+
await (0, stop_1.stop)();
|
|
21
|
+
}
|
|
22
|
+
console.log("\n Downloading latest release...");
|
|
23
|
+
const version = await (0, download_1.downloadAndExtract)();
|
|
24
|
+
console.log(` Downloaded ${version}`);
|
|
25
|
+
(0, database_1.installDependencies)();
|
|
26
|
+
(0, database_1.runMigrations)();
|
|
27
|
+
(0, database_1.buildApp)();
|
|
28
|
+
console.log(`\n Updated to ${version}`);
|
|
29
|
+
if (wasRunning) {
|
|
30
|
+
console.log(" Restarting...\n");
|
|
31
|
+
(0, start_1.startForeground)();
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const init_1 = require("./commands/init");
|
|
4
|
+
const start_1 = require("./commands/start");
|
|
5
|
+
const stop_1 = require("./commands/stop");
|
|
6
|
+
const status_1 = require("./commands/status");
|
|
7
|
+
const update_1 = require("./commands/update");
|
|
8
|
+
const uninstall_1 = require("./commands/uninstall");
|
|
9
|
+
// Version is injected from package.json at build time
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
11
|
+
const VERSION = require("../package.json").version;
|
|
12
|
+
function printHelp() {
|
|
13
|
+
console.log(`
|
|
14
|
+
HeySummon CLI v${VERSION}
|
|
15
|
+
Human-in-the-loop for AI agents
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
heysummon [command] [options]
|
|
19
|
+
|
|
20
|
+
Commands:
|
|
21
|
+
init Install and configure HeySummon (default)
|
|
22
|
+
start Start the HeySummon server
|
|
23
|
+
stop Stop the HeySummon server
|
|
24
|
+
status Check server status
|
|
25
|
+
update Update to the latest version
|
|
26
|
+
uninstall Remove all HeySummon data and stop the server
|
|
27
|
+
|
|
28
|
+
Options:
|
|
29
|
+
--help, -h Show this help message
|
|
30
|
+
--version, -v Show version number
|
|
31
|
+
|
|
32
|
+
Init options:
|
|
33
|
+
--yes, -y Use defaults, skip prompts (quickstart)
|
|
34
|
+
|
|
35
|
+
Start options:
|
|
36
|
+
--daemon, -d Run server in background
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
npx heysummon # First-time setup (interactive)
|
|
40
|
+
npx heysummon --yes # Quickstart with defaults
|
|
41
|
+
npx heysummon start -d # Start in background
|
|
42
|
+
npx heysummon status # Check if running
|
|
43
|
+
`);
|
|
44
|
+
}
|
|
45
|
+
async function main() {
|
|
46
|
+
const args = process.argv.slice(2);
|
|
47
|
+
const command = args[0] || "init";
|
|
48
|
+
if (command === "--help" || command === "-h") {
|
|
49
|
+
printHelp();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (command === "--version" || command === "-v") {
|
|
53
|
+
console.log(VERSION);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
58
|
+
switch (command) {
|
|
59
|
+
case "init":
|
|
60
|
+
await (0, init_1.init)({ yes });
|
|
61
|
+
break;
|
|
62
|
+
case "start":
|
|
63
|
+
await (0, start_1.start)(args.slice(1));
|
|
64
|
+
break;
|
|
65
|
+
case "stop":
|
|
66
|
+
await (0, stop_1.stop)();
|
|
67
|
+
break;
|
|
68
|
+
case "status":
|
|
69
|
+
await (0, status_1.status)();
|
|
70
|
+
break;
|
|
71
|
+
case "update":
|
|
72
|
+
await (0, update_1.update)();
|
|
73
|
+
break;
|
|
74
|
+
case "uninstall":
|
|
75
|
+
await (0, uninstall_1.uninstall)();
|
|
76
|
+
break;
|
|
77
|
+
default:
|
|
78
|
+
console.log(` Unknown command: ${command}`);
|
|
79
|
+
printHelp();
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
if (err instanceof Error) {
|
|
85
|
+
console.error(`\n Error: ${err.message}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.error("\n An unexpected error occurred");
|
|
89
|
+
}
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
main();
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.getHeysummonDir = getHeysummonDir;
|
|
37
|
+
exports.getAppDir = getAppDir;
|
|
38
|
+
exports.getEnvFile = getEnvFile;
|
|
39
|
+
exports.getPidFile = getPidFile;
|
|
40
|
+
exports.isInitialized = isInitialized;
|
|
41
|
+
exports.ensureDir = ensureDir;
|
|
42
|
+
exports.generateEnv = generateEnv;
|
|
43
|
+
exports.writeEnv = writeEnv;
|
|
44
|
+
exports.readPid = readPid;
|
|
45
|
+
exports.writePid = writePid;
|
|
46
|
+
exports.removePid = removePid;
|
|
47
|
+
exports.isProcessRunning = isProcessRunning;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const HEYSUMMON_DIR = path.join(os.homedir(), ".heysummon");
|
|
52
|
+
const APP_DIR = path.join(HEYSUMMON_DIR, "app");
|
|
53
|
+
const ENV_FILE = path.join(HEYSUMMON_DIR, ".env");
|
|
54
|
+
const PID_FILE = path.join(HEYSUMMON_DIR, "heysummon.pid");
|
|
55
|
+
function getHeysummonDir() {
|
|
56
|
+
return HEYSUMMON_DIR;
|
|
57
|
+
}
|
|
58
|
+
function getAppDir() {
|
|
59
|
+
return APP_DIR;
|
|
60
|
+
}
|
|
61
|
+
function getEnvFile() {
|
|
62
|
+
return ENV_FILE;
|
|
63
|
+
}
|
|
64
|
+
function getPidFile() {
|
|
65
|
+
return PID_FILE;
|
|
66
|
+
}
|
|
67
|
+
function isInitialized() {
|
|
68
|
+
return fs.existsSync(HEYSUMMON_DIR) && fs.existsSync(APP_DIR);
|
|
69
|
+
}
|
|
70
|
+
function ensureDir(dir) {
|
|
71
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
72
|
+
}
|
|
73
|
+
function generateEnv(config, secrets) {
|
|
74
|
+
const lines = [
|
|
75
|
+
"# HeySummon Configuration",
|
|
76
|
+
`# Generated on ${new Date().toISOString()}`,
|
|
77
|
+
"",
|
|
78
|
+
`DATABASE_URL="file:./prisma/heysummon.db"`,
|
|
79
|
+
"",
|
|
80
|
+
"# Server",
|
|
81
|
+
`PORT=${config.port}`,
|
|
82
|
+
`NEXTAUTH_URL="${config.publicUrl}"`,
|
|
83
|
+
`NEXTAUTH_SECRET="${secrets.nextauthSecret}"`,
|
|
84
|
+
"",
|
|
85
|
+
"# Authentication",
|
|
86
|
+
`ENABLE_FORM_LOGIN="${config.enableFormLogin ? "true" : "false"}"`,
|
|
87
|
+
];
|
|
88
|
+
if (config.enableGithubOauth && config.githubId && config.githubSecret) {
|
|
89
|
+
lines.push("");
|
|
90
|
+
lines.push("# GitHub OAuth");
|
|
91
|
+
lines.push(`GITHUB_ID="${config.githubId}"`);
|
|
92
|
+
lines.push(`GITHUB_SECRET="${config.githubSecret}"`);
|
|
93
|
+
}
|
|
94
|
+
if (config.enableGoogleOauth && config.googleId && config.googleSecret) {
|
|
95
|
+
lines.push("");
|
|
96
|
+
lines.push("# Google OAuth");
|
|
97
|
+
lines.push(`GOOGLE_ID="${config.googleId}"`);
|
|
98
|
+
lines.push(`GOOGLE_SECRET="${config.googleSecret}"`);
|
|
99
|
+
}
|
|
100
|
+
lines.push("");
|
|
101
|
+
return lines.join("\n");
|
|
102
|
+
}
|
|
103
|
+
function writeEnv(content) {
|
|
104
|
+
fs.writeFileSync(ENV_FILE, content, "utf-8");
|
|
105
|
+
}
|
|
106
|
+
function readPid() {
|
|
107
|
+
try {
|
|
108
|
+
const pid = parseInt(fs.readFileSync(PID_FILE, "utf-8").trim(), 10);
|
|
109
|
+
return isNaN(pid) ? null : pid;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function writePid(pid) {
|
|
116
|
+
fs.writeFileSync(PID_FILE, String(pid), "utf-8");
|
|
117
|
+
}
|
|
118
|
+
function removePid() {
|
|
119
|
+
try {
|
|
120
|
+
fs.unlinkSync(PID_FILE);
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// ignore if file doesn't exist
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
function isProcessRunning(pid) {
|
|
127
|
+
try {
|
|
128
|
+
process.kill(pid, 0);
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|