@neotx/cli 0.1.0-alpha.3 → 0.1.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +381 -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/{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 +25 -0
- package/dist/daemon/worker.js.map +1 -1
- package/dist/doctor-ZBO73UID.js +337 -0
- package/dist/doctor-ZBO73UID.js.map +1 -0
- package/dist/index.js +12 -10
- 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-XC5G3AHA.js → run-GJLDWPUE.js} +25 -8
- package/dist/run-GJLDWPUE.js.map +1 -0
- package/dist/{runs-CHA2JM5K.js → runs-LOYOWU55.js} +9 -10
- package/dist/runs-LOYOWU55.js.map +1 -0
- package/dist/{supervise-4QWX3UDF.js → supervise-LVCGVYA4.js} +35 -31
- package/dist/supervise-LVCGVYA4.js.map +1 -0
- package/dist/{tui-3YZDSBCX.js → tui-6USVDV75.js} +100 -33
- package/dist/tui-6USVDV75.js.map +1 -0
- package/dist/version-XVOAMGDD.js +26 -0
- package/dist/version-XVOAMGDD.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/log-EAZ7EVYM.js +0 -63
- package/dist/log-EAZ7EVYM.js.map +0 -1
- package/dist/mcp-GH6CCW7A.js.map +0 -1
- package/dist/run-XC5G3AHA.js.map +0 -1
- package/dist/runs-CHA2JM5K.js.map +0 -1
- package/dist/supervise-4QWX3UDF.js.map +0 -1
- package/dist/tui-3YZDSBCX.js.map +0 -1
- /package/dist/{agents-Y6LREFXP.js.map → agents-PH3P7G7E.js.map} +0 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import {
|
|
2
|
+
resolveAgentsDir
|
|
3
|
+
} from "./chunk-F622JUDY.js";
|
|
4
|
+
import {
|
|
5
|
+
printError,
|
|
6
|
+
printJson,
|
|
7
|
+
printSuccess
|
|
8
|
+
} from "./chunk-YQIWMDXL.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/doctor.ts
|
|
11
|
+
import { execFile } from "child_process";
|
|
12
|
+
import { existsSync } from "fs";
|
|
13
|
+
import { access, constants, mkdir } from "fs/promises";
|
|
14
|
+
import path from "path";
|
|
15
|
+
import { promisify } from "util";
|
|
16
|
+
import {
|
|
17
|
+
AgentRegistry,
|
|
18
|
+
getDataDir,
|
|
19
|
+
getJournalsDir,
|
|
20
|
+
listReposFromGlobalConfig,
|
|
21
|
+
listSessionClones,
|
|
22
|
+
loadGlobalConfig,
|
|
23
|
+
removeSessionClone,
|
|
24
|
+
toRepoSlug
|
|
25
|
+
} from "@neotx/core";
|
|
26
|
+
import { defineCommand } from "citty";
|
|
27
|
+
var execFileAsync = promisify(execFile);
|
|
28
|
+
async function checkNodeVersion() {
|
|
29
|
+
const version = process.versions.node;
|
|
30
|
+
const major = Number.parseInt(version.split(".")[0] ?? "0", 10);
|
|
31
|
+
if (major >= 22) {
|
|
32
|
+
return { name: "Node.js", status: "pass", message: `v${version}` };
|
|
33
|
+
}
|
|
34
|
+
return { name: "Node.js", status: "fail", message: `v${version} (requires >= 22)` };
|
|
35
|
+
}
|
|
36
|
+
async function checkGit() {
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = await execFileAsync("git", ["--version"]);
|
|
39
|
+
const match = stdout.match(/(\d+\.\d+)/);
|
|
40
|
+
const version = match?.[1] ?? "unknown";
|
|
41
|
+
const [major, minor] = version.split(".").map(Number);
|
|
42
|
+
if ((major ?? 0) > 2 || (major ?? 0) === 2 && (minor ?? 0) >= 20) {
|
|
43
|
+
return { name: "git", status: "pass", message: `v${version}` };
|
|
44
|
+
}
|
|
45
|
+
return { name: "git", status: "fail", message: `v${version} (requires >= 2.20)` };
|
|
46
|
+
} catch (err) {
|
|
47
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
48
|
+
return { name: "git", status: "fail", message: `not installed (${reason})` };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function checkGlobalConfig() {
|
|
52
|
+
try {
|
|
53
|
+
const config = await loadGlobalConfig();
|
|
54
|
+
const globalDir = getDataDir();
|
|
55
|
+
const repoCount = config.repos.length;
|
|
56
|
+
return {
|
|
57
|
+
name: "Global config",
|
|
58
|
+
status: "pass",
|
|
59
|
+
message: `${globalDir}/config.yml (budget: $${config.budget.dailyCapUsd}/day, ${repoCount} repos)`
|
|
60
|
+
};
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return {
|
|
63
|
+
name: "Global config",
|
|
64
|
+
status: "fail",
|
|
65
|
+
message: `Invalid: ${error instanceof Error ? error.message : String(error)}`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function checkRepoRegistered() {
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const repos = await listReposFromGlobalConfig();
|
|
72
|
+
const match = repos.find((r) => path.resolve(r.path) === cwd);
|
|
73
|
+
if (match) {
|
|
74
|
+
return {
|
|
75
|
+
name: "Repo registered",
|
|
76
|
+
status: "pass",
|
|
77
|
+
message: `"${toRepoSlug(match)}" (branch: ${match.defaultBranch})`
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
name: "Repo registered",
|
|
82
|
+
status: "info",
|
|
83
|
+
message: "CWD not registered. Run 'neo init' or 'neo repos add'. Zero-config mode works without registration."
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
async function checkClaudeCli() {
|
|
87
|
+
try {
|
|
88
|
+
const { stdout } = await execFileAsync("claude", ["--version"]);
|
|
89
|
+
return { name: "Claude CLI", status: "pass", message: stdout.trim() };
|
|
90
|
+
} catch (err) {
|
|
91
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
92
|
+
return {
|
|
93
|
+
name: "Claude CLI",
|
|
94
|
+
status: "fail",
|
|
95
|
+
message: `not installed or not in PATH (${reason})`
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function checkAgents() {
|
|
100
|
+
try {
|
|
101
|
+
const agentsDir = resolveAgentsDir();
|
|
102
|
+
if (!existsSync(agentsDir)) {
|
|
103
|
+
return { name: "Agents", status: "fail", message: "Agent definitions not found" };
|
|
104
|
+
}
|
|
105
|
+
const registry = new AgentRegistry(agentsDir);
|
|
106
|
+
await registry.load();
|
|
107
|
+
const count = registry.list().length;
|
|
108
|
+
return { name: "Agents", status: "pass", message: `${count} agents loaded` };
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
name: "Agents",
|
|
112
|
+
status: "fail",
|
|
113
|
+
message: error instanceof Error ? error.message : String(error)
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function checkJournalDirs() {
|
|
118
|
+
const journalDir = getJournalsDir();
|
|
119
|
+
if (!existsSync(journalDir)) {
|
|
120
|
+
return {
|
|
121
|
+
name: "Journals",
|
|
122
|
+
status: "fail",
|
|
123
|
+
message: `Directory missing: ${journalDir}`,
|
|
124
|
+
fixable: "missing-directory",
|
|
125
|
+
fixData: { path: journalDir }
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
await access(journalDir, constants.W_OK);
|
|
130
|
+
return { name: "Journals", status: "pass", message: journalDir };
|
|
131
|
+
} catch (err) {
|
|
132
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
133
|
+
return {
|
|
134
|
+
name: "Journals",
|
|
135
|
+
status: "fail",
|
|
136
|
+
message: `${journalDir} is not writable (${reason})`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async function checkDataDir() {
|
|
141
|
+
const dataDir = getDataDir();
|
|
142
|
+
if (!existsSync(dataDir)) {
|
|
143
|
+
return {
|
|
144
|
+
name: "Data directory",
|
|
145
|
+
status: "fail",
|
|
146
|
+
message: `Directory missing: ${dataDir}`,
|
|
147
|
+
fixable: "missing-directory",
|
|
148
|
+
fixData: { path: dataDir }
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
await access(dataDir, constants.W_OK);
|
|
153
|
+
return { name: "Data directory", status: "pass", message: dataDir };
|
|
154
|
+
} catch (err) {
|
|
155
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
156
|
+
return {
|
|
157
|
+
name: "Data directory",
|
|
158
|
+
status: "fail",
|
|
159
|
+
message: `${dataDir} is not writable (${reason})`
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
async function checkStaleSessions() {
|
|
164
|
+
const config = await loadGlobalConfig();
|
|
165
|
+
const sessionsDir = config.sessions.dir;
|
|
166
|
+
if (!existsSync(sessionsDir)) {
|
|
167
|
+
return { name: "Sessions", status: "pass", message: "No sessions directory" };
|
|
168
|
+
}
|
|
169
|
+
try {
|
|
170
|
+
const clones = await listSessionClones(sessionsDir);
|
|
171
|
+
if (clones.length === 0) {
|
|
172
|
+
return { name: "Sessions", status: "pass", message: "No stale session clones" };
|
|
173
|
+
}
|
|
174
|
+
const staleSessions = clones.map((c) => ({
|
|
175
|
+
path: c.path,
|
|
176
|
+
branch: c.branch
|
|
177
|
+
}));
|
|
178
|
+
return {
|
|
179
|
+
name: "Sessions",
|
|
180
|
+
status: "fail",
|
|
181
|
+
message: `${staleSessions.length} stale session clone(s) found`,
|
|
182
|
+
fixable: "stale-session",
|
|
183
|
+
fixData: { sessions: staleSessions }
|
|
184
|
+
};
|
|
185
|
+
} catch (error) {
|
|
186
|
+
return {
|
|
187
|
+
name: "Sessions",
|
|
188
|
+
status: "fail",
|
|
189
|
+
message: error instanceof Error ? error.message : String(error)
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
async function fixMissingDirectory(dirPath) {
|
|
194
|
+
try {
|
|
195
|
+
await mkdir(dirPath, { recursive: true });
|
|
196
|
+
return { name: `Create ${dirPath}`, success: true, message: "Created" };
|
|
197
|
+
} catch (error) {
|
|
198
|
+
return {
|
|
199
|
+
name: `Create ${dirPath}`,
|
|
200
|
+
success: false,
|
|
201
|
+
message: error instanceof Error ? error.message : String(error)
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
async function fixStaleSession(session) {
|
|
206
|
+
try {
|
|
207
|
+
await removeSessionClone(session.path);
|
|
208
|
+
return { name: `Remove ${session.path}`, success: true, message: "Removed" };
|
|
209
|
+
} catch (error) {
|
|
210
|
+
return {
|
|
211
|
+
name: `Remove ${session.path}`,
|
|
212
|
+
success: false,
|
|
213
|
+
message: error instanceof Error ? error.message : String(error)
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function applyFixes(checks) {
|
|
218
|
+
const results = [];
|
|
219
|
+
for (const check of checks) {
|
|
220
|
+
if (!check.fixable) continue;
|
|
221
|
+
switch (check.fixable) {
|
|
222
|
+
case "missing-directory": {
|
|
223
|
+
const data = check.fixData;
|
|
224
|
+
results.push(await fixMissingDirectory(data.path));
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case "stale-session": {
|
|
228
|
+
const data = check.fixData;
|
|
229
|
+
for (const session of data.sessions) {
|
|
230
|
+
results.push(await fixStaleSession(session));
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return results;
|
|
237
|
+
}
|
|
238
|
+
async function runAllChecks() {
|
|
239
|
+
const results = await Promise.all([
|
|
240
|
+
checkNodeVersion(),
|
|
241
|
+
checkGit(),
|
|
242
|
+
checkDataDir(),
|
|
243
|
+
checkGlobalConfig(),
|
|
244
|
+
checkRepoRegistered(),
|
|
245
|
+
checkClaudeCli(),
|
|
246
|
+
checkAgents(),
|
|
247
|
+
checkJournalDirs(),
|
|
248
|
+
checkStaleSessions()
|
|
249
|
+
]);
|
|
250
|
+
return results.filter((c) => c !== null);
|
|
251
|
+
}
|
|
252
|
+
function printCheckResult(check, shouldFix) {
|
|
253
|
+
if (check.status === "pass") {
|
|
254
|
+
printSuccess(`${check.name}: ${check.message ?? "OK"}`);
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
if (check.status === "info") {
|
|
258
|
+
console.log(` ${check.name}: ${check.message ?? ""}`);
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
const fixableHint = check.fixable && !shouldFix ? " (fixable with --fix)" : "";
|
|
262
|
+
printError(`${check.name}: ${check.message ?? "FAILED"}${fixableHint}`);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
function printFixResults(fixResults) {
|
|
266
|
+
console.log("\nFix results:");
|
|
267
|
+
let allFixed = true;
|
|
268
|
+
for (const fix of fixResults) {
|
|
269
|
+
if (fix.success) {
|
|
270
|
+
printSuccess(`${fix.name}: ${fix.message}`);
|
|
271
|
+
} else {
|
|
272
|
+
printError(`${fix.name}: ${fix.message}`);
|
|
273
|
+
allFixed = false;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return allFixed;
|
|
277
|
+
}
|
|
278
|
+
var doctor_default = defineCommand({
|
|
279
|
+
meta: {
|
|
280
|
+
name: "doctor",
|
|
281
|
+
description: "Check environment prerequisites (Node.js, git, config, Claude CLI)"
|
|
282
|
+
},
|
|
283
|
+
args: {
|
|
284
|
+
output: {
|
|
285
|
+
type: "string",
|
|
286
|
+
description: "Output format: json"
|
|
287
|
+
},
|
|
288
|
+
fix: {
|
|
289
|
+
type: "boolean",
|
|
290
|
+
description: "Attempt to automatically fix detected issues",
|
|
291
|
+
default: false
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
async run({ args }) {
|
|
295
|
+
const jsonOutput = args.output === "json";
|
|
296
|
+
const shouldFix = args.fix;
|
|
297
|
+
const checks = await runAllChecks();
|
|
298
|
+
let fixResults = [];
|
|
299
|
+
if (shouldFix) {
|
|
300
|
+
const fixableChecks = checks.filter((c) => c.status === "fail" && c.fixable);
|
|
301
|
+
if (fixableChecks.length > 0) {
|
|
302
|
+
fixResults = await applyFixes(fixableChecks);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (jsonOutput) {
|
|
306
|
+
const output = { checks };
|
|
307
|
+
if (shouldFix && fixResults.length > 0) {
|
|
308
|
+
output.fixes = fixResults;
|
|
309
|
+
}
|
|
310
|
+
printJson(output);
|
|
311
|
+
const hasUnfixedFailures = shouldFix ? fixResults.some((f) => !f.success) : checks.some((c) => c.status === "fail");
|
|
312
|
+
if (hasUnfixedFailures) {
|
|
313
|
+
process.exitCode = 1;
|
|
314
|
+
}
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
let hasFailure = false;
|
|
318
|
+
for (const check of checks) {
|
|
319
|
+
if (printCheckResult(check, shouldFix)) {
|
|
320
|
+
hasFailure = true;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (shouldFix && fixResults.length > 0) {
|
|
324
|
+
const allFixed = printFixResults(fixResults);
|
|
325
|
+
if (allFixed) {
|
|
326
|
+
hasFailure = false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (hasFailure) {
|
|
330
|
+
process.exitCode = 1;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
export {
|
|
335
|
+
doctor_default as default
|
|
336
|
+
};
|
|
337
|
+
//# sourceMappingURL=doctor-ZBO73UID.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/doctor.ts"],"sourcesContent":["import { execFile } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { access, constants, mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport {\n AgentRegistry,\n getDataDir,\n getJournalsDir,\n listReposFromGlobalConfig,\n listSessionClones,\n loadGlobalConfig,\n removeSessionClone,\n toRepoSlug,\n} from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printSuccess } from \"../output.js\";\nimport { resolveAgentsDir } from \"../resolve.js\";\n\nconst execFileAsync = promisify(execFile);\n\ntype FixableIssue = \"missing-directory\" | \"stale-session\";\n\ninterface CheckResult {\n name: string;\n status: \"pass\" | \"fail\" | \"info\";\n message?: string;\n fixable?: FixableIssue;\n fixData?: unknown;\n}\n\ninterface FixResult {\n name: string;\n success: boolean;\n message: string;\n}\n\nasync function checkNodeVersion(): Promise<CheckResult> {\n const version = process.versions.node;\n const major = Number.parseInt(version.split(\".\")[0] ?? \"0\", 10);\n if (major >= 22) {\n return { name: \"Node.js\", status: \"pass\", message: `v${version}` };\n }\n return { name: \"Node.js\", status: \"fail\", message: `v${version} (requires >= 22)` };\n}\n\nasync function checkGit(): Promise<CheckResult> {\n try {\n const { stdout } = await execFileAsync(\"git\", [\"--version\"]);\n const match = stdout.match(/(\\d+\\.\\d+)/);\n const version = match?.[1] ?? \"unknown\";\n const [major, minor] = version.split(\".\").map(Number);\n if ((major ?? 0) > 2 || ((major ?? 0) === 2 && (minor ?? 0) >= 20)) {\n return { name: \"git\", status: \"pass\", message: `v${version}` };\n }\n return { name: \"git\", status: \"fail\", message: `v${version} (requires >= 2.20)` };\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n return { name: \"git\", status: \"fail\", message: `not installed (${reason})` };\n }\n}\n\nasync function checkGlobalConfig(): Promise<CheckResult> {\n try {\n const config = await loadGlobalConfig();\n const globalDir = getDataDir();\n const repoCount = config.repos.length;\n return {\n name: \"Global config\",\n status: \"pass\",\n message: `${globalDir}/config.yml (budget: $${config.budget.dailyCapUsd}/day, ${repoCount} repos)`,\n };\n } catch (error) {\n return {\n name: \"Global config\",\n status: \"fail\",\n message: `Invalid: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n}\n\nasync function checkRepoRegistered(): Promise<CheckResult> {\n const cwd = process.cwd();\n const repos = await listReposFromGlobalConfig();\n const match = repos.find((r) => path.resolve(r.path) === cwd);\n\n if (match) {\n return {\n name: \"Repo registered\",\n status: \"pass\",\n message: `\"${toRepoSlug(match)}\" (branch: ${match.defaultBranch})`,\n };\n }\n\n return {\n name: \"Repo registered\",\n status: \"info\",\n message:\n \"CWD not registered. Run 'neo init' or 'neo repos add'. Zero-config mode works without registration.\",\n };\n}\n\nasync function checkClaudeCli(): Promise<CheckResult> {\n try {\n const { stdout } = await execFileAsync(\"claude\", [\"--version\"]);\n return { name: \"Claude CLI\", status: \"pass\", message: stdout.trim() };\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n return {\n name: \"Claude CLI\",\n status: \"fail\",\n message: `not installed or not in PATH (${reason})`,\n };\n }\n}\n\nasync function checkAgents(): Promise<CheckResult> {\n try {\n const agentsDir = resolveAgentsDir();\n if (!existsSync(agentsDir)) {\n return { name: \"Agents\", status: \"fail\", message: \"Agent definitions not found\" };\n }\n const registry = new AgentRegistry(agentsDir);\n await registry.load();\n const count = registry.list().length;\n return { name: \"Agents\", status: \"pass\", message: `${count} agents loaded` };\n } catch (error) {\n return {\n name: \"Agents\",\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function checkJournalDirs(): Promise<CheckResult> {\n const journalDir = getJournalsDir();\n if (!existsSync(journalDir)) {\n return {\n name: \"Journals\",\n status: \"fail\",\n message: `Directory missing: ${journalDir}`,\n fixable: \"missing-directory\",\n fixData: { path: journalDir },\n };\n }\n try {\n await access(journalDir, constants.W_OK);\n return { name: \"Journals\", status: \"pass\", message: journalDir };\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n return {\n name: \"Journals\",\n status: \"fail\",\n message: `${journalDir} is not writable (${reason})`,\n };\n }\n}\n\nasync function checkDataDir(): Promise<CheckResult> {\n const dataDir = getDataDir();\n if (!existsSync(dataDir)) {\n return {\n name: \"Data directory\",\n status: \"fail\",\n message: `Directory missing: ${dataDir}`,\n fixable: \"missing-directory\",\n fixData: { path: dataDir },\n };\n }\n try {\n await access(dataDir, constants.W_OK);\n return { name: \"Data directory\", status: \"pass\", message: dataDir };\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n return {\n name: \"Data directory\",\n status: \"fail\",\n message: `${dataDir} is not writable (${reason})`,\n };\n }\n}\n\ninterface StaleSession {\n path: string;\n branch: string;\n}\n\nasync function checkStaleSessions(): Promise<CheckResult> {\n const config = await loadGlobalConfig();\n const sessionsDir = config.sessions.dir;\n\n if (!existsSync(sessionsDir)) {\n return { name: \"Sessions\", status: \"pass\", message: \"No sessions directory\" };\n }\n\n try {\n const clones = await listSessionClones(sessionsDir);\n\n if (clones.length === 0) {\n return { name: \"Sessions\", status: \"pass\", message: \"No stale session clones\" };\n }\n\n const staleSessions: StaleSession[] = clones.map((c) => ({\n path: c.path,\n branch: c.branch,\n }));\n\n return {\n name: \"Sessions\",\n status: \"fail\",\n message: `${staleSessions.length} stale session clone(s) found`,\n fixable: \"stale-session\",\n fixData: { sessions: staleSessions },\n };\n } catch (error) {\n return {\n name: \"Sessions\",\n status: \"fail\",\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function fixMissingDirectory(dirPath: string): Promise<FixResult> {\n try {\n await mkdir(dirPath, { recursive: true });\n return { name: `Create ${dirPath}`, success: true, message: \"Created\" };\n } catch (error) {\n return {\n name: `Create ${dirPath}`,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function fixStaleSession(session: StaleSession): Promise<FixResult> {\n try {\n await removeSessionClone(session.path);\n return { name: `Remove ${session.path}`, success: true, message: \"Removed\" };\n } catch (error) {\n return {\n name: `Remove ${session.path}`,\n success: false,\n message: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nasync function applyFixes(checks: CheckResult[]): Promise<FixResult[]> {\n const results: FixResult[] = [];\n\n for (const check of checks) {\n if (!check.fixable) continue;\n\n switch (check.fixable) {\n case \"missing-directory\": {\n const data = check.fixData as { path: string };\n results.push(await fixMissingDirectory(data.path));\n break;\n }\n case \"stale-session\": {\n const data = check.fixData as { sessions: StaleSession[] };\n for (const session of data.sessions) {\n results.push(await fixStaleSession(session));\n }\n break;\n }\n }\n }\n\n return results;\n}\n\nasync function runAllChecks(): Promise<CheckResult[]> {\n const results = await Promise.all([\n checkNodeVersion(),\n checkGit(),\n checkDataDir(),\n checkGlobalConfig(),\n checkRepoRegistered(),\n checkClaudeCli(),\n checkAgents(),\n checkJournalDirs(),\n checkStaleSessions(),\n ]);\n return results.filter((c): c is CheckResult => c !== null);\n}\n\nfunction printCheckResult(check: CheckResult, shouldFix: boolean): boolean {\n if (check.status === \"pass\") {\n printSuccess(`${check.name}: ${check.message ?? \"OK\"}`);\n return false;\n }\n if (check.status === \"info\") {\n console.log(` ${check.name}: ${check.message ?? \"\"}`);\n return false;\n }\n const fixableHint = check.fixable && !shouldFix ? \" (fixable with --fix)\" : \"\";\n printError(`${check.name}: ${check.message ?? \"FAILED\"}${fixableHint}`);\n return true;\n}\n\nfunction printFixResults(fixResults: FixResult[]): boolean {\n console.log(\"\\nFix results:\");\n let allFixed = true;\n for (const fix of fixResults) {\n if (fix.success) {\n printSuccess(`${fix.name}: ${fix.message}`);\n } else {\n printError(`${fix.name}: ${fix.message}`);\n allFixed = false;\n }\n }\n return allFixed;\n}\n\nexport default defineCommand({\n meta: {\n name: \"doctor\",\n description: \"Check environment prerequisites (Node.js, git, config, Claude CLI)\",\n },\n args: {\n output: {\n type: \"string\",\n description: \"Output format: json\",\n },\n fix: {\n type: \"boolean\",\n description: \"Attempt to automatically fix detected issues\",\n default: false,\n },\n },\n async run({ args }) {\n const jsonOutput = args.output === \"json\";\n const shouldFix = args.fix;\n\n const checks = await runAllChecks();\n\n // In fix mode, attempt to fix issues\n let fixResults: FixResult[] = [];\n if (shouldFix) {\n const fixableChecks = checks.filter((c) => c.status === \"fail\" && c.fixable);\n if (fixableChecks.length > 0) {\n fixResults = await applyFixes(fixableChecks);\n }\n }\n\n if (jsonOutput) {\n const output: { checks: CheckResult[]; fixes?: FixResult[] } = { checks };\n if (shouldFix && fixResults.length > 0) {\n output.fixes = fixResults;\n }\n printJson(output);\n\n const hasUnfixedFailures = shouldFix\n ? fixResults.some((f) => !f.success)\n : checks.some((c) => c.status === \"fail\");\n if (hasUnfixedFailures) {\n process.exitCode = 1;\n }\n return;\n }\n\n // Print check results\n let hasFailure = false;\n for (const check of checks) {\n if (printCheckResult(check, shouldFix)) {\n hasFailure = true;\n }\n }\n\n // Print fix results\n if (shouldFix && fixResults.length > 0) {\n const allFixed = printFixResults(fixResults);\n if (allFixed) {\n hasFailure = false;\n }\n }\n\n if (hasFailure) {\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -5,20 +5,22 @@ var main = defineCommand({
|
|
|
5
5
|
meta: {
|
|
6
6
|
name: "neo",
|
|
7
7
|
version: "0.1.0",
|
|
8
|
-
description: "Orchestrate autonomous developer agents with
|
|
8
|
+
description: "Orchestrate autonomous developer agents with clone isolation, budget guards, and 3-level recovery. Run 'neo init' to get started."
|
|
9
9
|
},
|
|
10
10
|
subCommands: {
|
|
11
|
-
init: () => import("./init-
|
|
12
|
-
run: () => import("./run-
|
|
13
|
-
runs: () => import("./runs-
|
|
14
|
-
log: () => import("./log-
|
|
11
|
+
init: () => import("./init-UYS6KS5U.js").then((m) => m.default),
|
|
12
|
+
run: () => import("./run-GJLDWPUE.js").then((m) => m.default),
|
|
13
|
+
runs: () => import("./runs-LOYOWU55.js").then((m) => m.default),
|
|
14
|
+
log: () => import("./log-PTHLI7ZN.js").then((m) => m.default),
|
|
15
15
|
logs: () => import("./logs-AWNAMMJC.js").then((m) => m.default),
|
|
16
|
-
cost: () => import("./cost-
|
|
16
|
+
cost: () => import("./cost-OQGFNBBG.js").then((m) => m.default),
|
|
17
17
|
repos: () => import("./repos-GI6F72NO.js").then((m) => m.default),
|
|
18
|
-
agents: () => import("./agents-
|
|
19
|
-
supervise: () => import("./supervise-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
agents: () => import("./agents-PH3P7G7E.js").then((m) => m.default),
|
|
19
|
+
supervise: () => import("./supervise-LVCGVYA4.js").then((m) => m.default),
|
|
20
|
+
memory: () => import("./memory-6R22DFS7.js").then((m) => m.default),
|
|
21
|
+
mcp: () => import("./mcp-XHZND5A4.js").then((m) => m.default),
|
|
22
|
+
doctor: () => import("./doctor-ZBO73UID.js").then((m) => m.default),
|
|
23
|
+
version: () => import("./version-XVOAMGDD.js").then((m) => m.default)
|
|
22
24
|
}
|
|
23
25
|
});
|
|
24
26
|
runMain(main);
|
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
|
|
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 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 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 memory: () => import(\"./commands/memory.js\").then((m) => m.default),\n mcp: () => import(\"./commands/mcp.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 },\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,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,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,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,KAAK,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAC5D,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IAClE,SAAS,MAAM,OAAO,uBAAuB,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,EACtE;AACF,CAAC;AAED,QAAQ,IAAI;","names":[]}
|
|
@@ -8,26 +8,12 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/commands/init.ts
|
|
10
10
|
import { existsSync } from "fs";
|
|
11
|
-
import {
|
|
11
|
+
import { mkdir } from "fs/promises";
|
|
12
12
|
import path from "path";
|
|
13
13
|
import { addRepoToGlobalConfig, getDataDir, loadGlobalConfig } from "@neotx/core";
|
|
14
14
|
import { defineCommand } from "citty";
|
|
15
|
-
var GITIGNORE_ENTRY = ".neo/worktrees/";
|
|
16
15
|
async function ensureGitignore() {
|
|
17
|
-
|
|
18
|
-
if (existsSync(gitignorePath)) {
|
|
19
|
-
const content = await readFile(gitignorePath, "utf-8");
|
|
20
|
-
if (content.includes(GITIGNORE_ENTRY)) return false;
|
|
21
|
-
await appendFile(gitignorePath, `
|
|
22
|
-
# neo worktrees (ephemeral)
|
|
23
|
-
${GITIGNORE_ENTRY}
|
|
24
|
-
`);
|
|
25
|
-
} else {
|
|
26
|
-
await appendFile(gitignorePath, `# neo worktrees (ephemeral)
|
|
27
|
-
${GITIGNORE_ENTRY}
|
|
28
|
-
`);
|
|
29
|
-
}
|
|
30
|
-
return true;
|
|
16
|
+
return false;
|
|
31
17
|
}
|
|
32
18
|
var init_default = defineCommand({
|
|
33
19
|
meta: {
|
|
@@ -50,9 +36,7 @@ var init_default = defineCommand({
|
|
|
50
36
|
}
|
|
51
37
|
await mkdir(agentsDir, { recursive: true });
|
|
52
38
|
printSuccess("Created .neo/agents/");
|
|
53
|
-
|
|
54
|
-
printSuccess(`Added ${GITIGNORE_ENTRY} to .gitignore`);
|
|
55
|
-
}
|
|
39
|
+
await ensureGitignore();
|
|
56
40
|
const branch = await detectDefaultBranch();
|
|
57
41
|
const repoPath = path.resolve(".");
|
|
58
42
|
await addRepoToGlobalConfig({
|
|
@@ -71,4 +55,4 @@ var init_default = defineCommand({
|
|
|
71
55
|
export {
|
|
72
56
|
init_default as default
|
|
73
57
|
};
|
|
74
|
-
//# sourceMappingURL=init-
|
|
58
|
+
//# sourceMappingURL=init-UYS6KS5U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/init.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { mkdir } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { addRepoToGlobalConfig, getDataDir, loadGlobalConfig } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { detectDefaultBranch } from \"../git-utils.js\";\nimport { printError, printSuccess } from \"../output.js\";\n\nasync function ensureGitignore(): Promise<boolean> {\n // Session clones are stored in /tmp/neo-sessions/ by default,\n // so no .gitignore entry is needed. Keep the function for future use.\n return false;\n}\n\nexport default defineCommand({\n meta: {\n name: \"init\",\n description: \"Initialize a .neo/ project directory and register the repo\",\n },\n args: {\n force: {\n type: \"boolean\",\n description: \"Re-register even if already initialized\",\n default: false,\n },\n },\n async run({ args }) {\n const agentsDir = path.resolve(\".neo/agents\");\n\n if (existsSync(agentsDir) && !args.force) {\n printError(\".neo/agents/ already exists. Use --force to re-register.\");\n process.exitCode = 1;\n return;\n }\n\n // Create .neo/agents/ for project-local agent definitions\n await mkdir(agentsDir, { recursive: true });\n printSuccess(\"Created .neo/agents/\");\n\n await ensureGitignore();\n\n // Detect default branch and register repo in global config\n const branch = await detectDefaultBranch();\n const repoPath = path.resolve(\".\");\n\n await addRepoToGlobalConfig({\n path: repoPath,\n defaultBranch: branch,\n });\n printSuccess(`Registered repo in global config (branch: ${branch})`);\n\n // Ensure global config exists (creates with defaults if missing)\n const globalConfig = await loadGlobalConfig();\n const globalDir = getDataDir();\n printSuccess(\n `Global config at ${globalDir}/config.yml (budget: $${globalConfig.budget.dailyCapUsd}/day)`,\n );\n\n printSuccess(\"neo initialized. Run 'neo doctor' to verify setup.\");\n },\n});\n"],"mappings":";;;;;;;;;AAAA,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,OAAO,UAAU;AACjB,SAAS,uBAAuB,YAAY,wBAAwB;AACpE,SAAS,qBAAqB;AAI9B,eAAe,kBAAoC;AAGjD,SAAO;AACT;AAEA,IAAO,eAAQ,cAAc;AAAA,EAC3B,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa;AAAA,EACf;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,MACL,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,MAAM,IAAI,EAAE,KAAK,GAAG;AAClB,UAAM,YAAY,KAAK,QAAQ,aAAa;AAE5C,QAAI,WAAW,SAAS,KAAK,CAAC,KAAK,OAAO;AACxC,iBAAW,0DAA0D;AACrE,cAAQ,WAAW;AACnB;AAAA,IACF;AAGA,UAAM,MAAM,WAAW,EAAE,WAAW,KAAK,CAAC;AAC1C,iBAAa,sBAAsB;AAEnC,UAAM,gBAAgB;AAGtB,UAAM,SAAS,MAAM,oBAAoB;AACzC,UAAM,WAAW,KAAK,QAAQ,GAAG;AAEjC,UAAM,sBAAsB;AAAA,MAC1B,MAAM;AAAA,MACN,eAAe;AAAA,IACjB,CAAC;AACD,iBAAa,6CAA6C,MAAM,GAAG;AAGnE,UAAM,eAAe,MAAM,iBAAiB;AAC5C,UAAM,YAAY,WAAW;AAC7B;AAAA,MACE,oBAAoB,SAAS,yBAAyB,aAAa,OAAO,WAAW;AAAA,IACvF;AAEA,iBAAa,oDAAoD;AAAA,EACnE;AACF,CAAC;","names":[]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printError,
|
|
3
|
+
printSuccess
|
|
4
|
+
} from "./chunk-YQIWMDXL.js";
|
|
5
|
+
|
|
6
|
+
// src/commands/log.ts
|
|
7
|
+
import { randomUUID } from "crypto";
|
|
8
|
+
import { appendFile } from "fs/promises";
|
|
9
|
+
import path from "path";
|
|
10
|
+
import { appendLogBuffer, getSupervisorDir, MemoryStore } from "@neotx/core";
|
|
11
|
+
import { defineCommand } from "citty";
|
|
12
|
+
var VALID_TYPES = [
|
|
13
|
+
"progress",
|
|
14
|
+
"action",
|
|
15
|
+
"decision",
|
|
16
|
+
"blocker",
|
|
17
|
+
"milestone",
|
|
18
|
+
"discovery"
|
|
19
|
+
];
|
|
20
|
+
var TYPE_MAP = {
|
|
21
|
+
decision: "decision",
|
|
22
|
+
action: "action",
|
|
23
|
+
blocker: "error",
|
|
24
|
+
progress: "event",
|
|
25
|
+
milestone: "event",
|
|
26
|
+
discovery: "event"
|
|
27
|
+
};
|
|
28
|
+
var TARGET_MAP = {
|
|
29
|
+
progress: "digest",
|
|
30
|
+
action: "digest",
|
|
31
|
+
decision: "memory",
|
|
32
|
+
milestone: "memory",
|
|
33
|
+
blocker: "memory",
|
|
34
|
+
discovery: "knowledge"
|
|
35
|
+
};
|
|
36
|
+
var log_default = defineCommand({
|
|
37
|
+
meta: {
|
|
38
|
+
name: "log",
|
|
39
|
+
description: "Log a structured progress report to the supervisor activity log"
|
|
40
|
+
},
|
|
41
|
+
args: {
|
|
42
|
+
type: {
|
|
43
|
+
type: "positional",
|
|
44
|
+
description: "Report type: progress, action, decision, blocker, milestone, discovery",
|
|
45
|
+
required: true
|
|
46
|
+
},
|
|
47
|
+
message: {
|
|
48
|
+
type: "positional",
|
|
49
|
+
description: "Message to log",
|
|
50
|
+
required: true
|
|
51
|
+
},
|
|
52
|
+
name: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Supervisor instance name",
|
|
55
|
+
default: "supervisor"
|
|
56
|
+
},
|
|
57
|
+
memory: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Override routing: send to memory target",
|
|
60
|
+
default: false
|
|
61
|
+
},
|
|
62
|
+
knowledge: {
|
|
63
|
+
type: "boolean",
|
|
64
|
+
description: "Override routing: send to knowledge target",
|
|
65
|
+
default: false
|
|
66
|
+
},
|
|
67
|
+
repo: {
|
|
68
|
+
type: "string",
|
|
69
|
+
description: "Repository path"
|
|
70
|
+
},
|
|
71
|
+
procedure: {
|
|
72
|
+
type: "boolean",
|
|
73
|
+
description: "Also write as a procedure memory entry",
|
|
74
|
+
default: false
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
async run({ args }) {
|
|
78
|
+
const type = args.type;
|
|
79
|
+
if (!VALID_TYPES.includes(type)) {
|
|
80
|
+
printError(`Invalid type "${type}". Must be one of: ${VALID_TYPES.join(", ")}`);
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const dir = getSupervisorDir(args.name);
|
|
85
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
86
|
+
const id = randomUUID();
|
|
87
|
+
const agent = process.env.NEO_AGENT_NAME ?? void 0;
|
|
88
|
+
const runId = process.env.NEO_RUN_ID ?? void 0;
|
|
89
|
+
const repo = args.repo ?? process.env.NEO_REPOSITORY ?? void 0;
|
|
90
|
+
let target = TARGET_MAP[type] ?? "digest";
|
|
91
|
+
if (args.memory) target = "memory";
|
|
92
|
+
if (args.knowledge) target = "knowledge";
|
|
93
|
+
const activityEntry = {
|
|
94
|
+
id,
|
|
95
|
+
type: TYPE_MAP[type] ?? "event",
|
|
96
|
+
summary: args.message,
|
|
97
|
+
timestamp: now
|
|
98
|
+
};
|
|
99
|
+
await appendFile(`${dir}/activity.jsonl`, `${JSON.stringify(activityEntry)}
|
|
100
|
+
`, "utf-8");
|
|
101
|
+
await appendLogBuffer(dir, {
|
|
102
|
+
id,
|
|
103
|
+
type,
|
|
104
|
+
message: args.message,
|
|
105
|
+
agent,
|
|
106
|
+
runId,
|
|
107
|
+
repo,
|
|
108
|
+
target,
|
|
109
|
+
timestamp: now
|
|
110
|
+
});
|
|
111
|
+
if (target === "knowledge" || args.procedure) {
|
|
112
|
+
try {
|
|
113
|
+
const store = new MemoryStore(path.join(dir, "memory.sqlite"));
|
|
114
|
+
await store.write({
|
|
115
|
+
type: args.procedure ? "procedure" : "fact",
|
|
116
|
+
scope: repo ?? "global",
|
|
117
|
+
content: args.message,
|
|
118
|
+
source: agent ?? "user",
|
|
119
|
+
runId
|
|
120
|
+
});
|
|
121
|
+
store.close();
|
|
122
|
+
} catch {
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (type === "blocker") {
|
|
126
|
+
const inboxMessage = {
|
|
127
|
+
id: randomUUID(),
|
|
128
|
+
from: "agent",
|
|
129
|
+
text: `[BLOCKER]${agent ? ` (${agent})` : ""} ${args.message}`,
|
|
130
|
+
timestamp: now
|
|
131
|
+
};
|
|
132
|
+
await appendFile(`${dir}/inbox.jsonl`, `${JSON.stringify(inboxMessage)}
|
|
133
|
+
`, "utf-8");
|
|
134
|
+
}
|
|
135
|
+
printSuccess(`Logged: [${type}] ${args.message.slice(0, 100)}`);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
export {
|
|
139
|
+
log_default as default
|
|
140
|
+
};
|
|
141
|
+
//# sourceMappingURL=log-PTHLI7ZN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/log.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { appendLogBuffer, getSupervisorDir, MemoryStore } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess } from \"../output.js\";\n\nconst VALID_TYPES = [\n \"progress\",\n \"action\",\n \"decision\",\n \"blocker\",\n \"milestone\",\n \"discovery\",\n] as const;\ntype LogType = (typeof VALID_TYPES)[number];\n\n// Map log types to activity.jsonl entry types (preserve existing behavior)\nconst TYPE_MAP: Record<string, string> = {\n decision: \"decision\",\n action: \"action\",\n blocker: \"error\",\n progress: \"event\",\n milestone: \"event\",\n discovery: \"event\",\n};\n\n// Implicit routing: which target each type gets by default\nconst TARGET_MAP: Record<string, \"memory\" | \"knowledge\" | \"digest\"> = {\n progress: \"digest\",\n action: \"digest\",\n decision: \"memory\",\n milestone: \"memory\",\n blocker: \"memory\",\n discovery: \"knowledge\",\n};\n\nexport default defineCommand({\n meta: {\n name: \"log\",\n description: \"Log a structured progress report to the supervisor activity log\",\n },\n args: {\n type: {\n type: \"positional\",\n description: \"Report type: progress, action, decision, blocker, milestone, discovery\",\n required: true,\n },\n message: {\n type: \"positional\",\n description: \"Message to log\",\n required: true,\n },\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: \"supervisor\",\n },\n memory: {\n type: \"boolean\",\n description: \"Override routing: send to memory target\",\n default: false,\n },\n knowledge: {\n type: \"boolean\",\n description: \"Override routing: send to knowledge target\",\n default: false,\n },\n repo: {\n type: \"string\",\n description: \"Repository path\",\n },\n procedure: {\n type: \"boolean\",\n description: \"Also write as a procedure memory entry\",\n default: false,\n },\n },\n async run({ args }) {\n const type = args.type as string;\n if (!VALID_TYPES.includes(type as LogType)) {\n printError(`Invalid type \"${type}\". Must be one of: ${VALID_TYPES.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n const dir = getSupervisorDir(args.name);\n const now = new Date().toISOString();\n const id = randomUUID();\n\n // Resolve agent/run from env vars or flags\n const agent = process.env.NEO_AGENT_NAME ?? undefined;\n const runId = process.env.NEO_RUN_ID ?? undefined;\n const repo = (args.repo as string | undefined) ?? process.env.NEO_REPOSITORY ?? undefined;\n\n // Resolve target with flag overrides\n let target: \"memory\" | \"knowledge\" | \"digest\" = TARGET_MAP[type] ?? \"digest\";\n if (args.memory) target = \"memory\";\n if (args.knowledge) target = \"knowledge\";\n\n // 1. Always: append to activity.jsonl (existing behavior)\n const activityEntry = {\n id,\n type: TYPE_MAP[type] ?? \"event\",\n summary: args.message,\n timestamp: now,\n };\n await appendFile(`${dir}/activity.jsonl`, `${JSON.stringify(activityEntry)}\\n`, \"utf-8\");\n\n // 2. Always: append to log-buffer.jsonl via shared helper\n await appendLogBuffer(dir, {\n id,\n type: type as \"progress\" | \"action\" | \"decision\" | \"blocker\" | \"milestone\" | \"discovery\",\n message: args.message,\n agent,\n runId,\n repo,\n target,\n timestamp: now,\n });\n\n // 3. Write to memory store for knowledge/procedure entries\n if (target === \"knowledge\" || args.procedure) {\n try {\n const store = new MemoryStore(path.join(dir, \"memory.sqlite\"));\n await store.write({\n type: args.procedure ? \"procedure\" : \"fact\",\n scope: repo ?? \"global\",\n content: args.message,\n source: agent ?? \"user\",\n runId,\n });\n store.close();\n } catch {\n // Best-effort — don't crash CLI if store write fails\n }\n }\n\n // 4. If blocker: also append to inbox.jsonl (wake up heartbeat)\n if (type === \"blocker\") {\n const inboxMessage = {\n id: randomUUID(),\n from: \"agent\" as const,\n text: `[BLOCKER]${agent ? ` (${agent})` : \"\"} ${args.message}`,\n timestamp: now,\n };\n await appendFile(`${dir}/inbox.jsonl`, `${JSON.stringify(inboxMessage)}\\n`, \"utf-8\");\n }\n\n printSuccess(`Logged: [${type}] ${args.message.slice(0, 100)}`);\n },\n});\n"],"mappings":"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","names":[]}
|