agentic-qe 1.8.3 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
- package/.claude/skills/cicd-pipeline-qe-orchestrator/README.md +2 -2
- package/.claude/skills/cicd-pipeline-qe-orchestrator/SKILL.md +6 -6
- package/CHANGELOG.md +595 -0
- package/README.md +117 -16
- package/config/constitution.schema.json +423 -0
- package/config/otel-collector.yaml +234 -0
- package/dist/App.d.ts +5 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/App.js +15 -0
- package/dist/App.js.map +1 -0
- package/dist/cli/commands/constitution.d.ts +34 -0
- package/dist/cli/commands/constitution.d.ts.map +1 -0
- package/dist/cli/commands/constitution.js +679 -0
- package/dist/cli/commands/constitution.js.map +1 -0
- package/dist/cli/commands/init-claude-md-template.js +3 -3
- package/dist/cli/commands/init.d.ts +8 -75
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +22 -2292
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/telemetry.d.ts +36 -0
- package/dist/cli/commands/telemetry.d.ts.map +1 -0
- package/dist/cli/commands/telemetry.js +364 -0
- package/dist/cli/commands/telemetry.js.map +1 -0
- package/dist/cli/index.js +66 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/agents.d.ts +22 -0
- package/dist/cli/init/agents.d.ts.map +1 -0
- package/dist/cli/init/agents.js +522 -0
- package/dist/cli/init/agents.js.map +1 -0
- package/dist/cli/init/bash-wrapper.d.ts +14 -0
- package/dist/cli/init/bash-wrapper.d.ts.map +1 -0
- package/dist/cli/init/bash-wrapper.js +47 -0
- package/dist/cli/init/bash-wrapper.js.map +1 -0
- package/dist/cli/init/claude-config.d.ts +24 -0
- package/dist/cli/init/claude-config.d.ts.map +1 -0
- package/dist/cli/init/claude-config.js +275 -0
- package/dist/cli/init/claude-config.js.map +1 -0
- package/dist/cli/init/claude-md.d.ts +19 -0
- package/dist/cli/init/claude-md.d.ts.map +1 -0
- package/dist/cli/init/claude-md.js +153 -0
- package/dist/cli/init/claude-md.js.map +1 -0
- package/dist/cli/init/commands.d.ts +6 -0
- package/dist/cli/init/commands.d.ts.map +1 -0
- package/dist/cli/init/commands.js +83 -0
- package/dist/cli/init/commands.js.map +1 -0
- package/dist/cli/init/database-init.d.ts +15 -0
- package/dist/cli/init/database-init.d.ts.map +1 -0
- package/dist/cli/init/database-init.js +203 -0
- package/dist/cli/init/database-init.js.map +1 -0
- package/dist/cli/init/directory-structure.d.ts +14 -0
- package/dist/cli/init/directory-structure.d.ts.map +1 -0
- package/dist/cli/init/directory-structure.js +107 -0
- package/dist/cli/init/directory-structure.js.map +1 -0
- package/dist/cli/init/documentation.d.ts +14 -0
- package/dist/cli/init/documentation.d.ts.map +1 -0
- package/dist/cli/init/documentation.js +195 -0
- package/dist/cli/init/documentation.js.map +1 -0
- package/dist/cli/init/fleet-config.d.ts +34 -0
- package/dist/cli/init/fleet-config.d.ts.map +1 -0
- package/dist/cli/init/fleet-config.js +269 -0
- package/dist/cli/init/fleet-config.js.map +1 -0
- package/dist/cli/init/helpers.d.ts +6 -0
- package/dist/cli/init/helpers.d.ts.map +1 -0
- package/dist/cli/init/helpers.js +94 -0
- package/dist/cli/init/helpers.js.map +1 -0
- package/dist/cli/init/index.d.ts +32 -0
- package/dist/cli/init/index.d.ts.map +1 -0
- package/dist/cli/init/index.js +294 -0
- package/dist/cli/init/index.js.map +1 -0
- package/dist/cli/init/skills.d.ts +6 -0
- package/dist/cli/init/skills.d.ts.map +1 -0
- package/dist/cli/init/skills.js +138 -0
- package/dist/cli/init/skills.js.map +1 -0
- package/dist/cli/init/utils/file-utils.d.ts +74 -0
- package/dist/cli/init/utils/file-utils.d.ts.map +1 -0
- package/dist/cli/init/utils/file-utils.js +187 -0
- package/dist/cli/init/utils/file-utils.js.map +1 -0
- package/dist/cli/init/utils/index.d.ts +18 -0
- package/dist/cli/init/utils/index.d.ts.map +1 -0
- package/dist/cli/init/utils/index.js +48 -0
- package/dist/cli/init/utils/index.js.map +1 -0
- package/dist/cli/init/utils/log-utils.d.ts +47 -0
- package/dist/cli/init/utils/log-utils.d.ts.map +1 -0
- package/dist/cli/init/utils/log-utils.js +68 -0
- package/dist/cli/init/utils/log-utils.js.map +1 -0
- package/dist/cli/init/utils/path-utils.d.ts +91 -0
- package/dist/cli/init/utils/path-utils.d.ts.map +1 -0
- package/dist/cli/init/utils/path-utils.js +208 -0
- package/dist/cli/init/utils/path-utils.js.map +1 -0
- package/dist/cli/init/utils/validation-utils.d.ts +44 -0
- package/dist/cli/init/utils/validation-utils.d.ts.map +1 -0
- package/dist/cli/init/utils/validation-utils.js +68 -0
- package/dist/cli/init/utils/validation-utils.js.map +1 -0
- package/dist/cli/init/utils.d.ts +183 -0
- package/dist/cli/init/utils.d.ts.map +1 -0
- package/dist/cli/init/utils.js +354 -0
- package/dist/cli/init/utils.js.map +1 -0
- package/dist/components/Dashboard/Dashboard.d.ts +4 -0
- package/dist/components/Dashboard/Dashboard.d.ts.map +1 -0
- package/dist/components/Dashboard/Dashboard.js +148 -0
- package/dist/components/Dashboard/Dashboard.js.map +1 -0
- package/dist/components/Dashboard/DashboardHeader.d.ts +4 -0
- package/dist/components/Dashboard/DashboardHeader.d.ts.map +1 -0
- package/dist/components/Dashboard/DashboardHeader.js +138 -0
- package/dist/components/Dashboard/DashboardHeader.js.map +1 -0
- package/dist/constitution/evaluators/ast-evaluator.d.ts +42 -0
- package/dist/constitution/evaluators/ast-evaluator.d.ts.map +1 -0
- package/dist/constitution/evaluators/ast-evaluator.js +303 -0
- package/dist/constitution/evaluators/ast-evaluator.js.map +1 -0
- package/dist/constitution/evaluators/base.d.ts +144 -0
- package/dist/constitution/evaluators/base.d.ts.map +1 -0
- package/dist/constitution/evaluators/base.js +144 -0
- package/dist/constitution/evaluators/base.js.map +1 -0
- package/dist/constitution/evaluators/index.d.ts +19 -0
- package/dist/constitution/evaluators/index.d.ts.map +1 -0
- package/dist/constitution/evaluators/index.js +56 -0
- package/dist/constitution/evaluators/index.js.map +1 -0
- package/dist/constitution/evaluators/metric-evaluator.d.ts +59 -0
- package/dist/constitution/evaluators/metric-evaluator.d.ts.map +1 -0
- package/dist/constitution/evaluators/metric-evaluator.js +195 -0
- package/dist/constitution/evaluators/metric-evaluator.js.map +1 -0
- package/dist/constitution/evaluators/pattern-evaluator.d.ts +66 -0
- package/dist/constitution/evaluators/pattern-evaluator.d.ts.map +1 -0
- package/dist/constitution/evaluators/pattern-evaluator.js +221 -0
- package/dist/constitution/evaluators/pattern-evaluator.js.map +1 -0
- package/dist/constitution/evaluators/semantic-evaluator.d.ts +68 -0
- package/dist/constitution/evaluators/semantic-evaluator.d.ts.map +1 -0
- package/dist/constitution/evaluators/semantic-evaluator.js +250 -0
- package/dist/constitution/evaluators/semantic-evaluator.js.map +1 -0
- package/dist/constitution/index.d.ts +105 -0
- package/dist/constitution/index.d.ts.map +1 -0
- package/dist/constitution/index.js +207 -0
- package/dist/constitution/index.js.map +1 -0
- package/dist/constitution/loader.d.ts +141 -0
- package/dist/constitution/loader.d.ts.map +1 -0
- package/dist/constitution/loader.js +515 -0
- package/dist/constitution/loader.js.map +1 -0
- package/dist/constitution/schema.d.ts +409 -0
- package/dist/constitution/schema.d.ts.map +1 -0
- package/dist/constitution/schema.js +71 -0
- package/dist/constitution/schema.js.map +1 -0
- package/dist/contexts/DashboardContext.d.ts +41 -0
- package/dist/contexts/DashboardContext.d.ts.map +1 -0
- package/dist/contexts/DashboardContext.js +187 -0
- package/dist/contexts/DashboardContext.js.map +1 -0
- package/dist/core/memory/MemoryManagerFactory.d.ts +77 -0
- package/dist/core/memory/MemoryManagerFactory.d.ts.map +1 -0
- package/dist/core/memory/MemoryManagerFactory.js +270 -0
- package/dist/core/memory/MemoryManagerFactory.js.map +1 -0
- package/dist/core/memory/SwarmMemoryManager.d.ts +58 -0
- package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
- package/dist/core/memory/SwarmMemoryManager.js +375 -131
- package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
- package/dist/core/memory/index.d.ts +1 -0
- package/dist/core/memory/index.d.ts.map +1 -1
- package/dist/core/memory/index.js +12 -1
- package/dist/core/memory/index.js.map +1 -1
- package/dist/hooks/useKeyboardShortcuts.d.ts +12 -0
- package/dist/hooks/useKeyboardShortcuts.d.ts.map +1 -0
- package/dist/hooks/useKeyboardShortcuts.js +69 -0
- package/dist/hooks/useKeyboardShortcuts.js.map +1 -0
- package/dist/mcp/handlers/memory/memory-backup.js +6 -6
- package/dist/mcp/handlers/memory/memory-backup.js.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.d.ts.map +1 -1
- package/dist/mcp/handlers/phase2/Phase2Tools.js +4 -2
- package/dist/mcp/handlers/phase2/Phase2Tools.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +4 -38
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/services/AgentRegistry.d.ts.map +1 -1
- package/dist/mcp/services/AgentRegistry.js +4 -4
- package/dist/mcp/services/AgentRegistry.js.map +1 -1
- package/dist/persistence/event-store.d.ts +162 -0
- package/dist/persistence/event-store.d.ts.map +1 -0
- package/dist/persistence/event-store.js +315 -0
- package/dist/persistence/event-store.js.map +1 -0
- package/dist/persistence/index.d.ts +145 -0
- package/dist/persistence/index.d.ts.map +1 -0
- package/dist/persistence/index.js +227 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/persistence/metrics-aggregator.d.ts +187 -0
- package/dist/persistence/metrics-aggregator.d.ts.map +1 -0
- package/dist/persistence/metrics-aggregator.js +495 -0
- package/dist/persistence/metrics-aggregator.js.map +1 -0
- package/dist/persistence/reasoning-store.d.ts +178 -0
- package/dist/persistence/reasoning-store.d.ts.map +1 -0
- package/dist/persistence/reasoning-store.js +440 -0
- package/dist/persistence/reasoning-store.js.map +1 -0
- package/dist/persistence/schema.d.ts +181 -0
- package/dist/persistence/schema.d.ts.map +1 -0
- package/dist/persistence/schema.js +186 -0
- package/dist/persistence/schema.js.map +1 -0
- package/dist/telemetry/bootstrap.d.ts +67 -0
- package/dist/telemetry/bootstrap.d.ts.map +1 -0
- package/dist/telemetry/bootstrap.js +320 -0
- package/dist/telemetry/bootstrap.js.map +1 -0
- package/dist/telemetry/index.d.ts +16 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +84 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/instrumentation/agent.d.ts +158 -0
- package/dist/telemetry/instrumentation/agent.d.ts.map +1 -0
- package/dist/telemetry/instrumentation/agent.js +372 -0
- package/dist/telemetry/instrumentation/agent.js.map +1 -0
- package/dist/telemetry/instrumentation/index.d.ts +24 -0
- package/dist/telemetry/instrumentation/index.d.ts.map +1 -0
- package/dist/telemetry/instrumentation/index.js +54 -0
- package/dist/telemetry/instrumentation/index.js.map +1 -0
- package/dist/telemetry/instrumentation/memory.d.ts +313 -0
- package/dist/telemetry/instrumentation/memory.d.ts.map +1 -0
- package/dist/telemetry/instrumentation/memory.js +552 -0
- package/dist/telemetry/instrumentation/memory.js.map +1 -0
- package/dist/telemetry/instrumentation/task.d.ts +146 -0
- package/dist/telemetry/instrumentation/task.d.ts.map +1 -0
- package/dist/telemetry/instrumentation/task.js +305 -0
- package/dist/telemetry/instrumentation/task.js.map +1 -0
- package/dist/telemetry/metrics/agent-metrics.d.ts +109 -0
- package/dist/telemetry/metrics/agent-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/agent-metrics.js +213 -0
- package/dist/telemetry/metrics/agent-metrics.js.map +1 -0
- package/dist/telemetry/metrics/collectors/cost.d.ts +246 -0
- package/dist/telemetry/metrics/collectors/cost.d.ts.map +1 -0
- package/dist/telemetry/metrics/collectors/cost.js +526 -0
- package/dist/telemetry/metrics/collectors/cost.js.map +1 -0
- package/dist/telemetry/metrics/collectors/pricing-config.d.ts +87 -0
- package/dist/telemetry/metrics/collectors/pricing-config.d.ts.map +1 -0
- package/dist/telemetry/metrics/collectors/pricing-config.js +207 -0
- package/dist/telemetry/metrics/collectors/pricing-config.js.map +1 -0
- package/dist/telemetry/metrics/index.d.ts +54 -0
- package/dist/telemetry/metrics/index.d.ts.map +1 -0
- package/dist/telemetry/metrics/index.js +116 -0
- package/dist/telemetry/metrics/index.js.map +1 -0
- package/dist/telemetry/metrics/quality-metrics.d.ts +171 -0
- package/dist/telemetry/metrics/quality-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/quality-metrics.js +259 -0
- package/dist/telemetry/metrics/quality-metrics.js.map +1 -0
- package/dist/telemetry/metrics/system-metrics.d.ts +129 -0
- package/dist/telemetry/metrics/system-metrics.d.ts.map +1 -0
- package/dist/telemetry/metrics/system-metrics.js +380 -0
- package/dist/telemetry/metrics/system-metrics.js.map +1 -0
- package/dist/telemetry/types.d.ts +195 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +90 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/visualization/api/RestEndpoints.d.ts +136 -0
- package/dist/visualization/api/RestEndpoints.d.ts.map +1 -0
- package/dist/visualization/api/RestEndpoints.js +428 -0
- package/dist/visualization/api/RestEndpoints.js.map +1 -0
- package/dist/visualization/api/WebSocketServer.d.ts +165 -0
- package/dist/visualization/api/WebSocketServer.d.ts.map +1 -0
- package/dist/visualization/api/WebSocketServer.js +518 -0
- package/dist/visualization/api/WebSocketServer.js.map +1 -0
- package/dist/visualization/core/DataTransformer.d.ts +89 -0
- package/dist/visualization/core/DataTransformer.d.ts.map +1 -0
- package/dist/visualization/core/DataTransformer.js +478 -0
- package/dist/visualization/core/DataTransformer.js.map +1 -0
- package/dist/visualization/index.d.ts +92 -0
- package/dist/visualization/index.d.ts.map +1 -0
- package/dist/visualization/index.js +121 -0
- package/dist/visualization/index.js.map +1 -0
- package/dist/visualization/types.d.ts +148 -0
- package/dist/visualization/types.d.ts.map +1 -0
- package/dist/visualization/types.js +7 -0
- package/dist/visualization/types.js.map +1 -0
- package/dist/voting/consensus.d.ts +87 -0
- package/dist/voting/consensus.d.ts.map +1 -0
- package/dist/voting/consensus.js +568 -0
- package/dist/voting/consensus.js.map +1 -0
- package/dist/voting/index.d.ts +12 -0
- package/dist/voting/index.d.ts.map +1 -0
- package/dist/voting/index.js +36 -0
- package/dist/voting/index.js.map +1 -0
- package/dist/voting/orchestrator.d.ts +65 -0
- package/dist/voting/orchestrator.d.ts.map +1 -0
- package/dist/voting/orchestrator.js +306 -0
- package/dist/voting/orchestrator.js.map +1 -0
- package/dist/voting/panel-assembly.d.ts +54 -0
- package/dist/voting/panel-assembly.d.ts.map +1 -0
- package/dist/voting/panel-assembly.js +192 -0
- package/dist/voting/panel-assembly.js.map +1 -0
- package/dist/voting/protocol.d.ts +119 -0
- package/dist/voting/protocol.d.ts.map +1 -0
- package/dist/voting/protocol.js +18 -0
- package/dist/voting/protocol.js.map +1 -0
- package/dist/voting/types.d.ts +125 -0
- package/dist/voting/types.d.ts.map +1 -0
- package/dist/voting/types.js +7 -0
- package/dist/voting/types.js.map +1 -0
- package/package.json +43 -2
|
@@ -46,6 +46,9 @@ Object.defineProperty(exports, "AccessLevel", { enumerable: true, get: function
|
|
|
46
46
|
Object.defineProperty(exports, "Permission", { enumerable: true, get: function () { return AccessControl_1.Permission; } });
|
|
47
47
|
Object.defineProperty(exports, "AccessControlError", { enumerable: true, get: function () { return AccessControl_1.AccessControlError; } });
|
|
48
48
|
const AgentDBManager_1 = require("./AgentDBManager");
|
|
49
|
+
const PatternCache_1 = require("./PatternCache");
|
|
50
|
+
const memory_1 = require("../../telemetry/instrumentation/memory");
|
|
51
|
+
const types_1 = require("../../types");
|
|
49
52
|
/**
|
|
50
53
|
* SwarmMemoryManager - Manages persistent memory for agent swarm coordination
|
|
51
54
|
*
|
|
@@ -84,6 +87,12 @@ class SwarmMemoryManager {
|
|
|
84
87
|
this.accessControl = new AccessControl_1.AccessControl();
|
|
85
88
|
this.aclCache = new Map();
|
|
86
89
|
this.lastModifiedTimestamps = new Map();
|
|
90
|
+
// Initialize pattern cache with LRU eviction (100 entries, 60s TTL)
|
|
91
|
+
this.patternCache = new PatternCache_1.PatternCache({
|
|
92
|
+
maxSize: 100,
|
|
93
|
+
ttl: 60000,
|
|
94
|
+
enableStats: true
|
|
95
|
+
});
|
|
87
96
|
}
|
|
88
97
|
run(sql, params = []) {
|
|
89
98
|
if (!this.db) {
|
|
@@ -192,8 +201,18 @@ class SwarmMemoryManager {
|
|
|
192
201
|
metadata TEXT,
|
|
193
202
|
ttl INTEGER NOT NULL DEFAULT ${this.TTL_POLICY.patterns},
|
|
194
203
|
expires_at INTEGER,
|
|
195
|
-
created_at INTEGER NOT NULL
|
|
204
|
+
created_at INTEGER NOT NULL,
|
|
205
|
+
agent_id TEXT
|
|
196
206
|
)
|
|
207
|
+
`);
|
|
208
|
+
// Create indexes for O(log n) pattern queries (Issue #57)
|
|
209
|
+
await this.run(`
|
|
210
|
+
CREATE INDEX IF NOT EXISTS idx_patterns_agent_confidence
|
|
211
|
+
ON patterns(agent_id, confidence DESC)
|
|
212
|
+
`);
|
|
213
|
+
await this.run(`
|
|
214
|
+
CREATE INDEX IF NOT EXISTS idx_patterns_agent
|
|
215
|
+
ON patterns(agent_id)
|
|
197
216
|
`);
|
|
198
217
|
// Table 6: Consensus State (TTL: 7 days)
|
|
199
218
|
await this.run(`
|
|
@@ -384,6 +403,16 @@ class SwarmMemoryManager {
|
|
|
384
403
|
await this.run(`CREATE INDEX IF NOT EXISTS idx_learning_metrics_agent ON learning_metrics(agent_id)`);
|
|
385
404
|
this.initialized = true;
|
|
386
405
|
}
|
|
406
|
+
/**
|
|
407
|
+
* Store a key-value pair in memory with OpenTelemetry instrumentation
|
|
408
|
+
*
|
|
409
|
+
* Automatically instruments the memory store operation with distributed tracing.
|
|
410
|
+
* Records namespace, key, value size, TTL, and operation performance metrics.
|
|
411
|
+
*
|
|
412
|
+
* @param key - Memory key
|
|
413
|
+
* @param value - Value to store (will be JSON serialized)
|
|
414
|
+
* @param options - Store options including partition, TTL, access control
|
|
415
|
+
*/
|
|
387
416
|
async store(key, value, options = {}) {
|
|
388
417
|
// Auto-initialize if not initialized
|
|
389
418
|
if (!this.initialized) {
|
|
@@ -395,44 +424,73 @@ class SwarmMemoryManager {
|
|
|
395
424
|
const partition = options.partition || 'default';
|
|
396
425
|
const owner = options.owner || 'system';
|
|
397
426
|
const accessLevel = options.accessLevel || AccessControl_1.AccessLevel.PRIVATE;
|
|
398
|
-
const
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (
|
|
416
|
-
|
|
427
|
+
const valueJson = JSON.stringify(value);
|
|
428
|
+
const valueSize = valueJson.length;
|
|
429
|
+
// Create instrumentation span
|
|
430
|
+
const { span, context: spanContext } = memory_1.memorySpanManager.startStoreSpan({
|
|
431
|
+
agentId: { id: owner, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
|
|
432
|
+
namespace: partition,
|
|
433
|
+
key,
|
|
434
|
+
valueSize,
|
|
435
|
+
ttl: options.ttl,
|
|
436
|
+
});
|
|
437
|
+
const startTime = Date.now();
|
|
438
|
+
try {
|
|
439
|
+
const createdAt = Date.now();
|
|
440
|
+
const expiresAt = options.ttl ? createdAt + (options.ttl * 1000) : null;
|
|
441
|
+
const metadata = options.metadata ? JSON.stringify(options.metadata) : null;
|
|
442
|
+
// Check write permission if updating existing entry
|
|
443
|
+
const existing = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
444
|
+
if (existing && options.owner) {
|
|
445
|
+
// Verify write permission
|
|
446
|
+
const permCheck = this.accessControl.checkPermission({
|
|
447
|
+
agentId: options.owner,
|
|
448
|
+
resourceOwner: existing.owner,
|
|
449
|
+
accessLevel: existing.access_level,
|
|
450
|
+
permission: AccessControl_1.Permission.WRITE,
|
|
451
|
+
teamId: options.teamId,
|
|
452
|
+
resourceTeamId: existing.team_id,
|
|
453
|
+
swarmId: options.swarmId,
|
|
454
|
+
resourceSwarmId: existing.swarm_id
|
|
455
|
+
});
|
|
456
|
+
if (!permCheck.allowed) {
|
|
457
|
+
throw new AccessControl_1.AccessControlError(`Write denied: ${permCheck.reason}`);
|
|
458
|
+
}
|
|
417
459
|
}
|
|
460
|
+
await this.run(`INSERT OR REPLACE INTO memory_entries
|
|
461
|
+
(key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id)
|
|
462
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
463
|
+
key,
|
|
464
|
+
partition,
|
|
465
|
+
valueJson,
|
|
466
|
+
metadata,
|
|
467
|
+
createdAt,
|
|
468
|
+
expiresAt,
|
|
469
|
+
owner,
|
|
470
|
+
accessLevel,
|
|
471
|
+
options.teamId || null,
|
|
472
|
+
options.swarmId || null
|
|
473
|
+
]);
|
|
474
|
+
// Track modification for QUIC sync
|
|
475
|
+
const entryKey = `${partition}:${key}`;
|
|
476
|
+
this.lastModifiedTimestamps.set(entryKey, createdAt);
|
|
477
|
+
// Complete span successfully
|
|
478
|
+
const durationMs = Date.now() - startTime;
|
|
479
|
+
memory_1.memorySpanManager.completeStoreSpan(span, {
|
|
480
|
+
success: true,
|
|
481
|
+
durationMs,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
// Complete span with error
|
|
486
|
+
const durationMs = Date.now() - startTime;
|
|
487
|
+
memory_1.memorySpanManager.completeStoreSpan(span, {
|
|
488
|
+
success: false,
|
|
489
|
+
durationMs,
|
|
490
|
+
error: error,
|
|
491
|
+
});
|
|
492
|
+
throw error;
|
|
418
493
|
}
|
|
419
|
-
await this.run(`INSERT OR REPLACE INTO memory_entries
|
|
420
|
-
(key, partition, value, metadata, created_at, expires_at, owner, access_level, team_id, swarm_id)
|
|
421
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
422
|
-
key,
|
|
423
|
-
partition,
|
|
424
|
-
JSON.stringify(value),
|
|
425
|
-
metadata,
|
|
426
|
-
createdAt,
|
|
427
|
-
expiresAt,
|
|
428
|
-
owner,
|
|
429
|
-
accessLevel,
|
|
430
|
-
options.teamId || null,
|
|
431
|
-
options.swarmId || null
|
|
432
|
-
]);
|
|
433
|
-
// Track modification for QUIC sync
|
|
434
|
-
const entryKey = `${partition}:${key}`;
|
|
435
|
-
this.lastModifiedTimestamps.set(entryKey, createdAt);
|
|
436
494
|
}
|
|
437
495
|
/**
|
|
438
496
|
* Alias for store() method to maintain compatibility with MemoryStore interface
|
|
@@ -456,6 +514,16 @@ class SwarmMemoryManager {
|
|
|
456
514
|
}
|
|
457
515
|
return this.retrieve(key, options);
|
|
458
516
|
}
|
|
517
|
+
/**
|
|
518
|
+
* Retrieve a value from memory with OpenTelemetry instrumentation
|
|
519
|
+
*
|
|
520
|
+
* Automatically instruments the memory retrieve operation with distributed tracing.
|
|
521
|
+
* Records namespace, key, whether the value was found, value size, and performance metrics.
|
|
522
|
+
*
|
|
523
|
+
* @param key - Memory key
|
|
524
|
+
* @param options - Retrieve options including partition, agentId for access control
|
|
525
|
+
* @returns Retrieved value or null if not found
|
|
526
|
+
*/
|
|
459
527
|
async retrieve(key, options = {}) {
|
|
460
528
|
// Auto-initialize if not initialized
|
|
461
529
|
if (!this.initialized) {
|
|
@@ -465,55 +533,35 @@ class SwarmMemoryManager {
|
|
|
465
533
|
throw new Error('Memory manager not initialized. Call initialize() first.');
|
|
466
534
|
}
|
|
467
535
|
const partition = options.partition || 'default';
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
resourceOwner: row.owner,
|
|
485
|
-
accessLevel: row.access_level,
|
|
486
|
-
permission: AccessControl_1.Permission.READ,
|
|
487
|
-
teamId: options.teamId,
|
|
488
|
-
resourceTeamId: row.team_id,
|
|
489
|
-
swarmId: options.swarmId,
|
|
490
|
-
resourceSwarmId: row.swarm_id,
|
|
491
|
-
isSystemAgent: options.isSystemAgent
|
|
492
|
-
});
|
|
493
|
-
if (!permCheck.allowed) {
|
|
494
|
-
throw new AccessControl_1.AccessControlError(`Read denied: ${permCheck.reason}`);
|
|
536
|
+
const agentId = options.agentId || 'system';
|
|
537
|
+
// Create instrumentation span
|
|
538
|
+
const { span, context: spanContext } = memory_1.memorySpanManager.startRetrieveSpan({
|
|
539
|
+
agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
|
|
540
|
+
namespace: partition,
|
|
541
|
+
key,
|
|
542
|
+
});
|
|
543
|
+
const startTime = Date.now();
|
|
544
|
+
try {
|
|
545
|
+
const now = Date.now();
|
|
546
|
+
let query = `SELECT value, owner, access_level, team_id, swarm_id
|
|
547
|
+
FROM memory_entries WHERE key = ? AND partition = ?`;
|
|
548
|
+
const params = [key, partition];
|
|
549
|
+
if (!options.includeExpired) {
|
|
550
|
+
query += ` AND (expires_at IS NULL OR expires_at > ?)`;
|
|
551
|
+
params.push(now);
|
|
495
552
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const params = [partition, pattern];
|
|
509
|
-
if (!options.includeExpired) {
|
|
510
|
-
query += ` AND (expires_at IS NULL OR expires_at > ?)`;
|
|
511
|
-
params.push(now);
|
|
512
|
-
}
|
|
513
|
-
const rows = await this.queryAll(query, params);
|
|
514
|
-
// Filter by access control if agentId provided
|
|
515
|
-
const filteredRows = options.agentId
|
|
516
|
-
? rows.filter((row) => {
|
|
553
|
+
const row = await this.queryOne(query, params);
|
|
554
|
+
if (!row) {
|
|
555
|
+
// Complete span - not found
|
|
556
|
+
const durationMs = Date.now() - startTime;
|
|
557
|
+
memory_1.memorySpanManager.completeRetrieveSpan(span, {
|
|
558
|
+
found: false,
|
|
559
|
+
durationMs,
|
|
560
|
+
});
|
|
561
|
+
return null;
|
|
562
|
+
}
|
|
563
|
+
// Check read permission if agentId provided
|
|
564
|
+
if (options.agentId) {
|
|
517
565
|
const permCheck = this.accessControl.checkPermission({
|
|
518
566
|
agentId: options.agentId,
|
|
519
567
|
resourceOwner: row.owner,
|
|
@@ -525,50 +573,178 @@ class SwarmMemoryManager {
|
|
|
525
573
|
resourceSwarmId: row.swarm_id,
|
|
526
574
|
isSystemAgent: options.isSystemAgent
|
|
527
575
|
});
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
576
|
+
if (!permCheck.allowed) {
|
|
577
|
+
throw new AccessControl_1.AccessControlError(`Read denied: ${permCheck.reason}`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
const valueSize = row.value.length;
|
|
581
|
+
const parsedValue = JSON.parse(row.value);
|
|
582
|
+
// Complete span successfully
|
|
583
|
+
const durationMs = Date.now() - startTime;
|
|
584
|
+
memory_1.memorySpanManager.completeRetrieveSpan(span, {
|
|
585
|
+
found: true,
|
|
586
|
+
valueSize,
|
|
587
|
+
durationMs,
|
|
588
|
+
});
|
|
589
|
+
return parsedValue;
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
// Complete span with error
|
|
593
|
+
const durationMs = Date.now() - startTime;
|
|
594
|
+
memory_1.memorySpanManager.completeRetrieveSpan(span, {
|
|
595
|
+
found: false,
|
|
596
|
+
durationMs,
|
|
597
|
+
error: error,
|
|
598
|
+
});
|
|
599
|
+
throw error;
|
|
600
|
+
}
|
|
542
601
|
}
|
|
602
|
+
/**
|
|
603
|
+
* Query/search memory entries by pattern with OpenTelemetry instrumentation
|
|
604
|
+
*
|
|
605
|
+
* Automatically instruments the memory search operation with distributed tracing.
|
|
606
|
+
* Records namespace, search pattern, result count, and performance metrics.
|
|
607
|
+
*
|
|
608
|
+
* @param pattern - SQL LIKE pattern for key matching
|
|
609
|
+
* @param options - Retrieve options including partition, agentId for access control
|
|
610
|
+
* @returns Array of matching memory entries
|
|
611
|
+
*/
|
|
612
|
+
async query(pattern, options = {}) {
|
|
613
|
+
if (!this.db) {
|
|
614
|
+
throw new Error('Memory manager not initialized');
|
|
615
|
+
}
|
|
616
|
+
const partition = options.partition || 'default';
|
|
617
|
+
const agentId = options.agentId || 'system';
|
|
618
|
+
// Create instrumentation span
|
|
619
|
+
const { span, context: spanContext } = memory_1.memorySpanManager.startSearchSpan({
|
|
620
|
+
agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
|
|
621
|
+
namespace: partition,
|
|
622
|
+
pattern,
|
|
623
|
+
});
|
|
624
|
+
const startTime = Date.now();
|
|
625
|
+
try {
|
|
626
|
+
const now = Date.now();
|
|
627
|
+
let query = `SELECT key, value, partition, created_at, expires_at, owner, access_level, team_id, swarm_id
|
|
628
|
+
FROM memory_entries
|
|
629
|
+
WHERE partition = ? AND key LIKE ?`;
|
|
630
|
+
const params = [partition, pattern];
|
|
631
|
+
if (!options.includeExpired) {
|
|
632
|
+
query += ` AND (expires_at IS NULL OR expires_at > ?)`;
|
|
633
|
+
params.push(now);
|
|
634
|
+
}
|
|
635
|
+
const rows = await this.queryAll(query, params);
|
|
636
|
+
// Filter by access control if agentId provided
|
|
637
|
+
const filteredRows = options.agentId
|
|
638
|
+
? rows.filter((row) => {
|
|
639
|
+
const permCheck = this.accessControl.checkPermission({
|
|
640
|
+
agentId: options.agentId,
|
|
641
|
+
resourceOwner: row.owner,
|
|
642
|
+
accessLevel: row.access_level,
|
|
643
|
+
permission: AccessControl_1.Permission.READ,
|
|
644
|
+
teamId: options.teamId,
|
|
645
|
+
resourceTeamId: row.team_id,
|
|
646
|
+
swarmId: options.swarmId,
|
|
647
|
+
resourceSwarmId: row.swarm_id,
|
|
648
|
+
isSystemAgent: options.isSystemAgent
|
|
649
|
+
});
|
|
650
|
+
return permCheck.allowed;
|
|
651
|
+
})
|
|
652
|
+
: rows;
|
|
653
|
+
const results = filteredRows.map((row) => ({
|
|
654
|
+
key: row.key,
|
|
655
|
+
value: JSON.parse(row.value),
|
|
656
|
+
partition: row.partition,
|
|
657
|
+
createdAt: row.created_at,
|
|
658
|
+
expiresAt: row.expires_at,
|
|
659
|
+
owner: row.owner,
|
|
660
|
+
accessLevel: row.access_level,
|
|
661
|
+
teamId: row.team_id,
|
|
662
|
+
swarmId: row.swarm_id
|
|
663
|
+
}));
|
|
664
|
+
// Complete span successfully
|
|
665
|
+
const durationMs = Date.now() - startTime;
|
|
666
|
+
memory_1.memorySpanManager.completeSearchSpan(span, {
|
|
667
|
+
resultCount: results.length,
|
|
668
|
+
durationMs,
|
|
669
|
+
});
|
|
670
|
+
return results;
|
|
671
|
+
}
|
|
672
|
+
catch (error) {
|
|
673
|
+
// Complete span with error
|
|
674
|
+
const durationMs = Date.now() - startTime;
|
|
675
|
+
memory_1.memorySpanManager.completeSearchSpan(span, {
|
|
676
|
+
resultCount: 0,
|
|
677
|
+
durationMs,
|
|
678
|
+
error: error,
|
|
679
|
+
});
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Delete a key from memory with OpenTelemetry instrumentation
|
|
685
|
+
*
|
|
686
|
+
* Automatically instruments the memory delete operation with distributed tracing.
|
|
687
|
+
* Records namespace, key, and operation performance metrics.
|
|
688
|
+
*
|
|
689
|
+
* @param key - Memory key to delete
|
|
690
|
+
* @param partition - Memory partition (namespace)
|
|
691
|
+
* @param options - Delete options including agentId for access control
|
|
692
|
+
*/
|
|
543
693
|
async delete(key, partition = 'default', options = {}) {
|
|
544
694
|
if (!this.db) {
|
|
545
695
|
throw new Error('Memory manager not initialized');
|
|
546
696
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
697
|
+
const agentId = options.agentId || 'system';
|
|
698
|
+
// Create instrumentation span
|
|
699
|
+
const { span, context: spanContext } = memory_1.memorySpanManager.startDeleteSpan({
|
|
700
|
+
agentId: { id: agentId, type: types_1.QEAgentType.FLEET_COMMANDER, created: new Date() },
|
|
701
|
+
namespace: partition,
|
|
702
|
+
key,
|
|
703
|
+
});
|
|
704
|
+
const startTime = Date.now();
|
|
705
|
+
try {
|
|
706
|
+
// Check delete permission if agentId provided
|
|
707
|
+
if (options.agentId) {
|
|
708
|
+
const row = await this.queryOne(`SELECT owner, access_level, team_id, swarm_id FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
709
|
+
if (row) {
|
|
710
|
+
const permCheck = this.accessControl.checkPermission({
|
|
711
|
+
agentId: options.agentId,
|
|
712
|
+
resourceOwner: row.owner,
|
|
713
|
+
accessLevel: row.access_level,
|
|
714
|
+
permission: AccessControl_1.Permission.DELETE,
|
|
715
|
+
teamId: options.teamId,
|
|
716
|
+
resourceTeamId: row.team_id,
|
|
717
|
+
swarmId: options.swarmId,
|
|
718
|
+
resourceSwarmId: row.swarm_id,
|
|
719
|
+
isSystemAgent: options.isSystemAgent
|
|
720
|
+
});
|
|
721
|
+
if (!permCheck.allowed) {
|
|
722
|
+
throw new AccessControl_1.AccessControlError(`Delete denied: ${permCheck.reason}`);
|
|
723
|
+
}
|
|
564
724
|
}
|
|
565
725
|
}
|
|
726
|
+
await this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
727
|
+
// Clean up ACL if exists
|
|
728
|
+
const resourceId = `${partition}:${key}`;
|
|
729
|
+
await this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]);
|
|
730
|
+
this.aclCache.delete(resourceId);
|
|
731
|
+
// Complete span successfully
|
|
732
|
+
const durationMs = Date.now() - startTime;
|
|
733
|
+
memory_1.memorySpanManager.completeDeleteSpan(span, {
|
|
734
|
+
success: true,
|
|
735
|
+
durationMs,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
catch (error) {
|
|
739
|
+
// Complete span with error
|
|
740
|
+
const durationMs = Date.now() - startTime;
|
|
741
|
+
memory_1.memorySpanManager.completeDeleteSpan(span, {
|
|
742
|
+
success: false,
|
|
743
|
+
durationMs,
|
|
744
|
+
error: error,
|
|
745
|
+
});
|
|
746
|
+
throw error;
|
|
566
747
|
}
|
|
567
|
-
await this.run(`DELETE FROM memory_entries WHERE key = ? AND partition = ?`, [key, partition]);
|
|
568
|
-
// Clean up ACL if exists
|
|
569
|
-
const resourceId = `${partition}:${key}`;
|
|
570
|
-
await this.run(`DELETE FROM memory_acl WHERE resource_id = ?`, [resourceId]);
|
|
571
|
-
this.aclCache.delete(resourceId);
|
|
572
748
|
}
|
|
573
749
|
async clear(partition = 'default') {
|
|
574
750
|
if (!this.db) {
|
|
@@ -797,8 +973,10 @@ class SwarmMemoryManager {
|
|
|
797
973
|
const now = Date.now();
|
|
798
974
|
const ttl = pattern.ttl !== undefined ? pattern.ttl : this.TTL_POLICY.patterns;
|
|
799
975
|
const expiresAt = ttl > 0 ? now + (ttl * 1000) : null;
|
|
800
|
-
|
|
801
|
-
|
|
976
|
+
// Extract agent_id from metadata for indexed lookups (O(log n) vs O(n))
|
|
977
|
+
const agentId = pattern.metadata?.agent_id || pattern.metadata?.agentId || null;
|
|
978
|
+
await this.run(`INSERT OR REPLACE INTO patterns (id, pattern, confidence, usage_count, metadata, ttl, expires_at, created_at, agent_id)
|
|
979
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
802
980
|
id,
|
|
803
981
|
pattern.pattern,
|
|
804
982
|
pattern.confidence,
|
|
@@ -806,8 +984,11 @@ class SwarmMemoryManager {
|
|
|
806
984
|
pattern.metadata ? JSON.stringify(pattern.metadata) : null,
|
|
807
985
|
ttl,
|
|
808
986
|
expiresAt,
|
|
809
|
-
now
|
|
987
|
+
now,
|
|
988
|
+
agentId
|
|
810
989
|
]);
|
|
990
|
+
// Invalidate cache for this agent to ensure consistency
|
|
991
|
+
this.invalidatePatternCacheForAgent(agentId);
|
|
811
992
|
return id;
|
|
812
993
|
}
|
|
813
994
|
async getPattern(patternName) {
|
|
@@ -835,9 +1016,31 @@ class SwarmMemoryManager {
|
|
|
835
1016
|
if (!this.db) {
|
|
836
1017
|
throw new Error('Memory manager not initialized');
|
|
837
1018
|
}
|
|
838
|
-
|
|
1019
|
+
// Get the agent_id before updating to invalidate correct cache entries
|
|
1020
|
+
const pattern = this.queryOne(`SELECT agent_id, metadata FROM patterns WHERE pattern = ?`, [patternName]);
|
|
1021
|
+
this.run(`UPDATE patterns
|
|
839
1022
|
SET usage_count = usage_count + 1
|
|
840
1023
|
WHERE pattern = ?`, [patternName]);
|
|
1024
|
+
// Invalidate cache for affected agent
|
|
1025
|
+
if (pattern) {
|
|
1026
|
+
const agentId = pattern.agent_id ||
|
|
1027
|
+
(pattern.metadata ? JSON.parse(pattern.metadata).agent_id || JSON.parse(pattern.metadata).agentId : null);
|
|
1028
|
+
this.invalidatePatternCacheForAgent(agentId);
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Invalidate pattern cache for a specific agent
|
|
1033
|
+
* Call this after any pattern mutation to maintain cache coherence
|
|
1034
|
+
*/
|
|
1035
|
+
invalidatePatternCacheForAgent(agentId) {
|
|
1036
|
+
if (agentId) {
|
|
1037
|
+
this.patternCache.invalidate(agentId);
|
|
1038
|
+
}
|
|
1039
|
+
else {
|
|
1040
|
+
// Nuclear option for NULL agent_id - clear entire cache
|
|
1041
|
+
// This is expensive but ensures correctness for pre-migration data
|
|
1042
|
+
this.patternCache.clear();
|
|
1043
|
+
}
|
|
841
1044
|
}
|
|
842
1045
|
async queryPatternsByConfidence(threshold) {
|
|
843
1046
|
if (!this.db) {
|
|
@@ -865,23 +1068,49 @@ class SwarmMemoryManager {
|
|
|
865
1068
|
* @param minConfidence Minimum confidence threshold (default: 0)
|
|
866
1069
|
* @returns Array of patterns belonging to the agent
|
|
867
1070
|
*/
|
|
1071
|
+
/**
|
|
1072
|
+
* Escape special LIKE pattern characters to prevent SQL injection
|
|
1073
|
+
*/
|
|
1074
|
+
escapeLikePattern(value) {
|
|
1075
|
+
return value.replace(/[%_\\]/g, '\\$&');
|
|
1076
|
+
}
|
|
868
1077
|
async queryPatternsByAgent(agentId, minConfidence = 0) {
|
|
869
1078
|
if (!this.db) {
|
|
870
1079
|
throw new Error('Memory manager not initialized');
|
|
871
1080
|
}
|
|
1081
|
+
// Check cache first (O(1) lookup)
|
|
1082
|
+
const cacheKey = PatternCache_1.PatternCache.generateKey(agentId, minConfidence);
|
|
1083
|
+
const cached = this.patternCache.get(cacheKey);
|
|
1084
|
+
if (cached) {
|
|
1085
|
+
return cached;
|
|
1086
|
+
}
|
|
872
1087
|
const now = Date.now();
|
|
873
|
-
const
|
|
1088
|
+
const escapedAgentId = this.escapeLikePattern(agentId);
|
|
1089
|
+
// Split into two queries to ensure index usage on the fast path
|
|
1090
|
+
// Query 1: O(log n) - Use index for agent_id column (post-migration data)
|
|
1091
|
+
const indexedRows = this.queryAll(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at
|
|
874
1092
|
FROM patterns
|
|
875
|
-
WHERE
|
|
1093
|
+
WHERE agent_id = ?
|
|
1094
|
+
AND confidence >= ?
|
|
876
1095
|
AND (expires_at IS NULL OR expires_at > ?)
|
|
877
|
-
|
|
1096
|
+
ORDER BY confidence DESC`, [agentId, minConfidence, now]);
|
|
1097
|
+
// Query 2: O(n) - Fallback LIKE scan for pre-migration data (agent_id IS NULL)
|
|
1098
|
+
const nullRows = this.queryAll(`SELECT id, pattern, confidence, usage_count, metadata, ttl, created_at
|
|
1099
|
+
FROM patterns
|
|
1100
|
+
WHERE agent_id IS NULL
|
|
1101
|
+
AND confidence >= ?
|
|
1102
|
+
AND (expires_at IS NULL OR expires_at > ?)
|
|
1103
|
+
AND (metadata LIKE ? ESCAPE '\\' OR metadata LIKE ? ESCAPE '\\')
|
|
878
1104
|
ORDER BY confidence DESC`, [
|
|
879
1105
|
minConfidence,
|
|
880
1106
|
now,
|
|
881
|
-
`%"agent_id":"${
|
|
882
|
-
`%"agentId":"${
|
|
1107
|
+
`%"agent_id":"${escapedAgentId}"%`,
|
|
1108
|
+
`%"agentId":"${escapedAgentId}"%`
|
|
883
1109
|
]);
|
|
884
|
-
|
|
1110
|
+
// Combine results and sort by confidence (descending)
|
|
1111
|
+
const allRows = [...indexedRows, ...nullRows];
|
|
1112
|
+
allRows.sort((a, b) => b.confidence - a.confidence);
|
|
1113
|
+
const patterns = allRows.map((row) => ({
|
|
885
1114
|
id: row.id,
|
|
886
1115
|
pattern: row.pattern,
|
|
887
1116
|
confidence: row.confidence,
|
|
@@ -890,6 +1119,21 @@ class SwarmMemoryManager {
|
|
|
890
1119
|
ttl: row.ttl,
|
|
891
1120
|
createdAt: row.created_at
|
|
892
1121
|
}));
|
|
1122
|
+
// Cache results for subsequent lookups
|
|
1123
|
+
this.patternCache.set(cacheKey, patterns);
|
|
1124
|
+
return patterns;
|
|
1125
|
+
}
|
|
1126
|
+
/**
|
|
1127
|
+
* Get pattern cache statistics for monitoring
|
|
1128
|
+
*/
|
|
1129
|
+
getPatternCacheStats() {
|
|
1130
|
+
return this.patternCache.getStats();
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Clear pattern cache (useful after bulk updates)
|
|
1134
|
+
*/
|
|
1135
|
+
clearPatternCache() {
|
|
1136
|
+
this.patternCache.clear();
|
|
893
1137
|
}
|
|
894
1138
|
// ============================================================================
|
|
895
1139
|
// Table 6: Consensus State (TTL: 7 days)
|