@weavelogic/knowledge-graph-agent 0.6.0 → 0.7.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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -3
  3. package/dist/_virtual/__vite-browser-external.js +2 -2
  4. package/dist/_virtual/__vite-browser-external.js.map +1 -1
  5. package/dist/_virtual/index12.js +7 -0
  6. package/dist/_virtual/index12.js.map +1 -0
  7. package/dist/_virtual/ort-web.min.js +8 -0
  8. package/dist/_virtual/ort-web.min.js.map +1 -0
  9. package/dist/_virtual/ort-web.min2.js +5 -0
  10. package/dist/_virtual/ort-web.min2.js.map +1 -0
  11. package/dist/agents/base-agent.d.ts +63 -0
  12. package/dist/agents/base-agent.d.ts.map +1 -1
  13. package/dist/agents/base-agent.js +139 -0
  14. package/dist/agents/base-agent.js.map +1 -1
  15. package/dist/agents/coordinator-agent.d.ts +422 -0
  16. package/dist/agents/coordinator-agent.d.ts.map +1 -0
  17. package/dist/agents/documenter-agent.d.ts +298 -0
  18. package/dist/agents/documenter-agent.d.ts.map +1 -0
  19. package/dist/agents/index.d.ts +11 -1
  20. package/dist/agents/index.d.ts.map +1 -1
  21. package/dist/agents/index.js +4 -0
  22. package/dist/agents/index.js.map +1 -1
  23. package/dist/agents/mixins/index.d.ts +9 -0
  24. package/dist/agents/mixins/index.d.ts.map +1 -0
  25. package/dist/agents/mixins/trajectory-mixin.d.ts +112 -0
  26. package/dist/agents/mixins/trajectory-mixin.d.ts.map +1 -0
  27. package/dist/agents/optimizer-agent.d.ts +388 -0
  28. package/dist/agents/optimizer-agent.d.ts.map +1 -0
  29. package/dist/agents/planner-agent.d.ts +395 -0
  30. package/dist/agents/planner-agent.d.ts.map +1 -0
  31. package/dist/agents/registry.d.ts.map +1 -1
  32. package/dist/agents/registry.js +5 -0
  33. package/dist/agents/registry.js.map +1 -1
  34. package/dist/agents/reviewer-agent.d.ts +330 -0
  35. package/dist/agents/reviewer-agent.d.ts.map +1 -0
  36. package/dist/agents/types.d.ts +12 -1
  37. package/dist/agents/types.d.ts.map +1 -1
  38. package/dist/agents/types.js +1 -0
  39. package/dist/agents/types.js.map +1 -1
  40. package/dist/cli/commands/hive-mind/add-frontmatter.d.ts +102 -0
  41. package/dist/cli/commands/hive-mind/add-frontmatter.d.ts.map +1 -0
  42. package/dist/cli/commands/hive-mind/add-frontmatter.js +439 -0
  43. package/dist/cli/commands/hive-mind/add-frontmatter.js.map +1 -0
  44. package/dist/cli/commands/hive-mind/analyze-links.d.ts +80 -0
  45. package/dist/cli/commands/hive-mind/analyze-links.d.ts.map +1 -0
  46. package/dist/cli/commands/hive-mind/analyze-links.js +367 -0
  47. package/dist/cli/commands/hive-mind/analyze-links.js.map +1 -0
  48. package/dist/cli/commands/hive-mind/find-connections.d.ts +75 -0
  49. package/dist/cli/commands/hive-mind/find-connections.d.ts.map +1 -0
  50. package/dist/cli/commands/hive-mind/find-connections.js +347 -0
  51. package/dist/cli/commands/hive-mind/find-connections.js.map +1 -0
  52. package/dist/cli/commands/hive-mind/index.d.ts +37 -0
  53. package/dist/cli/commands/hive-mind/index.d.ts.map +1 -0
  54. package/dist/cli/commands/hive-mind/index.js +33 -0
  55. package/dist/cli/commands/hive-mind/index.js.map +1 -0
  56. package/dist/cli/commands/hive-mind/validate-names.d.ts +79 -0
  57. package/dist/cli/commands/hive-mind/validate-names.d.ts.map +1 -0
  58. package/dist/cli/commands/hive-mind/validate-names.js +353 -0
  59. package/dist/cli/commands/hive-mind/validate-names.js.map +1 -0
  60. package/dist/cli/commands/vector.js +2 -0
  61. package/dist/cli/commands/vector.js.map +1 -1
  62. package/dist/cli/index.d.ts.map +1 -1
  63. package/dist/cli/index.js +7 -0
  64. package/dist/cli/index.js.map +1 -1
  65. package/dist/equilibrium/agent-equilibrium.d.ts +194 -0
  66. package/dist/equilibrium/agent-equilibrium.d.ts.map +1 -0
  67. package/dist/equilibrium/agent-equilibrium.js +304 -0
  68. package/dist/equilibrium/agent-equilibrium.js.map +1 -0
  69. package/dist/equilibrium/graph-equilibrium.d.ts +177 -0
  70. package/dist/equilibrium/graph-equilibrium.d.ts.map +1 -0
  71. package/dist/equilibrium/index.d.ts +11 -0
  72. package/dist/equilibrium/index.d.ts.map +1 -0
  73. package/dist/equilibrium/memory-equilibrium.d.ts +153 -0
  74. package/dist/equilibrium/memory-equilibrium.d.ts.map +1 -0
  75. package/dist/graphql/resolvers/index.d.ts.map +1 -1
  76. package/dist/graphql/resolvers/queries.d.ts +11 -0
  77. package/dist/graphql/resolvers/queries.d.ts.map +1 -1
  78. package/dist/index.d.ts +2 -0
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/index.js +10 -4
  81. package/dist/index.js.map +1 -1
  82. package/dist/inference/index.d.ts +9 -0
  83. package/dist/inference/index.d.ts.map +1 -0
  84. package/dist/inference/model-selection.d.ts +131 -0
  85. package/dist/inference/model-selection.d.ts.map +1 -0
  86. package/dist/integrations/agentic-flow/adapters/agent-booster-adapter.d.ts +265 -0
  87. package/dist/integrations/agentic-flow/adapters/agent-booster-adapter.d.ts.map +1 -0
  88. package/dist/integrations/agentic-flow/adapters/agentdb-adapter.d.ts +197 -0
  89. package/dist/integrations/agentic-flow/adapters/agentdb-adapter.d.ts.map +1 -0
  90. package/dist/integrations/agentic-flow/adapters/agentdb-vector-store.d.ts +249 -0
  91. package/dist/integrations/agentic-flow/adapters/agentdb-vector-store.d.ts.map +1 -0
  92. package/dist/integrations/agentic-flow/adapters/base-adapter.d.ts +120 -0
  93. package/dist/integrations/agentic-flow/adapters/base-adapter.d.ts.map +1 -0
  94. package/dist/integrations/agentic-flow/adapters/federation-hub-adapter.d.ts +444 -0
  95. package/dist/integrations/agentic-flow/adapters/federation-hub-adapter.d.ts.map +1 -0
  96. package/dist/integrations/agentic-flow/adapters/index.d.ts +17 -0
  97. package/dist/integrations/agentic-flow/adapters/index.d.ts.map +1 -0
  98. package/dist/integrations/agentic-flow/adapters/model-router-adapter.d.ts +242 -0
  99. package/dist/integrations/agentic-flow/adapters/model-router-adapter.d.ts.map +1 -0
  100. package/dist/integrations/agentic-flow/adapters/quic-transport-adapter.d.ts +364 -0
  101. package/dist/integrations/agentic-flow/adapters/quic-transport-adapter.d.ts.map +1 -0
  102. package/dist/integrations/agentic-flow/adapters/reasoning-bank-adapter.d.ts +209 -0
  103. package/dist/integrations/agentic-flow/adapters/reasoning-bank-adapter.d.ts.map +1 -0
  104. package/dist/integrations/agentic-flow/benchmark/index.d.ts +9 -0
  105. package/dist/integrations/agentic-flow/benchmark/index.d.ts.map +1 -0
  106. package/dist/integrations/agentic-flow/benchmark/vector-benchmark.d.ts +253 -0
  107. package/dist/integrations/agentic-flow/benchmark/vector-benchmark.d.ts.map +1 -0
  108. package/dist/integrations/agentic-flow/config.d.ts +109 -0
  109. package/dist/integrations/agentic-flow/config.d.ts.map +1 -0
  110. package/dist/integrations/agentic-flow/feature-flags.d.ts +140 -0
  111. package/dist/integrations/agentic-flow/feature-flags.d.ts.map +1 -0
  112. package/dist/integrations/agentic-flow/index.d.ts +22 -0
  113. package/dist/integrations/agentic-flow/index.d.ts.map +1 -0
  114. package/dist/integrations/agentic-flow/migration/index.d.ts +9 -0
  115. package/dist/integrations/agentic-flow/migration/index.d.ts.map +1 -0
  116. package/dist/integrations/agentic-flow/migration/migrate-to-agentdb.d.ts +242 -0
  117. package/dist/integrations/agentic-flow/migration/migrate-to-agentdb.d.ts.map +1 -0
  118. package/dist/learning/index.d.ts +91 -0
  119. package/dist/learning/index.d.ts.map +1 -0
  120. package/dist/learning/learning-loop.d.ts +176 -0
  121. package/dist/learning/learning-loop.d.ts.map +1 -0
  122. package/dist/learning/services/ab-testing-framework.d.ts +135 -0
  123. package/dist/learning/services/ab-testing-framework.d.ts.map +1 -0
  124. package/dist/learning/services/agent-priming-service.d.ts +207 -0
  125. package/dist/learning/services/agent-priming-service.d.ts.map +1 -0
  126. package/dist/learning/services/daily-log-generator.d.ts +113 -0
  127. package/dist/learning/services/daily-log-generator.d.ts.map +1 -0
  128. package/dist/learning/services/index.d.ts +14 -0
  129. package/dist/learning/services/index.d.ts.map +1 -0
  130. package/dist/learning/services/memory-extraction-service.d.ts +87 -0
  131. package/dist/learning/services/memory-extraction-service.d.ts.map +1 -0
  132. package/dist/learning/services/task-completion-consumer.d.ts +162 -0
  133. package/dist/learning/services/task-completion-consumer.d.ts.map +1 -0
  134. package/dist/learning/services/trajectory-tracker.d.ts +174 -0
  135. package/dist/learning/services/trajectory-tracker.d.ts.map +1 -0
  136. package/dist/learning/types.d.ts +516 -0
  137. package/dist/learning/types.d.ts.map +1 -0
  138. package/dist/mcp/clients/claude-flow-memory-client.d.ts +259 -0
  139. package/dist/mcp/clients/claude-flow-memory-client.d.ts.map +1 -0
  140. package/dist/mcp/clients/claude-flow-memory-client.js +305 -0
  141. package/dist/mcp/clients/claude-flow-memory-client.js.map +1 -0
  142. package/dist/mcp/clients/index.d.ts +11 -0
  143. package/dist/mcp/clients/index.d.ts.map +1 -0
  144. package/dist/mcp/clients/mcp-client-adapter.d.ts +146 -0
  145. package/dist/mcp/clients/mcp-client-adapter.d.ts.map +1 -0
  146. package/dist/mcp/clients/mcp-client-adapter.js +372 -0
  147. package/dist/mcp/clients/mcp-client-adapter.js.map +1 -0
  148. package/dist/mcp/index.d.ts +10 -0
  149. package/dist/mcp/index.d.ts.map +1 -0
  150. package/dist/memory/vault-sync.d.ts +12 -0
  151. package/dist/memory/vault-sync.d.ts.map +1 -1
  152. package/dist/memory/vault-sync.js +94 -11
  153. package/dist/memory/vault-sync.js.map +1 -1
  154. package/dist/node_modules/@huggingface/jinja/dist/index.js +118 -0
  155. package/dist/node_modules/@huggingface/jinja/dist/index.js.map +1 -0
  156. package/dist/node_modules/@typescript-eslint/project-service/dist/index.js +1 -1
  157. package/dist/node_modules/@xenova/transformers/src/backends/onnx.js +24 -0
  158. package/dist/node_modules/@xenova/transformers/src/backends/onnx.js.map +1 -0
  159. package/dist/node_modules/@xenova/transformers/src/configs.js +52 -0
  160. package/dist/node_modules/@xenova/transformers/src/configs.js.map +1 -0
  161. package/dist/node_modules/@xenova/transformers/src/env.js +35 -0
  162. package/dist/node_modules/@xenova/transformers/src/env.js.map +1 -0
  163. package/dist/node_modules/@xenova/transformers/src/models.js +3852 -0
  164. package/dist/node_modules/@xenova/transformers/src/models.js.map +1 -0
  165. package/dist/node_modules/@xenova/transformers/src/tokenizers.js +144 -0
  166. package/dist/node_modules/@xenova/transformers/src/tokenizers.js.map +1 -0
  167. package/dist/node_modules/@xenova/transformers/src/utils/core.js +52 -0
  168. package/dist/node_modules/@xenova/transformers/src/utils/core.js.map +1 -0
  169. package/dist/node_modules/@xenova/transformers/src/utils/generation.js +623 -0
  170. package/dist/node_modules/@xenova/transformers/src/utils/generation.js.map +1 -0
  171. package/dist/node_modules/@xenova/transformers/src/utils/hub.js +395 -0
  172. package/dist/node_modules/@xenova/transformers/src/utils/hub.js.map +1 -0
  173. package/dist/node_modules/@xenova/transformers/src/utils/image.js +12 -0
  174. package/dist/node_modules/@xenova/transformers/src/utils/image.js.map +1 -0
  175. package/dist/node_modules/@xenova/transformers/src/utils/maths.js +89 -0
  176. package/dist/node_modules/@xenova/transformers/src/utils/maths.js.map +1 -0
  177. package/dist/node_modules/@xenova/transformers/src/utils/tensor.js +750 -0
  178. package/dist/node_modules/@xenova/transformers/src/utils/tensor.js.map +1 -0
  179. package/dist/node_modules/fdir/dist/index.js +13 -13
  180. package/dist/node_modules/fdir/dist/index.js.map +1 -1
  181. package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js +67 -0
  182. package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js.map +1 -0
  183. package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js +24 -0
  184. package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js.map +1 -0
  185. package/dist/node_modules/onnxruntime-common/dist/lib/env.js +6 -0
  186. package/dist/node_modules/onnxruntime-common/dist/lib/env.js.map +1 -0
  187. package/dist/node_modules/onnxruntime-common/dist/lib/index.js +11 -0
  188. package/dist/node_modules/onnxruntime-common/dist/lib/index.js.map +1 -0
  189. package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js +162 -0
  190. package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js.map +1 -0
  191. package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js +6 -0
  192. package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js.map +1 -0
  193. package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js +393 -0
  194. package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js.map +1 -0
  195. package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js +6 -0
  196. package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js.map +1 -0
  197. package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js +12919 -0
  198. package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js.map +1 -0
  199. package/dist/node_modules/tinyglobby/dist/index.js +14 -14
  200. package/dist/node_modules/tinyglobby/dist/index.js.map +1 -1
  201. package/dist/node_modules/typescript/lib/typescript.js +24 -24
  202. package/dist/node_modules/typescript/lib/typescript.js.map +1 -1
  203. package/dist/transport/agent-transport.d.ts +269 -0
  204. package/dist/transport/agent-transport.d.ts.map +1 -0
  205. package/dist/transport/index.d.ts +10 -0
  206. package/dist/transport/index.d.ts.map +1 -0
  207. package/dist/vector/index.d.ts +1 -1
  208. package/dist/vector/index.d.ts.map +1 -1
  209. package/dist/vector/services/embedding-service.d.ts +244 -0
  210. package/dist/vector/services/embedding-service.d.ts.map +1 -0
  211. package/dist/vector/services/embedding-service.js +10 -0
  212. package/dist/vector/services/embedding-service.js.map +1 -0
  213. package/dist/vector/services/hybrid-search.d.ts +320 -0
  214. package/dist/vector/services/hybrid-search.d.ts.map +1 -0
  215. package/dist/vector/services/hybrid-search.js +3 -0
  216. package/dist/vector/services/hybrid-search.js.map +1 -0
  217. package/dist/vector/services/index.d.ts +4 -0
  218. package/dist/vector/services/index.d.ts.map +1 -1
  219. package/package.json +10 -1
