@neotx/cli 0.1.0-alpha.2 → 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 -9
- package/dist/index.js.map +1 -1
- package/dist/{init-YNSPTCA3.js → init-UYS6KS5U.js} +4 -20
- package/dist/init-UYS6KS5U.js.map +1 -0
- package/dist/log-PTHLI7ZN.js +141 -0
- package/dist/log-PTHLI7ZN.js.map +1 -0
- package/dist/{mcp-GH6CCW7A.js → mcp-XHZND5A4.js} +6 -1
- package/dist/mcp-XHZND5A4.js.map +1 -0
- package/dist/memory-6R22DFS7.js +292 -0
- package/dist/memory-6R22DFS7.js.map +1 -0
- package/dist/{run-KIU2ZE72.js → run-GJLDWPUE.js} +32 -9
- 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-KIB2EYY4.js → supervise-LVCGVYA4.js} +33 -28
- package/dist/supervise-LVCGVYA4.js.map +1 -0
- package/dist/{tui-QS3RPHKH.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/mcp-GH6CCW7A.js.map +0 -1
- package/dist/run-KIU2ZE72.js.map +0 -1
- package/dist/runs-CHA2JM5K.js.map +0 -1
- package/dist/supervise-KIB2EYY4.js.map +0 -1
- package/dist/tui-QS3RPHKH.js.map +0 -1
- /package/dist/{agents-Y6LREFXP.js.map → agents-PH3P7G7E.js.map} +0 -0
|
@@ -17,6 +17,7 @@ var MCP_PRESETS = {
|
|
|
17
17
|
type: "stdio",
|
|
18
18
|
command: "npx",
|
|
19
19
|
args: ["-y", "@anthropic/linear-mcp-server"],
|
|
20
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code
|
|
20
21
|
env: { LINEAR_API_KEY: "${LINEAR_API_KEY}" }
|
|
21
22
|
},
|
|
22
23
|
envVars: ["LINEAR_API_KEY"]
|
|
@@ -26,6 +27,7 @@ var MCP_PRESETS = {
|
|
|
26
27
|
type: "stdio",
|
|
27
28
|
command: "npx",
|
|
28
29
|
args: ["-y", "@notionhq/notion-mcp-server"],
|
|
30
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code
|
|
29
31
|
env: { NOTION_TOKEN: "${NOTION_TOKEN}" }
|
|
30
32
|
},
|
|
31
33
|
envVars: ["NOTION_TOKEN"]
|
|
@@ -35,6 +37,7 @@ var MCP_PRESETS = {
|
|
|
35
37
|
type: "stdio",
|
|
36
38
|
command: "npx",
|
|
37
39
|
args: ["-y", "@modelcontextprotocol/server-github"],
|
|
40
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code
|
|
38
41
|
env: { GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}" }
|
|
39
42
|
},
|
|
40
43
|
envVars: ["GITHUB_TOKEN"]
|
|
@@ -44,6 +47,7 @@ var MCP_PRESETS = {
|
|
|
44
47
|
type: "stdio",
|
|
45
48
|
command: "npx",
|
|
46
49
|
args: ["-y", "@anthropic/jira-mcp-server"],
|
|
50
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholders interpolated at runtime by Claude Code
|
|
47
51
|
env: { JIRA_API_TOKEN: "${JIRA_API_TOKEN}", JIRA_URL: "${JIRA_URL}" }
|
|
48
52
|
},
|
|
49
53
|
envVars: ["JIRA_API_TOKEN", "JIRA_URL"]
|
|
@@ -53,6 +57,7 @@ var MCP_PRESETS = {
|
|
|
53
57
|
type: "stdio",
|
|
54
58
|
command: "npx",
|
|
55
59
|
args: ["-y", "@modelcontextprotocol/server-slack"],
|
|
60
|
+
// biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code
|
|
56
61
|
env: { SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}" }
|
|
57
62
|
},
|
|
58
63
|
envVars: ["SLACK_BOT_TOKEN"]
|
|
@@ -214,4 +219,4 @@ var mcp_default = defineCommand({
|
|
|
214
219
|
export {
|
|
215
220
|
mcp_default as default
|
|
216
221
|
};
|
|
217
|
-
//# sourceMappingURL=mcp-
|
|
222
|
+
//# sourceMappingURL=mcp-XHZND5A4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/mcp.ts"],"sourcesContent":["import { readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport path from \"node:path\";\nimport { loadGlobalConfig, type McpServerConfig } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport { printError, printSuccess, printTable } from \"../output.js\";\n\n// ─── Presets for popular MCP servers ─────────────────────\n\nconst MCP_PRESETS: Record<string, { config: McpServerConfig; envVars: string[] }> = {\n linear: {\n config: {\n type: \"stdio\",\n command: \"npx\",\n args: [\"-y\", \"@anthropic/linear-mcp-server\"],\n // biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code\n env: { LINEAR_API_KEY: \"${LINEAR_API_KEY}\" },\n },\n envVars: [\"LINEAR_API_KEY\"],\n },\n notion: {\n config: {\n type: \"stdio\",\n command: \"npx\",\n args: [\"-y\", \"@notionhq/notion-mcp-server\"],\n // biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code\n env: { NOTION_TOKEN: \"${NOTION_TOKEN}\" },\n },\n envVars: [\"NOTION_TOKEN\"],\n },\n github: {\n config: {\n type: \"stdio\",\n command: \"npx\",\n args: [\"-y\", \"@modelcontextprotocol/server-github\"],\n // biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code\n env: { GITHUB_PERSONAL_ACCESS_TOKEN: \"${GITHUB_TOKEN}\" },\n },\n envVars: [\"GITHUB_TOKEN\"],\n },\n jira: {\n config: {\n type: \"stdio\",\n command: \"npx\",\n args: [\"-y\", \"@anthropic/jira-mcp-server\"],\n // biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholders interpolated at runtime by Claude Code\n env: { JIRA_API_TOKEN: \"${JIRA_API_TOKEN}\", JIRA_URL: \"${JIRA_URL}\" },\n },\n envVars: [\"JIRA_API_TOKEN\", \"JIRA_URL\"],\n },\n slack: {\n config: {\n type: \"stdio\",\n command: \"npx\",\n args: [\"-y\", \"@modelcontextprotocol/server-slack\"],\n // biome-ignore lint/suspicious/noTemplateCurlyInString: Template placeholder interpolated at runtime by Claude Code\n env: { SLACK_BOT_TOKEN: \"${SLACK_BOT_TOKEN}\" },\n },\n envVars: [\"SLACK_BOT_TOKEN\"],\n },\n};\n\n// ─── Helpers ─────────────────────────────────────────────\n\nasync function loadAndModifyConfig(\n modify: (config: Record<string, unknown>) => void,\n): Promise<void> {\n const configPath = path.join(homedir(), \".neo\", \"config.yml\");\n let config: Record<string, unknown>;\n\n try {\n const raw = await readFile(configPath, \"utf-8\");\n config = (parseYaml(raw) as Record<string, unknown>) ?? {};\n } catch {\n config = {};\n }\n\n modify(config);\n await writeFile(configPath, stringifyYaml(config), \"utf-8\");\n}\n\n// ─── Subcommands ─────────────────────────────────────────\n\nconst listCmd = defineCommand({\n meta: { name: \"list\", description: \"List configured MCP servers\" },\n async run() {\n const config = await loadGlobalConfig();\n const servers = config.mcpServers ?? {};\n const entries = Object.entries(servers);\n\n if (entries.length === 0) {\n console.log(\"No MCP servers configured.\");\n console.log(\"Add one with: neo mcp add <name> or neo mcp add <preset>\");\n console.log(`Available presets: ${Object.keys(MCP_PRESETS).join(\", \")}`);\n return;\n }\n\n const rows = entries.map(([name, cfg]) => {\n if (cfg.type === \"stdio\") {\n return [name, \"stdio\", `${cfg.command} ${(cfg.args ?? []).join(\" \")}`];\n }\n return [name, \"http\", cfg.url];\n });\n\n printTable([\"Name\", \"Type\", \"Config\"], rows);\n },\n});\n\nconst addCmd = defineCommand({\n meta: { name: \"add\", description: \"Add an MCP server (use a preset name or custom flags)\" },\n args: {\n name: {\n type: \"positional\",\n description: \"Server name or preset (linear, notion, github, jira, slack)\",\n },\n type: { type: \"string\", description: \"Server type: stdio or http\" },\n command: { type: \"string\", description: \"Command for stdio servers\" },\n serverArgs: { type: \"string\", description: \"Comma-separated args for stdio servers\" },\n url: { type: \"string\", description: \"URL for http servers\" },\n },\n async run({ args }) {\n const name = args.name as string | undefined;\n if (!name) {\n printError(\"Server name is required. Usage: neo mcp add <name>\");\n process.exitCode = 1;\n return;\n }\n\n // Check if it's a preset\n const preset = MCP_PRESETS[name];\n if (preset) {\n // Check env vars\n const missing = preset.envVars.filter((v: string) => !process.env[v]);\n if (missing.length > 0) {\n console.log(`Preset \"${name}\" requires the following environment variables:`);\n for (const v of missing) {\n console.log(` ${v} (not set)`);\n }\n console.log(\"\\nSet them before starting the supervisor.\");\n }\n\n await loadAndModifyConfig((config) => {\n const servers = (config.mcpServers as Record<string, unknown>) ?? {};\n servers[name] = preset.config;\n config.mcpServers = servers;\n });\n\n printSuccess(`Added MCP server \"${name}\" (preset)`);\n return;\n }\n\n // Custom server\n if (!args.type) {\n printError(`Unknown preset \"${name}\". Use --type stdio or --type http for custom servers.`);\n console.log(`Available presets: ${Object.keys(MCP_PRESETS).join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n let serverConfig: McpServerConfig;\n if (args.type === \"stdio\") {\n if (!args.command) {\n printError(\"--command is required for stdio servers\");\n process.exitCode = 1;\n return;\n }\n serverConfig = {\n type: \"stdio\",\n command: args.command,\n args: args.serverArgs ? args.serverArgs.split(\",\") : undefined,\n };\n } else if (args.type === \"http\") {\n if (!args.url) {\n printError(\"--url is required for http servers\");\n process.exitCode = 1;\n return;\n }\n serverConfig = {\n type: \"http\",\n url: args.url,\n };\n } else {\n printError(`Invalid type \"${args.type}\". Use \"stdio\" or \"http\".`);\n process.exitCode = 1;\n return;\n }\n\n await loadAndModifyConfig((config) => {\n const servers = (config.mcpServers as Record<string, unknown>) ?? {};\n servers[name] = serverConfig;\n config.mcpServers = servers;\n });\n\n printSuccess(`Added MCP server \"${name}\"`);\n },\n});\n\nconst removeCmd = defineCommand({\n meta: { name: \"remove\", description: \"Remove an MCP server\" },\n args: {\n name: { type: \"positional\", description: \"Server name to remove\" },\n },\n async run({ args }) {\n const name = args.name as string | undefined;\n if (!name) {\n printError(\"Server name is required. Usage: neo mcp remove <name>\");\n process.exitCode = 1;\n return;\n }\n\n let found = false;\n\n await loadAndModifyConfig((config) => {\n const servers = config.mcpServers as Record<string, unknown> | undefined;\n if (servers && name in servers) {\n delete servers[name];\n found = true;\n if (Object.keys(servers).length === 0) {\n delete config.mcpServers;\n }\n }\n });\n\n if (found) {\n printSuccess(`Removed MCP server \"${name}\"`);\n } else {\n printError(`MCP server \"${name}\" not found`);\n process.exitCode = 1;\n }\n },\n});\n\n// ─── Main command ────────────────────────────────────────\n\nexport default defineCommand({\n meta: {\n name: \"mcp\",\n description: \"Manage MCP server integrations (Linear, Notion, GitHub, etc.)\",\n },\n subCommands: {\n list: () => Promise.resolve(listCmd),\n add: () => Promise.resolve(addCmd),\n remove: () => Promise.resolve(removeCmd),\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import {
|
|
2
|
+
printError,
|
|
3
|
+
printSuccess,
|
|
4
|
+
printTable
|
|
5
|
+
} from "./chunk-YQIWMDXL.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/memory.ts
|
|
8
|
+
import path from "path";
|
|
9
|
+
import { getSupervisorDir, LocalEmbedder, MemoryStore } from "@neotx/core";
|
|
10
|
+
import { defineCommand } from "citty";
|
|
11
|
+
var VALID_TYPES = ["fact", "procedure", "episode", "focus", "feedback", "task"];
|
|
12
|
+
function parseDuration(input) {
|
|
13
|
+
const match = input.match(/^(\d+)(h|m)$/);
|
|
14
|
+
if (!match) return void 0;
|
|
15
|
+
const value = Number(match[1]);
|
|
16
|
+
const unit = match[2];
|
|
17
|
+
const ms = unit === "h" ? value * 60 * 60 * 1e3 : value * 60 * 1e3;
|
|
18
|
+
return new Date(Date.now() + ms).toISOString();
|
|
19
|
+
}
|
|
20
|
+
function truncate(text, max) {
|
|
21
|
+
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
22
|
+
}
|
|
23
|
+
function createEmbedder() {
|
|
24
|
+
try {
|
|
25
|
+
return new LocalEmbedder();
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function openStore(name, withEmbeddings = false) {
|
|
31
|
+
const dir = getSupervisorDir(name);
|
|
32
|
+
const embedder = withEmbeddings ? createEmbedder() : null;
|
|
33
|
+
return new MemoryStore(path.join(dir, "memory.sqlite"), embedder);
|
|
34
|
+
}
|
|
35
|
+
function formatResultsTable(results) {
|
|
36
|
+
printTable(
|
|
37
|
+
["ID", "TYPE", "SCOPE", "CONTENT", "ACCESSES"],
|
|
38
|
+
results.map((m) => [m.id, m.type, m.scope, truncate(m.content, 60), String(m.accessCount)])
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
async function handleWrite(args) {
|
|
42
|
+
if (!args.value) {
|
|
43
|
+
printError("Usage: neo memory write <content> --type <type> [--scope <scope>]");
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const type = args.type ?? "fact";
|
|
48
|
+
if (!VALID_TYPES.includes(type)) {
|
|
49
|
+
printError(`Invalid type "${type}". Must be one of: ${VALID_TYPES.join(", ")}`);
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
let expiresAt;
|
|
54
|
+
if (args.expires) {
|
|
55
|
+
expiresAt = parseDuration(args.expires);
|
|
56
|
+
if (!expiresAt) {
|
|
57
|
+
printError('Invalid --expires format. Use e.g. "2h" or "30m".');
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const store = openStore(args.name, true);
|
|
63
|
+
try {
|
|
64
|
+
const tags = args.tags ? args.tags.split(",").map((t) => t.trim()) : [];
|
|
65
|
+
const id = await store.write({
|
|
66
|
+
type,
|
|
67
|
+
scope: args.scope,
|
|
68
|
+
content: args.value,
|
|
69
|
+
source: args.source,
|
|
70
|
+
tags,
|
|
71
|
+
expiresAt,
|
|
72
|
+
severity: args.severity,
|
|
73
|
+
category: args.category,
|
|
74
|
+
outcome: args.outcome
|
|
75
|
+
});
|
|
76
|
+
printSuccess(`Memory written: ${id}`);
|
|
77
|
+
} finally {
|
|
78
|
+
store.close();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function handleForget(args) {
|
|
82
|
+
if (!args.value) {
|
|
83
|
+
printError("Usage: neo memory forget <id>");
|
|
84
|
+
process.exitCode = 1;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const store = openStore(args.name);
|
|
88
|
+
try {
|
|
89
|
+
store.forget(args.value);
|
|
90
|
+
printSuccess(`Memory forgotten: ${args.value}`);
|
|
91
|
+
} finally {
|
|
92
|
+
store.close();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
var VALID_OUTCOMES = ["pending", "in_progress", "done", "blocked", "abandoned"];
|
|
96
|
+
function handleUpdate(args) {
|
|
97
|
+
if (!args.value) {
|
|
98
|
+
printError('Usage: neo memory update <id> ["new content"] [--outcome <status>]');
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const argv = process.argv;
|
|
103
|
+
const updateIdx = argv.indexOf("update");
|
|
104
|
+
const idArg = argv[updateIdx + 1];
|
|
105
|
+
const contentArg = argv[updateIdx + 2];
|
|
106
|
+
if (args.outcome && !VALID_OUTCOMES.includes(args.outcome)) {
|
|
107
|
+
printError(`Invalid outcome "${args.outcome}". Must be one of: ${VALID_OUTCOMES.join(", ")}`);
|
|
108
|
+
process.exitCode = 1;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const isContentArgAFlag = contentArg?.startsWith("--");
|
|
112
|
+
const hasContent = contentArg && !isContentArgAFlag;
|
|
113
|
+
if (!hasContent && !args.outcome) {
|
|
114
|
+
printError('Usage: neo memory update <id> ["new content"] [--outcome <status>]');
|
|
115
|
+
process.exitCode = 1;
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (!idArg) {
|
|
119
|
+
printError('Usage: neo memory update <id> ["new content"] [--outcome <status>]');
|
|
120
|
+
process.exitCode = 1;
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const store = openStore(args.name);
|
|
124
|
+
try {
|
|
125
|
+
if (args.outcome) {
|
|
126
|
+
store.updateFields(idArg, {
|
|
127
|
+
...hasContent && { content: contentArg },
|
|
128
|
+
outcome: args.outcome
|
|
129
|
+
});
|
|
130
|
+
} else {
|
|
131
|
+
store.update(idArg, contentArg);
|
|
132
|
+
}
|
|
133
|
+
printSuccess(`Memory updated: ${idArg}`);
|
|
134
|
+
} finally {
|
|
135
|
+
store.close();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async function handleSearch(args) {
|
|
139
|
+
if (!args.value) {
|
|
140
|
+
printError("Usage: neo memory search <query>");
|
|
141
|
+
process.exitCode = 1;
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const store = openStore(args.name, true);
|
|
145
|
+
try {
|
|
146
|
+
const results = await store.search(args.value, {
|
|
147
|
+
...args.scope !== "global" && { scope: args.scope },
|
|
148
|
+
...args.type && { types: [args.type] }
|
|
149
|
+
});
|
|
150
|
+
if (results.length === 0) {
|
|
151
|
+
console.log("No memories found.");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
formatResultsTable(results);
|
|
155
|
+
} finally {
|
|
156
|
+
store.close();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function handleList(args) {
|
|
160
|
+
const store = openStore(args.name);
|
|
161
|
+
try {
|
|
162
|
+
const results = store.query({
|
|
163
|
+
...args.scope !== "global" && { scope: args.scope },
|
|
164
|
+
...args.type && { types: [args.type] }
|
|
165
|
+
});
|
|
166
|
+
if (results.length === 0) {
|
|
167
|
+
console.log("No memories found.");
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
formatResultsTable(results);
|
|
171
|
+
} finally {
|
|
172
|
+
store.close();
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function handleStats(args) {
|
|
176
|
+
const store = openStore(args.name);
|
|
177
|
+
try {
|
|
178
|
+
const s = store.stats();
|
|
179
|
+
console.log(`Total memories: ${s.total}
|
|
180
|
+
`);
|
|
181
|
+
if (Object.keys(s.byType).length > 0) {
|
|
182
|
+
printTable(
|
|
183
|
+
["TYPE", "COUNT"],
|
|
184
|
+
Object.entries(s.byType).map(([t, c]) => [t, String(c)])
|
|
185
|
+
);
|
|
186
|
+
console.log();
|
|
187
|
+
}
|
|
188
|
+
if (Object.keys(s.byScope).length > 0) {
|
|
189
|
+
printTable(
|
|
190
|
+
["SCOPE", "COUNT"],
|
|
191
|
+
Object.entries(s.byScope).map(([sc, c]) => [sc, String(c)])
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
} finally {
|
|
195
|
+
store.close();
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
var memory_default = defineCommand({
|
|
199
|
+
meta: {
|
|
200
|
+
name: "memory",
|
|
201
|
+
description: "Manage the supervisor memory store"
|
|
202
|
+
},
|
|
203
|
+
args: {
|
|
204
|
+
action: {
|
|
205
|
+
type: "positional",
|
|
206
|
+
description: "Action: write, forget, update, search, list, stats",
|
|
207
|
+
required: true
|
|
208
|
+
},
|
|
209
|
+
value: {
|
|
210
|
+
type: "positional",
|
|
211
|
+
description: "Content or ID depending on action",
|
|
212
|
+
required: false
|
|
213
|
+
},
|
|
214
|
+
type: {
|
|
215
|
+
type: "string",
|
|
216
|
+
description: "Memory type: fact, procedure, episode, focus, feedback, task"
|
|
217
|
+
},
|
|
218
|
+
scope: {
|
|
219
|
+
type: "string",
|
|
220
|
+
description: "Scope: global or repo path",
|
|
221
|
+
default: "global"
|
|
222
|
+
},
|
|
223
|
+
source: {
|
|
224
|
+
type: "string",
|
|
225
|
+
description: "Source: developer, reviewer, supervisor, user",
|
|
226
|
+
default: "user"
|
|
227
|
+
},
|
|
228
|
+
expires: {
|
|
229
|
+
type: "string",
|
|
230
|
+
description: "TTL for focus entries (e.g. 2h, 30m)"
|
|
231
|
+
},
|
|
232
|
+
outcome: {
|
|
233
|
+
type: "string",
|
|
234
|
+
description: "Task outcome: pending, in_progress, done, blocked, abandoned"
|
|
235
|
+
},
|
|
236
|
+
severity: {
|
|
237
|
+
type: "string",
|
|
238
|
+
description: "Priority: critical, high, medium, low"
|
|
239
|
+
},
|
|
240
|
+
category: {
|
|
241
|
+
type: "string",
|
|
242
|
+
description: "Context reference (e.g. 'neo runs abc123' or 'cat notes/plan.md')"
|
|
243
|
+
},
|
|
244
|
+
tags: {
|
|
245
|
+
type: "string",
|
|
246
|
+
description: "Comma-separated tags (e.g. 'initiative:auth,depends:mem_abc')"
|
|
247
|
+
},
|
|
248
|
+
name: {
|
|
249
|
+
type: "string",
|
|
250
|
+
description: "Supervisor name",
|
|
251
|
+
default: "supervisor"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
async run({ args }) {
|
|
255
|
+
const action = args.action;
|
|
256
|
+
const parsed = {
|
|
257
|
+
value: args.value,
|
|
258
|
+
type: args.type,
|
|
259
|
+
scope: args.scope,
|
|
260
|
+
source: args.source,
|
|
261
|
+
expires: args.expires,
|
|
262
|
+
name: args.name,
|
|
263
|
+
outcome: args.outcome,
|
|
264
|
+
severity: args.severity,
|
|
265
|
+
category: args.category,
|
|
266
|
+
tags: args.tags
|
|
267
|
+
};
|
|
268
|
+
switch (action) {
|
|
269
|
+
case "write":
|
|
270
|
+
return handleWrite(parsed);
|
|
271
|
+
case "forget":
|
|
272
|
+
return handleForget(parsed);
|
|
273
|
+
case "update":
|
|
274
|
+
return handleUpdate(parsed);
|
|
275
|
+
case "search":
|
|
276
|
+
return handleSearch(parsed);
|
|
277
|
+
case "list":
|
|
278
|
+
return handleList(parsed);
|
|
279
|
+
case "stats":
|
|
280
|
+
return handleStats(parsed);
|
|
281
|
+
default:
|
|
282
|
+
printError(
|
|
283
|
+
`Unknown action "${action}". Must be one of: write, forget, update, search, list, stats`
|
|
284
|
+
);
|
|
285
|
+
process.exitCode = 1;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
export {
|
|
290
|
+
memory_default as default
|
|
291
|
+
};
|
|
292
|
+
//# sourceMappingURL=memory-6R22DFS7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { Embedder, MemoryEntry, MemoryType } from \"@neotx/core\";\nimport { getSupervisorDir, LocalEmbedder, MemoryStore } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess, printTable } from \"../output.js\";\n\nconst VALID_TYPES = [\"fact\", \"procedure\", \"episode\", \"focus\", \"feedback\", \"task\"] as const;\n\ninterface ParsedArgs {\n value: string | undefined;\n type: string | undefined;\n scope: string;\n source: string;\n expires: string | undefined;\n name: string;\n outcome: string | undefined;\n severity: string | undefined;\n category: string | undefined;\n tags: string | undefined;\n}\n\nfunction parseDuration(input: string): string | undefined {\n const match = input.match(/^(\\d+)(h|m)$/);\n if (!match) return undefined;\n\n const value = Number(match[1]);\n const unit = match[2];\n const ms = unit === \"h\" ? value * 60 * 60 * 1000 : value * 60 * 1000;\n return new Date(Date.now() + ms).toISOString();\n}\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}…` : text;\n}\n\nfunction createEmbedder(): Embedder | null {\n try {\n return new LocalEmbedder();\n } catch {\n return null;\n }\n}\n\nfunction openStore(name: string, withEmbeddings = false): MemoryStore {\n const dir = getSupervisorDir(name);\n const embedder = withEmbeddings ? createEmbedder() : null;\n return new MemoryStore(path.join(dir, \"memory.sqlite\"), embedder);\n}\n\nfunction formatResultsTable(results: MemoryEntry[]): void {\n printTable(\n [\"ID\", \"TYPE\", \"SCOPE\", \"CONTENT\", \"ACCESSES\"],\n results.map((m) => [m.id, m.type, m.scope, truncate(m.content, 60), String(m.accessCount)]),\n );\n}\n\nasync function handleWrite(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo memory write <content> --type <type> [--scope <scope>]\");\n process.exitCode = 1;\n return;\n }\n\n const type = args.type ?? \"fact\";\n if (!VALID_TYPES.includes(type as MemoryType)) {\n printError(`Invalid type \"${type}\". Must be one of: ${VALID_TYPES.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n let expiresAt: string | undefined;\n if (args.expires) {\n expiresAt = parseDuration(args.expires);\n if (!expiresAt) {\n printError('Invalid --expires format. Use e.g. \"2h\" or \"30m\".');\n process.exitCode = 1;\n return;\n }\n }\n\n const store = openStore(args.name, true);\n try {\n const tags = args.tags ? args.tags.split(\",\").map((t) => t.trim()) : [];\n const id = await store.write({\n type: type as MemoryType,\n scope: args.scope,\n content: args.value,\n source: args.source,\n tags,\n expiresAt,\n severity: args.severity,\n category: args.category,\n outcome: args.outcome,\n });\n printSuccess(`Memory written: ${id}`);\n } finally {\n store.close();\n }\n}\n\nfunction handleForget(args: ParsedArgs): void {\n if (!args.value) {\n printError(\"Usage: neo memory forget <id>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n try {\n store.forget(args.value);\n printSuccess(`Memory forgotten: ${args.value}`);\n } finally {\n store.close();\n }\n}\n\nconst VALID_OUTCOMES = [\"pending\", \"in_progress\", \"done\", \"blocked\", \"abandoned\"] as const;\n\nfunction handleUpdate(args: ParsedArgs): void {\n if (!args.value) {\n printError('Usage: neo memory update <id> [\"new content\"] [--outcome <status>]');\n process.exitCode = 1;\n return;\n }\n\n // The ID is in value, but we need content too.\n // citty only supports 2 positional args — content comes after ID.\n const argv = process.argv;\n const updateIdx = argv.indexOf(\"update\");\n const idArg = argv[updateIdx + 1];\n const contentArg = argv[updateIdx + 2];\n\n // Validate outcome if provided\n if (args.outcome && !VALID_OUTCOMES.includes(args.outcome as (typeof VALID_OUTCOMES)[number])) {\n printError(`Invalid outcome \"${args.outcome}\". Must be one of: ${VALID_OUTCOMES.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n // Determine if contentArg is actually content or a flag\n const isContentArgAFlag = contentArg?.startsWith(\"--\");\n const hasContent = contentArg && !isContentArgAFlag;\n\n // Need either content or --outcome\n if (!hasContent && !args.outcome) {\n printError('Usage: neo memory update <id> [\"new content\"] [--outcome <status>]');\n process.exitCode = 1;\n return;\n }\n\n // ID is required at this point — validated by args.value check above\n if (!idArg) {\n printError('Usage: neo memory update <id> [\"new content\"] [--outcome <status>]');\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n try {\n // Use updateFields when --outcome is provided\n if (args.outcome) {\n store.updateFields(idArg, {\n ...(hasContent && { content: contentArg }),\n outcome: args.outcome,\n });\n } else {\n // contentArg is guaranteed to be defined when hasContent is true and no outcome\n store.update(idArg, contentArg as string);\n }\n printSuccess(`Memory updated: ${idArg}`);\n } finally {\n store.close();\n }\n}\n\nasync function handleSearch(args: ParsedArgs): Promise<void> {\n if (!args.value) {\n printError(\"Usage: neo memory search <query>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name, true);\n try {\n const results = await store.search(args.value, {\n ...(args.scope !== \"global\" && { scope: args.scope }),\n ...(args.type && { types: [args.type as MemoryType] }),\n });\n\n if (results.length === 0) {\n console.log(\"No memories found.\");\n return;\n }\n\n formatResultsTable(results);\n } finally {\n store.close();\n }\n}\n\nfunction handleList(args: ParsedArgs): void {\n const store = openStore(args.name);\n try {\n const results = store.query({\n ...(args.scope !== \"global\" && { scope: args.scope }),\n ...(args.type && { types: [args.type as MemoryType] }),\n });\n\n if (results.length === 0) {\n console.log(\"No memories found.\");\n return;\n }\n\n formatResultsTable(results);\n } finally {\n store.close();\n }\n}\n\nfunction handleStats(args: ParsedArgs): void {\n const store = openStore(args.name);\n try {\n const s = store.stats();\n console.log(`Total memories: ${s.total}\\n`);\n\n if (Object.keys(s.byType).length > 0) {\n printTable(\n [\"TYPE\", \"COUNT\"],\n Object.entries(s.byType).map(([t, c]) => [t, String(c)]),\n );\n console.log();\n }\n\n if (Object.keys(s.byScope).length > 0) {\n printTable(\n [\"SCOPE\", \"COUNT\"],\n Object.entries(s.byScope).map(([sc, c]) => [sc, String(c)]),\n );\n }\n } finally {\n store.close();\n }\n}\n\nexport default defineCommand({\n meta: {\n name: \"memory\",\n description: \"Manage the supervisor memory store\",\n },\n args: {\n action: {\n type: \"positional\",\n description: \"Action: write, forget, update, search, list, stats\",\n required: true,\n },\n value: {\n type: \"positional\",\n description: \"Content or ID depending on action\",\n required: false,\n },\n type: {\n type: \"string\",\n description: \"Memory type: fact, procedure, episode, focus, feedback, task\",\n },\n scope: {\n type: \"string\",\n description: \"Scope: global or repo path\",\n default: \"global\",\n },\n source: {\n type: \"string\",\n description: \"Source: developer, reviewer, supervisor, user\",\n default: \"user\",\n },\n expires: {\n type: \"string\",\n description: \"TTL for focus entries (e.g. 2h, 30m)\",\n },\n outcome: {\n type: \"string\",\n description: \"Task outcome: pending, in_progress, done, blocked, abandoned\",\n },\n severity: {\n type: \"string\",\n description: \"Priority: critical, high, medium, low\",\n },\n category: {\n type: \"string\",\n description: \"Context reference (e.g. 'neo runs abc123' or 'cat notes/plan.md')\",\n },\n tags: {\n type: \"string\",\n description: \"Comma-separated tags (e.g. 'initiative:auth,depends:mem_abc')\",\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 value: args.value as string | undefined,\n type: args.type as string | undefined,\n scope: args.scope as string,\n source: args.source as string,\n expires: args.expires as string | undefined,\n name: args.name as string,\n outcome: args.outcome as string | undefined,\n severity: args.severity as string | undefined,\n category: args.category as string | undefined,\n tags: args.tags as string | undefined,\n };\n\n switch (action) {\n case \"write\":\n return handleWrite(parsed);\n case \"forget\":\n return handleForget(parsed);\n case \"update\":\n return handleUpdate(parsed);\n case \"search\":\n return handleSearch(parsed);\n case \"list\":\n return handleList(parsed);\n case \"stats\":\n return handleStats(parsed);\n default:\n printError(\n `Unknown action \"${action}\". Must be one of: write, forget, update, search, list, stats`,\n );\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveAgentsDir
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-F622JUDY.js";
|
|
4
4
|
import {
|
|
5
5
|
printError,
|
|
6
6
|
printJson,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-YQIWMDXL.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/run.ts
|
|
11
|
-
import {
|
|
11
|
+
import { spawn } from "child_process";
|
|
12
12
|
import { randomUUID } from "crypto";
|
|
13
13
|
import { existsSync } from "fs";
|
|
14
14
|
import { mkdir, writeFile } from "fs/promises";
|
|
@@ -60,6 +60,9 @@ function printResult(result, agentName) {
|
|
|
60
60
|
if (result.branch) {
|
|
61
61
|
console.log(`Branch: ${result.branch}`);
|
|
62
62
|
}
|
|
63
|
+
if (result.prUrl) {
|
|
64
|
+
console.log(`PR: ${result.prUrl}`);
|
|
65
|
+
}
|
|
63
66
|
const stepResult = Object.values(result.steps)[0];
|
|
64
67
|
const output = stepResult?.output ?? result.summary;
|
|
65
68
|
if (output) {
|
|
@@ -96,6 +99,7 @@ async function runDetached(params) {
|
|
|
96
99
|
agentName: params.agentName,
|
|
97
100
|
repo: params.repo,
|
|
98
101
|
prompt: params.prompt,
|
|
102
|
+
branch: params.branch,
|
|
99
103
|
priority: params.priority,
|
|
100
104
|
metadata: params.metadata,
|
|
101
105
|
bundledAgentsDir: params.bundledAgentsDir,
|
|
@@ -104,9 +108,10 @@ async function runDetached(params) {
|
|
|
104
108
|
"utf-8"
|
|
105
109
|
);
|
|
106
110
|
const workerPath = path.join(path.dirname(fileURLToPath(import.meta.url)), "daemon", "worker.js");
|
|
107
|
-
const child =
|
|
111
|
+
const child = spawn(process.execPath, [workerPath, runId, repoSlug], {
|
|
108
112
|
detached: true,
|
|
109
|
-
stdio: "ignore"
|
|
113
|
+
stdio: "ignore",
|
|
114
|
+
env: process.env
|
|
110
115
|
});
|
|
111
116
|
child.unref();
|
|
112
117
|
if (params.jsonOutput) {
|
|
@@ -120,7 +125,7 @@ async function runDetached(params) {
|
|
|
120
125
|
var run_default = defineCommand({
|
|
121
126
|
meta: {
|
|
122
127
|
name: "run",
|
|
123
|
-
description: "Dispatch an agent to execute a task in an isolated
|
|
128
|
+
description: "Dispatch an agent to execute a task in an isolated clone"
|
|
124
129
|
},
|
|
125
130
|
args: {
|
|
126
131
|
agent: {
|
|
@@ -138,13 +143,17 @@ var run_default = defineCommand({
|
|
|
138
143
|
description: "Task description for the agent",
|
|
139
144
|
required: true
|
|
140
145
|
},
|
|
146
|
+
branch: {
|
|
147
|
+
type: "string",
|
|
148
|
+
description: "Branch name for the session clone (required for writable agents)"
|
|
149
|
+
},
|
|
141
150
|
priority: {
|
|
142
151
|
type: "string",
|
|
143
152
|
description: "Priority level: critical, high, medium, low"
|
|
144
153
|
},
|
|
145
154
|
meta: {
|
|
146
155
|
type: "string",
|
|
147
|
-
description: "Metadata as JSON string"
|
|
156
|
+
description: "Metadata as JSON string (for traceability: ticketId, stage, etc.)"
|
|
148
157
|
},
|
|
149
158
|
output: {
|
|
150
159
|
type: "string",
|
|
@@ -154,7 +163,17 @@ var run_default = defineCommand({
|
|
|
154
163
|
type: "boolean",
|
|
155
164
|
alias: "d",
|
|
156
165
|
description: "Run in background and return immediately with the run ID",
|
|
166
|
+
default: true
|
|
167
|
+
},
|
|
168
|
+
sync: {
|
|
169
|
+
type: "boolean",
|
|
170
|
+
alias: "s",
|
|
171
|
+
description: "Run in foreground (blocking) instead of detached",
|
|
157
172
|
default: false
|
|
173
|
+
},
|
|
174
|
+
"git-strategy": {
|
|
175
|
+
type: "string",
|
|
176
|
+
description: "Git strategy: pr (create PR), branch (push only, default)"
|
|
158
177
|
}
|
|
159
178
|
},
|
|
160
179
|
async run({ args }) {
|
|
@@ -175,11 +194,12 @@ var run_default = defineCommand({
|
|
|
175
194
|
process.exitCode = 1;
|
|
176
195
|
return;
|
|
177
196
|
}
|
|
178
|
-
if (args.detach) {
|
|
197
|
+
if (args.detach && !args.sync) {
|
|
179
198
|
await runDetached({
|
|
180
199
|
agentName: args.agent,
|
|
181
200
|
repo,
|
|
182
201
|
prompt: args.prompt,
|
|
202
|
+
branch: args.branch,
|
|
183
203
|
priority: args.priority ?? "medium",
|
|
184
204
|
metadata: parseMetadata(args.meta),
|
|
185
205
|
bundledAgentsDir,
|
|
@@ -202,12 +222,15 @@ var run_default = defineCommand({
|
|
|
202
222
|
}
|
|
203
223
|
try {
|
|
204
224
|
await orchestrator.start();
|
|
225
|
+
const gitStrategy = args["git-strategy"];
|
|
205
226
|
const result = await orchestrator.dispatch({
|
|
206
227
|
workflow: `_run_${args.agent}`,
|
|
207
228
|
repo,
|
|
208
229
|
prompt: args.prompt,
|
|
230
|
+
...args.branch ? { branch: args.branch } : {},
|
|
209
231
|
priority: args.priority ?? "medium",
|
|
210
|
-
metadata: parseMetadata(args.meta)
|
|
232
|
+
metadata: parseMetadata(args.meta),
|
|
233
|
+
...gitStrategy ? { gitStrategy } : {}
|
|
211
234
|
});
|
|
212
235
|
if (jsonOutput) {
|
|
213
236
|
printJson(result);
|
|
@@ -228,4 +251,4 @@ var run_default = defineCommand({
|
|
|
228
251
|
export {
|
|
229
252
|
run_default as default
|
|
230
253
|
};
|
|
231
|
-
//# sourceMappingURL=run-
|
|
254
|
+
//# sourceMappingURL=run-GJLDWPUE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import { spawn } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { NeoEvent, PersistedRun } from \"@neotx/core\";\nimport {\n AgentRegistry,\n getRepoRunsDir,\n getRunDispatchPath,\n loadGlobalConfig,\n Orchestrator,\n toRepoSlug,\n} from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printSuccess } from \"../output.js\";\nimport { resolveAgentsDir } from \"../resolve.js\";\n\nfunction printProgress(event: NeoEvent): void {\n const ts = event.timestamp.slice(11, 19);\n switch (event.type) {\n case \"session:start\":\n console.log(`[${ts}] ${event.agent}: starting`);\n break;\n case \"session:complete\":\n console.log(`[${ts}] session complete: $${event.costUsd.toFixed(4)}`);\n break;\n case \"session:fail\":\n console.log(`[${ts}] session failed: ${event.error}`);\n break;\n case \"cost:update\":\n break;\n case \"budget:alert\":\n console.log(`[${ts}] ⚠ Budget alert: ${event.utilizationPct.toFixed(0)}% used`);\n break;\n }\n}\n\nfunction parseMetadata(meta: string | undefined): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n try {\n return JSON.parse(meta) as Record<string, unknown>;\n } catch {\n throw new Error(`Invalid --meta JSON: ${meta}`);\n }\n}\n\nfunction printResult(result: import(\"@neotx/core\").TaskResult, agentName: string): void {\n console.log(\"\");\n console.log(`Run: ${result.runId}`);\n console.log(`Agent: ${agentName}`);\n console.log(`Status: ${result.status}`);\n console.log(`Cost: $${result.costUsd.toFixed(4)}`);\n console.log(`Duration: ${(result.durationMs / 1000).toFixed(1)}s`);\n if (result.branch) {\n console.log(`Branch: ${result.branch}`);\n }\n if (result.prUrl) {\n console.log(`PR: ${result.prUrl}`);\n }\n\n const stepResult = Object.values(result.steps)[0];\n const output = stepResult?.output ?? result.summary;\n if (output) {\n console.log(\"\");\n console.log(typeof output === \"string\" ? output : JSON.stringify(output, null, 2));\n }\n}\n\ninterface DetachParams {\n agentName: string;\n repo: string;\n prompt: string;\n branch: string | undefined;\n priority: string;\n metadata: Record<string, unknown> | undefined;\n bundledAgentsDir: string;\n customAgentsDir: string | undefined;\n jsonOutput: boolean;\n}\n\nasync function runDetached(params: DetachParams): Promise<void> {\n const runId = randomUUID();\n const repoSlug = toRepoSlug({ path: params.repo });\n const runsDir = getRepoRunsDir(repoSlug);\n await mkdir(runsDir, { recursive: true });\n\n const persistedRun: PersistedRun = {\n version: 1,\n runId,\n workflow: `_run_${params.agentName}`,\n repo: params.repo,\n prompt: params.prompt,\n status: \"running\",\n steps: {},\n createdAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n metadata: params.metadata,\n };\n await writeFile(\n path.join(runsDir, `${runId}.json`),\n JSON.stringify(persistedRun, null, 2),\n \"utf-8\",\n );\n\n const dispatchPath = getRunDispatchPath(repoSlug, runId);\n await writeFile(\n dispatchPath,\n JSON.stringify({\n agentName: params.agentName,\n repo: params.repo,\n prompt: params.prompt,\n branch: params.branch,\n priority: params.priority,\n metadata: params.metadata,\n bundledAgentsDir: params.bundledAgentsDir,\n customAgentsDir: params.customAgentsDir,\n }),\n \"utf-8\",\n );\n\n const workerPath = path.join(path.dirname(fileURLToPath(import.meta.url)), \"daemon\", \"worker.js\");\n // Use spawn (not fork) so the child gets its own process group via detached: true.\n // fork() shares the parent's process group, so when the SDK kills the Bash\n // process tree the worker dies too.\n const child = spawn(process.execPath, [workerPath, runId, repoSlug], {\n detached: true,\n stdio: \"ignore\",\n env: process.env,\n });\n child.unref();\n\n if (params.jsonOutput) {\n printJson({ runId, status: \"detached\", pid: child.pid });\n } else {\n printSuccess(`Detached run started: ${runId}`);\n console.log(` PID: ${String(child.pid)}`);\n console.log(` Logs: neo logs -f ${runId}`);\n }\n}\n\nexport default defineCommand({\n meta: {\n name: \"run\",\n description: \"Dispatch an agent to execute a task in an isolated clone\",\n },\n args: {\n agent: {\n type: \"positional\",\n description: \"Agent name to run (e.g. developer, architect, reviewer-quality)\",\n required: true,\n },\n repo: {\n type: \"string\",\n description: \"Target repository path\",\n default: \".\",\n },\n prompt: {\n type: \"string\",\n description: \"Task description for the agent\",\n required: true,\n },\n branch: {\n type: \"string\",\n description: \"Branch name for the session clone (required for writable agents)\",\n },\n priority: {\n type: \"string\",\n description: \"Priority level: critical, high, medium, low\",\n },\n meta: {\n type: \"string\",\n description: \"Metadata as JSON string (for traceability: ticketId, stage, etc.)\",\n },\n output: {\n type: \"string\",\n description: \"Output format: json\",\n },\n detach: {\n type: \"boolean\",\n alias: \"d\",\n description: \"Run in background and return immediately with the run ID\",\n default: true,\n },\n sync: {\n type: \"boolean\",\n alias: \"s\",\n description: \"Run in foreground (blocking) instead of detached\",\n default: false,\n },\n \"git-strategy\": {\n type: \"string\",\n description: \"Git strategy: pr (create PR), branch (push only, default)\",\n },\n },\n async run({ args }) {\n const jsonOutput = args.output === \"json\";\n\n // Zero-config: only need global config (auto-creates ~/.neo/config.yml if absent)\n const config = await loadGlobalConfig();\n const repo = path.resolve(args.repo);\n\n // Load agent registry (bundled + project-local agents)\n const bundledAgentsDir = resolveAgentsDir();\n const customAgentsDir = path.resolve(\".neo/agents\");\n const agentRegistry = new AgentRegistry(\n bundledAgentsDir,\n existsSync(customAgentsDir) ? customAgentsDir : undefined,\n );\n await agentRegistry.load();\n\n // Validate agent exists\n const agent = agentRegistry.get(args.agent);\n if (!agent) {\n const available = agentRegistry\n .list()\n .map((a) => a.name)\n .join(\", \");\n printError(`Agent \"${args.agent}\" not found. Available: ${available}`);\n process.exitCode = 1;\n return;\n }\n\n if (args.detach && !args.sync) {\n await runDetached({\n agentName: args.agent,\n repo,\n prompt: args.prompt,\n branch: args.branch,\n priority: args.priority ?? \"medium\",\n metadata: parseMetadata(args.meta),\n bundledAgentsDir,\n customAgentsDir: existsSync(customAgentsDir) ? customAgentsDir : undefined,\n jsonOutput,\n });\n return;\n }\n\n // ─── Foreground mode (default) ──────────────────────\n const orchestrator = new Orchestrator(config);\n orchestrator.registerAgent(agent);\n orchestrator.registerWorkflow({\n name: `_run_${args.agent}`,\n description: `Direct dispatch to ${args.agent}`,\n steps: {\n run: { agent: args.agent },\n },\n });\n\n if (!jsonOutput) {\n orchestrator.on(\"*\", printProgress);\n }\n\n try {\n await orchestrator.start();\n\n const gitStrategy = args[\"git-strategy\"] as \"pr\" | \"branch\" | undefined;\n const result = await orchestrator.dispatch({\n workflow: `_run_${args.agent}`,\n repo,\n prompt: args.prompt,\n ...(args.branch ? { branch: args.branch } : {}),\n priority: (args.priority as \"critical\" | \"high\" | \"medium\" | \"low\") ?? \"medium\",\n metadata: parseMetadata(args.meta),\n ...(gitStrategy ? { gitStrategy } : {}),\n });\n\n if (jsonOutput) {\n printJson(result);\n } else {\n printResult(result, args.agent);\n }\n\n await orchestrator.shutdown();\n if (result.status !== \"success\") {\n process.exitCode = 1;\n }\n } catch (error) {\n await orchestrator.shutdown();\n printError(error instanceof Error ? error.message : String(error));\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadRunsFiltered,
|
|
3
3
|
resolveRepoFilter
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3ZP3BQXB.js";
|
|
5
5
|
import {
|
|
6
6
|
printError,
|
|
7
7
|
printJson,
|
|
@@ -23,6 +23,9 @@ function totalDuration(run) {
|
|
|
23
23
|
function shortId(runId) {
|
|
24
24
|
return runId.slice(0, 8);
|
|
25
25
|
}
|
|
26
|
+
function repoName(run) {
|
|
27
|
+
return run.repo.split("/").pop() ?? run.repo;
|
|
28
|
+
}
|
|
26
29
|
function showRunDetail(match, short) {
|
|
27
30
|
if (short) {
|
|
28
31
|
console.log(`${match.runId} ${match.status} $${totalCost(match).toFixed(4)}`);
|
|
@@ -59,7 +62,7 @@ function listRuns(runs, short) {
|
|
|
59
62
|
for (const r of runs) {
|
|
60
63
|
const agent = Object.values(r.steps)[0]?.agent ?? "?";
|
|
61
64
|
console.log(
|
|
62
|
-
`${shortId(r.runId)} ${r.status.padEnd(9)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`
|
|
65
|
+
`${shortId(r.runId)} ${r.status.padEnd(9)} ${repoName(r).padEnd(14)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`
|
|
63
66
|
);
|
|
64
67
|
}
|
|
65
68
|
return;
|
|
@@ -69,10 +72,11 @@ function listRuns(runs, short) {
|
|
|
69
72
|
return;
|
|
70
73
|
}
|
|
71
74
|
printTable(
|
|
72
|
-
["RUN", "STATUS", "AGENT", "COST", "DURATION", "BRANCH"],
|
|
75
|
+
["RUN", "STATUS", "REPO", "AGENT", "COST", "DURATION", "BRANCH"],
|
|
73
76
|
runs.map((r) => [
|
|
74
77
|
shortId(r.runId),
|
|
75
78
|
r.status,
|
|
79
|
+
repoName(r),
|
|
76
80
|
Object.values(r.steps)[0]?.agent ?? "unknown",
|
|
77
81
|
`$${totalCost(r).toFixed(4)}`,
|
|
78
82
|
formatDuration(totalDuration(r)),
|
|
@@ -91,11 +95,6 @@ var runs_default = defineCommand({
|
|
|
91
95
|
description: "Run ID to show details (omit to list all runs)",
|
|
92
96
|
required: false
|
|
93
97
|
},
|
|
94
|
-
all: {
|
|
95
|
-
type: "boolean",
|
|
96
|
-
description: "Show runs from all repos",
|
|
97
|
-
default: false
|
|
98
|
-
},
|
|
99
98
|
repo: {
|
|
100
99
|
type: "string",
|
|
101
100
|
description: "Filter by repo name or path"
|
|
@@ -120,7 +119,7 @@ var runs_default = defineCommand({
|
|
|
120
119
|
},
|
|
121
120
|
async run({ args }) {
|
|
122
121
|
const jsonOutput = args.output === "json";
|
|
123
|
-
const filter = await resolveRepoFilter({
|
|
122
|
+
const filter = await resolveRepoFilter({ repo: args.repo });
|
|
124
123
|
let runs = await loadRunsFiltered(filter);
|
|
125
124
|
if (runs.length === 0) {
|
|
126
125
|
if (!jsonOutput) {
|
|
@@ -173,4 +172,4 @@ var runs_default = defineCommand({
|
|
|
173
172
|
export {
|
|
174
173
|
runs_default as default
|
|
175
174
|
};
|
|
176
|
-
//# sourceMappingURL=runs-
|
|
175
|
+
//# sourceMappingURL=runs-LOYOWU55.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/runs.ts"],"sourcesContent":["import type { PersistedRun } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printJson, printTable } from \"../output.js\";\nimport { loadRunsFiltered, resolveRepoFilter } from \"../repo-filter.js\";\n\nfunction formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\nfunction totalCost(run: PersistedRun): number {\n return Object.values(run.steps).reduce((sum, s) => sum + s.costUsd, 0);\n}\n\nfunction totalDuration(run: PersistedRun): number {\n return Object.values(run.steps).reduce((sum, s) => sum + s.durationMs, 0);\n}\n\nfunction shortId(runId: string): string {\n return runId.slice(0, 8);\n}\n\nfunction repoName(run: PersistedRun): string {\n return run.repo.split(\"/\").pop() ?? run.repo;\n}\n\nfunction showRunDetail(match: PersistedRun, short: boolean): void {\n if (short) {\n console.log(`${match.runId} ${match.status} $${totalCost(match).toFixed(4)}`);\n for (const [name, step] of Object.entries(match.steps)) {\n const out = typeof step.output === \"string\" ? step.output.slice(0, 200) : \"\";\n console.log(` ${name}: ${step.status} ${step.agent} ${out}`);\n }\n return;\n }\n\n console.log(`Run: ${match.runId}`);\n console.log(`Status: ${match.status}`);\n console.log(`Repo: ${match.repo}`);\n console.log(`Prompt: ${match.prompt}`);\n if (match.branch) console.log(`Branch: ${match.branch}`);\n console.log(`Cost: $${totalCost(match).toFixed(4)}`);\n console.log(`Duration: ${formatDuration(totalDuration(match))}`);\n console.log(`Created: ${match.createdAt}`);\n console.log(\"\");\n for (const [name, step] of Object.entries(match.steps)) {\n console.log(`Step: ${name}`);\n console.log(` Agent: ${step.agent}`);\n console.log(` Status: ${step.status}`);\n console.log(` Cost: $${step.costUsd.toFixed(4)}`);\n console.log(` Duration: ${formatDuration(step.durationMs)}`);\n if (step.error) console.log(` Error: ${step.error}`);\n if (step.output) {\n const out = typeof step.output === \"string\" ? step.output : JSON.stringify(step.output);\n console.log(` Output: ${out}`);\n }\n }\n}\n\nfunction listRuns(runs: PersistedRun[], short: boolean): void {\n if (short) {\n for (const r of runs) {\n const agent = Object.values(r.steps)[0]?.agent ?? \"?\";\n console.log(\n `${shortId(r.runId)} ${r.status.padEnd(9)} ${repoName(r).padEnd(14)} ${agent.padEnd(18)} $${totalCost(r).toFixed(4).padStart(8)} ${formatDuration(totalDuration(r)).padStart(7)}`,\n );\n }\n return;\n }\n\n if (runs.length === 0) {\n console.log(\"No runs found.\");\n return;\n }\n\n printTable(\n [\"RUN\", \"STATUS\", \"REPO\", \"AGENT\", \"COST\", \"DURATION\", \"BRANCH\"],\n runs.map((r) => [\n shortId(r.runId),\n r.status,\n repoName(r),\n Object.values(r.steps)[0]?.agent ?? \"unknown\",\n `$${totalCost(r).toFixed(4)}`,\n formatDuration(totalDuration(r)),\n r.branch?.replace(\"feat/run-\", \"\").slice(0, 8) ?? \"-\",\n ]),\n );\n}\n\nexport default defineCommand({\n meta: {\n name: \"runs\",\n description: \"List runs or show details of a specific run\",\n },\n args: {\n runId: {\n type: \"positional\",\n description: \"Run ID to show details (omit to list all runs)\",\n required: false,\n },\n repo: {\n type: \"string\",\n description: \"Filter by repo name or path\",\n },\n last: {\n type: \"string\",\n description: \"Show only the last N runs\",\n },\n status: {\n type: \"string\",\n description: \"Filter by status: completed, failed, running\",\n },\n short: {\n type: \"boolean\",\n description: \"Compact output for supervisor agents (saves tokens)\",\n default: false,\n },\n output: {\n type: \"string\",\n description: \"Output format: json\",\n },\n },\n async run({ args }) {\n const jsonOutput = args.output === \"json\";\n const filter = await resolveRepoFilter({ repo: args.repo });\n let runs = await loadRunsFiltered(filter);\n\n if (runs.length === 0) {\n if (!jsonOutput) {\n printError(\"No runs found. Run 'neo run <agent>' first.\");\n } else {\n printJson([]);\n }\n return;\n }\n\n // If a runId is given (full or prefix), show details\n if (args.runId) {\n const match = runs.find(\n (r) => r.runId === args.runId || r.runId.startsWith(args.runId as string),\n );\n if (!match) {\n printError(`Run \"${args.runId}\" not found.`);\n process.exitCode = 1;\n return;\n }\n\n if (jsonOutput) {\n printJson(match);\n return;\n }\n\n showRunDetail(match, args.short);\n return;\n }\n\n // List mode\n if (args.status) {\n runs = runs.filter((r) => r.status === args.status);\n }\n\n if (args.last) {\n runs = runs.slice(0, Number(args.last));\n }\n\n if (jsonOutput) {\n printJson(\n runs.map((r) => ({\n runId: r.runId,\n status: r.status,\n repo: r.repo,\n agent: Object.values(r.steps)[0]?.agent ?? \"unknown\",\n costUsd: totalCost(r),\n durationMs: totalDuration(r),\n branch: r.branch,\n updatedAt: r.updatedAt,\n })),\n );\n return;\n }\n\n listRuns(runs, args.short);\n },\n});\n"],"mappings":"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","names":[]}
|