Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@
# AI_HISTORY_MAX_TURNS=10 # Older turns dropped (1–100)
# AI_HISTORY_MAX_TURN_CHARS=4096 # Per-turn char cap (100–100000)
# AI_HISTORY_MAX_TOTAL_CHARS=32768 # Total cap across all turns (100–1000000)
# Feature flag: when true, the inventory query path matches bins server-side
# and the LLM only formats the answer + relevance strings. Default false until
# validated.
# AI_DETERMINISTIC_MATCH=false
# Inventory query: when true (default), uses LLM planner + SQL executor.
# When false, falls back to legacy LLM-as-matcher. Disable for providers
# without structured-output support (some Ollama models).
# AI_DETERMINISTIC_MATCH=true

# ── Backups ───────────────────────────────────
# BACKUP_ENABLED=false
Expand Down
2 changes: 1 addition & 1 deletion server/src/__tests__/aiStreamDeterministicFlag.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ beforeEach(() => { app = createApp(); });
afterEach(() => { delete process.env.AI_DETERMINISTIC_MATCH; });

describe('AI_DETERMINISTIC_MATCH flag', () => {
it('legacy path is used when the flag is unset (no AI mock — just verifies the route still accepts the request)', async () => {
it('planner path is used by default (no AI mock — just verifies the route still accepts the request)', async () => {
const { token } = await createTestUser(app);
const loc = await createTestLocation(app, token);
await createTestBin(app, token, loc.id, { name: 'Battery Bin' });
Expand Down
10 changes: 5 additions & 5 deletions server/src/lib/__tests__/configDeterministicMatch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ describe('config.aiDeterministicMatch', () => {
await initialize();
});

it('defaults to false when env var unset', async () => {
it('defaults to true when env var unset', async () => {
delete process.env.AI_DETERMINISTIC_MATCH;
const { config } = await import('../config.js');
expect(config.aiDeterministicMatch).toBe(false);
expect(config.aiDeterministicMatch).toBe(true);
});

it('is true when AI_DETERMINISTIC_MATCH=true', async () => {
process.env.AI_DETERMINISTIC_MATCH = 'true';
it('is false when AI_DETERMINISTIC_MATCH=false', async () => {
process.env.AI_DETERMINISTIC_MATCH = 'false';
const { config } = await import('../config.js');
expect(config.aiDeterministicMatch).toBe(true);
expect(config.aiDeterministicMatch).toBe(false);
delete process.env.AI_DETERMINISTIC_MATCH;
});
});
8 changes: 4 additions & 4 deletions server/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,10 @@ export const config = Object.freeze({
aiHistoryMaxTurns: clamp(parseInt(process.env.AI_HISTORY_MAX_TURNS || '10', 10), 1, 100, 10),
aiHistoryMaxTurnChars: clamp(parseInt(process.env.AI_HISTORY_MAX_TURN_CHARS || '4096', 10), 100, 100000, 4096),
aiHistoryMaxTotalChars: clamp(parseInt(process.env.AI_HISTORY_MAX_TOTAL_CHARS || '32768', 10), 100, 1_000_000, 32768),
// Feature flag: when true, the inventory query path uses deterministic
// server-side bin matching and reduces the LLM to a formatter. Default off
// — flip on per-environment to validate before retiring the legacy path.
aiDeterministicMatch: parseBool(process.env.AI_DETERMINISTIC_MATCH, false),
// Inventory query: when true (default), uses LLM planner + SQL executor.
// When false, falls back to legacy LLM-as-matcher. Disable for providers
// without structured-output support (some Ollama models).
aiDeterministicMatch: parseBool(process.env.AI_DETERMINISTIC_MATCH, true),

// Backup
backupEnabled: parseBool(process.env.BACKUP_ENABLED, false),
Expand Down
Loading