@swarmvaultai/engine 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-BTWPJEP2.js +1421 -0
- package/dist/chunk-CG67P2HB.js +1420 -0
- package/dist/chunk-RSQRF4FV.js +1424 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +322 -34
- package/dist/registry-2QC3VN7M.js +12 -0
- package/dist/registry-JQYQOZYN.js +12 -0
- package/dist/registry-JR5WY22P.js +12 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,6 +43,10 @@ declare const agentTypeSchema: z.ZodEnum<{
|
|
|
43
43
|
trae: "trae";
|
|
44
44
|
claw: "claw";
|
|
45
45
|
droid: "droid";
|
|
46
|
+
kiro: "kiro";
|
|
47
|
+
hermes: "hermes";
|
|
48
|
+
antigravity: "antigravity";
|
|
49
|
+
vscode: "vscode";
|
|
46
50
|
}>;
|
|
47
51
|
type AgentType = z.infer<typeof agentTypeSchema>;
|
|
48
52
|
type PageKind = "index" | "source" | "module" | "concept" | "entity" | "output" | "insight" | "graph_report" | "community_summary";
|
|
@@ -113,6 +117,13 @@ interface AudioTranscriptionRequest {
|
|
|
113
117
|
bytes: Buffer;
|
|
114
118
|
fileName?: string;
|
|
115
119
|
language?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Optional one-sentence domain hint derived from the vault's top god nodes.
|
|
122
|
+
* Providers that accept a prompt (e.g. Whisper) can pass it through to bias
|
|
123
|
+
* transcription toward in-corpus terminology. Providers without prompt
|
|
124
|
+
* support ignore it safely.
|
|
125
|
+
*/
|
|
126
|
+
corpusHint?: string;
|
|
116
127
|
}
|
|
117
128
|
interface AudioTranscriptionResponse {
|
|
118
129
|
text: string;
|
|
@@ -534,6 +545,8 @@ interface GraphNode {
|
|
|
534
545
|
id: string;
|
|
535
546
|
type: "source" | "concept" | "entity" | "module" | "symbol" | "rationale";
|
|
536
547
|
label: string;
|
|
548
|
+
/** Lowercased NFKD-normalized label (diacritic-insensitive) for lexical matching. */
|
|
549
|
+
normLabel?: string;
|
|
537
550
|
pageId?: string;
|
|
538
551
|
freshness?: Freshness;
|
|
539
552
|
confidence?: number;
|
|
@@ -803,6 +816,7 @@ interface CompileOptions {
|
|
|
803
816
|
interface InitOptions {
|
|
804
817
|
obsidian?: boolean;
|
|
805
818
|
profile?: string;
|
|
819
|
+
lite?: boolean;
|
|
806
820
|
}
|
|
807
821
|
interface CompileResult {
|
|
808
822
|
graphPath: string;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
PRIMARY_SCHEMA_FILENAME,
|
|
2
3
|
appendJsonLine,
|
|
3
4
|
assertProviderCapability,
|
|
4
5
|
createProvider,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
uniqueBy,
|
|
23
24
|
writeFileIfChanged,
|
|
24
25
|
writeJsonFile
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-RSQRF4FV.js";
|
|
26
27
|
import {
|
|
27
28
|
estimatePageTokens,
|
|
28
29
|
estimateTokens,
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
// src/agents.ts
|
|
33
34
|
import crypto from "crypto";
|
|
34
35
|
import fs from "fs/promises";
|
|
36
|
+
import os from "os";
|
|
35
37
|
import path from "path";
|
|
36
38
|
import { fileURLToPath } from "url";
|
|
37
39
|
import YAML from "yaml";
|
|
@@ -83,23 +85,128 @@ var agentFileKinds = {
|
|
|
83
85
|
copilot: ".github/copilot-instructions.md",
|
|
84
86
|
trae: ".trae/rules/swarmvault.md",
|
|
85
87
|
claw: ".claw/skills/swarmvault/SKILL.md",
|
|
86
|
-
droid: ".factory/rules/swarmvault.md"
|
|
88
|
+
droid: ".factory/rules/swarmvault.md",
|
|
89
|
+
kiro: ".kiro/skills/swarmvault/SKILL.md",
|
|
90
|
+
kiroSteering: ".kiro/steering/swarmvault.md",
|
|
91
|
+
antigravityRules: ".agent/rules/swarmvault.md",
|
|
92
|
+
antigravityWorkflow: ".agent/workflows/swarmvault.md",
|
|
93
|
+
vscode: ".github/chatmodes/swarmvault.chatmode.md"
|
|
87
94
|
};
|
|
95
|
+
var hermesUserSkillRelative = path.join(".hermes", "skills", "swarmvault", "SKILL.md");
|
|
96
|
+
function hermesUserSkillPath() {
|
|
97
|
+
return path.join(os.homedir(), hermesUserSkillRelative);
|
|
98
|
+
}
|
|
99
|
+
var SWARMVAULT_RULE_BULLETS = [
|
|
100
|
+
"- Read `swarmvault.schema.md` before compile or query style work. It is the canonical schema path.",
|
|
101
|
+
"- Treat `raw/` as immutable source input.",
|
|
102
|
+
"- Treat `wiki/` as generated markdown owned by the agent and compiler workflow.",
|
|
103
|
+
"- Read `wiki/graph/report.md` before broad file searching when it exists; otherwise start with `wiki/index.md`.",
|
|
104
|
+
"- For graph questions, prefer `swarmvault graph query`, `swarmvault graph path`, and `swarmvault graph explain` before broad grep/glob searching.",
|
|
105
|
+
"- Preserve frontmatter fields including `page_id`, `source_ids`, `node_ids`, `freshness`, and `source_hashes`.",
|
|
106
|
+
"- Save high-value answers back into `wiki/outputs/` instead of leaving them only in chat.",
|
|
107
|
+
"- Prefer `swarmvault ingest`, `swarmvault compile`, `swarmvault query`, and `swarmvault lint` for SwarmVault maintenance tasks."
|
|
108
|
+
];
|
|
88
109
|
function buildManagedBlock(target) {
|
|
89
110
|
const heading = target === "aider" ? "# SwarmVault Conventions" : target === "copilot" ? "# SwarmVault Repository Instructions" : "# SwarmVault Rules";
|
|
111
|
+
return [managedStart, heading, "", ...SWARMVAULT_RULE_BULLETS, managedEnd, ""].join("\n");
|
|
112
|
+
}
|
|
113
|
+
function buildSkillFrontmatter() {
|
|
114
|
+
const frontmatter = YAML.stringify({
|
|
115
|
+
name: "swarmvault",
|
|
116
|
+
description: "SwarmVault graph-first workflow. Use to read the compiled wiki and query the knowledge graph before broad file search."
|
|
117
|
+
}).trimEnd();
|
|
118
|
+
return ["---", frontmatter, "---"].join("\n");
|
|
119
|
+
}
|
|
120
|
+
function buildSkillBody() {
|
|
90
121
|
return [
|
|
91
|
-
|
|
92
|
-
|
|
122
|
+
"# SwarmVault",
|
|
123
|
+
"",
|
|
124
|
+
"SwarmVault compiles curated sources in `raw/` into a queryable wiki in `wiki/` and a knowledge graph in `state/graph.json`.",
|
|
125
|
+
"",
|
|
126
|
+
"## Rules",
|
|
127
|
+
"",
|
|
128
|
+
...SWARMVAULT_RULE_BULLETS,
|
|
93
129
|
"",
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"-
|
|
97
|
-
"-
|
|
98
|
-
|
|
99
|
-
"-
|
|
100
|
-
"-
|
|
101
|
-
"
|
|
102
|
-
|
|
130
|
+
"## Entry points",
|
|
131
|
+
"",
|
|
132
|
+
"- `swarmvault ingest <path>` \u2014 register a new source",
|
|
133
|
+
"- `swarmvault compile` \u2014 refresh wiki pages and graph",
|
|
134
|
+
'- `swarmvault query "<question>"` \u2014 save-first multi-step query',
|
|
135
|
+
"- `swarmvault graph query|path|explain` \u2014 deterministic graph traversal",
|
|
136
|
+
"- `swarmvault lint` \u2014 wiki health and contradiction checks",
|
|
137
|
+
""
|
|
138
|
+
].join("\n");
|
|
139
|
+
}
|
|
140
|
+
function buildStandaloneSkillFile() {
|
|
141
|
+
return `${buildSkillFrontmatter()}
|
|
142
|
+
|
|
143
|
+
${buildSkillBody()}`;
|
|
144
|
+
}
|
|
145
|
+
function buildKiroSteeringFile() {
|
|
146
|
+
const frontmatter = YAML.stringify({
|
|
147
|
+
inclusion: "always",
|
|
148
|
+
description: "Always-on SwarmVault rules."
|
|
149
|
+
}).trimEnd();
|
|
150
|
+
return ["---", frontmatter, "---", "", "# SwarmVault Rules", "", ...SWARMVAULT_RULE_BULLETS, ""].join("\n");
|
|
151
|
+
}
|
|
152
|
+
function buildAntigravityRulesFile() {
|
|
153
|
+
const frontmatter = YAML.stringify({
|
|
154
|
+
alwaysApply: true,
|
|
155
|
+
description: "SwarmVault graph-first repository rules."
|
|
156
|
+
}).trimEnd();
|
|
157
|
+
return [
|
|
158
|
+
"---",
|
|
159
|
+
frontmatter,
|
|
160
|
+
"---",
|
|
161
|
+
"",
|
|
162
|
+
"# SwarmVault Rules",
|
|
163
|
+
"",
|
|
164
|
+
...SWARMVAULT_RULE_BULLETS,
|
|
165
|
+
"",
|
|
166
|
+
"> MCP navigation hint: SwarmVault exposes a local MCP server via `swarmvault mcp`. Wire it into your Antigravity MCP config to query the graph without shelling out."
|
|
167
|
+
].join("\n");
|
|
168
|
+
}
|
|
169
|
+
function buildAntigravityWorkflowFile() {
|
|
170
|
+
const frontmatter = YAML.stringify({
|
|
171
|
+
command: "swarmvault",
|
|
172
|
+
description: "Compile, query, and lint the SwarmVault vault."
|
|
173
|
+
}).trimEnd();
|
|
174
|
+
return [
|
|
175
|
+
"---",
|
|
176
|
+
frontmatter,
|
|
177
|
+
"---",
|
|
178
|
+
"",
|
|
179
|
+
"# /swarmvault",
|
|
180
|
+
"",
|
|
181
|
+
"Run SwarmVault against the current directory.",
|
|
182
|
+
"",
|
|
183
|
+
"## Steps",
|
|
184
|
+
"",
|
|
185
|
+
"1. If no vault exists, run `swarmvault init`.",
|
|
186
|
+
"2. For new sources, run `swarmvault ingest <path>`.",
|
|
187
|
+
"3. Run `swarmvault compile` to refresh the wiki and graph.",
|
|
188
|
+
"4. For follow-up questions, prefer `swarmvault query`, `swarmvault graph query`, `swarmvault graph path`, `swarmvault graph explain`.",
|
|
189
|
+
"5. Save high-value answers to `wiki/outputs/`.",
|
|
190
|
+
""
|
|
191
|
+
].join("\n");
|
|
192
|
+
}
|
|
193
|
+
function buildVscodeChatmodeFile() {
|
|
194
|
+
const frontmatter = YAML.stringify({
|
|
195
|
+
description: "SwarmVault graph-first workflow for VS Code Copilot Chat.",
|
|
196
|
+
tools: ["codebase", "terminal"]
|
|
197
|
+
}).trimEnd();
|
|
198
|
+
return [
|
|
199
|
+
"---",
|
|
200
|
+
frontmatter,
|
|
201
|
+
"---",
|
|
202
|
+
"",
|
|
203
|
+
"# SwarmVault mode",
|
|
204
|
+
"",
|
|
205
|
+
"You are working inside a SwarmVault vault. Follow these rules before other actions:",
|
|
206
|
+
"",
|
|
207
|
+
...SWARMVAULT_RULE_BULLETS,
|
|
208
|
+
"",
|
|
209
|
+
"Use the terminal tool to run `swarmvault` commands. Prefer graph queries over broad grep/glob.",
|
|
103
210
|
""
|
|
104
211
|
].join("\n");
|
|
105
212
|
}
|
|
@@ -136,6 +243,14 @@ function primaryTargetPathForAgent(rootDir, agent) {
|
|
|
136
243
|
return path.join(rootDir, agentFileKinds.claw);
|
|
137
244
|
case "droid":
|
|
138
245
|
return path.join(rootDir, agentFileKinds.droid);
|
|
246
|
+
case "kiro":
|
|
247
|
+
return path.join(rootDir, agentFileKinds.kiro);
|
|
248
|
+
case "hermes":
|
|
249
|
+
return hermesUserSkillPath();
|
|
250
|
+
case "antigravity":
|
|
251
|
+
return path.join(rootDir, agentFileKinds.antigravityRules);
|
|
252
|
+
case "vscode":
|
|
253
|
+
return path.join(rootDir, agentFileKinds.vscode);
|
|
139
254
|
default:
|
|
140
255
|
throw new Error(`Unsupported agent ${String(agent)}`);
|
|
141
256
|
}
|
|
@@ -174,6 +289,15 @@ function targetsForAgent(rootDir, agent, options = {}) {
|
|
|
174
289
|
if (agent === "aider") {
|
|
175
290
|
targets.push(path.join(rootDir, ".aider.conf.yml"));
|
|
176
291
|
}
|
|
292
|
+
if (agent === "kiro") {
|
|
293
|
+
targets.push(path.join(rootDir, agentFileKinds.kiroSteering));
|
|
294
|
+
}
|
|
295
|
+
if (agent === "hermes") {
|
|
296
|
+
targets.push(path.join(rootDir, agentFileKinds.agents));
|
|
297
|
+
}
|
|
298
|
+
if (agent === "antigravity") {
|
|
299
|
+
targets.push(path.join(rootDir, agentFileKinds.antigravityWorkflow));
|
|
300
|
+
}
|
|
177
301
|
if (options.hook && supportsAgentHook(agent)) {
|
|
178
302
|
const configPath = hookConfigPathForAgent(rootDir, agent);
|
|
179
303
|
const scriptPath = hookScriptPathForAgent(rootDir, agent);
|
|
@@ -409,6 +533,21 @@ async function installAgent(rootDir, agent, options = {}) {
|
|
|
409
533
|
case "droid":
|
|
410
534
|
await writeOwnedFile(target, buildManagedBlock("droid"));
|
|
411
535
|
break;
|
|
536
|
+
case "kiro":
|
|
537
|
+
await writeOwnedFile(target, buildStandaloneSkillFile());
|
|
538
|
+
await writeOwnedFile(path.join(rootDir, agentFileKinds.kiroSteering), buildKiroSteeringFile());
|
|
539
|
+
break;
|
|
540
|
+
case "hermes":
|
|
541
|
+
await upsertManagedBlock(path.join(rootDir, agentFileKinds.agents), buildManagedBlock("agents"));
|
|
542
|
+
await writeOwnedFile(hermesUserSkillPath(), buildStandaloneSkillFile());
|
|
543
|
+
break;
|
|
544
|
+
case "antigravity":
|
|
545
|
+
await writeOwnedFile(target, buildAntigravityRulesFile());
|
|
546
|
+
await writeOwnedFile(path.join(rootDir, agentFileKinds.antigravityWorkflow), buildAntigravityWorkflowFile());
|
|
547
|
+
break;
|
|
548
|
+
case "vscode":
|
|
549
|
+
await writeOwnedFile(target, buildVscodeChatmodeFile());
|
|
550
|
+
break;
|
|
412
551
|
default:
|
|
413
552
|
throw new Error(`Unsupported agent ${String(agent)}`);
|
|
414
553
|
}
|
|
@@ -2624,7 +2763,10 @@ async function pushGraphNeo4j(rootDir, options = {}) {
|
|
|
2624
2763
|
|
|
2625
2764
|
// src/graph-tools.ts
|
|
2626
2765
|
function normalizeTarget(value) {
|
|
2627
|
-
return normalizeWhitespace(value).toLowerCase();
|
|
2766
|
+
return normalizeWhitespace(value).normalize("NFKD").replace(/\p{Mn}+/gu, "").toLowerCase();
|
|
2767
|
+
}
|
|
2768
|
+
function computeNormLabel(label) {
|
|
2769
|
+
return normalizeTarget(label);
|
|
2628
2770
|
}
|
|
2629
2771
|
function nodeById(graph) {
|
|
2630
2772
|
return new Map(graph.nodes.map((node) => [node.id, node]));
|
|
@@ -8567,7 +8709,7 @@ async function analyzeCodeSource(manifest, extractedText, schemaHash) {
|
|
|
8567
8709
|
|
|
8568
8710
|
// src/extraction.ts
|
|
8569
8711
|
import fs7 from "fs/promises";
|
|
8570
|
-
import
|
|
8712
|
+
import os2 from "os";
|
|
8571
8713
|
import path7 from "path";
|
|
8572
8714
|
import { Readable } from "stream";
|
|
8573
8715
|
import { parse as parseCsvSync } from "csv-parse/sync";
|
|
@@ -8691,7 +8833,7 @@ async function materializeAttachmentPath(input) {
|
|
|
8691
8833
|
if (!input.bytes) {
|
|
8692
8834
|
throw new Error("Image extraction requires a file path or bytes.");
|
|
8693
8835
|
}
|
|
8694
|
-
const tempDir = await fs7.mkdtemp(path7.join(
|
|
8836
|
+
const tempDir = await fs7.mkdtemp(path7.join(os2.tmpdir(), "swarmvault-image-extract-"));
|
|
8695
8837
|
const extension = input.mimeType.split("/")[1]?.split("+")[0] ?? "bin";
|
|
8696
8838
|
const tempPath = path7.join(tempDir, `source.${extension}`);
|
|
8697
8839
|
await fs7.writeFile(tempPath, input.bytes);
|
|
@@ -8773,6 +8915,27 @@ async function extractImageWithVision(rootDir, input) {
|
|
|
8773
8915
|
await attachment.cleanup();
|
|
8774
8916
|
}
|
|
8775
8917
|
}
|
|
8918
|
+
async function buildCorpusHint(rootDir, maxTerms = 6) {
|
|
8919
|
+
let graphPath;
|
|
8920
|
+
try {
|
|
8921
|
+
const { paths } = await loadVaultConfig(rootDir);
|
|
8922
|
+
graphPath = paths.graphPath;
|
|
8923
|
+
} catch {
|
|
8924
|
+
return void 0;
|
|
8925
|
+
}
|
|
8926
|
+
if (!await fileExists(graphPath)) {
|
|
8927
|
+
return void 0;
|
|
8928
|
+
}
|
|
8929
|
+
const graph = await readJsonFile(graphPath);
|
|
8930
|
+
if (!graph || !Array.isArray(graph.nodes) || graph.nodes.length === 0) {
|
|
8931
|
+
return void 0;
|
|
8932
|
+
}
|
|
8933
|
+
const top = graph.nodes.filter((node) => node.type !== "source" && Boolean(node.label)).sort((left, right) => (right.degree ?? 0) - (left.degree ?? 0)).slice(0, maxTerms).map((node) => node.label.trim()).filter((label) => label.length > 0);
|
|
8934
|
+
if (top.length === 0) {
|
|
8935
|
+
return void 0;
|
|
8936
|
+
}
|
|
8937
|
+
return `This audio is likely about ${top.join(", ")}.`;
|
|
8938
|
+
}
|
|
8776
8939
|
async function extractAudioTranscription(rootDir, input) {
|
|
8777
8940
|
let provider;
|
|
8778
8941
|
try {
|
|
@@ -8793,11 +8956,13 @@ async function extractAudioTranscription(rootDir, input) {
|
|
|
8793
8956
|
}
|
|
8794
8957
|
};
|
|
8795
8958
|
}
|
|
8959
|
+
const corpusHint = input.corpusHint ?? await buildCorpusHint(rootDir);
|
|
8796
8960
|
try {
|
|
8797
8961
|
const result = await provider.transcribeAudio({
|
|
8798
8962
|
mimeType: input.mimeType,
|
|
8799
8963
|
bytes: input.bytes,
|
|
8800
|
-
fileName: input.fileName
|
|
8964
|
+
fileName: input.fileName,
|
|
8965
|
+
corpusHint
|
|
8801
8966
|
});
|
|
8802
8967
|
const metadata = {};
|
|
8803
8968
|
if (result.duration !== void 0) {
|
|
@@ -8806,6 +8971,9 @@ async function extractAudioTranscription(rootDir, input) {
|
|
|
8806
8971
|
if (result.language) {
|
|
8807
8972
|
metadata.language = result.language;
|
|
8808
8973
|
}
|
|
8974
|
+
if (corpusHint) {
|
|
8975
|
+
metadata.corpus_hint = corpusHint;
|
|
8976
|
+
}
|
|
8809
8977
|
return {
|
|
8810
8978
|
extractedText: result.text || void 0,
|
|
8811
8979
|
artifact: {
|
|
@@ -18221,7 +18389,7 @@ async function resolveImageGenerationProvider(rootDir) {
|
|
|
18221
18389
|
if (!providerConfig) {
|
|
18222
18390
|
throw new Error(`No provider configured with id "${preferredProviderId}" for task "imageProvider".`);
|
|
18223
18391
|
}
|
|
18224
|
-
const { createProvider: createProvider2 } = await import("./registry-
|
|
18392
|
+
const { createProvider: createProvider2 } = await import("./registry-JR5WY22P.js");
|
|
18225
18393
|
return createProvider2(preferredProviderId, providerConfig, rootDir);
|
|
18226
18394
|
}
|
|
18227
18395
|
async function generateOutputArtifacts(rootDir, input) {
|
|
@@ -19255,6 +19423,13 @@ function autoResolution(nodeCount, edgeCount) {
|
|
|
19255
19423
|
if (edgeCount / Math.max(1, nodeCount) < 2) return 0.8;
|
|
19256
19424
|
return 1;
|
|
19257
19425
|
}
|
|
19426
|
+
function pruneDanglingEdges(nodes, edges) {
|
|
19427
|
+
const nodeIds = new Set(nodes.map((node) => node.id));
|
|
19428
|
+
return edges.filter((edge) => nodeIds.has(edge.source) && nodeIds.has(edge.target));
|
|
19429
|
+
}
|
|
19430
|
+
function applyNormLabel(nodes) {
|
|
19431
|
+
return nodes.map((node) => node.normLabel ? node : { ...node, normLabel: computeNormLabel(node.label) });
|
|
19432
|
+
}
|
|
19258
19433
|
function deriveGraphMetrics(nodes, edges, options) {
|
|
19259
19434
|
const adjacency = /* @__PURE__ */ new Map();
|
|
19260
19435
|
const connect = (left, right) => {
|
|
@@ -19672,20 +19847,33 @@ function buildGraph(manifests, analyses, pages, sourceProjects, _codeIndex, opti
|
|
|
19672
19847
|
}
|
|
19673
19848
|
for (const symbol of analysis.code.symbols) {
|
|
19674
19849
|
for (const targetName of symbol.calls) {
|
|
19675
|
-
const
|
|
19676
|
-
if (
|
|
19850
|
+
const localTargetId = resolveLocalSymbolId(targetName);
|
|
19851
|
+
if (localTargetId && localTargetId !== symbol.id) {
|
|
19852
|
+
pushEdge({
|
|
19853
|
+
id: `${symbol.id}->${localTargetId}:calls`,
|
|
19854
|
+
source: symbol.id,
|
|
19855
|
+
target: localTargetId,
|
|
19856
|
+
relation: "calls",
|
|
19857
|
+
status: "extracted",
|
|
19858
|
+
evidenceClass: "extracted",
|
|
19859
|
+
confidence: 1,
|
|
19860
|
+
provenance: [analysis.sourceId]
|
|
19861
|
+
});
|
|
19677
19862
|
continue;
|
|
19678
19863
|
}
|
|
19679
|
-
|
|
19680
|
-
|
|
19681
|
-
|
|
19682
|
-
|
|
19683
|
-
|
|
19684
|
-
|
|
19685
|
-
|
|
19686
|
-
|
|
19687
|
-
|
|
19688
|
-
|
|
19864
|
+
const crossFileTargetId = importedSymbolIdsByName.get(targetName);
|
|
19865
|
+
if (crossFileTargetId && crossFileTargetId !== symbol.id) {
|
|
19866
|
+
pushEdge({
|
|
19867
|
+
id: `${symbol.id}->${crossFileTargetId}:calls`,
|
|
19868
|
+
source: symbol.id,
|
|
19869
|
+
target: crossFileTargetId,
|
|
19870
|
+
relation: "calls",
|
|
19871
|
+
status: "inferred",
|
|
19872
|
+
evidenceClass: "inferred",
|
|
19873
|
+
confidence: 0.8,
|
|
19874
|
+
provenance: [analysis.sourceId]
|
|
19875
|
+
});
|
|
19876
|
+
}
|
|
19689
19877
|
}
|
|
19690
19878
|
for (const targetName of symbol.extends) {
|
|
19691
19879
|
const targetId = resolveLocalSymbolId(targetName) ?? importedSymbolIdsByName.get(targetName);
|
|
@@ -19800,11 +19988,17 @@ function buildGraph(manifests, analyses, pages, sourceProjects, _codeIndex, opti
|
|
|
19800
19988
|
analyses
|
|
19801
19989
|
);
|
|
19802
19990
|
const metrics = deriveGraphMetrics(graphNodes, enriched.edges, { resolution: options?.communityResolution });
|
|
19991
|
+
const finalNodes = applyNormLabel(metrics.nodes);
|
|
19992
|
+
const finalEdges = pruneDanglingEdges(finalNodes, enriched.edges);
|
|
19993
|
+
const finalHyperedges = (enriched.hyperedges ?? []).filter((hyperedge) => {
|
|
19994
|
+
const nodeIdSet = new Set(finalNodes.map((node) => node.id));
|
|
19995
|
+
return hyperedge.nodeIds.every((id) => nodeIdSet.has(id));
|
|
19996
|
+
});
|
|
19803
19997
|
return {
|
|
19804
19998
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19805
|
-
nodes:
|
|
19806
|
-
edges:
|
|
19807
|
-
hyperedges:
|
|
19999
|
+
nodes: finalNodes,
|
|
20000
|
+
edges: finalEdges,
|
|
20001
|
+
hyperedges: finalHyperedges,
|
|
19808
20002
|
communities: metrics.communities,
|
|
19809
20003
|
sources: manifests,
|
|
19810
20004
|
pages
|
|
@@ -21656,7 +21850,101 @@ async function ensureObsidianWorkspace(rootDir) {
|
|
|
21656
21850
|
})
|
|
21657
21851
|
]);
|
|
21658
21852
|
}
|
|
21853
|
+
async function initLiteVault(rootDir, options) {
|
|
21854
|
+
const rawDir = path23.join(rootDir, "raw");
|
|
21855
|
+
const wikiDir = path23.join(rootDir, "wiki");
|
|
21856
|
+
const schemaPath = path23.join(rootDir, PRIMARY_SCHEMA_FILENAME);
|
|
21857
|
+
const indexPath = path23.join(wikiDir, "index.md");
|
|
21858
|
+
const logPath = path23.join(wikiDir, "log.md");
|
|
21859
|
+
await Promise.all([ensureDir(rawDir), ensureDir(wikiDir)]);
|
|
21860
|
+
if (!await fileExists(schemaPath)) {
|
|
21861
|
+
await fs19.writeFile(schemaPath, defaultVaultSchema("default"), "utf8");
|
|
21862
|
+
}
|
|
21863
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21864
|
+
if (!await fileExists(indexPath)) {
|
|
21865
|
+
await fs19.writeFile(
|
|
21866
|
+
indexPath,
|
|
21867
|
+
matter10.stringify(
|
|
21868
|
+
[
|
|
21869
|
+
"# Wiki Index",
|
|
21870
|
+
"",
|
|
21871
|
+
"This lite vault is agent-maintained. Drop sources into `raw/`, edit `swarmvault.schema.md` to teach the agent how the wiki should be organized, then ask your agent to read sources and update pages here.",
|
|
21872
|
+
"",
|
|
21873
|
+
"- Summaries, entity pages, and concept pages live under `wiki/`.",
|
|
21874
|
+
"- Append every ingest/query/lint operation to `wiki/log.md`.",
|
|
21875
|
+
"- Run `swarmvault init` (without `--lite`) when you want the full toolchain with graph, search, and approvals.",
|
|
21876
|
+
""
|
|
21877
|
+
].join("\n"),
|
|
21878
|
+
{
|
|
21879
|
+
page_id: "wiki:index",
|
|
21880
|
+
kind: "index",
|
|
21881
|
+
title: "Wiki Index",
|
|
21882
|
+
tags: ["index"],
|
|
21883
|
+
source_ids: [],
|
|
21884
|
+
project_ids: [],
|
|
21885
|
+
node_ids: [],
|
|
21886
|
+
freshness: "fresh",
|
|
21887
|
+
status: "active",
|
|
21888
|
+
confidence: 1,
|
|
21889
|
+
created_at: now,
|
|
21890
|
+
updated_at: now,
|
|
21891
|
+
compiled_from: [],
|
|
21892
|
+
managed_by: "agent",
|
|
21893
|
+
backlinks: [],
|
|
21894
|
+
schema_hash: "",
|
|
21895
|
+
source_hashes: {},
|
|
21896
|
+
source_semantic_hashes: {}
|
|
21897
|
+
}
|
|
21898
|
+
),
|
|
21899
|
+
"utf8"
|
|
21900
|
+
);
|
|
21901
|
+
}
|
|
21902
|
+
if (!await fileExists(logPath)) {
|
|
21903
|
+
await fs19.writeFile(
|
|
21904
|
+
logPath,
|
|
21905
|
+
matter10.stringify(
|
|
21906
|
+
[
|
|
21907
|
+
"# Activity Log",
|
|
21908
|
+
"",
|
|
21909
|
+
"Append-only chronological record. One line per ingest/query/lint operation, newest at the bottom.",
|
|
21910
|
+
"",
|
|
21911
|
+
"Format: `## [YYYY-MM-DD] <verb> | <subject>`",
|
|
21912
|
+
""
|
|
21913
|
+
].join("\n"),
|
|
21914
|
+
{
|
|
21915
|
+
page_id: "wiki:log",
|
|
21916
|
+
kind: "index",
|
|
21917
|
+
title: "Activity Log",
|
|
21918
|
+
tags: ["log", "append-only"],
|
|
21919
|
+
source_ids: [],
|
|
21920
|
+
project_ids: [],
|
|
21921
|
+
node_ids: [],
|
|
21922
|
+
freshness: "fresh",
|
|
21923
|
+
status: "active",
|
|
21924
|
+
confidence: 1,
|
|
21925
|
+
created_at: now,
|
|
21926
|
+
updated_at: now,
|
|
21927
|
+
compiled_from: [],
|
|
21928
|
+
managed_by: "agent",
|
|
21929
|
+
backlinks: [],
|
|
21930
|
+
schema_hash: "",
|
|
21931
|
+
source_hashes: {},
|
|
21932
|
+
source_semantic_hashes: {}
|
|
21933
|
+
}
|
|
21934
|
+
),
|
|
21935
|
+
"utf8"
|
|
21936
|
+
);
|
|
21937
|
+
}
|
|
21938
|
+
if (options.obsidian) {
|
|
21939
|
+
const obsidianDir = path23.join(rootDir, ".obsidian");
|
|
21940
|
+
await ensureDir(obsidianDir);
|
|
21941
|
+
}
|
|
21942
|
+
}
|
|
21659
21943
|
async function initVault(rootDir, options = {}) {
|
|
21944
|
+
if (options.lite) {
|
|
21945
|
+
await initLiteVault(rootDir, options);
|
|
21946
|
+
return;
|
|
21947
|
+
}
|
|
21660
21948
|
const requestedProfile = options.profile ?? "default";
|
|
21661
21949
|
const { config, paths } = await initWorkspace(rootDir, { profile: requestedProfile });
|
|
21662
21950
|
const profile = config.profile;
|
|
@@ -23352,7 +23640,7 @@ async function getWatchStatus(rootDir) {
|
|
|
23352
23640
|
}
|
|
23353
23641
|
|
|
23354
23642
|
// src/mcp.ts
|
|
23355
|
-
var SERVER_VERSION = "0.
|
|
23643
|
+
var SERVER_VERSION = "0.9.0";
|
|
23356
23644
|
async function createMcpServer(rootDir) {
|
|
23357
23645
|
const server = new McpServer({
|
|
23358
23646
|
name: "swarmvault",
|