@goondocks/myco 0.17.2 → 0.18.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 +14 -22
- package/bin/myco-run +15 -2
- package/dist/{agent-run-7AYHXIEF.js → agent-run-I4O2K2CK.js} +7 -7
- package/dist/{agent-tasks-UUIFKBD4.js → agent-tasks-UOW5BQIB.js} +7 -7
- package/dist/{chunk-XD3NEN3Q.js → chunk-2V7HR7HB.js} +2 -2
- package/dist/chunk-44PZCAYS.js +107 -0
- package/dist/chunk-44PZCAYS.js.map +1 -0
- package/dist/{chunk-DT42247G.js → chunk-75AZFBFW.js} +3 -3
- package/dist/{chunk-RMJPQZGF.js → chunk-C3EGL5JX.js} +755 -266
- package/dist/chunk-C3EGL5JX.js.map +1 -0
- package/dist/{chunk-7DAH5GLC.js → chunk-CKJAWZQE.js} +5 -1
- package/dist/chunk-CKJAWZQE.js.map +1 -0
- package/dist/{chunk-ML6GTPZU.js → chunk-CML4MCYF.js} +2 -2
- package/dist/{chunk-UTLWSKDV.js → chunk-CURS2TNP.js} +45 -4
- package/dist/chunk-CURS2TNP.js.map +1 -0
- package/dist/{chunk-EBIYONNZ.js → chunk-DPSLJ242.js} +34 -2
- package/dist/chunk-DPSLJ242.js.map +1 -0
- package/dist/{chunk-BZDZORVP.js → chunk-LSP5HYOO.js} +19 -16
- package/dist/chunk-LSP5HYOO.js.map +1 -0
- package/dist/{chunk-NUSTG3BH.js → chunk-N75GMQGA.js} +3 -3
- package/dist/{chunk-F6C4IC6R.js → chunk-NI23QCHB.js} +3 -3
- package/dist/{chunk-C3C5QVLK.js → chunk-O3TRN3RC.js} +2 -2
- package/dist/{chunk-3NCVCGUZ.js → chunk-RAV5YMRU.js} +3 -3
- package/dist/{chunk-25WHTV4N.js → chunk-RIDSOQDR.js} +21 -7
- package/dist/chunk-RIDSOQDR.js.map +1 -0
- package/dist/{chunk-HPZ7YAMA.js → chunk-TCSVDQF5.js} +1130 -195
- package/dist/chunk-TCSVDQF5.js.map +1 -0
- package/dist/{chunk-CTF7TQMJ.js → chunk-TLK46KKD.js} +14 -4
- package/dist/chunk-TLK46KKD.js.map +1 -0
- package/dist/{chunk-IGBHLFV5.js → chunk-TOER6RNC.js} +22 -2
- package/dist/chunk-TOER6RNC.js.map +1 -0
- package/dist/{chunk-ZSJPI5MS.js → chunk-TZAXQKO6.js} +6 -2
- package/dist/chunk-TZAXQKO6.js.map +1 -0
- package/dist/{chunk-RKPTMHED.js → chunk-U3J2DDSR.js} +2 -2
- package/dist/{chunk-SI5BBQAT.js → chunk-W7WENJ6F.js} +2 -2
- package/dist/{chunk-VVGZL2HX.js → chunk-WYOE4IAX.js} +153 -15
- package/dist/{chunk-VVGZL2HX.js.map → chunk-WYOE4IAX.js.map} +1 -1
- package/dist/{chunk-XZWFMMJR.js → chunk-XWOQL4XN.js} +3 -3
- package/dist/{chunk-5ZISXCDC.js → chunk-YZPI2Y3E.js} +39 -5
- package/dist/chunk-YZPI2Y3E.js.map +1 -0
- package/dist/{cli-WJVYP2QT.js → cli-D3TJYJ2U.js} +40 -40
- package/dist/{client-LZ3ZR4HC.js → client-4LLEXLVK.js} +4 -4
- package/dist/{config-ZQIMG3FB.js → config-DA4IUVFL.js} +3 -3
- package/dist/{detect-NJ2OREDP.js → detect-SZ2KDUF4.js} +2 -2
- package/dist/{detect-providers-C64L3QET.js → detect-providers-PSVKXTWE.js} +4 -4
- package/dist/{doctor-XEPBNHM3.js → doctor-KCTXPX5D.js} +12 -12
- package/dist/{executor-NXKJU5KW.js → executor-UYIZC3L5.js} +93 -285
- package/dist/executor-UYIZC3L5.js.map +1 -0
- package/dist/{init-BHVQAQ27.js → init-QFNBKKDC.js} +13 -13
- package/dist/{installer-45ZLP2RP.js → installer-BWJED3ED.js} +2 -2
- package/dist/{llm-KTD6SR55.js → llm-SMA5ZEAW.js} +4 -4
- package/dist/{loader-SHRKUKOS.js → loader-Q3P3R4UP.js} +3 -3
- package/dist/{loader-NEX3UF6U.js → loader-SKKUMT5C.js} +3 -3
- package/dist/{main-YFVBIRRK.js → main-5THODR77.js} +751 -257
- package/dist/main-5THODR77.js.map +1 -0
- package/dist/{open-2U7ZRGA3.js → open-7737CSPN.js} +7 -7
- package/dist/{post-compact-QIBMEWL3.js → post-compact-2TJ5FPZH.js} +7 -7
- package/dist/{post-tool-use-ICGFXDVY.js → post-tool-use-FRTSICC3.js} +6 -6
- package/dist/{post-tool-use-failure-C7TLH3XQ.js → post-tool-use-failure-KYO2NCNB.js} +7 -7
- package/dist/{pre-compact-IF7K4TQK.js → pre-compact-J6GCJEJR.js} +7 -7
- package/dist/{provider-check-LTLQ6BUZ.js → provider-check-AE3L5Z6R.js} +4 -4
- package/dist/{registry-TFQ22Z7N.js → registry-O2NZLO3V.js} +4 -4
- package/dist/{remove-FBGM2QVJ.js → remove-3WZZC7AX.js} +9 -9
- package/dist/{resolution-events-HGKIJOTA.js → resolution-events-XWYLLDRK.js} +4 -4
- package/dist/{restart-TQEECRNW.js → restart-HUHEFOXU.js} +8 -8
- package/dist/{search-NN5FC4Z6.js → search-ZGN3LDXG.js} +8 -8
- package/dist/{server-XMWJ4GF7.js → server-PTXLVVEE.js} +4 -4
- package/dist/{session-GLPAFYPO.js → session-7VV3IQMO.js} +9 -9
- package/dist/{session-end-TI3ILRBC.js → session-end-SMU55UCM.js} +6 -6
- package/dist/{session-start-PJLJDVJJ.js → session-start-NIMWEOIZ.js} +29 -13
- package/dist/session-start-NIMWEOIZ.js.map +1 -0
- package/dist/{setup-llm-AQSWLXCZ.js → setup-llm-7S3VPAPN.js} +8 -8
- package/dist/src/agent/definitions/tasks/extract-only.yaml +1 -1
- package/dist/src/agent/definitions/tasks/full-intelligence.yaml +10 -0
- package/dist/src/agent/definitions/tasks/skill-evolve.yaml +163 -49
- package/dist/src/agent/definitions/tasks/skill-generate.yaml +44 -27
- package/dist/src/agent/definitions/tasks/skill-survey.yaml +132 -138
- package/dist/src/agent/definitions/tasks/supersession-sweep.yaml +1 -1
- package/dist/src/cli.js +1 -1
- package/dist/src/daemon/main.js +1 -1
- package/dist/src/hooks/post-tool-use.js +1 -1
- package/dist/src/hooks/session-end.js +1 -1
- package/dist/src/hooks/session-start.js +1 -1
- package/dist/src/hooks/stop.js +1 -1
- package/dist/src/hooks/user-prompt-submit.js +1 -1
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/symbionts/manifests/codex.yaml +85 -0
- package/dist/src/symbionts/templates/claude-code/hooks.json +12 -12
- package/dist/src/symbionts/templates/claude-code/settings.json +3 -3
- package/dist/src/symbionts/templates/codex/hooks.json +4 -4
- package/dist/src/symbionts/templates/cursor/hooks.json +9 -9
- package/dist/src/symbionts/templates/cursor/settings.json +2 -2
- package/dist/src/symbionts/templates/gemini/hooks.json +6 -6
- package/dist/src/symbionts/templates/gemini/settings.json +2 -2
- package/dist/src/symbionts/templates/myco-run.cjs +44 -0
- package/dist/src/symbionts/templates/opencode/settings.json +2 -2
- package/dist/src/symbionts/templates/vscode-copilot/hooks.json +7 -7
- package/dist/src/symbionts/templates/vscode-copilot/settings.json +2 -2
- package/dist/src/symbionts/templates/windsurf/hooks.json +4 -4
- package/dist/src/symbionts/templates/windsurf/settings.json +2 -2
- package/dist/src/worker/package-lock.json +4338 -0
- package/dist/src/worker/package.json +5 -0
- package/dist/src/worker/src/index.ts +58 -65
- package/dist/src/worker/src/mcp/auth.ts +65 -0
- package/dist/src/worker/src/mcp/server.ts +53 -0
- package/dist/src/worker/src/mcp/tools/context.ts +13 -0
- package/dist/src/worker/src/mcp/tools/get.ts +15 -0
- package/dist/src/worker/src/mcp/tools/graph.ts +35 -0
- package/dist/src/worker/src/mcp/tools/search.ts +32 -0
- package/dist/src/worker/src/mcp/tools/sessions.ts +24 -0
- package/dist/src/worker/src/mcp/tools/skills.ts +16 -0
- package/dist/src/worker/src/mcp/tools/team.ts +9 -0
- package/dist/src/worker/src/schema.ts +5 -1
- package/dist/src/worker/src/search-helpers.ts +70 -0
- package/dist/src/worker/wrangler.toml +9 -0
- package/dist/{stats-BISBIBXZ.js → stats-GEOQ2DFF.js} +9 -9
- package/dist/{stop-47BJ42EO.js → stop-7AKYBJJ2.js} +6 -6
- package/dist/{stop-failure-VU5BTLWX.js → stop-failure-NLE2EURG.js} +7 -7
- package/dist/{subagent-start-SPTKQRHU.js → subagent-start-LBNZF2TG.js} +7 -7
- package/dist/{subagent-stop-UU75BYLC.js → subagent-stop-B2Z5GYAB.js} +7 -7
- package/dist/{task-completed-MVDO7TZF.js → task-completed-PO5TETJ7.js} +7 -7
- package/dist/{team-7X64J4Y6.js → team-DPNP2RN7.js} +97 -14
- package/dist/team-DPNP2RN7.js.map +1 -0
- package/dist/ui/assets/{index-rpmSpJpm.js → index-CiI1fwas.js} +120 -120
- package/dist/ui/index.html +1 -1
- package/dist/{update-DA7VEXOS.js → update-WBWB5URU.js} +18 -9
- package/dist/update-WBWB5URU.js.map +1 -0
- package/dist/{user-prompt-submit-ADZ4NTVO.js → user-prompt-submit-IZJC3NV7.js} +30 -7
- package/dist/user-prompt-submit-IZJC3NV7.js.map +1 -0
- package/dist/{verify-QYSERHF7.js → verify-FNSP62I3.js} +5 -5
- package/dist/{version-A72TAL2J.js → version-QEVU66NT.js} +2 -2
- package/package.json +7 -7
- package/dist/chunk-25WHTV4N.js.map +0 -1
- package/dist/chunk-5ZISXCDC.js.map +0 -1
- package/dist/chunk-7DAH5GLC.js.map +0 -1
- package/dist/chunk-BZDZORVP.js.map +0 -1
- package/dist/chunk-CTF7TQMJ.js.map +0 -1
- package/dist/chunk-EBIYONNZ.js.map +0 -1
- package/dist/chunk-HPZ7YAMA.js.map +0 -1
- package/dist/chunk-IGBHLFV5.js.map +0 -1
- package/dist/chunk-RMJPQZGF.js.map +0 -1
- package/dist/chunk-UTLWSKDV.js.map +0 -1
- package/dist/chunk-ZSJPI5MS.js.map +0 -1
- package/dist/executor-NXKJU5KW.js.map +0 -1
- package/dist/main-YFVBIRRK.js.map +0 -1
- package/dist/session-start-PJLJDVJJ.js.map +0 -1
- package/dist/src/symbionts/templates/hook-guard.cjs +0 -19
- package/dist/team-7X64J4Y6.js.map +0 -1
- package/dist/update-DA7VEXOS.js.map +0 -1
- package/dist/user-prompt-submit-ADZ4NTVO.js.map +0 -1
- /package/dist/{agent-run-7AYHXIEF.js.map → agent-run-I4O2K2CK.js.map} +0 -0
- /package/dist/{agent-tasks-UUIFKBD4.js.map → agent-tasks-UOW5BQIB.js.map} +0 -0
- /package/dist/{chunk-XD3NEN3Q.js.map → chunk-2V7HR7HB.js.map} +0 -0
- /package/dist/{chunk-DT42247G.js.map → chunk-75AZFBFW.js.map} +0 -0
- /package/dist/{chunk-ML6GTPZU.js.map → chunk-CML4MCYF.js.map} +0 -0
- /package/dist/{chunk-NUSTG3BH.js.map → chunk-N75GMQGA.js.map} +0 -0
- /package/dist/{chunk-F6C4IC6R.js.map → chunk-NI23QCHB.js.map} +0 -0
- /package/dist/{chunk-C3C5QVLK.js.map → chunk-O3TRN3RC.js.map} +0 -0
- /package/dist/{chunk-3NCVCGUZ.js.map → chunk-RAV5YMRU.js.map} +0 -0
- /package/dist/{chunk-RKPTMHED.js.map → chunk-U3J2DDSR.js.map} +0 -0
- /package/dist/{chunk-SI5BBQAT.js.map → chunk-W7WENJ6F.js.map} +0 -0
- /package/dist/{chunk-XZWFMMJR.js.map → chunk-XWOQL4XN.js.map} +0 -0
- /package/dist/{cli-WJVYP2QT.js.map → cli-D3TJYJ2U.js.map} +0 -0
- /package/dist/{client-LZ3ZR4HC.js.map → client-4LLEXLVK.js.map} +0 -0
- /package/dist/{config-ZQIMG3FB.js.map → config-DA4IUVFL.js.map} +0 -0
- /package/dist/{detect-NJ2OREDP.js.map → detect-SZ2KDUF4.js.map} +0 -0
- /package/dist/{detect-providers-C64L3QET.js.map → detect-providers-PSVKXTWE.js.map} +0 -0
- /package/dist/{doctor-XEPBNHM3.js.map → doctor-KCTXPX5D.js.map} +0 -0
- /package/dist/{init-BHVQAQ27.js.map → init-QFNBKKDC.js.map} +0 -0
- /package/dist/{installer-45ZLP2RP.js.map → installer-BWJED3ED.js.map} +0 -0
- /package/dist/{llm-KTD6SR55.js.map → llm-SMA5ZEAW.js.map} +0 -0
- /package/dist/{loader-NEX3UF6U.js.map → loader-Q3P3R4UP.js.map} +0 -0
- /package/dist/{loader-SHRKUKOS.js.map → loader-SKKUMT5C.js.map} +0 -0
- /package/dist/{open-2U7ZRGA3.js.map → open-7737CSPN.js.map} +0 -0
- /package/dist/{post-compact-QIBMEWL3.js.map → post-compact-2TJ5FPZH.js.map} +0 -0
- /package/dist/{post-tool-use-ICGFXDVY.js.map → post-tool-use-FRTSICC3.js.map} +0 -0
- /package/dist/{post-tool-use-failure-C7TLH3XQ.js.map → post-tool-use-failure-KYO2NCNB.js.map} +0 -0
- /package/dist/{pre-compact-IF7K4TQK.js.map → pre-compact-J6GCJEJR.js.map} +0 -0
- /package/dist/{provider-check-LTLQ6BUZ.js.map → provider-check-AE3L5Z6R.js.map} +0 -0
- /package/dist/{registry-TFQ22Z7N.js.map → registry-O2NZLO3V.js.map} +0 -0
- /package/dist/{remove-FBGM2QVJ.js.map → remove-3WZZC7AX.js.map} +0 -0
- /package/dist/{resolution-events-HGKIJOTA.js.map → resolution-events-XWYLLDRK.js.map} +0 -0
- /package/dist/{restart-TQEECRNW.js.map → restart-HUHEFOXU.js.map} +0 -0
- /package/dist/{search-NN5FC4Z6.js.map → search-ZGN3LDXG.js.map} +0 -0
- /package/dist/{server-XMWJ4GF7.js.map → server-PTXLVVEE.js.map} +0 -0
- /package/dist/{session-GLPAFYPO.js.map → session-7VV3IQMO.js.map} +0 -0
- /package/dist/{session-end-TI3ILRBC.js.map → session-end-SMU55UCM.js.map} +0 -0
- /package/dist/{setup-llm-AQSWLXCZ.js.map → setup-llm-7S3VPAPN.js.map} +0 -0
- /package/dist/{stats-BISBIBXZ.js.map → stats-GEOQ2DFF.js.map} +0 -0
- /package/dist/{stop-47BJ42EO.js.map → stop-7AKYBJJ2.js.map} +0 -0
- /package/dist/{stop-failure-VU5BTLWX.js.map → stop-failure-NLE2EURG.js.map} +0 -0
- /package/dist/{subagent-start-SPTKQRHU.js.map → subagent-start-LBNZF2TG.js.map} +0 -0
- /package/dist/{subagent-stop-UU75BYLC.js.map → subagent-stop-B2Z5GYAB.js.map} +0 -0
- /package/dist/{task-completed-MVDO7TZF.js.map → task-completed-PO5TETJ7.js.map} +0 -0
- /package/dist/{verify-QYSERHF7.js.map → verify-FNSP62I3.js.map} +0 -0
- /package/dist/{version-A72TAL2J.js.map → version-QEVU66NT.js.map} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __cr } from 'node:module'; const require = __cr(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
loadAllTasks
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RAV5YMRU.js";
|
|
5
5
|
import {
|
|
6
6
|
getAgent,
|
|
7
7
|
getDefaultTask,
|
|
@@ -9,21 +9,23 @@ import {
|
|
|
9
9
|
loadAgentDefinition,
|
|
10
10
|
resolveDefinitionsDir,
|
|
11
11
|
resolveEffectiveConfig
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NI23QCHB.js";
|
|
13
13
|
import {
|
|
14
14
|
getSpore,
|
|
15
|
-
listSporeIdsSince
|
|
16
|
-
|
|
15
|
+
listSporeIdsSince,
|
|
16
|
+
listSpores
|
|
17
|
+
} from "./chunk-TZAXQKO6.js";
|
|
17
18
|
import {
|
|
18
|
-
getSession
|
|
19
|
-
|
|
19
|
+
getSession,
|
|
20
|
+
listSessions
|
|
21
|
+
} from "./chunk-RIDSOQDR.js";
|
|
20
22
|
import {
|
|
21
23
|
getTeamMachineId,
|
|
22
24
|
syncRow
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-O3TRN3RC.js";
|
|
24
26
|
import {
|
|
25
27
|
loadConfig
|
|
26
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-2V7HR7HB.js";
|
|
27
29
|
import {
|
|
28
30
|
getDatabase
|
|
29
31
|
} from "./chunk-MYX5NCRH.js";
|
|
@@ -37,7 +39,126 @@ import {
|
|
|
37
39
|
GRAPH_EDGE_DEFAULT_CONFIDENCE,
|
|
38
40
|
QUERY_DEFAULT_LIST_LIMIT,
|
|
39
41
|
epochSeconds
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-CKJAWZQE.js";
|
|
43
|
+
|
|
44
|
+
// src/notifications/notify.ts
|
|
45
|
+
import crypto from "crypto";
|
|
46
|
+
|
|
47
|
+
// src/db/queries/notifications.ts
|
|
48
|
+
var DEFAULT_LIMIT = 50;
|
|
49
|
+
var NOTIFICATION_PRUNE_AGE_SECONDS = 30 * 24 * 60 * 60;
|
|
50
|
+
function insertNotification(n) {
|
|
51
|
+
const db = getDatabase();
|
|
52
|
+
db.prepare(
|
|
53
|
+
`INSERT INTO notifications (id, domain, type, level, title, message, mode, status, link, metadata, created_at)
|
|
54
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, 'unread', ?, ?, ?)`
|
|
55
|
+
).run(n.id, n.domain, n.type, n.level, n.title, n.message, n.mode, n.link, n.metadata, epochSeconds());
|
|
56
|
+
}
|
|
57
|
+
function listNotifications(opts = {}) {
|
|
58
|
+
const db = getDatabase();
|
|
59
|
+
const conditions = [];
|
|
60
|
+
const params = [];
|
|
61
|
+
if (opts.status) {
|
|
62
|
+
conditions.push("status = ?");
|
|
63
|
+
params.push(opts.status);
|
|
64
|
+
}
|
|
65
|
+
if (opts.domain) {
|
|
66
|
+
conditions.push("domain = ?");
|
|
67
|
+
params.push(opts.domain);
|
|
68
|
+
}
|
|
69
|
+
if (opts.mode) {
|
|
70
|
+
conditions.push("mode = ?");
|
|
71
|
+
params.push(opts.mode);
|
|
72
|
+
}
|
|
73
|
+
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
74
|
+
const limit = opts.limit ?? DEFAULT_LIMIT;
|
|
75
|
+
const offset = opts.offset ?? 0;
|
|
76
|
+
return db.prepare(
|
|
77
|
+
`SELECT * FROM notifications ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`
|
|
78
|
+
).all(...params, limit, offset);
|
|
79
|
+
}
|
|
80
|
+
function countNotifications(status) {
|
|
81
|
+
const db = getDatabase();
|
|
82
|
+
if (status) {
|
|
83
|
+
const row2 = db.prepare("SELECT COUNT(*) as count FROM notifications WHERE status = ?").get(status);
|
|
84
|
+
return row2.count;
|
|
85
|
+
}
|
|
86
|
+
const row = db.prepare("SELECT COUNT(*) as count FROM notifications").get();
|
|
87
|
+
return row.count;
|
|
88
|
+
}
|
|
89
|
+
function getNotification(id) {
|
|
90
|
+
const db = getDatabase();
|
|
91
|
+
return db.prepare("SELECT * FROM notifications WHERE id = ?").get(id);
|
|
92
|
+
}
|
|
93
|
+
function updateNotificationStatus(id, status) {
|
|
94
|
+
const db = getDatabase();
|
|
95
|
+
const result = db.prepare("UPDATE notifications SET status = ? WHERE id = ?").run(status, id);
|
|
96
|
+
return result.changes > 0;
|
|
97
|
+
}
|
|
98
|
+
function dismissAllNotifications(domain) {
|
|
99
|
+
const db = getDatabase();
|
|
100
|
+
if (domain) {
|
|
101
|
+
const result2 = db.prepare("UPDATE notifications SET status = 'dismissed' WHERE domain = ? AND status != 'dismissed'").run(domain);
|
|
102
|
+
return result2.changes;
|
|
103
|
+
}
|
|
104
|
+
const result = db.prepare("UPDATE notifications SET status = 'dismissed' WHERE status != 'dismissed'").run();
|
|
105
|
+
return result.changes;
|
|
106
|
+
}
|
|
107
|
+
function markAllRead(domain) {
|
|
108
|
+
const db = getDatabase();
|
|
109
|
+
if (domain) {
|
|
110
|
+
const result2 = db.prepare("UPDATE notifications SET status = 'read' WHERE domain = ? AND status = 'unread'").run(domain);
|
|
111
|
+
return result2.changes;
|
|
112
|
+
}
|
|
113
|
+
const result = db.prepare("UPDATE notifications SET status = 'read' WHERE status = 'unread'").run();
|
|
114
|
+
return result.changes;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/notifications/registry.ts
|
|
118
|
+
var domains = /* @__PURE__ */ new Map();
|
|
119
|
+
function register(descriptor) {
|
|
120
|
+
domains.set(descriptor.domain, descriptor);
|
|
121
|
+
}
|
|
122
|
+
function getAllDomains() {
|
|
123
|
+
return [...domains.values()].sort((a, b) => a.domain.localeCompare(b.domain));
|
|
124
|
+
}
|
|
125
|
+
function getType(typeId) {
|
|
126
|
+
for (const descriptor of domains.values()) {
|
|
127
|
+
const match = descriptor.types.find((t) => t.id === typeId);
|
|
128
|
+
if (match) return { domain: descriptor, type: match };
|
|
129
|
+
}
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// src/notifications/notify.ts
|
|
134
|
+
function notify(vaultDir, payload, config) {
|
|
135
|
+
if (!vaultDir) return null;
|
|
136
|
+
try {
|
|
137
|
+
const cfg = config ?? loadConfig(vaultDir);
|
|
138
|
+
if (!cfg.notifications.enabled) return null;
|
|
139
|
+
const domainConfig = cfg.notifications.domains[payload.domain];
|
|
140
|
+
if (domainConfig && !domainConfig.enabled) return null;
|
|
141
|
+
const registeredType = getType(payload.type);
|
|
142
|
+
const mode = payload.mode ?? domainConfig?.mode ?? registeredType?.type.defaultMode ?? cfg.notifications.default_mode;
|
|
143
|
+
const level = payload.level ?? registeredType?.type.defaultLevel ?? "info";
|
|
144
|
+
const id = crypto.randomUUID();
|
|
145
|
+
insertNotification({
|
|
146
|
+
id,
|
|
147
|
+
domain: payload.domain,
|
|
148
|
+
type: payload.type,
|
|
149
|
+
level,
|
|
150
|
+
title: payload.title,
|
|
151
|
+
message: payload.message ?? null,
|
|
152
|
+
mode,
|
|
153
|
+
link: payload.link ?? null,
|
|
154
|
+
metadata: payload.metadata ? JSON.stringify(payload.metadata) : null
|
|
155
|
+
});
|
|
156
|
+
return id;
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.warn("[notify] Failed to emit notification:", err instanceof Error ? err.message : err);
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
41
162
|
|
|
42
163
|
// src/utils/error-message.ts
|
|
43
164
|
function errorMessage(err) {
|
|
@@ -50,6 +171,10 @@ function errorMessage(err) {
|
|
|
50
171
|
}
|
|
51
172
|
}
|
|
52
173
|
|
|
174
|
+
// src/agent/instruction-builders.ts
|
|
175
|
+
import { readFileSync } from "fs";
|
|
176
|
+
import { resolve } from "path";
|
|
177
|
+
|
|
53
178
|
// src/db/queries/skill-candidates.ts
|
|
54
179
|
var DEFAULT_CONFIDENCE = 0;
|
|
55
180
|
var DEFAULT_STATUS = "identified";
|
|
@@ -63,6 +188,7 @@ var CANDIDATE_COLUMNS = [
|
|
|
63
188
|
"status",
|
|
64
189
|
"source_ids",
|
|
65
190
|
"skill_id",
|
|
191
|
+
"supersedes",
|
|
66
192
|
"approved_at",
|
|
67
193
|
"created_at",
|
|
68
194
|
"updated_at",
|
|
@@ -80,6 +206,7 @@ function toCandidateRow(row) {
|
|
|
80
206
|
status: row.status,
|
|
81
207
|
source_ids: row.source_ids ?? "[]",
|
|
82
208
|
skill_id: row.skill_id ?? null,
|
|
209
|
+
supersedes: row.supersedes ?? null,
|
|
83
210
|
approved_at: row.approved_at ?? null,
|
|
84
211
|
created_at: row.created_at,
|
|
85
212
|
updated_at: row.updated_at,
|
|
@@ -111,11 +238,11 @@ function insertCandidate(data) {
|
|
|
111
238
|
db.prepare(
|
|
112
239
|
`INSERT INTO skill_candidates (
|
|
113
240
|
id, agent_id, machine_id, topic, rationale,
|
|
114
|
-
confidence, status, source_ids, skill_id, approved_at,
|
|
241
|
+
confidence, status, source_ids, skill_id, supersedes, approved_at,
|
|
115
242
|
created_at, updated_at
|
|
116
243
|
) VALUES (
|
|
117
244
|
?, ?, ?, ?, ?,
|
|
118
|
-
?, ?, ?, ?, ?,
|
|
245
|
+
?, ?, ?, ?, ?, ?,
|
|
119
246
|
?, ?
|
|
120
247
|
)`
|
|
121
248
|
).run(
|
|
@@ -128,6 +255,7 @@ function insertCandidate(data) {
|
|
|
128
255
|
data.status ?? DEFAULT_STATUS,
|
|
129
256
|
data.source_ids ?? "[]",
|
|
130
257
|
data.skill_id ?? null,
|
|
258
|
+
data.supersedes ?? null,
|
|
131
259
|
data.approved_at ?? null,
|
|
132
260
|
data.created_at,
|
|
133
261
|
data.updated_at
|
|
@@ -177,6 +305,7 @@ function updateCandidate(id, updates) {
|
|
|
177
305
|
status: "status",
|
|
178
306
|
source_ids: "source_ids",
|
|
179
307
|
skill_id: "skill_id",
|
|
308
|
+
supersedes: "supersedes",
|
|
180
309
|
approved_at: "approved_at",
|
|
181
310
|
updated_at: "updated_at"
|
|
182
311
|
};
|
|
@@ -437,69 +566,357 @@ function deleteSkillRecordCascade(idOrName) {
|
|
|
437
566
|
return { id: record.id, name: record.name };
|
|
438
567
|
}
|
|
439
568
|
|
|
440
|
-
// src/db/queries/
|
|
441
|
-
var
|
|
569
|
+
// src/db/queries/digest-extracts.ts
|
|
570
|
+
var EXTRACT_COLUMNS = [
|
|
442
571
|
"id",
|
|
443
|
-
"
|
|
444
|
-
"
|
|
445
|
-
"
|
|
446
|
-
"
|
|
447
|
-
"
|
|
448
|
-
"
|
|
449
|
-
"
|
|
572
|
+
"agent_id",
|
|
573
|
+
"tier",
|
|
574
|
+
"content",
|
|
575
|
+
"substrate_hash",
|
|
576
|
+
"generated_at",
|
|
577
|
+
"machine_id",
|
|
578
|
+
"synced_at"
|
|
450
579
|
];
|
|
451
|
-
var SELECT_COLUMNS3 =
|
|
452
|
-
function
|
|
580
|
+
var SELECT_COLUMNS3 = EXTRACT_COLUMNS.join(", ");
|
|
581
|
+
function toDigestExtractRow(row) {
|
|
453
582
|
return {
|
|
454
583
|
id: row.id,
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
584
|
+
agent_id: row.agent_id,
|
|
585
|
+
tier: row.tier,
|
|
586
|
+
content: row.content,
|
|
587
|
+
substrate_hash: row.substrate_hash ?? null,
|
|
588
|
+
generated_at: row.generated_at,
|
|
589
|
+
machine_id: row.machine_id ?? "local",
|
|
590
|
+
synced_at: row.synced_at ?? null
|
|
462
591
|
};
|
|
463
592
|
}
|
|
464
|
-
function
|
|
593
|
+
function upsertDigestExtract(data) {
|
|
465
594
|
const db = getDatabase();
|
|
466
595
|
db.prepare(
|
|
467
|
-
`INSERT INTO
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
data.generation,
|
|
478
|
-
data.action,
|
|
479
|
-
data.rationale,
|
|
480
|
-
data.source_ids_added ?? "[]",
|
|
481
|
-
data.content_snapshot,
|
|
482
|
-
data.created_at
|
|
483
|
-
);
|
|
484
|
-
return toLineageRow(
|
|
485
|
-
db.prepare(`SELECT ${SELECT_COLUMNS3} FROM skill_lineage WHERE id = ?`).get(data.id)
|
|
486
|
-
);
|
|
596
|
+
`INSERT INTO digest_extracts (agent_id, tier, content, generated_at)
|
|
597
|
+
VALUES (?, ?, ?, ?)
|
|
598
|
+
ON CONFLICT (agent_id, tier) DO UPDATE SET
|
|
599
|
+
content = EXCLUDED.content,
|
|
600
|
+
generated_at = EXCLUDED.generated_at`
|
|
601
|
+
).run(data.agent_id, data.tier, data.content, data.generated_at);
|
|
602
|
+
const row = db.prepare(
|
|
603
|
+
`SELECT ${SELECT_COLUMNS3} FROM digest_extracts WHERE agent_id = ? AND tier = ?`
|
|
604
|
+
).get(data.agent_id, data.tier);
|
|
605
|
+
return toDigestExtractRow(row);
|
|
487
606
|
}
|
|
488
|
-
function
|
|
607
|
+
function getDigestExtract(agentId, tier) {
|
|
608
|
+
const db = getDatabase();
|
|
609
|
+
const row = db.prepare(
|
|
610
|
+
`SELECT ${SELECT_COLUMNS3} FROM digest_extracts
|
|
611
|
+
WHERE agent_id = ? AND tier = ?`
|
|
612
|
+
).get(agentId, tier);
|
|
613
|
+
if (!row) return null;
|
|
614
|
+
return toDigestExtractRow(row);
|
|
615
|
+
}
|
|
616
|
+
function listDigestExtracts(agentId) {
|
|
489
617
|
const db = getDatabase();
|
|
618
|
+
const tierPlaceholders = DIGEST_TIERS.map(() => "?").join(", ");
|
|
490
619
|
const rows = db.prepare(
|
|
491
620
|
`SELECT ${SELECT_COLUMNS3}
|
|
492
|
-
FROM
|
|
493
|
-
WHERE
|
|
494
|
-
ORDER BY
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
621
|
+
FROM digest_extracts
|
|
622
|
+
WHERE agent_id = ? AND tier IN (${tierPlaceholders})
|
|
623
|
+
ORDER BY tier ASC`
|
|
624
|
+
).all(agentId, ...DIGEST_TIERS);
|
|
625
|
+
return rows.map(toDigestExtractRow);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// src/db/queries/agent-state.ts
|
|
629
|
+
var STATE_COLUMNS = [
|
|
630
|
+
"agent_id",
|
|
631
|
+
"key",
|
|
632
|
+
"value",
|
|
633
|
+
"updated_at"
|
|
634
|
+
];
|
|
635
|
+
var SELECT_COLUMNS4 = STATE_COLUMNS.join(", ");
|
|
636
|
+
function toAgentStateRow(row) {
|
|
637
|
+
return {
|
|
638
|
+
agent_id: row.agent_id,
|
|
639
|
+
key: row.key,
|
|
640
|
+
value: row.value,
|
|
641
|
+
updated_at: row.updated_at
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function getState(agentId, key) {
|
|
645
|
+
const db = getDatabase();
|
|
646
|
+
const row = db.prepare(
|
|
647
|
+
`SELECT ${SELECT_COLUMNS4} FROM agent_state WHERE agent_id = ? AND key = ?`
|
|
648
|
+
).get(agentId, key);
|
|
649
|
+
if (!row) return null;
|
|
650
|
+
return toAgentStateRow(row);
|
|
651
|
+
}
|
|
652
|
+
function setState(agentId, key, value, updatedAt) {
|
|
653
|
+
const db = getDatabase();
|
|
654
|
+
db.prepare(
|
|
655
|
+
`INSERT INTO agent_state (agent_id, key, value, updated_at)
|
|
656
|
+
VALUES (?, ?, ?, ?)
|
|
657
|
+
ON CONFLICT (agent_id, key) DO UPDATE SET
|
|
658
|
+
value = EXCLUDED.value,
|
|
659
|
+
updated_at = EXCLUDED.updated_at`
|
|
660
|
+
).run(agentId, key, value, updatedAt);
|
|
661
|
+
return toAgentStateRow(
|
|
662
|
+
db.prepare(`SELECT ${SELECT_COLUMNS4} FROM agent_state WHERE agent_id = ? AND key = ?`).get(agentId, key)
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
function getStatesForAgent(agentId) {
|
|
666
|
+
const db = getDatabase();
|
|
667
|
+
const rows = db.prepare(
|
|
668
|
+
`SELECT ${SELECT_COLUMNS4}
|
|
669
|
+
FROM agent_state
|
|
670
|
+
WHERE agent_id = ?
|
|
671
|
+
ORDER BY key ASC`
|
|
672
|
+
).all(agentId);
|
|
673
|
+
return rows.map(toAgentStateRow);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/agent/tools/skill-validator.ts
|
|
677
|
+
var MAX_SKILL_LINES = 800;
|
|
678
|
+
var REQUIRED_FRONTMATTER_FIELDS = ["name", "description", "managed_by", "user-invocable", "allowed-tools"];
|
|
679
|
+
var PROTECTED_FRONTMATTER_FIELDS = ["user-invocable", "allowed-tools"];
|
|
680
|
+
var ALLOWED_CLAUDE_CODE_TOOLS = /* @__PURE__ */ new Set([
|
|
681
|
+
"Read",
|
|
682
|
+
"Edit",
|
|
683
|
+
"Write",
|
|
684
|
+
"MultiEdit",
|
|
685
|
+
"Bash",
|
|
686
|
+
"Grep",
|
|
687
|
+
"Glob",
|
|
688
|
+
"NotebookRead",
|
|
689
|
+
"NotebookEdit",
|
|
690
|
+
"WebFetch",
|
|
691
|
+
"WebSearch",
|
|
692
|
+
"Task",
|
|
693
|
+
"TodoWrite"
|
|
694
|
+
]);
|
|
695
|
+
function extractFrontmatterField(content, field) {
|
|
696
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
697
|
+
if (!fmMatch) return void 0;
|
|
698
|
+
const fm = fmMatch[1];
|
|
699
|
+
const match = fm.match(new RegExp(`^${field}:\\s*(.+)$`, "m"));
|
|
700
|
+
if (match) return match[1].trim();
|
|
701
|
+
const blockMatch = fm.match(new RegExp(`^${field}:\\s*$`, "m"));
|
|
702
|
+
if (blockMatch) {
|
|
703
|
+
const startIdx = fm.indexOf(blockMatch[0]) + blockMatch[0].length;
|
|
704
|
+
const remaining = fm.slice(startIdx);
|
|
705
|
+
const items = [];
|
|
706
|
+
for (const line of remaining.split("\n")) {
|
|
707
|
+
const itemMatch = line.match(/^\s+-\s+(.+)$/);
|
|
708
|
+
if (!itemMatch) break;
|
|
709
|
+
items.push(itemMatch[1].trim());
|
|
710
|
+
}
|
|
711
|
+
if (items.length > 0) return items.join(", ");
|
|
712
|
+
}
|
|
713
|
+
return void 0;
|
|
714
|
+
}
|
|
715
|
+
function parseAllowedTools(rawValue) {
|
|
716
|
+
if (!rawValue) return null;
|
|
717
|
+
let stripped = rawValue.trim();
|
|
718
|
+
if (stripped.length === 0) return null;
|
|
719
|
+
if (stripped.startsWith("[") && stripped.endsWith("]")) {
|
|
720
|
+
stripped = stripped.slice(1, -1).trim();
|
|
721
|
+
}
|
|
722
|
+
if (stripped.length === 0) return null;
|
|
723
|
+
const parts = stripped.split(",").map((s) => s.trim().replace(/^['"]|['"]$/g, "")).filter((s) => s.length > 0);
|
|
724
|
+
if (parts.length === 0) return null;
|
|
725
|
+
const sentinels = /* @__PURE__ */ new Set(["None", "none", "null", "Null", "~"]);
|
|
726
|
+
if (parts.some((p) => sentinels.has(p))) return null;
|
|
727
|
+
return parts;
|
|
728
|
+
}
|
|
729
|
+
function stemToken(word) {
|
|
730
|
+
let w = word;
|
|
731
|
+
if (w.length > 5 && w.endsWith("ing")) w = w.slice(0, -3);
|
|
732
|
+
else if (w.length > 5 && w.endsWith("ed")) w = w.slice(0, -2);
|
|
733
|
+
if (w.length > 4 && w.endsWith("s")) w = w.slice(0, -1);
|
|
734
|
+
if (w.length > 4 && w.endsWith("e")) w = w.slice(0, -1);
|
|
735
|
+
return w;
|
|
736
|
+
}
|
|
737
|
+
var STOPWORDS = /* @__PURE__ */ new Set([
|
|
738
|
+
"the",
|
|
739
|
+
"a",
|
|
740
|
+
"an",
|
|
741
|
+
"and",
|
|
742
|
+
"or",
|
|
743
|
+
"but",
|
|
744
|
+
"is",
|
|
745
|
+
"are",
|
|
746
|
+
"was",
|
|
747
|
+
"were",
|
|
748
|
+
"be",
|
|
749
|
+
"been",
|
|
750
|
+
"being",
|
|
751
|
+
"have",
|
|
752
|
+
"has",
|
|
753
|
+
"had",
|
|
754
|
+
"do",
|
|
755
|
+
"does",
|
|
756
|
+
"did",
|
|
757
|
+
"will",
|
|
758
|
+
"would",
|
|
759
|
+
"should",
|
|
760
|
+
"could",
|
|
761
|
+
"may",
|
|
762
|
+
"might",
|
|
763
|
+
"must",
|
|
764
|
+
"can",
|
|
765
|
+
"this",
|
|
766
|
+
"that",
|
|
767
|
+
"these",
|
|
768
|
+
"those",
|
|
769
|
+
"with",
|
|
770
|
+
"from",
|
|
771
|
+
"into",
|
|
772
|
+
"onto",
|
|
773
|
+
"for",
|
|
774
|
+
"when",
|
|
775
|
+
"where",
|
|
776
|
+
"which",
|
|
777
|
+
"what",
|
|
778
|
+
"who",
|
|
779
|
+
"how",
|
|
780
|
+
"why",
|
|
781
|
+
"use",
|
|
782
|
+
"uses",
|
|
783
|
+
"used",
|
|
784
|
+
"using",
|
|
785
|
+
"not",
|
|
786
|
+
"also",
|
|
787
|
+
"than",
|
|
788
|
+
"then",
|
|
789
|
+
"ensure",
|
|
790
|
+
"ensures",
|
|
791
|
+
"make",
|
|
792
|
+
"makes"
|
|
793
|
+
]);
|
|
794
|
+
function tokenSet(text) {
|
|
795
|
+
return new Set(
|
|
796
|
+
text.toLowerCase().replace(/[^a-z0-9_\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4 && !STOPWORDS.has(w)).map(stemToken)
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
function intersectionSize(a, b) {
|
|
800
|
+
let count = 0;
|
|
801
|
+
for (const token of a) {
|
|
802
|
+
if (b.has(token)) count++;
|
|
803
|
+
}
|
|
804
|
+
return count;
|
|
805
|
+
}
|
|
806
|
+
function descriptionSimilarity(a, b) {
|
|
807
|
+
const aTokens = tokenSet(a);
|
|
808
|
+
const bTokens = tokenSet(b);
|
|
809
|
+
if (aTokens.size === 0 || bTokens.size === 0) return 0;
|
|
810
|
+
const intersection = intersectionSize(aTokens, bTokens);
|
|
811
|
+
const union = aTokens.size + bTokens.size - intersection;
|
|
812
|
+
return union === 0 ? 0 : intersection / union;
|
|
813
|
+
}
|
|
814
|
+
function topicOverlapSimilarity(a, b, minTokens = 3) {
|
|
815
|
+
const aTokens = tokenSet(a);
|
|
816
|
+
const bTokens = tokenSet(b);
|
|
817
|
+
if (aTokens.size < minTokens || bTokens.size < minTokens) return 0;
|
|
818
|
+
const intersection = intersectionSize(aTokens, bTokens);
|
|
819
|
+
const smaller = Math.min(aTokens.size, bTokens.size);
|
|
820
|
+
return smaller === 0 ? 0 : intersection / smaller;
|
|
821
|
+
}
|
|
822
|
+
var DESCRIPTION_DUPLICATE_THRESHOLD = 0.4;
|
|
823
|
+
var TOPIC_OVERLAP_THRESHOLD = 0.6;
|
|
824
|
+
function checkFrontmatterPreservation(existing, incoming) {
|
|
825
|
+
const violations = [];
|
|
826
|
+
for (const field of PROTECTED_FRONTMATTER_FIELDS) {
|
|
827
|
+
const oldValue = extractFrontmatterField(existing, field);
|
|
828
|
+
const newValue = extractFrontmatterField(incoming, field);
|
|
829
|
+
if (oldValue === void 0 || newValue === void 0) continue;
|
|
830
|
+
if (field === "allowed-tools") {
|
|
831
|
+
const oldParsed = parseAllowedTools(oldValue);
|
|
832
|
+
const newParsed = parseAllowedTools(newValue);
|
|
833
|
+
if (oldParsed && newParsed) {
|
|
834
|
+
const oldSet = new Set(oldParsed);
|
|
835
|
+
const newSet = new Set(newParsed);
|
|
836
|
+
const changed = oldSet.size !== newSet.size || [...oldSet].some((t) => !newSet.has(t));
|
|
837
|
+
if (changed) {
|
|
838
|
+
violations.push(`${field}: was [${oldParsed.join(", ")}], changed to [${newParsed.join(", ")}]`);
|
|
839
|
+
}
|
|
840
|
+
continue;
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
if (oldValue !== newValue) {
|
|
844
|
+
violations.push(`${field}: was "${oldValue}", changed to "${newValue}"`);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
const oldDesc = extractFrontmatterField(existing, "description");
|
|
848
|
+
const newDesc = extractFrontmatterField(incoming, "description");
|
|
849
|
+
if (oldDesc && newDesc && newDesc.length < oldDesc.length * 0.9) {
|
|
850
|
+
violations.push(
|
|
851
|
+
`description shortened from ${oldDesc.length} to ${newDesc.length} chars (${Math.round((1 - newDesc.length / oldDesc.length) * 100)}% reduction). Descriptions are the primary triggering mechanism \u2014 do not shorten them.`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
return violations;
|
|
855
|
+
}
|
|
856
|
+
function validateSkillContent(content, dirName) {
|
|
857
|
+
const issues = [];
|
|
858
|
+
const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
859
|
+
if (!fmMatch) {
|
|
860
|
+
issues.push("Missing YAML frontmatter (must start with --- and end with ---)");
|
|
861
|
+
return issues;
|
|
862
|
+
}
|
|
863
|
+
const frontmatter = fmMatch[1];
|
|
864
|
+
for (const field of REQUIRED_FRONTMATTER_FIELDS) {
|
|
865
|
+
if (!frontmatter.includes(`${field}:`)) {
|
|
866
|
+
issues.push(`Missing required frontmatter field: ${field}`);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
const nameMatch = frontmatter.match(/^name:\s*(.+)$/m);
|
|
870
|
+
if (nameMatch && !nameMatch[1].trim().startsWith("myco:")) {
|
|
871
|
+
issues.push(`Skill name must start with "myco:" prefix. Got: "${nameMatch[1].trim()}"`);
|
|
872
|
+
}
|
|
873
|
+
const managedMatch = frontmatter.match(/^managed_by:\s*(.+)$/m);
|
|
874
|
+
if (managedMatch && managedMatch[1].trim() !== "myco") {
|
|
875
|
+
issues.push(`managed_by must be "myco". Got: "${managedMatch[1].trim()}"`);
|
|
876
|
+
}
|
|
877
|
+
const rawAllowedTools = extractFrontmatterField(content, "allowed-tools");
|
|
878
|
+
if (rawAllowedTools) {
|
|
879
|
+
const rawValue = rawAllowedTools;
|
|
880
|
+
if (rawValue.includes("vault_")) {
|
|
881
|
+
issues.push(
|
|
882
|
+
"allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
|
|
883
|
+
);
|
|
884
|
+
} else {
|
|
885
|
+
const parsed = parseAllowedTools(rawValue);
|
|
886
|
+
if (parsed === null) {
|
|
887
|
+
issues.push(
|
|
888
|
+
`allowed-tools value is malformed or empty: "${rawValue}". Provide a comma-separated list of Claude Code tools, e.g. "Read, Edit, Write, Bash, Grep, Glob". Use the narrowest set the skill actually needs.`
|
|
889
|
+
);
|
|
890
|
+
} else {
|
|
891
|
+
const unknown = parsed.filter((t) => !ALLOWED_CLAUDE_CODE_TOOLS.has(t));
|
|
892
|
+
if (unknown.length > 0) {
|
|
893
|
+
issues.push(
|
|
894
|
+
`allowed-tools contains unknown tool name(s): ${unknown.join(", ")}. Valid Claude Code tools: ${[...ALLOWED_CLAUDE_CODE_TOOLS].join(", ")}.`
|
|
895
|
+
);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
const listToolLines = frontmatter.match(/^\s+-\s+vault_\w+/gm);
|
|
901
|
+
if (listToolLines) {
|
|
902
|
+
issues.push(
|
|
903
|
+
"allowed-tools contains vault agent tool names (vault_*). Skills run in Claude Code sessions -- use Claude Code tool names instead: Read, Edit, Write, Bash, Grep, Glob"
|
|
904
|
+
);
|
|
905
|
+
}
|
|
906
|
+
const lineCount = content.split("\n").length;
|
|
907
|
+
if (lineCount > MAX_SKILL_LINES) {
|
|
908
|
+
issues.push(`Skill is ${lineCount} lines (max ${MAX_SKILL_LINES})`);
|
|
909
|
+
}
|
|
910
|
+
return issues;
|
|
498
911
|
}
|
|
499
912
|
|
|
500
913
|
// src/agent/instruction-builders.ts
|
|
501
914
|
var SKILL_GENERATE_TASK = "skill-generate";
|
|
502
915
|
var SKILL_EVOLVE_TASK = "skill-evolve";
|
|
916
|
+
var SKILL_SURVEY_TASK = "skill-survey";
|
|
917
|
+
var SURVEY_MAX_WISDOM_SPORES = 30;
|
|
918
|
+
var SURVEY_MAX_SESSIONS = 15;
|
|
919
|
+
var SURVEY_WATERMARK_KEY = "skill-survey-watermark";
|
|
503
920
|
function buildSkillGenerateInstruction() {
|
|
504
921
|
const candidates = listCandidates({ status: "approved", limit: 1 });
|
|
505
922
|
if (candidates.length === 0) return void 0;
|
|
@@ -537,14 +954,108 @@ function buildSkillGenerateInstruction() {
|
|
|
537
954
|
}
|
|
538
955
|
}
|
|
539
956
|
}
|
|
540
|
-
return {
|
|
541
|
-
instruction: parts.join("\n"),
|
|
542
|
-
context: { candidate_id: c.id }
|
|
543
|
-
};
|
|
957
|
+
return {
|
|
958
|
+
instruction: parts.join("\n"),
|
|
959
|
+
context: { candidate_id: c.id }
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
function buildSkillSurveyInstruction(agentId) {
|
|
963
|
+
const now = epochSeconds();
|
|
964
|
+
const watermarkState = getState(agentId, SURVEY_WATERMARK_KEY);
|
|
965
|
+
const watermarkEpoch = watermarkState ? Number(watermarkState.value) : 0;
|
|
966
|
+
const sinceFilter = watermarkEpoch > 0 ? { since: watermarkEpoch } : {};
|
|
967
|
+
const parts = [
|
|
968
|
+
"## Pre-assembled Vault Context",
|
|
969
|
+
"",
|
|
970
|
+
`Survey watermark: ${watermarkEpoch === 0 ? "first run (full scan)" : new Date(watermarkEpoch * 1e3).toISOString()}`,
|
|
971
|
+
""
|
|
972
|
+
];
|
|
973
|
+
const digests = listDigestExtracts(agentId);
|
|
974
|
+
if (digests.length > 0) {
|
|
975
|
+
const smallest = digests.reduce((a, b) => a.tier < b.tier ? a : b);
|
|
976
|
+
parts.push("### Digest");
|
|
977
|
+
parts.push(`**Tier ${smallest.tier}** (${smallest.content.length} chars):`);
|
|
978
|
+
parts.push(smallest.content);
|
|
979
|
+
parts.push("");
|
|
980
|
+
}
|
|
981
|
+
const wisdomSpores = listSpores({
|
|
982
|
+
observation_type: "wisdom",
|
|
983
|
+
limit: SURVEY_MAX_WISDOM_SPORES,
|
|
984
|
+
...sinceFilter
|
|
985
|
+
});
|
|
986
|
+
if (wisdomSpores.length > 0) {
|
|
987
|
+
parts.push(`### Wisdom Spores (${wisdomSpores.length})`);
|
|
988
|
+
for (const s of wisdomSpores) {
|
|
989
|
+
parts.push(`- **${s.id}** (importance ${s.importance}): ${s.content.slice(0, 300)}`);
|
|
990
|
+
}
|
|
991
|
+
parts.push("");
|
|
992
|
+
}
|
|
993
|
+
const decisions = listSpores({
|
|
994
|
+
observation_type: "decision",
|
|
995
|
+
limit: 20,
|
|
996
|
+
...sinceFilter
|
|
997
|
+
});
|
|
998
|
+
const gotchas = listSpores({
|
|
999
|
+
observation_type: "gotcha",
|
|
1000
|
+
limit: 10,
|
|
1001
|
+
...sinceFilter
|
|
1002
|
+
});
|
|
1003
|
+
if (decisions.length > 0 || gotchas.length > 0) {
|
|
1004
|
+
parts.push(`### Decisions (${decisions.length}) & Gotchas (${gotchas.length})`);
|
|
1005
|
+
for (const s of [...decisions, ...gotchas]) {
|
|
1006
|
+
parts.push(`- **${s.observation_type}** ${s.id}: ${s.content.slice(0, 200)}`);
|
|
1007
|
+
}
|
|
1008
|
+
parts.push("");
|
|
1009
|
+
}
|
|
1010
|
+
const sessions = listSessions({
|
|
1011
|
+
limit: SURVEY_MAX_SESSIONS,
|
|
1012
|
+
...sinceFilter
|
|
1013
|
+
});
|
|
1014
|
+
if (sessions.length > 0) {
|
|
1015
|
+
parts.push(`### Recent Sessions (${sessions.length})`);
|
|
1016
|
+
for (const s of sessions) {
|
|
1017
|
+
parts.push(`- **${s.id}**: ${s.title ?? "(untitled)"} \u2014 ${(s.summary ?? "").slice(0, 200)}`);
|
|
1018
|
+
}
|
|
1019
|
+
parts.push("");
|
|
1020
|
+
}
|
|
1021
|
+
const activeSkills = listSkillRecords({ status: "active", limit: 100 });
|
|
1022
|
+
parts.push(`### Active Skills (${activeSkills.length})`);
|
|
1023
|
+
for (const s of activeSkills) {
|
|
1024
|
+
parts.push(`- **${s.name}**: ${s.description.slice(0, 150)}`);
|
|
1025
|
+
}
|
|
1026
|
+
parts.push("");
|
|
1027
|
+
setState(agentId, SURVEY_WATERMARK_KEY, String(now), now);
|
|
1028
|
+
return { instruction: parts.join("\n") };
|
|
1029
|
+
}
|
|
1030
|
+
var SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS = 24;
|
|
1031
|
+
var SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN = 8;
|
|
1032
|
+
var MIN_SECTIONS_FOR_STANDALONE = 2;
|
|
1033
|
+
function extractHeadings(content) {
|
|
1034
|
+
const bodyMatch = content.match(/^---[\s\S]*?---\n([\s\S]*)$/);
|
|
1035
|
+
const body = bodyMatch ? bodyMatch[1] : content;
|
|
1036
|
+
return body.split("\n").filter((line) => line.startsWith("## ")).map((line) => line.slice(3).trim());
|
|
1037
|
+
}
|
|
1038
|
+
function headingOverlap(headingsA, headingsB) {
|
|
1039
|
+
if (headingsA.length === 0 || headingsB.length === 0) return { score: 0, shared: [] };
|
|
1040
|
+
const tokenize = (h) => new Set(
|
|
1041
|
+
h.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length >= 4)
|
|
1042
|
+
);
|
|
1043
|
+
const shared = [];
|
|
1044
|
+
for (const a of headingsA) {
|
|
1045
|
+
const aTokens = tokenize(a);
|
|
1046
|
+
for (const b of headingsB) {
|
|
1047
|
+
const bTokens = tokenize(b);
|
|
1048
|
+
const intersection = [...aTokens].filter((t) => bTokens.has(t)).length;
|
|
1049
|
+
const union = (/* @__PURE__ */ new Set([...aTokens, ...bTokens])).size;
|
|
1050
|
+
if (union > 0 && intersection / union >= 0.5) {
|
|
1051
|
+
shared.push(`"${a}" ~ "${b}"`);
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
const smaller = Math.min(headingsA.length, headingsB.length);
|
|
1056
|
+
return { score: smaller > 0 ? shared.length / smaller : 0, shared };
|
|
544
1057
|
}
|
|
545
|
-
|
|
546
|
-
var SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN = 5;
|
|
547
|
-
function buildSkillEvolveInstruction(params) {
|
|
1058
|
+
function buildSkillEvolveInstruction(params, projectRoot, similarityProvider) {
|
|
548
1059
|
const assessIntervalHours = Number(params?.assess_interval_hours ?? SKILL_EVOLVE_DEFAULT_ASSESS_INTERVAL_HOURS);
|
|
549
1060
|
const maxSkillsPerRun = Number(params?.max_skills_per_run ?? SKILL_EVOLVE_DEFAULT_MAX_SKILLS_PER_RUN);
|
|
550
1061
|
const now = epochSeconds();
|
|
@@ -563,14 +1074,11 @@ function buildSkillEvolveInstruction(params) {
|
|
|
563
1074
|
if (lastAssessedAt > 0 && now - lastAssessedAt < intervalSeconds) continue;
|
|
564
1075
|
const newSporeIds = listSporeIdsSince(knowledgeWatermark, 10);
|
|
565
1076
|
if (newSporeIds.length === 0) continue;
|
|
566
|
-
const lineage = listLineageForSkill(skill.id, 1);
|
|
567
|
-
if (lineage.length === 0) continue;
|
|
568
1077
|
needsAssessment.push({
|
|
569
1078
|
id: skill.id,
|
|
570
1079
|
name: skill.name,
|
|
571
1080
|
generation: skill.generation,
|
|
572
1081
|
description: skill.description,
|
|
573
|
-
contentSnapshot: lineage[0].content_snapshot,
|
|
574
1082
|
newSporeIds
|
|
575
1083
|
});
|
|
576
1084
|
if (needsAssessment.length >= maxSkillsPerRun) {
|
|
@@ -580,6 +1088,48 @@ function buildSkillEvolveInstruction(params) {
|
|
|
580
1088
|
if (needsAssessment.length === 0) {
|
|
581
1089
|
return "No skills need assessment. All active skills are current or were recently assessed. Report skip via vault_report and finish.";
|
|
582
1090
|
}
|
|
1091
|
+
const structures = [];
|
|
1092
|
+
const skillHeadings = /* @__PURE__ */ new Map();
|
|
1093
|
+
for (const skill of allSkills) {
|
|
1094
|
+
let content = "";
|
|
1095
|
+
if (projectRoot && skill.path) {
|
|
1096
|
+
try {
|
|
1097
|
+
content = readFileSync(resolve(projectRoot, skill.path), "utf-8");
|
|
1098
|
+
} catch {
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
const headings = extractHeadings(content);
|
|
1102
|
+
skillHeadings.set(skill.name, headings);
|
|
1103
|
+
structures.push({
|
|
1104
|
+
name: skill.name,
|
|
1105
|
+
sectionCount: headings.length,
|
|
1106
|
+
headings,
|
|
1107
|
+
narrow: headings.length < MIN_SECTIONS_FOR_STANDALONE
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1110
|
+
const overlaps = [];
|
|
1111
|
+
for (let i = 0; i < allSkills.length; i++) {
|
|
1112
|
+
for (let j = i + 1; j < allSkills.length; j++) {
|
|
1113
|
+
const a = allSkills[i];
|
|
1114
|
+
const b = allSkills[j];
|
|
1115
|
+
const descJaccard = descriptionSimilarity(a.description, b.description);
|
|
1116
|
+
const aHeadings = skillHeadings.get(a.name) ?? [];
|
|
1117
|
+
const bHeadings = skillHeadings.get(b.name) ?? [];
|
|
1118
|
+
const ho = headingOverlap(aHeadings, bHeadings);
|
|
1119
|
+
const descFlag = descJaccard >= DESCRIPTION_DUPLICATE_THRESHOLD * 0.75;
|
|
1120
|
+
const headingFlag = ho.score >= 0.4;
|
|
1121
|
+
if (!descFlag && !headingFlag) continue;
|
|
1122
|
+
const verdict = descJaccard >= DESCRIPTION_DUPLICATE_THRESHOLD || ho.score >= 0.5 ? "potential-merge" : "potential-narrow";
|
|
1123
|
+
overlaps.push({
|
|
1124
|
+
skillA: a.name,
|
|
1125
|
+
skillB: b.name,
|
|
1126
|
+
descriptionJaccard: Math.round(descJaccard * 100) / 100,
|
|
1127
|
+
headingOverlap: Math.round(ho.score * 100) / 100,
|
|
1128
|
+
sharedHeadings: ho.shared,
|
|
1129
|
+
verdict
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
583
1133
|
const parts = [
|
|
584
1134
|
`${needsAssessment.length} skill(s) need assessment.`,
|
|
585
1135
|
`assess_interval_hours: ${assessIntervalHours}`,
|
|
@@ -592,19 +1142,66 @@ function buildSkillEvolveInstruction(params) {
|
|
|
592
1142
|
parts.push(`id: ${skill.id}`);
|
|
593
1143
|
parts.push(`description: ${skill.description}`);
|
|
594
1144
|
parts.push(`new_spore_ids: ${JSON.stringify(skill.newSporeIds)}`);
|
|
1145
|
+
}
|
|
1146
|
+
parts.push("");
|
|
1147
|
+
parts.push("## All Active Skills (for inventory analysis)");
|
|
1148
|
+
for (const s of structures) {
|
|
1149
|
+
const skill = allSkills.find((sk) => sk.name === s.name);
|
|
1150
|
+
const narrowTag = s.narrow ? " **[NARROW \u2014 <2 sections]**" : "";
|
|
1151
|
+
parts.push(`- **${skill.name}** (gen ${skill.generation}, ${s.sectionCount} sections${narrowTag}): ${skill.description.slice(0, 200)}`);
|
|
1152
|
+
if (s.headings.length > 0) {
|
|
1153
|
+
parts.push(` Headings: ${s.headings.join(" | ")}`);
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
const narrowSkills = structures.filter((s) => s.narrow);
|
|
1157
|
+
if (narrowSkills.length > 0) {
|
|
595
1158
|
parts.push("");
|
|
596
|
-
parts.push("
|
|
1159
|
+
parts.push("## Mechanically Narrow Skills (<2 H2 sections)");
|
|
1160
|
+
parts.push("These skills have insufficient section breadth for domain-level standalone status.");
|
|
1161
|
+
parts.push("Determine which broader skill each should be absorbed into.");
|
|
1162
|
+
for (const s of narrowSkills) {
|
|
1163
|
+
parts.push(`- **${s.name}**: ${s.sectionCount} section(s). Headings: ${s.headings.length > 0 ? s.headings.join(" | ") : "(none)"}`);
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (overlaps.length > 0) {
|
|
597
1167
|
parts.push("");
|
|
598
|
-
parts.push(
|
|
1168
|
+
parts.push("## Pre-computed Token Overlap");
|
|
1169
|
+
parts.push("Pairs flagged by description token similarity AND/OR heading overlap:");
|
|
1170
|
+
for (const o of overlaps) {
|
|
1171
|
+
parts.push(`- **${o.skillA}** <-> **${o.skillB}**: desc=${o.descriptionJaccard}, headings=${o.headingOverlap} (${o.verdict})`);
|
|
1172
|
+
if (o.sharedHeadings.length > 0) {
|
|
1173
|
+
parts.push(` Shared headings: ${o.sharedHeadings.join("; ")}`);
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
if (similarityProvider) {
|
|
1178
|
+
const idToName = new Map(allSkills.map((s) => [s.id, s.name]));
|
|
1179
|
+
try {
|
|
1180
|
+
const semanticPairs = similarityProvider.pairwiseSimilarity("skill_records", 0.65);
|
|
1181
|
+
if (semanticPairs.length > 0) {
|
|
1182
|
+
parts.push("");
|
|
1183
|
+
parts.push("## Semantic Similarity (embedding cosine distance)");
|
|
1184
|
+
parts.push("Pairs with cosine similarity >= 0.65. This is the STRONGEST overlap signal.");
|
|
1185
|
+
parts.push("High similarity (>0.8) means the skills describe nearly identical procedures.");
|
|
1186
|
+
for (const p of semanticPairs) {
|
|
1187
|
+
const nameA = idToName.get(p.idA) ?? p.idA;
|
|
1188
|
+
const nameB = idToName.get(p.idB) ?? p.idB;
|
|
1189
|
+
parts.push(`- **${nameA}** <-> **${nameB}**: cosine=${p.similarity}`);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
} catch {
|
|
1193
|
+
}
|
|
599
1194
|
}
|
|
600
1195
|
return parts.join("\n");
|
|
601
1196
|
}
|
|
602
|
-
function buildTaskInstruction(taskName, taskParams) {
|
|
1197
|
+
function buildTaskInstruction(taskName, taskParams, agentId, projectRoot, similarityProvider) {
|
|
603
1198
|
switch (taskName) {
|
|
604
1199
|
case SKILL_GENERATE_TASK:
|
|
605
1200
|
return buildSkillGenerateInstruction();
|
|
1201
|
+
case SKILL_SURVEY_TASK:
|
|
1202
|
+
return agentId ? buildSkillSurveyInstruction(agentId) : void 0;
|
|
606
1203
|
case SKILL_EVOLVE_TASK: {
|
|
607
|
-
const instruction = buildSkillEvolveInstruction(taskParams);
|
|
1204
|
+
const instruction = buildSkillEvolveInstruction(taskParams, projectRoot, similarityProvider);
|
|
608
1205
|
return instruction ? { instruction } : void 0;
|
|
609
1206
|
}
|
|
610
1207
|
default:
|
|
@@ -612,7 +1209,7 @@ function buildTaskInstruction(taskName, taskParams) {
|
|
|
612
1209
|
}
|
|
613
1210
|
}
|
|
614
1211
|
function isInstructionRequiredTask(taskName) {
|
|
615
|
-
return taskName === SKILL_GENERATE_TASK || taskName === SKILL_EVOLVE_TASK;
|
|
1212
|
+
return taskName === SKILL_GENERATE_TASK || taskName === SKILL_EVOLVE_TASK || taskName === SKILL_SURVEY_TASK;
|
|
616
1213
|
}
|
|
617
1214
|
|
|
618
1215
|
// src/db/queries/runs.ts
|
|
@@ -634,7 +1231,7 @@ var RUN_COLUMNS = [
|
|
|
634
1231
|
"actions_taken",
|
|
635
1232
|
"error"
|
|
636
1233
|
];
|
|
637
|
-
var
|
|
1234
|
+
var SELECT_COLUMNS5 = RUN_COLUMNS.join(", ");
|
|
638
1235
|
function toRunRow(row) {
|
|
639
1236
|
return {
|
|
640
1237
|
id: row.id,
|
|
@@ -676,13 +1273,13 @@ function insertRun(data) {
|
|
|
676
1273
|
data.error ?? null
|
|
677
1274
|
);
|
|
678
1275
|
return toRunRow(
|
|
679
|
-
db.prepare(`SELECT ${
|
|
1276
|
+
db.prepare(`SELECT ${SELECT_COLUMNS5} FROM agent_runs WHERE id = ?`).get(data.id)
|
|
680
1277
|
);
|
|
681
1278
|
}
|
|
682
1279
|
function getRun(id) {
|
|
683
1280
|
const db = getDatabase();
|
|
684
1281
|
const row = db.prepare(
|
|
685
|
-
`SELECT ${
|
|
1282
|
+
`SELECT ${SELECT_COLUMNS5} FROM agent_runs WHERE id = ?`
|
|
686
1283
|
).get(id);
|
|
687
1284
|
if (!row) return null;
|
|
688
1285
|
return toRunRow(row);
|
|
@@ -717,7 +1314,7 @@ function listRuns(options = {}) {
|
|
|
717
1314
|
const limit = options.limit ?? DEFAULT_LIST_LIMIT2;
|
|
718
1315
|
const offset = options.offset ?? 0;
|
|
719
1316
|
const rows = db.prepare(
|
|
720
|
-
`SELECT ${
|
|
1317
|
+
`SELECT ${SELECT_COLUMNS5}
|
|
721
1318
|
FROM agent_runs
|
|
722
1319
|
${where}
|
|
723
1320
|
ORDER BY started_at DESC NULLS LAST
|
|
@@ -766,7 +1363,7 @@ function updateRunStatus(id, status, completion) {
|
|
|
766
1363
|
).run(...params);
|
|
767
1364
|
if (info.changes === 0) return null;
|
|
768
1365
|
return toRunRow(
|
|
769
|
-
db.prepare(`SELECT ${
|
|
1366
|
+
db.prepare(`SELECT ${SELECT_COLUMNS5} FROM agent_runs WHERE id = ?`).get(id)
|
|
770
1367
|
);
|
|
771
1368
|
}
|
|
772
1369
|
function getRunningRunForTask(agentId, taskName) {
|
|
@@ -875,121 +1472,64 @@ function resolveRunConfig(agentId, requestedTask, vaultDir) {
|
|
|
875
1472
|
};
|
|
876
1473
|
}
|
|
877
1474
|
|
|
878
|
-
// src/db/queries/
|
|
879
|
-
var
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
conditions.push("mode = ?");
|
|
902
|
-
params.push(opts.mode);
|
|
903
|
-
}
|
|
904
|
-
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
905
|
-
const limit = opts.limit ?? DEFAULT_LIMIT;
|
|
906
|
-
const offset = opts.offset ?? 0;
|
|
907
|
-
return db.prepare(
|
|
908
|
-
`SELECT * FROM notifications ${where} ORDER BY created_at DESC LIMIT ? OFFSET ?`
|
|
909
|
-
).all(...params, limit, offset);
|
|
910
|
-
}
|
|
911
|
-
function countNotifications(status) {
|
|
912
|
-
const db = getDatabase();
|
|
913
|
-
if (status) {
|
|
914
|
-
const row2 = db.prepare("SELECT COUNT(*) as count FROM notifications WHERE status = ?").get(status);
|
|
915
|
-
return row2.count;
|
|
916
|
-
}
|
|
917
|
-
const row = db.prepare("SELECT COUNT(*) as count FROM notifications").get();
|
|
918
|
-
return row.count;
|
|
919
|
-
}
|
|
920
|
-
function getNotification(id) {
|
|
921
|
-
const db = getDatabase();
|
|
922
|
-
return db.prepare("SELECT * FROM notifications WHERE id = ?").get(id);
|
|
923
|
-
}
|
|
924
|
-
function updateNotificationStatus(id, status) {
|
|
925
|
-
const db = getDatabase();
|
|
926
|
-
const result = db.prepare("UPDATE notifications SET status = ? WHERE id = ?").run(status, id);
|
|
927
|
-
return result.changes > 0;
|
|
1475
|
+
// src/db/queries/skill-lineage.ts
|
|
1476
|
+
var LINEAGE_COLUMNS = [
|
|
1477
|
+
"id",
|
|
1478
|
+
"skill_id",
|
|
1479
|
+
"generation",
|
|
1480
|
+
"action",
|
|
1481
|
+
"rationale",
|
|
1482
|
+
"source_ids_added",
|
|
1483
|
+
"content_snapshot",
|
|
1484
|
+
"created_at"
|
|
1485
|
+
];
|
|
1486
|
+
var SELECT_COLUMNS6 = LINEAGE_COLUMNS.join(", ");
|
|
1487
|
+
function toLineageRow(row) {
|
|
1488
|
+
return {
|
|
1489
|
+
id: row.id,
|
|
1490
|
+
skill_id: row.skill_id,
|
|
1491
|
+
generation: row.generation,
|
|
1492
|
+
action: row.action,
|
|
1493
|
+
rationale: row.rationale,
|
|
1494
|
+
source_ids_added: row.source_ids_added ?? "[]",
|
|
1495
|
+
content_snapshot: row.content_snapshot,
|
|
1496
|
+
created_at: row.created_at
|
|
1497
|
+
};
|
|
928
1498
|
}
|
|
929
|
-
function
|
|
1499
|
+
function insertLineage(data) {
|
|
930
1500
|
const db = getDatabase();
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1501
|
+
db.prepare(
|
|
1502
|
+
`INSERT INTO skill_lineage (
|
|
1503
|
+
id, skill_id, generation, action, rationale,
|
|
1504
|
+
source_ids_added, content_snapshot, created_at
|
|
1505
|
+
) VALUES (
|
|
1506
|
+
?, ?, ?, ?, ?,
|
|
1507
|
+
?, ?, ?
|
|
1508
|
+
)`
|
|
1509
|
+
).run(
|
|
1510
|
+
data.id,
|
|
1511
|
+
data.skill_id,
|
|
1512
|
+
data.generation,
|
|
1513
|
+
data.action,
|
|
1514
|
+
data.rationale,
|
|
1515
|
+
data.source_ids_added ?? "[]",
|
|
1516
|
+
data.content_snapshot,
|
|
1517
|
+
data.created_at
|
|
1518
|
+
);
|
|
1519
|
+
return toLineageRow(
|
|
1520
|
+
db.prepare(`SELECT ${SELECT_COLUMNS6} FROM skill_lineage WHERE id = ?`).get(data.id)
|
|
1521
|
+
);
|
|
937
1522
|
}
|
|
938
|
-
function
|
|
1523
|
+
function listLineageForSkill(skillId, limit = 50) {
|
|
939
1524
|
const db = getDatabase();
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
// src/notifications/registry.ts
|
|
949
|
-
var domains = /* @__PURE__ */ new Map();
|
|
950
|
-
function register(descriptor) {
|
|
951
|
-
domains.set(descriptor.domain, descriptor);
|
|
952
|
-
}
|
|
953
|
-
function getAllDomains() {
|
|
954
|
-
return [...domains.values()].sort((a, b) => a.domain.localeCompare(b.domain));
|
|
955
|
-
}
|
|
956
|
-
function getType(typeId) {
|
|
957
|
-
for (const descriptor of domains.values()) {
|
|
958
|
-
const match = descriptor.types.find((t) => t.id === typeId);
|
|
959
|
-
if (match) return { domain: descriptor, type: match };
|
|
960
|
-
}
|
|
961
|
-
return void 0;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
// src/notifications/notify.ts
|
|
965
|
-
import crypto from "crypto";
|
|
966
|
-
function notify(vaultDir, payload, config) {
|
|
967
|
-
if (!vaultDir) return null;
|
|
968
|
-
try {
|
|
969
|
-
const cfg = config ?? loadConfig(vaultDir);
|
|
970
|
-
if (!cfg.notifications.enabled) return null;
|
|
971
|
-
const domainConfig = cfg.notifications.domains[payload.domain];
|
|
972
|
-
if (domainConfig && !domainConfig.enabled) return null;
|
|
973
|
-
const registeredType = getType(payload.type);
|
|
974
|
-
const mode = payload.mode ?? domainConfig?.mode ?? registeredType?.type.defaultMode ?? cfg.notifications.default_mode;
|
|
975
|
-
const level = payload.level ?? registeredType?.type.defaultLevel ?? "info";
|
|
976
|
-
const id = crypto.randomUUID();
|
|
977
|
-
insertNotification({
|
|
978
|
-
id,
|
|
979
|
-
domain: payload.domain,
|
|
980
|
-
type: payload.type,
|
|
981
|
-
level,
|
|
982
|
-
title: payload.title,
|
|
983
|
-
message: payload.message ?? null,
|
|
984
|
-
mode,
|
|
985
|
-
link: payload.link ?? null,
|
|
986
|
-
metadata: payload.metadata ? JSON.stringify(payload.metadata) : null
|
|
987
|
-
});
|
|
988
|
-
return id;
|
|
989
|
-
} catch (err) {
|
|
990
|
-
console.warn("[notify] Failed to emit notification:", err instanceof Error ? err.message : err);
|
|
991
|
-
return null;
|
|
992
|
-
}
|
|
1525
|
+
const rows = db.prepare(
|
|
1526
|
+
`SELECT ${SELECT_COLUMNS6}
|
|
1527
|
+
FROM skill_lineage
|
|
1528
|
+
WHERE skill_id = ?
|
|
1529
|
+
ORDER BY generation DESC
|
|
1530
|
+
LIMIT ?`
|
|
1531
|
+
).all(skillId, limit);
|
|
1532
|
+
return rows.map(toLineageRow);
|
|
993
1533
|
}
|
|
994
1534
|
|
|
995
1535
|
// src/db/queries/batches.ts
|
|
@@ -1018,7 +1558,7 @@ var BATCH_COLUMNS = [
|
|
|
1018
1558
|
"machine_id",
|
|
1019
1559
|
"synced_at"
|
|
1020
1560
|
];
|
|
1021
|
-
var
|
|
1561
|
+
var SELECT_COLUMNS7 = BATCH_COLUMNS.join(", ");
|
|
1022
1562
|
function toBatchRow(row) {
|
|
1023
1563
|
return {
|
|
1024
1564
|
id: row.id,
|
|
@@ -1065,7 +1605,7 @@ function getUnprocessedBatches(options = {}) {
|
|
|
1065
1605
|
params.push(limit);
|
|
1066
1606
|
const where = conditions.join(" AND ");
|
|
1067
1607
|
const rows = db.prepare(
|
|
1068
|
-
`SELECT ${
|
|
1608
|
+
`SELECT ${SELECT_COLUMNS7}
|
|
1069
1609
|
FROM prompt_batches
|
|
1070
1610
|
WHERE ${where}
|
|
1071
1611
|
ORDER BY id ASC
|
|
@@ -1082,7 +1622,7 @@ function incrementActivityCount(id) {
|
|
|
1082
1622
|
).run(id);
|
|
1083
1623
|
if (info.changes === 0) return null;
|
|
1084
1624
|
return toBatchRow(
|
|
1085
|
-
db.prepare(`SELECT ${
|
|
1625
|
+
db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(id)
|
|
1086
1626
|
);
|
|
1087
1627
|
}
|
|
1088
1628
|
function markBatchProcessed(id) {
|
|
@@ -1094,7 +1634,7 @@ function markBatchProcessed(id) {
|
|
|
1094
1634
|
).run(PROCESSED_FLAG, id);
|
|
1095
1635
|
if (info.changes === 0) return null;
|
|
1096
1636
|
return toBatchRow(
|
|
1097
|
-
db.prepare(`SELECT ${
|
|
1637
|
+
db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(id)
|
|
1098
1638
|
);
|
|
1099
1639
|
}
|
|
1100
1640
|
function findBatchByPromptPrefix(sessionId, promptPrefix) {
|
|
@@ -1134,7 +1674,7 @@ function insertBatchStateless(data) {
|
|
|
1134
1674
|
);
|
|
1135
1675
|
const batchId = Number(info.lastInsertRowid);
|
|
1136
1676
|
return toBatchRow(
|
|
1137
|
-
db.prepare(`SELECT ${
|
|
1677
|
+
db.prepare(`SELECT ${SELECT_COLUMNS7} FROM prompt_batches WHERE id = ?`).get(batchId)
|
|
1138
1678
|
);
|
|
1139
1679
|
}
|
|
1140
1680
|
function closeOpenBatches(sessionId, endedAt) {
|
|
@@ -1155,7 +1695,7 @@ function setResponseSummary(batchId, summary) {
|
|
|
1155
1695
|
function getLatestBatch(sessionId) {
|
|
1156
1696
|
const db = getDatabase();
|
|
1157
1697
|
const row = db.prepare(
|
|
1158
|
-
`SELECT ${
|
|
1698
|
+
`SELECT ${SELECT_COLUMNS7} FROM prompt_batches
|
|
1159
1699
|
WHERE session_id = ?
|
|
1160
1700
|
ORDER BY id DESC LIMIT 1`
|
|
1161
1701
|
).get(sessionId);
|
|
@@ -1167,7 +1707,7 @@ function listBatchesBySession(sessionId, options = {}) {
|
|
|
1167
1707
|
const limit = options.limit ?? BATCHES_DEFAULT_LIMIT;
|
|
1168
1708
|
const offset = options.offset ?? 0;
|
|
1169
1709
|
const rows = db.prepare(
|
|
1170
|
-
`SELECT ${
|
|
1710
|
+
`SELECT ${SELECT_COLUMNS7}
|
|
1171
1711
|
FROM prompt_batches
|
|
1172
1712
|
WHERE session_id = ?
|
|
1173
1713
|
ORDER BY prompt_number ASC
|
|
@@ -1203,7 +1743,7 @@ var GRAPH_EDGE_COLUMNS = [
|
|
|
1203
1743
|
"machine_id",
|
|
1204
1744
|
"synced_at"
|
|
1205
1745
|
];
|
|
1206
|
-
var
|
|
1746
|
+
var SELECT_COLUMNS8 = GRAPH_EDGE_COLUMNS.join(", ");
|
|
1207
1747
|
function toGraphEdgeRow(row) {
|
|
1208
1748
|
return {
|
|
1209
1749
|
id: row.id,
|
|
@@ -1244,7 +1784,7 @@ function insertGraphEdge(data) {
|
|
|
1244
1784
|
data.machine_id ?? getTeamMachineId()
|
|
1245
1785
|
);
|
|
1246
1786
|
const row = toGraphEdgeRow(
|
|
1247
|
-
db.prepare(`SELECT ${
|
|
1787
|
+
db.prepare(`SELECT ${SELECT_COLUMNS8} FROM graph_edges WHERE id = ?`).get(id)
|
|
1248
1788
|
);
|
|
1249
1789
|
syncRow("graph_edges", row);
|
|
1250
1790
|
return row;
|
|
@@ -1273,7 +1813,7 @@ function listGraphEdges(options = {}) {
|
|
|
1273
1813
|
const limit = options.limit ?? QUERY_DEFAULT_LIST_LIMIT;
|
|
1274
1814
|
params.push(limit);
|
|
1275
1815
|
const rows = db.prepare(
|
|
1276
|
-
`SELECT ${
|
|
1816
|
+
`SELECT ${SELECT_COLUMNS8}
|
|
1277
1817
|
FROM graph_edges
|
|
1278
1818
|
${where}
|
|
1279
1819
|
ORDER BY created_at DESC
|
|
@@ -1293,7 +1833,7 @@ function getGraphForNode(nodeId, nodeType, options) {
|
|
|
1293
1833
|
const frontierArray = Array.from(frontier);
|
|
1294
1834
|
const placeholders = frontierArray.map(() => `?`).join(", ");
|
|
1295
1835
|
const rows = db.prepare(
|
|
1296
|
-
`SELECT ${
|
|
1836
|
+
`SELECT ${SELECT_COLUMNS8}
|
|
1297
1837
|
FROM graph_edges
|
|
1298
1838
|
WHERE source_id IN (${placeholders}) OR target_id IN (${placeholders})`
|
|
1299
1839
|
).all(...frontierArray, ...frontierArray);
|
|
@@ -1334,7 +1874,7 @@ var ENTITY_COLUMNS = [
|
|
|
1334
1874
|
"machine_id",
|
|
1335
1875
|
"synced_at"
|
|
1336
1876
|
];
|
|
1337
|
-
var
|
|
1877
|
+
var SELECT_COLUMNS9 = ENTITY_COLUMNS.join(", ");
|
|
1338
1878
|
function toEntityRow(row) {
|
|
1339
1879
|
return {
|
|
1340
1880
|
id: row.id,
|
|
@@ -1368,7 +1908,7 @@ function insertEntity(data) {
|
|
|
1368
1908
|
data.machine_id ?? getTeamMachineId()
|
|
1369
1909
|
);
|
|
1370
1910
|
const row = toEntityRow(
|
|
1371
|
-
db.prepare(`SELECT ${
|
|
1911
|
+
db.prepare(`SELECT ${SELECT_COLUMNS9} FROM entities WHERE agent_id = ? AND type = ? AND name = ?`).get(
|
|
1372
1912
|
data.agent_id,
|
|
1373
1913
|
data.type,
|
|
1374
1914
|
data.name
|
|
@@ -1380,7 +1920,7 @@ function insertEntity(data) {
|
|
|
1380
1920
|
function getEntity(id) {
|
|
1381
1921
|
const db = getDatabase();
|
|
1382
1922
|
const row = db.prepare(
|
|
1383
|
-
`SELECT ${
|
|
1923
|
+
`SELECT ${SELECT_COLUMNS9} FROM entities WHERE id = ?`
|
|
1384
1924
|
).get(id);
|
|
1385
1925
|
if (!row) return null;
|
|
1386
1926
|
return toEntityRow(row);
|
|
@@ -1421,7 +1961,7 @@ function listEntities(options = {}) {
|
|
|
1421
1961
|
params.push(limit);
|
|
1422
1962
|
params.push(offset);
|
|
1423
1963
|
const rows = db.prepare(
|
|
1424
|
-
`SELECT ${
|
|
1964
|
+
`SELECT ${SELECT_COLUMNS9}
|
|
1425
1965
|
FROM entities
|
|
1426
1966
|
${where}
|
|
1427
1967
|
ORDER BY last_seen DESC
|
|
@@ -1431,65 +1971,6 @@ function listEntities(options = {}) {
|
|
|
1431
1971
|
return rows.map(toEntityRow);
|
|
1432
1972
|
}
|
|
1433
1973
|
|
|
1434
|
-
// src/db/queries/digest-extracts.ts
|
|
1435
|
-
var EXTRACT_COLUMNS = [
|
|
1436
|
-
"id",
|
|
1437
|
-
"agent_id",
|
|
1438
|
-
"tier",
|
|
1439
|
-
"content",
|
|
1440
|
-
"substrate_hash",
|
|
1441
|
-
"generated_at",
|
|
1442
|
-
"machine_id",
|
|
1443
|
-
"synced_at"
|
|
1444
|
-
];
|
|
1445
|
-
var SELECT_COLUMNS8 = EXTRACT_COLUMNS.join(", ");
|
|
1446
|
-
function toDigestExtractRow(row) {
|
|
1447
|
-
return {
|
|
1448
|
-
id: row.id,
|
|
1449
|
-
agent_id: row.agent_id,
|
|
1450
|
-
tier: row.tier,
|
|
1451
|
-
content: row.content,
|
|
1452
|
-
substrate_hash: row.substrate_hash ?? null,
|
|
1453
|
-
generated_at: row.generated_at,
|
|
1454
|
-
machine_id: row.machine_id ?? "local",
|
|
1455
|
-
synced_at: row.synced_at ?? null
|
|
1456
|
-
};
|
|
1457
|
-
}
|
|
1458
|
-
function upsertDigestExtract(data) {
|
|
1459
|
-
const db = getDatabase();
|
|
1460
|
-
db.prepare(
|
|
1461
|
-
`INSERT INTO digest_extracts (agent_id, tier, content, generated_at)
|
|
1462
|
-
VALUES (?, ?, ?, ?)
|
|
1463
|
-
ON CONFLICT (agent_id, tier) DO UPDATE SET
|
|
1464
|
-
content = EXCLUDED.content,
|
|
1465
|
-
generated_at = EXCLUDED.generated_at`
|
|
1466
|
-
).run(data.agent_id, data.tier, data.content, data.generated_at);
|
|
1467
|
-
const row = db.prepare(
|
|
1468
|
-
`SELECT ${SELECT_COLUMNS8} FROM digest_extracts WHERE agent_id = ? AND tier = ?`
|
|
1469
|
-
).get(data.agent_id, data.tier);
|
|
1470
|
-
return toDigestExtractRow(row);
|
|
1471
|
-
}
|
|
1472
|
-
function getDigestExtract(agentId, tier) {
|
|
1473
|
-
const db = getDatabase();
|
|
1474
|
-
const row = db.prepare(
|
|
1475
|
-
`SELECT ${SELECT_COLUMNS8} FROM digest_extracts
|
|
1476
|
-
WHERE agent_id = ? AND tier = ?`
|
|
1477
|
-
).get(agentId, tier);
|
|
1478
|
-
if (!row) return null;
|
|
1479
|
-
return toDigestExtractRow(row);
|
|
1480
|
-
}
|
|
1481
|
-
function listDigestExtracts(agentId) {
|
|
1482
|
-
const db = getDatabase();
|
|
1483
|
-
const tierPlaceholders = DIGEST_TIERS.map(() => "?").join(", ");
|
|
1484
|
-
const rows = db.prepare(
|
|
1485
|
-
`SELECT ${SELECT_COLUMNS8}
|
|
1486
|
-
FROM digest_extracts
|
|
1487
|
-
WHERE agent_id = ? AND tier IN (${tierPlaceholders})
|
|
1488
|
-
ORDER BY tier ASC`
|
|
1489
|
-
).all(agentId, ...DIGEST_TIERS);
|
|
1490
|
-
return rows.map(toDigestExtractRow);
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
1974
|
// src/db/queries/lineage.ts
|
|
1494
1975
|
function createSporeLineage(spore) {
|
|
1495
1976
|
if (spore.session_id) {
|
|
@@ -1556,7 +2037,7 @@ var REPORT_COLUMNS = [
|
|
|
1556
2037
|
"details",
|
|
1557
2038
|
"created_at"
|
|
1558
2039
|
];
|
|
1559
|
-
var
|
|
2040
|
+
var SELECT_COLUMNS10 = REPORT_COLUMNS.join(", ");
|
|
1560
2041
|
function toReportRow(row) {
|
|
1561
2042
|
return {
|
|
1562
2043
|
id: row.id,
|
|
@@ -1586,13 +2067,13 @@ function insertReport(data) {
|
|
|
1586
2067
|
);
|
|
1587
2068
|
const reportId = Number(info.lastInsertRowid);
|
|
1588
2069
|
return toReportRow(
|
|
1589
|
-
db.prepare(`SELECT ${
|
|
2070
|
+
db.prepare(`SELECT ${SELECT_COLUMNS10} FROM agent_reports WHERE id = ?`).get(reportId)
|
|
1590
2071
|
);
|
|
1591
2072
|
}
|
|
1592
2073
|
function listReports(runId) {
|
|
1593
2074
|
const db = getDatabase();
|
|
1594
2075
|
const rows = db.prepare(
|
|
1595
|
-
`SELECT ${
|
|
2076
|
+
`SELECT ${SELECT_COLUMNS10}
|
|
1596
2077
|
FROM agent_reports
|
|
1597
2078
|
WHERE run_id = ?
|
|
1598
2079
|
ORDER BY created_at ASC`
|
|
@@ -1649,6 +2130,14 @@ export {
|
|
|
1649
2130
|
getDigestExtract,
|
|
1650
2131
|
listDigestExtracts,
|
|
1651
2132
|
errorMessage,
|
|
2133
|
+
setState,
|
|
2134
|
+
getStatesForAgent,
|
|
2135
|
+
descriptionSimilarity,
|
|
2136
|
+
topicOverlapSimilarity,
|
|
2137
|
+
DESCRIPTION_DUPLICATE_THRESHOLD,
|
|
2138
|
+
TOPIC_OVERLAP_THRESHOLD,
|
|
2139
|
+
checkFrontmatterPreservation,
|
|
2140
|
+
validateSkillContent,
|
|
1652
2141
|
SKILL_GENERATE_TASK,
|
|
1653
2142
|
buildTaskInstruction,
|
|
1654
2143
|
isInstructionRequiredTask,
|
|
@@ -1669,4 +2158,4 @@ export {
|
|
|
1669
2158
|
hasConfiguredProvider,
|
|
1670
2159
|
resolveRunConfig
|
|
1671
2160
|
};
|
|
1672
|
-
//# sourceMappingURL=chunk-
|
|
2161
|
+
//# sourceMappingURL=chunk-C3EGL5JX.js.map
|