@neotx/cli 0.1.0-alpha.22 → 0.1.0-alpha.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/{decision-PNZ2S2TU.js → decision-T2526ITK.js} +35 -2
- package/dist/decision-T2526ITK.js.map +1 -0
- 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/health-SWQ6V4H5.js +72 -0
- package/dist/health-SWQ6V4H5.js.map +1 -0
- package/dist/index.js +10 -6
- 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/decision-PNZ2S2TU.js.map +0 -1
- 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
|
@@ -1,14 +1,41 @@
|
|
|
1
1
|
import {
|
|
2
2
|
printError,
|
|
3
|
-
printSuccess
|
|
3
|
+
printSuccess,
|
|
4
|
+
printTable
|
|
4
5
|
} from "./chunk-YQIWMDXL.js";
|
|
5
6
|
|
|
6
7
|
// src/commands/log.ts
|
|
7
8
|
import { randomUUID } from "crypto";
|
|
8
9
|
import { appendFile } from "fs/promises";
|
|
9
10
|
import path from "path";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
appendLogBuffer,
|
|
13
|
+
getSupervisorDir,
|
|
14
|
+
MemoryStore,
|
|
15
|
+
readLogBuffer
|
|
16
|
+
} from "@neotx/core";
|
|
11
17
|
import { defineCommand } from "citty";
|
|
18
|
+
function truncate(text, max) {
|
|
19
|
+
return text.length > max ? `${text.slice(0, max - 1)}...` : text;
|
|
20
|
+
}
|
|
21
|
+
async function handleListRecent(name, limit = 20) {
|
|
22
|
+
const dir = getSupervisorDir(name);
|
|
23
|
+
const entries = await readLogBuffer(dir);
|
|
24
|
+
const recent = entries.slice(-limit).reverse();
|
|
25
|
+
if (recent.length === 0) {
|
|
26
|
+
console.log("No log entries found.");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
printTable(
|
|
30
|
+
["TIME", "TYPE", "AGENT", "MESSAGE"],
|
|
31
|
+
recent.map((e) => [
|
|
32
|
+
new Date(e.timestamp).toLocaleTimeString(),
|
|
33
|
+
e.type,
|
|
34
|
+
e.agent ?? "-",
|
|
35
|
+
truncate(e.message, 60)
|
|
36
|
+
])
|
|
37
|
+
);
|
|
38
|
+
}
|
|
12
39
|
var VALID_TYPES = [
|
|
13
40
|
"progress",
|
|
14
41
|
"action",
|
|
@@ -41,13 +68,13 @@ var log_default = defineCommand({
|
|
|
41
68
|
args: {
|
|
42
69
|
type: {
|
|
43
70
|
type: "positional",
|
|
44
|
-
description: "Report type: progress, action, decision, blocker, milestone, discovery",
|
|
45
|
-
required:
|
|
71
|
+
description: "Report type: progress, action, decision, blocker, milestone, discovery (or omit to list recent)",
|
|
72
|
+
required: false
|
|
46
73
|
},
|
|
47
74
|
message: {
|
|
48
75
|
type: "positional",
|
|
49
|
-
description: "Message to log",
|
|
50
|
-
required:
|
|
76
|
+
description: "Message to log (required when type is provided)",
|
|
77
|
+
required: false
|
|
51
78
|
},
|
|
52
79
|
name: {
|
|
53
80
|
type: "string",
|
|
@@ -68,25 +95,44 @@ var log_default = defineCommand({
|
|
|
68
95
|
type: "string",
|
|
69
96
|
description: "Repository path"
|
|
70
97
|
},
|
|
98
|
+
scope: {
|
|
99
|
+
type: "string",
|
|
100
|
+
description: "Repository scope for discovery entries (alias for --repo)"
|
|
101
|
+
},
|
|
71
102
|
procedure: {
|
|
72
103
|
type: "boolean",
|
|
73
104
|
description: "Also write as a procedure memory entry",
|
|
74
105
|
default: false
|
|
106
|
+
},
|
|
107
|
+
preview: {
|
|
108
|
+
type: "boolean",
|
|
109
|
+
description: "Preview the formatted inbox message before writing (for blocker type)",
|
|
110
|
+
default: false
|
|
75
111
|
}
|
|
76
112
|
},
|
|
113
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: CLI command handler with multiple type-specific branches; extracting would obscure flow
|
|
77
114
|
async run({ args }) {
|
|
78
115
|
const type = args.type;
|
|
116
|
+
if (!type) {
|
|
117
|
+
await handleListRecent(args.name);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
79
120
|
if (!VALID_TYPES.includes(type)) {
|
|
80
121
|
printError(`Invalid type "${type}". Must be one of: ${VALID_TYPES.join(", ")}`);
|
|
81
122
|
process.exitCode = 1;
|
|
82
123
|
return;
|
|
83
124
|
}
|
|
125
|
+
if (!args.message) {
|
|
126
|
+
printError(`Usage: neo log ${type} <message>`);
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
84
130
|
const dir = getSupervisorDir(args.name);
|
|
85
131
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
86
132
|
const id = randomUUID();
|
|
87
133
|
const agent = process.env.NEO_AGENT_NAME ?? void 0;
|
|
88
134
|
const runId = process.env.NEO_RUN_ID ?? void 0;
|
|
89
|
-
const repo = args.repo ?? process.env.NEO_REPOSITORY ?? void 0;
|
|
135
|
+
const repo = args.repo ?? args.scope ?? process.env.NEO_REPOSITORY ?? void 0;
|
|
90
136
|
let target = TARGET_MAP[type] ?? "digest";
|
|
91
137
|
if (args.memory) target = "memory";
|
|
92
138
|
if (args.knowledge) target = "knowledge";
|
|
@@ -112,7 +158,8 @@ var log_default = defineCommand({
|
|
|
112
158
|
try {
|
|
113
159
|
const store = new MemoryStore(path.join(dir, "memory.sqlite"));
|
|
114
160
|
await store.write({
|
|
115
|
-
type:
|
|
161
|
+
type: "knowledge",
|
|
162
|
+
subtype: args.procedure ? "procedure" : "fact",
|
|
116
163
|
scope: repo ?? "global",
|
|
117
164
|
content: args.message,
|
|
118
165
|
source: agent ?? "user",
|
|
@@ -129,6 +176,14 @@ var log_default = defineCommand({
|
|
|
129
176
|
text: `[BLOCKER]${agent ? ` (${agent})` : ""} ${args.message}`,
|
|
130
177
|
timestamp: now
|
|
131
178
|
};
|
|
179
|
+
if (args.preview) {
|
|
180
|
+
console.log("\nPreview of inbox message:");
|
|
181
|
+
console.log("\u2500".repeat(60));
|
|
182
|
+
console.log(JSON.stringify(inboxMessage, null, 2));
|
|
183
|
+
console.log("\u2500".repeat(60));
|
|
184
|
+
console.log("\nUse without --preview to write to inbox.");
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
132
187
|
await appendFile(`${dir}/inbox.jsonl`, `${JSON.stringify(inboxMessage)}
|
|
133
188
|
`, "utf-8");
|
|
134
189
|
}
|
|
@@ -138,4 +193,4 @@ var log_default = defineCommand({
|
|
|
138
193
|
export {
|
|
139
194
|
log_default as default
|
|
140
195
|
};
|
|
141
|
-
//# sourceMappingURL=log-
|
|
196
|
+
//# sourceMappingURL=log-ZLIAIBZQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/log.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { appendFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport {\n appendLogBuffer,\n getSupervisorDir,\n type LogBufferEntry,\n MemoryStore,\n readLogBuffer,\n} from \"@neotx/core\";\nimport { defineCommand } from \"citty\";\nimport { printError, printSuccess, printTable } from \"../output.js\";\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max - 1)}...` : text;\n}\n\nasync function handleListRecent(name: string, limit = 20): Promise<void> {\n const dir = getSupervisorDir(name);\n\n const entries = await readLogBuffer(dir);\n const recent = entries.slice(-limit).reverse();\n\n if (recent.length === 0) {\n console.log(\"No log entries found.\");\n return;\n }\n\n printTable(\n [\"TIME\", \"TYPE\", \"AGENT\", \"MESSAGE\"],\n recent.map((e: LogBufferEntry) => [\n new Date(e.timestamp).toLocaleTimeString(),\n e.type,\n e.agent ?? \"-\",\n truncate(e.message, 60),\n ]),\n );\n}\n\nconst VALID_TYPES = [\n \"progress\",\n \"action\",\n \"decision\",\n \"blocker\",\n \"milestone\",\n \"discovery\",\n] as const;\ntype LogType = (typeof VALID_TYPES)[number];\n\n// Map log types to activity.jsonl entry types (preserve existing behavior)\nconst TYPE_MAP: Record<string, string> = {\n decision: \"decision\",\n action: \"action\",\n blocker: \"error\",\n progress: \"event\",\n milestone: \"event\",\n discovery: \"event\",\n};\n\n// Implicit routing: which target each type gets by default\nconst TARGET_MAP: Record<string, \"memory\" | \"knowledge\" | \"digest\"> = {\n progress: \"digest\",\n action: \"digest\",\n decision: \"memory\",\n milestone: \"memory\",\n blocker: \"memory\",\n discovery: \"knowledge\",\n};\n\nexport default defineCommand({\n meta: {\n name: \"log\",\n description: \"Log a structured progress report to the supervisor activity log\",\n },\n args: {\n type: {\n type: \"positional\",\n description:\n \"Report type: progress, action, decision, blocker, milestone, discovery (or omit to list recent)\",\n required: false,\n },\n message: {\n type: \"positional\",\n description: \"Message to log (required when type is provided)\",\n required: false,\n },\n name: {\n type: \"string\",\n description: \"Supervisor instance name\",\n default: \"supervisor\",\n },\n memory: {\n type: \"boolean\",\n description: \"Override routing: send to memory target\",\n default: false,\n },\n knowledge: {\n type: \"boolean\",\n description: \"Override routing: send to knowledge target\",\n default: false,\n },\n repo: {\n type: \"string\",\n description: \"Repository path\",\n },\n scope: {\n type: \"string\",\n description: \"Repository scope for discovery entries (alias for --repo)\",\n },\n procedure: {\n type: \"boolean\",\n description: \"Also write as a procedure memory entry\",\n default: false,\n },\n preview: {\n type: \"boolean\",\n description: \"Preview the formatted inbox message before writing (for blocker type)\",\n default: false,\n },\n },\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: CLI command handler with multiple type-specific branches; extracting would obscure flow\n async run({ args }) {\n const type = args.type as string | undefined;\n\n // No type = list recent logs\n if (!type) {\n await handleListRecent(args.name);\n return;\n }\n\n if (!VALID_TYPES.includes(type as LogType)) {\n printError(`Invalid type \"${type}\". Must be one of: ${VALID_TYPES.join(\", \")}`);\n process.exitCode = 1;\n return;\n }\n\n if (!args.message) {\n printError(`Usage: neo log ${type} <message>`);\n process.exitCode = 1;\n return;\n }\n\n const dir = getSupervisorDir(args.name);\n const now = new Date().toISOString();\n const id = randomUUID();\n\n // Resolve agent/run from env vars or flags\n const agent = process.env.NEO_AGENT_NAME ?? undefined;\n const runId = process.env.NEO_RUN_ID ?? undefined;\n const repo =\n (args.repo as string | undefined) ??\n (args.scope as string | undefined) ??\n process.env.NEO_REPOSITORY ??\n undefined;\n\n // Resolve target with flag overrides\n let target: \"memory\" | \"knowledge\" | \"digest\" = TARGET_MAP[type] ?? \"digest\";\n if (args.memory) target = \"memory\";\n if (args.knowledge) target = \"knowledge\";\n\n // 1. Always: append to activity.jsonl (existing behavior)\n const activityEntry = {\n id,\n type: TYPE_MAP[type] ?? \"event\",\n summary: args.message,\n timestamp: now,\n };\n await appendFile(`${dir}/activity.jsonl`, `${JSON.stringify(activityEntry)}\\n`, \"utf-8\");\n\n // 2. Always: append to log-buffer.jsonl via shared helper\n await appendLogBuffer(dir, {\n id,\n type: type as \"progress\" | \"action\" | \"decision\" | \"blocker\" | \"milestone\" | \"discovery\",\n message: args.message,\n agent,\n runId,\n repo,\n target,\n timestamp: now,\n });\n\n // 3. Write to memory store for knowledge entries (facts or procedures)\n if (target === \"knowledge\" || args.procedure) {\n try {\n const store = new MemoryStore(path.join(dir, \"memory.sqlite\"));\n await store.write({\n type: \"knowledge\",\n subtype: args.procedure ? \"procedure\" : \"fact\",\n scope: repo ?? \"global\",\n content: args.message,\n source: agent ?? \"user\",\n runId,\n });\n store.close();\n } catch {\n // Best-effort — don't crash CLI if store write fails\n }\n }\n\n // 4. If blocker: also append to inbox.jsonl (wake up heartbeat)\n if (type === \"blocker\") {\n const inboxMessage = {\n id: randomUUID(),\n from: \"agent\" as const,\n text: `[BLOCKER]${agent ? ` (${agent})` : \"\"} ${args.message}`,\n timestamp: now,\n };\n\n if (args.preview) {\n console.log(\"\\nPreview of inbox message:\");\n console.log(\"─\".repeat(60));\n console.log(JSON.stringify(inboxMessage, null, 2));\n console.log(\"─\".repeat(60));\n console.log(\"\\nUse without --preview to write to inbox.\");\n return;\n }\n\n await appendFile(`${dir}/inbox.jsonl`, `${JSON.stringify(inboxMessage)}\\n`, \"utf-8\");\n }\n\n printSuccess(`Logged: [${type}] ${args.message.slice(0, 100)}`);\n },\n});\n"],"mappings":"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","names":[]}
|
|
@@ -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
|