mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-09 06:12:15 +00:00
Add memory rollout feature flags and docs
This commit is contained in:
1 parent
ab680f8b7b
commit
d1586228be
10 files changed
+274
-27
No files matched your search
@@ -8,6 +8,7 @@ import {
|
||||
listMemories,
|
||||
memoryStats,
|
||||
pinMemory,
|
||||
runPruneCycle,
|
||||
triggerPruneDryRun,
|
||||
unpinMemory,
|
||||
} from '../src/services/memory/index.js';
|
||||
@@ -104,3 +105,31 @@ test('memoryStats reports counts/rates and retrieval telemetry remains redaction
|
||||
assert.ok(stats.indexSizeEstimateBytes >= 0);
|
||||
assert.ok(Number.isFinite(stats.ingestThroughputPerMinute));
|
||||
});
|
||||
|
||||
|
||||
test('runPruneCycle respects prune feature-flag modes', async () => {
|
||||
const repository = {
|
||||
async listPruneCandidates() {
|
||||
return [
|
||||
{ id: 'old-1', agent_id: 'agent-z', type: 'event', pinned: false, last_seen: 1, merged_into: null },
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
const dryRunResult = await runPruneCycle({
|
||||
repository,
|
||||
env: { TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' },
|
||||
retentionMs: 1000,
|
||||
});
|
||||
assert.equal(dryRunResult.mode, 'dry-run');
|
||||
assert.equal(dryRunResult.pruned.length, 0);
|
||||
assert.equal(dryRunResult.candidates.length, 1);
|
||||
|
||||
const offResult = await runPruneCycle({
|
||||
repository,
|
||||
env: { TORCH_MEMORY_PRUNE_ENABLED: 'false' },
|
||||
retentionMs: 1000,
|
||||
});
|
||||
assert.equal(offResult.mode, 'off');
|
||||
assert.equal(offResult.pruned.length, 0);
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
import {
|
||||
getMemoryPruneMode,
|
||||
isMemoryEnabled,
|
||||
isMemoryIngestEnabled,
|
||||
isMemoryPruneEnabled,
|
||||
} from '../src/services/memory/feature-flags.js';
|
||||
|
||||
test('memory feature flags parse defaults and canary allow-lists', () => {
|
||||
assert.equal(isMemoryEnabled({}), true);
|
||||
assert.equal(isMemoryEnabled({ TORCH_MEMORY_ENABLED: 'false' }), false);
|
||||
|
||||
assert.equal(isMemoryIngestEnabled('agent-a', {}), true);
|
||||
assert.equal(isMemoryIngestEnabled('agent-a', { TORCH_MEMORY_INGEST_ENABLED: 'false' }), false);
|
||||
assert.equal(isMemoryIngestEnabled('agent-a', { TORCH_MEMORY_INGEST_ENABLED: 'agent-a,agent-b' }), true);
|
||||
assert.equal(isMemoryIngestEnabled('agent-c', { TORCH_MEMORY_INGEST_ENABLED: 'agent-a,agent-b' }), false);
|
||||
});
|
||||
|
||||
test('memory prune flag supports off, dry-run, and active modes', () => {
|
||||
assert.equal(getMemoryPruneMode({}), 'active');
|
||||
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'false' }), 'off');
|
||||
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' }), 'dry-run');
|
||||
assert.equal(getMemoryPruneMode({ TORCH_MEMORY_PRUNE_ENABLED: 'true' }), 'active');
|
||||
assert.equal(isMemoryPruneEnabled({ TORCH_MEMORY_PRUNE_ENABLED: 'dry-run' }), false);
|
||||
assert.equal(isMemoryPruneEnabled({ TORCH_MEMORY_PRUNE_ENABLED: 'true' }), true);
|
||||
});
|
||||
@@ -143,6 +143,13 @@ test('isMemoryRetrievalEnabled supports global toggle and agent canary list', ()
|
||||
isMemoryRetrievalEnabled('agent-c', { TORCH_MEMORY_RETRIEVAL_ENABLED: 'agent-a,agent-b' }),
|
||||
false,
|
||||
);
|
||||
assert.equal(
|
||||
isMemoryRetrievalEnabled('agent-a', {
|
||||
TORCH_MEMORY_ENABLED: 'false',
|
||||
TORCH_MEMORY_RETRIEVAL_ENABLED: 'true',
|
||||
}),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test('renderPromptWithMemoryContext injects bounded memory block before base prompt', async () => {
|
||||
|
||||
@@ -90,3 +90,37 @@ test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including
|
||||
assert.equal(byJob.pruningCycle[0].payload.status, 'success');
|
||||
assert.equal(byJob.deepMergeArchivalMaintenance[0].payload.status, 'success');
|
||||
});
|
||||
|
||||
|
||||
test('startMemoryMaintenanceScheduler skips jobs when feature flags disable memory', async () => {
|
||||
const metrics = [];
|
||||
const called = [];
|
||||
|
||||
const scheduler = startMemoryMaintenanceScheduler({
|
||||
runImmediately: true,
|
||||
env: { TORCH_MEMORY_ENABLED: 'false' },
|
||||
emitMetric(name, payload) {
|
||||
metrics.push({ name, payload });
|
||||
},
|
||||
handlers: {
|
||||
async ingestRecentRuntimeEvents() {
|
||||
called.push('ingest');
|
||||
},
|
||||
async consolidateObservations() {
|
||||
called.push('consolidate');
|
||||
},
|
||||
async pruningCycle() {
|
||||
called.push('prune');
|
||||
},
|
||||
async deepMergeArchivalMaintenance() {
|
||||
called.push('merge');
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await wait(10);
|
||||
scheduler.stop();
|
||||
|
||||
assert.deepEqual(called, []);
|
||||
assert.ok(metrics.some((entry) => entry.payload.status === 'skipped_flag_disabled'));
|
||||
});
|
||||
Reference in new issue
Block a user