@neotx/cli 0.1.0-alpha.22 → 0.1.0-alpha.25

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.
Files changed (46) hide show
  1. package/dist/child-5X5IHAKS.js +92 -0
  2. package/dist/child-5X5IHAKS.js.map +1 -0
  3. package/dist/child-mode-IB3XSUHD.js +8 -0
  4. package/dist/child-mode-IB3XSUHD.js.map +1 -0
  5. package/dist/chunk-4TQ3Q6IE.js +43 -0
  6. package/dist/chunk-4TQ3Q6IE.js.map +1 -0
  7. package/dist/chunk-6PSXZ3UV.js +46 -0
  8. package/dist/chunk-6PSXZ3UV.js.map +1 -0
  9. package/dist/chunk-V5SN5F73.js +54 -0
  10. package/dist/chunk-V5SN5F73.js.map +1 -0
  11. package/dist/daemon/child-supervisor-worker.js +136 -0
  12. package/dist/daemon/child-supervisor-worker.js.map +1 -0
  13. package/dist/daemon/supervisor-worker.js +9 -1
  14. package/dist/daemon/supervisor-worker.js.map +1 -1
  15. package/dist/daemon/worker.js +16 -3
  16. package/dist/daemon/worker.js.map +1 -1
  17. package/dist/{decision-PNZ2S2TU.js → decision-T2526ITK.js} +35 -2
  18. package/dist/decision-T2526ITK.js.map +1 -0
  19. package/dist/directive-7WM2Q2UW.js +259 -0
  20. package/dist/directive-7WM2Q2UW.js.map +1 -0
  21. package/dist/do-F5XW2ELZ.js +83 -0
  22. package/dist/do-F5XW2ELZ.js.map +1 -0
  23. package/dist/health-SWQ6V4H5.js +72 -0
  24. package/dist/health-SWQ6V4H5.js.map +1 -0
  25. package/dist/index.js +10 -6
  26. package/dist/index.js.map +1 -1
  27. package/dist/{log-PTHLI7ZN.js → log-ZLIAIBZQ.js} +64 -9
  28. package/dist/log-ZLIAIBZQ.js.map +1 -0
  29. package/dist/{memory-SDZ57W2S.js → memory-CW6E65SQ.js} +112 -62
  30. package/dist/memory-CW6E65SQ.js.map +1 -0
  31. package/dist/{run-MWHIQUSY.js → run-NV762V5B.js} +56 -22
  32. package/dist/run-NV762V5B.js.map +1 -0
  33. package/dist/{supervise-XMZRNODO.js → supervise-BWIKWNHH.js} +68 -41
  34. package/dist/supervise-BWIKWNHH.js.map +1 -0
  35. package/dist/{supervisor-3RUX5SPH.js → supervisor-N4D5EWCC.js} +1 -1
  36. package/dist/tui-LSW7VVK6.js +1319 -0
  37. package/dist/tui-LSW7VVK6.js.map +1 -0
  38. package/package.json +4 -4
  39. package/dist/decision-PNZ2S2TU.js.map +0 -1
  40. package/dist/log-PTHLI7ZN.js.map +0 -1
  41. package/dist/memory-SDZ57W2S.js.map +0 -1
  42. package/dist/run-MWHIQUSY.js.map +0 -1
  43. package/dist/supervise-XMZRNODO.js.map +0 -1
  44. package/dist/tui-67VJ5VBA.js +0 -842
  45. package/dist/tui-67VJ5VBA.js.map +0 -1
  46. /package/dist/{supervisor-3RUX5SPH.js.map → supervisor-N4D5EWCC.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/decision.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Decision, DecisionOption, InboxMessage } from \"@neotx/core\";\nimport { DecisionStore, getSupervisorDecisionsPath, getSupervisorDir } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printSuccess, printTable } from \"../output.js\";\n\nconst DEFAULT_EXPIRES_MS = 24 * 60 * 60 * 1000; // 24 hours\n\ninterface ParsedArgs {\n action: string;\n value: string | undefined;\n question: string | undefined;\n options: string | undefined;\n defaultAnswer: string | undefined;\n expiresIn: string | undefined;\n type: string | undefined;\n context: string | undefined;\n name: string;\n id: string | undefined;\n answer: string | undefined;\n json: boolean;\n wait: boolean;\n timeout: string;\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction formatStatus(decision: Decision): string {\n if (decision.answer !== undefined) {\n return \"answered\";\n }\n if (decision.expiredAt !== undefined) {\n return \"expired\";\n }\n if (decision.expiresAt && decision.expiresAt < new Date().toISOString()) {\n return \"expired\";\n }\n return \"pending\";\n}\n\nfunction formatTimeAgo(timestamp: string): string {\n const ms = Date.now() - new Date(timestamp).getTime();\n const seconds = Math.floor(ms / 1000);\n if (seconds < 60) return `${seconds}s ago`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n return `${hours}h ago`;\n}\n\nfunction parseDurationMs(input: string): number | undefined {\n const match = input.match(/^(\\d+)(h|m|d)$/);\n if (!match) return undefined;\n\n const value = Number(match[1]);\n const unit = match[2];\n switch (unit) {\n case \"d\":\n return value * 24 * 60 * 60 * 1000;\n case \"h\":\n return value * 60 * 60 * 1000;\n case \"m\":\n return value * 60 * 1000;\n default:\n return undefined;\n }\n}\n\nfunction parseOptions(optionsArg: string): DecisionOption[] | undefined {\n // Format: \"key1:label1,key2:label2\" or \"key1:label1:description1,key2:label2:description2\"\n if (!optionsArg.trim()) return undefined;\n\n const options: DecisionOption[] = [];\n const parts = optionsArg.split(\",\");\n\n for (const part of parts) {\n const segments = part.trim().split(\":\");\n const key = segments[0];\n const label = segments[1];\n if (!key || !label) {\n throw new Error(\n `Invalid option format: \"${part}\". Expected \"key:label\" or \"key:label:description\"`,\n );\n }\n const descParts = segments.slice(2);\n options.push({\n key: key.trim(),\n label: label.trim(),\n description: descParts.length > 0 ? descParts.join(\":\").trim() : undefined,\n });\n }\n\n return options.length > 0 ? options : undefined;\n}\n\nfunction openStore(name: string): DecisionStore {\n const filePath = getSupervisorDecisionsPath(name);\n return new DecisionStore(filePath);\n}\n\nasync function pollForAnswer(store: DecisionStore, id: string, timeout: string): Promise<void> {\n const timeoutMs = parseDurationMs(timeout) ?? 30 * 60 * 1000;\n const startTime = Date.now();\n const pollIntervalMs = 10_000;\n\n process.stdout.write(`Waiting for answer (timeout: ${timeout})...\\n`);\n\n while (Date.now() - startTime < timeoutMs) {\n const decision = await store.get(id);\n if (decision?.answer !== undefined) {\n console.log(`Answer: ${decision.answer}`);\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n\n printError(`Decision ${id} timed out after ${timeout}`);\n process.exitCode = 1;\n}\n\nasync function handleCreate(args: ParsedArgs): Promise<void> {\n if (!args.question) {\n printError(\n \"Usage: neo decision create <question> --options 'key1:label1,key2:label2' [--default <key>] [--expires-in 24h]\",\n );\n process.exitCode = 1;\n return;\n }\n\n let options: DecisionOption[] | undefined;\n if (args.options) {\n try {\n options = parseOptions(args.options);\n } catch (error) {\n printError(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n return;\n }\n }\n\n let expiresAt: string | undefined;\n if (args.expiresIn) {\n const ms = parseDurationMs(args.expiresIn);\n if (!ms) {\n printError('Invalid --expires-in format. Use e.g. \"24h\", \"30m\", or \"7d\".');\n process.exitCode = 1;\n return;\n }\n expiresAt = new Date(Date.now() + ms).toISOString();\n } else {\n // Default to 24 hours\n expiresAt = new Date(Date.now() + DEFAULT_EXPIRES_MS).toISOString();\n }\n\n const store = openStore(args.name);\n try {\n const id = await store.create({\n question: args.question,\n options,\n defaultAnswer: args.defaultAnswer,\n expiresAt,\n type: args.type ?? \"generic\",\n source: \"supervisor\",\n context: args.context,\n });\n printSuccess(`Decision created: ${id}`);\n console.log(id); // Output just the ID for easy parsing in scripts\n\n if (args.wait) {\n await pollForAnswer(store, id, args.timeout);\n }\n } catch (error) {\n printError(\n `Failed to create decision: ${error instanceof Error ? error.message : String(error)}`,\n );\n process.exitCode = 1;\n }\n}\n\nasync function handleList(args: ParsedArgs): Promise<void> {\n const store = openStore(args.name);\n const pending = await store.pending();\n\n if (args.json) {\n printJson(pending);\n return;\n }\n\n if (pending.length === 0) {\n console.log(\"No pending decisions.\");\n return;\n }\n\n printTable(\n [\"ID\", \"TYPE\", \"QUESTION\", \"SOURCE\", \"CREATED\"],\n pending.map((d) => [\n d.id.slice(0, 12),\n d.type,\n truncate(d.question, 50),\n d.source,\n formatTimeAgo(d.createdAt),\n ]),\n );\n}\n\nasync function handleGet(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo decision get <id>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n const decision = await store.get(args.value);\n\n if (!decision) {\n printError(`Decision not found: ${args.value}`);\n process.exitCode = 1;\n return;\n }\n\n if (args.json) {\n printJson(decision);\n return;\n }\n\n const status = formatStatus(decision);\n console.log(`ID: ${decision.id}`);\n console.log(`Status: ${status}`);\n console.log(`Type: ${decision.type}`);\n console.log(`Source: ${decision.source}`);\n console.log(`Created: ${decision.createdAt}`);\n console.log();\n console.log(`Question: ${decision.question}`);\n if (decision.context) {\n console.log();\n console.log(`Context:\\n${decision.context}`);\n }\n if (decision.options && decision.options.length > 0) {\n console.log();\n console.log(\"Options:\");\n for (const opt of decision.options) {\n console.log(` [${opt.key}] ${opt.label}${opt.description ? ` - ${opt.description}` : \"\"}`);\n }\n }\n if (decision.answer !== undefined) {\n console.log();\n console.log(`Answer: ${decision.answer}`);\n if (decision.answeredAt) {\n console.log(`Answered: ${decision.answeredAt}`);\n }\n }\n if (decision.defaultAnswer !== undefined) {\n console.log(`Default: ${decision.defaultAnswer}`);\n }\n if (decision.expiresAt) {\n console.log(`Expires: ${decision.expiresAt}`);\n }\n}\n\nasync function handleAnswer(args: ParsedArgs): Promise<void> {\n // Parse positional args from process.argv\n const argv = process.argv;\n const answerIdx = argv.indexOf(\"answer\");\n const idArg = argv[answerIdx + 1];\n const answerArg = argv[answerIdx + 2];\n\n if (!idArg || !answerArg) {\n printError(\"Usage: neo decision answer <id> <answer>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n\n try {\n await store.answer(idArg, answerArg);\n\n // Wake up the supervisor heartbeat by appending to inbox.jsonl\n const dir = getSupervisorDir(args.name);\n const inboxMessage: InboxMessage = {\n id: randomUUID(),\n from: \"external\",\n text: `decision:answer ${idArg} ${answerArg}`,\n timestamp: new Date().toISOString(),\n };\n const inboxPath = path.join(dir, \"inbox.jsonl\");\n try {\n await mkdir(dir, { recursive: true });\n await appendFile(inboxPath, `${JSON.stringify(inboxMessage)}\\n`, \"utf-8\");\n } catch (error) {\n // Log but don't fail the answer operation - the decision was still recorded\n console.error(\n `Warning: Failed to write to inbox: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n printSuccess(`Decision answered: ${idArg} → \"${answerArg}\"`);\n } catch (error) {\n printError(error instanceof Error ? error.message : \"Unknown error\");\n process.exitCode = 1;\n }\n}\n\nasync function handlePending(args: ParsedArgs): Promise<void> {\n const store = openStore(args.name);\n const pending = await store.pending();\n\n if (args.json) {\n printJson(pending);\n return;\n }\n\n if (pending.length === 0) {\n console.log(\"No pending decisions.\");\n return;\n }\n\n // Show more detailed view for pending decisions\n for (const d of pending) {\n console.log(`─────────────────────────────────────────`);\n console.log(`ID: ${d.id} (${formatTimeAgo(d.createdAt)})`);\n console.log(`Question: ${d.question}`);\n if (d.options && d.options.length > 0) {\n console.log(\"Options:\");\n for (const opt of d.options) {\n console.log(` [${opt.key}] ${opt.label}`);\n }\n }\n if (d.defaultAnswer) {\n console.log(`Default: ${d.defaultAnswer}`);\n }\n console.log();\n }\n console.log(`─────────────────────────────────────────`);\n console.log(`\\nAnswer with: neo decision answer <id> <answer>`);\n}\n\nexport default defineCommand({\n meta: {\n name: \"decision\",\n description: \"Manage supervisor decision gates\",\n },\n args: {\n action: {\n type: \"positional\",\n description: \"Action: create, list, get, answer, pending\",\n required: true,\n },\n value: {\n type: \"positional\",\n description: \"Decision ID (for get/answer) or question text (for create)\",\n required: false,\n },\n options: {\n type: \"string\",\n alias: \"o\",\n description:\n 'Options in format \"key1:label1,key2:label2\" or \"key1:label1:desc1,key2:label2:desc2\"',\n },\n \"default-answer\": {\n type: \"string\",\n alias: \"d\",\n description: \"Default answer key (used if decision expires)\",\n },\n \"expires-in\": {\n type: \"string\",\n alias: \"e\",\n description: \"Expiration duration (e.g. 24h, 30m, 7d). Default: 24h\",\n },\n type: {\n type: \"string\",\n alias: \"t\",\n description: \"Decision type (default: generic)\",\n },\n context: {\n type: \"string\",\n alias: \"c\",\n description: \"Additional context for the decision\",\n },\n name: {\n type: \"string\",\n description: \"Supervisor name\",\n default: \"supervisor\",\n },\n json: {\n type: \"boolean\",\n description: \"Output as JSON\",\n default: false,\n },\n wait: {\n type: \"boolean\",\n alias: \"w\",\n description: \"Block until the decision is answered (poll every 10s)\",\n default: false,\n },\n timeout: {\n type: \"string\",\n description: \"Max wait time when using --wait (e.g. 30m, 1h). Default: 30m\",\n default: \"30m\",\n },\n },\n async run({ args }) {\n const action = args.action as string;\n const parsed: ParsedArgs = {\n action,\n value: args.value as string | undefined,\n question: args.value as string | undefined, // For create action\n options: args.options as string | undefined,\n defaultAnswer: args[\"default-answer\"] as string | undefined,\n expiresIn: args[\"expires-in\"] as string | undefined,\n type: args.type as string | undefined,\n context: args.context as string | undefined,\n name: args.name as string,\n id: args.value as string | undefined, // For get/answer actions\n answer: undefined,\n json: args.json as boolean,\n wait: args.wait as boolean,\n timeout: args.timeout as string,\n };\n\n switch (action) {\n case \"create\":\n return handleCreate(parsed);\n case \"list\":\n return handleList(parsed);\n case \"get\":\n return handleGet(parsed);\n case \"answer\":\n return handleAnswer(parsed);\n case \"pending\":\n return handlePending(parsed);\n default:\n printError(\n `Unknown action \"${action}\". Must be one of: create, list, get, answer, pending`,\n );\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,259 @@
