@neotx/cli 0.1.0-alpha.2 → 0.1.0-alpha.20
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 +383 -0
- package/dist/activity-LWUVGQVN.js +86 -0
- package/dist/activity-LWUVGQVN.js.map +1 -0
- package/dist/{agents-Y6LREFXP.js → agents-PH3P7G7E.js} +2 -2
- package/dist/{chunk-CP54H7WA.js → chunk-3ZP3BQXB.js} +6 -11
- package/dist/chunk-3ZP3BQXB.js.map +1 -0
- package/dist/{chunk-TNJOG54I.js → chunk-F622JUDY.js} +6 -2
- package/dist/{chunk-TNJOG54I.js.map → chunk-F622JUDY.js.map} +1 -1
- package/dist/config-NYF6AJXU.js +282 -0
- package/dist/config-NYF6AJXU.js.map +1 -0
- package/dist/{cost-DNGKT4UC.js → cost-OQGFNBBG.js} +3 -8
- package/dist/cost-OQGFNBBG.js.map +1 -0
- package/dist/daemon/supervisor-worker.js +7 -1
- package/dist/daemon/supervisor-worker.js.map +1 -1
- package/dist/daemon/worker.js +27 -10
- package/dist/daemon/worker.js.map +1 -1
- package/dist/decision-PNZ2S2TU.js +362 -0
- package/dist/decision-PNZ2S2TU.js.map +1 -0
- package/dist/doctor-ZBO73UID.js +337 -0
- package/dist/doctor-ZBO73UID.js.map +1 -0
- package/dist/guide-UQRNA3FC.js +23 -0
- package/dist/guide-UQRNA3FC.js.map +1 -0
- package/dist/index.js +17 -9
- package/dist/index.js.map +1 -1
- package/dist/{init-YNSPTCA3.js → init-UYS6KS5U.js} +4 -20
- package/dist/init-UYS6KS5U.js.map +1 -0
- package/dist/log-PTHLI7ZN.js +141 -0
- package/dist/log-PTHLI7ZN.js.map +1 -0
- package/dist/{mcp-GH6CCW7A.js → mcp-XHZND5A4.js} +6 -1
- package/dist/mcp-XHZND5A4.js.map +1 -0
- package/dist/memory-6R22DFS7.js +292 -0
- package/dist/memory-6R22DFS7.js.map +1 -0
- package/dist/{run-KIU2ZE72.js → run-OF53USMD.js} +46 -20
- package/dist/run-OF53USMD.js.map +1 -0
- package/dist/{runs-CHA2JM5K.js → runs-TAASM3YF.js} +16 -12
- package/dist/runs-TAASM3YF.js.map +1 -0
- package/dist/status-LQOFOJJI.js +90 -0
- package/dist/status-LQOFOJJI.js.map +1 -0
- package/dist/{supervise-KIB2EYY4.js → supervise-FI6MYULH.js} +33 -28
- package/dist/supervise-FI6MYULH.js.map +1 -0
- package/dist/supervisor-3RUX5SPH.js +16 -0
- package/dist/supervisor-3RUX5SPH.js.map +1 -0
- package/dist/{tui-QS3RPHKH.js → tui-JJ6CD2YW.js} +377 -43
- package/dist/tui-JJ6CD2YW.js.map +1 -0
- package/dist/version-XVOAMGDD.js +26 -0
- package/dist/version-XVOAMGDD.js.map +1 -0
- package/dist/webhooks-PUKAHFHE.js +151 -0
- package/dist/webhooks-PUKAHFHE.js.map +1 -0
- package/package.json +22 -4
- package/dist/chunk-CP54H7WA.js.map +0 -1
- package/dist/cost-DNGKT4UC.js.map +0 -1
- package/dist/doctor-GC4NH7H6.js +0 -173
- package/dist/doctor-GC4NH7H6.js.map +0 -1
- package/dist/init-YNSPTCA3.js.map +0 -1
- package/dist/mcp-GH6CCW7A.js.map +0 -1
- package/dist/run-KIU2ZE72.js.map +0 -1
- package/dist/runs-CHA2JM5K.js.map +0 -1
- package/dist/supervise-KIB2EYY4.js.map +0 -1
- package/dist/tui-QS3RPHKH.js.map +0 -1
- /package/dist/{agents-Y6LREFXP.js.map → agents-PH3P7G7E.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadRunsFiltered,
|
|
3
3
|
resolveRepoFilter
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3ZP3BQXB.js";
|
|
5
5
|
import {
|
|
6
6
|
printError,
|
|
7
7
|
printJson,
|
|
@@ -23,6 +23,14 @@ function totalDuration(run) {
|
|
|
23
23
|
function shortId(runId) {
|
|
24
24
|
return runId.slice(0, 8);
|
|
25
25
|
}
|
|
26
|
+
function repoName(run) {
|
|
27
|
+
return run.repo.split("/").pop() ?? run.repo;
|
|
28
|
+
}
|
|
29
|
+
function agentName(run) {
|
|
30
|
+
if (run.agent) return run.agent;
|
|
31
|
+
const stepAgent = Object.values(run.steps)[0]?.agent;
|
|
32
|
+
return stepAgent ?? "unknown";
|
|
33
|
+
}
|
|
26
34
|
function showRunDetail(match, short) {
|
|
27
35
|
if (short) {
|
|
28
36
|
console.log(`${match.runId} ${match.status} $${totalCost(match).toFixed(4)}`);
|
|
@@ -59,7 +67,7 @@ function listRuns(runs, short) {
|
|
|
59
67
|
for (const r of runs) {
|
|
60
68
|
const agent = Object.values(r.steps)[0]?.agent ?? "?";
|
|
61
69
|
console.log(
|
|
62
|
-
`${shortId(r.runId)} ${r.status.padEnd(9)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`
|
|
70
|
+
`${shortId(r.runId)} ${r.status.padEnd(9)} ${repoName(r).padEnd(14)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`
|
|
63
71
|
);
|
|
64
72
|
}
|
|
65
73
|
return;
|
|
@@ -69,11 +77,12 @@ function listRuns(runs, short) {
|
|
|
69
77
|
return;
|
|
70
78
|
}
|
|
71
79
|
printTable(
|
|
72
|
-
["RUN", "STATUS", "AGENT", "COST", "DURATION", "BRANCH"],
|
|
80
|
+
["RUN", "STATUS", "REPO", "AGENT", "COST", "DURATION", "BRANCH"],
|
|
73
81
|
runs.map((r) => [
|
|
74
82
|
shortId(r.runId),
|
|
75
83
|
r.status,
|
|
76
|
-
|
|
84
|
+
repoName(r),
|
|
85
|
+
agentName(r),
|
|
77
86
|
`$${totalCost(r).toFixed(4)}`,
|
|
78
87
|
formatDuration(totalDuration(r)),
|
|
79
88
|
r.branch?.replace("feat/run-", "").slice(0, 8) ?? "-"
|
|
@@ -91,11 +100,6 @@ var runs_default = defineCommand({
|
|
|
91
100
|
description: "Run ID to show details (omit to list all runs)",
|
|
92
101
|
required: false
|
|
93
102
|
},
|
|
94
|
-
all: {
|
|
95
|
-
type: "boolean",
|
|
96
|
-
description: "Show runs from all repos",
|
|
97
|
-
default: false
|
|
98
|
-
},
|
|
99
103
|
repo: {
|
|
100
104
|
type: "string",
|
|
101
105
|
description: "Filter by repo name or path"
|
|
@@ -120,7 +124,7 @@ var runs_default = defineCommand({
|
|
|
120
124
|
},
|
|
121
125
|
async run({ args }) {
|
|
122
126
|
const jsonOutput = args.output === "json";
|
|
123
|
-
const filter = await resolveRepoFilter({
|
|
127
|
+
const filter = await resolveRepoFilter({ repo: args.repo });
|
|
124
128
|
let runs = await loadRunsFiltered(filter);
|
|
125
129
|
if (runs.length === 0) {
|
|
126
130
|
if (!jsonOutput) {
|
|
@@ -158,7 +162,7 @@ var runs_default = defineCommand({
|
|
|
158
162
|
runId: r.runId,
|
|
159
163
|
status: r.status,
|
|
160
164
|
repo: r.repo,
|
|
161
|
-
agent:
|
|
165
|
+
agent: agentName(r),
|
|
162
166
|
costUsd: totalCost(r),
|
|
163
167
|
durationMs: totalDuration(r),
|
|
164
168
|
branch: r.branch,
|
|
@@ -173,4 +177,4 @@ var runs_default = defineCommand({
|
|
|
173
177
|
export {
|
|
174
178
|
runs_default as default
|
|
175
179
|
};
|
|
176
|
-
//# sourceMappingURL=runs-
|
|
180
|
+
//# sourceMappingURL=runs-TAASM3YF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/runs.ts"],"sourcesContent":["import type { PersistedRun } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printTable } from \"../output.js\";\nimport { loadRunsFiltered, resolveRepoFilter } from \"../repo-filter.js\";\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction totalCost(run: PersistedRun): number {\n return Object.values(run.steps).reduce((sum, s) => sum + s.costUsd, 0);\n}\n\nfunction totalDuration(run: PersistedRun): number {\n return Object.values(run.steps).reduce((sum, s) => sum + s.durationMs, 0);\n}\n\nfunction shortId(runId: string): string {\n return runId.slice(0, 8);\n}\n\nfunction repoName(run: PersistedRun): string {\n return run.repo.split(\"/\").pop() ?? run.repo;\n}\n\nfunction agentName(run: PersistedRun): string {\n // Use run.agent directly (new schema)\n if (run.agent) return run.agent;\n\n // Fall back to step's agent field for older runs\n const stepAgent = Object.values(run.steps)[0]?.agent;\n return stepAgent ?? \"unknown\";\n}\n\nfunction showRunDetail(match: PersistedRun, short: boolean): void {\n if (short) {\n console.log(`${match.runId} ${match.status} $${totalCost(match).toFixed(4)}`);\n for (const [name, step] of Object.entries(match.steps)) {\n const out = typeof step.output === \"string\" ? step.output.slice(0, 200) : \"\";\n console.log(` ${name}: ${step.status} ${step.agent} ${out}`);\n }\n return;\n }\n\n console.log(`Run: ${match.runId}`);\n console.log(`Status: ${match.status}`);\n console.log(`Repo: ${match.repo}`);\n console.log(`Prompt: ${match.prompt}`);\n if (match.branch) console.log(`Branch: ${match.branch}`);\n console.log(`Cost: $${totalCost(match).toFixed(4)}`);\n console.log(`Duration: ${formatDuration(totalDuration(match))}`);\n console.log(`Created: ${match.createdAt}`);\n console.log(\"\");\n for (const [name, step] of Object.entries(match.steps)) {\n console.log(`Step: ${name}`);\n console.log(` Agent: ${step.agent}`);\n console.log(` Status: ${step.status}`);\n console.log(` Cost: $${step.costUsd.toFixed(4)}`);\n console.log(` Duration: ${formatDuration(step.durationMs)}`);\n if (step.error) console.log(` Error: ${step.error}`);\n if (step.output) {\n const out = typeof step.output === \"string\" ? step.output : JSON.stringify(step.output);\n console.log(` Output: ${out}`);\n }\n }\n}\n\nfunction listRuns(runs: PersistedRun[], short: boolean): void {\n if (short) {\n for (const r of runs) {\n const agent = Object.values(r.steps)[0]?.agent ?? \"?\";\n console.log(\n `${shortId(r.runId)} ${r.status.padEnd(9)} ${repoName(r).padEnd(14)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`,\n );\n }\n return;\n }\n\n if (runs.length === 0) {\n console.log(\"No runs found.\");\n return;\n }\n\n printTable(\n [\"RUN\", \"STATUS\", \"REPO\", \"AGENT\", \"COST\", \"DURATION\", \"BRANCH\"],\n runs.map((r) => [\n shortId(r.runId),\n r.status,\n repoName(r),\n agentName(r),\n `$${totalCost(r).toFixed(4)}`,\n formatDuration(totalDuration(r)),\n r.branch?.replace(\"feat/run-\", \"\").slice(0, 8) ?? \"-\",\n ]),\n );\n}\n\nexport default defineCommand({\n meta: {\n name: \"runs\",\n description: \"List runs or show details of a specific run\",\n },\n args: {\n runId: {\n type: \"positional\",\n description: \"Run ID to show details (omit to list all runs)\",\n required: false,\n },\n repo: {\n type: \"string\",\n description: \"Filter by repo name or path\",\n },\n last: {\n type: \"string\",\n description: \"Show only the last N runs\",\n },\n status: {\n type: \"string\",\n description: \"Filter by status: completed, failed, running\",\n },\n short: {\n type: \"boolean\",\n description: \"Compact output for supervisor agents (saves tokens)\",\n default: false,\n },\n output: {\n type: \"string\",\n description: \"Output format: json\",\n },\n },\n async run({ args }) {\n const jsonOutput = args.output === \"json\";\n const filter = await resolveRepoFilter({ repo: args.repo });\n let runs = await loadRunsFiltered(filter);\n\n if (runs.length === 0) {\n if (!jsonOutput) {\n printError(\"No runs found. Run 'neo run <agent>' first.\");\n } else {\n printJson([]);\n }\n return;\n }\n\n // If a runId is given (full or prefix), show details\n if (args.runId) {\n const match = runs.find(\n (r) => r.runId === args.runId || r.runId.startsWith(args.runId as string),\n );\n if (!match) {\n printError(`Run \"${args.runId}\" not found.`);\n process.exitCode = 1;\n return;\n }\n\n if (jsonOutput) {\n printJson(match);\n return;\n }\n\n showRunDetail(match, args.short);\n return;\n }\n\n // List mode\n if (args.status) {\n runs = runs.filter((r) => r.status === args.status);\n }\n\n if (args.last) {\n runs = runs.slice(0, Number(args.last));\n }\n\n if (jsonOutput) {\n printJson(\n runs.map((r) => ({\n runId: r.runId,\n status: r.status,\n repo: r.repo,\n agent: agentName(r),\n costUsd: totalCost(r),\n durationMs: totalDuration(r),\n branch: r.branch,\n updatedAt: r.updatedAt,\n })),\n );\n return;\n }\n\n listRuns(runs, args.short);\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printError,
|
|
3
|
+
printJson,
|
|
4
|
+
printSuccess
|
|
5
|
+
} from "./chunk-YQIWMDXL.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/supervisor/status.ts
|
|
8
|
+
import { getSupervisorDir, StatusReader } from "@neotx/core";
|
|
9
|
+
import { defineCommand } from "citty";
|
|
10
|
+
var DEFAULT_NAME = "supervisor";
|
|
11
|
+
function formatUptime(startedAt) {
|
|
12
|
+
const start = new Date(startedAt).getTime();
|
|
13
|
+
const now = Date.now();
|
|
14
|
+
const diffMs = now - start;
|
|
15
|
+
const seconds = Math.floor(diffMs / 1e3) % 60;
|
|
16
|
+
const minutes = Math.floor(diffMs / (1e3 * 60)) % 60;
|
|
17
|
+
const hours = Math.floor(diffMs / (1e3 * 60 * 60)) % 24;
|
|
18
|
+
const days = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
|
|
19
|
+
if (days > 0) {
|
|
20
|
+
return `${days}d ${hours}h ${minutes}m`;
|
|
21
|
+
}
|
|
22
|
+
if (hours > 0) {
|
|
23
|
+
return `${hours}h ${minutes}m ${seconds}s`;
|
|
24
|
+
}
|
|
25
|
+
if (minutes > 0) {
|
|
26
|
+
return `${minutes}m ${seconds}s`;
|
|
27
|
+
}
|
|
28
|
+
return `${seconds}s`;
|
|
29
|
+
}
|
|
30
|
+
function formatStatus(status) {
|
|
31
|
+
const stateColor = status.status === "running" ? "32" : status.status === "idle" ? "33" : "31";
|
|
32
|
+
const stateDisplay = `\x1B[${stateColor}m${status.status}\x1B[0m`;
|
|
33
|
+
printSuccess(`Supervisor running (PID ${status.pid})`);
|
|
34
|
+
console.log(` State: ${stateDisplay}`);
|
|
35
|
+
console.log(` Uptime: ${formatUptime(status.startedAt)}`);
|
|
36
|
+
console.log(` Active runs: ${status.activeRunCount}`);
|
|
37
|
+
console.log(` Heartbeats: ${status.heartbeatCount}`);
|
|
38
|
+
console.log(` Last beat: ${status.lastHeartbeat}`);
|
|
39
|
+
console.log(` Cost today: $${status.todayCostUsd.toFixed(2)}`);
|
|
40
|
+
console.log(` Cost total: $${status.totalCostUsd.toFixed(2)}`);
|
|
41
|
+
if (status.recentActivitySummary.length > 0) {
|
|
42
|
+
console.log("\nRecent activity:");
|
|
43
|
+
for (const activity of status.recentActivitySummary.slice(0, 5)) {
|
|
44
|
+
console.log(` \u2022 ${activity}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
var status_default = defineCommand({
|
|
49
|
+
meta: {
|
|
50
|
+
name: "status",
|
|
51
|
+
description: "Show current supervisor status"
|
|
52
|
+
},
|
|
53
|
+
args: {
|
|
54
|
+
name: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "Supervisor instance name",
|
|
57
|
+
default: DEFAULT_NAME
|
|
58
|
+
},
|
|
59
|
+
json: {
|
|
60
|
+
type: "boolean",
|
|
61
|
+
description: "Output as JSON",
|
|
62
|
+
default: false
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async run({ args }) {
|
|
66
|
+
const name = args.name;
|
|
67
|
+
const dataDir = getSupervisorDir(name);
|
|
68
|
+
const reader = new StatusReader(dataDir);
|
|
69
|
+
const status = await reader.getStatus();
|
|
70
|
+
if (!status) {
|
|
71
|
+
if (args.json) {
|
|
72
|
+
printJson({ running: false, error: "Supervisor is not running" });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
printError(`Supervisor "${name}" is not running.`);
|
|
76
|
+
console.log("\nStart the supervisor with: neo supervise --detach");
|
|
77
|
+
process.exitCode = 1;
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (args.json) {
|
|
81
|
+
printJson(status);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
formatStatus(status);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
export {
|
|
88
|
+
status_default as default
|
|
89
|
+
};
|
|
90
|
+
//# sourceMappingURL=status-LQOFOJJI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/supervisor/status.ts"],"sourcesContent":["import { getSupervisorDir, StatusReader, type SupervisorStatus } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printSuccess } from \"../../output.js\";\n\nconst DEFAULT_NAME = \"supervisor\";\n\nfunction formatUptime(startedAt: string): string {\n const start = new Date(startedAt).getTime();\n const now = Date.now();\n const diffMs = now - start;\n\n const seconds = Math.floor(diffMs / 1000) % 60;\n const minutes = Math.floor(diffMs / (1000 * 60)) % 60;\n const hours = Math.floor(diffMs / (1000 * 60 * 60)) % 24;\n const days = Math.floor(diffMs / (1000 * 60 * 60 * 24));\n\n if (days > 0) {\n return `${days}d ${hours}h ${minutes}m`;\n }\n if (hours > 0) {\n return `${hours}h ${minutes}m ${seconds}s`;\n }\n if (minutes > 0) {\n return `${minutes}m ${seconds}s`;\n }\n return `${seconds}s`;\n}\n\nfunction formatStatus(status: SupervisorStatus): void {\n const stateColor = status.status === \"running\" ? \"32\" : status.status === \"idle\" ? \"33\" : \"31\";\n const stateDisplay = `\\x1b[${stateColor}m${status.status}\\x1b[0m`;\n\n printSuccess(`Supervisor running (PID ${status.pid})`);\n console.log(` State: ${stateDisplay}`);\n console.log(` Uptime: ${formatUptime(status.startedAt)}`);\n console.log(` Active runs: ${status.activeRunCount}`);\n console.log(` Heartbeats: ${status.heartbeatCount}`);\n console.log(` Last beat: ${status.lastHeartbeat}`);\n console.log(` Cost today: $${status.todayCostUsd.toFixed(2)}`);\n console.log(` Cost total: $${status.totalCostUsd.toFixed(2)}`);\n\n if (status.recentActivitySummary.length > 0) {\n console.log(\"\\nRecent activity:\");\n for (const activity of status.recentActivitySummary.slice(0, 5)) {\n console.log(` • ${activity}`);\n }\n }\n}\n\nexport default defineCommand({\n meta: {\n name: \"status\",\n description: \"Show current supervisor status\",\n },\n args: {\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: DEFAULT_NAME,\n },\n json: {\n type: \"boolean\",\n description: \"Output as JSON\",\n default: false,\n },\n },\n async run({ args }) {\n const name = args.name;\n const dataDir = getSupervisorDir(name);\n const reader = new StatusReader(dataDir);\n\n const status = await reader.getStatus();\n\n if (!status) {\n if (args.json) {\n printJson({ running: false, error: \"Supervisor is not running\" });\n return;\n }\n printError(`Supervisor \"${name}\" is not running.`);\n console.log(\"\\nStart the supervisor with: neo supervise --detach\");\n process.exitCode = 1;\n return;\n }\n\n if (args.json) {\n printJson(status);\n return;\n }\n\n formatStatus(status);\n },\n});\n"],"mappings":";;;;;;;AAAA,SAAS,kBAAkB,oBAA2C;AACtE,SAAS,qBAAqB;AAG9B,IAAM,eAAe;AAErB,SAAS,aAAa,WAA2B;AAC/C,QAAM,QAAQ,IAAI,KAAK,SAAS,EAAE,QAAQ;AAC1C,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,SAAS,MAAM;AAErB,QAAM,UAAU,KAAK,MAAM,SAAS,GAAI,IAAI;AAC5C,QAAM,UAAU,KAAK,MAAM,UAAU,MAAO,GAAG,IAAI;AACnD,QAAM,QAAQ,KAAK,MAAM,UAAU,MAAO,KAAK,GAAG,IAAI;AACtD,QAAM,OAAO,KAAK,MAAM,UAAU,MAAO,KAAK,KAAK,GAAG;AAEtD,MAAI,OAAO,GAAG;AACZ,WAAO,GAAG,IAAI,KAAK,KAAK,KAAK,OAAO;AAAA,EACtC;AACA,MAAI,QAAQ,GAAG;AACb,WAAO,GAAG,KAAK,KAAK,OAAO,KAAK,OAAO;AAAA,EACzC;AACA,MAAI,UAAU,GAAG;AACf,WAAO,GAAG,OAAO,KAAK,OAAO;AAAA,EAC/B;AACA,SAAO,GAAG,OAAO;AACnB;AAEA,SAAS,aAAa,QAAgC;AACpD,QAAM,aAAa,OAAO,WAAW,YAAY,OAAO,OAAO,WAAW,SAAS,OAAO;AAC1F,QAAM,eAAe,QAAQ,UAAU,IAAI,OAAO,MAAM;AAExD,eAAa,2BAA2B,OAAO,GAAG,GAAG;AACrD,UAAQ,IAAI,kBAAkB,YAAY,EAAE;AAC5C,UAAQ,IAAI,kBAAkB,aAAa,OAAO,SAAS,CAAC,EAAE;AAC9D,UAAQ,IAAI,kBAAkB,OAAO,cAAc,EAAE;AACrD,UAAQ,IAAI,kBAAkB,OAAO,cAAc,EAAE;AACrD,UAAQ,IAAI,kBAAkB,OAAO,aAAa,EAAE;AACpD,UAAQ,IAAI,mBAAmB,OAAO,aAAa,QAAQ,CAAC,CAAC,EAAE;AAC/D,UAAQ,IAAI,mBAAmB,OAAO,aAAa,QAAQ,CAAC,CAAC,EAAE;AAE/D,MAAI,OAAO,sBAAsB,SAAS,GAAG;AAC3C,YAAQ,IAAI,oBAAoB;AAChC,eAAW,YAAY,OAAO,sBAAsB,MAAM,GAAG,CAAC,GAAG;AAC/D,cAAQ,IAAI,YAAO,QAAQ,EAAE;AAAA,IAC/B;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,OAAO,KAAK;AAClB,UAAM,UAAU,iBAAiB,IAAI;AACrC,UAAM,SAAS,IAAI,aAAa,OAAO;AAEvC,UAAM,SAAS,MAAM,OAAO,UAAU;AAEtC,QAAI,CAAC,QAAQ;AACX,UAAI,KAAK,MAAM;AACb,kBAAU,EAAE,SAAS,OAAO,OAAO,4BAA4B,CAAC;AAChE;AAAA,MACF;AACA,iBAAW,eAAe,IAAI,mBAAmB;AACjD,cAAQ,IAAI,qDAAqD;AACjE,cAAQ,WAAW;AACnB;AAAA,IACF;AAEA,QAAI,KAAK,MAAM;AACb,gBAAU,MAAM;AAChB;AAAA,IACF;AAEA,iBAAa,MAAM;AAAA,EACrB;AACF,CAAC;","names":[]}
|
|
@@ -11,10 +11,12 @@ import { appendFile, mkdir, readFile, rm } from "fs/promises";
|
|
|
11
11
|
import path from "path";
|
|
12
12
|
import { fileURLToPath } from "url";
|
|
13
13
|
import {
|
|
14
|
+
getSupervisorActivityPath,
|
|
14
15
|
getSupervisorDir,
|
|
15
16
|
getSupervisorInboxPath,
|
|
16
17
|
getSupervisorLockPath,
|
|
17
18
|
getSupervisorStatePath,
|
|
19
|
+
isProcessAlive,
|
|
18
20
|
loadGlobalConfig,
|
|
19
21
|
supervisorDaemonStateSchema
|
|
20
22
|
} from "@neotx/core";
|
|
@@ -30,14 +32,6 @@ async function readState(name) {
|
|
|
30
32
|
return null;
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
|
-
function isProcessAlive(pid) {
|
|
34
|
-
try {
|
|
35
|
-
process.kill(pid, 0);
|
|
36
|
-
return true;
|
|
37
|
-
} catch {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
35
|
async function isDaemonRunning(name) {
|
|
42
36
|
const state = await readState(name);
|
|
43
37
|
if (!state || state.status === "stopped") return null;
|
|
@@ -56,9 +50,7 @@ async function handleStatus(name) {
|
|
|
56
50
|
console.log(` Port: ${state.port}`);
|
|
57
51
|
console.log(` Session: ${state.sessionId}`);
|
|
58
52
|
console.log(` Started: ${state.startedAt}`);
|
|
59
|
-
console.log(
|
|
60
|
-
` Interval: ${config.supervisor.idleIntervalMs / 1e3}s (skip up to ${config.supervisor.idleSkipMax} idle)`
|
|
61
|
-
);
|
|
53
|
+
console.log(` Timeout: ${config.supervisor.eventTimeoutMs / 1e3}s`);
|
|
62
54
|
console.log(` Heartbeats: ${state.heartbeatCount}`);
|
|
63
55
|
if (state.lastHeartbeat) {
|
|
64
56
|
console.log(` Last beat: ${state.lastHeartbeat}`);
|
|
@@ -68,7 +60,7 @@ async function handleStatus(name) {
|
|
|
68
60
|
console.log(` Status: ${state.status}`);
|
|
69
61
|
console.log("");
|
|
70
62
|
console.log(` Health: curl localhost:${state.port}/health`);
|
|
71
|
-
console.log("
|
|
63
|
+
console.log(" TUI: neo supervise");
|
|
72
64
|
console.log(" Stop: neo supervise --kill");
|
|
73
65
|
}
|
|
74
66
|
async function handleKill(name) {
|
|
@@ -112,7 +104,7 @@ async function startDaemon(name) {
|
|
|
112
104
|
const running = await isDaemonRunning(name);
|
|
113
105
|
if (running) {
|
|
114
106
|
printError(`Supervisor "${name}" is already running (PID ${running.pid}).`);
|
|
115
|
-
printError("Use --kill first, or
|
|
107
|
+
printError("Use --kill first, or run neo supervise to open TUI.");
|
|
116
108
|
process.exitCode = 1;
|
|
117
109
|
return;
|
|
118
110
|
}
|
|
@@ -140,7 +132,7 @@ async function startDaemon(name) {
|
|
|
140
132
|
console.log(` Health: curl localhost:${config.supervisor.port}/health`);
|
|
141
133
|
console.log(` Webhook: curl -X POST localhost:${config.supervisor.port}/webhook -d '{}'`);
|
|
142
134
|
console.log(` Logs: ${getSupervisorDir(name)}/daemon.log`);
|
|
143
|
-
console.log(`
|
|
135
|
+
console.log(` TUI: neo supervise`);
|
|
144
136
|
console.log(` Status: neo supervise --status`);
|
|
145
137
|
console.log(` Stop: neo supervise --kill`);
|
|
146
138
|
}
|
|
@@ -152,7 +144,7 @@ async function handleAttach(name) {
|
|
|
152
144
|
process.exitCode = 1;
|
|
153
145
|
return;
|
|
154
146
|
}
|
|
155
|
-
const { renderSupervisorTui } = await import("./tui-
|
|
147
|
+
const { renderSupervisorTui } = await import("./tui-JJ6CD2YW.js");
|
|
156
148
|
await renderSupervisorTui(name);
|
|
157
149
|
}
|
|
158
150
|
async function handleMessage(name, text) {
|
|
@@ -162,14 +154,13 @@ async function handleMessage(name, text) {
|
|
|
162
154
|
process.exitCode = 1;
|
|
163
155
|
return;
|
|
164
156
|
}
|
|
165
|
-
const
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
await appendFile(inboxPath, `${JSON.stringify(message)}
|
|
157
|
+
const id = randomUUID();
|
|
158
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
159
|
+
const message = { id, from: "api", text, timestamp };
|
|
160
|
+
await appendFile(getSupervisorInboxPath(name), `${JSON.stringify(message)}
|
|
161
|
+
`, "utf-8");
|
|
162
|
+
const activityEntry = { id, type: "message", summary: text, timestamp };
|
|
163
|
+
await appendFile(getSupervisorActivityPath(name), `${JSON.stringify(activityEntry)}
|
|
173
164
|
`, "utf-8");
|
|
174
165
|
printSuccess(`Message sent to supervisor "${name}".`);
|
|
175
166
|
}
|
|
@@ -196,7 +187,13 @@ var supervise_default = defineCommand({
|
|
|
196
187
|
},
|
|
197
188
|
attach: {
|
|
198
189
|
type: "boolean",
|
|
199
|
-
description: "Open the TUI for a running supervisor",
|
|
190
|
+
description: "Open the TUI for a running supervisor (default when no flags given)",
|
|
191
|
+
default: false
|
|
192
|
+
},
|
|
193
|
+
detach: {
|
|
194
|
+
type: "boolean",
|
|
195
|
+
alias: "d",
|
|
196
|
+
description: "Start daemon in the background without opening the TUI",
|
|
200
197
|
default: false
|
|
201
198
|
},
|
|
202
199
|
message: {
|
|
@@ -222,16 +219,24 @@ var supervise_default = defineCommand({
|
|
|
222
219
|
await handleMessage(name, args.message);
|
|
223
220
|
return;
|
|
224
221
|
}
|
|
222
|
+
if (args.detach) {
|
|
223
|
+
const alreadyRunning2 = await isDaemonRunning(name);
|
|
224
|
+
if (alreadyRunning2) {
|
|
225
|
+
printSuccess(`Supervisor "${name}" already running (PID ${alreadyRunning2.pid}).`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
await startDaemon(name);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
225
231
|
const alreadyRunning = await isDaemonRunning(name);
|
|
226
232
|
if (!alreadyRunning) {
|
|
227
233
|
await startDaemon(name);
|
|
228
|
-
await new Promise((r) => setTimeout(r,
|
|
234
|
+
await new Promise((r) => setTimeout(r, 1500));
|
|
229
235
|
}
|
|
230
|
-
|
|
231
|
-
await renderSupervisorTui(name);
|
|
236
|
+
await handleAttach(name);
|
|
232
237
|
}
|
|
233
238
|
});
|
|
234
239
|
export {
|
|
235
240
|
supervise_default as default
|
|
236
241
|
};
|
|
237
|
-
//# sourceMappingURL=supervise-
|
|
242
|
+
//# sourceMappingURL=supervise-FI6MYULH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/supervise.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { closeSync, existsSync, openSync } from \"node:fs\";\nimport { appendFile, mkdir, readFile, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n getSupervisorActivityPath,\n getSupervisorDir,\n getSupervisorInboxPath,\n getSupervisorLockPath,\n getSupervisorStatePath,\n isProcessAlive,\n loadGlobalConfig,\n type SupervisorDaemonState,\n supervisorDaemonStateSchema,\n} from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess } from \"../output.js\";\n\nconst DEFAULT_NAME = \"supervisor\";\n\nasync function readState(name: string): Promise<SupervisorDaemonState | null> {\n const statePath = getSupervisorStatePath(name);\n if (!existsSync(statePath)) return null;\n try {\n const raw = await readFile(statePath, \"utf-8\");\n return supervisorDaemonStateSchema.parse(JSON.parse(raw));\n } catch {\n return null;\n }\n}\n\nasync function isDaemonRunning(name: string): Promise<SupervisorDaemonState | null> {\n const state = await readState(name);\n if (!state || state.status === \"stopped\") return null;\n if (!isProcessAlive(state.pid)) return null;\n return state;\n}\n\nasync function handleStatus(name: string): Promise<void> {\n const state = await isDaemonRunning(name);\n if (!state) {\n console.log(`No supervisor daemon running (name: ${name}).`);\n return;\n }\n\n const config = await loadGlobalConfig();\n printSuccess(`Supervisor \"${name}\" running`);\n console.log(` PID: ${state.pid}`);\n console.log(` Port: ${state.port}`);\n console.log(` Session: ${state.sessionId}`);\n console.log(` Started: ${state.startedAt}`);\n console.log(` Timeout: ${config.supervisor.eventTimeoutMs / 1000}s`);\n console.log(` Heartbeats: ${state.heartbeatCount}`);\n if (state.lastHeartbeat) {\n console.log(` Last beat: ${state.lastHeartbeat}`);\n }\n console.log(` Cost today: $${state.todayCostUsd?.toFixed(2) ?? \"0.00\"}`);\n console.log(` Cost total: $${state.totalCostUsd?.toFixed(2) ?? \"0.00\"}`);\n console.log(` Status: ${state.status}`);\n console.log(\"\");\n console.log(` Health: curl localhost:${state.port}/health`);\n console.log(\" TUI: neo supervise\");\n console.log(\" Stop: neo supervise --kill\");\n}\n\nasync function handleKill(name: string): Promise<void> {\n const state = await isDaemonRunning(name);\n if (!state) {\n printError(`No supervisor daemon running (name: ${name}).`);\n\n // Clean up stale lock if exists\n const lockPath = getSupervisorLockPath(name);\n if (existsSync(lockPath)) {\n await rm(lockPath, { force: true });\n }\n process.exitCode = 1;\n return;\n }\n\n // Send SIGTERM for graceful shutdown, then SIGKILL after 10s\n const pid = state.pid;\n try {\n process.kill(pid, \"SIGTERM\");\n printSuccess(`Sent SIGTERM to supervisor \"${name}\" (PID ${pid})`);\n } catch {\n printError(`Failed to send signal to PID ${pid}. Cleaning up.`);\n const lockPath = getSupervisorLockPath(name);\n await rm(lockPath, { force: true });\n return;\n }\n\n // Wait up to 10s for graceful exit, then force kill\n const deadline = Date.now() + 10_000;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 500));\n if (!isProcessAlive(pid)) {\n printSuccess(\"Daemon stopped.\");\n return;\n }\n }\n\n // Force kill\n try {\n process.kill(pid, \"SIGKILL\");\n printSuccess(`Daemon did not exit in time — sent SIGKILL (PID ${pid}).`);\n } catch {\n // Already dead\n }\n\n // Clean up lock\n const lockPath = getSupervisorLockPath(name);\n await rm(lockPath, { force: true });\n}\n\nasync function startDaemon(name: string): Promise<void> {\n const running = await isDaemonRunning(name);\n if (running) {\n printError(`Supervisor \"${name}\" is already running (PID ${running.pid}).`);\n printError(\"Use --kill first, or run neo supervise to open TUI.\");\n process.exitCode = 1;\n return;\n }\n\n // Clean up stale lock\n const lockPath = getSupervisorLockPath(name);\n if (existsSync(lockPath)) {\n await rm(lockPath, { force: true });\n }\n\n // Resolve the worker script path and package root (for module resolution)\n const __dirname = path.dirname(fileURLToPath(import.meta.url));\n const workerPath = path.join(__dirname, \"daemon\", \"supervisor-worker.js\");\n const packageRoot = path.resolve(__dirname, \"..\");\n\n // Spawn as detached child process with stdio to log file\n const logDir = getSupervisorDir(name);\n await mkdir(logDir, { recursive: true });\n const logFd = openSync(path.join(logDir, \"daemon.log\"), \"a\");\n const child = spawn(process.execPath, [workerPath, name], {\n detached: true,\n stdio: [\"ignore\", logFd, logFd],\n cwd: packageRoot,\n env: process.env,\n });\n child.unref();\n closeSync(logFd);\n\n const config = await loadGlobalConfig();\n printSuccess(`Supervisor \"${name}\" started (PID ${child.pid})`);\n console.log(` Port: ${config.supervisor.port}`);\n console.log(` Health: curl localhost:${config.supervisor.port}/health`);\n console.log(` Webhook: curl -X POST localhost:${config.supervisor.port}/webhook -d '{}'`);\n console.log(` Logs: ${getSupervisorDir(name)}/daemon.log`);\n console.log(` TUI: neo supervise`);\n console.log(` Status: neo supervise --status`);\n console.log(` Stop: neo supervise --kill`);\n}\n\nasync function handleAttach(name: string): Promise<void> {\n const running = await isDaemonRunning(name);\n if (!running) {\n printError(`No supervisor daemon running (name: ${name}).`);\n printError(\"Start with: neo supervise\");\n process.exitCode = 1;\n return;\n }\n\n const { renderSupervisorTui } = await import(\"../tui/index.js\");\n await renderSupervisorTui(name);\n}\n\nasync function handleMessage(name: string, text: string): Promise<void> {\n const running = await isDaemonRunning(name);\n if (!running) {\n printError(`No supervisor daemon running (name: ${name}).`);\n process.exitCode = 1;\n return;\n }\n\n const id = randomUUID();\n const timestamp = new Date().toISOString();\n\n const message = { id, from: \"api\" as const, text, timestamp };\n await appendFile(getSupervisorInboxPath(name), `${JSON.stringify(message)}\\n`, \"utf-8\");\n\n // Write to activity.jsonl so the message appears in the TUI conversation\n const activityEntry = { id, type: \"message\", summary: text, timestamp };\n await appendFile(getSupervisorActivityPath(name), `${JSON.stringify(activityEntry)}\\n`, \"utf-8\");\n\n printSuccess(`Message sent to supervisor \"${name}\".`);\n}\n\nexport default defineCommand({\n meta: {\n name: \"supervise\",\n description: \"Manage the autonomous supervisor daemon\",\n },\n args: {\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: DEFAULT_NAME,\n },\n status: {\n type: \"boolean\",\n description: \"Show supervisor status\",\n default: false,\n },\n kill: {\n type: \"boolean\",\n description: \"Stop the running supervisor\",\n default: false,\n },\n attach: {\n type: \"boolean\",\n description: \"Open the TUI for a running supervisor (default when no flags given)\",\n default: false,\n },\n detach: {\n type: \"boolean\",\n alias: \"d\",\n description: \"Start daemon in the background without opening the TUI\",\n default: false,\n },\n message: {\n type: \"string\",\n description: \"Send a message to the supervisor inbox\",\n },\n },\n async run({ args }) {\n const name = args.name;\n\n if (args.status) {\n await handleStatus(name);\n return;\n }\n\n if (args.kill) {\n await handleKill(name);\n return;\n }\n\n if (args.attach) {\n await handleAttach(name);\n return;\n }\n\n if (args.message) {\n await handleMessage(name, args.message);\n return;\n }\n\n // --detach: start daemon headless (no TUI)\n if (args.detach) {\n const alreadyRunning = await isDaemonRunning(name);\n if (alreadyRunning) {\n printSuccess(`Supervisor \"${name}\" already running (PID ${alreadyRunning.pid}).`);\n return;\n }\n await startDaemon(name);\n return;\n }\n\n // Default: start daemon if needed, then open TUI\n const alreadyRunning = await isDaemonRunning(name);\n if (!alreadyRunning) {\n await startDaemon(name);\n // Wait briefly for daemon to initialize before attaching\n await new Promise((r) => setTimeout(r, 1500));\n }\n await handleAttach(name);\n },\n});\n"],"mappings":"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","names":["lockPath","alreadyRunning"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// src/commands/supervisor/index.ts
|
|
2
|
+
import { defineCommand } from "citty";
|
|
3
|
+
var supervisor_default = defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "supervisor",
|
|
6
|
+
description: "Supervisor status and activity"
|
|
7
|
+
},
|
|
8
|
+
subCommands: {
|
|
9
|
+
status: () => import("./status-LQOFOJJI.js").then((m) => m.default),
|
|
10
|
+
activity: () => import("./activity-LWUVGQVN.js").then((m) => m.default)
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
export {
|
|
14
|
+
supervisor_default as default
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=supervisor-3RUX5SPH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/supervisor/index.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\n\nexport default defineCommand({\n meta: {\n name: \"supervisor\",\n description: \"Supervisor status and activity\",\n },\n subCommands: {\n status: () => import(\"./status.js\").then((m) => m.default),\n activity: () => import(\"./activity.js\").then((m) => m.default),\n },\n});\n"],"mappings":";AAAA,SAAS,qBAAqB;AAE9B,IAAO,qBAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,aAAa;AAAA,IACX,QAAQ,MAAM,OAAO,sBAAa,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACzD,UAAU,MAAM,OAAO,wBAAe,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,EAC/D;AACF,CAAC;","names":[]}
|