@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.
Files changed (122) hide show
  1. package/README.md +6 -1
  2. package/dist/{chunk-NUWZUYE7.js → chunk-NON6BVEI.js} +4 -0
  3. package/dist/{chunk-JJDJF2P3.js → chunk-TQIIJVVG.js} +341 -10
  4. package/dist/index.d.ts +77 -2
  5. package/dist/index.js +234 -4
  6. package/dist/{memory-A4VPLUBA.js → memory-4BDKH4Y2.js} +2 -2
  7. package/dist/{registry-2QC3VN7M.js → registry-ZZ6NESFD.js} +1 -1
  8. package/package.json +3 -3
  9. package/dist/chunk-2CH2WWS4.js +0 -1359
  10. package/dist/chunk-2PN46RDI.js +0 -26846
  11. package/dist/chunk-333AMRSV.js +0 -1056
  12. package/dist/chunk-3GVEUYQZ.js +0 -1641
  13. package/dist/chunk-4MSSM2GH.js +0 -1476
  14. package/dist/chunk-563TZ4TZ.js +0 -26573
  15. package/dist/chunk-5GEPTIZE.js +0 -26010
  16. package/dist/chunk-5HNZ2WQI.js +0 -1341
  17. package/dist/chunk-5Q4IV4O3.js +0 -1336
  18. package/dist/chunk-6MO57J5C.js +0 -988
  19. package/dist/chunk-6UPHDGEB.js +0 -1073
  20. package/dist/chunk-75BU5TQ6.js +0 -1690
  21. package/dist/chunk-7O2HJSWQ.js +0 -1686
  22. package/dist/chunk-7QHDATCQ.js +0 -1673
  23. package/dist/chunk-B3FC4J3P.js +0 -1214
  24. package/dist/chunk-BTWPJEP2.js +0 -1421
  25. package/dist/chunk-CG67P2HB.js +0 -1420
  26. package/dist/chunk-CSPDMCON.js +0 -26846
  27. package/dist/chunk-CVFY54CF.js +0 -24893
  28. package/dist/chunk-CWLDFLH2.js +0 -1163
  29. package/dist/chunk-DAJAZPPO.js +0 -26865
  30. package/dist/chunk-EEWB4WGH.js +0 -1056
  31. package/dist/chunk-EXD4RWT3.js +0 -1131
  32. package/dist/chunk-F7HZZ3VM.js +0 -931
  33. package/dist/chunk-FD3LJQ4T.js +0 -1216
  34. package/dist/chunk-G2TH6ZTA.js +0 -1468
  35. package/dist/chunk-H3CDZYRE.js +0 -1701
  36. package/dist/chunk-HFU5S5NO.js +0 -838
  37. package/dist/chunk-HKU2T5JX.js +0 -25213
  38. package/dist/chunk-HOJ7NSYC.js +0 -937
  39. package/dist/chunk-HRRPWXRZ.js +0 -1335
  40. package/dist/chunk-HW72C7O2.js +0 -1690
  41. package/dist/chunk-IAEYFTUS.js +0 -1159
  42. package/dist/chunk-IHMJCCXR.js +0 -1146
  43. package/dist/chunk-JTRE7C7P.js +0 -26062
  44. package/dist/chunk-LEUV6TWJ.js +0 -1131
  45. package/dist/chunk-MB7HPUTR.js +0 -1364
  46. package/dist/chunk-MZSUYTSL.js +0 -998
  47. package/dist/chunk-N56FAH4N.js +0 -1404
  48. package/dist/chunk-NCSZ4AKP.js +0 -1057
  49. package/dist/chunk-NECZ4MUE.js +0 -1416
  50. package/dist/chunk-NHGS4LOI.js +0 -1346
  51. package/dist/chunk-OK5752AP.js +0 -1325
  52. package/dist/chunk-QMW7OISM.js +0 -1063
  53. package/dist/chunk-RN56HUXA.js +0 -26972
  54. package/dist/chunk-RSQRF4FV.js +0 -1424
  55. package/dist/chunk-S2E65WRI.js +0 -26062
  56. package/dist/chunk-SRHM3HP4.js +0 -944
  57. package/dist/chunk-U7JO257M.js +0 -25017
  58. package/dist/chunk-UQCF65BN.js +0 -1623
  59. package/dist/chunk-USSP4GVB.js +0 -25064
  60. package/dist/chunk-V7KX3AQD.js +0 -26010
  61. package/dist/chunk-WOA5LSNB.js +0 -26559
  62. package/dist/chunk-WWP3VPEJ.js +0 -26080
  63. package/dist/chunk-YFKWMXJ6.js +0 -26066
  64. package/dist/chunk-Z552HHPV.js +0 -26846
  65. package/dist/chunk-ZQ5T64AR.js +0 -1365
  66. package/dist/memory-DNSQCDHC.js +0 -32
  67. package/dist/memory-ECS3TSGC.js +0 -32
  68. package/dist/memory-FVIBFROA.js +0 -32
  69. package/dist/memory-G6I3DBW4.js +0 -32
  70. package/dist/memory-HE6VWUPV.js +0 -32
  71. package/dist/memory-HEA7XNKB.js +0 -32
  72. package/dist/memory-JRYTVHNH.js +0 -32
  73. package/dist/memory-K3NL5E3K.js +0 -32
  74. package/dist/memory-KANI73CX.js +0 -32
  75. package/dist/memory-KI5G2A4C.js +0 -32
  76. package/dist/memory-PK55JUKG.js +0 -32
  77. package/dist/memory-PK5JJNAG.js +0 -32
  78. package/dist/memory-SAQPBIB4.js +0 -32
  79. package/dist/memory-SVGRP5KS.js +0 -32
  80. package/dist/memory-TQ46BGCI.js +0 -32
  81. package/dist/memory-YKQWWIVY.js +0 -32
  82. package/dist/memory-Z7BP5OSC.js +0 -32
  83. package/dist/registry-2REAPKPO.js +0 -12
  84. package/dist/registry-2XHXZDGH.js +0 -12
  85. package/dist/registry-4C55ZCPL.js +0 -12
  86. package/dist/registry-4QRMVAHX.js +0 -12
  87. package/dist/registry-5SYH3Y3U.js +0 -12
  88. package/dist/registry-6KZMA3XM.js +0 -12
  89. package/dist/registry-7QACDJQQ.js +0 -12
  90. package/dist/registry-B7UXRBW3.js +0 -12
  91. package/dist/registry-FKEREVDO.js +0 -12
  92. package/dist/registry-FLSGGY2R.js +0 -12
  93. package/dist/registry-G7NSRYCO.js +0 -12
  94. package/dist/registry-GH4O3A7H.js +0 -12
  95. package/dist/registry-IBH6K2KK.js +0 -12
  96. package/dist/registry-ILDEBNCW.js +0 -12
  97. package/dist/registry-JFEW5RUP.js +0 -12
  98. package/dist/registry-JQYQOZYN.js +0 -12
  99. package/dist/registry-JR5WY22P.js +0 -12
  100. package/dist/registry-KLO5YIHP.js +0 -12
  101. package/dist/registry-KVJAO5DF.js +0 -12
  102. package/dist/registry-MYJX6AEE.js +0 -12
  103. package/dist/registry-NBLIJHZT.js +0 -12
  104. package/dist/registry-NLRWSN5J.js +0 -12
  105. package/dist/registry-NMXDBYIZ.js +0 -12
  106. package/dist/registry-OUB6W3LM.js +0 -12
  107. package/dist/registry-P5KRT66L.js +0 -12
  108. package/dist/registry-PGZWRXMD.js +0 -12
  109. package/dist/registry-QAG2ZYH3.js +0 -12
  110. package/dist/registry-SUXWCWB4.js +0 -12
  111. package/dist/registry-SYCRRA65.js +0 -12
  112. package/dist/registry-TYROWPR5.js +0 -12
  113. package/dist/registry-U23ML76I.js +0 -12
  114. package/dist/registry-U76DBOV3.js +0 -12
  115. package/dist/registry-UA42LQUQ.js +0 -12
  116. package/dist/registry-W6ZFRI73.js +0 -12
  117. package/dist/registry-X5PMZTZY.js +0 -12
  118. package/dist/registry-XIL5F33J.js +0 -12
  119. package/dist/registry-XOPLQNZY.js +0 -12
  120. package/dist/registry-YDXVCE4Q.js +0 -12
  121. package/dist/registry-YGVTLIZH.js +0 -12
  122. package/dist/registry-ZNW3FDED.js +0 -12
