@moreih29/nexus-core 0.13.0 → 0.14.1
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 +34 -0
- package/dist/assets/hooks/agent-bootstrap/handler.d.ts +4 -0
- package/dist/assets/hooks/agent-bootstrap/handler.d.ts.map +1 -0
- package/dist/assets/hooks/agent-bootstrap/handler.js +100 -0
- package/dist/assets/hooks/agent-bootstrap/handler.js.map +1 -0
- package/dist/assets/hooks/agent-finalize/handler.d.ts +4 -0
- package/dist/assets/hooks/agent-finalize/handler.d.ts.map +1 -0
- package/dist/assets/hooks/agent-finalize/handler.js +63 -0
- package/dist/assets/hooks/agent-finalize/handler.js.map +1 -0
- package/dist/assets/hooks/post-tool-telemetry/handler.d.ts +4 -0
- package/dist/assets/hooks/post-tool-telemetry/handler.d.ts.map +1 -0
- package/dist/assets/hooks/post-tool-telemetry/handler.js +40 -0
- package/dist/assets/hooks/post-tool-telemetry/handler.js.map +1 -0
- package/dist/assets/hooks/prompt-router/handler.d.ts +4 -0
- package/dist/assets/hooks/prompt-router/handler.d.ts.map +1 -0
- package/dist/assets/hooks/prompt-router/handler.js +204 -0
- package/dist/assets/hooks/prompt-router/handler.js.map +1 -0
- package/dist/assets/hooks/session-init/handler.d.ts +4 -0
- package/dist/assets/hooks/session-init/handler.d.ts.map +1 -0
- package/dist/assets/hooks/session-init/handler.js +23 -0
- package/dist/assets/hooks/session-init/handler.js.map +1 -0
- package/dist/hooks/agent-bootstrap.js +105 -0
- package/dist/hooks/agent-finalize.js +164 -0
- package/dist/hooks/post-tool-telemetry.js +55 -0
- package/dist/hooks/prompt-router.js +7300 -0
- package/dist/hooks/session-init.js +21 -0
- package/dist/manifests/claude-hooks.json +52 -0
- package/dist/manifests/codex-hooks.json +28 -0
- package/dist/manifests/opencode-manifest.json +44 -0
- package/dist/manifests/portability-report.json +87 -0
- package/dist/scripts/build-agents.d.ts +157 -0
- package/dist/scripts/build-agents.d.ts.map +1 -0
- package/dist/scripts/build-agents.js +738 -0
- package/dist/scripts/build-agents.js.map +1 -0
- package/dist/scripts/build-hooks.d.ts +16 -0
- package/dist/scripts/build-hooks.d.ts.map +1 -0
- package/dist/scripts/build-hooks.js +389 -0
- package/dist/scripts/build-hooks.js.map +1 -0
- package/dist/scripts/cli.d.ts +54 -0
- package/dist/scripts/cli.d.ts.map +1 -0
- package/dist/scripts/cli.js +482 -0
- package/dist/scripts/cli.js.map +1 -0
- package/dist/src/hooks/opencode-mount.d.ts.map +1 -0
- package/dist/{hooks → src/hooks}/opencode-mount.js +26 -6
- package/dist/src/hooks/opencode-mount.js.map +1 -0
- package/dist/src/hooks/runtime.d.ts.map +1 -0
- package/dist/src/hooks/runtime.js.map +1 -0
- package/dist/src/hooks/types.d.ts.map +1 -0
- package/dist/src/hooks/types.js.map +1 -0
- package/dist/src/lsp/cache.d.ts.map +1 -0
- package/dist/src/lsp/cache.js.map +1 -0
- package/dist/src/lsp/client.d.ts.map +1 -0
- package/dist/src/lsp/client.js.map +1 -0
- package/dist/src/lsp/detect.d.ts.map +1 -0
- package/dist/src/lsp/detect.js.map +1 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/mcp/tools/artifact.d.ts.map +1 -0
- package/dist/src/mcp/tools/artifact.js.map +1 -0
- package/dist/src/mcp/tools/history.d.ts.map +1 -0
- package/dist/src/mcp/tools/history.js.map +1 -0
- package/dist/src/mcp/tools/lsp.d.ts.map +1 -0
- package/dist/src/mcp/tools/lsp.js.map +1 -0
- package/dist/src/mcp/tools/plan.d.ts.map +1 -0
- package/dist/src/mcp/tools/plan.js.map +1 -0
- package/dist/src/mcp/tools/task.d.ts.map +1 -0
- package/dist/src/mcp/tools/task.js.map +1 -0
- package/dist/src/shared/invocations.d.ts.map +1 -0
- package/dist/src/shared/invocations.js.map +1 -0
- package/dist/src/shared/json-store.d.ts.map +1 -0
- package/dist/src/shared/json-store.js.map +1 -0
- package/dist/src/shared/mcp-utils.d.ts.map +1 -0
- package/dist/src/shared/mcp-utils.js.map +1 -0
- package/dist/src/shared/package-root.d.ts +6 -0
- package/dist/src/shared/package-root.d.ts.map +1 -0
- package/dist/src/shared/package-root.js +19 -0
- package/dist/src/shared/package-root.js.map +1 -0
- package/dist/src/shared/paths.d.ts.map +1 -0
- package/dist/src/shared/paths.js.map +1 -0
- package/dist/src/shared/tool-log.d.ts.map +1 -0
- package/dist/src/shared/tool-log.js.map +1 -0
- package/dist/src/types/state.d.ts.map +1 -0
- package/dist/src/types/state.js.map +1 -0
- package/docs/plugin-guide.md +36 -0
- package/package.json +25 -17
- package/dist/hooks/opencode-mount.d.ts.map +0 -1
- package/dist/hooks/opencode-mount.js.map +0 -1
- package/dist/hooks/runtime.d.ts.map +0 -1
- package/dist/hooks/runtime.js.map +0 -1
- package/dist/hooks/types.d.ts.map +0 -1
- package/dist/hooks/types.js.map +0 -1
- package/dist/lsp/cache.d.ts.map +0 -1
- package/dist/lsp/cache.js.map +0 -1
- package/dist/lsp/client.d.ts.map +0 -1
- package/dist/lsp/client.js.map +0 -1
- package/dist/lsp/detect.d.ts.map +0 -1
- package/dist/lsp/detect.js.map +0 -1
- package/dist/mcp/server.d.ts.map +0 -1
- package/dist/mcp/server.js.map +0 -1
- package/dist/mcp/tools/artifact.d.ts.map +0 -1
- package/dist/mcp/tools/artifact.js.map +0 -1
- package/dist/mcp/tools/history.d.ts.map +0 -1
- package/dist/mcp/tools/history.js.map +0 -1
- package/dist/mcp/tools/lsp.d.ts.map +0 -1
- package/dist/mcp/tools/lsp.js.map +0 -1
- package/dist/mcp/tools/plan.d.ts.map +0 -1
- package/dist/mcp/tools/plan.js.map +0 -1
- package/dist/mcp/tools/task.d.ts.map +0 -1
- package/dist/mcp/tools/task.js.map +0 -1
- package/dist/shared/invocations.d.ts.map +0 -1
- package/dist/shared/invocations.js.map +0 -1
- package/dist/shared/json-store.d.ts.map +0 -1
- package/dist/shared/json-store.js.map +0 -1
- package/dist/shared/mcp-utils.d.ts.map +0 -1
- package/dist/shared/mcp-utils.js.map +0 -1
- package/dist/shared/paths.d.ts.map +0 -1
- package/dist/shared/paths.js.map +0 -1
- package/dist/shared/tool-log.d.ts.map +0 -1
- package/dist/shared/tool-log.js.map +0 -1
- package/dist/types/state.d.ts.map +0 -1
- package/dist/types/state.js.map +0 -1
- package/scripts/build-agents.test.ts +0 -1279
- package/scripts/build-agents.ts +0 -978
- package/scripts/build-hooks.test.ts +0 -1385
- package/scripts/build-hooks.ts +0 -584
- package/scripts/cli.test.ts +0 -367
- package/scripts/cli.ts +0 -547
- /package/dist/{hooks → src/hooks}/opencode-mount.d.ts +0 -0
- /package/dist/{hooks → src/hooks}/runtime.d.ts +0 -0
- /package/dist/{hooks → src/hooks}/runtime.js +0 -0
- /package/dist/{hooks → src/hooks}/types.d.ts +0 -0
- /package/dist/{hooks → src/hooks}/types.js +0 -0
- /package/dist/{lsp → src/lsp}/cache.d.ts +0 -0
- /package/dist/{lsp → src/lsp}/cache.js +0 -0
- /package/dist/{lsp → src/lsp}/client.d.ts +0 -0
- /package/dist/{lsp → src/lsp}/client.js +0 -0
- /package/dist/{lsp → src/lsp}/detect.d.ts +0 -0
- /package/dist/{lsp → src/lsp}/detect.js +0 -0
- /package/dist/{mcp → src/mcp}/server.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/server.js +0 -0
- /package/dist/{mcp → src/mcp}/tools/artifact.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/tools/artifact.js +0 -0
- /package/dist/{mcp → src/mcp}/tools/history.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/tools/history.js +0 -0
- /package/dist/{mcp → src/mcp}/tools/lsp.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/tools/lsp.js +0 -0
- /package/dist/{mcp → src/mcp}/tools/plan.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/tools/plan.js +0 -0
- /package/dist/{mcp → src/mcp}/tools/task.d.ts +0 -0
- /package/dist/{mcp → src/mcp}/tools/task.js +0 -0
- /package/dist/{shared → src/shared}/invocations.d.ts +0 -0
- /package/dist/{shared → src/shared}/invocations.js +0 -0
- /package/dist/{shared → src/shared}/json-store.d.ts +0 -0
- /package/dist/{shared → src/shared}/json-store.js +0 -0
- /package/dist/{shared → src/shared}/mcp-utils.d.ts +0 -0
- /package/dist/{shared → src/shared}/mcp-utils.js +0 -0
- /package/dist/{shared → src/shared}/paths.d.ts +0 -0
- /package/dist/{shared → src/shared}/paths.js +0 -0
- /package/dist/{shared → src/shared}/tool-log.d.ts +0 -0
- /package/dist/{shared → src/shared}/tool-log.js +0 -0
- /package/dist/{types → src/types}/state.d.ts +0 -0
- /package/dist/{types → src/types}/state.js +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// assets/hooks/agent-bootstrap/handler.ts
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
var CORE_INDEX_SIZE_LIMIT = 2 * 1024;
|
|
5
|
+
function loadValidRoles(cwd) {
|
|
6
|
+
const agentsDir = join(cwd, "assets/agents");
|
|
7
|
+
const roles = [];
|
|
8
|
+
if (existsSync(agentsDir)) {
|
|
9
|
+
for (const entry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
10
|
+
if (entry.isDirectory())
|
|
11
|
+
roles.push(entry.name);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return roles;
|
|
15
|
+
}
|
|
16
|
+
function readFirstLine(path) {
|
|
17
|
+
try {
|
|
18
|
+
const content = readFileSync(path, "utf-8");
|
|
19
|
+
const firstNonEmpty = content.split(`
|
|
20
|
+
`).find((l) => l.trim().length > 0) ?? "";
|
|
21
|
+
return firstNonEmpty.replace(/^#+\s*/, "").slice(0, 80);
|
|
22
|
+
} catch {
|
|
23
|
+
return "";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function buildCoreIndex(cwd) {
|
|
27
|
+
const entries = [];
|
|
28
|
+
for (const sub of [".nexus/memory", ".nexus/context"]) {
|
|
29
|
+
const absDir = join(cwd, sub);
|
|
30
|
+
if (!existsSync(absDir))
|
|
31
|
+
continue;
|
|
32
|
+
for (const f of readdirSync(absDir, { withFileTypes: true })) {
|
|
33
|
+
if (!f.isFile() || !f.name.endsWith(".md"))
|
|
34
|
+
continue;
|
|
35
|
+
const full = join(absDir, f.name);
|
|
36
|
+
entries.push({
|
|
37
|
+
path: `${sub}/${f.name}`,
|
|
38
|
+
mtime: statSync(full).mtimeMs,
|
|
39
|
+
line: readFirstLine(full)
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
entries.sort((a, b) => b.mtime - a.mtime);
|
|
44
|
+
const lines = [];
|
|
45
|
+
let bytes = 0;
|
|
46
|
+
for (const e of entries) {
|
|
47
|
+
const formatted = `- ${e.path}: ${e.line}`;
|
|
48
|
+
if (bytes + formatted.length + 1 > CORE_INDEX_SIZE_LIMIT)
|
|
49
|
+
break;
|
|
50
|
+
lines.push(formatted);
|
|
51
|
+
bytes += formatted.length + 1;
|
|
52
|
+
}
|
|
53
|
+
return lines.length > 0 ? `Available memory/context:
|
|
54
|
+
` + lines.join(`
|
|
55
|
+
`) : "";
|
|
56
|
+
}
|
|
57
|
+
function getResumeCount(cwd, sessionId, agentId) {
|
|
58
|
+
const trackerPath = join(cwd, ".nexus/state", sessionId, "agent-tracker.json");
|
|
59
|
+
if (!existsSync(trackerPath))
|
|
60
|
+
return 0;
|
|
61
|
+
try {
|
|
62
|
+
const tracker = JSON.parse(readFileSync(trackerPath, "utf-8"));
|
|
63
|
+
const entry = Array.isArray(tracker) ? tracker.find((e) => e.agent_id === agentId) : null;
|
|
64
|
+
return entry?.resume_count ?? 0;
|
|
65
|
+
} catch {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
var handler = async (input) => {
|
|
70
|
+
if (input.hook_event_name !== "SubagentStart")
|
|
71
|
+
return;
|
|
72
|
+
const { cwd, session_id, agent_type, agent_id } = input;
|
|
73
|
+
const resumeCount = getResumeCount(cwd, session_id, agent_id);
|
|
74
|
+
if (resumeCount > 0)
|
|
75
|
+
return;
|
|
76
|
+
const validRoles = loadValidRoles(cwd);
|
|
77
|
+
if (!validRoles.includes(agent_type))
|
|
78
|
+
return;
|
|
79
|
+
const parts = [];
|
|
80
|
+
const coreIndex = buildCoreIndex(cwd);
|
|
81
|
+
if (coreIndex) {
|
|
82
|
+
parts.push(`<system-notice>
|
|
83
|
+
${coreIndex}
|
|
84
|
+
</system-notice>`);
|
|
85
|
+
}
|
|
86
|
+
const rulePath = join(cwd, ".nexus/rules", `${agent_type}.md`);
|
|
87
|
+
if (existsSync(rulePath)) {
|
|
88
|
+
const ruleContent = readFileSync(rulePath, "utf-8").trim();
|
|
89
|
+
if (ruleContent) {
|
|
90
|
+
parts.push(`<system-notice>
|
|
91
|
+
Custom rule for ${agent_type}:
|
|
92
|
+
${ruleContent}
|
|
93
|
+
</system-notice>`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (parts.length === 0)
|
|
97
|
+
return;
|
|
98
|
+
return { additional_context: parts.join(`
|
|
99
|
+
|
|
100
|
+
`) };
|
|
101
|
+
};
|
|
102
|
+
var handler_default = handler;
|
|
103
|
+
export {
|
|
104
|
+
handler_default as default
|
|
105
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// src/shared/json-store.js
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import { constants as fsConstants, appendFileSync, mkdirSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { randomUUID } from "node:crypto";
|
|
6
|
+
var inProcessQueues = new Map;
|
|
7
|
+
async function runWithInProcessLock(filePath, action) {
|
|
8
|
+
const previous = inProcessQueues.get(filePath) ?? Promise.resolve();
|
|
9
|
+
let release = () => {};
|
|
10
|
+
const gate = new Promise((resolve) => {
|
|
11
|
+
release = resolve;
|
|
12
|
+
});
|
|
13
|
+
const entry = previous.then(() => gate);
|
|
14
|
+
inProcessQueues.set(filePath, entry);
|
|
15
|
+
await previous;
|
|
16
|
+
try {
|
|
17
|
+
return await action();
|
|
18
|
+
} finally {
|
|
19
|
+
release();
|
|
20
|
+
entry.finally(() => {
|
|
21
|
+
if (inProcessQueues.get(filePath) === entry) {
|
|
22
|
+
inProcessQueues.delete(filePath);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
var LOCK_RETRY_INTERVAL_MS = 100;
|
|
28
|
+
var LOCK_MAX_RETRIES = 50;
|
|
29
|
+
var LOCK_STALE_MS = 30000;
|
|
30
|
+
function lockPath(filePath) {
|
|
31
|
+
return `${filePath}.lock`;
|
|
32
|
+
}
|
|
33
|
+
async function acquireFsLock(filePath) {
|
|
34
|
+
const lp = lockPath(filePath);
|
|
35
|
+
for (let attempt = 0;attempt <= LOCK_MAX_RETRIES; attempt++) {
|
|
36
|
+
try {
|
|
37
|
+
const fd = await fs.open(lp, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL);
|
|
38
|
+
await fd.close();
|
|
39
|
+
return;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
const e = err;
|
|
42
|
+
if (e.code !== "EEXIST")
|
|
43
|
+
throw err;
|
|
44
|
+
try {
|
|
45
|
+
const stat = await fs.stat(lp);
|
|
46
|
+
const ageMs = Date.now() - stat.mtimeMs;
|
|
47
|
+
if (ageMs > LOCK_STALE_MS) {
|
|
48
|
+
await fs.unlink(lp).catch(() => {
|
|
49
|
+
return;
|
|
50
|
+
});
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (attempt === LOCK_MAX_RETRIES) {
|
|
57
|
+
throw new Error(`Failed to acquire lock for "${filePath}" after ${LOCK_MAX_RETRIES} retries`);
|
|
58
|
+
}
|
|
59
|
+
await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_INTERVAL_MS));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function releaseFsLock(filePath) {
|
|
64
|
+
await fs.unlink(lockPath(filePath)).catch(() => {
|
|
65
|
+
return;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async function readJsonFile(filePath, defaultValue) {
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = await fs.readFile(filePath, "utf8");
|
|
72
|
+
} catch (err) {
|
|
73
|
+
const e = err;
|
|
74
|
+
if (e.code === "ENOENT")
|
|
75
|
+
return defaultValue;
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(raw);
|
|
80
|
+
} catch {
|
|
81
|
+
return defaultValue;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function writeJsonFile(filePath, data) {
|
|
85
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
86
|
+
const tmpPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${randomUUID()}`;
|
|
87
|
+
await fs.writeFile(tmpPath, JSON.stringify(data, null, 2) + `
|
|
88
|
+
`, "utf8");
|
|
89
|
+
await fs.rename(tmpPath, filePath);
|
|
90
|
+
}
|
|
91
|
+
async function updateJsonFileLocked(filePath, defaultValue, updater) {
|
|
92
|
+
return runWithInProcessLock(filePath, async () => {
|
|
93
|
+
await acquireFsLock(filePath);
|
|
94
|
+
try {
|
|
95
|
+
const current = await readJsonFile(filePath, defaultValue);
|
|
96
|
+
const next = await updater(current);
|
|
97
|
+
await writeJsonFile(filePath, next);
|
|
98
|
+
return next;
|
|
99
|
+
} finally {
|
|
100
|
+
await releaseFsLock(filePath);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
var APPEND_SIZE_WARN_THRESHOLD = 4 * 1024;
|
|
105
|
+
|
|
106
|
+
// assets/hooks/agent-finalize/handler.ts
|
|
107
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
108
|
+
import { join } from "node:path";
|
|
109
|
+
var handler = async (input) => {
|
|
110
|
+
if (input.hook_event_name !== "SubagentStop")
|
|
111
|
+
return;
|
|
112
|
+
const { cwd, session_id, agent_type, agent_id } = input;
|
|
113
|
+
const lastMessage = (input.last_assistant_message ?? "").slice(0, 500);
|
|
114
|
+
const sessionDir = join(cwd, ".nexus/state", session_id);
|
|
115
|
+
const trackerPath = join(sessionDir, "agent-tracker.json");
|
|
116
|
+
const toolLogPath = join(sessionDir, "tool-log.jsonl");
|
|
117
|
+
const tasksPath = join(sessionDir, "tasks.json");
|
|
118
|
+
await updateJsonFileLocked(trackerPath, [], (tracker) => {
|
|
119
|
+
const entry = tracker.find((e) => e["agent_id"] === agent_id);
|
|
120
|
+
if (!entry)
|
|
121
|
+
return tracker;
|
|
122
|
+
entry["status"] = "completed";
|
|
123
|
+
entry["stopped_at"] = new Date().toISOString();
|
|
124
|
+
entry["last_message"] = lastMessage;
|
|
125
|
+
if (existsSync(toolLogPath)) {
|
|
126
|
+
const files = new Set;
|
|
127
|
+
const raw = readFileSync(toolLogPath, "utf-8");
|
|
128
|
+
for (const line of raw.split(`
|
|
129
|
+
`)) {
|
|
130
|
+
if (!line.trim())
|
|
131
|
+
continue;
|
|
132
|
+
try {
|
|
133
|
+
const log = JSON.parse(line);
|
|
134
|
+
if (log["agent_id"] === agent_id && typeof log["file"] === "string") {
|
|
135
|
+
files.add(log["file"]);
|
|
136
|
+
}
|
|
137
|
+
} catch {}
|
|
138
|
+
}
|
|
139
|
+
entry["files_touched"] = [...files];
|
|
140
|
+
}
|
|
141
|
+
return tracker;
|
|
142
|
+
});
|
|
143
|
+
if (!existsSync(tasksPath))
|
|
144
|
+
return;
|
|
145
|
+
try {
|
|
146
|
+
const tasksData = JSON.parse(readFileSync(tasksPath, "utf-8"));
|
|
147
|
+
const tasks = Array.isArray(tasksData?.["tasks"]) ? tasksData["tasks"] : [];
|
|
148
|
+
const incomplete = tasks.filter((t) => t["owner"]?.["role"] === agent_type && t["status"] !== "completed");
|
|
149
|
+
if (incomplete.length === 0)
|
|
150
|
+
return;
|
|
151
|
+
const ids = incomplete.map((t) => t["id"]).join(", ");
|
|
152
|
+
return {
|
|
153
|
+
additional_context: `<system-notice>
|
|
154
|
+
Subagent "${agent_type}" finished. Tasks still pending with this role: ${ids}. Review status and coordinate remaining subagent delegation.
|
|
155
|
+
</system-notice>`
|
|
156
|
+
};
|
|
157
|
+
} catch {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var handler_default = handler;
|
|
162
|
+
export {
|
|
163
|
+
handler_default as default
|
|
164
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/shared/json-store.js
|
|
2
|
+
import { constants as fsConstants, appendFileSync, mkdirSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
var inProcessQueues = new Map;
|
|
5
|
+
var APPEND_SIZE_WARN_THRESHOLD = 4 * 1024;
|
|
6
|
+
function appendJsonLine(filePath, record) {
|
|
7
|
+
const line = JSON.stringify(record) + `
|
|
8
|
+
`;
|
|
9
|
+
if (line.length > APPEND_SIZE_WARN_THRESHOLD) {
|
|
10
|
+
console.error(`[json-store] appendJsonLine line exceeds ${APPEND_SIZE_WARN_THRESHOLD} bytes ` + `(${line.length}) — write may not be atomic on some filesystems. path=${filePath}`);
|
|
11
|
+
}
|
|
12
|
+
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
13
|
+
appendFileSync(filePath, line);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// assets/hooks/post-tool-telemetry/handler.ts
|
|
17
|
+
import { join, resolve, relative } from "node:path";
|
|
18
|
+
var EDIT_TOOLS = new Set(["Edit", "Write", "MultiEdit", "ApplyPatch", "NotebookEdit"]);
|
|
19
|
+
function isWithinMemory(filePath, projectRoot) {
|
|
20
|
+
const memRoot = resolve(projectRoot, ".nexus/memory");
|
|
21
|
+
const abs = resolve(filePath);
|
|
22
|
+
return abs.startsWith(memRoot + "/") || abs === memRoot;
|
|
23
|
+
}
|
|
24
|
+
var handler = async (input) => {
|
|
25
|
+
if (input.hook_event_name !== "PostToolUse")
|
|
26
|
+
return;
|
|
27
|
+
const { cwd, session_id, tool_name, agent_id } = input;
|
|
28
|
+
const toolInput = input.tool_input ?? {};
|
|
29
|
+
if (tool_name === "Read") {
|
|
30
|
+
const filePath = toolInput.file_path;
|
|
31
|
+
if (filePath && isWithinMemory(filePath, cwd)) {
|
|
32
|
+
appendJsonLine(join(cwd, ".nexus/memory-access.jsonl"), {
|
|
33
|
+
path: relative(cwd, resolve(filePath)),
|
|
34
|
+
accessed_at: new Date().toISOString(),
|
|
35
|
+
agent: agent_id ?? null
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (EDIT_TOOLS.has(tool_name) && agent_id) {
|
|
40
|
+
const filePath = toolInput.file_path ?? toolInput.notebook_path;
|
|
41
|
+
if (filePath) {
|
|
42
|
+
appendJsonLine(join(cwd, ".nexus/state", session_id, "tool-log.jsonl"), {
|
|
43
|
+
ts: new Date().toISOString(),
|
|
44
|
+
agent_id,
|
|
45
|
+
tool: tool_name,
|
|
46
|
+
file: relative(cwd, resolve(filePath)),
|
|
47
|
+
status: "ok"
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
var handler_default = handler;
|
|
53
|
+
export {
|
|
54
|
+
handler_default as default
|
|
55
|
+
};
|