1
+ import {
2
+ printError,
3
+ printSuccess,
4
+ printTable
5
+ } from "./chunk-YQIWMDXL.js";
6
+
7
+ // src/commands/directive.ts
8
+ import path from "path";
9
+ import {
10
+ DirectiveStore,
11
+ getSupervisorDir,
12
+ parseDirectiveDuration
13
+ } from "@neotx/core";
14
+ import { defineCommand } from "citty";
15
+ var VALID_TRIGGERS = ["idle", "startup", "shutdown"];
16
+ function openStore(name) {
17
+ const dir = getSupervisorDir(name);
18
+ return new DirectiveStore(path.join(dir, "directives.jsonl"));
19
+ }
20
+ function formatExpiry(expiresAt) {
21
+ if (!expiresAt) return "\u221E";
22
+ const date = new Date(expiresAt);
23
+ const now = /* @__PURE__ */ new Date();
24
+ if (date < now) return "expired";
25
+ const diffMs = date.getTime() - now.getTime();
26
+ const hours = Math.floor(diffMs / (60 * 60 * 1e3));
27
+ const minutes = Math.floor(diffMs % (60 * 60 * 1e3) / (60 * 1e3));
28
+ if (hours > 24) {
29
+ const days = Math.floor(hours / 24);
30
+ return `${days}d ${hours % 24}h`;
31
+ }
32
+ if (hours > 0) {
33
+ return `${hours}h ${minutes}m`;
34
+ }
35
+ return `${minutes}m`;
36
+ }
37
+ async function handleCreate(args) {
38
+ if (!args.value) {
39
+ printError('Usage: neo directive create "<action>" [--trigger idle] [--duration "2h"]');
40
+ process.exitCode = 1;
41
+ return;
42
+ }
43
+ const trigger = args.trigger;
44
+ if (!VALID_TRIGGERS.includes(trigger)) {
45
+ printError(`Invalid trigger "${trigger}". Must be one of: ${VALID_TRIGGERS.join(", ")}`);
46
+ process.exitCode = 1;
47
+ return;
48
+ }
49
+ let expiresAt;
50
+ if (args.duration) {
51
+ expiresAt = parseDirectiveDuration(args.duration);
52
+ const isIndefinite = ["indefinitely", "forever", ""].includes(
53
+ args.duration.toLowerCase().trim()
54
+ );
55
+ if (expiresAt === void 0 && !isIndefinite) {
56
+ printError(
57
+ `Invalid --duration format "${args.duration}". Use: "2h", "30m", "for 2 hours", "until midnight", "until 18:00", or "indefinitely"`
58
+ );
59
+ process.exitCode = 1;
60
+ return;
61
+ }
62
+ }
63
+ const store = openStore(args.name);
64
+ const input = {
65
+ trigger,
66
+ action: args.value
67
+ };
68
+ if (args.description) {
69
+ input.description = args.description;
70
+ }
71
+ if (args.priority) {
72
+ input.priority = Number(args.priority);
73
+ }
74
+ if (expiresAt) {
75
+ input.expiresAt = expiresAt;
76
+ }
77
+ const id = await store.create(input);
78
+ const expiryLabel = expiresAt ? formatExpiry(expiresAt) : "indefinitely";
79
+ printSuccess(`Directive created: ${id}`);
80
+ console.log(` Trigger: ${trigger}`);
81
+ console.log(` Action: ${args.value}`);
82
+ console.log(` Duration: ${expiryLabel}`);
83
+ }
84
+ async function handleList(args) {
85
+ const store = openStore(args.name);
86
+ const directives = await store.list();
87
+ if (directives.length === 0) {
88
+ console.log("No directives found.");
89
+ return;
90
+ }
91
+ printTable(
92
+ ["ID", "TRIGGER", "STATUS", "EXPIRES", "PRIORITY", "ACTION"],
93
+ directives.map((d) => {
94
+ const now = (/* @__PURE__ */ new Date()).toISOString();
95
+ let status = d.enabled ? "active" : "disabled";
96
+ if (d.expiresAt && d.expiresAt < now) {
97
+ status = "expired";
98
+ }
99
+ return [
100
+ d.id,
101
+ d.trigger,
102
+ status,
103
+ formatExpiry(d.expiresAt),
104
+ String(d.priority),
105
+ d.action.length > 40 ? `${d.action.slice(0, 37)}...` : d.action
106
+ ];
107
+ })
108
+ );
109
+ }
110
+ async function handleDelete(args) {
111
+ if (!args.value) {
112
+ printError("Usage: neo directive delete <id>");
113
+ process.exitCode = 1;
114
+ return;
115
+ }
116
+ const store = openStore(args.name);
117
+ try {
118
+ await store.delete(args.value);
119
+ printSuccess(`Directive deleted: ${args.value}`);
120
+ } catch (err) {
121
+ printError(err instanceof Error ? err.message : String(err));
122
+ process.exitCode = 1;
123
+ }
124
+ }
125
+ async function handleToggle(args) {
126
+ if (!args.value) {
127
+ printError("Usage: neo directive toggle <id>");
128
+ process.exitCode = 1;
129
+ return;
130
+ }
131
+ const store = openStore(args.name);
132
+ try {
133
+ const directive = await store.get(args.value);
134
+ if (!directive) {
135
+ printError(`Directive not found: ${args.value}`);
136
+ process.exitCode = 1;
137
+ return;
138
+ }
139
+ const newState = !directive.enabled;
140
+ await store.toggle(args.value, newState);
141
+ printSuccess(`Directive ${args.value} ${newState ? "enabled" : "disabled"}`);
142
+ } catch (err) {
143
+ printError(err instanceof Error ? err.message : String(err));
144
+ process.exitCode = 1;
145
+ }
146
+ }
147
+ async function handleShow(args) {
148
+ if (!args.value) {
149
+ printError("Usage: neo directive show <id>");
150
+ process.exitCode = 1;
151
+ return;
152
+ }
153
+ const store = openStore(args.name);
154
+ const directive = await store.get(args.value);
155
+ if (!directive) {
156
+ printError(`Directive not found: ${args.value}`);
157
+ process.exitCode = 1;
158
+ return;
159
+ }
160
+ const now = (/* @__PURE__ */ new Date()).toISOString();
161
+ let status = directive.enabled ? "active" : "disabled";
162
+ if (directive.expiresAt && directive.expiresAt < now) {
163
+ status = "expired";
164
+ }
165
+ console.log(`ID: ${directive.id}`);
166
+ console.log(`Trigger: ${directive.trigger}`);
167
+ console.log(`Status: ${status}`);
168
+ console.log(`Priority: ${directive.priority}`);
169
+ console.log(`Action: ${directive.action}`);
170
+ if (directive.description) {
171
+ console.log(`Description: ${directive.description}`);
172
+ }
173
+ console.log(`Created: ${directive.createdAt}`);
174
+ if (directive.expiresAt) {
175
+ console.log(`Expires: ${directive.expiresAt} (${formatExpiry(directive.expiresAt)})`);
176
+ } else {
177
+ console.log(`Expires: never (indefinite)`);
178
+ }
179
+ if (directive.lastTriggeredAt) {
180
+ console.log(`Last triggered: ${directive.lastTriggeredAt}`);
181
+ }
182
+ }
183
+ var directive_default = defineCommand({
184
+ meta: {
185
+ name: "directive",
186
+ description: "Manage persistent supervisor directives"
187
+ },
188
+ args: {
189
+ action: {
190
+ type: "positional",
191
+ description: "Action: create, list, delete, toggle, show",
192
+ required: true
193
+ },
194
+ value: {
195
+ type: "positional",
196
+ description: "Action text or directive ID",
197
+ required: false
198
+ },
199
+ trigger: {
200
+ type: "string",
201
+ alias: "t",
202
+ description: "Trigger type: idle, startup, shutdown",
203
+ default: "idle"
204
+ },
205
+ duration: {
206
+ type: "string",
207
+ alias: "d",
208
+ description: 'Duration: "2h", "until midnight", "for 2 hours", "indefinitely"'
209
+ },
210
+ priority: {
211
+ type: "string",
212
+ alias: "p",
213
+ description: "Priority (higher = execute first)",
214
+ default: "0"
215
+ },
216
+ description: {
217
+ type: "string",
218
+ description: "Human-readable description"
219
+ },
220
+ name: {
221
+ type: "string",
222
+ description: "Supervisor name",
223
+ default: "supervisor"
224
+ }
225
+ },
226
+ async run({ args }) {
227
+ const action = args.action;
228
+ const parsed = {
229
+ action,
230
+ value: args.value,
231
+ trigger: args.trigger,
232
+ duration: args.duration,
233
+ priority: args.priority,
234
+ description: args.description,
235
+ name: args.name
236
+ };
237
+ switch (action) {
238
+ case "create":
239
+ return handleCreate(parsed);
240
+ case "list":
241
+ return handleList(parsed);
242
+ case "delete":
243
+ return handleDelete(parsed);
244
+ case "toggle":
245
+ return handleToggle(parsed);
246
+ case "show":
247
+ return handleShow(parsed);
248
+ default:
249
+ printError(
250
+ `Unknown action "${action}". Must be one of: create, list, delete, toggle, show`
251
+ );
252
+ process.exitCode = 1;
253
+ }
254
+ }
255
+ });
256
+ export {
257
+ directive_default as default
258
+ };
259
+ //# sourceMappingURL=directive-7WM2Q2UW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/directive.ts"],"sourcesContent":["import path from \"node:path\";\nimport {\n DirectiveStore,\n type DirectiveTrigger,\n getSupervisorDir,\n parseDirectiveDuration,\n} from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess, printTable } from \"../output.js\";\n\nconst VALID_TRIGGERS = [\"idle\", \"startup\", \"shutdown\"] as const;\n\ninterface ParsedArgs {\n action: string;\n value: string | undefined;\n trigger: string;\n duration: string | undefined;\n priority: string | undefined;\n description: string | undefined;\n name: string;\n}\n\nfunction openStore(name: string): DirectiveStore {\n const dir = getSupervisorDir(name);\n return new DirectiveStore(path.join(dir, \"directives.jsonl\"));\n}\n\nfunction formatExpiry(expiresAt: string | undefined): string {\n if (!expiresAt) return \"∞\";\n const date = new Date(expiresAt);\n const now = new Date();\n if (date < now) return \"expired\";\n\n const diffMs = date.getTime() - now.getTime();\n const hours = Math.floor(diffMs / (60 * 60 * 1000));\n const minutes = Math.floor((diffMs % (60 * 60 * 1000)) / (60 * 1000));\n\n if (hours > 24) {\n const days = Math.floor(hours / 24);\n return `${days}d ${hours % 24}h`;\n }\n if (hours > 0) {\n return `${hours}h ${minutes}m`;\n }\n return `${minutes}m`;\n}\n\nasync function handleCreate(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError('Usage: neo directive create \"<action>\" [--trigger idle] [--duration \"2h\"]');\n process.exitCode = 1;\n return;\n }\n\n const trigger = args.trigger as DirectiveTrigger;\n if (!VALID_TRIGGERS.includes(trigger)) {\n printError(`Invalid trigger \"${trigger}\". Must be one of: ${VALID_TRIGGERS.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n let expiresAt: string | undefined;\n if (args.duration) {\n expiresAt = parseDirectiveDuration(args.duration);\n // parseDirectiveDuration returns undefined for \"indefinitely\" which is valid\n // But if user provided something and we got undefined, it might be invalid format\n // Check against known indefinite keywords\n const isIndefinite = [\"indefinitely\", \"forever\", \"\"].includes(\n args.duration.toLowerCase().trim(),\n );\n if (expiresAt === undefined && !isIndefinite) {\n printError(\n `Invalid --duration format \"${args.duration}\". Use: \"2h\", \"30m\", \"for 2 hours\", \"until midnight\", \"until 18:00\", or \"indefinitely\"`,\n );\n process.exitCode = 1;\n return;\n }\n }\n\n const store = openStore(args.name);\n const input: Parameters<typeof store.create>[0] = {\n trigger,\n action: args.value,\n };\n if (args.description) {\n input.description = args.description;\n }\n if (args.priority) {\n input.priority = Number(args.priority);\n }\n if (expiresAt) {\n input.expiresAt = expiresAt;\n }\n const id = await store.create(input);\n\n const expiryLabel = expiresAt ? formatExpiry(expiresAt) : \"indefinitely\";\n printSuccess(`Directive created: ${id}`);\n console.log(` Trigger: ${trigger}`);\n console.log(` Action: ${args.value}`);\n console.log(` Duration: ${expiryLabel}`);\n}\n\nasync function handleList(args: ParsedArgs): Promise<void> {\n const store = openStore(args.name);\n const directives = await store.list();\n\n if (directives.length === 0) {\n console.log(\"No directives found.\");\n return;\n }\n\n printTable(\n [\"ID\", \"TRIGGER\", \"STATUS\", \"EXPIRES\", \"PRIORITY\", \"ACTION\"],\n directives.map((d) => {\n const now = new Date().toISOString();\n let status = d.enabled ? \"active\" : \"disabled\";\n if (d.expiresAt && d.expiresAt < now) {\n status = \"expired\";\n }\n\n return [\n d.id,\n d.trigger,\n status,\n formatExpiry(d.expiresAt),\n String(d.priority),\n d.action.length > 40 ? `${d.action.slice(0, 37)}...` : d.action,\n ];\n }),\n );\n}\n\nasync function handleDelete(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo directive delete <id>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n try {\n await store.delete(args.value);\n printSuccess(`Directive deleted: ${args.value}`);\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n}\n\nasync function handleToggle(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo directive toggle <id>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n try {\n const directive = await store.get(args.value);\n if (!directive) {\n printError(`Directive not found: ${args.value}`);\n process.exitCode = 1;\n return;\n }\n\n const newState = !directive.enabled;\n await store.toggle(args.value, newState);\n printSuccess(`Directive ${args.value} ${newState ? \"enabled\" : \"disabled\"}`);\n } catch (err) {\n printError(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n }\n}\n\nasync function handleShow(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo directive show <id>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n const directive = await store.get(args.value);\n\n if (!directive) {\n printError(`Directive not found: ${args.value}`);\n process.exitCode = 1;\n return;\n }\n\n const now = new Date().toISOString();\n let status = directive.enabled ? \"active\" : \"disabled\";\n if (directive.expiresAt && directive.expiresAt < now) {\n status = \"expired\";\n }\n\n console.log(`ID: ${directive.id}`);\n console.log(`Trigger: ${directive.trigger}`);\n console.log(`Status: ${status}`);\n console.log(`Priority: ${directive.priority}`);\n console.log(`Action: ${directive.action}`);\n if (directive.description) {\n console.log(`Description: ${directive.description}`);\n }\n console.log(`Created: ${directive.createdAt}`);\n if (directive.expiresAt) {\n console.log(`Expires: ${directive.expiresAt} (${formatExpiry(directive.expiresAt)})`);\n } else {\n console.log(`Expires: never (indefinite)`);\n }\n if (directive.lastTriggeredAt) {\n console.log(`Last triggered: ${directive.lastTriggeredAt}`);\n }\n}\n\nexport default defineCommand({\n meta: {\n name: \"directive\",\n description: \"Manage persistent supervisor directives\",\n },\n args: {\n action: {\n type: \"positional\",\n description: \"Action: create, list, delete, toggle, show\",\n required: true,\n },\n value: {\n type: \"positional\",\n description: \"Action text or directive ID\",\n required: false,\n },\n trigger: {\n type: \"string\",\n alias: \"t\",\n description: \"Trigger type: idle, startup, shutdown\",\n default: \"idle\",\n },\n duration: {\n type: \"string\",\n alias: \"d\",\n description: 'Duration: \"2h\", \"until midnight\", \"for 2 hours\", \"indefinitely\"',\n },\n priority: {\n type: \"string\",\n alias: \"p\",\n description: \"Priority (higher = execute first)\",\n default: \"0\",\n },\n description: {\n type: \"string\",\n description: \"Human-readable description\",\n },\n name: {\n type: \"string\",\n description: \"Supervisor name\",\n default: \"supervisor\",\n },\n },\n async run({ args }) {\n const action = args.action as string;\n const parsed: ParsedArgs = {\n action,\n value: args.value as string | undefined,\n trigger: args.trigger as string,\n duration: args.duration as string | undefined,\n priority: args.priority as string | undefined,\n description: args.description as string | undefined,\n name: args.name as string,\n };\n\n switch (action) {\n case \"create\":\n return handleCreate(parsed);\n case \"list\":\n return handleList(parsed);\n case \"delete\":\n return handleDelete(parsed);\n case \"toggle\":\n return handleToggle(parsed);\n case \"show\":\n return handleShow(parsed);\n default:\n printError(\n `Unknown action \"${action}\". Must be one of: create, list, delete, toggle, show`,\n );\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,83 @@
1
+ import {
2
+ isDaemonRunning,
3
+ startDaemonDetached
4
+ } from "./chunk-V5SN5F73.js";
5
+ import "./chunk-6PSXZ3UV.js";
6
+ import {
7
+ printError,
8
+ printSuccess
9
+ } from "./chunk-YQIWMDXL.js";
10
+
11
+ // src/commands/do.ts
12
+ import { randomUUID } from "crypto";
13
+ import { appendFile } from "fs/promises";
14
+ import { getSupervisorActivityPath, getSupervisorInboxPath } from "@neotx/core";
15
+ import { defineCommand } from "citty";
16
+ var DEFAULT_NAME = "supervisor";
17
+ var do_default = defineCommand({
18
+ meta: {
19
+ name: "do",
20
+ description: "Send a task to the supervisor (alias for neo supervise --message)"
21
+ },
22
+ args: {
23
+ task: {
24
+ type: "positional",
25
+ description: "Task description to send to the supervisor",
26
+ required: true
27
+ },
28
+ name: {
29
+ type: "string",
30
+ description: "Supervisor instance name",
31
+ default: DEFAULT_NAME
32
+ },
33
+ detach: {
34
+ type: "boolean",
35
+ alias: "d",
36
+ description: "Start supervisor in background if not running",
37
+ default: false
38
+ }
39
+ },
40
+ async run({ args }) {
41
+ const name = args.name;
42
+ const task = args.task;
43
+ let running = await isDaemonRunning(name);
44
+ if (!running) {
45
+ if (args.detach) {
46
+ const result = await startDaemonDetached(name);
47
+ if (result.error) {
48
+ printError(`Failed to start supervisor daemon: ${result.error}`);
49
+ process.exitCode = 1;
50
+ return;
51
+ }
52
+ printSuccess(`Supervisor "${name}" started (PID ${result.pid})`);
53
+ await new Promise((r) => setTimeout(r, 1500));
54
+ running = await isDaemonRunning(name);
55
+ } else {
56
+ printError(`No supervisor daemon running (name: ${name}).`);
57
+ printError("Use --detach to start one, or run: neo supervise");
58
+ process.exitCode = 1;
59
+ return;
60
+ }
61
+ }
62
+ const id = randomUUID();
63
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
64
+ const message = { id, from: "api", text: task, timestamp };
65
+ await appendFile(getSupervisorInboxPath(name), `${JSON.stringify(message)}
66
+ `, "utf-8");
67
+ const activityEntry = { id, type: "message", summary: task, timestamp };
68
+ await appendFile(
69
+ getSupervisorActivityPath(name),
70
+ `${JSON.stringify(activityEntry)}
71
+ `,
72
+ "utf-8"
73
+ );
74
+ printSuccess(`Task sent to supervisor "${name}"`);
75
+ console.log(` Task: ${task.slice(0, 80)}${task.length > 80 ? "..." : ""}`);
76
+ console.log(` Status: neo supervise --status`);
77
+ console.log(` TUI: neo supervise`);
78
+ }
79
+ });
80
+ export {
81
+ do_default as default
82
+ };
83
+ //# sourceMappingURL=do-F5XW2ELZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/do.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport { getSupervisorActivityPath, getSupervisorInboxPath } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { isDaemonRunning, startDaemonDetached } from \"../daemon-utils.js\";\nimport { printError, printSuccess } from \"../output.js\";\n\nconst DEFAULT_NAME = \"supervisor\";\n\nexport default defineCommand({\n meta: {\n name: \"do\",\n description: \"Send a task to the supervisor (alias for neo supervise --message)\",\n },\n args: {\n task: {\n type: \"positional\",\n description: \"Task description to send to the supervisor\",\n required: true,\n },\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: DEFAULT_NAME,\n },\n detach: {\n type: \"boolean\",\n alias: \"d\",\n description: \"Start supervisor in background if not running\",\n default: false,\n },\n },\n async run({ args }) {\n const name = args.name as string;\n const task = args.task as string;\n\n let running = await isDaemonRunning(name);\n\n if (!running) {\n if (args.detach) {\n const result = await startDaemonDetached(name);\n if (result.error) {\n printError(`Failed to start supervisor daemon: ${result.error}`);\n process.exitCode = 1;\n return;\n }\n printSuccess(`Supervisor \"${name}\" started (PID ${result.pid})`);\n // Wait briefly for daemon to initialize\n await new Promise((r) => setTimeout(r, 1500));\n running = await isDaemonRunning(name);\n } else {\n printError(`No supervisor daemon running (name: ${name}).`);\n printError(\"Use --detach to start one, or run: neo supervise\");\n process.exitCode = 1;\n return;\n }\n }\n\n // Send message to inbox\n const id = randomUUID();\n const timestamp = new Date().toISOString();\n const message = { id, from: \"api\" as const, text: task, timestamp };\n\n await appendFile(getSupervisorInboxPath(name), `${JSON.stringify(message)}\\n`, \"utf-8\");\n\n // Also write to activity.jsonl for TUI visibility\n const activityEntry = { id, type: \"message\", summary: task, timestamp };\n await appendFile(\n getSupervisorActivityPath(name),\n `${JSON.stringify(activityEntry)}\\n`,\n \"utf-8\",\n );\n\n printSuccess(`Task sent to supervisor \"${name}\"`);\n console.log(` Task: ${task.slice(0, 80)}${task.length > 80 ? \"...\" : \"\"}`);\n console.log(` Status: neo supervise --status`);\n console.log(` TUI: neo supervise`);\n },\n});\n"],"mappings":";;;;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,2BAA2B,8BAA8B;AAClE,SAAS,qBAAqB;AAI9B,IAAM,eAAe;AAErB,IAAO,aAAQ,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,UAAU;AAAA,IACZ;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,OAAO,KAAK;AAClB,UAAM,OAAO,KAAK;AAElB,QAAI,UAAU,MAAM,gBAAgB,IAAI;AAExC,QAAI,CAAC,SAAS;AACZ,UAAI,KAAK,QAAQ;AACf,cAAM,SAAS,MAAM,oBAAoB,IAAI;AAC7C,YAAI,OAAO,OAAO;AAChB,qBAAW,sCAAsC,OAAO,KAAK,EAAE;AAC/D,kBAAQ,WAAW;AACnB;AAAA,QACF;AACA,qBAAa,eAAe,IAAI,kBAAkB,OAAO,GAAG,GAAG;AAE/D,cAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC;AAC5C,kBAAU,MAAM,gBAAgB,IAAI;AAAA,MACtC,OAAO;AACL,mBAAW,uCAAuC,IAAI,IAAI;AAC1D,mBAAW,kDAAkD;AAC7D,gBAAQ,WAAW;AACnB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,WAAW;AACtB,UAAM,aAAY,oBAAI,KAAK,GAAE,YAAY;AACzC,UAAM,UAAU,EAAE,IAAI,MAAM,OAAgB,MAAM,MAAM,UAAU;AAElE,UAAM,WAAW,uBAAuB,IAAI,GAAG,GAAG,KAAK,UAAU,OAAO,CAAC;AAAA,GAAM,OAAO;AAGtF,UAAM,gBAAgB,EAAE,IAAI,MAAM,WAAW,SAAS,MAAM,UAAU;AACtE,UAAM;AAAA,MACJ,0BAA0B,IAAI;AAAA,MAC9B,GAAG,KAAK,UAAU,aAAa,CAAC;AAAA;AAAA,MAChC;AAAA,IACF;AAEA,iBAAa,4BAA4B,IAAI,GAAG;AAChD,YAAQ,IAAI,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,KAAK,SAAS,KAAK,QAAQ,EAAE,EAAE;AAC1E,YAAQ,IAAI,kCAAkC;AAC9C,YAAQ,IAAI,sBAAsB;AAAA,EACpC;AACF,CAAC;","names":[]}
@@ -0,0 +1,72 @@
1
+ // src/commands/health.ts
2
+ import { execFile } from "child_process";
3
+ import { promisify } from "util";
4
+ import { loadGlobalConfig } from "@neotx/core";
5
+ import { defineCommand } from "citty";
6
+ var execFileAsync = promisify(execFile);
7
+ var CLAUDE_TIMEOUT_MS = 5e3;
8
+ async function checkConfig() {
9
+ try {
10
+ await loadGlobalConfig();
11
+ return { ok: true };
12
+ } catch (err) {
13
+ return {
14
+ ok: false,
15
+ error: err instanceof Error ? err.message : String(err)
16
+ };
17
+ }
18
+ }
19
+ async function checkGit() {
20
+ try {
21
+ const { stdout } = await execFileAsync("git", ["--version"]);
22
+ const match = stdout.match(/git version (\d+\.\d+(?:\.\d+)?)/);
23
+ return { ok: true, version: match?.[1] ?? "unknown" };
24
+ } catch (err) {
25
+ return {
26
+ ok: false,
27
+ error: err instanceof Error ? err.message : String(err)
28
+ };
29
+ }
30
+ }
31
+ async function checkClaude() {
32
+ const controller = new AbortController();
33
+ const timeout = setTimeout(() => controller.abort(), CLAUDE_TIMEOUT_MS);
34
+ try {
35
+ const { stdout } = await execFileAsync("claude", ["--version"], {
36
+ signal: controller.signal
37
+ });
38
+ const version = stdout.trim();
39
+ return { ok: true, version };
40
+ } catch (err) {
41
+ if (err instanceof Error && err.name === "AbortError") {
42
+ return { ok: false, error: `timeout after ${CLAUDE_TIMEOUT_MS}ms` };
43
+ }
44
+ return {
45
+ ok: false,
46
+ error: err instanceof Error ? err.message : String(err)
47
+ };
48
+ } finally {
49
+ clearTimeout(timeout);
50
+ }
51
+ }
52
+ var health_default = defineCommand({
53
+ meta: {
54
+ name: "health",
55
+ description: "Quick health check: config, git, Claude SDK (JSON output)"
56
+ },
57
+ async run() {
58
+ const [config, git, claude] = await Promise.all([checkConfig(), checkGit(), checkClaude()]);
59
+ const summary = {
60
+ ok: config.ok && git.ok && claude.ok,
61
+ checks: { config, git, claude }
62
+ };
63
+ console.log(JSON.stringify(summary, null, 2));
64
+ if (!summary.ok) {
65
+ process.exitCode = 1;
66
+ }
67
+ }
68
+ });
69
+ export {
70
+ health_default as default
71
+ };
72
+ //# sourceMappingURL=health-SWQ6V4H5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/health.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { loadGlobalConfig } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\n\nconst execFileAsync = promisify(execFile);\n\nconst CLAUDE_TIMEOUT_MS = 5000;\n\ninterface CheckResult {\n ok: boolean;\n version?: string;\n error?: string;\n}\n\ninterface HealthSummary {\n ok: boolean;\n checks: {\n config: CheckResult;\n git: CheckResult;\n claude: CheckResult;\n };\n}\n\nasync function checkConfig(): Promise<CheckResult> {\n try {\n await loadGlobalConfig();\n return { ok: true };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nasync function checkGit(): Promise<CheckResult> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"--version\"]);\n // Handle both \"2.25.1\" and \"2.25\" version formats\n const match = stdout.match(/git version (\\d+\\.\\d+(?:\\.\\d+)?)/);\n return { ok: true, version: match?.[1] ?? \"unknown\" };\n } catch (err) {\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n}\n\nasync function checkClaude(): Promise<CheckResult> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), CLAUDE_TIMEOUT_MS);\n\n try {\n const { stdout } = await execFileAsync(\"claude\", [\"--version\"], {\n signal: controller.signal,\n });\n\n const version = stdout.trim();\n return { ok: true, version };\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") {\n return { ok: false, error: `timeout after ${CLAUDE_TIMEOUT_MS}ms` };\n }\n return {\n ok: false,\n error: err instanceof Error ? err.message : String(err),\n };\n } finally {\n clearTimeout(timeout);\n }\n}\n\nexport default defineCommand({\n meta: {\n name: \"health\",\n description: \"Quick health check: config, git, Claude SDK (JSON output)\",\n },\n async run() {\n const [config, git, claude] = await Promise.all([checkConfig(), checkGit(), checkClaude()]);\n\n const summary: HealthSummary = {\n ok: config.ok && git.ok && claude.ok,\n checks: { config, git, claude },\n };\n\n console.log(JSON.stringify(summary, null, 2));\n\n // Use process.exitCode (not process.exit) to allow proper cleanup\n if (!summary.ok) {\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":";AAAA,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAE9B,IAAM,gBAAgB,UAAU,QAAQ;AAExC,IAAM,oBAAoB;AAiB1B,eAAe,cAAoC;AACjD,MAAI;AACF,UAAM,iBAAiB;AACvB,WAAO,EAAE,IAAI,KAAK;AAAA,EACpB,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF;AACF;AAEA,eAAe,WAAiC;AAC9C,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,CAAC,WAAW,CAAC;AAE3D,UAAM,QAAQ,OAAO,MAAM,kCAAkC;AAC7D,WAAO,EAAE,IAAI,MAAM,SAAS,QAAQ,CAAC,KAAK,UAAU;AAAA,EACtD,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF;AACF;AAEA,eAAe,cAAoC;AACjD,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,iBAAiB;AAEtE,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,UAAU,CAAC,WAAW,GAAG;AAAA,MAC9D,QAAQ,WAAW;AAAA,IACrB,CAAC;AAED,UAAM,UAAU,OAAO,KAAK;AAC5B,WAAO,EAAE,IAAI,MAAM,QAAQ;AAAA,EAC7B,SAAS,KAAK;AACZ,QAAI,eAAe,SAAS,IAAI,SAAS,cAAc;AACrD,aAAO,EAAE,IAAI,OAAO,OAAO,iBAAiB,iBAAiB,KAAK;AAAA,IACpE;AACA,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD;AAAA,EACF,UAAE;AACA,iBAAa,OAAO;AAAA,EACtB;AACF;AAEA,IAAO,iBAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM,MAAM;AACV,UAAM,CAAC,QAAQ,KAAK,MAAM,IAAI,MAAM,QAAQ,IAAI,CAAC,YAAY,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;AAE1F,UAAM,UAAyB;AAAA,MAC7B,IAAI,OAAO,MAAM,IAAI,MAAM,OAAO;AAAA,MAClC,QAAQ,EAAE,QAAQ,KAAK,OAAO;AAAA,IAChC;AAEA,YAAQ,IAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAG5C,QAAI,CAAC,QAAQ,IAAI;AACf,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACF,CAAC;","names":[]}
package/dist/index.js CHANGED
@@ -9,20 +9,24 @@ var main = defineCommand({
9
9
  },
10
10
  subCommands: {
11
11
  init: () => import("./init-OE4LAB6S.js").then((m) => m.default),
12
- run: () => import("./run-MWHIQUSY.js").then((m) => m.default),
13
- decision: () => import("./decision-PNZ2S2TU.js").then((m) => m.default),
12
+ run: () => import("./run-NV762V5B.js").then((m) => m.default),
13
+ do: () => import("./do-F5XW2ELZ.js").then((m) => m.default),
14
+ decision: () => import("./decision-T2526ITK.js").then((m) => m.default),
15
+ directive: () => import("./directive-7WM2Q2UW.js").then((m) => m.default),
14
16
  runs: () => import("./runs-CMLDYH7M.js").then((m) => m.default),
15
- log: () => import("./log-PTHLI7ZN.js").then((m) => m.default),
17
+ log: () => import("./log-ZLIAIBZQ.js").then((m) => m.default),
16
18
  logs: () => import("./logs-AWNAMMJC.js").then((m) => m.default),
17
19
  cost: () => import("./cost-IH37SMPY.js").then((m) => m.default),
18
20
  config: () => import("./config-NYF6AJXU.js").then((m) => m.default),
19
21
  repos: () => import("./repos-PWRYO4II.js").then((m) => m.default),
20
22
  agents: () => import("./agents-PH3P7G7E.js").then((m) => m.default),
21
- supervise: () => import("./supervise-XMZRNODO.js").then((m) => m.default),
22
- supervisor: () => import("./supervisor-3RUX5SPH.js").then((m) => m.default),
23
- memory: () => import("./memory-SDZ57W2S.js").then((m) => m.default),
23
+ supervise: () => import("./supervise-BWIKWNHH.js").then((m) => m.default),
24
+ supervisor: () => import("./supervisor-N4D5EWCC.js").then((m) => m.default),
25
+ child: () => import("./child-5X5IHAKS.js").then((m) => m.default),
26
+ memory: () => import("./memory-CW6E65SQ.js").then((m) => m.default),
24
27
  mcp: () => import("./mcp-XHZND5A4.js").then((m) => m.default),
25
28
  guide: () => import("./guide-UQRNA3FC.js").then((m) => m.default),
29
+ health: () => import("./health-SWQ6V4H5.js").then((m) => m.default),
26
30
  doctor: () => import("./doctor-ZBO73UID.js").then((m) => m.default),
27
31
  version: () => import("./version-XVOAMGDD.js").then((m) => m.default),
28
32
  webhooks: () => import("./webhooks-PUKAHFHE.js").then((m) => m.default)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { defineCommand, runMain } from \"citty\";\n\nconst main = defineCommand({\n meta: {\n name: \"neo\",\n version: \"0.1.0\",\n description:\n \"Orchestrate autonomous developer agents with clone isolation, budget guards, and 3-level recovery. Run 'neo init' to get started.\",\n },\n subCommands: {\n init: () => import(\"./commands/init.js\").then((m) => m.default),\n run: () => import(\"./commands/run.js\").then((m) => m.default),\n decision: () => import(\"./commands/decision.js\").then((m) => m.default),\n runs: () => import(\"./commands/runs.js\").then((m) => m.default),\n log: () => import(\"./commands/log.js\").then((m) => m.default),\n logs: () => import(\"./commands/logs.js\").then((m) => m.default),\n cost: () => import(\"./commands/cost.js\").then((m) => m.default),\n config: () => import(\"./commands/config.js\").then((m) => m.default),\n repos: () => import(\"./commands/repos.js\").then((m) => m.default),\n agents: () => import(\"./commands/agents.js\").then((m) => m.default),\n supervise: () => import(\"./commands/supervise.js\").then((m) => m.default),\n supervisor: () => import(\"./commands/supervisor/index.js\").then((m) => m.default),\n memory: () => import(\"./commands/memory.js\").then((m) => m.default),\n mcp: () => import(\"./commands/mcp.js\").then((m) => m.default),\n guide: () => import(\"./commands/guide.js\").then((m) => m.default),\n doctor: () => import(\"./commands/doctor.js\").then((m) => m.default),\n version: () => import(\"./commands/version.js\").then((m) => m.default),\n webhooks: () => import(\"./commands/webhooks.js\").then((m) => m.default),\n },\n});\n\nrunMain(main);\n"],"mappings":";AAAA,SAAS,eAAe,eAAe;AAEvC,IAAM,OAAO,cAAc;AAAA,EACzB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aACE;AAAA,EACJ;AAAA,EACA,aAAa;AAAA,IACX,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,UAAU,MAAM,OAAO,wBAAwB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACtE,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,OAAO,MAAM,OAAO,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,WAAW,MAAM,OAAO,yBAAyB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACxE,YAAY,MAAM,OAAO,0BAAgC,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChF,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,OAAO,MAAM,OAAO,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,SAAS,MAAM,OAAO,uBAAuB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACpE,UAAU,MAAM,OAAO,wBAAwB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,EACxE;AACF,CAAC;AAED,QAAQ,IAAI;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { defineCommand, runMain } from \"citty\";\n\nconst main = defineCommand({\n meta: {\n name: \"neo\",\n version: \"0.1.0\",\n description:\n \"Orchestrate autonomous developer agents with clone isolation, budget guards, and 3-level recovery. Run 'neo init' to get started.\",\n },\n subCommands: {\n init: () => import(\"./commands/init.js\").then((m) => m.default),\n run: () => import(\"./commands/run.js\").then((m) => m.default),\n do: () => import(\"./commands/do.js\").then((m) => m.default),\n decision: () => import(\"./commands/decision.js\").then((m) => m.default),\n directive: () => import(\"./commands/directive.js\").then((m) => m.default),\n runs: () => import(\"./commands/runs.js\").then((m) => m.default),\n log: () => import(\"./commands/log.js\").then((m) => m.default),\n logs: () => import(\"./commands/logs.js\").then((m) => m.default),\n cost: () => import(\"./commands/cost.js\").then((m) => m.default),\n config: () => import(\"./commands/config.js\").then((m) => m.default),\n repos: () => import(\"./commands/repos.js\").then((m) => m.default),\n agents: () => import(\"./commands/agents.js\").then((m) => m.default),\n supervise: () => import(\"./commands/supervise.js\").then((m) => m.default),\n supervisor: () => import(\"./commands/supervisor/index.js\").then((m) => m.default),\n child: () => import(\"./commands/child.js\").then((m) => m.default),\n memory: () => import(\"./commands/memory.js\").then((m) => m.default),\n mcp: () => import(\"./commands/mcp.js\").then((m) => m.default),\n guide: () => import(\"./commands/guide.js\").then((m) => m.default),\n health: () => import(\"./commands/health.js\").then((m) => m.default),\n doctor: () => import(\"./commands/doctor.js\").then((m) => m.default),\n version: () => import(\"./commands/version.js\").then((m) => m.default),\n webhooks: () => import(\"./commands/webhooks.js\").then((m) => m.default),\n },\n});\n\nrunMain(main);\n"],"mappings":";AAAA,SAAS,eAAe,eAAe;AAEvC,IAAM,OAAO,cAAc;AAAA,EACzB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aACE;AAAA,EACJ;AAAA,EACA,aAAa;AAAA,IACX,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,IAAI,MAAM,OAAO,kBAAkB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC1D,UAAU,MAAM,OAAO,wBAAwB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACtE,WAAW,MAAM,OAAO,yBAAyB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACxE,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,MAAM,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC9D,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,OAAO,MAAM,OAAO,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,WAAW,MAAM,OAAO,yBAAyB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACxE,YAAY,MAAM,OAAO,0BAAgC,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChF,OAAO,MAAM,OAAO,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,OAAO,MAAM,OAAO,qBAAqB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAChE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,SAAS,MAAM,OAAO,uBAAuB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACpE,UAAU,MAAM,OAAO,wBAAwB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,EACxE;AACF,CAAC;AAED,QAAQ,IAAI;","names":[]}