@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.
- package/LICENSE +21 -0
- package/README.md +70 -3
- package/dist/_virtual/__vite-browser-external.js +2 -2
- package/dist/_virtual/__vite-browser-external.js.map +1 -1
- package/dist/_virtual/index12.js +7 -0
- package/dist/_virtual/index12.js.map +1 -0
- package/dist/_virtual/ort-web.min.js +8 -0
- package/dist/_virtual/ort-web.min.js.map +1 -0
- package/dist/_virtual/ort-web.min2.js +5 -0
- package/dist/_virtual/ort-web.min2.js.map +1 -0
- package/dist/agents/base-agent.d.ts +63 -0
- package/dist/agents/base-agent.d.ts.map +1 -1
- package/dist/agents/base-agent.js +139 -0
- package/dist/agents/base-agent.js.map +1 -1
- package/dist/agents/coordinator-agent.d.ts +422 -0
- package/dist/agents/coordinator-agent.d.ts.map +1 -0
- package/dist/agents/documenter-agent.d.ts +298 -0
- package/dist/agents/documenter-agent.d.ts.map +1 -0
- package/dist/agents/index.d.ts +11 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +4 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/mixins/index.d.ts +9 -0
- package/dist/agents/mixins/index.d.ts.map +1 -0
- package/dist/agents/mixins/trajectory-mixin.d.ts +112 -0
- package/dist/agents/mixins/trajectory-mixin.d.ts.map +1 -0
- package/dist/agents/optimizer-agent.d.ts +388 -0
- package/dist/agents/optimizer-agent.d.ts.map +1 -0
- package/dist/agents/planner-agent.d.ts +395 -0
- package/dist/agents/planner-agent.d.ts.map +1 -0
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +5 -0
- package/dist/agents/registry.js.map +1 -1
- package/dist/agents/reviewer-agent.d.ts +330 -0
- package/dist/agents/reviewer-agent.d.ts.map +1 -0
- package/dist/agents/types.d.ts +12 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/types.js +1 -0
- package/dist/agents/types.js.map +1 -1
- package/dist/cli/commands/hive-mind/add-frontmatter.d.ts +102 -0
- package/dist/cli/commands/hive-mind/add-frontmatter.d.ts.map +1 -0
- package/dist/cli/commands/hive-mind/add-frontmatter.js +439 -0
- package/dist/cli/commands/hive-mind/add-frontmatter.js.map +1 -0
- package/dist/cli/commands/hive-mind/analyze-links.d.ts +80 -0
- package/dist/cli/commands/hive-mind/analyze-links.d.ts.map +1 -0
- package/dist/cli/commands/hive-mind/analyze-links.js +367 -0
- package/dist/cli/commands/hive-mind/analyze-links.js.map +1 -0
- package/dist/cli/commands/hive-mind/find-connections.d.ts +75 -0
- package/dist/cli/commands/hive-mind/find-connections.d.ts.map +1 -0
- package/dist/cli/commands/hive-mind/find-connections.js +347 -0
- package/dist/cli/commands/hive-mind/find-connections.js.map +1 -0
- package/dist/cli/commands/hive-mind/index.d.ts +37 -0
- package/dist/cli/commands/hive-mind/index.d.ts.map +1 -0
- package/dist/cli/commands/hive-mind/index.js +33 -0
- package/dist/cli/commands/hive-mind/index.js.map +1 -0
- package/dist/cli/commands/hive-mind/validate-names.d.ts +79 -0
- package/dist/cli/commands/hive-mind/validate-names.d.ts.map +1 -0
- package/dist/cli/commands/hive-mind/validate-names.js +353 -0
- package/dist/cli/commands/hive-mind/validate-names.js.map +1 -0
- package/dist/cli/commands/vector.js +2 -0
- package/dist/cli/commands/vector.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/equilibrium/agent-equilibrium.d.ts +194 -0
- package/dist/equilibrium/agent-equilibrium.d.ts.map +1 -0
- package/dist/equilibrium/agent-equilibrium.js +304 -0
- package/dist/equilibrium/agent-equilibrium.js.map +1 -0
- package/dist/equilibrium/graph-equilibrium.d.ts +177 -0
- package/dist/equilibrium/graph-equilibrium.d.ts.map +1 -0
- package/dist/equilibrium/index.d.ts +11 -0
- package/dist/equilibrium/index.d.ts.map +1 -0
- package/dist/equilibrium/memory-equilibrium.d.ts +153 -0
- package/dist/equilibrium/memory-equilibrium.d.ts.map +1 -0
- package/dist/graphql/resolvers/index.d.ts.map +1 -1
- package/dist/graphql/resolvers/queries.d.ts +11 -0
- package/dist/graphql/resolvers/queries.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -4
- package/dist/index.js.map +1 -1
- package/dist/inference/index.d.ts +9 -0
- package/dist/inference/index.d.ts.map +1 -0
- package/dist/inference/model-selection.d.ts +131 -0
- package/dist/inference/model-selection.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/agent-booster-adapter.d.ts +265 -0
- package/dist/integrations/agentic-flow/adapters/agent-booster-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/agentdb-adapter.d.ts +197 -0
- package/dist/integrations/agentic-flow/adapters/agentdb-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/agentdb-vector-store.d.ts +249 -0
- package/dist/integrations/agentic-flow/adapters/agentdb-vector-store.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/base-adapter.d.ts +120 -0
- package/dist/integrations/agentic-flow/adapters/base-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/federation-hub-adapter.d.ts +444 -0
- package/dist/integrations/agentic-flow/adapters/federation-hub-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/index.d.ts +17 -0
- package/dist/integrations/agentic-flow/adapters/index.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/model-router-adapter.d.ts +242 -0
- package/dist/integrations/agentic-flow/adapters/model-router-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/quic-transport-adapter.d.ts +364 -0
- package/dist/integrations/agentic-flow/adapters/quic-transport-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/adapters/reasoning-bank-adapter.d.ts +209 -0
- package/dist/integrations/agentic-flow/adapters/reasoning-bank-adapter.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/benchmark/index.d.ts +9 -0
- package/dist/integrations/agentic-flow/benchmark/index.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/benchmark/vector-benchmark.d.ts +253 -0
- package/dist/integrations/agentic-flow/benchmark/vector-benchmark.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/config.d.ts +109 -0
- package/dist/integrations/agentic-flow/config.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/feature-flags.d.ts +140 -0
- package/dist/integrations/agentic-flow/feature-flags.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/index.d.ts +22 -0
- package/dist/integrations/agentic-flow/index.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/migration/index.d.ts +9 -0
- package/dist/integrations/agentic-flow/migration/index.d.ts.map +1 -0
- package/dist/integrations/agentic-flow/migration/migrate-to-agentdb.d.ts +242 -0
- package/dist/integrations/agentic-flow/migration/migrate-to-agentdb.d.ts.map +1 -0
- package/dist/learning/index.d.ts +91 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/learning-loop.d.ts +176 -0
- package/dist/learning/learning-loop.d.ts.map +1 -0
- package/dist/learning/services/ab-testing-framework.d.ts +135 -0
- package/dist/learning/services/ab-testing-framework.d.ts.map +1 -0
- package/dist/learning/services/agent-priming-service.d.ts +207 -0
- package/dist/learning/services/agent-priming-service.d.ts.map +1 -0
- package/dist/learning/services/daily-log-generator.d.ts +113 -0
- package/dist/learning/services/daily-log-generator.d.ts.map +1 -0
- package/dist/learning/services/index.d.ts +14 -0
- package/dist/learning/services/index.d.ts.map +1 -0
- package/dist/learning/services/memory-extraction-service.d.ts +87 -0
- package/dist/learning/services/memory-extraction-service.d.ts.map +1 -0
- package/dist/learning/services/task-completion-consumer.d.ts +162 -0
- package/dist/learning/services/task-completion-consumer.d.ts.map +1 -0
- package/dist/learning/services/trajectory-tracker.d.ts +174 -0
- package/dist/learning/services/trajectory-tracker.d.ts.map +1 -0
- package/dist/learning/types.d.ts +516 -0
- package/dist/learning/types.d.ts.map +1 -0
- package/dist/mcp/clients/claude-flow-memory-client.d.ts +259 -0
- package/dist/mcp/clients/claude-flow-memory-client.d.ts.map +1 -0
- package/dist/mcp/clients/claude-flow-memory-client.js +305 -0
- package/dist/mcp/clients/claude-flow-memory-client.js.map +1 -0
- package/dist/mcp/clients/index.d.ts +11 -0
- package/dist/mcp/clients/index.d.ts.map +1 -0
- package/dist/mcp/clients/mcp-client-adapter.d.ts +146 -0
- package/dist/mcp/clients/mcp-client-adapter.d.ts.map +1 -0
- package/dist/mcp/clients/mcp-client-adapter.js +372 -0
- package/dist/mcp/clients/mcp-client-adapter.js.map +1 -0
- package/dist/mcp/index.d.ts +10 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/memory/vault-sync.d.ts +12 -0
- package/dist/memory/vault-sync.d.ts.map +1 -1
- package/dist/memory/vault-sync.js +94 -11
- package/dist/memory/vault-sync.js.map +1 -1
- package/dist/node_modules/@huggingface/jinja/dist/index.js +118 -0
- package/dist/node_modules/@huggingface/jinja/dist/index.js.map +1 -0
- package/dist/node_modules/@typescript-eslint/project-service/dist/index.js +1 -1
- package/dist/node_modules/@xenova/transformers/src/backends/onnx.js +24 -0
- package/dist/node_modules/@xenova/transformers/src/backends/onnx.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/configs.js +52 -0
- package/dist/node_modules/@xenova/transformers/src/configs.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/env.js +35 -0
- package/dist/node_modules/@xenova/transformers/src/env.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/models.js +3852 -0
- package/dist/node_modules/@xenova/transformers/src/models.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/tokenizers.js +144 -0
- package/dist/node_modules/@xenova/transformers/src/tokenizers.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/core.js +52 -0
- package/dist/node_modules/@xenova/transformers/src/utils/core.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/generation.js +623 -0
- package/dist/node_modules/@xenova/transformers/src/utils/generation.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/hub.js +395 -0
- package/dist/node_modules/@xenova/transformers/src/utils/hub.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/image.js +12 -0
- package/dist/node_modules/@xenova/transformers/src/utils/image.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/maths.js +89 -0
- package/dist/node_modules/@xenova/transformers/src/utils/maths.js.map +1 -0
- package/dist/node_modules/@xenova/transformers/src/utils/tensor.js +750 -0
- package/dist/node_modules/@xenova/transformers/src/utils/tensor.js.map +1 -0
- package/dist/node_modules/fdir/dist/index.js +13 -13
- package/dist/node_modules/fdir/dist/index.js.map +1 -1
- package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js +67 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/backend-impl.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js +24 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/env-impl.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/env.js +6 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/env.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/index.js +11 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/index.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js +162 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session-impl.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js +6 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/inference-session.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js +393 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor-impl.js.map +1 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js +6 -0
- package/dist/node_modules/onnxruntime-common/dist/lib/tensor.js.map +1 -0
- package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js +12919 -0
- package/dist/node_modules/onnxruntime-web/dist/ort-web.min.js.map +1 -0
- package/dist/node_modules/tinyglobby/dist/index.js +14 -14
- package/dist/node_modules/tinyglobby/dist/index.js.map +1 -1
- package/dist/node_modules/typescript/lib/typescript.js +24 -24
- package/dist/node_modules/typescript/lib/typescript.js.map +1 -1
- package/dist/transport/agent-transport.d.ts +269 -0
- package/dist/transport/agent-transport.d.ts.map +1 -0
- package/dist/transport/index.d.ts +10 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/vector/index.d.ts +1 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/services/embedding-service.d.ts +244 -0
- package/dist/vector/services/embedding-service.d.ts.map +1 -0
- package/dist/vector/services/embedding-service.js +10 -0
- package/dist/vector/services/embedding-service.js.map +1 -0
- package/dist/vector/services/hybrid-search.d.ts +320 -0
- package/dist/vector/services/hybrid-search.d.ts.map +1 -0
- package/dist/vector/services/hybrid-search.js +3 -0
- package/dist/vector/services/hybrid-search.js.map +1 -0
- package/dist/vector/services/index.d.ts +4 -0
- package/dist/vector/services/index.d.ts.map +1 -1
- 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
|
-
|
|
315
|
-
|
|
316
|
-
|
|
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("
|
|
365
|
+
logger.debug("Retrieving nodes from memory via MCP", {
|
|
321
366
|
namespace: this.options.namespace
|
|
322
367
|
});
|
|
323
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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":";;;AAeA,MAAM,SAAS,aAAa,YAAY;AAiJjC,MAAM,gBAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EACA,KAAoC;AAAA,EACpC,kCAA2C,IAAA;AAAA,EAC3C,YAA4B,CAAA;AAAA,EAC5B,eAA4B;AAAA,EAC5B,YAAY;AAAA,EACZ,aAAuB,CAAA;AAAA,EACvB,gBAAuC;AAAA,EAE/C,YAAY,SAA2B;AACrC,SAAK,UAAU;AAAA,MACb,aAAa,QAAQ;AAAA,MACrB,WAAW,QAAQ,aAAa;AAAA,MAChC,kBAAkB,QAAQ,oBAAoB;AAAA,MAC9C,UAAU,QAAQ,YAAY;AAAA,MAC9B,kBAAkB,QAAQ,oBAAoB;AAAA;AAAA,MAC9C,cAAc,QAAQ,gBAAgB,EAAE,YAAY,GAAG,cAAc,IAAA;AAAA,MACrE,WAAW,QAAQ,aAAa;AAAA,MAChC,gBAAgB,QAAQ,kBAAkB;AAAA,MAC1C,kBAAkB,QAAQ,oBAAoB;AAAA,IAAA;AAGhD,SAAK,cAAc,IAAI,YAAY;AAAA,MACjC,aAAa,QAAQ;AAAA,MACrB,UAAU;AAAA,IAAA,CACX;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,IAA2C;AAC1D,SAAK,KAAK;AACV,UAAM,KAAK,YAAY,KAAA;AAGvB,UAAM,KAAK,gBAAA;AAEX,QAAI,KAAK,QAAQ,UAAU;AACzB,WAAK,cAAA;AAAA,IACP;AAEA,WAAO,KAAK,0BAA0B;AAAA,MACpC,WAAW,KAAK,QAAQ;AAAA,MACxB,UAAU,KAAK,QAAQ;AAAA,IAAA,CACxB;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAA6C;AACjD,QAAI,CAAC,KAAK,IAAI;AACZ,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,UAAM,YAAY,KAAK,IAAA;AACvB,UAAM,SAA8B;AAAA,MAClC,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW,CAAA;AAAA,MACX,QAAQ,CAAA;AAAA,MACR,UAAU;AAAA,IAAA;AAGZ,SAAK,YAAY;AACjB,SAAK,aAAa,CAAA;AAElB,QAAI;AACF,YAAM,QAAQ,KAAK,GAAG,YAAA;AACtB,YAAM,UAAU,KAAK,cAAc,OAAO,KAAK,QAAQ,SAAS;AAEhE,iBAAW,SAAS,SAAS;AAC3B,mBAAW,QAAQ,OAAO;AACxB,cAAI;AACF,kBAAM,aAAa,KAAK,kBAAkB,IAAI;AAC9C,kBAAM,SAAS,KAAK,YAAY,IAAI,KAAK,EAAE;AAG3C,gBAAI,UAAU,OAAO,gBAAgB,WAAW,aAAa;AAC3D,oBAAM,WAAW,MAAM,KAAK,eAAe,MAAM,MAAM;AACvD,kBAAI,UAAU;AACZ,uBAAO,UAAU,KAAK,QAAQ;AAC9B,sBAAM,WAAW,MAAM,KAAK,gBAAgB,QAAQ;AACpD,oBAAI,CAAC,UAAU;AACb,yBAAO;AACP;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAGA,kBAAM,KAAK,cAAc,UAAU;AACnC,iBAAK,YAAY,IAAI,KAAK,IAAI,UAAU;AACxC,mBAAO;AAAA,UACT,SAAS,OAAO;AACd,mBAAO;AACP,mBAAO,OAAO,KAAK;AAAA,cACjB,QAAQ,KAAK;AAAA,cACb,OAAO,OAAO,KAAK;AAAA,YAAA,CACpB;AACD,iBAAK,WAAW,KAAK,kBAAkB,KAAK,EAAE,KAAK,KAAK,EAAE;AAAA,UAC5D;AAAA,QACF;AAAA,MACF;AAGA,YAAM,KAAK,oBAAoB,KAAK;AAEpC,aAAO,WAAW,KAAK,IAAA,IAAQ;AAC/B,aAAO,UAAU,OAAO,WAAW;AACnC,WAAK,mCAAmB,KAAA;AAExB,aAAO,KAAK,4BAA4B;AAAA,QACtC,QAAQ,OAAO;AAAA,QACf,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,MAAA,CAClB;AAAA,IACH,UAAA;AACE,WAAK,YAAY;AACjB,YAAM,KAAK,gBAAA;AAAA,IACb;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAA+C;AACnD,QAAI,CAAC,KAAK,IAAI;AACZ,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AAEA,UAAM,YAAY,KAAK,IAAA;AACvB,UAAM,SAA8B;AAAA,MAClC,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,WAAW,CAAA;AAAA,MACX,QAAQ,CAAA;AAAA,MACR,UAAU;AAAA,IAAA;AAGZ,SAAK,YAAY;AACjB,SAAK,aAAa,CAAA;AAElB,QAAI;AAEF,YAAM,cAAc,MAAM,KAAK,mBAAA;AAE/B,iBAAW,cAAc,aAAa;AACpC,YAAI;AACF,gBAAM,eAAe,KAAK,GAAG,QAAQ,WAAW,EAAE;AAElD,cAAI,cAAc;AAEhB,kBAAM,cAAc,KAAK,mBAAmB,aAAa,OAAO;AAChE,gBAAI,gBAAgB,WAAW,aAAa;AAC1C,oBAAM,WAAW,KAAK,qBAAqB,cAAc,UAAU;AACnE,qBAAO,UAAU,KAAK,QAAQ;AAE9B,oBAAM,WAAW,MAAM,KAAK,gBAAgB,QAAQ;AACpD,kBAAI,CAAC,YAAY,SAAS,eAAe,SAAS;AAChD,uBAAO;AACP;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAIA,iBAAO;AACP,eAAK,YAAY,IAAI,WAAW,IAAI,UAAU;AAAA,QAChD,SAAS,OAAO;AACd,iBAAO;AACP,iBAAO,OAAO,KAAK;AAAA,YACjB,QAAQ,WAAW;AAAA,YACnB,OAAO,OAAO,KAAK;AAAA,UAAA,CACpB;AAAA,QACH;AAAA,MACF;AAEA,aAAO,WAAW,KAAK,IAAA,IAAQ;AAC/B,aAAO,UAAU,OAAO,WAAW;AACnC,WAAK,mCAAmB,KAAA;AAExB,aAAO,KAAK,8BAA8B;AAAA,QACxC,QAAQ,OAAO;AAAA,QACf,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,MAAA,CAClB;AAAA,IACH,UAAA;AACE,WAAK,YAAY;AACjB,YAAM,KAAK,gBAAA;AAAA,IACb;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAoC;AACxC,UAAM,YAAY,KAAK,IAAA;AAEvB,UAAM,WAAW,MAAM,KAAK,aAAA;AAC5B,UAAM,aAAa,MAAM,KAAK,eAAA;AAE9B,WAAO;AAAA,MACL,SAAS,SAAS,WAAW,WAAW;AAAA,MACxC;AAAA,MACA;AAAA,MACA,eAAe,KAAK,IAAA,IAAQ;AAAA,MAC5B,+BAAe,KAAA;AAAA,IAAK;AAAA,EAExB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAwB;AACtB,UAAM,sBAAsB,KAAK,KAC7B,KAAK,6BACL;AAEJ,UAAM,uBAAuB,KAAK,0BAAA;AAElC,QAAI,SAA+B;AACnC,QAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,eAAS;AAAA,IACX,WAAW,KAAK,UAAU,SAAS,KAAK,sBAAsB,IAAI;AAChE,eAAS;AAAA,IACX;AAEA,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,MACA,QAAQ,CAAC,GAAG,KAAK,UAAU;AAAA,MAC3B;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKA,eAA+B;AAC7B,WAAO,KAAK,UAAU,OAAO,CAAA,MAAK,CAAC,EAAE,UAAU;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,wBACJ,QACA,YACkB;AAClB,UAAM,WAAW,KAAK,UAAU;AAAA,MAC9B,CAAA,MAAK,EAAE,WAAW,UAAU,CAAC,EAAE;AAAA,IAAA;AAGjC,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AAEA,aAAS,aAAa;AACtB,aAAS,iCAAiB,KAAA;AAE1B,QAAI,eAAe,WAAW,KAAK,IAAI;AAErC,YAAM,OAAO,KAAK,GAAG,QAAQ,MAAM;AACnC,UAAI,MAAM;AACR,cAAM,aAAa,KAAK,kBAAkB,IAAI;AAC9C,cAAM,KAAK,cAAc,UAAU;AACnC,aAAK,YAAY,IAAI,QAAQ,UAAU;AAAA,MACzC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAuC;AAC3C,QAAI,CAAC,KAAK,IAAI;AACZ,aAAO,CAAA;AAAA,IACT;AAEA,UAAM,QAAQ,KAAK,GAAG,YAAA;AACtB,UAAM,YAAY,MAAM,IAAI,CAAA,MAAK,EAAE,IAAI;AAEvC,WAAO,KAAK,YAAY,cAAc,SAAS;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AACX,QAAI,KAAK,eAAe;AACtB,oBAAc,KAAK,aAAa;AAChC,WAAK,gBAAgB;AAAA,IACvB;AACA,SAAK,kBAAkB;AAAA,MAAM,CAAA,QAC3B,OAAO,MAAM,uCAAuC,GAAG;AAAA,IAAA;AAAA,EAE3D;AAAA;AAAA,EAIQ,gBAAsB;AAC5B,QAAI,KAAK,eAAe;AACtB,oBAAc,KAAK,aAAa;AAAA,IAClC;AAEA,SAAK,gBAAgB,YAAY,YAAY;AAC3C,UAAI,CAAC,KAAK,WAAW;AACnB,YAAI;AACF,gBAAM,KAAK,aAAA;AAAA,QACb,SAAS,OAAO;AACd,iBAAO,MAAM,oBAAoB,KAAc;AAAA,QACjD;AAAA,MACF;AAAA,IACF,GAAG,KAAK,QAAQ,gBAAgB;AAAA,EAClC;AAAA,EAEQ,kBAAkB,MAAiC;AACzD,UAAM,UAAU,KAAK,eAAe,KAAK,OAAO;AAChD,UAAM,cAAc,KAAK,mBAAmB,KAAK,OAAO;AAExD,WAAO;AAAA,MACL,IAAI,KAAK;AAAA,MACT,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,eAAe,KAAK,cAAc,IAAI,CAAA,MAAK,EAAE,MAAM;AAAA,MACnD,eAAe,KAAK,cAAc,IAAI,CAAA,MAAK,EAAE,MAAM;AAAA,MACnD;AAAA,MACA;AAAA,MACA,cAAc,KAAK,aAAa,YAAA;AAAA,MAChC,WAAU,oBAAI,KAAA,GAAO,YAAA;AAAA,IAAY;AAAA,EAErC;AAAA,EAEQ,eAAe,SAAiB,YAAY,KAAa;AAC/D,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAI,UAAU;AAEd,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,KAAA;AACrB,UAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,KAAK,QAAQ,WAAW,KAAK,KAAK,YAAY,OAAO;AACzF;AAAA,MACF;AACA,gBAAU;AACV;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,WAAW;AAC9B,gBAAU,QAAQ,MAAM,GAAG,YAAY,CAAC,IAAI;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAmB,SAAyB;AAClD,WAAO,WAAW,KAAK,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK,EAAE,UAAU,GAAG,EAAE;AAAA,EACxE;AAAA,EAEA,MAAc,cAAc,MAAiC;AAG3D,WAAO,MAAM,mBAAmB;AAAA,MAC9B,KAAK,QAAQ,KAAK,EAAE;AAAA,MACpB,WAAW,KAAK,QAAQ;AAAA,IAAA,CACzB;AAAA,EASH;AAAA,EAEA,MAAc,qBAA4C;AAGxD,WAAO,MAAM,wBAAwB;AAAA,MACnC,WAAW,KAAK,QAAQ;AAAA,IAAA,CACzB;AAED,WAAO,MAAM,KAAK,KAAK,YAAY,QAAQ;AAAA,EAC7C;AAAA,EAEA,MAAc,oBAAoB,OAAuC;AAEvE,UAAM,YAAY,MAAM,IAAI,CAAA,OAAM;AAAA,MAChC,IAAI,EAAE;AAAA,MACN,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,MACR,MAAM,EAAE;AAAA,IAAA,EACR;AAEF,WAAO,MAAM,mBAAmB;AAAA,MAC9B,OAAO,UAAU;AAAA,MACjB,WAAW,KAAK,QAAQ;AAAA,IAAA,CACzB;AAGD,UAAM,WAAqC,CAAA;AAC3C,eAAW,QAAQ,OAAO;AACxB,iBAAW,OAAO,KAAK,MAAM;AAC3B,YAAI,CAAC,SAAS,GAAG,GAAG;AAClB,mBAAS,GAAG,IAAI,CAAA;AAAA,QAClB;AACA,iBAAS,GAAG,EAAE,KAAK,KAAK,EAAE;AAAA,MAC5B;AAAA,IACF;AAEA,WAAO,MAAM,kBAAkB;AAAA,MAC7B,MAAM,OAAO,KAAK,QAAQ,EAAE;AAAA,MAC5B,WAAW,KAAK,QAAQ;AAAA,IAAA,CACzB;AAGD,UAAM,WAAW;AAAA,MACf,WAAU,oBAAI,KAAA,GAAO,YAAA;AAAA,MACrB,WAAW,MAAM;AAAA,MACjB,WAAW,KAAK,QAAQ;AAAA,IAAA;AAG1B,WAAO,MAAM,iBAAiB,QAAQ;AAAA,EACxC;AAAA,EAEA,MAAc,eACZ,MACA,QAC8B;AAC9B,UAAM,YAAY,KAAK,mBAAmB,KAAK,OAAO;AAEtD,QAAI,cAAc,OAAO,aAAa;AACpC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,YAAY,KAAK;AAAA,QACjB,SAAS,KAAK,QAAQ,iBAAiB,KAAK,UAAU;AAAA,MAAA;AAAA,MAExD,eAAe;AAAA,QACb,MAAM,OAAO;AAAA,QACb,YAAY,IAAI,KAAK,OAAO,YAAY;AAAA,MAAA;AAAA,IAC1C;AAAA,EAEJ;AAAA,EAEQ,qBACN,MACA,YACc;AACd,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,cAAc;AAAA,QACZ,MAAM,KAAK,mBAAmB,KAAK,OAAO;AAAA,QAC1C,YAAY,KAAK;AAAA,MAAA;AAAA,MAEnB,eAAe;AAAA,QACb,MAAM,WAAW;AAAA,QACjB,YAAY,IAAI,KAAK,WAAW,YAAY;AAAA,MAAA;AAAA,IAC9C;AAAA,EAEJ;AAAA,EAEA,MAAc,gBAAgB,UAA0C;AACtE,YAAQ,KAAK,QAAQ,kBAAA;AAAA,MACnB,KAAK;AACH,iBAAS,aAAa;AACtB,iBAAS,iCAAiB,KAAA;AAC1B,eAAO;AAAA,MAET,KAAK;AACH,iBAAS,aAAa;AACtB,iBAAS,iCAAiB,KAAA;AAC1B,eAAO;AAAA,MAET,KAAK;AACH,YAAI,SAAS,aAAa,aAAa,SAAS,cAAc,YAAY;AACxE,mBAAS,aAAa;AAAA,QACxB,OAAO;AACL,mBAAS,aAAa;AAAA,QACxB;AACA,iBAAS,iCAAiB,KAAA;AAC1B,eAAO;AAAA,MAET,KAAK;AAGH,YAAI,SAAS,aAAa,aAAa,SAAS,cAAc,YAAY;AACxE,mBAAS,aAAa;AAAA,QACxB,OAAO;AACL,mBAAS,aAAa;AAAA,QACxB;AACA,iBAAS,iCAAiB,KAAA;AAC1B,eAAO;AAAA,MAET,KAAK;AAEH,aAAK,UAAU,KAAK,QAAQ;AAC5B,eAAO;AAAA,MAET;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAAA,EAEQ,2BAAmC;AACzC,UAAM,mCAAmB,IAAA;AACzB,eAAW,CAAC,IAAI,IAAI,KAAK,KAAK,aAAa;AACzC,mBAAa,IAAI,IAAI,KAAK,WAAW;AAAA,IACvC;AAEA,QAAI,UAAU;AACd,UAAM,QAAQ,KAAK,IAAI,YAAA,KAAiB,CAAA;AAExC,eAAW,QAAQ,OAAO;AACxB,YAAM,aAAa,aAAa,IAAI,KAAK,EAAE;AAC3C,YAAM,cAAc,KAAK,mBAAmB,KAAK,OAAO;AAExD,UAAI,CAAC,cAAc,eAAe,aAAa;AAC7C;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,4BAAoC;AAG1C,WAAO;AAAA,EACT;AAAA,EAEQ,cAAiB,OAAY,WAA0B;AAC7D,UAAM,UAAiB,CAAA;AACvB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,WAAW;AAChD,cAAQ,KAAK,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,kBAAiC;AAG7C,WAAO,MAAM,sBAAsB;AAAA,EACrC;AAAA,EAEA,MAAc,kBAAiC;AAE7C,UAAM,KAAK,YAAY,KAAA;AACvB,WAAO,MAAM,oBAAoB;AAAA,EACnC;AACF;AAKO,SAAS,sBAAsB,SAA4C;AAChF,SAAO,IAAI,gBAAgB,OAAO;AACpC;"}
|
|
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/
|
|
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]}
|