@@ -1,1163 +0,0 @@
1
- // src/providers/registry.ts
2
- import path3 from "path";
3
- import { pathToFileURL } from "url";
4
- import { z as z5 } from "zod";
5
-
6
- // src/config.ts
7
- import fs2 from "fs/promises";
8
- import path2 from "path";
9
- import { fileURLToPath } from "url";
10
- import { z as z2 } from "zod";
11
-
12
- // src/types.ts
13
- import { z } from "zod";
14
- var providerCapabilitySchema = z.enum([
15
- "responses",
16
- "chat",
17
- "structured",
18
- "tools",
19
- "vision",
20
- "embeddings",
21
- "streaming",
22
- "local",
23
- "image_generation"
24
- ]);
25
- var providerTypeSchema = z.enum([
26
- "heuristic",
27
- "openai",
28
- "ollama",
29
- "anthropic",
30
- "gemini",
31
- "openai-compatible",
32
- "openrouter",
33
- "groq",
34
- "together",
35
- "xai",
36
- "cerebras",
37
- "custom"
38
- ]);
39
- var agentTypeSchema = z.enum(["codex", "claude", "cursor", "goose", "pi", "gemini", "opencode", "aider", "copilot"]);
40
- var webSearchProviderTypeSchema = z.enum(["http-json", "custom"]);
41
-
42
- // src/utils.ts
43
- import crypto from "crypto";
44
- import fs from "fs/promises";
45
- import path from "path";
46
- function slugify(value) {
47
- return value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80) || "item";
48
- }
49
- function sha256(value) {
50
- return crypto.createHash("sha256").update(value).digest("hex");
51
- }
52
- async function ensureDir(dirPath) {
53
- await fs.mkdir(dirPath, { recursive: true });
54
- }
55
- async function fileExists(filePath) {
56
- try {
57
- await fs.access(filePath);
58
- return true;
59
- } catch {
60
- return false;
61
- }
62
- }
63
- async function readJsonFile(filePath) {
64
- try {
65
- const content = await fs.readFile(filePath, "utf8");
66
- return JSON.parse(content);
67
- } catch (error) {
68
- if (error instanceof Error && "code" in error && error.code === "ENOENT") {
69
- return null;
70
- }
71
- throw error;
72
- }
73
- }
74
- async function writeJsonFile(filePath, value) {
75
- await ensureDir(path.dirname(filePath));
76
- await fs.writeFile(filePath, `${JSON.stringify(value, null, 2)}
77
- `, "utf8");
78
- }
79
- async function appendJsonLine(filePath, value) {
80
- await ensureDir(path.dirname(filePath));
81
- await fs.appendFile(filePath, `${JSON.stringify(value)}
82
- `, "utf8");
83
- }
84
- async function writeFileIfChanged(filePath, content) {
85
- await ensureDir(path.dirname(filePath));
86
- if (await fileExists(filePath)) {
87
- const existing = await fs.readFile(filePath, "utf8");
88
- if (existing === content) {
89
- return false;
90
- }
91
- }
92
- await fs.writeFile(filePath, content, "utf8");
93
- return true;
94
- }
95
- function toPosix(value) {
96
- return value.split(path.sep).join(path.posix.sep);
97
- }
98
- function firstSentences(value, count = 3) {
99
- const sentences = value.replace(/\s+/g, " ").split(/(?<=[.!?])\s+/).filter(Boolean);
100
- return sentences.slice(0, count).join(" ").trim();
101
- }
102
- function uniqueBy(items, key) {
103
- const seen = /* @__PURE__ */ new Set();
104
- const result = [];
105
- for (const item of items) {
106
- const itemKey = key(item);
107
- if (seen.has(itemKey)) {
108
- continue;
109
- }
110
- seen.add(itemKey);
111
- result.push(item);
112
- }
113
- return result;
114
- }
115
- function extractJson(text) {
116
- const fencedMatch = text.match(/```json\s*([\s\S]*?)```/i);
117
- if (fencedMatch) {
118
- return fencedMatch[1].trim();
119
- }
120
- const start = text.indexOf("{");
121
- if (start !== -1) {
122
- let end = text.lastIndexOf("}");
123
- while (end > start) {
124
- const candidate = text.slice(start, end + 1);
125
- try {
126
- JSON.parse(candidate);
127
- return candidate;
128
- } catch {
129
- end = text.lastIndexOf("}", end - 1);
130
- }
131
- }
132
- }
133
- throw new Error("Could not locate JSON object in provider response.");
134
- }
135
- function normalizeWhitespace(value) {
136
- return value.replace(/\s+/g, " ").trim();
137
- }
138
- function truncate(value, maxLength) {
139
- if (value.length <= maxLength) {
140
- return value;
141
- }
142
- if (maxLength < 4) {
143
- return value.slice(0, maxLength);
144
- }
145
- return `${value.slice(0, maxLength - 3)}...`;
146
- }
147
- async function listFilesRecursive(rootDir) {
148
- const entries = await fs.readdir(rootDir, { withFileTypes: true }).catch(() => []);
149
- const files = [];
150
- for (const entry of entries) {
151
- const absolutePath = path.join(rootDir, entry.name);
152
- if (entry.isDirectory()) {
153
- files.push(...await listFilesRecursive(absolutePath));
154
- continue;
155
- }
156
- if (entry.isFile()) {
157
- files.push(absolutePath);
158
- }
159
- }
160
- return files;
161
- }
162
-
163
- // src/config.ts
164
- var PRIMARY_CONFIG_FILENAME = "swarmvault.config.json";
165
- var PRIMARY_SCHEMA_FILENAME = "swarmvault.schema.md";
166
- var moduleDir = path2.dirname(fileURLToPath(import.meta.url));
167
- var viewerDistDir = path2.basename(moduleDir) === "src" ? path2.resolve(moduleDir, "../../viewer/dist") : path2.resolve(moduleDir, "viewer");
168
- var providerConfigSchema = z2.object({
169
- type: providerTypeSchema,
170
- model: z2.string().min(1),
171
- baseUrl: z2.string().url().optional(),
172
- apiKeyEnv: z2.string().min(1).optional(),
173
- headers: z2.record(z2.string(), z2.string()).optional(),
174
- module: z2.string().min(1).optional(),
175
- capabilities: z2.array(providerCapabilitySchema).optional(),
176
- apiStyle: z2.enum(["responses", "chat"]).optional()
177
- });
178
- var sourceClassSchema = z2.enum(["first_party", "third_party", "resource", "generated"]);
179
- var neo4jGraphSinkConfigSchema = z2.object({
180
- uri: z2.string().min(1),
181
- username: z2.string().min(1),
182
- passwordEnv: z2.string().min(1),
183
- database: z2.string().min(1).optional(),
184
- vaultId: z2.string().min(1).optional(),
185
- includeClasses: z2.array(sourceClassSchema).optional(),
186
- batchSize: z2.number().int().positive().optional()
187
- });
188
- var scheduleTriggerSchema = z2.object({
189
- cron: z2.string().min(1).optional(),
190
- every: z2.string().min(1).optional()
191
- }).refine((value) => Boolean(value.cron || value.every), {
192
- message: "Schedule triggers require `cron` or `every`."
193
- });
194
- var scheduledTaskSchema = z2.discriminatedUnion("type", [
195
- z2.object({
196
- type: z2.literal("compile"),
197
- approve: z2.boolean().optional()
198
- }),
199
- z2.object({
200
- type: z2.literal("lint"),
201
- deep: z2.boolean().optional(),
202
- web: z2.boolean().optional()
203
- }),
204
- z2.object({
205
- type: z2.literal("query"),
206
- question: z2.string().min(1),
207
- format: z2.enum(["markdown", "report", "slides", "chart", "image"]).optional(),
208
- save: z2.boolean().optional()
209
- }),
210
- z2.object({
211
- type: z2.literal("explore"),
212
- question: z2.string().min(1),
213
- steps: z2.number().int().positive().optional(),
214
- format: z2.enum(["markdown", "report", "slides", "chart", "image"]).optional()
215
- })
216
- ]);
217
- var roleExecutorConfigSchema = z2.discriminatedUnion("type", [
218
- z2.object({
219
- type: z2.literal("provider"),
220
- provider: z2.string().min(1)
221
- }),
222
- z2.object({
223
- type: z2.literal("command"),
224
- command: z2.array(z2.string().min(1)).min(1),
225
- cwd: z2.string().min(1).optional(),
226
- env: z2.record(z2.string(), z2.string()).optional(),
227
- timeoutMs: z2.number().int().positive().optional()
228
- })
229
- ]);
230
- var webSearchProviderConfigSchema = z2.object({
231
- type: webSearchProviderTypeSchema,
232
- endpoint: z2.string().url().optional(),
233
- method: z2.enum(["GET", "POST"]).optional(),
234
- apiKeyEnv: z2.string().min(1).optional(),
235
- apiKeyHeader: z2.string().min(1).optional(),
236
- apiKeyPrefix: z2.string().optional(),
237
- headers: z2.record(z2.string(), z2.string()).optional(),
238
- queryParam: z2.string().min(1).optional(),
239
- limitParam: z2.string().min(1).optional(),
240
- resultsPath: z2.string().min(1).optional(),
241
- titleField: z2.string().min(1).optional(),
242
- urlField: z2.string().min(1).optional(),
243
- snippetField: z2.string().min(1).optional(),
244
- module: z2.string().min(1).optional()
245
- });
246
- var vaultConfigSchema = z2.object({
247
- workspace: z2.object({
248
- rawDir: z2.string().min(1),
249
- wikiDir: z2.string().min(1),
250
- stateDir: z2.string().min(1),
251
- agentDir: z2.string().min(1),
252
- inboxDir: z2.string().min(1)
253
- }),
254
- providers: z2.record(z2.string(), providerConfigSchema),
255
- tasks: z2.object({
256
- compileProvider: z2.string().min(1),
257
- queryProvider: z2.string().min(1),
258
- lintProvider: z2.string().min(1),
259
- visionProvider: z2.string().min(1),
260
- imageProvider: z2.string().min(1).optional(),
261
- embeddingProvider: z2.string().min(1).optional()
262
- }),
263
- viewer: z2.object({
264
- port: z2.number().int().positive()
265
- }),
266
- projects: z2.record(
267
- z2.string(),
268
- z2.object({
269
- roots: z2.array(z2.string().min(1)).min(1),
270
- schemaPath: z2.string().min(1).optional()
271
- })
272
- ).optional(),
273
- agents: z2.array(agentTypeSchema).default(["codex", "claude", "cursor"]),
274
- schedules: z2.record(z2.string(), z2.object({ enabled: z2.boolean().optional(), when: scheduleTriggerSchema, task: scheduledTaskSchema })).optional(),
275
- orchestration: z2.object({
276
- maxParallelRoles: z2.number().int().positive().optional(),
277
- compilePostPass: z2.boolean().optional(),
278
- roles: z2.object({
279
- research: z2.object({ executor: roleExecutorConfigSchema }).optional(),
280
- audit: z2.object({ executor: roleExecutorConfigSchema }).optional(),
281
- context: z2.object({ executor: roleExecutorConfigSchema }).optional(),
282
- safety: z2.object({ executor: roleExecutorConfigSchema }).optional()
283
- }).optional()
284
- }).optional(),
285
- benchmark: z2.object({
286
- enabled: z2.boolean().optional(),
287
- questions: z2.array(z2.string().min(1)).optional(),
288
- maxQuestions: z2.number().int().positive().optional()
289
- }).optional(),
290
- repoAnalysis: z2.object({
291
- classifyGlobs: z2.partialRecord(sourceClassSchema, z2.array(z2.string().min(1))).optional(),
292
- extractClasses: z2.array(sourceClassSchema).optional()
293
- }).optional(),
294
- graphSinks: z2.object({
295
- neo4j: neo4jGraphSinkConfigSchema.optional()
296
- }).optional(),
297
- webSearch: z2.object({
298
- providers: z2.record(z2.string(), webSearchProviderConfigSchema),
299
- tasks: z2.object({
300
- deepLintProvider: z2.string().min(1)
301
- })
302
- }).optional()
303
- });
304
- function defaultVaultConfig() {
305
- return {
306
- workspace: {
307
- rawDir: "raw",
308
- wikiDir: "wiki",
309
- stateDir: "state",
310
- agentDir: "agent",
311
- inboxDir: "inbox"
312
- },
313
- providers: {
314
- local: {
315
- type: "heuristic",
316
- model: "heuristic-v1",
317
- capabilities: ["chat", "structured", "vision", "local"]
318
- }
319
- },
320
- tasks: {
321
- compileProvider: "local",
322
- queryProvider: "local",
323
- lintProvider: "local",
324
- visionProvider: "local",
325
- imageProvider: "local"
326
- },
327
- viewer: {
328
- port: 4123
329
- },
330
- projects: {},
331
- agents: ["codex", "claude", "cursor"],
332
- schedules: {},
333
- orchestration: {
334
- maxParallelRoles: 2,
335
- compilePostPass: false,
336
- roles: {}
337
- },
338
- benchmark: {
339
- enabled: true,
340
- questions: [],
341
- maxQuestions: 3
342
- },
343
- repoAnalysis: {
344
- classifyGlobs: {},
345
- extractClasses: ["first_party"]
346
- },
347
- graphSinks: {}
348
- };
349
- }
350
- function defaultVaultSchema() {
351
- return [
352
- "# SwarmVault Schema",
353
- "",
354
- "Edit this file to teach SwarmVault how this vault should be organized and maintained.",
355
- "",
356
- "## Vault Purpose",
357
- "",
358
- "- Describe the domain this vault covers.",
359
- "- Note the intended audience and the kinds of questions the vault should answer well.",
360
- "",
361
- "## Naming Conventions",
362
- "",
363
- "- Prefer stable, descriptive page titles.",
364
- "- Keep concept and entity names specific to the domain.",
365
- "",
366
- "## Page Structure Rules",
367
- "",
368
- "- Source pages should stay grounded in the original material.",
369
- "- Concept and entity pages should aggregate source-backed claims instead of inventing new ones.",
370
- "- Preserve contradictions instead of smoothing them away.",
371
- "",
372
- "## Categories",
373
- "",
374
- "- List domain-specific concept categories here.",
375
- "- List important entity types here.",
376
- "",
377
- "## Relationship Types",
378
- "",
379
- "- Mentions",
380
- "- Supports",
381
- "- Contradicts",
382
- "- Depends on",
383
- "",
384
- "## Grounding Rules",
385
- "",
386
- "- Prefer raw sources over summaries.",
387
- "- Cite source ids whenever claims are stated.",
388
- "- Do not treat the wiki as a source of truth when the raw material disagrees.",
389
- "",
390
- "## Exclusions",
391
- "",
392
- "- List topics, claims, or page types the compiler should avoid generating.",
393
- ""
394
- ].join("\n");
395
- }
396
- async function findConfigPath(rootDir) {
397
- const primaryPath = path2.join(rootDir, PRIMARY_CONFIG_FILENAME);
398
- return primaryPath;
399
- }
400
- async function findSchemaPath(rootDir) {
401
- const primaryPath = path2.join(rootDir, PRIMARY_SCHEMA_FILENAME);
402
- return primaryPath;
403
- }
404
- function resolvePaths(rootDir, config, configPath = path2.join(rootDir, PRIMARY_CONFIG_FILENAME), schemaPath = path2.join(rootDir, PRIMARY_SCHEMA_FILENAME)) {
405
- const effective = config ?? defaultVaultConfig();
406
- const rawDir = path2.resolve(rootDir, effective.workspace.rawDir);
407
- const rawSourcesDir = path2.join(rawDir, "sources");
408
- const rawAssetsDir = path2.join(rawDir, "assets");
409
- const wikiDir = path2.resolve(rootDir, effective.workspace.wikiDir);
410
- const outputsAssetsDir = path2.join(wikiDir, "outputs", "assets");
411
- const projectsDir = path2.join(wikiDir, "projects");
412
- const candidatesDir = path2.join(wikiDir, "candidates");
413
- const stateDir = path2.resolve(rootDir, effective.workspace.stateDir);
414
- const schedulesDir = path2.join(stateDir, "schedules");
415
- const watchDir = path2.join(stateDir, "watch");
416
- const managedSourcesDir = path2.join(stateDir, "sources");
417
- const agentDir = path2.resolve(rootDir, effective.workspace.agentDir);
418
- const inboxDir = path2.resolve(rootDir, effective.workspace.inboxDir);
419
- return {
420
- rootDir,
421
- schemaPath,
422
- rawDir,
423
- rawSourcesDir,
424
- rawAssetsDir,
425
- wikiDir,
426
- outputsAssetsDir,
427
- projectsDir,
428
- candidatesDir,
429
- candidateConceptsDir: path2.join(candidatesDir, "concepts"),
430
- candidateEntitiesDir: path2.join(candidatesDir, "entities"),
431
- stateDir,
432
- schedulesDir,
433
- agentDir,
434
- inboxDir,
435
- manifestsDir: path2.join(stateDir, "manifests"),
436
- extractsDir: path2.join(stateDir, "extracts"),
437
- analysesDir: path2.join(stateDir, "analyses"),
438
- viewerDistDir,
439
- graphPath: path2.join(stateDir, "graph.json"),
440
- searchDbPath: path2.join(stateDir, "search.sqlite"),
441
- compileStatePath: path2.join(stateDir, "compile-state.json"),
442
- codeIndexPath: path2.join(stateDir, "code-index.json"),
443
- embeddingsPath: path2.join(stateDir, "embeddings.json"),
444
- benchmarkPath: path2.join(stateDir, "benchmark.json"),
445
- jobsLogPath: path2.join(stateDir, "jobs.ndjson"),
446
- sessionsDir: path2.join(stateDir, "sessions"),
447
- approvalsDir: path2.join(stateDir, "approvals"),
448
- watchDir,
449
- watchStatusPath: path2.join(watchDir, "status.json"),
450
- pendingSemanticRefreshPath: path2.join(watchDir, "pending-semantic-refresh.json"),
451
- managedSourcesPath: path2.join(stateDir, "sources.json"),
452
- managedSourcesDir,
453
- configPath
454
- };
455
- }
456
- async function loadVaultConfig(rootDir) {
457
- const configPath = await findConfigPath(rootDir);
458
- const schemaPath = await findSchemaPath(rootDir);
459
- const raw = await readJsonFile(configPath);
460
- const parsed = vaultConfigSchema.parse(raw ?? defaultVaultConfig());
461
- return {
462
- config: parsed,
463
- paths: resolvePaths(rootDir, parsed, configPath, schemaPath)
464
- };
465
- }
466
- async function initWorkspace(rootDir) {
467
- const configPath = await findConfigPath(rootDir);
468
- const schemaPath = await findSchemaPath(rootDir);
469
- const config = await fileExists(configPath) ? (await loadVaultConfig(rootDir)).config : defaultVaultConfig();
470
- const paths = resolvePaths(rootDir, config, configPath, schemaPath);
471
- const primarySchemaPath = path2.join(rootDir, PRIMARY_SCHEMA_FILENAME);
472
- await Promise.all([
473
- ensureDir(paths.rawDir),
474
- ensureDir(paths.wikiDir),
475
- ensureDir(paths.outputsAssetsDir),
476
- ensureDir(paths.projectsDir),
477
- ensureDir(paths.candidatesDir),
478
- ensureDir(paths.candidateConceptsDir),
479
- ensureDir(paths.candidateEntitiesDir),
480
- ensureDir(paths.stateDir),
481
- ensureDir(paths.schedulesDir),
482
- ensureDir(paths.watchDir),
483
- ensureDir(paths.managedSourcesDir),
484
- ensureDir(paths.sessionsDir),
485
- ensureDir(paths.approvalsDir),
486
- ensureDir(paths.agentDir),
487
- ensureDir(paths.inboxDir),
488
- ensureDir(paths.manifestsDir),
489
- ensureDir(paths.extractsDir),
490
- ensureDir(paths.analysesDir),
491
- ensureDir(paths.rawSourcesDir),
492
- ensureDir(paths.rawAssetsDir)
493
- ]);
494
- if (!await fileExists(configPath)) {
495
- await writeJsonFile(configPath, config);
496
- }
497
- if (!await fileExists(primarySchemaPath)) {
498
- await ensureDir(path2.dirname(primarySchemaPath));
499
- await fs2.writeFile(primarySchemaPath, defaultVaultSchema(), "utf8");
500
- }
501
- return { config, paths };
502
- }
503
-
504
- // src/providers/base.ts
505
- import fs3 from "fs/promises";
506
- import { z as z3 } from "zod";
507
- var BaseProviderAdapter = class {
508
- constructor(id, type, model, capabilities) {
509
- this.id = id;
510
- this.type = type;
511
- this.model = model;
512
- this.capabilities = new Set(capabilities);
513
- }
514
- id;
515
- type;
516
- model;
517
- capabilities;
518
- async embedTexts(_texts) {
519
- throw new Error(`Provider ${this.id} does not support embeddings.`);
520
- }
521
- async generateImage(_request) {
522
- throw new Error(`Provider ${this.id} does not support image generation.`);
523
- }
524
- async generateStructured(request, schema) {
525
- const schemaDescription = JSON.stringify(z3.toJSONSchema(schema), null, 2);
526
- const response = await this.generateText({
527
- ...request,
528
- prompt: `${request.prompt}
529
-
530
- Return JSON only. Follow this JSON Schema exactly:
531
- ${schemaDescription}`
532
- });
533
- const parsed = JSON.parse(extractJson(response.text));
534
- return schema.parse(parsed);
535
- }
536
- async encodeAttachments(attachments = []) {
537
- return Promise.all(
538
- attachments.map(async (attachment) => ({
539
- mimeType: attachment.mimeType,
540
- base64: await fs3.readFile(attachment.filePath, "base64")
541
- }))
542
- );
543
- }
544
- };
545
-
546
- // src/providers/anthropic.ts
547
- var AnthropicProviderAdapter = class extends BaseProviderAdapter {
548
- apiKey;
549
- headers;
550
- baseUrl;
551
- constructor(id, model, options) {
552
- super(id, "anthropic", model, ["chat", "structured", "tools", "vision", "streaming"]);
553
- this.apiKey = options.apiKey;
554
- this.headers = options.headers;
555
- this.baseUrl = (options.baseUrl ?? "https://api.anthropic.com").replace(/\/+$/, "");
556
- }
557
- async generateText(request) {
558
- const encodedAttachments = await this.encodeAttachments(request.attachments);
559
- const content = [
560
- { type: "text", text: request.prompt },
561
- ...encodedAttachments.map((item) => ({
562
- type: "image",
563
- source: {
564
- type: "base64",
565
- media_type: item.mimeType,
566
- data: item.base64
567
- }
568
- }))
569
- ];
570
- const response = await fetch(`${this.baseUrl}/v1/messages`, {
571
- method: "POST",
572
- headers: {
573
- "content-type": "application/json",
574
- "anthropic-version": "2023-06-01",
575
- ...this.apiKey ? { "x-api-key": this.apiKey } : {},
576
- ...this.headers
577
- },
578
- body: JSON.stringify({
579
- model: this.model,
580
- max_tokens: request.maxOutputTokens ?? 1200,
581
- system: request.system,
582
- messages: [
583
- {
584
- role: "user",
585
- content
586
- }
587
- ]
588
- })
589
- });
590
- if (!response.ok) {
591
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
592
- }
593
- const payload = await response.json();
594
- return {
595
- text: payload.content?.filter((item) => item.type === "text").map((item) => item.text ?? "").join("\n") ?? "",
596
- usage: payload.usage ? { inputTokens: payload.usage.input_tokens, outputTokens: payload.usage.output_tokens } : void 0
597
- };
598
- }
599
- };
600
-
601
- // src/providers/gemini.ts
602
- var GeminiProviderAdapter = class extends BaseProviderAdapter {
603
- apiKey;
604
- baseUrl;
605
- constructor(id, model, options) {
606
- super(id, "gemini", model, ["chat", "structured", "vision", "tools", "streaming"]);
607
- this.apiKey = options.apiKey;
608
- this.baseUrl = (options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta").replace(/\/+$/, "");
609
- }
610
- async generateText(request) {
611
- const encodedAttachments = await this.encodeAttachments(request.attachments);
612
- const parts = [
613
- ...request.system ? [{ text: `System instructions:
614
- ${request.system}` }] : [],
615
- { text: request.prompt },
616
- ...encodedAttachments.map((item) => ({
617
- inline_data: {
618
- mime_type: item.mimeType,
619
- data: item.base64
620
- }
621
- }))
622
- ];
623
- const response = await fetch(`${this.baseUrl}/models/${this.model}:generateContent`, {
624
- method: "POST",
625
- headers: {
626
- "content-type": "application/json",
627
- ...this.apiKey ? { "x-goog-api-key": this.apiKey } : {}
628
- },
629
- body: JSON.stringify({
630
- contents: [
631
- {
632
- role: "user",
633
- parts
634
- }
635
- ],
636
- generationConfig: {
637
- maxOutputTokens: request.maxOutputTokens ?? 1200
638
- }
639
- })
640
- });
641
- if (!response.ok) {
642
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
643
- }
644
- const payload = await response.json();
645
- const text = payload.candidates?.[0]?.content?.parts?.map((part) => part.text ?? "").join("\n") ?? "";
646
- return {
647
- text,
648
- usage: payload.usageMetadata ? { inputTokens: payload.usageMetadata.promptTokenCount, outputTokens: payload.usageMetadata.candidatesTokenCount } : void 0
649
- };
650
- }
651
- };
652
-
653
- // src/providers/heuristic.ts
654
- function summarizePrompt(prompt) {
655
- const cleaned = normalizeWhitespace(prompt);
656
- if (!cleaned) {
657
- return "No prompt content provided.";
658
- }
659
- return firstSentences(cleaned, 2) || cleaned.slice(0, 280);
660
- }
661
- var HeuristicProviderAdapter = class extends BaseProviderAdapter {
662
- constructor(id, model) {
663
- super(id, "heuristic", model, ["chat", "structured", "vision", "local"]);
664
- }
665
- async generateText(request) {
666
- const attachmentHint = request.attachments?.length ? ` Attachments: ${request.attachments.length}.` : "";
667
- return {
668
- text: `Heuristic provider response.${attachmentHint} ${summarizePrompt(request.prompt)}`.trim()
669
- };
670
- }
671
- };
672
-
673
- // src/providers/openai-compatible.ts
674
- import { z as z4 } from "zod";
675
- function buildAuthHeaders(apiKey) {
676
- return apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
677
- }
678
- function extractResponsesText(payload) {
679
- if (typeof payload.output_text === "string" && payload.output_text.trim()) {
680
- return payload.output_text;
681
- }
682
- return payload.output?.flatMap((item) => item.content ?? []).filter((item) => item.type === "output_text" && typeof item.text === "string").map((item) => item.text ?? "").join("\n").trim() ?? "";
683
- }
684
- function isJsonSchemaObject(value) {
685
- return typeof value === "object" && value !== null && !Array.isArray(value);
686
- }
687
- function allowNullInSchema(schema) {
688
- if (Array.isArray(schema.type)) {
689
- return schema.type.includes("null") ? schema : { ...schema, type: [...schema.type, "null"] };
690
- }
691
- if (typeof schema.type === "string") {
692
- return schema.type === "null" ? schema : { ...schema, type: [schema.type, "null"] };
693
- }
694
- if (Array.isArray(schema.enum)) {
695
- return schema.enum.includes(null) ? schema : { ...schema, enum: [...schema.enum, null] };
696
- }
697
- if (Array.isArray(schema.anyOf)) {
698
- return schema.anyOf.some((item) => isJsonSchemaObject(item) && item.type === "null") ? schema : { ...schema, anyOf: [...schema.anyOf, { type: "null" }] };
699
- }
700
- return { anyOf: [schema, { type: "null" }] };
701
- }
702
- function toOpenAiStrictJsonSchema(schema) {
703
- if (Array.isArray(schema)) {
704
- return schema.map((item) => toOpenAiStrictJsonSchema(item));
705
- }
706
- if (!isJsonSchemaObject(schema)) {
707
- return schema;
708
- }
709
- const normalizedEntries = Object.entries(schema).filter(([key]) => key !== "$schema").map(([key, value]) => [key, toOpenAiStrictJsonSchema(value)]);
710
- const normalizedSchema = Object.fromEntries(normalizedEntries);
711
- if (isJsonSchemaObject(normalizedSchema.properties)) {
712
- const properties = normalizedSchema.properties;
713
- const originalRequired = Array.isArray(normalizedSchema.required) ? normalizedSchema.required.filter((item) => typeof item === "string") : [];
714
- const requiredSet = new Set(originalRequired);
715
- const propertyEntries = Object.entries(properties).map(([key, value]) => {
716
- const normalizedProperty = isJsonSchemaObject(value) ? value : {};
717
- return [key, requiredSet.has(key) ? normalizedProperty : allowNullInSchema(normalizedProperty)];
718
- });
719
- return {
720
- ...normalizedSchema,
721
- properties: Object.fromEntries(propertyEntries),
722
- required: Object.keys(properties),
723
- additionalProperties: false
724
- };
725
- }
726
- return normalizedSchema;
727
- }
728
- function stripNullObjectProperties(value) {
729
- if (Array.isArray(value)) {
730
- return value.map((item) => stripNullObjectProperties(item));
731
- }
732
- if (!isJsonSchemaObject(value)) {
733
- return value;
734
- }
735
- const entries = Object.entries(value).filter(([, item]) => item !== null).map(([key, item]) => [key, stripNullObjectProperties(item)]);
736
- return Object.fromEntries(entries);
737
- }
738
- function buildStructuredFormat(schema) {
739
- return {
740
- type: "json_schema",
741
- name: "swarmvault_response",
742
- schema: toOpenAiStrictJsonSchema(z4.toJSONSchema(schema)),
743
- strict: true
744
- };
745
- }
746
- var OpenAiCompatibleProviderAdapter = class extends BaseProviderAdapter {
747
- baseUrl;
748
- apiKey;
749
- headers;
750
- apiStyle;
751
- constructor(id, type, model, options) {
752
- super(id, type, model, options.capabilities);
753
- this.baseUrl = options.baseUrl.replace(/\/+$/, "");
754
- this.apiKey = options.apiKey;
755
- this.headers = options.headers;
756
- this.apiStyle = options.apiStyle ?? "responses";
757
- }
758
- async generateText(request) {
759
- if (this.apiStyle === "chat") {
760
- return this.generateViaChatCompletions(request);
761
- }
762
- return this.generateViaResponses(request);
763
- }
764
- async generateStructured(request, schema) {
765
- if (this.type !== "openai") {
766
- return super.generateStructured(request, schema);
767
- }
768
- const structuredFormat = buildStructuredFormat(schema);
769
- const text = this.apiStyle === "chat" ? await this.generateStructuredViaChatCompletions(
770
- {
771
- ...request
772
- },
773
- structuredFormat
774
- ) : await this.generateStructuredViaResponses(
775
- {
776
- ...request
777
- },
778
- structuredFormat
779
- );
780
- return schema.parse(stripNullObjectProperties(JSON.parse(extractJson(text))));
781
- }
782
- async embedTexts(texts) {
783
- if (!texts.length) {
784
- return [];
785
- }
786
- const response = await fetch(`${this.baseUrl}/embeddings`, {
787
- method: "POST",
788
- headers: {
789
- "content-type": "application/json",
790
- ...buildAuthHeaders(this.apiKey),
791
- ...this.headers
792
- },
793
- body: JSON.stringify({
794
- model: this.model,
795
- input: texts
796
- })
797
- });
798
- if (!response.ok) {
799
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
800
- }
801
- const payload = await response.json();
802
- const vectors = payload.data?.map((item) => item.embedding ?? []) ?? [];
803
- if (vectors.length !== texts.length || vectors.some((vector) => !Array.isArray(vector) || vector.length === 0)) {
804
- throw new Error(`Provider ${this.id} returned invalid embedding data.`);
805
- }
806
- return vectors;
807
- }
808
- async generateImage(request) {
809
- const encodedAttachments = await this.encodeAttachments(request.attachments);
810
- const response = await fetch(`${this.baseUrl}/images/generations`, {
811
- method: "POST",
812
- headers: {
813
- "content-type": "application/json",
814
- ...buildAuthHeaders(this.apiKey),
815
- ...this.headers
816
- },
817
- body: JSON.stringify({
818
- model: this.model,
819
- prompt: request.prompt,
820
- size: request.width && request.height ? `${Math.max(256, Math.round(request.width))}x${Math.max(256, Math.round(request.height))}` : void 0,
821
- response_format: "b64_json",
822
- ...encodedAttachments.length ? {
823
- input_image: encodedAttachments.map((item) => `data:${item.mimeType};base64,${item.base64}`)
824
- } : {}
825
- })
826
- });
827
- if (!response.ok) {
828
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
829
- }
830
- const payload = await response.json();
831
- const image = payload.data?.[0];
832
- if (!image?.b64_json) {
833
- throw new Error(`Provider ${this.id} returned no image data.`);
834
- }
835
- return {
836
- mimeType: "image/png",
837
- bytes: Buffer.from(image.b64_json, "base64"),
838
- width: request.width,
839
- height: request.height,
840
- revisedPrompt: image.revised_prompt
841
- };
842
- }
843
- async generateViaResponses(request) {
844
- const encodedAttachments = await this.encodeAttachments(request.attachments);
845
- const input = encodedAttachments.length ? [
846
- {
847
- role: "user",
848
- content: [
849
- { type: "input_text", text: request.prompt },
850
- ...encodedAttachments.map((item) => ({
851
- type: "input_image",
852
- image_url: `data:${item.mimeType};base64,${item.base64}`
853
- }))
854
- ]
855
- }
856
- ] : request.prompt;
857
- const response = await fetch(`${this.baseUrl}/responses`, {
858
- method: "POST",
859
- headers: {
860
- "content-type": "application/json",
861
- ...buildAuthHeaders(this.apiKey),
862
- ...this.headers
863
- },
864
- body: JSON.stringify({
865
- model: this.model,
866
- input,
867
- instructions: request.system,
868
- max_output_tokens: request.maxOutputTokens
869
- })
870
- });
871
- if (!response.ok) {
872
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
873
- }
874
- const payload = await response.json();
875
- return {
876
- text: extractResponsesText(payload),
877
- usage: payload.usage ? { inputTokens: payload.usage.input_tokens, outputTokens: payload.usage.output_tokens } : void 0
878
- };
879
- }
880
- async generateStructuredViaResponses(request, format) {
881
- const encodedAttachments = await this.encodeAttachments(request.attachments);
882
- const input = encodedAttachments.length ? [
883
- {
884
- role: "user",
885
- content: [
886
- { type: "input_text", text: request.prompt },
887
- ...encodedAttachments.map((item) => ({
888
- type: "input_image",
889
- image_url: `data:${item.mimeType};base64,${item.base64}`
890
- }))
891
- ]
892
- }
893
- ] : request.prompt;
894
- const response = await fetch(`${this.baseUrl}/responses`, {
895
- method: "POST",
896
- headers: {
897
- "content-type": "application/json",
898
- ...buildAuthHeaders(this.apiKey),
899
- ...this.headers
900
- },
901
- body: JSON.stringify({
902
- model: this.model,
903
- input,
904
- instructions: request.system,
905
- max_output_tokens: request.maxOutputTokens,
906
- text: {
907
- format
908
- }
909
- })
910
- });
911
- if (!response.ok) {
912
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
913
- }
914
- const payload = await response.json();
915
- return extractResponsesText(payload);
916
- }
917
- async generateViaChatCompletions(request) {
918
- const encodedAttachments = await this.encodeAttachments(request.attachments);
919
- const content = encodedAttachments.length ? [
920
- { type: "text", text: request.prompt },
921
- ...encodedAttachments.map((item) => ({
922
- type: "image_url",
923
- image_url: {
924
- url: `data:${item.mimeType};base64,${item.base64}`
925
- }
926
- }))
927
- ] : request.prompt;
928
- const messages = [...request.system ? [{ role: "system", content: request.system }] : [], { role: "user", content }];
929
- const response = await fetch(`${this.baseUrl}/chat/completions`, {
930
- method: "POST",
931
- headers: {
932
- "content-type": "application/json",
933
- ...buildAuthHeaders(this.apiKey),
934
- ...this.headers
935
- },
936
- body: JSON.stringify({
937
- model: this.model,
938
- messages,
939
- max_tokens: request.maxOutputTokens
940
- })
941
- });
942
- if (!response.ok) {
943
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
944
- }
945
- const payload = await response.json();
946
- const contentValue = payload.choices?.[0]?.message?.content;
947
- const text = Array.isArray(contentValue) ? contentValue.map((item) => item.text ?? "").join("\n") : contentValue ?? "";
948
- return {
949
- text,
950
- usage: payload.usage ? { inputTokens: payload.usage.prompt_tokens, outputTokens: payload.usage.completion_tokens } : void 0
951
- };
952
- }
953
- async generateStructuredViaChatCompletions(request, format) {
954
- const encodedAttachments = await this.encodeAttachments(request.attachments);
955
- const content = encodedAttachments.length ? [
956
- { type: "text", text: request.prompt },
957
- ...encodedAttachments.map((item) => ({
958
- type: "image_url",
959
- image_url: {
960
- url: `data:${item.mimeType};base64,${item.base64}`
961
- }
962
- }))
963
- ] : request.prompt;
964
- const messages = [...request.system ? [{ role: "system", content: request.system }] : [], { role: "user", content }];
965
- const response = await fetch(`${this.baseUrl}/chat/completions`, {
966
- method: "POST",
967
- headers: {
968
- "content-type": "application/json",
969
- ...buildAuthHeaders(this.apiKey),
970
- ...this.headers
971
- },
972
- body: JSON.stringify({
973
- model: this.model,
974
- messages,
975
- max_tokens: request.maxOutputTokens,
976
- response_format: {
977
- type: "json_schema",
978
- json_schema: format
979
- }
980
- })
981
- });
982
- if (!response.ok) {
983
- throw new Error(`Provider ${this.id} failed: ${response.status} ${response.statusText}`);
984
- }
985
- const payload = await response.json();
986
- const contentValue = payload.choices?.[0]?.message?.content;
987
- return Array.isArray(contentValue) ? contentValue.map((item) => item.text ?? "").join("\n") : contentValue ?? "";
988
- }
989
- };
990
-
991
- // src/providers/registry.ts
992
- var customModuleSchema = z5.object({
993
- createAdapter: z5.function({
994
- input: [z5.string(), z5.custom(), z5.string()],
995
- output: z5.promise(z5.custom())
996
- })
997
- });
998
- function resolveCapabilities(config, fallback) {
999
- return config.capabilities?.length ? config.capabilities : fallback;
1000
- }
1001
- function envOrUndefined(name) {
1002
- return name ? process.env[name] : void 0;
1003
- }
1004
- function createOpenAiCompatiblePreset(id, type, config, defaults) {
1005
- return new OpenAiCompatibleProviderAdapter(id, type, config.model, {
1006
- baseUrl: config.baseUrl ?? defaults.baseUrl,
1007
- apiKey: envOrUndefined(config.apiKeyEnv ?? defaults.apiKeyEnv),
1008
- headers: config.headers,
1009
- apiStyle: config.apiStyle ?? defaults.apiStyle ?? "chat",
1010
- capabilities: resolveCapabilities(config, defaults.capabilities)
1011
- });
1012
- }
1013
- async function createProvider(id, config, rootDir) {
1014
- switch (config.type) {
1015
- case "heuristic":
1016
- return new HeuristicProviderAdapter(id, config.model);
1017
- case "openai":
1018
- return new OpenAiCompatibleProviderAdapter(id, "openai", config.model, {
1019
- baseUrl: config.baseUrl ?? "https://api.openai.com/v1",
1020
- apiKey: envOrUndefined(config.apiKeyEnv),
1021
- headers: config.headers,
1022
- apiStyle: config.apiStyle ?? "responses",
1023
- capabilities: resolveCapabilities(config, [
1024
- "responses",
1025
- "chat",
1026
- "structured",
1027
- "tools",
1028
- "vision",
1029
- "embeddings",
1030
- "streaming",
1031
- "image_generation"
1032
- ])
1033
- });
1034
- case "ollama":
1035
- return new OpenAiCompatibleProviderAdapter(id, "ollama", config.model, {
1036
- baseUrl: config.baseUrl ?? "http://localhost:11434/v1",
1037
- apiKey: envOrUndefined(config.apiKeyEnv) ?? "ollama",
1038
- headers: config.headers,
1039
- apiStyle: config.apiStyle ?? "responses",
1040
- capabilities: resolveCapabilities(config, [
1041
- "responses",
1042
- "chat",
1043
- "structured",
1044
- "tools",
1045
- "vision",
1046
- "embeddings",
1047
- "streaming",
1048
- "local"
1049
- ])
1050
- });
1051
- case "openai-compatible":
1052
- return new OpenAiCompatibleProviderAdapter(id, "openai-compatible", config.model, {
1053
- baseUrl: config.baseUrl ?? "http://localhost:8000/v1",
1054
- apiKey: envOrUndefined(config.apiKeyEnv),
1055
- headers: config.headers,
1056
- apiStyle: config.apiStyle ?? "responses",
1057
- capabilities: resolveCapabilities(config, ["chat", "structured", "embeddings"])
1058
- });
1059
- case "openrouter":
1060
- return createOpenAiCompatiblePreset(id, "openrouter", config, {
1061
- baseUrl: "https://openrouter.ai/api/v1",
1062
- apiKeyEnv: "OPENROUTER_API_KEY",
1063
- apiStyle: "chat",
1064
- capabilities: ["chat", "structured", "embeddings"]
1065
- });
1066
- case "groq":
1067
- return createOpenAiCompatiblePreset(id, "groq", config, {
1068
- baseUrl: "https://api.groq.com/openai/v1",
1069
- apiKeyEnv: "GROQ_API_KEY",
1070
- apiStyle: "chat",
1071
- capabilities: ["chat", "structured", "embeddings"]
1072
- });
1073
- case "together":
1074
- return createOpenAiCompatiblePreset(id, "together", config, {
1075
- baseUrl: "https://api.together.xyz/v1",
1076
- apiKeyEnv: "TOGETHER_API_KEY",
1077
- apiStyle: "chat",
1078
- capabilities: ["chat", "structured", "embeddings"]
1079
- });
1080
- case "xai":
1081
- return createOpenAiCompatiblePreset(id, "xai", config, {
1082
- baseUrl: "https://api.x.ai/v1",
1083
- apiKeyEnv: "XAI_API_KEY",
1084
- apiStyle: "chat",
1085
- capabilities: ["chat", "structured", "embeddings"]
1086
- });
1087
- case "cerebras":
1088
- return createOpenAiCompatiblePreset(id, "cerebras", config, {
1089
- baseUrl: "https://api.cerebras.ai/v1",
1090
- apiKeyEnv: "CEREBRAS_API_KEY",
1091
- apiStyle: "chat",
1092
- capabilities: ["chat", "structured", "embeddings"]
1093
- });
1094
- case "anthropic":
1095
- return new AnthropicProviderAdapter(id, config.model, {
1096
- apiKey: envOrUndefined(config.apiKeyEnv),
1097
- headers: config.headers,
1098
- baseUrl: config.baseUrl
1099
- });
1100
- case "gemini":
1101
- return new GeminiProviderAdapter(id, config.model, {
1102
- apiKey: envOrUndefined(config.apiKeyEnv),
1103
- baseUrl: config.baseUrl
1104
- });
1105
- case "custom": {
1106
- if (!config.module) {
1107
- throw new Error(`Provider ${id} is type "custom" but no module path was configured.`);
1108
- }
1109
- const resolvedModule = path3.isAbsolute(config.module) ? config.module : path3.resolve(rootDir, config.module);
1110
- const loaded = await import(pathToFileURL(resolvedModule).href);
1111
- const parsed = customModuleSchema.parse(loaded);
1112
- return parsed.createAdapter(id, config, rootDir);
1113
- }
1114
- default:
1115
- throw new Error(`Unsupported provider type ${String(config.type)}`);
1116
- }
1117
- }
1118
- async function getProviderForTask(rootDir, task) {
1119
- const { config } = await loadVaultConfig(rootDir);
1120
- const providerId = config.tasks[task];
1121
- if (!providerId) {
1122
- throw new Error(`No provider configured for task "${String(task)}".`);
1123
- }
1124
- const providerConfig = config.providers[providerId];
1125
- if (!providerConfig) {
1126
- throw new Error(`No provider configured with id "${providerId}" for task "${task}".`);
1127
- }
1128
- return createProvider(providerId, providerConfig, rootDir);
1129
- }
1130
- function assertProviderCapability(provider, capability) {
1131
- if (!provider.capabilities.has(capability)) {
1132
- throw new Error(`Provider ${provider.id} does not support required capability "${capability}".`);
1133
- }
1134
- }
1135
- async function getResolvedPaths(rootDir) {
1136
- return (await loadVaultConfig(rootDir)).paths;
1137
- }
1138
-
1139
- export {
1140
- slugify,
1141
- sha256,
1142
- ensureDir,
1143
- fileExists,
1144
- readJsonFile,
1145
- writeJsonFile,
1146
- appendJsonLine,
1147
- writeFileIfChanged,
1148
- toPosix,
1149
- firstSentences,
1150
- uniqueBy,
1151
- normalizeWhitespace,
1152
- truncate,
1153
- listFilesRecursive,
1154
- defaultVaultConfig,
1155
- defaultVaultSchema,
1156
- resolvePaths,
1157
- loadVaultConfig,
1158
- initWorkspace,
1159
- createProvider,
1160
- getProviderForTask,
1161
- assertProviderCapability,
1162
- getResolvedPaths
1163
- };