@swarmvaultai/engine 3.15.0 → 3.16.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 +6 -1
- package/dist/{chunk-NUWZUYE7.js → chunk-NON6BVEI.js} +4 -0
- package/dist/{chunk-JJDJF2P3.js → chunk-TQIIJVVG.js} +341 -10
- package/dist/index.d.ts +77 -2
- package/dist/index.js +234 -4
- package/dist/{memory-A4VPLUBA.js → memory-4BDKH4Y2.js} +2 -2
- package/dist/{registry-2QC3VN7M.js → registry-ZZ6NESFD.js} +1 -1
- package/package.json +3 -3
- package/dist/chunk-2CH2WWS4.js +0 -1359
- package/dist/chunk-2PN46RDI.js +0 -26846
- package/dist/chunk-333AMRSV.js +0 -1056
- package/dist/chunk-3GVEUYQZ.js +0 -1641
- package/dist/chunk-4MSSM2GH.js +0 -1476
- package/dist/chunk-563TZ4TZ.js +0 -26573
- package/dist/chunk-5GEPTIZE.js +0 -26010
- package/dist/chunk-5HNZ2WQI.js +0 -1341
- package/dist/chunk-5Q4IV4O3.js +0 -1336
- package/dist/chunk-6MO57J5C.js +0 -988
- package/dist/chunk-6UPHDGEB.js +0 -1073
- package/dist/chunk-75BU5TQ6.js +0 -1690
- package/dist/chunk-7O2HJSWQ.js +0 -1686
- package/dist/chunk-7QHDATCQ.js +0 -1673
- package/dist/chunk-B3FC4J3P.js +0 -1214
- package/dist/chunk-BTWPJEP2.js +0 -1421
- package/dist/chunk-CG67P2HB.js +0 -1420
- package/dist/chunk-CSPDMCON.js +0 -26846
- package/dist/chunk-CVFY54CF.js +0 -24893
- package/dist/chunk-CWLDFLH2.js +0 -1163
- package/dist/chunk-DAJAZPPO.js +0 -26865
- package/dist/chunk-EEWB4WGH.js +0 -1056
- package/dist/chunk-EXD4RWT3.js +0 -1131
- package/dist/chunk-F7HZZ3VM.js +0 -931
- package/dist/chunk-FD3LJQ4T.js +0 -1216
- package/dist/chunk-G2TH6ZTA.js +0 -1468
- package/dist/chunk-H3CDZYRE.js +0 -1701
- package/dist/chunk-HFU5S5NO.js +0 -838
- package/dist/chunk-HKU2T5JX.js +0 -25213
- package/dist/chunk-HOJ7NSYC.js +0 -937
- package/dist/chunk-HRRPWXRZ.js +0 -1335
- package/dist/chunk-HW72C7O2.js +0 -1690
- package/dist/chunk-IAEYFTUS.js +0 -1159
- package/dist/chunk-IHMJCCXR.js +0 -1146
- package/dist/chunk-JTRE7C7P.js +0 -26062
- package/dist/chunk-LEUV6TWJ.js +0 -1131
- package/dist/chunk-MB7HPUTR.js +0 -1364
- package/dist/chunk-MZSUYTSL.js +0 -998
- package/dist/chunk-N56FAH4N.js +0 -1404
- package/dist/chunk-NCSZ4AKP.js +0 -1057
- package/dist/chunk-NECZ4MUE.js +0 -1416
- package/dist/chunk-NHGS4LOI.js +0 -1346
- package/dist/chunk-OK5752AP.js +0 -1325
- package/dist/chunk-QMW7OISM.js +0 -1063
- package/dist/chunk-RN56HUXA.js +0 -26972
- package/dist/chunk-RSQRF4FV.js +0 -1424
- package/dist/chunk-S2E65WRI.js +0 -26062
- package/dist/chunk-SRHM3HP4.js +0 -944
- package/dist/chunk-U7JO257M.js +0 -25017
- package/dist/chunk-UQCF65BN.js +0 -1623
- package/dist/chunk-USSP4GVB.js +0 -25064
- package/dist/chunk-V7KX3AQD.js +0 -26010
- package/dist/chunk-WOA5LSNB.js +0 -26559
- package/dist/chunk-WWP3VPEJ.js +0 -26080
- package/dist/chunk-YFKWMXJ6.js +0 -26066
- package/dist/chunk-Z552HHPV.js +0 -26846
- package/dist/chunk-ZQ5T64AR.js +0 -1365
- package/dist/memory-DNSQCDHC.js +0 -32
- package/dist/memory-ECS3TSGC.js +0 -32
- package/dist/memory-FVIBFROA.js +0 -32
- package/dist/memory-G6I3DBW4.js +0 -32
- package/dist/memory-HE6VWUPV.js +0 -32
- package/dist/memory-HEA7XNKB.js +0 -32
- package/dist/memory-JRYTVHNH.js +0 -32
- package/dist/memory-K3NL5E3K.js +0 -32
- package/dist/memory-KANI73CX.js +0 -32
- package/dist/memory-KI5G2A4C.js +0 -32
- package/dist/memory-PK55JUKG.js +0 -32
- package/dist/memory-PK5JJNAG.js +0 -32
- package/dist/memory-SAQPBIB4.js +0 -32
- package/dist/memory-SVGRP5KS.js +0 -32
- package/dist/memory-TQ46BGCI.js +0 -32
- package/dist/memory-YKQWWIVY.js +0 -32
- package/dist/memory-Z7BP5OSC.js +0 -32
- package/dist/registry-2REAPKPO.js +0 -12
- package/dist/registry-2XHXZDGH.js +0 -12
- package/dist/registry-4C55ZCPL.js +0 -12
- package/dist/registry-4QRMVAHX.js +0 -12
- package/dist/registry-5SYH3Y3U.js +0 -12
- package/dist/registry-6KZMA3XM.js +0 -12
- package/dist/registry-7QACDJQQ.js +0 -12
- package/dist/registry-B7UXRBW3.js +0 -12
- package/dist/registry-FKEREVDO.js +0 -12
- package/dist/registry-FLSGGY2R.js +0 -12
- package/dist/registry-G7NSRYCO.js +0 -12
- package/dist/registry-GH4O3A7H.js +0 -12
- package/dist/registry-IBH6K2KK.js +0 -12
- package/dist/registry-ILDEBNCW.js +0 -12
- package/dist/registry-JFEW5RUP.js +0 -12
- package/dist/registry-JQYQOZYN.js +0 -12
- package/dist/registry-JR5WY22P.js +0 -12
- package/dist/registry-KLO5YIHP.js +0 -12
- package/dist/registry-KVJAO5DF.js +0 -12
- package/dist/registry-MYJX6AEE.js +0 -12
- package/dist/registry-NBLIJHZT.js +0 -12
- package/dist/registry-NLRWSN5J.js +0 -12
- package/dist/registry-NMXDBYIZ.js +0 -12
- package/dist/registry-OUB6W3LM.js +0 -12
- package/dist/registry-P5KRT66L.js +0 -12
- package/dist/registry-PGZWRXMD.js +0 -12
- package/dist/registry-QAG2ZYH3.js +0 -12
- package/dist/registry-SUXWCWB4.js +0 -12
- package/dist/registry-SYCRRA65.js +0 -12
- package/dist/registry-TYROWPR5.js +0 -12
- package/dist/registry-U23ML76I.js +0 -12
- package/dist/registry-U76DBOV3.js +0 -12
- package/dist/registry-UA42LQUQ.js +0 -12
- package/dist/registry-W6ZFRI73.js +0 -12
- package/dist/registry-X5PMZTZY.js +0 -12
- package/dist/registry-XIL5F33J.js +0 -12
- package/dist/registry-XOPLQNZY.js +0 -12
- package/dist/registry-YDXVCE4Q.js +0 -12
- package/dist/registry-YGVTLIZH.js +0 -12
- package/dist/registry-ZNW3FDED.js +0 -12
package/README.md
CHANGED
|
@@ -215,6 +215,7 @@ The engine supports:
|
|
|
215
215
|
- `together`
|
|
216
216
|
- `xai`
|
|
217
217
|
- `cerebras`
|
|
218
|
+
- `local-whisper`
|
|
218
219
|
- `openai-compatible`
|
|
219
220
|
- `custom`
|
|
220
221
|
|
|
@@ -228,6 +229,7 @@ Providers are capability-driven. Each provider declares support for features suc
|
|
|
228
229
|
- `streaming`
|
|
229
230
|
- `local`
|
|
230
231
|
- `image_generation`
|
|
232
|
+
- `audio`
|
|
231
233
|
|
|
232
234
|
This matters because many "OpenAI-compatible" backends only implement part of the OpenAI surface.
|
|
233
235
|
|
|
@@ -271,6 +273,7 @@ This matters because many "OpenAI-compatible" backends only implement part of th
|
|
|
271
273
|
- `queryGraphVault(rootDir, question, { traversal, budget })` runs deterministic local graph search, preferring semantic seed matches from `tasks.embeddingProvider` when configured and falling back to lexical search plus matching group patterns otherwise
|
|
272
274
|
- `pathGraphVault(rootDir, from, to)` returns the shortest graph path between two targets
|
|
273
275
|
- `explainGraphVault(rootDir, target)` returns node, community, neighbor, provenance, and group-pattern details
|
|
276
|
+
- `findGraphCycles(graph, { relations, limit, maxDepth })` returns deterministic directed cycles, commonly used for import or call-loop inspection
|
|
274
277
|
- `listGraphHyperedges(rootDir, target?, limit?)` returns graph hyperedges globally or for a specific node/page target
|
|
275
278
|
- `listGodNodes(rootDir, limit)` returns the most connected bridge-heavy graph nodes
|
|
276
279
|
- `buildGraphShareArtifact(...)`, `renderGraphShareMarkdown(...)`, `renderGraphShareSvg(...)`, `renderGraphSharePreviewHtml(...)`, and `renderGraphShareBundleFiles(...)` produce the post-ready text, 1200x630 visual card, self-contained HTML preview, and portable share kit used by `wiki/graph/share-card.md`, `wiki/graph/share-card.svg`, `wiki/graph/share-kit/`, and the CLI `graph share` command
|
|
@@ -289,7 +292,9 @@ This matters because many "OpenAI-compatible" backends only implement part of th
|
|
|
289
292
|
- large ingest and compile passes emit low-noise progress on TTYs, bound source-analysis concurrency, and use sparse graph co-occurrence projection so dense note sets do not create unbounded pairwise graph work
|
|
290
293
|
- JSON state writes are atomic, and JSON parse failures include the exact state file path that failed to parse
|
|
291
294
|
- `installGitHooks(rootDir)`, `uninstallGitHooks(rootDir)`, and `getGitHookStatus(rootDir)` manage local `post-commit` and `post-checkout` hook blocks for the nearest git repository
|
|
292
|
-
- `installAgent(rootDir, agent, { hook })` writes agent instructions and returns the primary `target`, all touched `targets`, and optional merge warnings for agents such as Aider
|
|
295
|
+
- `installAgent(rootDir, agent, { hook, scope })` writes agent instructions and returns the primary `target`, all touched `targets`, and optional merge warnings for agents such as Aider and Kilo
|
|
296
|
+
- `getAgentInstallStatus(rootDir, agent, { scope })` reports expected install targets, presence, and managed-block status
|
|
297
|
+
- `addProviderConfig`, `listProviderConfigEntries`, `getProviderConfigEntry`, and `removeProviderConfig` manage named provider entries and task routing in `swarmvault.config.json`
|
|
293
298
|
- `lintVault(rootDir, options)` runs structural lint, optional deep lint, optional contradiction-only filtering through `{ conflicts: true }`, and optional web-augmented evidence gathering
|
|
294
299
|
- `listSchedules(rootDir)`, `runSchedule(rootDir, jobId)`, and `serveSchedules(rootDir)` manage recurring local jobs from config
|
|
295
300
|
- compile, query, explore, lint, and watch also write canonical markdown session artifacts to `state/sessions/`
|
|
@@ -66,9 +66,11 @@ var agentTypeSchema = z.enum([
|
|
|
66
66
|
"cortex",
|
|
67
67
|
"crush",
|
|
68
68
|
"deepagents",
|
|
69
|
+
"devin",
|
|
69
70
|
"firebender",
|
|
70
71
|
"iflow",
|
|
71
72
|
"junie",
|
|
73
|
+
"kilo",
|
|
72
74
|
"kilo-code",
|
|
73
75
|
"kimi",
|
|
74
76
|
"kode",
|
|
@@ -1669,6 +1671,8 @@ async function getResolvedPaths(rootDir) {
|
|
|
1669
1671
|
}
|
|
1670
1672
|
|
|
1671
1673
|
export {
|
|
1674
|
+
providerCapabilitySchema,
|
|
1675
|
+
providerTypeSchema,
|
|
1672
1676
|
slugify,
|
|
1673
1677
|
sha256,
|
|
1674
1678
|
ensureDir,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
uniqueBy,
|
|
23
23
|
writeFileIfChanged,
|
|
24
24
|
writeJsonFile
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-NON6BVEI.js";
|
|
26
26
|
import {
|
|
27
27
|
estimateTokens
|
|
28
28
|
} from "./chunk-NAIERP4C.js";
|
|
@@ -208,6 +208,7 @@ var agentFileKinds = {
|
|
|
208
208
|
kiroSteering: ".kiro/steering/swarmvault.md",
|
|
209
209
|
antigravityRules: ".agents/rules/swarmvault.md",
|
|
210
210
|
antigravityWorkflow: ".agents/workflows/swarmvault.md",
|
|
211
|
+
devinRules: ".windsurf/rules/swarmvault.md",
|
|
211
212
|
vscode: ".github/chatmodes/swarmvault.chatmode.md"
|
|
212
213
|
};
|
|
213
214
|
var legacyAntigravityFileKinds = {
|
|
@@ -226,6 +227,7 @@ var SKILL_BUNDLE_AGENTS = {
|
|
|
226
227
|
cortex: ".snowflake/cortex/skills",
|
|
227
228
|
crush: ".config/crush/skills",
|
|
228
229
|
deepagents: ".deepagents/agent/skills",
|
|
230
|
+
devin: ".devin/skills",
|
|
229
231
|
firebender: ".firebender/skills",
|
|
230
232
|
iflow: ".iflow/skills",
|
|
231
233
|
junie: ".junie/skills",
|
|
@@ -248,15 +250,53 @@ var SKILL_BUNDLE_AGENTS = {
|
|
|
248
250
|
windsurf: ".codeium/windsurf/skills",
|
|
249
251
|
zencoder: ".zencoder/skills"
|
|
250
252
|
};
|
|
253
|
+
var PROJECT_SKILL_TARGETS = {
|
|
254
|
+
antigravity: [".agents/skills"],
|
|
255
|
+
amp: [".amp/skills"],
|
|
256
|
+
codex: [".agents/skills"],
|
|
257
|
+
copilot: [".copilot/skills"],
|
|
258
|
+
devin: [".devin/skills"],
|
|
259
|
+
gemini: [".gemini/skills"],
|
|
260
|
+
kimi: [".kimi/skills"],
|
|
261
|
+
opencode: [".opencode/skills"],
|
|
262
|
+
pi: [".pi/agent/skills"],
|
|
263
|
+
vscode: [".copilot/skills"]
|
|
264
|
+
};
|
|
265
|
+
var USER_SKILL_TARGETS = {
|
|
266
|
+
antigravity: path2.join(".gemini", "config", "skills"),
|
|
267
|
+
amp: path2.join(".amp", "skills"),
|
|
268
|
+
codex: path2.join(".codex", "skills"),
|
|
269
|
+
copilot: path2.join(".copilot", "skills"),
|
|
270
|
+
devin: path2.join(".config", "devin", "skills"),
|
|
271
|
+
gemini: path2.join(".gemini", "skills"),
|
|
272
|
+
kimi: path2.join(".kimi", "skills"),
|
|
273
|
+
kilo: path2.join(".config", "kilo", "skills"),
|
|
274
|
+
opencode: path2.join(".config", "opencode", "skills"),
|
|
275
|
+
pi: path2.join(".pi", "agent", "skills"),
|
|
276
|
+
vscode: path2.join(".copilot", "skills")
|
|
277
|
+
};
|
|
251
278
|
function skillBundleTarget(rootDir, agent) {
|
|
252
279
|
const relativeSkillsDir = SKILL_BUNDLE_AGENTS[agent];
|
|
253
280
|
if (!relativeSkillsDir) return null;
|
|
254
281
|
return path2.join(rootDir, relativeSkillsDir, "swarmvault", "SKILL.md");
|
|
255
282
|
}
|
|
283
|
+
function skillBundlePath(baseDir, relativeSkillsDir) {
|
|
284
|
+
return path2.join(baseDir, relativeSkillsDir, "swarmvault", "SKILL.md");
|
|
285
|
+
}
|
|
286
|
+
function projectSkillTargets(rootDir, agent) {
|
|
287
|
+
return (PROJECT_SKILL_TARGETS[agent] ?? []).map((relativeSkillsDir) => skillBundlePath(rootDir, relativeSkillsDir));
|
|
288
|
+
}
|
|
289
|
+
function userSkillTarget(agent) {
|
|
290
|
+
const relativeSkillsDir = USER_SKILL_TARGETS[agent];
|
|
291
|
+
return relativeSkillsDir ? skillBundlePath(os.homedir(), relativeSkillsDir) : null;
|
|
292
|
+
}
|
|
256
293
|
var hermesUserSkillRelative = path2.join(".hermes", "skills", "swarmvault", "SKILL.md");
|
|
257
294
|
function hermesUserSkillPath() {
|
|
258
295
|
return path2.join(os.homedir(), hermesUserSkillRelative);
|
|
259
296
|
}
|
|
297
|
+
function kiloUserCommandPath() {
|
|
298
|
+
return path2.join(os.homedir(), ".config", "kilo", "command", "swarmvault.md");
|
|
299
|
+
}
|
|
260
300
|
var SWARMVAULT_RULE_BULLETS = [
|
|
261
301
|
"- Read `swarmvault.schema.md` before compile or query style work. It is the canonical schema path.",
|
|
262
302
|
"- Treat `raw/` as immutable source input.",
|
|
@@ -357,6 +397,37 @@ function buildAntigravityWorkflowFile() {
|
|
|
357
397
|
""
|
|
358
398
|
].join("\n");
|
|
359
399
|
}
|
|
400
|
+
function buildKiloCommandFile() {
|
|
401
|
+
return [
|
|
402
|
+
"# /swarmvault",
|
|
403
|
+
"",
|
|
404
|
+
"Use SwarmVault's graph-first workflow in the current project.",
|
|
405
|
+
"",
|
|
406
|
+
"1. If no vault exists, run `swarmvault init`.",
|
|
407
|
+
"2. Read `wiki/graph/report.md` before broad source search when it exists.",
|
|
408
|
+
"3. Prefer `swarmvault graph query`, `swarmvault graph path`, and `swarmvault graph explain` for structure questions.",
|
|
409
|
+
"4. Run `swarmvault compile` after adding or refreshing sources.",
|
|
410
|
+
""
|
|
411
|
+
].join("\n");
|
|
412
|
+
}
|
|
413
|
+
function buildKiloPluginFile() {
|
|
414
|
+
return [
|
|
415
|
+
"export default async function SwarmVaultPlugin({ project }) {",
|
|
416
|
+
" return {",
|
|
417
|
+
" name: 'swarmvault-graph-first',",
|
|
418
|
+
" async beforeToolUse(event) {",
|
|
419
|
+
" const toolName = event?.tool?.name ?? event?.toolName ?? '';",
|
|
420
|
+
" if (!['bash', 'shell', 'terminal', 'search', 'grep', 'glob'].includes(String(toolName).toLowerCase())) return;",
|
|
421
|
+
" const root = project?.root ?? process.cwd();",
|
|
422
|
+
" return {",
|
|
423
|
+
" message: `SwarmVault graph guidance: from ${root}, read wiki/graph/report.md first when it exists, or run swarmvault graph query/path/explain before broad search.`",
|
|
424
|
+
" };",
|
|
425
|
+
" }",
|
|
426
|
+
" };",
|
|
427
|
+
"}",
|
|
428
|
+
""
|
|
429
|
+
].join("\n");
|
|
430
|
+
}
|
|
360
431
|
function buildVscodeChatmodeFile() {
|
|
361
432
|
const frontmatter = YAML.stringify({
|
|
362
433
|
description: "SwarmVault graph-first workflow for VS Code Copilot Chat.",
|
|
@@ -387,10 +458,20 @@ function buildCursorRule() {
|
|
|
387
458
|
return ["---", frontmatter, "---", "", buildManagedBlock("cursor").trimEnd(), ""].join("\n");
|
|
388
459
|
}
|
|
389
460
|
function supportsAgentHook(agent) {
|
|
390
|
-
return agent === "codex" || agent === "claude" || agent === "opencode" || agent === "gemini" || agent === "copilot";
|
|
461
|
+
return agent === "codex" || agent === "claude" || agent === "opencode" || agent === "gemini" || agent === "copilot" || agent === "kilo";
|
|
462
|
+
}
|
|
463
|
+
function installScope(agent, options = {}) {
|
|
464
|
+
if (options.scope) return options.scope;
|
|
465
|
+
return agent === "hermes" ? "user" : "project";
|
|
391
466
|
}
|
|
392
|
-
function primaryTargetPathForAgent(rootDir, agent) {
|
|
467
|
+
function primaryTargetPathForAgent(rootDir, agent, options = {}) {
|
|
468
|
+
if (installScope(agent, options) === "user") {
|
|
469
|
+
if (agent === "hermes") return hermesUserSkillPath();
|
|
470
|
+
const target = userSkillTarget(agent);
|
|
471
|
+
if (target) return target;
|
|
472
|
+
}
|
|
393
473
|
switch (agent) {
|
|
474
|
+
case "kilo":
|
|
394
475
|
case "codex":
|
|
395
476
|
case "goose":
|
|
396
477
|
case "pi":
|
|
@@ -435,6 +516,8 @@ function hookScriptPathForAgent(rootDir, agent) {
|
|
|
435
516
|
return path2.join(rootDir, ".claude", "hooks", "swarmvault-graph-first.js");
|
|
436
517
|
case "opencode":
|
|
437
518
|
return path2.join(rootDir, ".opencode", "plugins", "swarmvault-graph-first.js");
|
|
519
|
+
case "kilo":
|
|
520
|
+
return path2.join(rootDir, ".kilo", "plugins", "swarmvault.js");
|
|
438
521
|
case "gemini":
|
|
439
522
|
return path2.join(rootDir, ".gemini", "hooks", "swarmvault-graph-first.js");
|
|
440
523
|
case "copilot":
|
|
@@ -451,6 +534,10 @@ function hookConfigPathForAgent(rootDir, agent) {
|
|
|
451
534
|
return path2.join(rootDir, ".claude", "settings.json");
|
|
452
535
|
case "gemini":
|
|
453
536
|
return path2.join(rootDir, ".gemini", "settings.json");
|
|
537
|
+
case "opencode":
|
|
538
|
+
return path2.join(rootDir, ".opencode", "opencode.json");
|
|
539
|
+
case "kilo":
|
|
540
|
+
return path2.join(rootDir, ".kilo", "kilo.json");
|
|
454
541
|
case "copilot":
|
|
455
542
|
return path2.join(rootDir, ".github", "hooks", "swarmvault-graph-first.json");
|
|
456
543
|
default:
|
|
@@ -458,7 +545,20 @@ function hookConfigPathForAgent(rootDir, agent) {
|
|
|
458
545
|
}
|
|
459
546
|
}
|
|
460
547
|
function targetsForAgent(rootDir, agent, options = {}) {
|
|
461
|
-
const
|
|
548
|
+
const scope = installScope(agent, options);
|
|
549
|
+
const targets = [primaryTargetPathForAgent(rootDir, agent, options)];
|
|
550
|
+
if (scope === "user") {
|
|
551
|
+
if (agent === "kilo") {
|
|
552
|
+
targets.push(kiloUserCommandPath());
|
|
553
|
+
}
|
|
554
|
+
if (agent === "hermes") {
|
|
555
|
+
targets.push(path2.join(rootDir, agentFileKinds.agents));
|
|
556
|
+
}
|
|
557
|
+
return [...new Set(targets)];
|
|
558
|
+
}
|
|
559
|
+
if (options.scope === "project") {
|
|
560
|
+
targets.push(...projectSkillTargets(rootDir, agent));
|
|
561
|
+
}
|
|
462
562
|
if (agent === "copilot") {
|
|
463
563
|
targets.push(path2.join(rootDir, agentFileKinds.agents));
|
|
464
564
|
}
|
|
@@ -477,6 +577,9 @@ function targetsForAgent(rootDir, agent, options = {}) {
|
|
|
477
577
|
if (agent === "antigravity") {
|
|
478
578
|
targets.push(path2.join(rootDir, agentFileKinds.antigravityWorkflow));
|
|
479
579
|
}
|
|
580
|
+
if (agent === "devin") {
|
|
581
|
+
targets.push(path2.join(rootDir, agentFileKinds.devinRules));
|
|
582
|
+
}
|
|
480
583
|
if (options.hook && supportsAgentHook(agent)) {
|
|
481
584
|
const configPath = hookConfigPathForAgent(rootDir, agent);
|
|
482
585
|
const scriptPath = hookScriptPathForAgent(rootDir, agent);
|
|
@@ -557,6 +660,85 @@ async function readJsonWithWarnings(filePath, fallback, label) {
|
|
|
557
660
|
};
|
|
558
661
|
}
|
|
559
662
|
}
|
|
663
|
+
function stripJsonComments(source) {
|
|
664
|
+
let output = "";
|
|
665
|
+
let inString = false;
|
|
666
|
+
let escaped = false;
|
|
667
|
+
let inLineComment = false;
|
|
668
|
+
let inBlockComment = false;
|
|
669
|
+
for (let index = 0; index < source.length; index += 1) {
|
|
670
|
+
const current = source[index] ?? "";
|
|
671
|
+
const next = source[index + 1] ?? "";
|
|
672
|
+
if (inLineComment) {
|
|
673
|
+
if (current === "\n" || current === "\r") {
|
|
674
|
+
inLineComment = false;
|
|
675
|
+
output += current;
|
|
676
|
+
}
|
|
677
|
+
continue;
|
|
678
|
+
}
|
|
679
|
+
if (inBlockComment) {
|
|
680
|
+
if (current === "*" && next === "/") {
|
|
681
|
+
inBlockComment = false;
|
|
682
|
+
index += 1;
|
|
683
|
+
} else if (current === "\n" || current === "\r") {
|
|
684
|
+
output += current;
|
|
685
|
+
}
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
if (inString) {
|
|
689
|
+
output += current;
|
|
690
|
+
if (escaped) {
|
|
691
|
+
escaped = false;
|
|
692
|
+
} else if (current === "\\") {
|
|
693
|
+
escaped = true;
|
|
694
|
+
} else if (current === '"') {
|
|
695
|
+
inString = false;
|
|
696
|
+
}
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
699
|
+
if (current === '"') {
|
|
700
|
+
inString = true;
|
|
701
|
+
output += current;
|
|
702
|
+
continue;
|
|
703
|
+
}
|
|
704
|
+
if (current === "/" && next === "/") {
|
|
705
|
+
inLineComment = true;
|
|
706
|
+
index += 1;
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
709
|
+
if (current === "/" && next === "*") {
|
|
710
|
+
inBlockComment = true;
|
|
711
|
+
index += 1;
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
output += current;
|
|
715
|
+
}
|
|
716
|
+
return output;
|
|
717
|
+
}
|
|
718
|
+
async function readJsonOrJsoncWithWarnings(jsonPath, jsoncPath, fallback, label) {
|
|
719
|
+
if (await fileExists(jsonPath)) {
|
|
720
|
+
return readJsonWithWarnings(jsonPath, fallback, label);
|
|
721
|
+
}
|
|
722
|
+
if (!await fileExists(jsoncPath)) {
|
|
723
|
+
return { data: fallback, warnings: [] };
|
|
724
|
+
}
|
|
725
|
+
try {
|
|
726
|
+
const parsed = JSON.parse(stripJsonComments(await fs2.readFile(jsoncPath, "utf8")));
|
|
727
|
+
return { data: parsed, warnings: [] };
|
|
728
|
+
} catch {
|
|
729
|
+
return {
|
|
730
|
+
data: fallback,
|
|
731
|
+
warnings: [`Could not parse ${label}. Left the existing file unchanged.`]
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function withPluginEntry(config, pluginEntry) {
|
|
736
|
+
const existing = Array.isArray(config.plugins) ? config.plugins.filter((entry) => typeof entry === "string") : [];
|
|
737
|
+
return {
|
|
738
|
+
...config,
|
|
739
|
+
plugins: existing.includes(pluginEntry) ? existing : [...existing, pluginEntry]
|
|
740
|
+
};
|
|
741
|
+
}
|
|
560
742
|
async function installClaudeHook(rootDir) {
|
|
561
743
|
const settingsPath = path2.join(rootDir, ".claude", "settings.json");
|
|
562
744
|
const scriptPath = path2.join(rootDir, ".claude", "hooks", "swarmvault-graph-first.js");
|
|
@@ -724,8 +906,33 @@ async function installCopilotHook(rootDir) {
|
|
|
724
906
|
}
|
|
725
907
|
async function installOpenCodeHook(rootDir) {
|
|
726
908
|
const pluginPath = path2.join(rootDir, ".opencode", "plugins", "swarmvault-graph-first.js");
|
|
909
|
+
const configPath = path2.join(rootDir, ".opencode", "opencode.json");
|
|
727
910
|
await writeOwnedFile(pluginPath, await readBuiltHook("opencode.js"));
|
|
728
|
-
|
|
911
|
+
const { data: config, warnings } = await readJsonWithWarnings(configPath, {}, ".opencode/opencode.json");
|
|
912
|
+
if (warnings.length > 0 && await fileExists(configPath)) {
|
|
913
|
+
return { paths: [pluginPath, configPath], warnings };
|
|
914
|
+
}
|
|
915
|
+
await writeOwnedFile(configPath, `${JSON.stringify(withPluginEntry(config, "./plugins/swarmvault-graph-first.js"), null, 2)}
|
|
916
|
+
`);
|
|
917
|
+
return { paths: [pluginPath, configPath], warnings: [] };
|
|
918
|
+
}
|
|
919
|
+
async function installKiloHook(rootDir) {
|
|
920
|
+
const pluginPath = path2.join(rootDir, ".kilo", "plugins", "swarmvault.js");
|
|
921
|
+
const configPath = path2.join(rootDir, ".kilo", "kilo.json");
|
|
922
|
+
const jsoncPath = path2.join(rootDir, ".kilo", "kilo.jsonc");
|
|
923
|
+
await writeOwnedFile(pluginPath, buildKiloPluginFile());
|
|
924
|
+
const { data: config, warnings } = await readJsonOrJsoncWithWarnings(
|
|
925
|
+
configPath,
|
|
926
|
+
jsoncPath,
|
|
927
|
+
{},
|
|
928
|
+
".kilo/kilo.json or .kilo/kilo.jsonc"
|
|
929
|
+
);
|
|
930
|
+
if (warnings.length > 0 && (await fileExists(configPath) || await fileExists(jsoncPath))) {
|
|
931
|
+
return { paths: [pluginPath, configPath], warnings };
|
|
932
|
+
}
|
|
933
|
+
await writeOwnedFile(configPath, `${JSON.stringify(withPluginEntry(config, "./plugins/swarmvault.js"), null, 2)}
|
|
934
|
+
`);
|
|
935
|
+
return { paths: [pluginPath, configPath], warnings: [] };
|
|
729
936
|
}
|
|
730
937
|
function stableKeyForAgent(rootDir, agent) {
|
|
731
938
|
if (agent === "codex" || agent === "goose" || agent === "pi") {
|
|
@@ -735,9 +942,28 @@ function stableKeyForAgent(rootDir, agent) {
|
|
|
735
942
|
}
|
|
736
943
|
async function installAgent(rootDir, agent, options = {}) {
|
|
737
944
|
await initWorkspace(rootDir);
|
|
738
|
-
const
|
|
945
|
+
const scope = installScope(agent, options);
|
|
946
|
+
const target = primaryTargetPathForAgent(rootDir, agent, options);
|
|
739
947
|
const warnings = [];
|
|
948
|
+
if (scope === "user") {
|
|
949
|
+
if (agent === "hermes") {
|
|
950
|
+
await upsertManagedBlock(path2.join(rootDir, agentFileKinds.agents), buildManagedBlock("agents"));
|
|
951
|
+
await writeOwnedFile(hermesUserSkillPath(), buildStandaloneSkillFile());
|
|
952
|
+
} else {
|
|
953
|
+
const userTarget = userSkillTarget(agent);
|
|
954
|
+
if (!userTarget) {
|
|
955
|
+
throw new Error(`User-scope install is not supported for agent ${String(agent)}`);
|
|
956
|
+
}
|
|
957
|
+
await writeOwnedFile(userTarget, buildStandaloneSkillFile());
|
|
958
|
+
if (agent === "kilo") {
|
|
959
|
+
await writeOwnedFile(kiloUserCommandPath(), buildKiloCommandFile());
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
const targets2 = targetsForAgent(rootDir, agent, options);
|
|
963
|
+
return warnings.length > 0 ? { agent, target, targets: targets2, warnings } : { agent, target, targets: targets2 };
|
|
964
|
+
}
|
|
740
965
|
switch (agent) {
|
|
966
|
+
case "kilo":
|
|
741
967
|
case "codex":
|
|
742
968
|
case "goose":
|
|
743
969
|
case "pi":
|
|
@@ -798,6 +1024,14 @@ async function installAgent(rootDir, agent, options = {}) {
|
|
|
798
1024
|
const aiderResult = await mergeAiderConfig(rootDir);
|
|
799
1025
|
warnings.push(...aiderResult.warnings);
|
|
800
1026
|
}
|
|
1027
|
+
if (options.scope === "project") {
|
|
1028
|
+
for (const skillTarget of projectSkillTargets(rootDir, agent)) {
|
|
1029
|
+
await writeOwnedFile(skillTarget, buildStandaloneSkillFile());
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
if (agent === "devin") {
|
|
1033
|
+
await writeOwnedFile(path2.join(rootDir, agentFileKinds.devinRules), buildManagedBlock("devinRules"));
|
|
1034
|
+
}
|
|
801
1035
|
if (options.hook && supportsAgentHook(agent)) {
|
|
802
1036
|
if (agent === "codex") {
|
|
803
1037
|
const result = await installCodexHook(rootDir);
|
|
@@ -811,6 +1045,10 @@ async function installAgent(rootDir, agent, options = {}) {
|
|
|
811
1045
|
const result = await installOpenCodeHook(rootDir);
|
|
812
1046
|
warnings.push(...result.warnings);
|
|
813
1047
|
}
|
|
1048
|
+
if (agent === "kilo") {
|
|
1049
|
+
const result = await installKiloHook(rootDir);
|
|
1050
|
+
warnings.push(...result.warnings);
|
|
1051
|
+
}
|
|
814
1052
|
if (agent === "gemini") {
|
|
815
1053
|
const result = await installGeminiHook(rootDir);
|
|
816
1054
|
warnings.push(...result.warnings);
|
|
@@ -823,6 +1061,24 @@ async function installAgent(rootDir, agent, options = {}) {
|
|
|
823
1061
|
const targets = targetsForAgent(rootDir, agent, options);
|
|
824
1062
|
return warnings.length > 0 ? { agent, target, targets, warnings } : { agent, target, targets };
|
|
825
1063
|
}
|
|
1064
|
+
async function getAgentInstallStatus(rootDir, agent, options = {}) {
|
|
1065
|
+
const target = primaryTargetPathForAgent(rootDir, agent, options);
|
|
1066
|
+
const targets = targetsForAgent(rootDir, agent, options);
|
|
1067
|
+
const targetStatuses = await Promise.all(
|
|
1068
|
+
targets.map(async (targetPath) => ({
|
|
1069
|
+
path: targetPath,
|
|
1070
|
+
exists: await fileExists(targetPath)
|
|
1071
|
+
}))
|
|
1072
|
+
);
|
|
1073
|
+
return {
|
|
1074
|
+
agent,
|
|
1075
|
+
scope: installScope(agent, options),
|
|
1076
|
+
hook: options.hook ?? false,
|
|
1077
|
+
target,
|
|
1078
|
+
targets: targetStatuses,
|
|
1079
|
+
installed: targetStatuses.length > 0 && targetStatuses.every((entry) => entry.exists)
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
826
1082
|
async function installConfiguredAgents(rootDir) {
|
|
827
1083
|
const { config } = await initWorkspace(rootDir);
|
|
828
1084
|
const dedupedAgents = /* @__PURE__ */ new Map();
|
|
@@ -15779,6 +16035,79 @@ function graphDiff(oldGraph, newGraph) {
|
|
|
15779
16035
|
const summary = parts.length ? parts.join("; ") : "No changes";
|
|
15780
16036
|
return { addedNodes, removedNodes, addedEdges, removedEdges, addedPages, removedPages, summary };
|
|
15781
16037
|
}
|
|
16038
|
+
function findGraphCycles(graph, options = {}) {
|
|
16039
|
+
const relationFilter = options.relations?.length ? new Set(options.relations) : null;
|
|
16040
|
+
const limit = Math.max(1, Math.min(options.limit ?? 25, 250));
|
|
16041
|
+
const maxDepth = Math.max(2, Math.min(options.maxDepth ?? 25, 100));
|
|
16042
|
+
const nodes = nodeById(graph);
|
|
16043
|
+
const adjacency = /* @__PURE__ */ new Map();
|
|
16044
|
+
for (const edge of graph.edges) {
|
|
16045
|
+
if (relationFilter && !relationFilter.has(edge.relation)) {
|
|
16046
|
+
continue;
|
|
16047
|
+
}
|
|
16048
|
+
if (!nodes.has(edge.source) || !nodes.has(edge.target)) {
|
|
16049
|
+
continue;
|
|
16050
|
+
}
|
|
16051
|
+
const outgoing = adjacency.get(edge.source) ?? [];
|
|
16052
|
+
outgoing.push(edge);
|
|
16053
|
+
adjacency.set(edge.source, outgoing);
|
|
16054
|
+
}
|
|
16055
|
+
for (const [nodeId, edges] of adjacency.entries()) {
|
|
16056
|
+
adjacency.set(
|
|
16057
|
+
nodeId,
|
|
16058
|
+
edges.sort(
|
|
16059
|
+
(left, right) => left.target.localeCompare(right.target) || left.relation.localeCompare(right.relation) || left.id.localeCompare(right.id)
|
|
16060
|
+
)
|
|
16061
|
+
);
|
|
16062
|
+
}
|
|
16063
|
+
const cycles = [];
|
|
16064
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
16065
|
+
const sortedNodeIds = [...nodes.keys()].sort((left, right) => left.localeCompare(right));
|
|
16066
|
+
const addCycle = (nodeIds, edges) => {
|
|
16067
|
+
const key = nodeIds.join(">");
|
|
16068
|
+
if (seenKeys.has(key)) {
|
|
16069
|
+
return;
|
|
16070
|
+
}
|
|
16071
|
+
seenKeys.add(key);
|
|
16072
|
+
cycles.push({
|
|
16073
|
+
nodeIds,
|
|
16074
|
+
labels: nodeIds.map((nodeId) => nodes.get(nodeId)?.label ?? nodeId),
|
|
16075
|
+
edgeIds: edges.map((edge) => edge.id),
|
|
16076
|
+
relations: edges.map((edge) => edge.relation)
|
|
16077
|
+
});
|
|
16078
|
+
};
|
|
16079
|
+
const visit = (startId, currentId, pathNodeIds, pathEdges, visited) => {
|
|
16080
|
+
if (cycles.length >= limit || pathNodeIds.length > maxDepth) {
|
|
16081
|
+
return;
|
|
16082
|
+
}
|
|
16083
|
+
for (const edge of adjacency.get(currentId) ?? []) {
|
|
16084
|
+
const nextId = edge.target;
|
|
16085
|
+
if (nextId === startId && pathNodeIds.length > 1) {
|
|
16086
|
+
addCycle([...pathNodeIds], [...pathEdges, edge]);
|
|
16087
|
+
if (cycles.length >= limit) return;
|
|
16088
|
+
continue;
|
|
16089
|
+
}
|
|
16090
|
+
if (visited.has(nextId) || nextId.localeCompare(startId) < 0) {
|
|
16091
|
+
continue;
|
|
16092
|
+
}
|
|
16093
|
+
visited.add(nextId);
|
|
16094
|
+
visit(startId, nextId, [...pathNodeIds, nextId], [...pathEdges, edge], visited);
|
|
16095
|
+
visited.delete(nextId);
|
|
16096
|
+
if (cycles.length >= limit) return;
|
|
16097
|
+
}
|
|
16098
|
+
};
|
|
16099
|
+
for (const startId of sortedNodeIds) {
|
|
16100
|
+
visit(startId, startId, [startId], [], /* @__PURE__ */ new Set([startId]));
|
|
16101
|
+
if (cycles.length >= limit) {
|
|
16102
|
+
break;
|
|
16103
|
+
}
|
|
16104
|
+
}
|
|
16105
|
+
cycles.sort(
|
|
16106
|
+
(left, right) => left.labels.join(" > ").localeCompare(right.labels.join(" > ")) || left.nodeIds.join(">").localeCompare(right.nodeIds.join(">"))
|
|
16107
|
+
);
|
|
16108
|
+
const summary = cycles.length ? `Found ${cycles.length} cycle${cycles.length === 1 ? "" : "s"}${cycles.length >= limit ? ` (limited to ${limit})` : ""}.` : "No cycles found.";
|
|
16109
|
+
return { cycles, limit, summary };
|
|
16110
|
+
}
|
|
15782
16111
|
function blastRadius(graph, target, options) {
|
|
15783
16112
|
const maxDepth = Math.max(1, Math.min(options?.maxDepth ?? 3, 10));
|
|
15784
16113
|
const resolved = resolveNode(graph, target);
|
|
@@ -20150,7 +20479,7 @@ async function resolveImageGenerationProvider(rootDir) {
|
|
|
20150
20479
|
if (!providerConfig) {
|
|
20151
20480
|
throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
|
|
20152
20481
|
}
|
|
20153
|
-
const { createProvider: createProvider2 } = await import("./registry-
|
|
20482
|
+
const { createProvider: createProvider2 } = await import("./registry-ZZ6NESFD.js");
|
|
20154
20483
|
return createProvider2(preferredProviderId, providerConfig, rootDir);
|
|
20155
20484
|
}
|
|
20156
20485
|
async function generateOutputArtifacts(rootDir, input) {
|
|
@@ -26120,13 +26449,13 @@ async function buildContextPack(rootDir, options) {
|
|
|
26120
26449
|
}
|
|
26121
26450
|
}
|
|
26122
26451
|
}
|
|
26123
|
-
const memorySummaries = await import("./memory-
|
|
26452
|
+
const memorySummaries = await import("./memory-4BDKH4Y2.js").then(({ listMemoryTasks: listMemoryTasks2 }) => listMemoryTasks2(rootDir)).catch(() => []);
|
|
26124
26453
|
const memorySummaryIds = uniqueStrings5([
|
|
26125
26454
|
...options.memoryTaskId ? [options.memoryTaskId] : [],
|
|
26126
26455
|
...memorySummaries.slice(0, 20).map((summary) => summary.id)
|
|
26127
26456
|
]);
|
|
26128
26457
|
if (memorySummaryIds.length) {
|
|
26129
|
-
const { readMemoryTask: readMemoryTask2 } = await import("./memory-
|
|
26458
|
+
const { readMemoryTask: readMemoryTask2 } = await import("./memory-4BDKH4Y2.js");
|
|
26130
26459
|
for (const taskId of memorySummaryIds) {
|
|
26131
26460
|
const task = await readMemoryTask2(rootDir, taskId).catch(() => null);
|
|
26132
26461
|
if (!task) {
|
|
@@ -26205,7 +26534,7 @@ async function buildContextPack(rootDir, options) {
|
|
|
26205
26534
|
]
|
|
26206
26535
|
});
|
|
26207
26536
|
if (options.memoryTaskId) {
|
|
26208
|
-
const { updateMemoryTask: updateMemoryTask2 } = await import("./memory-
|
|
26537
|
+
const { updateMemoryTask: updateMemoryTask2 } = await import("./memory-4BDKH4Y2.js");
|
|
26209
26538
|
await updateMemoryTask2(rootDir, options.memoryTaskId, { contextPackId: pack.id });
|
|
26210
26539
|
}
|
|
26211
26540
|
return {
|
|
@@ -26879,6 +27208,7 @@ function estimateMemoryTaskTokens(task) {
|
|
|
26879
27208
|
|
|
26880
27209
|
export {
|
|
26881
27210
|
installAgent,
|
|
27211
|
+
getAgentInstallStatus,
|
|
26882
27212
|
installConfiguredAgents,
|
|
26883
27213
|
DEFAULT_PROMOTION_CONFIG,
|
|
26884
27214
|
evaluateCandidateForPromotion,
|
|
@@ -26920,6 +27250,7 @@ export {
|
|
|
26920
27250
|
graphStats,
|
|
26921
27251
|
validateGraphArtifact,
|
|
26922
27252
|
graphDiff,
|
|
27253
|
+
findGraphCycles,
|
|
26923
27254
|
blastRadius,
|
|
26924
27255
|
LARGE_REPO_NODE_THRESHOLD,
|
|
26925
27256
|
resolveLargeRepoDefaults,
|