@@ -1,6 +1,8 @@
1
1
  import { createHash } from "crypto";
2
2
  import { createLogger } from "../utils/logger.js";
3
3
  import { ShadowCache } from "../core/cache.js";
4
+ import "../mcp/clients/mcp-client-adapter.js";
5
+ import { createClaudeFlowMemoryClient } from "../mcp/clients/claude-flow-memory-client.js";
4
6
  const logger = createLogger("vault-sync");
5
7
  class VaultMemorySync {
6
8
  options;
@@ -12,6 +14,7 @@ class VaultMemorySync {
12
14
  isSyncing = false;
13
15
  syncErrors = [];
14
16
  autoSyncTimer = null;
17
+ mcpClient;
15
18
  constructor(options) {
16
19
  this.options = {
17
20
  projectRoot: options.projectRoot,
@@ -23,12 +26,20 @@ class VaultMemorySync {
23
26
  retryOptions: options.retryOptions ?? { maxRetries: 3, initialDelay: 1e3 },
24
27
  batchSize: options.batchSize ?? 50,
25
28
  includeContent: options.includeContent ?? false,
26
- maxContentLength: options.maxContentLength ?? 5e3
29
+ maxContentLength: options.maxContentLength ?? 5e3,
30
+ mcpClientConfig: options.mcpClientConfig
27
31
  };
28
32
  this.shadowCache = new ShadowCache({
29
33
  projectRoot: options.projectRoot,
30
34
  cacheDir: ".kg/sync-cache"
31
35
  });
36
+ this.mcpClient = createClaudeFlowMemoryClient({
37
+ namespace: this.options.namespace,
38
+ maxRetries: this.options.retryOptions?.maxRetries ?? 3,
39
+ retryDelayMs: this.options.retryOptions?.initialDelay ?? 1e3,
40
+ fallbackEnabled: true,
41
+ ...options.mcpClientConfig
42
+ });
32
43
  }
33
44
  /**
34
45
  * Initialize the sync system with database
@@ -258,6 +269,18 @@ class VaultMemorySync {
258
269
  (err) => logger.error("Failed to save memory cache on stop", err)
259
270
  );
260
271
  }
272
+ /**
273
+ * Check if the claude-flow CLI is available
274
+ */
275
+ async isCliAvailable() {
276
+ return this.mcpClient.isCliAvailable();
277
+ }
278
+ /**
279
+ * Get the MCP client for advanced usage
280
+ */
281
+ getMcpClient() {
282
+ return this.mcpClient;
283
+ }
261
284
  // Private methods
262
285
  startAutoSync() {
263
286
  if (this.autoSyncTimer) {
@@ -311,16 +334,54 @@ class VaultMemorySync {
311
334
  return createHash("md5").update(content).digest("hex").substring(0, 16);
312
335
  }
313
336
  async storeToMemory(node) {
314
- logger.debug("Store to memory", {
315
- key: `node/${node.id}`,
316
- namespace: this.options.namespace
317
- });
337
+ const entry = {
338
+ id: node.id,
339
+ title: node.title,
340
+ type: node.type,
341
+ status: node.status,
342
+ path: node.path,
343
+ tags: node.tags,
344
+ outgoingLinks: node.outgoingLinks,
345
+ incomingLinks: node.incomingLinks,
346
+ summary: node.summary,
347
+ contentHash: node.contentHash,
348
+ lastModified: node.lastModified,
349
+ syncedAt: node.syncedAt
350
+ };
351
+ const success = await this.mcpClient.storeNode(entry);
352
+ if (success) {
353
+ logger.debug("Stored node to memory via MCP", {
354
+ nodeId: node.id,
355
+ namespace: this.options.namespace
356
+ });
357
+ } else {
358
+ logger.warn("Failed to store node to memory via MCP, using fallback", {
359
+ nodeId: node.id,
360
+ namespace: this.options.namespace
361
+ });
362
+ }
318
363
  }
319
364
  async retrieveFromMemory() {
320
- logger.debug("Retrieve from memory", {
365
+ logger.debug("Retrieving nodes from memory via MCP", {
321
366
  namespace: this.options.namespace
322
367
  });
323
- return Array.from(this.memoryCache.values());
368
+ const nodeIndex = await this.mcpClient.getNodeIndex();
369
+ if (!nodeIndex || nodeIndex.length === 0) {
370
+ logger.debug("No node index found in memory, using local cache");
371
+ return Array.from(this.memoryCache.values());
372
+ }
373
+ const nodes = [];
374
+ for (const indexEntry of nodeIndex) {
375
+ const nodeEntry = await this.mcpClient.getNode(indexEntry.id);
376
+ if (nodeEntry) {
377
+ nodes.push(nodeEntry);
378
+ }
379
+ }
380
+ logger.debug("Retrieved nodes from memory via MCP", {
381
+ count: nodes.length,
382
+ namespace: this.options.namespace
383
+ });
384
+ return nodes;
324
385
  }
325
386
  async syncIndexesToMemory(nodes) {
326
387
  const nodeIndex = nodes.map((n) => ({
@@ -329,8 +390,10 @@ class VaultMemorySync {
329
390
  type: n.type,
330
391
  path: n.path
331
392
  }));
332
- logger.debug("Sync node index", {
393
+ const indexSuccess = await this.mcpClient.storeNodeIndex(nodeIndex);
394
+ logger.debug("Synced node index via MCP", {
333
395
  count: nodeIndex.length,
396
+ success: indexSuccess,
334
397
  namespace: this.options.namespace
335
398
  });
336
399
  const tagIndex = {};
@@ -342,8 +405,10 @@ class VaultMemorySync {
342
405
  tagIndex[tag].push(node.id);
343
406
  }
344
407
  }
345
- logger.debug("Sync tag index", {
408
+ const tagSuccess = await this.mcpClient.storeTagIndex(tagIndex);
409
+ logger.debug("Synced tag index via MCP", {
346
410
  tags: Object.keys(tagIndex).length,
411
+ success: tagSuccess,
347
412
  namespace: this.options.namespace
348
413
  });
349
414
  const metadata = {
@@ -351,7 +416,11 @@ class VaultMemorySync {
351
416
  nodeCount: nodes.length,
352
417
  namespace: this.options.namespace
353
418
  };
354
- logger.debug("Sync metadata", metadata);
419
+ const metaSuccess = await this.mcpClient.storeMetadata(metadata);
420
+ logger.debug("Synced metadata via MCP", {
421
+ success: metaSuccess,
422
+ metadata
423
+ });
355
424
  }
356
425
  async detectConflict(node, cached) {
357
426
  const vaultHash = this.computeContentHash(node.content);
@@ -446,7 +515,21 @@ class VaultMemorySync {
446
515
  return batches;
447
516
  }
448
517
  async loadMemoryCache() {
449
- logger.debug("Loading memory cache");
518
+ logger.debug("Loading memory cache from MCP");
519
+ const nodeIndex = await this.mcpClient.getNodeIndex();
520
+ if (!nodeIndex || nodeIndex.length === 0) {
521
+ logger.debug("No existing memory cache found in MCP");
522
+ return;
523
+ }
524
+ for (const indexEntry of nodeIndex) {
525
+ const nodeEntry = await this.mcpClient.getNode(indexEntry.id);
526
+ if (nodeEntry) {
527
+ this.memoryCache.set(indexEntry.id, nodeEntry);
528
+ }
529
+ }
530
+ logger.debug("Loaded memory cache from MCP", {
531
+ count: this.memoryCache.size
532
+ });
450
533
  }
451
534
  async saveMemoryCache() {
452
535
  await this.shadowCache.save();
@@ -1 +1 @@
1
- {"version":3,"file":"vault-sync.js","sources":["../../src/memory/vault-sync.ts"],"sourcesContent":["/**\n * Vault Memory Sync\n *\n * Provides bidirectional synchronization between the knowledge graph\n * and claude-flow memory system for persistent agent coordination.\n *\n * @module memory/vault-sync\n */\n\nimport { createHash } from 'crypto';\nimport { createLogger, withRetry, type RetryOptions } from '../utils/index.js';\nimport { ShadowCache, type FileMetadata, type FileChange } from '../core/cache.js';\nimport type { KnowledgeNode, GraphStats, SyncResult } from '../core/types.js';\nimport { KnowledgeGraphDatabase } from '../core/database.js';\n\nconst logger = createLogger('vault-sync');\n\n/**\n * Sync direction\n */\nexport type SyncDirection = 'to-memory' | 'from-memory' | 'bidirectional';\n\n/**\n * Conflict resolution strategy\n */\nexport type ConflictStrategy =\n | 'memory-wins' // Memory version takes precedence\n | 'vault-wins' // Vault version takes precedence\n | 'newest-wins' // Most recently modified wins\n | 'merge' // Attempt to merge changes\n | 'manual'; // Require manual resolution\n\n/**\n * Sync status\n */\nexport interface SyncStatus {\n /** Last successful sync timestamp */\n lastSync: Date | null;\n /** Whether sync is currently running */\n isSyncing: boolean;\n /** Number of pending changes in vault */\n pendingVaultChanges: number;\n /** Number of pending changes in memory */\n pendingMemoryChanges: number;\n /** Any sync errors */\n errors: string[];\n /** Sync health status */\n health: 'healthy' | 'warning' | 'error';\n}\n\n/**\n * Memory entry format for claude-flow\n */\nexport interface MemoryNode {\n id: string;\n title: string;\n type: string;\n status: string;\n path: string;\n tags: string[];\n outgoingLinks: string[];\n incomingLinks: string[];\n summary: string;\n contentHash: string;\n lastModified: string;\n syncedAt: string;\n}\n\n/**\n * Conflict record\n */\nexport interface SyncConflict {\n nodeId: string;\n path: string;\n vaultVersion: {\n hash: string;\n modifiedAt: Date;\n content?: string;\n };\n memoryVersion: {\n hash: string;\n modifiedAt: Date;\n content?: string;\n };\n resolvedAs?: 'vault' | 'memory' | 'merged';\n resolvedAt?: Date;\n}\n\n/**\n * Sync options\n */\nexport interface VaultSyncOptions {\n /** Project root directory */\n projectRoot: string;\n /** Claude-flow memory namespace */\n namespace?: string;\n /** Conflict resolution strategy */\n conflictStrategy?: ConflictStrategy;\n /** Whether to auto-sync on changes */\n autoSync?: boolean;\n /** Auto-sync interval in milliseconds */\n autoSyncInterval?: number;\n /** Retry options for network operations */\n retryOptions?: RetryOptions;\n /** Maximum batch size for sync operations */\n batchSize?: number;\n /** Whether to include content in memory entries */\n includeContent?: boolean;\n /** Maximum content length to store */\n maxContentLength?: number;\n}\n\n/**\n * Sync result for a single operation\n */\nexport interface SyncOperationResult {\n success: boolean;\n synced: number;\n skipped: number;\n failed: number;\n conflicts: SyncConflict[];\n errors: Array<{ nodeId: string; error: string }>;\n duration: number;\n}\n\n/**\n * Full sync result\n */\nexport interface FullSyncResult {\n success: boolean;\n toMemory: SyncOperationResult;\n fromMemory: SyncOperationResult;\n totalDuration: number;\n timestamp: Date;\n}\n\n/**\n * Vault Memory Sync\n *\n * Manages bidirectional synchronization between the knowledge graph vault\n * and claude-flow memory for cross-session persistence and agent coordination.\n *\n * @example\n * ```typescript\n * const sync = new VaultMemorySync({\n * projectRoot: '/my/project',\n * namespace: 'knowledge-graph',\n * conflictStrategy: 'newest-wins',\n * });\n *\n * // Initialize with database\n * await sync.initialize(db);\n *\n * // Sync to memory\n * const result = await sync.syncToMemory();\n *\n * // Check status\n * const status = sync.getStatus();\n * ```\n */\nexport class VaultMemorySync {\n private options: Required<VaultSyncOptions>;\n private shadowCache: ShadowCache;\n private db: KnowledgeGraphDatabase | null = null;\n private memoryCache: Map<string, MemoryNode> = new Map();\n private conflicts: SyncConflict[] = [];\n private lastSyncTime: Date | null = null;\n private isSyncing = false;\n private syncErrors: string[] = [];\n private autoSyncTimer: NodeJS.Timeout | null = null;\n\n constructor(options: VaultSyncOptions) {\n this.options = {\n projectRoot: options.projectRoot,\n namespace: options.namespace ?? 'knowledge-graph',\n conflictStrategy: options.conflictStrategy ?? 'newest-wins',\n autoSync: options.autoSync ?? false,\n autoSyncInterval: options.autoSyncInterval ?? 300000, // 5 minutes\n retryOptions: options.retryOptions ?? { maxRetries: 3, initialDelay: 1000 },\n batchSize: options.batchSize ?? 50,\n includeContent: options.includeContent ?? false,\n maxContentLength: options.maxContentLength ?? 5000,\n };\n\n this.shadowCache = new ShadowCache({\n projectRoot: options.projectRoot,\n cacheDir: '.kg/sync-cache',\n });\n }\n\n /**\n * Initialize the sync system with database\n */\n async initialize(db: KnowledgeGraphDatabase): Promise<void> {\n this.db = db;\n await this.shadowCache.load();\n\n // Load memory cache from previous sync\n await this.loadMemoryCache();\n\n if (this.options.autoSync) {\n this.startAutoSync();\n }\n\n logger.info('Vault sync initialized', {\n namespace: this.options.namespace,\n autoSync: this.options.autoSync,\n });\n }\n\n /**\n * Sync knowledge graph to claude-flow memory\n */\n async syncToMemory(): Promise<SyncOperationResult> {\n if (!this.db) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n\n const startTime = Date.now();\n const result: SyncOperationResult = {\n success: true,\n synced: 0,\n skipped: 0,\n failed: 0,\n conflicts: [],\n errors: [],\n duration: 0,\n };\n\n this.isSyncing = true;\n this.syncErrors = [];\n\n try {\n const nodes = this.db.getAllNodes();\n const batches = this.createBatches(nodes, this.options.batchSize);\n\n for (const batch of batches) {\n for (const node of batch) {\n try {\n const memoryNode = this.nodeToMemoryEntry(node);\n const cached = this.memoryCache.get(node.id);\n\n // Check for conflicts\n if (cached && cached.contentHash !== memoryNode.contentHash) {\n const conflict = await this.detectConflict(node, cached);\n if (conflict) {\n result.conflicts.push(conflict);\n const resolved = await this.resolveConflict(conflict);\n if (!resolved) {\n result.skipped++;\n continue;\n }\n }\n }\n\n // Generate MCP command for sync\n await this.storeToMemory(memoryNode);\n this.memoryCache.set(node.id, memoryNode);\n result.synced++;\n } catch (error) {\n result.failed++;\n result.errors.push({\n nodeId: node.id,\n error: String(error),\n });\n this.syncErrors.push(`Failed to sync ${node.id}: ${error}`);\n }\n }\n }\n\n // Sync indexes and metadata\n await this.syncIndexesToMemory(nodes);\n\n result.duration = Date.now() - startTime;\n result.success = result.failed === 0;\n this.lastSyncTime = new Date();\n\n logger.info('Sync to memory completed', {\n synced: result.synced,\n failed: result.failed,\n duration: result.duration,\n });\n } finally {\n this.isSyncing = false;\n await this.saveMemoryCache();\n }\n\n return result;\n }\n\n /**\n * Sync from claude-flow memory to knowledge graph\n */\n async syncFromMemory(): Promise<SyncOperationResult> {\n if (!this.db) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n\n const startTime = Date.now();\n const result: SyncOperationResult = {\n success: true,\n synced: 0,\n skipped: 0,\n failed: 0,\n conflicts: [],\n errors: [],\n duration: 0,\n };\n\n this.isSyncing = true;\n this.syncErrors = [];\n\n try {\n // Retrieve node index from memory\n const memoryNodes = await this.retrieveFromMemory();\n\n for (const memoryNode of memoryNodes) {\n try {\n const existingNode = this.db.getNode(memoryNode.id);\n\n if (existingNode) {\n // Check for conflicts\n const currentHash = this.computeContentHash(existingNode.content);\n if (currentHash !== memoryNode.contentHash) {\n const conflict = this.createConflictRecord(existingNode, memoryNode);\n result.conflicts.push(conflict);\n\n const resolved = await this.resolveConflict(conflict);\n if (!resolved || conflict.resolvedAs === 'vault') {\n result.skipped++;\n continue;\n }\n }\n }\n\n // Memory sync would update vault files if needed\n // For now, we track what would be synced\n result.synced++;\n this.memoryCache.set(memoryNode.id, memoryNode);\n } catch (error) {\n result.failed++;\n result.errors.push({\n nodeId: memoryNode.id,\n error: String(error),\n });\n }\n }\n\n result.duration = Date.now() - startTime;\n result.success = result.failed === 0;\n this.lastSyncTime = new Date();\n\n logger.info('Sync from memory completed', {\n synced: result.synced,\n failed: result.failed,\n duration: result.duration,\n });\n } finally {\n this.isSyncing = false;\n await this.saveMemoryCache();\n }\n\n return result;\n }\n\n /**\n * Perform full bidirectional sync\n */\n async fullSync(): Promise<FullSyncResult> {\n const startTime = Date.now();\n\n const toMemory = await this.syncToMemory();\n const fromMemory = await this.syncFromMemory();\n\n return {\n success: toMemory.success && fromMemory.success,\n toMemory,\n fromMemory,\n totalDuration: Date.now() - startTime,\n timestamp: new Date(),\n };\n }\n\n /**\n * Get current sync status\n */\n getStatus(): SyncStatus {\n const pendingVaultChanges = this.db\n ? this.countPendingVaultChanges()\n : 0;\n\n const pendingMemoryChanges = this.countPendingMemoryChanges();\n\n let health: SyncStatus['health'] = 'healthy';\n if (this.syncErrors.length > 0) {\n health = 'error';\n } else if (this.conflicts.length > 0 || pendingVaultChanges > 10) {\n health = 'warning';\n }\n\n return {\n lastSync: this.lastSyncTime,\n isSyncing: this.isSyncing,\n pendingVaultChanges,\n pendingMemoryChanges,\n errors: [...this.syncErrors],\n health,\n };\n }\n\n /**\n * Get unresolved conflicts\n */\n getConflicts(): SyncConflict[] {\n return this.conflicts.filter(c => !c.resolvedAt);\n }\n\n /**\n * Manually resolve a conflict\n */\n async resolveConflictManually(\n nodeId: string,\n resolution: 'vault' | 'memory'\n ): Promise<boolean> {\n const conflict = this.conflicts.find(\n c => c.nodeId === nodeId && !c.resolvedAt\n );\n\n if (!conflict) {\n return false;\n }\n\n conflict.resolvedAs = resolution;\n conflict.resolvedAt = new Date();\n\n if (resolution === 'vault' && this.db) {\n // Re-sync vault version to memory\n const node = this.db.getNode(nodeId);\n if (node) {\n const memoryNode = this.nodeToMemoryEntry(node);\n await this.storeToMemory(memoryNode);\n this.memoryCache.set(nodeId, memoryNode);\n }\n }\n\n return true;\n }\n\n /**\n * Detect changes in vault since last sync\n */\n async detectChanges(): Promise<FileChange[]> {\n if (!this.db) {\n return [];\n }\n\n const nodes = this.db.getAllNodes();\n const filePaths = nodes.map(n => n.path);\n\n return this.shadowCache.detectChanges(filePaths);\n }\n\n /**\n * Stop the sync system\n */\n stop(): void {\n if (this.autoSyncTimer) {\n clearInterval(this.autoSyncTimer);\n this.autoSyncTimer = null;\n }\n this.saveMemoryCache().catch(err =>\n logger.error('Failed to save memory cache on stop', err)\n );\n }\n\n // Private methods\n\n private startAutoSync(): void {\n if (this.autoSyncTimer) {\n clearInterval(this.autoSyncTimer);\n }\n\n this.autoSyncTimer = setInterval(async () => {\n if (!this.isSyncing) {\n try {\n await this.syncToMemory();\n } catch (error) {\n logger.error('Auto-sync failed', error as Error);\n }\n }\n }, this.options.autoSyncInterval);\n }\n\n private nodeToMemoryEntry(node: KnowledgeNode): MemoryNode {\n const summary = this.extractSummary(node.content);\n const contentHash = this.computeContentHash(node.content);\n\n return {\n id: node.id,\n title: node.title,\n type: node.type,\n status: node.status,\n path: node.path,\n tags: node.tags,\n outgoingLinks: node.outgoingLinks.map(l => l.target),\n incomingLinks: node.incomingLinks.map(l => l.target),\n summary,\n contentHash,\n lastModified: node.lastModified.toISOString(),\n syncedAt: new Date().toISOString(),\n };\n }\n\n private extractSummary(content: string, maxLength = 200): string {\n const lines = content.split('\\n');\n let summary = '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('```') || trimmed === '---') {\n continue;\n }\n summary = trimmed;\n break;\n }\n\n if (summary.length > maxLength) {\n summary = summary.slice(0, maxLength - 3) + '...';\n }\n\n return summary;\n }\n\n private computeContentHash(content: string): string {\n return createHash('md5').update(content).digest('hex').substring(0, 16);\n }\n\n private async storeToMemory(node: MemoryNode): Promise<void> {\n // This would integrate with actual claude-flow MCP calls\n // For now, we log the command that would be executed\n logger.debug('Store to memory', {\n key: `node/${node.id}`,\n namespace: this.options.namespace,\n });\n\n // In production, this would call:\n // await mcpClient.memoryUsage({\n // action: 'store',\n // key: `node/${node.id}`,\n // namespace: this.options.namespace,\n // value: JSON.stringify(node),\n // });\n }\n\n private async retrieveFromMemory(): Promise<MemoryNode[]> {\n // This would integrate with actual claude-flow MCP calls\n // For now, return cached nodes\n logger.debug('Retrieve from memory', {\n namespace: this.options.namespace,\n });\n\n return Array.from(this.memoryCache.values());\n }\n\n private async syncIndexesToMemory(nodes: KnowledgeNode[]): Promise<void> {\n // Sync node index\n const nodeIndex = nodes.map(n => ({\n id: n.id,\n title: n.title,\n type: n.type,\n path: n.path,\n }));\n\n logger.debug('Sync node index', {\n count: nodeIndex.length,\n namespace: this.options.namespace,\n });\n\n // Sync tag index\n const tagIndex: Record<string, string[]> = {};\n for (const node of nodes) {\n for (const tag of node.tags) {\n if (!tagIndex[tag]) {\n tagIndex[tag] = [];\n }\n tagIndex[tag].push(node.id);\n }\n }\n\n logger.debug('Sync tag index', {\n tags: Object.keys(tagIndex).length,\n namespace: this.options.namespace,\n });\n\n // Sync metadata\n const metadata = {\n lastSync: new Date().toISOString(),\n nodeCount: nodes.length,\n namespace: this.options.namespace,\n };\n\n logger.debug('Sync metadata', metadata);\n }\n\n private async detectConflict(\n node: KnowledgeNode,\n cached: MemoryNode\n ): Promise<SyncConflict | null> {\n const vaultHash = this.computeContentHash(node.content);\n\n if (vaultHash === cached.contentHash) {\n return null; // No conflict\n }\n\n return {\n nodeId: node.id,\n path: node.path,\n vaultVersion: {\n hash: vaultHash,\n modifiedAt: node.lastModified,\n content: this.options.includeContent ? node.content : undefined,\n },\n memoryVersion: {\n hash: cached.contentHash,\n modifiedAt: new Date(cached.lastModified),\n },\n };\n }\n\n private createConflictRecord(\n node: KnowledgeNode,\n memoryNode: MemoryNode\n ): SyncConflict {\n return {\n nodeId: node.id,\n path: node.path,\n vaultVersion: {\n hash: this.computeContentHash(node.content),\n modifiedAt: node.lastModified,\n },\n memoryVersion: {\n hash: memoryNode.contentHash,\n modifiedAt: new Date(memoryNode.lastModified),\n },\n };\n }\n\n private async resolveConflict(conflict: SyncConflict): Promise<boolean> {\n switch (this.options.conflictStrategy) {\n case 'vault-wins':\n conflict.resolvedAs = 'vault';\n conflict.resolvedAt = new Date();\n return true;\n\n case 'memory-wins':\n conflict.resolvedAs = 'memory';\n conflict.resolvedAt = new Date();\n return true;\n\n case 'newest-wins':\n if (conflict.vaultVersion.modifiedAt > conflict.memoryVersion.modifiedAt) {\n conflict.resolvedAs = 'vault';\n } else {\n conflict.resolvedAs = 'memory';\n }\n conflict.resolvedAt = new Date();\n return true;\n\n case 'merge':\n // Merge strategy would require content comparison\n // For now, fall back to newest-wins\n if (conflict.vaultVersion.modifiedAt > conflict.memoryVersion.modifiedAt) {\n conflict.resolvedAs = 'vault';\n } else {\n conflict.resolvedAs = 'memory';\n }\n conflict.resolvedAt = new Date();\n return true;\n\n case 'manual':\n // Don't auto-resolve, add to conflicts list\n this.conflicts.push(conflict);\n return false;\n\n default:\n return false;\n }\n }\n\n private countPendingVaultChanges(): number {\n const cachedHashes = new Map<string, string>();\n for (const [id, node] of this.memoryCache) {\n cachedHashes.set(id, node.contentHash);\n }\n\n let pending = 0;\n const nodes = this.db?.getAllNodes() ?? [];\n\n for (const node of nodes) {\n const cachedHash = cachedHashes.get(node.id);\n const currentHash = this.computeContentHash(node.content);\n\n if (!cachedHash || cachedHash !== currentHash) {\n pending++;\n }\n }\n\n return pending;\n }\n\n private countPendingMemoryChanges(): number {\n // In a real implementation, this would check memory for changes\n // that haven't been synced to vault\n return 0;\n }\n\n private createBatches<T>(items: T[], batchSize: number): T[][] {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n }\n\n private async loadMemoryCache(): Promise<void> {\n // In production, this would load from persistent storage\n // or retrieve the current state from claude-flow memory\n logger.debug('Loading memory cache');\n }\n\n private async saveMemoryCache(): Promise<void> {\n // Persist cache to disk for recovery\n await this.shadowCache.save();\n logger.debug('Memory cache saved');\n }\n}\n\n/**\n * Create a vault memory sync instance\n */\nexport function createVaultMemorySync(options: VaultSyncOptions): VaultMemorySync {\n return new VaultMemorySync(options);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vault-sync.js","sources":["../../src/memory/vault-sync.ts"],"sourcesContent":["/**\n * Vault Memory Sync\n *\n * Provides bidirectional synchronization between the knowledge graph\n * and claude-flow memory system for persistent agent coordination.\n *\n * @module memory/vault-sync\n */\n\nimport { createHash } from 'crypto';\nimport { createLogger, withRetry, type RetryOptions } from '../utils/index.js';\nimport { ShadowCache, type FileMetadata, type FileChange } from '../core/cache.js';\nimport type { KnowledgeNode, GraphStats, SyncResult } from '../core/types.js';\nimport { KnowledgeGraphDatabase } from '../core/database.js';\nimport {\n ClaudeFlowMemoryClient,\n createClaudeFlowMemoryClient,\n type MemoryNodeEntry,\n type MemoryIndexEntry,\n type ClaudeFlowMemoryClientConfig,\n} from '../mcp/clients/index.js';\n\nconst logger = createLogger('vault-sync');\n\n/**\n * Sync direction\n */\nexport type SyncDirection = 'to-memory' | 'from-memory' | 'bidirectional';\n\n/**\n * Conflict resolution strategy\n */\nexport type ConflictStrategy =\n | 'memory-wins' // Memory version takes precedence\n | 'vault-wins' // Vault version takes precedence\n | 'newest-wins' // Most recently modified wins\n | 'merge' // Attempt to merge changes\n | 'manual'; // Require manual resolution\n\n/**\n * Sync status\n */\nexport interface SyncStatus {\n /** Last successful sync timestamp */\n lastSync: Date | null;\n /** Whether sync is currently running */\n isSyncing: boolean;\n /** Number of pending changes in vault */\n pendingVaultChanges: number;\n /** Number of pending changes in memory */\n pendingMemoryChanges: number;\n /** Any sync errors */\n errors: string[];\n /** Sync health status */\n health: 'healthy' | 'warning' | 'error';\n}\n\n/**\n * Memory entry format for claude-flow\n */\nexport interface MemoryNode {\n id: string;\n title: string;\n type: string;\n status: string;\n path: string;\n tags: string[];\n outgoingLinks: string[];\n incomingLinks: string[];\n summary: string;\n contentHash: string;\n lastModified: string;\n syncedAt: string;\n}\n\n/**\n * Conflict record\n */\nexport interface SyncConflict {\n nodeId: string;\n path: string;\n vaultVersion: {\n hash: string;\n modifiedAt: Date;\n content?: string;\n };\n memoryVersion: {\n hash: string;\n modifiedAt: Date;\n content?: string;\n };\n resolvedAs?: 'vault' | 'memory' | 'merged';\n resolvedAt?: Date;\n}\n\n/**\n * Sync options\n */\nexport interface VaultSyncOptions {\n /** Project root directory */\n projectRoot: string;\n /** Claude-flow memory namespace */\n namespace?: string;\n /** Conflict resolution strategy */\n conflictStrategy?: ConflictStrategy;\n /** Whether to auto-sync on changes */\n autoSync?: boolean;\n /** Auto-sync interval in milliseconds */\n autoSyncInterval?: number;\n /** Retry options for network operations */\n retryOptions?: RetryOptions;\n /** Maximum batch size for sync operations */\n batchSize?: number;\n /** Whether to include content in memory entries */\n includeContent?: boolean;\n /** Maximum content length to store */\n maxContentLength?: number;\n /** MCP client configuration */\n mcpClientConfig?: Partial<ClaudeFlowMemoryClientConfig>;\n}\n\n/**\n * Sync result for a single operation\n */\nexport interface SyncOperationResult {\n success: boolean;\n synced: number;\n skipped: number;\n failed: number;\n conflicts: SyncConflict[];\n errors: Array<{ nodeId: string; error: string }>;\n duration: number;\n}\n\n/**\n * Full sync result\n */\nexport interface FullSyncResult {\n success: boolean;\n toMemory: SyncOperationResult;\n fromMemory: SyncOperationResult;\n totalDuration: number;\n timestamp: Date;\n}\n\n/**\n * Vault Memory Sync\n *\n * Manages bidirectional synchronization between the knowledge graph vault\n * and claude-flow memory for cross-session persistence and agent coordination.\n *\n * @example\n * ```typescript\n * const sync = new VaultMemorySync({\n * projectRoot: '/my/project',\n * namespace: 'knowledge-graph',\n * conflictStrategy: 'newest-wins',\n * });\n *\n * // Initialize with database\n * await sync.initialize(db);\n *\n * // Sync to memory\n * const result = await sync.syncToMemory();\n *\n * // Check status\n * const status = sync.getStatus();\n * ```\n */\nexport class VaultMemorySync {\n private options: Required<Omit<VaultSyncOptions, 'mcpClientConfig'>> & { mcpClientConfig?: Partial<ClaudeFlowMemoryClientConfig> };\n private shadowCache: ShadowCache;\n private db: KnowledgeGraphDatabase | null = null;\n private memoryCache: Map<string, MemoryNode> = new Map();\n private conflicts: SyncConflict[] = [];\n private lastSyncTime: Date | null = null;\n private isSyncing = false;\n private syncErrors: string[] = [];\n private autoSyncTimer: NodeJS.Timeout | null = null;\n private mcpClient: ClaudeFlowMemoryClient;\n\n constructor(options: VaultSyncOptions) {\n this.options = {\n projectRoot: options.projectRoot,\n namespace: options.namespace ?? 'knowledge-graph',\n conflictStrategy: options.conflictStrategy ?? 'newest-wins',\n autoSync: options.autoSync ?? false,\n autoSyncInterval: options.autoSyncInterval ?? 300000, // 5 minutes\n retryOptions: options.retryOptions ?? { maxRetries: 3, initialDelay: 1000 },\n batchSize: options.batchSize ?? 50,\n includeContent: options.includeContent ?? false,\n maxContentLength: options.maxContentLength ?? 5000,\n mcpClientConfig: options.mcpClientConfig,\n };\n\n this.shadowCache = new ShadowCache({\n projectRoot: options.projectRoot,\n cacheDir: '.kg/sync-cache',\n });\n\n // Initialize the MCP client for real claude-flow integration\n this.mcpClient = createClaudeFlowMemoryClient({\n namespace: this.options.namespace,\n maxRetries: this.options.retryOptions?.maxRetries ?? 3,\n retryDelayMs: this.options.retryOptions?.initialDelay ?? 1000,\n fallbackEnabled: true,\n ...options.mcpClientConfig,\n });\n }\n\n /**\n * Initialize the sync system with database\n */\n async initialize(db: KnowledgeGraphDatabase): Promise<void> {\n this.db = db;\n await this.shadowCache.load();\n\n // Load memory cache from previous sync\n await this.loadMemoryCache();\n\n if (this.options.autoSync) {\n this.startAutoSync();\n }\n\n logger.info('Vault sync initialized', {\n namespace: this.options.namespace,\n autoSync: this.options.autoSync,\n });\n }\n\n /**\n * Sync knowledge graph to claude-flow memory\n */\n async syncToMemory(): Promise<SyncOperationResult> {\n if (!this.db) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n\n const startTime = Date.now();\n const result: SyncOperationResult = {\n success: true,\n synced: 0,\n skipped: 0,\n failed: 0,\n conflicts: [],\n errors: [],\n duration: 0,\n };\n\n this.isSyncing = true;\n this.syncErrors = [];\n\n try {\n const nodes = this.db.getAllNodes();\n const batches = this.createBatches(nodes, this.options.batchSize);\n\n for (const batch of batches) {\n for (const node of batch) {\n try {\n const memoryNode = this.nodeToMemoryEntry(node);\n const cached = this.memoryCache.get(node.id);\n\n // Check for conflicts\n if (cached && cached.contentHash !== memoryNode.contentHash) {\n const conflict = await this.detectConflict(node, cached);\n if (conflict) {\n result.conflicts.push(conflict);\n const resolved = await this.resolveConflict(conflict);\n if (!resolved) {\n result.skipped++;\n continue;\n }\n }\n }\n\n // Generate MCP command for sync\n await this.storeToMemory(memoryNode);\n this.memoryCache.set(node.id, memoryNode);\n result.synced++;\n } catch (error) {\n result.failed++;\n result.errors.push({\n nodeId: node.id,\n error: String(error),\n });\n this.syncErrors.push(`Failed to sync ${node.id}: ${error}`);\n }\n }\n }\n\n // Sync indexes and metadata\n await this.syncIndexesToMemory(nodes);\n\n result.duration = Date.now() - startTime;\n result.success = result.failed === 0;\n this.lastSyncTime = new Date();\n\n logger.info('Sync to memory completed', {\n synced: result.synced,\n failed: result.failed,\n duration: result.duration,\n });\n } finally {\n this.isSyncing = false;\n await this.saveMemoryCache();\n }\n\n return result;\n }\n\n /**\n * Sync from claude-flow memory to knowledge graph\n */\n async syncFromMemory(): Promise<SyncOperationResult> {\n if (!this.db) {\n throw new Error('Database not initialized. Call initialize() first.');\n }\n\n const startTime = Date.now();\n const result: SyncOperationResult = {\n success: true,\n synced: 0,\n skipped: 0,\n failed: 0,\n conflicts: [],\n errors: [],\n duration: 0,\n };\n\n this.isSyncing = true;\n this.syncErrors = [];\n\n try {\n // Retrieve node index from memory\n const memoryNodes = await this.retrieveFromMemory();\n\n for (const memoryNode of memoryNodes) {\n try {\n const existingNode = this.db.getNode(memoryNode.id);\n\n if (existingNode) {\n // Check for conflicts\n const currentHash = this.computeContentHash(existingNode.content);\n if (currentHash !== memoryNode.contentHash) {\n const conflict = this.createConflictRecord(existingNode, memoryNode);\n result.conflicts.push(conflict);\n\n const resolved = await this.resolveConflict(conflict);\n if (!resolved || conflict.resolvedAs === 'vault') {\n result.skipped++;\n continue;\n }\n }\n }\n\n // Memory sync would update vault files if needed\n // For now, we track what would be synced\n result.synced++;\n this.memoryCache.set(memoryNode.id, memoryNode);\n } catch (error) {\n result.failed++;\n result.errors.push({\n nodeId: memoryNode.id,\n error: String(error),\n });\n }\n }\n\n result.duration = Date.now() - startTime;\n result.success = result.failed === 0;\n this.lastSyncTime = new Date();\n\n logger.info('Sync from memory completed', {\n synced: result.synced,\n failed: result.failed,\n duration: result.duration,\n });\n } finally {\n this.isSyncing = false;\n await this.saveMemoryCache();\n }\n\n return result;\n }\n\n /**\n * Perform full bidirectional sync\n */\n async fullSync(): Promise<FullSyncResult> {\n const startTime = Date.now();\n\n const toMemory = await this.syncToMemory();\n const fromMemory = await this.syncFromMemory();\n\n return {\n success: toMemory.success && fromMemory.success,\n toMemory,\n fromMemory,\n totalDuration: Date.now() - startTime,\n timestamp: new Date(),\n };\n }\n\n /**\n * Get current sync status\n */\n getStatus(): SyncStatus {\n const pendingVaultChanges = this.db\n ? this.countPendingVaultChanges()\n : 0;\n\n const pendingMemoryChanges = this.countPendingMemoryChanges();\n\n let health: SyncStatus['health'] = 'healthy';\n if (this.syncErrors.length > 0) {\n health = 'error';\n } else if (this.conflicts.length > 0 || pendingVaultChanges > 10) {\n health = 'warning';\n }\n\n return {\n lastSync: this.lastSyncTime,\n isSyncing: this.isSyncing,\n pendingVaultChanges,\n pendingMemoryChanges,\n errors: [...this.syncErrors],\n health,\n };\n }\n\n /**\n * Get unresolved conflicts\n */\n getConflicts(): SyncConflict[] {\n return this.conflicts.filter(c => !c.resolvedAt);\n }\n\n /**\n * Manually resolve a conflict\n */\n async resolveConflictManually(\n nodeId: string,\n resolution: 'vault' | 'memory'\n ): Promise<boolean> {\n const conflict = this.conflicts.find(\n c => c.nodeId === nodeId && !c.resolvedAt\n );\n\n if (!conflict) {\n return false;\n }\n\n conflict.resolvedAs = resolution;\n conflict.resolvedAt = new Date();\n\n if (resolution === 'vault' && this.db) {\n // Re-sync vault version to memory\n const node = this.db.getNode(nodeId);\n if (node) {\n const memoryNode = this.nodeToMemoryEntry(node);\n await this.storeToMemory(memoryNode);\n this.memoryCache.set(nodeId, memoryNode);\n }\n }\n\n return true;\n }\n\n /**\n * Detect changes in vault since last sync\n */\n async detectChanges(): Promise<FileChange[]> {\n if (!this.db) {\n return [];\n }\n\n const nodes = this.db.getAllNodes();\n const filePaths = nodes.map(n => n.path);\n\n return this.shadowCache.detectChanges(filePaths);\n }\n\n /**\n * Stop the sync system\n */\n stop(): void {\n if (this.autoSyncTimer) {\n clearInterval(this.autoSyncTimer);\n this.autoSyncTimer = null;\n }\n this.saveMemoryCache().catch(err =>\n logger.error('Failed to save memory cache on stop', err)\n );\n }\n\n /**\n * Check if the claude-flow CLI is available\n */\n async isCliAvailable(): Promise<boolean> {\n return this.mcpClient.isCliAvailable();\n }\n\n /**\n * Get the MCP client for advanced usage\n */\n getMcpClient(): ClaudeFlowMemoryClient {\n return this.mcpClient;\n }\n\n // Private methods\n\n private startAutoSync(): void {\n if (this.autoSyncTimer) {\n clearInterval(this.autoSyncTimer);\n }\n\n this.autoSyncTimer = setInterval(async () => {\n if (!this.isSyncing) {\n try {\n await this.syncToMemory();\n } catch (error) {\n logger.error('Auto-sync failed', error as Error);\n }\n }\n }, this.options.autoSyncInterval);\n }\n\n private nodeToMemoryEntry(node: KnowledgeNode): MemoryNode {\n const summary = this.extractSummary(node.content);\n const contentHash = this.computeContentHash(node.content);\n\n return {\n id: node.id,\n title: node.title,\n type: node.type,\n status: node.status,\n path: node.path,\n tags: node.tags,\n outgoingLinks: node.outgoingLinks.map(l => l.target),\n incomingLinks: node.incomingLinks.map(l => l.target),\n summary,\n contentHash,\n lastModified: node.lastModified.toISOString(),\n syncedAt: new Date().toISOString(),\n };\n }\n\n private extractSummary(content: string, maxLength = 200): string {\n const lines = content.split('\\n');\n let summary = '';\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#') || trimmed.startsWith('```') || trimmed === '---') {\n continue;\n }\n summary = trimmed;\n break;\n }\n\n if (summary.length > maxLength) {\n summary = summary.slice(0, maxLength - 3) + '...';\n }\n\n return summary;\n }\n\n private computeContentHash(content: string): string {\n return createHash('md5').update(content).digest('hex').substring(0, 16);\n }\n\n private async storeToMemory(node: MemoryNode): Promise<void> {\n // Convert MemoryNode to MemoryNodeEntry for the MCP client\n const entry: MemoryNodeEntry = {\n id: node.id,\n title: node.title,\n type: node.type,\n status: node.status,\n path: node.path,\n tags: node.tags,\n outgoingLinks: node.outgoingLinks,\n incomingLinks: node.incomingLinks,\n summary: node.summary,\n contentHash: node.contentHash,\n lastModified: node.lastModified,\n syncedAt: node.syncedAt,\n };\n\n const success = await this.mcpClient.storeNode(entry);\n\n if (success) {\n logger.debug('Stored node to memory via MCP', {\n nodeId: node.id,\n namespace: this.options.namespace,\n });\n } else {\n logger.warn('Failed to store node to memory via MCP, using fallback', {\n nodeId: node.id,\n namespace: this.options.namespace,\n });\n }\n }\n\n private async retrieveFromMemory(): Promise<MemoryNode[]> {\n logger.debug('Retrieving nodes from memory via MCP', {\n namespace: this.options.namespace,\n });\n\n // First try to get the node index from MCP\n const nodeIndex = await this.mcpClient.getNodeIndex();\n\n if (!nodeIndex || nodeIndex.length === 0) {\n logger.debug('No node index found in memory, using local cache');\n return Array.from(this.memoryCache.values());\n }\n\n // Retrieve each node from MCP\n const nodes: MemoryNode[] = [];\n for (const indexEntry of nodeIndex) {\n const nodeEntry = await this.mcpClient.getNode(indexEntry.id);\n if (nodeEntry) {\n nodes.push(nodeEntry as MemoryNode);\n }\n }\n\n logger.debug('Retrieved nodes from memory via MCP', {\n count: nodes.length,\n namespace: this.options.namespace,\n });\n\n return nodes;\n }\n\n private async syncIndexesToMemory(nodes: KnowledgeNode[]): Promise<void> {\n // Sync node index\n const nodeIndex: MemoryIndexEntry[] = nodes.map(n => ({\n id: n.id,\n title: n.title,\n type: n.type,\n path: n.path,\n }));\n\n const indexSuccess = await this.mcpClient.storeNodeIndex(nodeIndex);\n logger.debug('Synced node index via MCP', {\n count: nodeIndex.length,\n success: indexSuccess,\n namespace: this.options.namespace,\n });\n\n // Sync tag index\n const tagIndex: Record<string, string[]> = {};\n for (const node of nodes) {\n for (const tag of node.tags) {\n if (!tagIndex[tag]) {\n tagIndex[tag] = [];\n }\n tagIndex[tag].push(node.id);\n }\n }\n\n const tagSuccess = await this.mcpClient.storeTagIndex(tagIndex);\n logger.debug('Synced tag index via MCP', {\n tags: Object.keys(tagIndex).length,\n success: tagSuccess,\n namespace: this.options.namespace,\n });\n\n // Sync metadata\n const metadata = {\n lastSync: new Date().toISOString(),\n nodeCount: nodes.length,\n namespace: this.options.namespace,\n };\n\n const metaSuccess = await this.mcpClient.storeMetadata(metadata);\n logger.debug('Synced metadata via MCP', {\n success: metaSuccess,\n metadata,\n });\n }\n\n private async detectConflict(\n node: KnowledgeNode,\n cached: MemoryNode\n ): Promise<SyncConflict | null> {\n const vaultHash = this.computeContentHash(node.content);\n\n if (vaultHash === cached.contentHash) {\n return null; // No conflict\n }\n\n return {\n nodeId: node.id,\n path: node.path,\n vaultVersion: {\n hash: vaultHash,\n modifiedAt: node.lastModified,\n content: this.options.includeContent ? node.content : undefined,\n },\n memoryVersion: {\n hash: cached.contentHash,\n modifiedAt: new Date(cached.lastModified),\n },\n };\n }\n\n private createConflictRecord(\n node: KnowledgeNode,\n memoryNode: MemoryNode\n ): SyncConflict {\n return {\n nodeId: node.id,\n path: node.path,\n vaultVersion: {\n hash: this.computeContentHash(node.content),\n modifiedAt: node.lastModified,\n },\n memoryVersion: {\n hash: memoryNode.contentHash,\n modifiedAt: new Date(memoryNode.lastModified),\n },\n };\n }\n\n private async resolveConflict(conflict: SyncConflict): Promise<boolean> {\n switch (this.options.conflictStrategy) {\n case 'vault-wins':\n conflict.resolvedAs = 'vault';\n conflict.resolvedAt = new Date();\n return true;\n\n case 'memory-wins':\n conflict.resolvedAs = 'memory';\n conflict.resolvedAt = new Date();\n return true;\n\n case 'newest-wins':\n if (conflict.vaultVersion.modifiedAt > conflict.memoryVersion.modifiedAt) {\n conflict.resolvedAs = 'vault';\n } else {\n conflict.resolvedAs = 'memory';\n }\n conflict.resolvedAt = new Date();\n return true;\n\n case 'merge':\n // Merge strategy would require content comparison\n // For now, fall back to newest-wins\n if (conflict.vaultVersion.modifiedAt > conflict.memoryVersion.modifiedAt) {\n conflict.resolvedAs = 'vault';\n } else {\n conflict.resolvedAs = 'memory';\n }\n conflict.resolvedAt = new Date();\n return true;\n\n case 'manual':\n // Don't auto-resolve, add to conflicts list\n this.conflicts.push(conflict);\n return false;\n\n default:\n return false;\n }\n }\n\n private countPendingVaultChanges(): number {\n const cachedHashes = new Map<string, string>();\n for (const [id, node] of this.memoryCache) {\n cachedHashes.set(id, node.contentHash);\n }\n\n let pending = 0;\n const nodes = this.db?.getAllNodes() ?? [];\n\n for (const node of nodes) {\n const cachedHash = cachedHashes.get(node.id);\n const currentHash = this.computeContentHash(node.content);\n\n if (!cachedHash || cachedHash !== currentHash) {\n pending++;\n }\n }\n\n return pending;\n }\n\n private countPendingMemoryChanges(): number {\n // In a real implementation, this would check memory for changes\n // that haven't been synced to vault\n return 0;\n }\n\n private createBatches<T>(items: T[], batchSize: number): T[][] {\n const batches: T[][] = [];\n for (let i = 0; i < items.length; i += batchSize) {\n batches.push(items.slice(i, i + batchSize));\n }\n return batches;\n }\n\n private async loadMemoryCache(): Promise<void> {\n logger.debug('Loading memory cache from MCP');\n\n // Try to load the node index from MCP\n const nodeIndex = await this.mcpClient.getNodeIndex();\n\n if (!nodeIndex || nodeIndex.length === 0) {\n logger.debug('No existing memory cache found in MCP');\n return;\n }\n\n // Load each node from MCP into the local cache\n for (const indexEntry of nodeIndex) {\n const nodeEntry = await this.mcpClient.getNode(indexEntry.id);\n if (nodeEntry) {\n this.memoryCache.set(indexEntry.id, nodeEntry as MemoryNode);\n }\n }\n\n logger.debug('Loaded memory cache from MCP', {\n count: this.memoryCache.size,\n });\n }\n\n private async saveMemoryCache(): Promise<void> {\n // Persist cache to disk for recovery\n await this.shadowCache.save();\n logger.debug('Memory cache saved');\n }\n}\n\n/**\n * Create a vault memory sync instance\n */\nexport function createVaultMemorySync(options: VaultSyncOptions): VaultMemorySync {\n return new VaultMemorySync(options);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,118 @@
1
+ var TOKEN_TYPES = Object.freeze({
2
+ Text: "Text",
3
+ // The text between Jinja statements or expressions
4
+ NumericLiteral: "NumericLiteral",
5
+ // e.g., 123
6
+ BooleanLiteral: "BooleanLiteral",
7
+ // true or false
8
+ StringLiteral: "StringLiteral",
9
+ // 'string'
10
+ Identifier: "Identifier",
11
+ // Variables, functions, etc.
12
+ Equals: "Equals",
13
+ // =
14
+ OpenParen: "OpenParen",
15
+ // (
16
+ CloseParen: "CloseParen",
17
+ // )
18
+ OpenStatement: "OpenStatement",
19
+ // {%
20
+ CloseStatement: "CloseStatement",
21
+ // %}
22
+ OpenExpression: "OpenExpression",
23
+ // {{
24
+ CloseExpression: "CloseExpression",
25
+ // }}
26
+ OpenSquareBracket: "OpenSquareBracket",
27
+ // [
28
+ CloseSquareBracket: "CloseSquareBracket",
29
+ // ]
30
+ OpenCurlyBracket: "OpenCurlyBracket",
31
+ // {
32
+ CloseCurlyBracket: "CloseCurlyBracket",
33
+ // }
34
+ Comma: "Comma",
35
+ // ,
36
+ Dot: "Dot",
37
+ // .
38
+ Colon: "Colon",
39
+ // :
40
+ Pipe: "Pipe",
41
+ // |
42
+ CallOperator: "CallOperator",
43
+ // ()
44
+ AdditiveBinaryOperator: "AdditiveBinaryOperator",
45
+ // + -
46
+ MultiplicativeBinaryOperator: "MultiplicativeBinaryOperator",
47
+ // * / %
48
+ ComparisonBinaryOperator: "ComparisonBinaryOperator",
49
+ // < > <= >= == !=
50
+ UnaryOperator: "UnaryOperator",
51
+ // ! - +
52
+ // Keywords
53
+ Set: "Set",
54
+ If: "If",
55
+ For: "For",
56
+ In: "In",
57
+ Is: "Is",
58
+ NotIn: "NotIn",
59
+ Else: "Else",
60
+ EndIf: "EndIf",
61
+ ElseIf: "ElseIf",
62
+ EndFor: "EndFor",
63
+ And: "And",
64
+ Or: "Or",
65
+ Not: "UnaryOperator"
66
+ });
67
+ Object.freeze({
68
+ set: TOKEN_TYPES.Set,
69
+ for: TOKEN_TYPES.For,
70
+ in: TOKEN_TYPES.In,
71
+ is: TOKEN_TYPES.Is,
72
+ if: TOKEN_TYPES.If,
73
+ else: TOKEN_TYPES.Else,
74
+ endif: TOKEN_TYPES.EndIf,
75
+ elif: TOKEN_TYPES.ElseIf,
76
+ endfor: TOKEN_TYPES.EndFor,
77
+ and: TOKEN_TYPES.And,
78
+ or: TOKEN_TYPES.Or,
79
+ not: TOKEN_TYPES.Not,
80
+ "not in": TOKEN_TYPES.NotIn,
81
+ // Literals
82
+ true: TOKEN_TYPES.BooleanLiteral,
83
+ false: TOKEN_TYPES.BooleanLiteral
84
+ });
85
+ [
86
+ // Control sequences
87
+ ["{%", TOKEN_TYPES.OpenStatement],
88
+ ["%}", TOKEN_TYPES.CloseStatement],
89
+ ["{{", TOKEN_TYPES.OpenExpression],
90
+ ["}}", TOKEN_TYPES.CloseExpression],
91
+ // Single character tokens
92
+ ["(", TOKEN_TYPES.OpenParen],
93
+ [")", TOKEN_TYPES.CloseParen],
94
+ ["{", TOKEN_TYPES.OpenCurlyBracket],
95
+ ["}", TOKEN_TYPES.CloseCurlyBracket],
96
+ ["[", TOKEN_TYPES.OpenSquareBracket],
97
+ ["]", TOKEN_TYPES.CloseSquareBracket],
98
+ [",", TOKEN_TYPES.Comma],
99
+ [".", TOKEN_TYPES.Dot],
100
+ [":", TOKEN_TYPES.Colon],
101
+ ["|", TOKEN_TYPES.Pipe],
102
+ // Comparison operators
103
+ ["<=", TOKEN_TYPES.ComparisonBinaryOperator],
104
+ [">=", TOKEN_TYPES.ComparisonBinaryOperator],
105
+ ["==", TOKEN_TYPES.ComparisonBinaryOperator],
106
+ ["!=", TOKEN_TYPES.ComparisonBinaryOperator],
107
+ ["<", TOKEN_TYPES.ComparisonBinaryOperator],
108
+ [">", TOKEN_TYPES.ComparisonBinaryOperator],
109
+ // Arithmetic operators
110
+ ["+", TOKEN_TYPES.AdditiveBinaryOperator],
111
+ ["-", TOKEN_TYPES.AdditiveBinaryOperator],
112
+ ["*", TOKEN_TYPES.MultiplicativeBinaryOperator],
113
+ ["/", TOKEN_TYPES.MultiplicativeBinaryOperator],
114
+ ["%", TOKEN_TYPES.MultiplicativeBinaryOperator],
115
+ // Assignment operator
116
+ ["=", TOKEN_TYPES.Equals]
117
+ ];
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../../node_modules/@huggingface/jinja/dist/index.js"],"sourcesContent":["// src/lexer.ts\nvar TOKEN_TYPES = Object.freeze({\n Text: \"Text\",\n // The text between Jinja statements or expressions\n NumericLiteral: \"NumericLiteral\",\n // e.g., 123\n BooleanLiteral: \"BooleanLiteral\",\n // true or false\n StringLiteral: \"StringLiteral\",\n // 'string'\n Identifier: \"Identifier\",\n // Variables, functions, etc.\n Equals: \"Equals\",\n // =\n OpenParen: \"OpenParen\",\n // (\n CloseParen: \"CloseParen\",\n // )\n OpenStatement: \"OpenStatement\",\n // {%\n CloseStatement: \"CloseStatement\",\n // %}\n OpenExpression: \"OpenExpression\",\n // {{\n CloseExpression: \"CloseExpression\",\n // }}\n OpenSquareBracket: \"OpenSquareBracket\",\n // [\n CloseSquareBracket: \"CloseSquareBracket\",\n // ]\n OpenCurlyBracket: \"OpenCurlyBracket\",\n // {\n CloseCurlyBracket: \"CloseCurlyBracket\",\n // }\n Comma: \"Comma\",\n // ,\n Dot: \"Dot\",\n // .\n Colon: \"Colon\",\n // :\n Pipe: \"Pipe\",\n // |\n CallOperator: \"CallOperator\",\n // ()\n AdditiveBinaryOperator: \"AdditiveBinaryOperator\",\n // + -\n MultiplicativeBinaryOperator: \"MultiplicativeBinaryOperator\",\n // * / %\n ComparisonBinaryOperator: \"ComparisonBinaryOperator\",\n // < > <= >= == !=\n UnaryOperator: \"UnaryOperator\",\n // ! - +\n // Keywords\n Set: \"Set\",\n If: \"If\",\n For: \"For\",\n In: \"In\",\n Is: \"Is\",\n NotIn: \"NotIn\",\n Else: \"Else\",\n EndIf: \"EndIf\",\n ElseIf: \"ElseIf\",\n EndFor: \"EndFor\",\n And: \"And\",\n Or: \"Or\",\n Not: \"UnaryOperator\"\n});\nvar KEYWORDS = Object.freeze({\n set: TOKEN_TYPES.Set,\n for: TOKEN_TYPES.For,\n in: TOKEN_TYPES.In,\n is: TOKEN_TYPES.Is,\n if: TOKEN_TYPES.If,\n else: TOKEN_TYPES.Else,\n endif: TOKEN_TYPES.EndIf,\n elif: TOKEN_TYPES.ElseIf,\n endfor: TOKEN_TYPES.EndFor,\n and: TOKEN_TYPES.And,\n or: TOKEN_TYPES.Or,\n not: TOKEN_TYPES.Not,\n \"not in\": TOKEN_TYPES.NotIn,\n // Literals\n true: TOKEN_TYPES.BooleanLiteral,\n false: TOKEN_TYPES.BooleanLiteral\n});\nvar Token = class {\n /**\n * Constructs a new Token.\n * @param {string} value The raw value as seen inside the source code.\n * @param {TokenType} type The type of token.\n */\n constructor(value, type) {\n this.value = value;\n this.type = type;\n }\n};\nfunction isWord(char) {\n return /\\w/.test(char);\n}\nfunction isInteger(char) {\n return /[0-9]/.test(char);\n}\nvar ORDERED_MAPPING_TABLE = [\n // Control sequences\n [\"{%\", TOKEN_TYPES.OpenStatement],\n [\"%}\", TOKEN_TYPES.CloseStatement],\n [\"{{\", TOKEN_TYPES.OpenExpression],\n [\"}}\", TOKEN_TYPES.CloseExpression],\n // Single character tokens\n [\"(\", TOKEN_TYPES.OpenParen],\n [\")\", TOKEN_TYPES.CloseParen],\n [\"{\", TOKEN_TYPES.OpenCurlyBracket],\n [\"}\", TOKEN_TYPES.CloseCurlyBracket],\n [\"[\", TOKEN_TYPES.OpenSquareBracket],\n [\"]\", TOKEN_TYPES.CloseSquareBracket],\n [\",\", TOKEN_TYPES.Comma],\n [\".\", TOKEN_TYPES.Dot],\n [\":\", TOKEN_TYPES.Colon],\n [\"|\", TOKEN_TYPES.Pipe],\n // Comparison operators\n [\"<=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\">=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"==\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"!=\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\"<\", TOKEN_TYPES.ComparisonBinaryOperator],\n [\">\", TOKEN_TYPES.ComparisonBinaryOperator],\n // Arithmetic operators\n [\"+\", TOKEN_TYPES.AdditiveBinaryOperator],\n [\"-\", TOKEN_TYPES.AdditiveBinaryOperator],\n [\"*\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n [\"/\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n [\"%\", TOKEN_TYPES.MultiplicativeBinaryOperator],\n // Assignment operator\n [\"=\", TOKEN_TYPES.Equals]\n];\nvar ESCAPE_CHARACTERS = /* @__PURE__ */ new Map([\n [\"n\", \"\\n\"],\n // New line\n [\"t\", \"\t\"],\n // Horizontal tab\n [\"r\", \"\\r\"],\n // Carriage return\n [\"b\", \"\\b\"],\n // Backspace\n [\"f\", \"\\f\"],\n // Form feed\n [\"v\", \"\\v\"],\n // Vertical tab\n [\"'\", \"'\"],\n // Single quote\n ['\"', '\"'],\n // Double quote\n [\"\\\\\", \"\\\\\"]\n // Backslash\n]);\nfunction preprocess(template, options = {}) {\n if (template.endsWith(\"\\n\")) {\n template = template.slice(0, -1);\n }\n template = template.replace(/{#.*?#}/gs, \"{##}\");\n if (options.lstrip_blocks) {\n template = template.replace(/^[ \\t]*({[#%])/gm, \"$1\");\n }\n if (options.trim_blocks) {\n template = template.replace(/([#%]})\\n/g, \"$1\");\n }\n return template.replace(/{##}/g, \"\").replace(/-%}\\s*/g, \"%}\").replace(/\\s*{%-/g, \"{%\").replace(/-}}\\s*/g, \"}}\").replace(/\\s*{{-/g, \"{{\");\n}\nfunction tokenize(source, options = {}) {\n const tokens = [];\n const src = preprocess(source, options);\n let cursorPosition = 0;\n const consumeWhile = (predicate) => {\n let str = \"\";\n while (predicate(src[cursorPosition])) {\n if (src[cursorPosition] === \"\\\\\") {\n ++cursorPosition;\n if (cursorPosition >= src.length)\n throw new SyntaxError(\"Unexpected end of input\");\n const escaped = src[cursorPosition++];\n const unescaped = ESCAPE_CHARACTERS.get(escaped);\n if (unescaped === void 0) {\n throw new SyntaxError(`Unexpected escaped character: ${escaped}`);\n }\n str += unescaped;\n continue;\n }\n str += src[cursorPosition++];\n if (cursorPosition >= src.length)\n throw new SyntaxError(\"Unexpected end of input\");\n }\n return str;\n };\n main:\n while (cursorPosition < src.length) {\n const lastTokenType = tokens.at(-1)?.type;\n if (lastTokenType === void 0 || lastTokenType === TOKEN_TYPES.CloseStatement || lastTokenType === TOKEN_TYPES.CloseExpression) {\n let text = \"\";\n while (cursorPosition < src.length && // Keep going until we hit the next Jinja statement or expression\n !(src[cursorPosition] === \"{\" && (src[cursorPosition + 1] === \"%\" || src[cursorPosition + 1] === \"{\"))) {\n text += src[cursorPosition++];\n }\n if (text.length > 0) {\n tokens.push(new Token(text, TOKEN_TYPES.Text));\n continue;\n }\n }\n consumeWhile((char2) => /\\s/.test(char2));\n const char = src[cursorPosition];\n if (char === \"-\" || char === \"+\") {\n const lastTokenType2 = tokens.at(-1)?.type;\n if (lastTokenType2 === TOKEN_TYPES.Text || lastTokenType2 === void 0) {\n throw new SyntaxError(`Unexpected character: ${char}`);\n }\n switch (lastTokenType2) {\n case TOKEN_TYPES.Identifier:\n case TOKEN_TYPES.NumericLiteral:\n case TOKEN_TYPES.BooleanLiteral:\n case TOKEN_TYPES.StringLiteral:\n case TOKEN_TYPES.CloseParen:\n case TOKEN_TYPES.CloseSquareBracket:\n break;\n default: {\n ++cursorPosition;\n const num = consumeWhile(isInteger);\n tokens.push(\n new Token(`${char}${num}`, num.length > 0 ? TOKEN_TYPES.NumericLiteral : TOKEN_TYPES.UnaryOperator)\n );\n continue;\n }\n }\n }\n for (const [char2, token] of ORDERED_MAPPING_TABLE) {\n const slice2 = src.slice(cursorPosition, cursorPosition + char2.length);\n if (slice2 === char2) {\n tokens.push(new Token(char2, token));\n cursorPosition += char2.length;\n continue main;\n }\n }\n if (char === \"'\" || char === '\"') {\n ++cursorPosition;\n const str = consumeWhile((c) => c !== char);\n tokens.push(new Token(str, TOKEN_TYPES.StringLiteral));\n ++cursorPosition;\n continue;\n }\n if (isInteger(char)) {\n const num = consumeWhile(isInteger);\n tokens.push(new Token(num, TOKEN_TYPES.NumericLiteral));\n continue;\n }\n if (isWord(char)) {\n const word = consumeWhile(isWord);\n const type = Object.hasOwn(KEYWORDS, word) ? KEYWORDS[word] : TOKEN_TYPES.Identifier;\n if (type === TOKEN_TYPES.In && tokens.at(-1)?.type === TOKEN_TYPES.Not) {\n tokens.pop();\n tokens.push(new Token(\"not in\", TOKEN_TYPES.NotIn));\n } else {\n tokens.push(new Token(word, type));\n }\n continue;\n }\n throw new SyntaxError(`Unexpected character: ${char}`);\n }\n return tokens;\n}\n\n// src/ast.ts\nvar Statement = class {\n type = \"Statement\";\n};\nvar Program = class extends Statement {\n constructor(body) {\n super();\n this.body = body;\n }\n type = \"Program\";\n};\nvar If = class extends Statement {\n constructor(test, body, alternate) {\n super();\n this.test = test;\n this.body = body;\n this.alternate = alternate;\n }\n type = \"If\";\n};\nvar For = class extends Statement {\n constructor(loopvar, iterable, body) {\n super();\n this.loopvar = loopvar;\n this.iterable = iterable;\n this.body = body;\n }\n type = \"For\";\n};\nvar SetStatement = class extends Statement {\n constructor(assignee, value) {\n super();\n this.assignee = assignee;\n this.value = value;\n }\n type = \"Set\";\n};\nvar Expression = class extends Statement {\n type = \"Expression\";\n};\nvar MemberExpression = class extends Expression {\n constructor(object, property, computed) {\n super();\n this.object = object;\n this.property = property;\n this.computed = computed;\n }\n type = \"MemberExpression\";\n};\nvar CallExpression = class extends Expression {\n constructor(callee, args) {\n super();\n this.callee = callee;\n this.args = args;\n }\n type = \"CallExpression\";\n};\nvar Identifier = class extends Expression {\n /**\n * @param {string} value The name of the identifier\n */\n constructor(value) {\n super();\n this.value = value;\n }\n type = \"Identifier\";\n};\nvar Literal = class extends Expression {\n constructor(value) {\n super();\n this.value = value;\n }\n type = \"Literal\";\n};\nvar NumericLiteral = class extends Literal {\n type = \"NumericLiteral\";\n};\nvar StringLiteral = class extends Literal {\n type = \"StringLiteral\";\n};\nvar BooleanLiteral = class extends Literal {\n type = \"BooleanLiteral\";\n};\nvar ArrayLiteral = class extends Literal {\n type = \"ArrayLiteral\";\n};\nvar TupleLiteral = class extends Literal {\n type = \"TupleLiteral\";\n};\nvar ObjectLiteral = class extends Literal {\n type = \"ObjectLiteral\";\n};\nvar BinaryExpression = class extends Expression {\n constructor(operator, left, right) {\n super();\n this.operator = operator;\n this.left = left;\n this.right = right;\n }\n type = \"BinaryExpression\";\n};\nvar FilterExpression = class extends Expression {\n constructor(operand, filter) {\n super();\n this.operand = operand;\n this.filter = filter;\n }\n type = \"FilterExpression\";\n};\nvar TestExpression = class extends Expression {\n constructor(operand, negate, test) {\n super();\n this.operand = operand;\n this.negate = negate;\n this.test = test;\n }\n type = \"TestExpression\";\n};\nvar UnaryExpression = class extends Expression {\n constructor(operator, argument) {\n super();\n this.operator = operator;\n this.argument = argument;\n }\n type = \"UnaryExpression\";\n};\nvar SliceExpression = class extends Expression {\n constructor(start = void 0, stop = void 0, step = void 0) {\n super();\n this.start = start;\n this.stop = stop;\n this.step = step;\n }\n type = \"SliceExpression\";\n};\nvar KeywordArgumentExpression = class extends Expression {\n constructor(key, value) {\n super();\n this.key = key;\n this.value = value;\n }\n type = \"KeywordArgumentExpression\";\n};\n\n// src/parser.ts\nfunction parse(tokens) {\n const program = new Program([]);\n let current = 0;\n function expect(type, error) {\n const prev = tokens[current++];\n if (!prev || prev.type !== type) {\n throw new Error(`Parser Error: ${error}. ${prev.type} !== ${type}.`);\n }\n return prev;\n }\n function parseAny() {\n switch (tokens[current].type) {\n case TOKEN_TYPES.Text:\n return parseText();\n case TOKEN_TYPES.OpenStatement:\n return parseJinjaStatement();\n case TOKEN_TYPES.OpenExpression:\n return parseJinjaExpression();\n default:\n throw new SyntaxError(`Unexpected token type: ${tokens[current].type}`);\n }\n }\n function not(...types) {\n return current + types.length <= tokens.length && types.some((type, i) => type !== tokens[current + i].type);\n }\n function is(...types) {\n return current + types.length <= tokens.length && types.every((type, i) => type === tokens[current + i].type);\n }\n function parseText() {\n return new StringLiteral(expect(TOKEN_TYPES.Text, \"Expected text token\").value);\n }\n function parseJinjaStatement() {\n expect(TOKEN_TYPES.OpenStatement, \"Expected opening statement token\");\n let result;\n switch (tokens[current].type) {\n case TOKEN_TYPES.Set:\n ++current;\n result = parseSetStatement();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n break;\n case TOKEN_TYPES.If:\n ++current;\n result = parseIfStatement();\n expect(TOKEN_TYPES.OpenStatement, \"Expected {% token\");\n expect(TOKEN_TYPES.EndIf, \"Expected endif token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected %} token\");\n break;\n case TOKEN_TYPES.For:\n ++current;\n result = parseForStatement();\n expect(TOKEN_TYPES.OpenStatement, \"Expected {% token\");\n expect(TOKEN_TYPES.EndFor, \"Expected endfor token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected %} token\");\n break;\n default:\n throw new SyntaxError(`Unknown statement type: ${tokens[current].type}`);\n }\n return result;\n }\n function parseJinjaExpression() {\n expect(TOKEN_TYPES.OpenExpression, \"Expected opening expression token\");\n const result = parseExpression();\n expect(TOKEN_TYPES.CloseExpression, \"Expected closing expression token\");\n return result;\n }\n function parseSetStatement() {\n const left = parseExpression();\n if (is(TOKEN_TYPES.Equals)) {\n ++current;\n const value = parseSetStatement();\n return new SetStatement(left, value);\n }\n return left;\n }\n function parseIfStatement() {\n const test = parseExpression();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n const body = [];\n const alternate = [];\n while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && (tokens[current + 1]?.type === TOKEN_TYPES.ElseIf || tokens[current + 1]?.type === TOKEN_TYPES.Else || tokens[current + 1]?.type === TOKEN_TYPES.EndIf))) {\n body.push(parseAny());\n }\n if (tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type !== TOKEN_TYPES.EndIf) {\n ++current;\n if (is(TOKEN_TYPES.ElseIf)) {\n expect(TOKEN_TYPES.ElseIf, \"Expected elseif token\");\n alternate.push(parseIfStatement());\n } else {\n expect(TOKEN_TYPES.Else, \"Expected else token\");\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n while (!(tokens[current]?.type === TOKEN_TYPES.OpenStatement && tokens[current + 1]?.type === TOKEN_TYPES.EndIf)) {\n alternate.push(parseAny());\n }\n }\n }\n return new If(test, body, alternate);\n }\n function parseExpressionSequence(primary = false) {\n const fn = primary ? parsePrimaryExpression : parseExpression;\n const expressions = [fn()];\n const isTuple = is(TOKEN_TYPES.Comma);\n while (isTuple) {\n ++current;\n expressions.push(fn());\n if (!is(TOKEN_TYPES.Comma)) {\n break;\n }\n }\n return isTuple ? new TupleLiteral(expressions) : expressions[0];\n }\n function parseForStatement() {\n const loopVariable = parseExpressionSequence(true);\n if (!(loopVariable instanceof Identifier || loopVariable instanceof TupleLiteral)) {\n throw new SyntaxError(`Expected identifier/tuple for the loop variable, got ${loopVariable.type} instead`);\n }\n expect(TOKEN_TYPES.In, \"Expected `in` keyword following loop variable\");\n const iterable = parseExpression();\n expect(TOKEN_TYPES.CloseStatement, \"Expected closing statement token\");\n const body = [];\n while (not(TOKEN_TYPES.OpenStatement, TOKEN_TYPES.EndFor)) {\n body.push(parseAny());\n }\n return new For(loopVariable, iterable, body);\n }\n function parseExpression() {\n return parseTernaryExpression();\n }\n function parseTernaryExpression() {\n const a = parseLogicalOrExpression();\n if (is(TOKEN_TYPES.If)) {\n ++current;\n const predicate = parseLogicalOrExpression();\n expect(TOKEN_TYPES.Else, \"Expected else token\");\n const b = parseLogicalOrExpression();\n return new If(predicate, [a], [b]);\n }\n return a;\n }\n function parseLogicalOrExpression() {\n let left = parseLogicalAndExpression();\n while (is(TOKEN_TYPES.Or)) {\n const operator = tokens[current];\n ++current;\n const right = parseLogicalAndExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseLogicalAndExpression() {\n let left = parseLogicalNegationExpression();\n while (is(TOKEN_TYPES.And)) {\n const operator = tokens[current];\n ++current;\n const right = parseLogicalNegationExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseLogicalNegationExpression() {\n let right;\n while (is(TOKEN_TYPES.Not)) {\n const operator = tokens[current];\n ++current;\n const arg = parseLogicalNegationExpression();\n right = new UnaryExpression(operator, arg);\n }\n return right ?? parseComparisonExpression();\n }\n function parseComparisonExpression() {\n let left = parseAdditiveExpression();\n while (is(TOKEN_TYPES.ComparisonBinaryOperator) || is(TOKEN_TYPES.In) || is(TOKEN_TYPES.NotIn)) {\n const operator = tokens[current];\n ++current;\n const right = parseAdditiveExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseAdditiveExpression() {\n let left = parseMultiplicativeExpression();\n while (is(TOKEN_TYPES.AdditiveBinaryOperator)) {\n const operator = tokens[current];\n ++current;\n const right = parseMultiplicativeExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseCallMemberExpression() {\n const member = parseMemberExpression();\n if (is(TOKEN_TYPES.OpenParen)) {\n return parseCallExpression(member);\n }\n return member;\n }\n function parseCallExpression(callee) {\n let callExpression = new CallExpression(callee, parseArgs());\n if (is(TOKEN_TYPES.OpenParen)) {\n callExpression = parseCallExpression(callExpression);\n }\n return callExpression;\n }\n function parseArgs() {\n expect(TOKEN_TYPES.OpenParen, \"Expected opening parenthesis for arguments list\");\n const args = parseArgumentsList();\n expect(TOKEN_TYPES.CloseParen, \"Expected closing parenthesis for arguments list\");\n return args;\n }\n function parseArgumentsList() {\n const args = [];\n while (!is(TOKEN_TYPES.CloseParen)) {\n let argument = parseExpression();\n if (is(TOKEN_TYPES.Equals)) {\n ++current;\n if (!(argument instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for keyword argument`);\n }\n const value = parseExpression();\n argument = new KeywordArgumentExpression(argument, value);\n }\n args.push(argument);\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n return args;\n }\n function parseMemberExpressionArgumentsList() {\n const slices = [];\n let isSlice = false;\n while (!is(TOKEN_TYPES.CloseSquareBracket)) {\n if (is(TOKEN_TYPES.Colon)) {\n slices.push(void 0);\n ++current;\n isSlice = true;\n } else {\n slices.push(parseExpression());\n if (is(TOKEN_TYPES.Colon)) {\n ++current;\n isSlice = true;\n }\n }\n }\n if (slices.length === 0) {\n throw new SyntaxError(`Expected at least one argument for member/slice expression`);\n }\n if (isSlice) {\n if (slices.length > 3) {\n throw new SyntaxError(`Expected 0-3 arguments for slice expression`);\n }\n return new SliceExpression(...slices);\n }\n return slices[0];\n }\n function parseMemberExpression() {\n let object = parsePrimaryExpression();\n while (is(TOKEN_TYPES.Dot) || is(TOKEN_TYPES.OpenSquareBracket)) {\n const operator = tokens[current];\n ++current;\n let property;\n const computed = operator.type !== TOKEN_TYPES.Dot;\n if (computed) {\n property = parseMemberExpressionArgumentsList();\n expect(TOKEN_TYPES.CloseSquareBracket, \"Expected closing square bracket\");\n } else {\n property = parsePrimaryExpression();\n if (property.type !== \"Identifier\") {\n throw new SyntaxError(`Expected identifier following dot operator`);\n }\n }\n object = new MemberExpression(object, property, computed);\n }\n return object;\n }\n function parseMultiplicativeExpression() {\n let left = parseTestExpression();\n while (is(TOKEN_TYPES.MultiplicativeBinaryOperator)) {\n const operator = tokens[current];\n ++current;\n const right = parseTestExpression();\n left = new BinaryExpression(operator, left, right);\n }\n return left;\n }\n function parseTestExpression() {\n let operand = parseFilterExpression();\n while (is(TOKEN_TYPES.Is)) {\n ++current;\n const negate = is(TOKEN_TYPES.Not);\n if (negate) {\n ++current;\n }\n let filter = parsePrimaryExpression();\n if (filter instanceof BooleanLiteral) {\n filter = new Identifier(filter.value.toString());\n }\n if (!(filter instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for the test`);\n }\n operand = new TestExpression(operand, negate, filter);\n }\n return operand;\n }\n function parseFilterExpression() {\n let operand = parseCallMemberExpression();\n while (is(TOKEN_TYPES.Pipe)) {\n ++current;\n let filter = parsePrimaryExpression();\n if (!(filter instanceof Identifier)) {\n throw new SyntaxError(`Expected identifier for the filter`);\n }\n if (is(TOKEN_TYPES.OpenParen)) {\n filter = parseCallExpression(filter);\n }\n operand = new FilterExpression(operand, filter);\n }\n return operand;\n }\n function parsePrimaryExpression() {\n const token = tokens[current];\n switch (token.type) {\n case TOKEN_TYPES.NumericLiteral:\n ++current;\n return new NumericLiteral(Number(token.value));\n case TOKEN_TYPES.StringLiteral:\n ++current;\n return new StringLiteral(token.value);\n case TOKEN_TYPES.BooleanLiteral:\n ++current;\n return new BooleanLiteral(token.value === \"true\");\n case TOKEN_TYPES.Identifier:\n ++current;\n return new Identifier(token.value);\n case TOKEN_TYPES.OpenParen: {\n ++current;\n const expression = parseExpressionSequence();\n if (tokens[current].type !== TOKEN_TYPES.CloseParen) {\n throw new SyntaxError(`Expected closing parenthesis, got ${tokens[current].type} instead`);\n }\n ++current;\n return expression;\n }\n case TOKEN_TYPES.OpenSquareBracket: {\n ++current;\n const values = [];\n while (!is(TOKEN_TYPES.CloseSquareBracket)) {\n values.push(parseExpression());\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n ++current;\n return new ArrayLiteral(values);\n }\n case TOKEN_TYPES.OpenCurlyBracket: {\n ++current;\n const values = /* @__PURE__ */ new Map();\n while (!is(TOKEN_TYPES.CloseCurlyBracket)) {\n const key = parseExpression();\n expect(TOKEN_TYPES.Colon, \"Expected colon between key and value in object literal\");\n const value = parseExpression();\n values.set(key, value);\n if (is(TOKEN_TYPES.Comma)) {\n ++current;\n }\n }\n ++current;\n return new ObjectLiteral(values);\n }\n default:\n throw new SyntaxError(`Unexpected token: ${token.type}`);\n }\n }\n while (current < tokens.length) {\n program.body.push(parseAny());\n }\n return program;\n}\n\n// src/utils.ts\nfunction range(start, stop, step = 1) {\n if (stop === void 0) {\n stop = start;\n start = 0;\n }\n const result = [];\n for (let i = start; i < stop; i += step) {\n result.push(i);\n }\n return result;\n}\nfunction slice(array, start, stop, step = 1) {\n const direction = Math.sign(step);\n if (direction >= 0) {\n start = (start ??= 0) < 0 ? Math.max(array.length + start, 0) : Math.min(start, array.length);\n stop = (stop ??= array.length) < 0 ? Math.max(array.length + stop, 0) : Math.min(stop, array.length);\n } else {\n start = (start ??= array.length - 1) < 0 ? Math.max(array.length + start, -1) : Math.min(start, array.length - 1);\n stop = (stop ??= -1) < -1 ? Math.max(array.length + stop, -1) : Math.min(stop, array.length - 1);\n }\n const result = [];\n for (let i = start; direction * i < direction * stop; i += step) {\n result.push(array[i]);\n }\n return result;\n}\nfunction titleCase(value) {\n return value.replace(/\\b\\w/g, (c) => c.toUpperCase());\n}\n\n// src/runtime.ts\nvar RuntimeValue = class {\n type = \"RuntimeValue\";\n value;\n /**\n * A collection of built-in functions for this type.\n */\n builtins = /* @__PURE__ */ new Map();\n /**\n * Creates a new RuntimeValue.\n */\n constructor(value = void 0) {\n this.value = value;\n }\n /**\n * Determines truthiness or falsiness of the runtime value.\n * This function should be overridden by subclasses if it has custom truthiness criteria.\n * @returns {BooleanValue} BooleanValue(true) if the value is truthy, BooleanValue(false) otherwise.\n */\n __bool__() {\n return new BooleanValue(!!this.value);\n }\n};\nvar NumericValue = class extends RuntimeValue {\n type = \"NumericValue\";\n};\nvar StringValue = class extends RuntimeValue {\n type = \"StringValue\";\n builtins = /* @__PURE__ */ new Map([\n [\n \"upper\",\n new FunctionValue(() => {\n return new StringValue(this.value.toUpperCase());\n })\n ],\n [\n \"lower\",\n new FunctionValue(() => {\n return new StringValue(this.value.toLowerCase());\n })\n ],\n [\n \"strip\",\n new FunctionValue(() => {\n return new StringValue(this.value.trim());\n })\n ],\n [\n \"title\",\n new FunctionValue(() => {\n return new StringValue(titleCase(this.value));\n })\n ],\n [\"length\", new NumericValue(this.value.length)]\n ]);\n};\nvar BooleanValue = class extends RuntimeValue {\n type = \"BooleanValue\";\n};\nvar ObjectValue = class extends RuntimeValue {\n type = \"ObjectValue\";\n /**\n * NOTE: necessary to override since all JavaScript arrays are considered truthy,\n * while only non-empty Python arrays are consider truthy.\n *\n * e.g.,\n * - JavaScript: {} && 5 -> 5\n * - Python: {} and 5 -> {}\n */\n __bool__() {\n return new BooleanValue(this.value.size > 0);\n }\n builtins = /* @__PURE__ */ new Map([\n [\n \"get\",\n new FunctionValue(([key, defaultValue]) => {\n if (!(key instanceof StringValue)) {\n throw new Error(`Object key must be a string: got ${key.type}`);\n }\n return this.value.get(key.value) ?? defaultValue ?? new NullValue();\n })\n ],\n [\n \"items\",\n new FunctionValue(() => {\n return new ArrayValue(\n Array.from(this.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))\n );\n })\n ]\n ]);\n};\nvar ArrayValue = class extends RuntimeValue {\n type = \"ArrayValue\";\n builtins = /* @__PURE__ */ new Map([[\"length\", new NumericValue(this.value.length)]]);\n /**\n * NOTE: necessary to override since all JavaScript arrays are considered truthy,\n * while only non-empty Python arrays are consider truthy.\n *\n * e.g.,\n * - JavaScript: [] && 5 -> 5\n * - Python: [] and 5 -> []\n */\n __bool__() {\n return new BooleanValue(this.value.length > 0);\n }\n};\nvar TupleValue = class extends ArrayValue {\n type = \"TupleValue\";\n};\nvar FunctionValue = class extends RuntimeValue {\n type = \"FunctionValue\";\n};\nvar NullValue = class extends RuntimeValue {\n type = \"NullValue\";\n};\nvar UndefinedValue = class extends RuntimeValue {\n type = \"UndefinedValue\";\n};\nvar Environment = class {\n constructor(parent) {\n this.parent = parent;\n }\n /**\n * The variables declared in this environment.\n */\n variables = /* @__PURE__ */ new Map([\n [\n \"namespace\",\n new FunctionValue((args) => {\n if (args.length === 0) {\n return new ObjectValue(/* @__PURE__ */ new Map());\n }\n if (args.length !== 1 || !(args[0] instanceof ObjectValue)) {\n throw new Error(\"`namespace` expects either zero arguments or a single object argument\");\n }\n return args[0];\n })\n ]\n ]);\n /**\n * The tests available in this environment.\n */\n tests = /* @__PURE__ */ new Map([\n [\"boolean\", (operand) => operand.type === \"BooleanValue\"],\n [\"callable\", (operand) => operand instanceof FunctionValue],\n [\n \"odd\",\n (operand) => {\n if (operand.type !== \"NumericValue\") {\n throw new Error(`Cannot apply test \"odd\" to type: ${operand.type}`);\n }\n return operand.value % 2 !== 0;\n }\n ],\n [\n \"even\",\n (operand) => {\n if (operand.type !== \"NumericValue\") {\n throw new Error(`Cannot apply test \"even\" to type: ${operand.type}`);\n }\n return operand.value % 2 === 0;\n }\n ],\n [\"false\", (operand) => operand.type === \"BooleanValue\" && !operand.value],\n [\"true\", (operand) => operand.type === \"BooleanValue\" && operand.value],\n [\"number\", (operand) => operand.type === \"NumericValue\"],\n [\"integer\", (operand) => operand.type === \"NumericValue\" && Number.isInteger(operand.value)],\n [\"iterable\", (operand) => operand instanceof ArrayValue || operand instanceof StringValue],\n [\n \"lower\",\n (operand) => {\n const str = operand.value;\n return operand.type === \"StringValue\" && str === str.toLowerCase();\n }\n ],\n [\n \"upper\",\n (operand) => {\n const str = operand.value;\n return operand.type === \"StringValue\" && str === str.toUpperCase();\n }\n ],\n [\"none\", (operand) => operand.type === \"NullValue\"],\n [\"defined\", (operand) => operand.type !== \"UndefinedValue\"],\n [\"undefined\", (operand) => operand.type === \"UndefinedValue\"],\n [\"equalto\", (a, b) => a.value === b.value]\n ]);\n /**\n * Set the value of a variable in the current environment.\n */\n set(name, value) {\n return this.declareVariable(name, convertToRuntimeValues(value));\n }\n declareVariable(name, value) {\n if (this.variables.has(name)) {\n throw new SyntaxError(`Variable already declared: ${name}`);\n }\n this.variables.set(name, value);\n return value;\n }\n // private assignVariable(name: string, value: AnyRuntimeValue): AnyRuntimeValue {\n // \tconst env = this.resolve(name);\n // \tenv.variables.set(name, value);\n // \treturn value;\n // }\n /**\n * Set variable in the current scope.\n * See https://jinja.palletsprojects.com/en/3.0.x/templates/#assignments for more information.\n */\n setVariable(name, value) {\n this.variables.set(name, value);\n return value;\n }\n /**\n * Resolve the environment in which the variable is declared.\n * @param {string} name The name of the variable.\n * @returns {Environment} The environment in which the variable is declared.\n */\n resolve(name) {\n if (this.variables.has(name)) {\n return this;\n }\n if (this.parent) {\n return this.parent.resolve(name);\n }\n throw new Error(`Unknown variable: ${name}`);\n }\n lookupVariable(name) {\n try {\n return this.resolve(name).variables.get(name) ?? new UndefinedValue();\n } catch {\n return new UndefinedValue();\n }\n }\n};\nvar Interpreter = class {\n global;\n constructor(env) {\n this.global = env ?? new Environment();\n }\n /**\n * Run the program.\n */\n run(program) {\n return this.evaluate(program, this.global);\n }\n /**\n * Evaluates expressions following the binary operation type.\n */\n evaluateBinaryExpression(node, environment) {\n const left = this.evaluate(node.left, environment);\n switch (node.operator.value) {\n case \"and\":\n return left.__bool__().value ? this.evaluate(node.right, environment) : left;\n case \"or\":\n return left.__bool__().value ? left : this.evaluate(node.right, environment);\n }\n const right = this.evaluate(node.right, environment);\n switch (node.operator.value) {\n case \"==\":\n return new BooleanValue(left.value == right.value);\n case \"!=\":\n return new BooleanValue(left.value != right.value);\n }\n if (left instanceof UndefinedValue || right instanceof UndefinedValue) {\n throw new Error(\"Cannot perform operation on undefined values\");\n } else if (left instanceof NullValue || right instanceof NullValue) {\n throw new Error(\"Cannot perform operation on null values\");\n } else if (left instanceof NumericValue && right instanceof NumericValue) {\n switch (node.operator.value) {\n case \"+\":\n return new NumericValue(left.value + right.value);\n case \"-\":\n return new NumericValue(left.value - right.value);\n case \"*\":\n return new NumericValue(left.value * right.value);\n case \"/\":\n return new NumericValue(left.value / right.value);\n case \"%\":\n return new NumericValue(left.value % right.value);\n case \"<\":\n return new BooleanValue(left.value < right.value);\n case \">\":\n return new BooleanValue(left.value > right.value);\n case \">=\":\n return new BooleanValue(left.value >= right.value);\n case \"<=\":\n return new BooleanValue(left.value <= right.value);\n }\n } else if (left instanceof ArrayValue && right instanceof ArrayValue) {\n switch (node.operator.value) {\n case \"+\":\n return new ArrayValue(left.value.concat(right.value));\n }\n } else if (right instanceof ArrayValue) {\n const member = right.value.find((x) => x.value === left.value) !== void 0;\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(member);\n case \"not in\":\n return new BooleanValue(!member);\n }\n }\n if (left instanceof StringValue || right instanceof StringValue) {\n switch (node.operator.value) {\n case \"+\":\n return new StringValue(left.value.toString() + right.value.toString());\n }\n }\n if (left instanceof StringValue && right instanceof StringValue) {\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(right.value.includes(left.value));\n case \"not in\":\n return new BooleanValue(!right.value.includes(left.value));\n }\n }\n if (left instanceof StringValue && right instanceof ObjectValue) {\n switch (node.operator.value) {\n case \"in\":\n return new BooleanValue(right.value.has(left.value));\n case \"not in\":\n return new BooleanValue(!right.value.has(left.value));\n }\n }\n throw new SyntaxError(`Unknown operator \"${node.operator.value}\" between ${left.type} and ${right.type}`);\n }\n /**\n * Evaluates expressions following the filter operation type.\n */\n evaluateFilterExpression(node, environment) {\n const operand = this.evaluate(node.operand, environment);\n if (node.filter.type === \"Identifier\") {\n const filter = node.filter;\n if (operand instanceof ArrayValue) {\n switch (filter.value) {\n case \"list\":\n return operand;\n case \"first\":\n return operand.value[0];\n case \"last\":\n return operand.value[operand.value.length - 1];\n case \"length\":\n return new NumericValue(operand.value.length);\n case \"reverse\":\n return new ArrayValue(operand.value.reverse());\n case \"sort\":\n return new ArrayValue(\n operand.value.sort((a, b) => {\n if (a.type !== b.type) {\n throw new Error(`Cannot compare different types: ${a.type} and ${b.type}`);\n }\n switch (a.type) {\n case \"NumericValue\":\n return a.value - b.value;\n case \"StringValue\":\n return a.value.localeCompare(b.value);\n default:\n throw new Error(`Cannot compare type: ${a.type}`);\n }\n })\n );\n default:\n throw new Error(`Unknown ArrayValue filter: ${filter.value}`);\n }\n } else if (operand instanceof StringValue) {\n switch (filter.value) {\n case \"length\":\n return new NumericValue(operand.value.length);\n case \"upper\":\n return new StringValue(operand.value.toUpperCase());\n case \"lower\":\n return new StringValue(operand.value.toLowerCase());\n case \"title\":\n return new StringValue(titleCase(operand.value));\n case \"capitalize\":\n return new StringValue(operand.value.charAt(0).toUpperCase() + operand.value.slice(1));\n case \"trim\":\n return new StringValue(operand.value.trim());\n default:\n throw new Error(`Unknown StringValue filter: ${filter.value}`);\n }\n } else if (operand instanceof NumericValue) {\n switch (filter.value) {\n case \"abs\":\n return new NumericValue(Math.abs(operand.value));\n default:\n throw new Error(`Unknown NumericValue filter: ${filter.value}`);\n }\n } else if (operand instanceof ObjectValue) {\n switch (filter.value) {\n case \"items\":\n return new ArrayValue(\n Array.from(operand.value.entries()).map(([key, value]) => new ArrayValue([new StringValue(key), value]))\n );\n case \"length\":\n return new NumericValue(operand.value.size);\n default:\n throw new Error(`Unknown ObjectValue filter: ${filter.value}`);\n }\n }\n throw new Error(`Cannot apply filter \"${filter.value}\" to type: ${operand.type}`);\n } else if (node.filter.type === \"CallExpression\") {\n const filter = node.filter;\n if (filter.callee.type !== \"Identifier\") {\n throw new Error(`Unknown filter: ${filter.callee.type}`);\n }\n const filterName = filter.callee.value;\n if (operand instanceof ArrayValue) {\n switch (filterName) {\n case \"selectattr\": {\n if (operand.value.some((x) => !(x instanceof ObjectValue))) {\n throw new Error(\"`selectattr` can only be applied to array of objects\");\n }\n if (filter.args.some((x) => x.type !== \"StringLiteral\")) {\n throw new Error(\"arguments of `selectattr` must be strings\");\n }\n const [attr, testName, value] = filter.args.map((x) => this.evaluate(x, environment));\n let testFunction;\n if (testName) {\n const test = environment.tests.get(testName.value);\n if (!test) {\n throw new Error(`Unknown test: ${testName.value}`);\n }\n testFunction = test;\n } else {\n testFunction = (...x) => x[0].__bool__().value;\n }\n const filtered = operand.value.filter((item) => {\n const a = item.value.get(attr.value);\n if (a) {\n return testFunction(a, value);\n }\n return false;\n });\n return new ArrayValue(filtered);\n }\n }\n throw new Error(`Unknown ArrayValue filter: ${filterName}`);\n } else {\n throw new Error(`Cannot apply filter \"${filterName}\" to type: ${operand.type}`);\n }\n }\n throw new Error(`Unknown filter: ${node.filter.type}`);\n }\n /**\n * Evaluates expressions following the test operation type.\n */\n evaluateTestExpression(node, environment) {\n const operand = this.evaluate(node.operand, environment);\n const test = environment.tests.get(node.test.value);\n if (!test) {\n throw new Error(`Unknown test: ${node.test.value}`);\n }\n const result = test(operand);\n return new BooleanValue(node.negate ? !result : result);\n }\n /**\n * Evaluates expressions following the unary operation type.\n */\n evaluateUnaryExpression(node, environment) {\n const argument = this.evaluate(node.argument, environment);\n switch (node.operator.value) {\n case \"not\":\n return new BooleanValue(!argument.value);\n default:\n throw new SyntaxError(`Unknown operator: ${node.operator.value}`);\n }\n }\n evalProgram(program, environment) {\n return this.evaluateBlock(program.body, environment);\n }\n evaluateBlock(statements, environment) {\n let result = \"\";\n for (const statement of statements) {\n const lastEvaluated = this.evaluate(statement, environment);\n if (lastEvaluated.type !== \"NullValue\" && lastEvaluated.type !== \"UndefinedValue\") {\n result += lastEvaluated.value;\n }\n }\n return new StringValue(result);\n }\n evaluateIdentifier(node, environment) {\n return environment.lookupVariable(node.value);\n }\n evaluateCallExpression(expr, environment) {\n const args = [];\n const kwargs = /* @__PURE__ */ new Map();\n for (const argument of expr.args) {\n if (argument.type === \"KeywordArgumentExpression\") {\n const kwarg = argument;\n kwargs.set(kwarg.key.value, this.evaluate(kwarg.value, environment));\n } else {\n args.push(this.evaluate(argument, environment));\n }\n }\n if (kwargs.size > 0) {\n args.push(new ObjectValue(kwargs));\n }\n const fn = this.evaluate(expr.callee, environment);\n if (fn.type !== \"FunctionValue\") {\n throw new Error(`Cannot call something that is not a function: got ${fn.type}`);\n }\n return fn.value(args, environment);\n }\n evaluateSliceExpression(object, expr, environment) {\n if (!(object instanceof ArrayValue || object instanceof StringValue)) {\n throw new Error(\"Slice object must be an array or string\");\n }\n const start = this.evaluate(expr.start, environment);\n const stop = this.evaluate(expr.stop, environment);\n const step = this.evaluate(expr.step, environment);\n if (!(start instanceof NumericValue || start instanceof UndefinedValue)) {\n throw new Error(\"Slice start must be numeric or undefined\");\n }\n if (!(stop instanceof NumericValue || stop instanceof UndefinedValue)) {\n throw new Error(\"Slice stop must be numeric or undefined\");\n }\n if (!(step instanceof NumericValue || step instanceof UndefinedValue)) {\n throw new Error(\"Slice step must be numeric or undefined\");\n }\n if (object instanceof ArrayValue) {\n return new ArrayValue(slice(object.value, start.value, stop.value, step.value));\n } else {\n return new StringValue(slice(Array.from(object.value), start.value, stop.value, step.value).join(\"\"));\n }\n }\n evaluateMemberExpression(expr, environment) {\n const object = this.evaluate(expr.object, environment);\n let property;\n if (expr.computed) {\n if (expr.property.type === \"SliceExpression\") {\n return this.evaluateSliceExpression(object, expr.property, environment);\n } else {\n property = this.evaluate(expr.property, environment);\n }\n } else {\n property = new StringValue(expr.property.value);\n }\n let value;\n if (object instanceof ObjectValue) {\n if (!(property instanceof StringValue)) {\n throw new Error(`Cannot access property with non-string: got ${property.type}`);\n }\n value = object.value.get(property.value) ?? object.builtins.get(property.value);\n } else if (object instanceof ArrayValue || object instanceof StringValue) {\n if (property instanceof NumericValue) {\n value = object.value.at(property.value);\n if (object instanceof StringValue) {\n value = new StringValue(object.value.at(property.value));\n }\n } else if (property instanceof StringValue) {\n value = object.builtins.get(property.value);\n } else {\n throw new Error(`Cannot access property with non-string/non-number: got ${property.type}`);\n }\n } else {\n if (!(property instanceof StringValue)) {\n throw new Error(`Cannot access property with non-string: got ${property.type}`);\n }\n value = object.builtins.get(property.value);\n }\n return value instanceof RuntimeValue ? value : new UndefinedValue();\n }\n evaluateSet(node, environment) {\n const rhs = this.evaluate(node.value, environment);\n if (node.assignee.type === \"Identifier\") {\n const variableName = node.assignee.value;\n environment.setVariable(variableName, rhs);\n } else if (node.assignee.type === \"MemberExpression\") {\n const member = node.assignee;\n const object = this.evaluate(member.object, environment);\n if (!(object instanceof ObjectValue)) {\n throw new Error(\"Cannot assign to member of non-object\");\n }\n if (member.property.type !== \"Identifier\") {\n throw new Error(\"Cannot assign to member with non-identifier property\");\n }\n object.value.set(member.property.value, rhs);\n } else {\n throw new Error(`Invalid LHS inside assignment expression: ${JSON.stringify(node.assignee)}`);\n }\n return new NullValue();\n }\n evaluateIf(node, environment) {\n const test = this.evaluate(node.test, environment);\n return this.evaluateBlock(test.__bool__().value ? node.body : node.alternate, environment);\n }\n evaluateFor(node, environment) {\n const scope = new Environment(environment);\n const iterable = this.evaluate(node.iterable, scope);\n if (!(iterable instanceof ArrayValue)) {\n throw new Error(`Expected iterable type in for loop: got ${iterable.type}`);\n }\n let result = \"\";\n for (let i = 0; i < iterable.value.length; ++i) {\n const loop = /* @__PURE__ */ new Map([\n [\"index\", new NumericValue(i + 1)],\n [\"index0\", new NumericValue(i)],\n [\"revindex\", new NumericValue(iterable.value.length - i)],\n [\"revindex0\", new NumericValue(iterable.value.length - i - 1)],\n [\"first\", new BooleanValue(i === 0)],\n [\"last\", new BooleanValue(i === iterable.value.length - 1)],\n [\"length\", new NumericValue(iterable.value.length)],\n [\"previtem\", i > 0 ? iterable.value[i - 1] : new UndefinedValue()],\n [\"nextitem\", i < iterable.value.length - 1 ? iterable.value[i + 1] : new UndefinedValue()]\n ]);\n scope.setVariable(\"loop\", new ObjectValue(loop));\n const current = iterable.value[i];\n if (node.loopvar.type === \"Identifier\") {\n scope.setVariable(node.loopvar.value, current);\n } else if (node.loopvar.type === \"TupleLiteral\") {\n const loopvar = node.loopvar;\n if (current.type !== \"ArrayValue\") {\n throw new Error(`Cannot unpack non-iterable type: ${current.type}`);\n }\n const c = current;\n if (loopvar.value.length !== c.value.length) {\n throw new Error(`Too ${loopvar.value.length > c.value.length ? \"few\" : \"many\"} items to unpack`);\n }\n for (let j = 0; j < loopvar.value.length; ++j) {\n if (loopvar.value[j].type !== \"Identifier\") {\n throw new Error(`Cannot unpack non-identifier type: ${loopvar.value[j].type}`);\n }\n scope.setVariable(loopvar.value[j].value, c.value[j]);\n }\n }\n const evaluated = this.evaluateBlock(node.body, scope);\n result += evaluated.value;\n }\n return new StringValue(result);\n }\n evaluate(statement, environment) {\n if (statement === void 0)\n return new UndefinedValue();\n switch (statement.type) {\n case \"Program\":\n return this.evalProgram(statement, environment);\n case \"Set\":\n return this.evaluateSet(statement, environment);\n case \"If\":\n return this.evaluateIf(statement, environment);\n case \"For\":\n return this.evaluateFor(statement, environment);\n case \"NumericLiteral\":\n return new NumericValue(Number(statement.value));\n case \"StringLiteral\":\n return new StringValue(statement.value);\n case \"BooleanLiteral\":\n return new BooleanValue(statement.value);\n case \"ArrayLiteral\":\n return new ArrayValue(statement.value.map((x) => this.evaluate(x, environment)));\n case \"TupleLiteral\":\n return new TupleValue(statement.value.map((x) => this.evaluate(x, environment)));\n case \"ObjectLiteral\": {\n const mapping = /* @__PURE__ */ new Map();\n for (const [key, value] of statement.value) {\n const evaluatedKey = this.evaluate(key, environment);\n if (!(evaluatedKey instanceof StringValue)) {\n throw new Error(`Object keys must be strings: got ${evaluatedKey.type}`);\n }\n mapping.set(evaluatedKey.value, this.evaluate(value, environment));\n }\n return new ObjectValue(mapping);\n }\n case \"Identifier\":\n return this.evaluateIdentifier(statement, environment);\n case \"CallExpression\":\n return this.evaluateCallExpression(statement, environment);\n case \"MemberExpression\":\n return this.evaluateMemberExpression(statement, environment);\n case \"UnaryExpression\":\n return this.evaluateUnaryExpression(statement, environment);\n case \"BinaryExpression\":\n return this.evaluateBinaryExpression(statement, environment);\n case \"FilterExpression\":\n return this.evaluateFilterExpression(statement, environment);\n case \"TestExpression\":\n return this.evaluateTestExpression(statement, environment);\n default:\n throw new SyntaxError(`Unknown node type: ${statement.type}`);\n }\n }\n};\nfunction convertToRuntimeValues(input) {\n switch (typeof input) {\n case \"number\":\n return new NumericValue(input);\n case \"string\":\n return new StringValue(input);\n case \"boolean\":\n return new BooleanValue(input);\n case \"object\":\n if (input === null) {\n return new NullValue();\n } else if (Array.isArray(input)) {\n return new ArrayValue(input.map(convertToRuntimeValues));\n } else {\n return new ObjectValue(\n new Map(Object.entries(input).map(([key, value]) => [key, convertToRuntimeValues(value)]))\n );\n }\n case \"function\":\n return new FunctionValue((args, _scope) => {\n const result = input(...args.map((x) => x.value)) ?? null;\n return convertToRuntimeValues(result);\n });\n default:\n throw new Error(`Cannot convert to runtime value: ${input}`);\n }\n}\n\n// src/index.ts\nvar Template = class {\n parsed;\n /**\n * @param {string} template The template string\n */\n constructor(template) {\n const tokens = tokenize(template, {\n lstrip_blocks: true,\n trim_blocks: true\n });\n this.parsed = parse(tokens);\n }\n render(items) {\n const env = new Environment();\n env.set(\"false\", false);\n env.set(\"true\", true);\n env.set(\"raise_exception\", (args) => {\n throw new Error(args);\n });\n env.set(\"range\", range);\n for (const [key, value] of Object.entries(items)) {\n env.set(key, value);\n }\n const interpreter = new Interpreter(env);\n const result = interpreter.run(this.parsed);\n return result.value;\n }\n};\nexport {\n Environment,\n Interpreter,\n Template,\n parse,\n tokenize\n};\n"],"names":[],"mappings":"AACA,IAAI,cAAc,OAAO,OAAO;AAAA,EAC9B,MAAM;AAAA;AAAA,EAEN,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,eAAe;AAAA;AAAA,EAEf,YAAY;AAAA;AAAA,EAEZ,QAAQ;AAAA;AAAA,EAER,WAAW;AAAA;AAAA,EAEX,YAAY;AAAA;AAAA,EAEZ,eAAe;AAAA;AAAA,EAEf,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,iBAAiB;AAAA;AAAA,EAEjB,mBAAmB;AAAA;AAAA,EAEnB,oBAAoB;AAAA;AAAA,EAEpB,kBAAkB;AAAA;AAAA,EAElB,mBAAmB;AAAA;AAAA,EAEnB,OAAO;AAAA;AAAA,EAEP,KAAK;AAAA;AAAA,EAEL,OAAO;AAAA;AAAA,EAEP,MAAM;AAAA;AAAA,EAEN,cAAc;AAAA;AAAA,EAEd,wBAAwB;AAAA;AAAA,EAExB,8BAA8B;AAAA;AAAA,EAE9B,0BAA0B;AAAA;AAAA,EAE1B,eAAe;AAAA;AAAA;AAAA,EAGf,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,KAAK;AACP,CAAC;AACc,OAAO,OAAO;AAAA,EAC3B,KAAK,YAAY;AAAA,EACjB,KAAK,YAAY;AAAA,EACjB,IAAI,YAAY;AAAA,EAChB,IAAI,YAAY;AAAA,EAChB,IAAI,YAAY;AAAA,EAChB,MAAM,YAAY;AAAA,EAClB,OAAO,YAAY;AAAA,EACnB,MAAM,YAAY;AAAA,EAClB,QAAQ,YAAY;AAAA,EACpB,KAAK,YAAY;AAAA,EACjB,IAAI,YAAY;AAAA,EAChB,KAAK,YAAY;AAAA,EACjB,UAAU,YAAY;AAAA;AAAA,EAEtB,MAAM,YAAY;AAAA,EAClB,OAAO,YAAY;AACrB,CAAC;AAkB2B;AAAA;AAAA,EAE1B,CAAC,MAAM,YAAY,aAAa;AAAA,EAChC,CAAC,MAAM,YAAY,cAAc;AAAA,EACjC,CAAC,MAAM,YAAY,cAAc;AAAA,EACjC,CAAC,MAAM,YAAY,eAAe;AAAA;AAAA,EAElC,CAAC,KAAK,YAAY,SAAS;AAAA,EAC3B,CAAC,KAAK,YAAY,UAAU;AAAA,EAC5B,CAAC,KAAK,YAAY,gBAAgB;AAAA,EAClC,CAAC,KAAK,YAAY,iBAAiB;AAAA,EACnC,CAAC,KAAK,YAAY,iBAAiB;AAAA,EACnC,CAAC,KAAK,YAAY,kBAAkB;AAAA,EACpC,CAAC,KAAK,YAAY,KAAK;AAAA,EACvB,CAAC,KAAK,YAAY,GAAG;AAAA,EACrB,CAAC,KAAK,YAAY,KAAK;AAAA,EACvB,CAAC,KAAK,YAAY,IAAI;AAAA;AAAA,EAEtB,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,MAAM,YAAY,wBAAwB;AAAA,EAC3C,CAAC,KAAK,YAAY,wBAAwB;AAAA,EAC1C,CAAC,KAAK,YAAY,wBAAwB;AAAA;AAAA,EAE1C,CAAC,KAAK,YAAY,sBAAsB;AAAA,EACxC,CAAC,KAAK,YAAY,sBAAsB;AAAA,EACxC,CAAC,KAAK,YAAY,4BAA4B;AAAA,EAC9C,CAAC,KAAK,YAAY,4BAA4B;AAAA,EAC9C,CAAC,KAAK,YAAY,4BAA4B;AAAA;AAAA,EAE9C,CAAC,KAAK,YAAY,MAAM;AAC1B;","x_google_ignoreList":[0]}
@@ -1,4 +1,4 @@
1
- import { __exports as dist } from "../../../../_virtual/index8.js";
1
+ import { __exports as dist } from "../../../../_virtual/index7.js";
2
2
  import { __require as requireCreateProjectService } from "./createProjectService.js";
3
3
  var hasRequiredDist;
4
4
  function requireDist() {
@@ -0,0 +1,24 @@
1
+ import * as __viteBrowserExternal from "../../../../../_virtual/__vite-browser-external.js";
2
+ import sharp from "../../../../../_virtual/__vite-browser-external.js";
3
+ import * as ortWeb_min from "../../../../../_virtual/ort-web.min.js";
4
+ import ortWeb_min$1 from "../../../../../_virtual/ort-web.min.js";
5
+ let ONNX;
6
+ const executionProviders = [
7
+ // 'webgpu',
8
+ "wasm"
9
+ ];
10
+ if (typeof process !== "undefined" && process?.release?.name === "node") {
11
+ ONNX = sharp ?? __viteBrowserExternal;
12
+ executionProviders.unshift("cpu");
13
+ } else {
14
+ ONNX = ortWeb_min$1 ?? ortWeb_min;
15
+ const isIOS = typeof navigator !== "undefined" && /iP(hone|od|ad).+16_4.+AppleWebKit/.test(navigator.userAgent);
16
+ if (isIOS) {
17
+ ONNX.env.wasm.simd = false;
18
+ }
19
+ }
20
+ export {
21
+ ONNX,
22
+ executionProviders
23
+ };
24
+ //# sourceMappingURL=onnx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"onnx.js","sources":["../../../../../../node_modules/@xenova/transformers/src/backends/onnx.js"],"sourcesContent":["/**\n * @file Handler file for choosing the correct version of ONNX Runtime, based on the environment.\n * Ideally, we could import the `onnxruntime-web` and `onnxruntime-node` packages only when needed,\n * but dynamic imports don't seem to work with the current webpack version and/or configuration.\n * This is possibly due to the experimental nature of top-level await statements.\n * So, we just import both packages, and use the appropriate one based on the environment:\n * - When running in node, we use `onnxruntime-node`.\n * - When running in the browser, we use `onnxruntime-web` (`onnxruntime-node` is not bundled).\n * \n * This module is not directly exported, but can be accessed through the environment variables:\n * ```javascript\n * import { env } from '@xenova/transformers';\n * console.log(env.backends.onnx);\n * ```\n * \n * @module backends/onnx\n */\n\n// NOTE: Import order matters here. We need to import `onnxruntime-node` before `onnxruntime-web`.\n// In either case, we select the default export if it exists, otherwise we use the named export.\nimport * as ONNX_NODE from 'onnxruntime-node';\nimport * as ONNX_WEB from 'onnxruntime-web';\n\n/** @type {import('onnxruntime-web')} The ONNX runtime module. */\nexport let ONNX;\n\nexport const executionProviders = [\n // 'webgpu',\n 'wasm'\n];\n\nif (typeof process !== 'undefined' && process?.release?.name === 'node') {\n // Running in a node-like environment.\n ONNX = ONNX_NODE.default ?? ONNX_NODE;\n\n // Add `cpu` execution provider, with higher precedence that `wasm`.\n executionProviders.unshift('cpu');\n\n} else {\n // Running in a browser-environment\n ONNX = ONNX_WEB.default ?? ONNX_WEB;\n\n // SIMD for WebAssembly does not operate correctly in some recent versions of iOS (16.4.x).\n // As a temporary fix, we disable it for now.\n // For more information, see: https://github.com/microsoft/onnxruntime/issues/15644\n const isIOS = typeof navigator !== 'undefined' && /iP(hone|od|ad).+16_4.+AppleWebKit/.test(navigator.userAgent);\n if (isIOS) {\n ONNX.env.wasm.simd = false;\n }\n}\n"],"names":["ONNX_NODE.default","ONNX_NODE","ONNX_WEB.default","ONNX_WEB"],"mappings":";;;;AAwBU,IAAC;AAEC,MAAC,qBAAqB;AAAA;AAAA,EAE9B;AACJ;AAEA,IAAI,OAAO,YAAY,eAAe,SAAS,SAAS,SAAS,QAAQ;AAErE,SAAOA,SAAqBC;AAG5B,qBAAmB,QAAQ,KAAK;AAEpC,OAAO;AAEH,SAAOC,gBAAoBC;AAK3B,QAAM,QAAQ,OAAO,cAAc,eAAe,oCAAoC,KAAK,UAAU,SAAS;AAC9G,MAAI,OAAO;AACP,SAAK,IAAI,KAAK,OAAO;AAAA,EACzB;AACJ;","x_google_ignoreList":[0]}