Merge PR #2903: fix(mnemopi): make proactive linking configurable from host settings (@wolfiesch)
This commit is contained in:
@@ -98,7 +98,7 @@ note text
|
||||
|
||||
When you deliberately interrupt the agent (Esc, or a cancel from collab, ACP, RPC, the SDK, or an extension), the advisor stops auto-resuming it. An interrupting `concern`/`blocker` raised while the run is stopped is recorded as a visible advisor card instead of restarting the turn, and a concern already in flight when you interrupt is preserved the same way rather than driving a surprise resume. The advice re-enters context the next time you resume — a new message, the `.`/`c` continue shortcut, or a steer/follow-up. A normal yield is unaffected: the advisor can still steer and resume a run the agent ended on its own.
|
||||
|
||||
`advisor.immuneTurns` limits interruption frequency. After the advisor successfully delivers a `concern` or `blocker` through the steering channel, later concerns/blockers are routed as non-interrupting asides until the configured number of primary turns has completed. The default is `3`. `nit` notes are unchanged, and advice raised while user-interrupt auto-resume suppression is active is still preserved instead of restarting a stopped run.
|
||||
`advisor.immuneTurns` limits interruption frequency. After the advisor successfully delivers a `concern` or `blocker` through the steering channel, later concerns/blockers are routed as non-interrupting asides until the configured number of primary turns has completed. The default is `3`. `nit` notes are unchanged, and advice raised while user-interrupt auto-resume suppression is active is still preserved instead of restarting a stopped run.
|
||||
|
||||
## Bounded catch-up with `advisor.syncBacklog`
|
||||
|
||||
|
||||
@@ -268,6 +268,9 @@
|
||||
### Added
|
||||
|
||||
- Added a copy affordance for completed `/btw` answers so users can copy the visible side-answer text before branching or dismissing the panel.
|
||||
### Fixed
|
||||
|
||||
- Fixed mnemopi proactive linking being configurable only through the `MNEMOPI_PROACTIVE_LINKING` environment variable, unlike the sibling `mnemopi.polyphonicRecall` / `mnemopi.enhancedRecall` settings: added a `mnemopi.proactiveLinking` config.yml setting (off by default, `/settings` → Memory → Mnemopi) that ingests new memories into the episodic graph as they are stored, linking them to related entities and memories; `MNEMOPI_PROACTIVE_LINKING` still overrides the configured value when set ([#2440](https://github.com/can1357/oh-my-pi/issues/2440)).
|
||||
|
||||
## [16.0.6] - 2026-06-18
|
||||
|
||||
|
||||
@@ -2257,6 +2257,18 @@ export const SETTINGS_SCHEMA = {
|
||||
condition: "mnemopiActive",
|
||||
},
|
||||
},
|
||||
"mnemopi.proactiveLinking": {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
ui: {
|
||||
tab: "memory",
|
||||
group: "Mnemopi",
|
||||
label: "Mnemopi Proactive Linking",
|
||||
description:
|
||||
"Ingest new memories into the episodic graph as they are stored, linking them to related entities and memories",
|
||||
condition: "mnemopiActive",
|
||||
},
|
||||
},
|
||||
"mnemopi.noEmbeddings": {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
|
||||
@@ -26,6 +26,7 @@ export interface MnemopiBackendConfig {
|
||||
autoRetain: boolean;
|
||||
polyphonicRecall: boolean;
|
||||
enhancedRecall: boolean;
|
||||
proactiveLinking: boolean;
|
||||
retainEveryNTurns: number;
|
||||
recallLimit: number;
|
||||
recallContextTurns: number;
|
||||
@@ -71,6 +72,7 @@ export function loadMnemopiConfig(settings: Settings, agentDir: string): Mnemopi
|
||||
autoRetain: settings.get("mnemopi.autoRetain"),
|
||||
polyphonicRecall: settings.get("mnemopi.polyphonicRecall"),
|
||||
enhancedRecall: settings.get("mnemopi.enhancedRecall"),
|
||||
proactiveLinking: settings.get("mnemopi.proactiveLinking"),
|
||||
retainEveryNTurns: Math.max(1, Math.floor(settings.get("mnemopi.retainEveryNTurns"))),
|
||||
recallLimit: Math.max(1, Math.floor(settings.get("mnemopi.recallLimit"))),
|
||||
recallContextTurns: Math.max(1, Math.floor(settings.get("mnemopi.recallContextTurns"))),
|
||||
|
||||
@@ -450,7 +450,8 @@ export class MnemopiSessionState {
|
||||
// shared bank, then merging recall results while keeping writes project-local.
|
||||
function createScopedResources(config: MnemopiBackendConfig): MnemopiScopedResources {
|
||||
// Env vars (MNEMOPI_POLYPHONIC_RECALL / MNEMOPI_ENHANCED_RECALL) still override
|
||||
// these config-driven defaults inside the core gates.
|
||||
// these config-driven defaults inside the core gates. Proactive linking is
|
||||
// per-memory instance below so concurrent sessions cannot clobber each other.
|
||||
requireMnemopi().configureRecallFeatures({
|
||||
polyphonicRecall: config.polyphonicRecall,
|
||||
enhancedRecall: config.enhancedRecall,
|
||||
@@ -576,6 +577,7 @@ function createMemory(config: MnemopiBackendConfig, bank: string): Mnemopi {
|
||||
authorType: "agent",
|
||||
channelId: bank,
|
||||
...providerOptions,
|
||||
proactiveLinking: config.proactiveLinking,
|
||||
} as ConstructorParameters<typeof Mnemopi>[0]);
|
||||
}
|
||||
|
||||
|
||||
@@ -129,6 +129,7 @@ function makeMnemopiConfig(
|
||||
autoRetain: true,
|
||||
polyphonicRecall: false,
|
||||
enhancedRecall: false,
|
||||
proactiveLinking: false,
|
||||
retainEveryNTurns: 3,
|
||||
recallLimit: 10,
|
||||
recallContextTurns: 1,
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
- Fixed background fact extraction skipping runtime-configured remote LLM endpoints when `MNEMOPI_LLM_BASE_URL` was unset, so `remember(..., { extract: true })` now stores remote-distilled facts from `mnemopi.llm` config instead of falling back to regex heuristics. ([#3041](https://github.com/can1357/oh-my-pi/issues/3041))
|
||||
- Fixed local fastembed startup on macOS ARM64 by letting `fastembed@2.1.0` install its matching `onnxruntime-node@1.21.0` native runtime instead of forcing `1.26.0`, and by repairing missing tokenizer sidecars from the upstream Hugging Face model cache when a stale fastembed archive lacks them. ([#3054](https://github.com/can1357/oh-my-pi/issues/3054))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the proactive-linking write path ignoring host configuration: `proactiveLinkIfEnabled` read `MNEMOPI_PROACTIVE_LINKING` directly, so a host that enabled proactive linking through `configureRecallFeatures()` had no effect unless the environment variable was also set. `proactiveLinking` is now a `RecallFeatureFlags` option resolved through a `proactiveLinkingEnabled()` fallback, matching the existing polyphonic and enhanced recall flags, with the `MNEMOPI_PROACTIVE_LINKING` environment variable still taking precedence whenever it is set. ([#2440](https://github.com/can1357/oh-my-pi/issues/2440))
|
||||
|
||||
## [16.0.6] - 2026-06-18
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -268,27 +268,27 @@ export function autoMigrateEnabled(env: Env = process.env): boolean {
|
||||
return envString("MNEMOPI_AUTO_MIGRATE", "1", env) !== "0";
|
||||
}
|
||||
|
||||
export function proactiveLinkingEnabled(env: Env = process.env): boolean {
|
||||
return envString("MNEMOPI_PROACTIVE_LINKING", "0", env) === "1";
|
||||
}
|
||||
|
||||
export interface RecallFeatureFlags {
|
||||
polyphonicRecall?: boolean;
|
||||
enhancedRecall?: boolean;
|
||||
proactiveLinking?: boolean;
|
||||
}
|
||||
|
||||
let polyphonicRecallDefault = false;
|
||||
let enhancedRecallDefault = false;
|
||||
let proactiveLinkingDefault = false;
|
||||
|
||||
/**
|
||||
* Sets process-wide defaults for the env-gated recall features. Host configuration
|
||||
* (e.g. the coding-agent `mnemopi.polyphonicRecall` / `mnemopi.enhancedRecall`
|
||||
* settings) lands here; the `MNEMOPI_POLYPHONIC_RECALL` / `MNEMOPI_ENHANCED_RECALL`
|
||||
* environment variables still win whenever they are set.
|
||||
* (e.g. the coding-agent `mnemopi.polyphonicRecall` / `mnemopi.enhancedRecall` /
|
||||
* `mnemopi.proactiveLinking` settings) lands here; the `MNEMOPI_POLYPHONIC_RECALL` /
|
||||
* `MNEMOPI_ENHANCED_RECALL` / `MNEMOPI_PROACTIVE_LINKING` environment variables still
|
||||
* win whenever they are set.
|
||||
*/
|
||||
export function configureRecallFeatures(flags: RecallFeatureFlags): void {
|
||||
if (flags.polyphonicRecall !== undefined) polyphonicRecallDefault = flags.polyphonicRecall;
|
||||
if (flags.enhancedRecall !== undefined) enhancedRecallDefault = flags.enhancedRecall;
|
||||
if (flags.proactiveLinking !== undefined) proactiveLinkingDefault = flags.proactiveLinking;
|
||||
}
|
||||
|
||||
export function polyphonicRecallEnabled(env: Env = process.env): boolean {
|
||||
@@ -305,6 +305,11 @@ export function enhancedRecallEnabled(env: Env = process.env): boolean {
|
||||
return value === undefined ? enhancedRecallDefault : value === "1";
|
||||
}
|
||||
|
||||
export function proactiveLinkingEnabled(env: Env = process.env): boolean {
|
||||
const value = envOptionalString("MNEMOPI_PROACTIVE_LINKING", env);
|
||||
return value === undefined ? proactiveLinkingDefault : value === "1";
|
||||
}
|
||||
|
||||
export function llmEnabled(env: Env = process.env): boolean {
|
||||
return envBool("MNEMOPI_LLM_ENABLED", true, env);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Database } from "bun:sqlite";
|
||||
import { existsSync } from "node:fs";
|
||||
import { ftsWeight, importanceWeight, maxEpisodeChars, vectorWeight } from "../../config";
|
||||
import { ftsWeight, importanceWeight, maxEpisodeChars, proactiveLinkingEnabled, vectorWeight } from "../../config";
|
||||
import { closeQuietly, openDatabase } from "../../db";
|
||||
import { AnnotationStore } from "../annotations";
|
||||
import { EpisodicGraph } from "../episodic-graph";
|
||||
@@ -69,11 +69,13 @@ const DEFAULT_CONFIG: BeamConfig = {
|
||||
useCloud: false,
|
||||
localLlmEnabled: false,
|
||||
maxEpisodeChars: 100_000,
|
||||
proactiveLinking: false,
|
||||
};
|
||||
|
||||
function normalizeConfig(options: BeamMemoryOptions): BeamConfig {
|
||||
const configured = options.config ?? {};
|
||||
const useCloud = options.useCloud ?? configured.useCloud ?? DEFAULT_CONFIG.useCloud;
|
||||
const proactiveLinking = options.proactiveLinking ?? configured.proactiveLinking ?? proactiveLinkingEnabled({});
|
||||
return {
|
||||
workingMemoryLimit: configured.workingMemoryLimit ?? DEFAULT_CONFIG.workingMemoryLimit,
|
||||
workingMemoryTtlHours: configured.workingMemoryTtlHours ?? DEFAULT_CONFIG.workingMemoryTtlHours,
|
||||
@@ -84,6 +86,7 @@ function normalizeConfig(options: BeamMemoryOptions): BeamConfig {
|
||||
useCloud,
|
||||
localLlmEnabled: configured.localLlmEnabled ?? DEFAULT_CONFIG.localLlmEnabled,
|
||||
maxEpisodeChars: configured.maxEpisodeChars ?? maxEpisodeChars(),
|
||||
proactiveLinking,
|
||||
};
|
||||
}
|
||||
function autoMigrateAnnotations(db: Database, dbPath: string | undefined): void {
|
||||
|
||||
@@ -187,13 +187,18 @@ function addTemporalAnnotations(beam: BeamMemoryState, memoryId: string, timesta
|
||||
}
|
||||
}
|
||||
|
||||
function proactiveLinkingAllowed(beam: BeamMemoryState): boolean {
|
||||
const override = process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
return override === undefined ? beam.config.proactiveLinking === true : override === "1";
|
||||
}
|
||||
|
||||
function proactiveLinkIfEnabled(
|
||||
beam: BeamMemoryState,
|
||||
memoryId: string,
|
||||
content: string,
|
||||
extractEntities: boolean,
|
||||
): void {
|
||||
if (process.env.MNEMOPI_PROACTIVE_LINKING !== "1") return;
|
||||
if (!proactiveLinkingAllowed(beam)) return;
|
||||
try {
|
||||
const graph =
|
||||
beam.episodicGraph instanceof EpisodicGraph
|
||||
|
||||
@@ -54,6 +54,7 @@ export interface BeamConfig {
|
||||
useCloud: boolean;
|
||||
localLlmEnabled: boolean;
|
||||
maxEpisodeChars: number;
|
||||
proactiveLinking?: boolean;
|
||||
}
|
||||
|
||||
export interface BeamMemoryOptions {
|
||||
@@ -63,6 +64,7 @@ export interface BeamMemoryOptions {
|
||||
authorType?: string | null;
|
||||
channelId?: string | null;
|
||||
useCloud?: boolean;
|
||||
proactiveLinking?: boolean;
|
||||
eventEmitter?: (event: BeamEvent) => void;
|
||||
pluginManager?: BeamPluginManager | null;
|
||||
annotations?: AnnotationStoreLike | null;
|
||||
|
||||
@@ -43,6 +43,7 @@ export interface MnemopiOptions {
|
||||
readonly llmApiKey?: ApiKey;
|
||||
readonly llmModel?: string | Model<Api>;
|
||||
readonly llm?: false | MnemopiLlmRuntimeOptions | Model<Api> | MnemopiLlmCompletion;
|
||||
readonly proactiveLinking?: boolean;
|
||||
/** Escalate best-effort failure logs (embedding pipeline) from debug to warn. */
|
||||
readonly debug?: boolean;
|
||||
/**
|
||||
@@ -383,6 +384,7 @@ export class Mnemopi {
|
||||
authorId: this.authorId,
|
||||
authorType: this.authorType,
|
||||
channelId: this.channelId,
|
||||
proactiveLinking: options.proactiveLinking,
|
||||
});
|
||||
this.#ownsDb = options.db === undefined;
|
||||
if (options.db !== undefined) {
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import { afterEach, describe, expect, it } from "bun:test";
|
||||
import "./setup";
|
||||
import { configureRecallFeatures } from "@oh-my-pi/pi-mnemopi/config";
|
||||
import { BeamMemory } from "@oh-my-pi/pi-mnemopi/core/beam";
|
||||
import type { EpisodicGraph, RelatedMemory } from "@oh-my-pi/pi-mnemopi/core/episodic-graph";
|
||||
import { Mnemopi } from "@oh-my-pi/pi-mnemopi/core/memory";
|
||||
|
||||
const previousProactive = process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
|
||||
afterEach(() => {
|
||||
if (previousProactive === undefined) delete process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
else process.env.MNEMOPI_PROACTIVE_LINKING = previousProactive;
|
||||
configureRecallFeatures({ proactiveLinking: false });
|
||||
});
|
||||
|
||||
function linkedIds(edges: readonly RelatedMemory[]): Set<string> {
|
||||
@@ -39,6 +42,170 @@ describe("proactive memory linking", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("honors host configuration when the environment variable is unset", () => {
|
||||
delete process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
configureRecallFeatures({ proactiveLinking: true });
|
||||
const beam = new BeamMemory({ sessionId: "proactive-host-config", dbPath: ":memory:" });
|
||||
try {
|
||||
const first = beam.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const second = beam.remember("Alice configured the deployment pipeline for continuous integration", {
|
||||
importance: 0.8,
|
||||
});
|
||||
|
||||
const edges = graphOf(beam).findRelatedMemories(second, 1);
|
||||
expect(linkedIds(edges).has(first)).toBe(true);
|
||||
expect(edges.some(edge => edge.memoryId === first && edge.edgeType === "related_to")).toBe(true);
|
||||
} finally {
|
||||
beam.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps host configuration scoped to each BeamMemory instance", () => {
|
||||
delete process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
const enabled = new BeamMemory({
|
||||
sessionId: "proactive-instance-on",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: true,
|
||||
});
|
||||
configureRecallFeatures({ proactiveLinking: false });
|
||||
const disabled = new BeamMemory({
|
||||
sessionId: "proactive-instance-off",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: false,
|
||||
});
|
||||
try {
|
||||
const enabledFirst = enabled.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const enabledSecond = enabled.remember("Alice configured the deployment pipeline for continuous integration", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const disabledFirst = disabled.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const disabledSecond = disabled.remember(
|
||||
"Alice configured the deployment pipeline for continuous integration",
|
||||
{
|
||||
importance: 0.8,
|
||||
},
|
||||
);
|
||||
|
||||
expect(linkedIds(graphOf(enabled).findRelatedMemories(enabledSecond, 1)).has(enabledFirst)).toBe(true);
|
||||
expect(linkedIds(graphOf(disabled).findRelatedMemories(disabledSecond, 1)).has(disabledFirst)).toBe(false);
|
||||
} finally {
|
||||
enabled.close();
|
||||
disabled.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("keeps host configuration scoped to each Mnemopi instance", () => {
|
||||
delete process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
const enabled = new Mnemopi({
|
||||
sessionId: "proactive-mnemopi-on",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: true,
|
||||
});
|
||||
configureRecallFeatures({ proactiveLinking: false });
|
||||
const disabled = new Mnemopi({
|
||||
sessionId: "proactive-mnemopi-off",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: false,
|
||||
});
|
||||
try {
|
||||
const enabledFirst = enabled.remember("Database indexing improves query performance significantly", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const enabledSecond = enabled.remember("Database indexing optimizes query performance and efficiency", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const disabledFirst = disabled.remember("Database indexing improves query performance significantly", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const disabledSecond = disabled.remember("Database indexing optimizes query performance and efficiency", {
|
||||
importance: 0.8,
|
||||
});
|
||||
|
||||
expect(linkedIds(graphOf(enabled.beam).findRelatedMemories(enabledSecond, 1)).has(enabledFirst)).toBe(true);
|
||||
expect(linkedIds(graphOf(disabled.beam).findRelatedMemories(disabledSecond, 1)).has(disabledFirst)).toBe(
|
||||
false,
|
||||
);
|
||||
} finally {
|
||||
enabled.close();
|
||||
disabled.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("lets the environment variable override instance configuration", () => {
|
||||
process.env.MNEMOPI_PROACTIVE_LINKING = "0";
|
||||
const disabledByEnv = new BeamMemory({
|
||||
sessionId: "proactive-env-off",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: true,
|
||||
});
|
||||
try {
|
||||
const disabledFirst = disabledByEnv.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const disabledSecond = disabledByEnv.remember(
|
||||
"Alice configured the deployment pipeline for continuous integration",
|
||||
{
|
||||
importance: 0.8,
|
||||
},
|
||||
);
|
||||
process.env.MNEMOPI_PROACTIVE_LINKING = "1";
|
||||
const enabledByEnv = new BeamMemory({
|
||||
sessionId: "proactive-env-on",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: false,
|
||||
});
|
||||
try {
|
||||
const enabledFirst = enabledByEnv.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const enabledSecond = enabledByEnv.remember(
|
||||
"Alice configured the deployment pipeline for continuous integration",
|
||||
{
|
||||
importance: 0.8,
|
||||
},
|
||||
);
|
||||
|
||||
expect(linkedIds(graphOf(enabledByEnv).findRelatedMemories(enabledSecond, 1)).has(enabledFirst)).toBe(true);
|
||||
} finally {
|
||||
enabledByEnv.close();
|
||||
}
|
||||
|
||||
expect(linkedIds(graphOf(disabledByEnv).findRelatedMemories(disabledSecond, 1)).has(disabledFirst)).toBe(
|
||||
false,
|
||||
);
|
||||
} finally {
|
||||
disabledByEnv.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("does not snapshot a construction-time environment override into instance defaults", () => {
|
||||
process.env.MNEMOPI_PROACTIVE_LINKING = "1";
|
||||
const beam = new BeamMemory({
|
||||
sessionId: "proactive-env-snapshot",
|
||||
dbPath: ":memory:",
|
||||
proactiveLinking: false,
|
||||
});
|
||||
delete process.env.MNEMOPI_PROACTIVE_LINKING;
|
||||
try {
|
||||
const first = beam.remember("Alice set up the CI/CD pipeline for backend deployment", {
|
||||
importance: 0.8,
|
||||
});
|
||||
const second = beam.remember("Alice configured the deployment pipeline for continuous integration", {
|
||||
importance: 0.8,
|
||||
});
|
||||
|
||||
expect(linkedIds(graphOf(beam).findRelatedMemories(second, 1)).has(first)).toBe(false);
|
||||
} finally {
|
||||
beam.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("does not create recall-similarity edges for unrelated content", () => {
|
||||
process.env.MNEMOPI_PROACTIVE_LINKING = "1";
|
||||
const beam = new BeamMemory({ sessionId: "proactive-unrelated", dbPath: ":memory:" });
|
||||
|
||||
@@ -1,39 +1,48 @@
|
||||
import { afterEach, describe, expect, it } from "bun:test";
|
||||
import { configureRecallFeatures, enhancedRecallEnabled, polyphonicRecallEnabled } from "@oh-my-pi/pi-mnemopi/config";
|
||||
import {
|
||||
configureRecallFeatures,
|
||||
enhancedRecallEnabled,
|
||||
polyphonicRecallEnabled,
|
||||
proactiveLinkingEnabled,
|
||||
} from "@oh-my-pi/pi-mnemopi/config";
|
||||
import { polyphonicRecallIsEnabled } from "@oh-my-pi/pi-mnemopi/core/polyphonic-recall";
|
||||
import { isEnhancedRecallEnabled, isQueryCacheEnabled } from "@oh-my-pi/pi-mnemopi/core/query-cache";
|
||||
|
||||
afterEach(() => {
|
||||
configureRecallFeatures({ polyphonicRecall: false, enhancedRecall: false });
|
||||
configureRecallFeatures({ polyphonicRecall: false, enhancedRecall: false, proactiveLinking: false });
|
||||
});
|
||||
|
||||
describe("configureRecallFeatures", () => {
|
||||
it("keeps both recall gates off by default", () => {
|
||||
it("keeps all recall gates off by default", () => {
|
||||
expect(polyphonicRecallEnabled({})).toBe(false);
|
||||
expect(enhancedRecallEnabled({})).toBe(false);
|
||||
expect(proactiveLinkingEnabled({})).toBe(false);
|
||||
expect(isEnhancedRecallEnabled({})).toBe(false);
|
||||
expect(isQueryCacheEnabled(true, {})).toBe(false);
|
||||
});
|
||||
|
||||
it("enables the gates from host configuration when the env vars are unset", () => {
|
||||
configureRecallFeatures({ polyphonicRecall: true, enhancedRecall: true });
|
||||
configureRecallFeatures({ polyphonicRecall: true, enhancedRecall: true, proactiveLinking: true });
|
||||
expect(polyphonicRecallEnabled({})).toBe(true);
|
||||
expect(polyphonicRecallIsEnabled({})).toBe(true);
|
||||
expect(enhancedRecallEnabled({})).toBe(true);
|
||||
expect(proactiveLinkingEnabled({})).toBe(true);
|
||||
expect(isEnhancedRecallEnabled({})).toBe(true);
|
||||
expect(isQueryCacheEnabled(true, {})).toBe(true);
|
||||
expect(isQueryCacheEnabled(false, {})).toBe(false);
|
||||
});
|
||||
|
||||
it("lets the env vars override the configured value in both directions", () => {
|
||||
configureRecallFeatures({ polyphonicRecall: true, enhancedRecall: true });
|
||||
configureRecallFeatures({ polyphonicRecall: true, enhancedRecall: true, proactiveLinking: true });
|
||||
expect(polyphonicRecallEnabled({ MNEMOPI_POLYPHONIC_RECALL: "0" })).toBe(false);
|
||||
expect(enhancedRecallEnabled({ MNEMOPI_ENHANCED_RECALL: "0" })).toBe(false);
|
||||
expect(proactiveLinkingEnabled({ MNEMOPI_PROACTIVE_LINKING: "0" })).toBe(false);
|
||||
expect(isQueryCacheEnabled(true, { MNEMOPI_ENHANCED_RECALL: "0" })).toBe(false);
|
||||
|
||||
configureRecallFeatures({ polyphonicRecall: false, enhancedRecall: false });
|
||||
configureRecallFeatures({ polyphonicRecall: false, enhancedRecall: false, proactiveLinking: false });
|
||||
expect(polyphonicRecallEnabled({ MNEMOPI_POLYPHONIC_RECALL: "1" })).toBe(true);
|
||||
expect(enhancedRecallEnabled({ MNEMOPI_ENHANCED_RECALL: "1" })).toBe(true);
|
||||
expect(proactiveLinkingEnabled({ MNEMOPI_PROACTIVE_LINKING: "1" })).toBe(true);
|
||||
expect(isQueryCacheEnabled(true, { MNEMOPI_ENHANCED_RECALL: "1" })).toBe(true);
|
||||
});
|
||||
|
||||
@@ -41,8 +50,14 @@ describe("configureRecallFeatures", () => {
|
||||
configureRecallFeatures({ polyphonicRecall: true });
|
||||
expect(polyphonicRecallEnabled({})).toBe(true);
|
||||
expect(enhancedRecallEnabled({})).toBe(false);
|
||||
expect(proactiveLinkingEnabled({})).toBe(false);
|
||||
configureRecallFeatures({ enhancedRecall: true });
|
||||
expect(polyphonicRecallEnabled({})).toBe(true);
|
||||
expect(enhancedRecallEnabled({})).toBe(true);
|
||||
expect(proactiveLinkingEnabled({})).toBe(false);
|
||||
configureRecallFeatures({ proactiveLinking: true });
|
||||
expect(polyphonicRecallEnabled({})).toBe(true);
|
||||
expect(enhancedRecallEnabled({})).toBe(true);
|
||||
expect(proactiveLinkingEnabled({})).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user