@neotx/cli 0.1.0-alpha.24 → 0.1.0-alpha.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/child-5X5IHAKS.js +92 -0
- package/dist/child-5X5IHAKS.js.map +1 -0
- package/dist/child-mode-IB3XSUHD.js +8 -0
- package/dist/child-mode-IB3XSUHD.js.map +1 -0
- package/dist/chunk-4TQ3Q6IE.js +43 -0
- package/dist/chunk-4TQ3Q6IE.js.map +1 -0
- package/dist/chunk-6PSXZ3UV.js +46 -0
- package/dist/chunk-6PSXZ3UV.js.map +1 -0
- package/dist/chunk-V5SN5F73.js +54 -0
- package/dist/chunk-V5SN5F73.js.map +1 -0
- package/dist/daemon/child-supervisor-worker.js +136 -0
- package/dist/daemon/child-supervisor-worker.js.map +1 -0
- package/dist/daemon/supervisor-worker.js +9 -1
- package/dist/daemon/supervisor-worker.js.map +1 -1
- package/dist/daemon/worker.js +16 -3
- package/dist/daemon/worker.js.map +1 -1
- package/dist/directive-7WM2Q2UW.js +259 -0
- package/dist/directive-7WM2Q2UW.js.map +1 -0
- package/dist/do-F5XW2ELZ.js +83 -0
- package/dist/do-F5XW2ELZ.js.map +1 -0
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/{log-PTHLI7ZN.js → log-ZLIAIBZQ.js} +64 -9
- package/dist/log-ZLIAIBZQ.js.map +1 -0
- package/dist/{memory-SDZ57W2S.js → memory-CW6E65SQ.js} +112 -62
- package/dist/memory-CW6E65SQ.js.map +1 -0
- package/dist/{run-MWHIQUSY.js → run-NV762V5B.js} +56 -22
- package/dist/run-NV762V5B.js.map +1 -0
- package/dist/{supervise-XMZRNODO.js → supervise-BWIKWNHH.js} +68 -41
- package/dist/supervise-BWIKWNHH.js.map +1 -0
- package/dist/{supervisor-3RUX5SPH.js → supervisor-N4D5EWCC.js} +1 -1
- package/dist/tui-LSW7VVK6.js +1319 -0
- package/dist/tui-LSW7VVK6.js.map +1 -0
- package/package.json +4 -4
- package/dist/log-PTHLI7ZN.js.map +0 -1
- package/dist/memory-SDZ57W2S.js.map +0 -1
- package/dist/run-MWHIQUSY.js.map +0 -1
- package/dist/supervise-XMZRNODO.js.map +0 -1
- package/dist/tui-67VJ5VBA.js +0 -842
- package/dist/tui-67VJ5VBA.js.map +0 -1
- /package/dist/{supervisor-3RUX5SPH.js.map → supervisor-N4D5EWCC.js.map} +0 -0
|
@@ -6,9 +6,15 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// src/commands/memory.ts
|
|
8
8
|
import path from "path";
|
|
9
|
-
import { getSupervisorDir,
|
|
9
|
+
import { getSupervisorDir, MemoryStore } from "@neotx/core";
|
|
10
10
|
import { defineCommand } from "citty";
|
|
11
|
-
var VALID_TYPES = ["
|
|
11
|
+
var VALID_TYPES = ["knowledge", "warning", "focus"];
|
|
12
|
+
var VALID_SUBTYPES = ["fact", "procedure"];
|
|
13
|
+
var LEGACY_TYPE_MAP = {
|
|
14
|
+
fact: { type: "knowledge", subtype: "fact" },
|
|
15
|
+
procedure: { type: "knowledge", subtype: "procedure" },
|
|
16
|
+
feedback: { type: "warning" }
|
|
17
|
+
};
|
|
12
18
|
function parseDuration(input) {
|
|
13
19
|
const match = input.match(/^(\d+)(h|m)$/);
|
|
14
20
|
if (!match) return void 0;
|
|
@@ -20,25 +26,21 @@ function parseDuration(input) {
|
|
|
20
26
|
function truncate(text, max) {
|
|
21
27
|
return text.length > max ? `${text.slice(0, max - 1)}\u2026` : text;
|
|
22
28
|
}
|
|
23
|
-
function
|
|
24
|
-
try {
|
|
25
|
-
return new LocalEmbedder();
|
|
26
|
-
} catch (err) {
|
|
27
|
-
console.debug(
|
|
28
|
-
`[memory] Failed to create embedder: ${err instanceof Error ? err.message : String(err)}`
|
|
29
|
-
);
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function openStore(name, withEmbeddings = false) {
|
|
29
|
+
function openStore(name) {
|
|
34
30
|
const dir = getSupervisorDir(name);
|
|
35
|
-
|
|
36
|
-
return new MemoryStore(path.join(dir, "memory.sqlite"), embedder);
|
|
31
|
+
return new MemoryStore(path.join(dir, "memory.sqlite"));
|
|
37
32
|
}
|
|
38
|
-
function formatResultsTable(results) {
|
|
33
|
+
function formatResultsTable(results, full = false) {
|
|
34
|
+
const maxContent = full ? 500 : 60;
|
|
39
35
|
printTable(
|
|
40
36
|
["ID", "TYPE", "SCOPE", "CONTENT", "ACCESSES"],
|
|
41
|
-
results.map((m) => [
|
|
37
|
+
results.map((m) => [
|
|
38
|
+
m.id,
|
|
39
|
+
m.type,
|
|
40
|
+
m.scope,
|
|
41
|
+
truncate(m.content, maxContent),
|
|
42
|
+
String(m.accessCount)
|
|
43
|
+
])
|
|
42
44
|
);
|
|
43
45
|
}
|
|
44
46
|
async function handleWrite(args) {
|
|
@@ -47,9 +49,24 @@ async function handleWrite(args) {
|
|
|
47
49
|
process.exitCode = 1;
|
|
48
50
|
return;
|
|
49
51
|
}
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
const inputType = args.type ?? "knowledge";
|
|
53
|
+
const legacyMapping = LEGACY_TYPE_MAP[inputType];
|
|
54
|
+
let type;
|
|
55
|
+
let subtype;
|
|
56
|
+
if (legacyMapping) {
|
|
57
|
+
type = legacyMapping.type;
|
|
58
|
+
subtype = args.subtype ?? legacyMapping.subtype;
|
|
59
|
+
} else if (VALID_TYPES.includes(inputType)) {
|
|
60
|
+
type = inputType;
|
|
61
|
+
subtype = args.subtype ?? (type === "knowledge" ? "fact" : void 0);
|
|
62
|
+
} else {
|
|
63
|
+
const allValid = [...VALID_TYPES, ...Object.keys(LEGACY_TYPE_MAP)];
|
|
64
|
+
printError(`Invalid type "${inputType}". Must be one of: ${allValid.join(", ")}`);
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (type === "knowledge" && subtype && !VALID_SUBTYPES.includes(subtype)) {
|
|
69
|
+
printError(`Invalid subtype "${subtype}". Must be one of: ${VALID_SUBTYPES.join(", ")}`);
|
|
53
70
|
process.exitCode = 1;
|
|
54
71
|
return;
|
|
55
72
|
}
|
|
@@ -62,7 +79,7 @@ async function handleWrite(args) {
|
|
|
62
79
|
return;
|
|
63
80
|
}
|
|
64
81
|
}
|
|
65
|
-
const store = openStore(args.name
|
|
82
|
+
const store = openStore(args.name);
|
|
66
83
|
try {
|
|
67
84
|
const tags = args.tags ? args.tags.split(",").map((t) => t.trim()) : [];
|
|
68
85
|
const id = await store.write({
|
|
@@ -72,9 +89,8 @@ async function handleWrite(args) {
|
|
|
72
89
|
source: args.source,
|
|
73
90
|
tags,
|
|
74
91
|
expiresAt,
|
|
75
|
-
|
|
76
|
-
category: args.category
|
|
77
|
-
outcome: args.outcome
|
|
92
|
+
...type === "knowledge" && subtype && { subtype },
|
|
93
|
+
...type === "warning" && args.category && { category: args.category }
|
|
78
94
|
});
|
|
79
95
|
printSuccess(`Memory written: ${id}`);
|
|
80
96
|
} finally {
|
|
@@ -95,10 +111,9 @@ function handleForget(args) {
|
|
|
95
111
|
store.close();
|
|
96
112
|
}
|
|
97
113
|
}
|
|
98
|
-
var VALID_OUTCOMES = ["pending", "in_progress", "done", "blocked", "abandoned"];
|
|
99
114
|
function handleUpdate(args) {
|
|
100
115
|
if (!args.value) {
|
|
101
|
-
printError(
|
|
116
|
+
printError("Usage: neo memory update <id> <new content>");
|
|
102
117
|
process.exitCode = 1;
|
|
103
118
|
return;
|
|
104
119
|
}
|
|
@@ -106,33 +121,21 @@ function handleUpdate(args) {
|
|
|
106
121
|
const updateIdx = argv.indexOf("update");
|
|
107
122
|
const idArg = argv[updateIdx + 1];
|
|
108
123
|
const contentArg = argv[updateIdx + 2];
|
|
109
|
-
if (args.outcome && !VALID_OUTCOMES.includes(args.outcome)) {
|
|
110
|
-
printError(`Invalid outcome "${args.outcome}". Must be one of: ${VALID_OUTCOMES.join(", ")}`);
|
|
111
|
-
process.exitCode = 1;
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
124
|
const isContentArgAFlag = contentArg?.startsWith("--");
|
|
115
125
|
const hasContent = contentArg && !isContentArgAFlag;
|
|
116
|
-
if (!hasContent
|
|
117
|
-
printError(
|
|
126
|
+
if (!hasContent) {
|
|
127
|
+
printError("Usage: neo memory update <id> <new content>");
|
|
118
128
|
process.exitCode = 1;
|
|
119
129
|
return;
|
|
120
130
|
}
|
|
121
131
|
if (!idArg) {
|
|
122
|
-
printError(
|
|
132
|
+
printError("Usage: neo memory update <id> <new content>");
|
|
123
133
|
process.exitCode = 1;
|
|
124
134
|
return;
|
|
125
135
|
}
|
|
126
136
|
const store = openStore(args.name);
|
|
127
137
|
try {
|
|
128
|
-
|
|
129
|
-
store.updateFields(idArg, {
|
|
130
|
-
...hasContent && { content: contentArg },
|
|
131
|
-
outcome: args.outcome
|
|
132
|
-
});
|
|
133
|
-
} else {
|
|
134
|
-
store.update(idArg, contentArg);
|
|
135
|
-
}
|
|
138
|
+
store.update(idArg, contentArg);
|
|
136
139
|
printSuccess(`Memory updated: ${idArg}`);
|
|
137
140
|
} finally {
|
|
138
141
|
store.close();
|
|
@@ -144,7 +147,7 @@ async function handleSearch(args) {
|
|
|
144
147
|
process.exitCode = 1;
|
|
145
148
|
return;
|
|
146
149
|
}
|
|
147
|
-
const store = openStore(args.name
|
|
150
|
+
const store = openStore(args.name);
|
|
148
151
|
try {
|
|
149
152
|
const results = await store.search(args.value, {
|
|
150
153
|
...args.scope !== "global" && { scope: args.scope },
|
|
@@ -154,7 +157,18 @@ async function handleSearch(args) {
|
|
|
154
157
|
console.log("No memories found.");
|
|
155
158
|
return;
|
|
156
159
|
}
|
|
157
|
-
|
|
160
|
+
const maxContent = args.full ? 500 : 60;
|
|
161
|
+
printTable(
|
|
162
|
+
["ID", "TYPE", "SCOPE", "SCORE", "CONTENT", "ACCESSES"],
|
|
163
|
+
results.map((m) => [
|
|
164
|
+
m.id,
|
|
165
|
+
m.type,
|
|
166
|
+
m.scope,
|
|
167
|
+
`${(m.score * 100).toFixed(0)}%`,
|
|
168
|
+
truncate(m.content, maxContent),
|
|
169
|
+
String(m.accessCount)
|
|
170
|
+
])
|
|
171
|
+
);
|
|
158
172
|
} finally {
|
|
159
173
|
store.close();
|
|
160
174
|
}
|
|
@@ -170,7 +184,26 @@ function handleList(args) {
|
|
|
170
184
|
console.log("No memories found.");
|
|
171
185
|
return;
|
|
172
186
|
}
|
|
173
|
-
formatResultsTable(results);
|
|
187
|
+
formatResultsTable(results, args.full);
|
|
188
|
+
} finally {
|
|
189
|
+
store.close();
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function handleRecent(args) {
|
|
193
|
+
const limit = args.limit ? Number(args.limit) : 10;
|
|
194
|
+
const store = openStore(args.name);
|
|
195
|
+
try {
|
|
196
|
+
const results = store.query({
|
|
197
|
+
...args.scope !== "global" && { scope: args.scope },
|
|
198
|
+
...args.type && { types: [args.type] },
|
|
199
|
+
sortBy: "createdAt",
|
|
200
|
+
limit
|
|
201
|
+
});
|
|
202
|
+
if (results.length === 0) {
|
|
203
|
+
console.log("No memories found.");
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
formatResultsTable(results, args.full);
|
|
174
207
|
} finally {
|
|
175
208
|
store.close();
|
|
176
209
|
}
|
|
@@ -193,6 +226,15 @@ function handleStats(args) {
|
|
|
193
226
|
["SCOPE", "COUNT"],
|
|
194
227
|
Object.entries(s.byScope).map(([sc, c]) => [sc, String(c)])
|
|
195
228
|
);
|
|
229
|
+
console.log();
|
|
230
|
+
}
|
|
231
|
+
const topAccessed = store.topAccessed(5);
|
|
232
|
+
if (topAccessed.length > 0) {
|
|
233
|
+
console.log("Top 5 most-accessed memories:\n");
|
|
234
|
+
printTable(
|
|
235
|
+
["ID", "TYPE", "ACCESSES", "CONTENT"],
|
|
236
|
+
topAccessed.map((m) => [m.id, m.type, String(m.accessCount), truncate(m.content, 50)])
|
|
237
|
+
);
|
|
196
238
|
}
|
|
197
239
|
} finally {
|
|
198
240
|
store.close();
|
|
@@ -206,7 +248,7 @@ var memory_default = defineCommand({
|
|
|
206
248
|
args: {
|
|
207
249
|
action: {
|
|
208
250
|
type: "positional",
|
|
209
|
-
description: "Action: write, forget, update, search, list, stats",
|
|
251
|
+
description: "Action: write, forget, update, search, list, stats, recent",
|
|
210
252
|
required: true
|
|
211
253
|
},
|
|
212
254
|
value: {
|
|
@@ -216,7 +258,11 @@ var memory_default = defineCommand({
|
|
|
216
258
|
},
|
|
217
259
|
type: {
|
|
218
260
|
type: "string",
|
|
219
|
-
description: "Memory type:
|
|
261
|
+
description: "Memory type: knowledge, warning, focus"
|
|
262
|
+
},
|
|
263
|
+
subtype: {
|
|
264
|
+
type: "string",
|
|
265
|
+
description: "Knowledge subtype: fact, procedure (only for knowledge type)"
|
|
220
266
|
},
|
|
221
267
|
scope: {
|
|
222
268
|
type: "string",
|
|
@@ -232,26 +278,27 @@ var memory_default = defineCommand({
|
|
|
232
278
|
type: "string",
|
|
233
279
|
description: "TTL for focus entries (e.g. 2h, 30m)"
|
|
234
280
|
},
|
|
235
|
-
outcome: {
|
|
236
|
-
type: "string",
|
|
237
|
-
description: "Task outcome: pending, in_progress, done, blocked, abandoned"
|
|
238
|
-
},
|
|
239
|
-
severity: {
|
|
240
|
-
type: "string",
|
|
241
|
-
description: "Priority: critical, high, medium, low"
|
|
242
|
-
},
|
|
243
281
|
category: {
|
|
244
282
|
type: "string",
|
|
245
|
-
description: "
|
|
283
|
+
description: "Warning category (e.g. input_validation, testing)"
|
|
246
284
|
},
|
|
247
285
|
tags: {
|
|
248
286
|
type: "string",
|
|
249
|
-
description: "Comma-separated tags
|
|
287
|
+
description: "Comma-separated tags"
|
|
250
288
|
},
|
|
251
289
|
name: {
|
|
252
290
|
type: "string",
|
|
253
291
|
description: "Supervisor name",
|
|
254
292
|
default: "supervisor"
|
|
293
|
+
},
|
|
294
|
+
full: {
|
|
295
|
+
type: "boolean",
|
|
296
|
+
description: "Show full content without truncation",
|
|
297
|
+
default: false
|
|
298
|
+
},
|
|
299
|
+
limit: {
|
|
300
|
+
type: "string",
|
|
301
|
+
description: "Limit number of results (for recent command)"
|
|
255
302
|
}
|
|
256
303
|
},
|
|
257
304
|
async run({ args }) {
|
|
@@ -259,14 +306,15 @@ var memory_default = defineCommand({
|
|
|
259
306
|
const parsed = {
|
|
260
307
|
value: args.value,
|
|
261
308
|
type: args.type,
|
|
309
|
+
subtype: args.subtype,
|
|
262
310
|
scope: args.scope,
|
|
263
311
|
source: args.source,
|
|
264
312
|
expires: args.expires,
|
|
265
313
|
name: args.name,
|
|
266
|
-
outcome: args.outcome,
|
|
267
|
-
severity: args.severity,
|
|
268
314
|
category: args.category,
|
|
269
|
-
tags: args.tags
|
|
315
|
+
tags: args.tags,
|
|
316
|
+
full: args.full,
|
|
317
|
+
limit: args.limit
|
|
270
318
|
};
|
|
271
319
|
switch (action) {
|
|
272
320
|
case "write":
|
|
@@ -281,9 +329,11 @@ var memory_default = defineCommand({
|
|
|
281
329
|
return handleList(parsed);
|
|
282
330
|
case "stats":
|
|
283
331
|
return handleStats(parsed);
|
|
332
|
+
case "recent":
|
|
333
|
+
return handleRecent(parsed);
|
|
284
334
|
default:
|
|
285
335
|
printError(
|
|
286
|
-
`Unknown action "${action}". Must be one of: write, forget, update, search, list, stats`
|
|
336
|
+
`Unknown action "${action}". Must be one of: write, forget, update, search, list, stats, recent`
|
|
287
337
|
);
|
|
288
338
|
process.exitCode = 1;
|
|
289
339
|
}
|
|
@@ -292,4 +342,4 @@ var memory_default = defineCommand({
|
|
|
292
342
|
export {
|
|
293
343
|
memory_default as default
|
|
294
344
|
};
|
|
295
|
-
//# sourceMappingURL=memory-
|
|
345
|
+
//# sourceMappingURL=memory-CW6E65SQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/memory.ts"],"sourcesContent":["import path from \"node:path\";\nimport type { KnowledgeSubtype, MemoryEntry, MemoryType } from \"@neotx/core\";\nimport { getSupervisorDir, MemoryStore } from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess, printTable } from \"../output.js\";\n\nconst VALID_TYPES = [\"knowledge\", \"warning\", \"focus\"] as const;\nconst VALID_SUBTYPES = [\"fact\", \"procedure\"] as const;\n\n// Legacy type aliases for backward compatibility\n// Agents/docs may use: --type fact, --type procedure, --type feedback\nconst LEGACY_TYPE_MAP: Record<string, { type: MemoryType; subtype?: KnowledgeSubtype }> = {\n fact: { type: \"knowledge\", subtype: \"fact\" },\n procedure: { type: \"knowledge\", subtype: \"procedure\" },\n feedback: { type: \"warning\" },\n};\n\ninterface ParsedArgs {\n value: string | undefined;\n type: string | undefined;\n subtype: string | undefined;\n scope: string;\n source: string;\n expires: string | undefined;\n name: string;\n category: string | undefined;\n tags: string | undefined;\n full: boolean;\n limit: 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 openStore(name: string): MemoryStore {\n const dir = getSupervisorDir(name);\n return new MemoryStore(path.join(dir, \"memory.sqlite\"));\n}\n\nfunction formatResultsTable(results: MemoryEntry[], full = false): void {\n const maxContent = full ? 500 : 60;\n printTable(\n [\"ID\", \"TYPE\", \"SCOPE\", \"CONTENT\", \"ACCESSES\"],\n results.map((m) => [\n m.id,\n m.type,\n m.scope,\n truncate(m.content, maxContent),\n String(m.accessCount),\n ]),\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 inputType = args.type ?? \"knowledge\";\n\n // Map legacy types (fact, procedure, feedback) to new schema\n const legacyMapping = LEGACY_TYPE_MAP[inputType];\n let type: MemoryType;\n let subtype: KnowledgeSubtype | undefined;\n\n if (legacyMapping) {\n type = legacyMapping.type;\n subtype = (args.subtype as KnowledgeSubtype | undefined) ?? legacyMapping.subtype;\n } else if (VALID_TYPES.includes(inputType as MemoryType)) {\n type = inputType as MemoryType;\n subtype =\n (args.subtype as KnowledgeSubtype | undefined) ?? (type === \"knowledge\" ? \"fact\" : undefined);\n } else {\n const allValid = [...VALID_TYPES, ...Object.keys(LEGACY_TYPE_MAP)];\n printError(`Invalid type \"${inputType}\". Must be one of: ${allValid.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n // Validate subtype for knowledge type\n if (type === \"knowledge\" && subtype && !VALID_SUBTYPES.includes(subtype)) {\n printError(`Invalid subtype \"${subtype}\". Must be one of: ${VALID_SUBTYPES.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);\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 ...(type === \"knowledge\" && subtype && { subtype: subtype as KnowledgeSubtype }),\n ...(type === \"warning\" && args.category && { category: args.category }),\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\nfunction handleUpdate(args: ParsedArgs): void {\n if (!args.value) {\n printError(\"Usage: neo memory update <id> <new content>\");\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 // Determine if contentArg is actually content or a flag\n const isContentArgAFlag = contentArg?.startsWith(\"--\");\n const hasContent = contentArg && !isContentArgAFlag;\n\n // Need content\n if (!hasContent) {\n printError(\"Usage: neo memory update <id> <new content>\");\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>\");\n process.exitCode = 1;\n return;\n }\n\n const store = openStore(args.name);\n try {\n store.update(idArg, contentArg as string);\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);\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 // Display with relevance score\n const maxContent = args.full ? 500 : 60;\n printTable(\n [\"ID\", \"TYPE\", \"SCOPE\", \"SCORE\", \"CONTENT\", \"ACCESSES\"],\n results.map((m) => [\n m.id,\n m.type,\n m.scope,\n `${(m.score * 100).toFixed(0)}%`,\n truncate(m.content, maxContent),\n String(m.accessCount),\n ]),\n );\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, args.full);\n } finally {\n store.close();\n }\n}\n\nfunction handleRecent(args: ParsedArgs): void {\n const limit = args.limit ? Number(args.limit) : 10;\n\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 sortBy: \"createdAt\",\n limit,\n });\n\n if (results.length === 0) {\n console.log(\"No memories found.\");\n return;\n }\n\n formatResultsTable(results, args.full);\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 console.log();\n }\n\n // Show top 5 most-accessed memories\n const topAccessed = store.topAccessed(5);\n if (topAccessed.length > 0) {\n console.log(\"Top 5 most-accessed memories:\\n\");\n printTable(\n [\"ID\", \"TYPE\", \"ACCESSES\", \"CONTENT\"],\n topAccessed.map((m) => [m.id, m.type, String(m.accessCount), truncate(m.content, 50)]),\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, recent\",\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: knowledge, warning, focus\",\n },\n subtype: {\n type: \"string\",\n description: \"Knowledge subtype: fact, procedure (only for knowledge type)\",\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 category: {\n type: \"string\",\n description: \"Warning category (e.g. input_validation, testing)\",\n },\n tags: {\n type: \"string\",\n description: \"Comma-separated tags\",\n },\n name: {\n type: \"string\",\n description: \"Supervisor name\",\n default: \"supervisor\",\n },\n full: {\n type: \"boolean\",\n description: \"Show full content without truncation\",\n default: false,\n },\n limit: {\n type: \"string\",\n description: \"Limit number of results (for recent command)\",\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 subtype: args.subtype 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 category: args.category as string | undefined,\n tags: args.tags as string | undefined,\n full: args.full as boolean,\n limit: args.limit 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 case \"recent\":\n return handleRecent(parsed);\n default:\n printError(\n `Unknown action \"${action}\". Must be one of: write, forget, update, search, list, stats, recent`,\n );\n process.exitCode = 1;\n }\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveAgentsDir
|
|
3
3
|
} from "./chunk-F622JUDY.js";
|
|
4
|
+
import {
|
|
5
|
+
spawnWithConfirmation
|
|
6
|
+
} from "./chunk-6PSXZ3UV.js";
|
|
4
7
|
import {
|
|
5
8
|
printError,
|
|
6
9
|
printJson,
|
|
@@ -8,7 +11,6 @@ import {
|
|
|
8
11
|
} from "./chunk-YQIWMDXL.js";
|
|
9
12
|
|
|
10
13
|
// src/commands/run.ts
|
|
11
|
-
import { spawn } from "child_process";
|
|
12
14
|
import { randomUUID } from "crypto";
|
|
13
15
|
import { existsSync } from "fs";
|
|
14
16
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
@@ -18,6 +20,7 @@ import {
|
|
|
18
20
|
AgentRegistry,
|
|
19
21
|
getRepoRunsDir,
|
|
20
22
|
getRunDispatchPath,
|
|
23
|
+
getWorkerStartedPath,
|
|
21
24
|
loadGlobalConfig,
|
|
22
25
|
Orchestrator,
|
|
23
26
|
toRepoSlug
|
|
@@ -72,6 +75,18 @@ function printResult(result, agentName) {
|
|
|
72
75
|
console.log(typeof output === "string" ? output : JSON.stringify(output, null, 2));
|
|
73
76
|
}
|
|
74
77
|
}
|
|
78
|
+
var WORKER_STARTUP_TIMEOUT_MS = 5e3;
|
|
79
|
+
var WORKER_STARTUP_POLL_MS = 100;
|
|
80
|
+
async function waitForWorkerStartup(startedPath, timeoutMs) {
|
|
81
|
+
const deadline = Date.now() + timeoutMs;
|
|
82
|
+
while (Date.now() < deadline) {
|
|
83
|
+
if (existsSync(startedPath)) {
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
await new Promise((resolve) => setTimeout(resolve, WORKER_STARTUP_POLL_MS));
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
75
90
|
async function runDetached(params) {
|
|
76
91
|
const runId = randomUUID();
|
|
77
92
|
const repoSlug = toRepoSlug({ path: params.repo });
|
|
@@ -89,11 +104,8 @@ async function runDetached(params) {
|
|
|
89
104
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
90
105
|
metadata: params.metadata
|
|
91
106
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
JSON.stringify(persistedRun, null, 2),
|
|
95
|
-
"utf-8"
|
|
96
|
-
);
|
|
107
|
+
const runFilePath = path.join(runsDir, `${runId}.json`);
|
|
108
|
+
await writeFile(runFilePath, JSON.stringify(persistedRun, null, 2), "utf-8");
|
|
97
109
|
const dispatchPath = getRunDispatchPath(repoSlug, runId);
|
|
98
110
|
await writeFile(
|
|
99
111
|
dispatchPath,
|
|
@@ -110,30 +122,52 @@ async function runDetached(params) {
|
|
|
110
122
|
"utf-8"
|
|
111
123
|
);
|
|
112
124
|
const workerPath = path.join(path.dirname(fileURLToPath(import.meta.url)), "daemon", "worker.js");
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
125
|
+
const spawnResult = await spawnWithConfirmation(process.execPath, [workerPath, runId, repoSlug]);
|
|
126
|
+
if ("error" in spawnResult) {
|
|
127
|
+
try {
|
|
128
|
+
const raw = await readFile(runFilePath, "utf-8");
|
|
129
|
+
const run = JSON.parse(raw);
|
|
130
|
+
run.status = "failed";
|
|
131
|
+
run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
132
|
+
await writeFile(runFilePath, JSON.stringify(run, null, 2), "utf-8");
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
printError(`Failed to spawn worker: ${spawnResult.error}`);
|
|
136
|
+
process.exitCode = 1;
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
const startedPath = getWorkerStartedPath(repoSlug, runId);
|
|
140
|
+
const workerStarted = await waitForWorkerStartup(startedPath, WORKER_STARTUP_TIMEOUT_MS);
|
|
141
|
+
if (!workerStarted) {
|
|
121
142
|
try {
|
|
122
143
|
const raw = await readFile(runFilePath, "utf-8");
|
|
123
144
|
const run = JSON.parse(raw);
|
|
124
|
-
run.
|
|
145
|
+
run.status = "failed";
|
|
146
|
+
run.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
125
147
|
await writeFile(runFilePath, JSON.stringify(run, null, 2), "utf-8");
|
|
126
|
-
} catch
|
|
127
|
-
console.debug(
|
|
128
|
-
`[run] Failed to update run file with PID: ${err instanceof Error ? err.message : String(err)}`
|
|
129
|
-
);
|
|
148
|
+
} catch {
|
|
130
149
|
}
|
|
150
|
+
printError(
|
|
151
|
+
`Worker failed to start within ${WORKER_STARTUP_TIMEOUT_MS / 1e3}s. The process may have crashed before initialization.`
|
|
152
|
+
);
|
|
153
|
+
process.exitCode = 1;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const raw = await readFile(runFilePath, "utf-8");
|
|
158
|
+
const run = JSON.parse(raw);
|
|
159
|
+
run.pid = spawnResult.pid;
|
|
160
|
+
await writeFile(runFilePath, JSON.stringify(run, null, 2), "utf-8");
|
|
161
|
+
} catch (err) {
|
|
162
|
+
console.debug(
|
|
163
|
+
`[run] Failed to update run file with PID: ${err instanceof Error ? err.message : String(err)}`
|
|
164
|
+
);
|
|
131
165
|
}
|
|
132
166
|
if (params.jsonOutput) {
|
|
133
|
-
printJson({ runId, status: "detached", pid:
|
|
167
|
+
printJson({ runId, status: "detached", pid: spawnResult.pid });
|
|
134
168
|
} else {
|
|
135
169
|
printSuccess(`Detached run started: ${runId}`);
|
|
136
|
-
console.log(` PID: ${String(
|
|
170
|
+
console.log(` PID: ${String(spawnResult.pid)}`);
|
|
137
171
|
console.log(` Logs: neo logs -f ${runId}`);
|
|
138
172
|
}
|
|
139
173
|
}
|
|
@@ -259,4 +293,4 @@ var run_default = defineCommand({
|
|
|
259
293
|
export {
|
|
260
294
|
run_default as default
|
|
261
295
|
};
|
|
262
|
-
//# sourceMappingURL=run-
|
|
296
|
+
//# sourceMappingURL=run-NV762V5B.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { mkdir, readFile, 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 getWorkerStartedPath,\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\";\nimport { spawnWithConfirmation } from \"../spawn-utils.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 (err) {\n // Expected error: invalid JSON provided by user\n throw new Error(\n `Invalid --meta JSON: ${meta}. Error: ${err instanceof Error ? err.message : String(err)}`,\n );\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\n/**\n * Time in milliseconds to wait for worker startup confirmation.\n * The worker writes a .started file immediately after spawning.\n * If this file doesn't appear within the timeout, the worker likely crashed.\n */\nconst WORKER_STARTUP_TIMEOUT_MS = 5000;\n\n/**\n * Polling interval for checking if the worker has started.\n */\nconst WORKER_STARTUP_POLL_MS = 100;\n\n/**\n * Wait for the worker to write its startup confirmation file.\n * Returns true if the worker started successfully, false if it timed out.\n */\nasync function waitForWorkerStartup(startedPath: string, timeoutMs: number): Promise<boolean> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n if (existsSync(startedPath)) {\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, WORKER_STARTUP_POLL_MS));\n }\n return false;\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 agent: 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 const runFilePath = path.join(runsDir, `${runId}.json`);\n await writeFile(runFilePath, JSON.stringify(persistedRun, null, 2), \"utf-8\");\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\n // Wait for spawn confirmation before persisting PID\n // This prevents ghost runs where spawn fails silently\n const spawnResult = await spawnWithConfirmation(process.execPath, [workerPath, runId, repoSlug]);\n\n if (\"error\" in spawnResult) {\n // Mark run as failed if spawn failed\n try {\n const raw = await readFile(runFilePath, \"utf-8\");\n const run = JSON.parse(raw) as PersistedRun;\n run.status = \"failed\";\n run.updatedAt = new Date().toISOString();\n await writeFile(runFilePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch {\n // Best effort - run file update failed\n }\n\n printError(`Failed to spawn worker: ${spawnResult.error}`);\n process.exitCode = 1;\n return;\n }\n\n // Wait for worker to confirm startup by writing .started file\n // This catches early crashes between spawn() and actual worker initialization\n const startedPath = getWorkerStartedPath(repoSlug, runId);\n const workerStarted = await waitForWorkerStartup(startedPath, WORKER_STARTUP_TIMEOUT_MS);\n\n if (!workerStarted) {\n // Worker failed to start - mark run as failed\n try {\n const raw = await readFile(runFilePath, \"utf-8\");\n const run = JSON.parse(raw) as PersistedRun;\n run.status = \"failed\";\n run.updatedAt = new Date().toISOString();\n await writeFile(runFilePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch {\n // Best effort - run file update failed\n }\n\n printError(\n `Worker failed to start within ${WORKER_STARTUP_TIMEOUT_MS / 1000}s. The process may have crashed before initialization.`,\n );\n process.exitCode = 1;\n return;\n }\n\n // Write PID to persisted run AFTER spawn confirmation\n // This ensures PID in run.json corresponds to an actually running process\n try {\n const raw = await readFile(runFilePath, \"utf-8\");\n const run = JSON.parse(raw) as PersistedRun;\n run.pid = spawnResult.pid;\n await writeFile(runFilePath, JSON.stringify(run, null, 2), \"utf-8\");\n } catch (err) {\n // Non-critical — worker will write PID on startup anyway\n console.debug(\n `[run] Failed to update run file with PID: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (params.jsonOutput) {\n printJson({ runId, status: \"detached\", pid: spawnResult.pid });\n } else {\n printSuccess(`Detached run started: ${runId}`);\n console.log(` PID: ${String(spawnResult.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, { skipOrphanRecovery: true });\n orchestrator.registerAgent(agent);\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 agent: 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":[]}
|