fix(models): make tier-change listener registration non-destructive
This commit is contained in:
@@ -14,6 +14,7 @@ Scope: Production-risk-first audit of bugs, code improvements, and feature oppor
|
||||
- ✅ F-012 addressed: synthetic repeated-tool nudge no longer emits invalid `tool_result.tool_use_id`; nudge is injected as plain user text guidance.
|
||||
- ✅ F-009 addressed: gateway now enforces per-connection WebSocket ingress rate limits with deterministic throttle errors and close-on-repeated-violation behavior.
|
||||
- ✅ F-008 addressed: WhatsApp Chromium launch is now sandboxed by default; no-sandbox mode is behind explicit `whatsapp.no_sandbox: true` opt-in.
|
||||
- ✅ F-014 addressed: `ModelRouter.setOnTierChange` now preserves existing listeners instead of replacing them, removing destructive listener-setter behavior.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
|
||||
@@ -2512,6 +2512,18 @@
|
||||
"docs/plans/analysis/2026-02-16-codebase-audit-report.md"
|
||||
],
|
||||
"test_status": "pnpm test:run src/channels/whatsapp/adapter.test.ts src/config/schema.test.ts + pnpm typecheck passing"
|
||||
},
|
||||
"audit-followup-modelrouter-listeners": {
|
||||
"status": "completed",
|
||||
"date": "2026-02-16",
|
||||
"updated": "2026-02-16",
|
||||
"summary": "Removed ModelRouter tier-change listener setter footgun: setOnTierChange now appends instead of replacing existing listeners, with regression test coverage.",
|
||||
"files_modified": [
|
||||
"src/models/router.ts",
|
||||
"src/models/router.test.ts",
|
||||
"docs/plans/analysis/2026-02-16-codebase-audit-report.md"
|
||||
],
|
||||
"test_status": "pnpm test:run src/models/router.test.ts + pnpm typecheck passing"
|
||||
}
|
||||
},
|
||||
"overall_progress": {
|
||||
|
||||
@@ -463,4 +463,22 @@ describe('setClient and labels', () => {
|
||||
expect(fallback.chat).not.toHaveBeenCalled();
|
||||
expect(router.isTierStrict('default')).toBe(true);
|
||||
});
|
||||
|
||||
it('setOnTierChange does not replace existing listeners', () => {
|
||||
const router = new ModelRouter({
|
||||
default: { chat: vi.fn() } as unknown as ModelClient,
|
||||
fast: { chat: vi.fn() } as unknown as ModelClient,
|
||||
fallbackChain: [],
|
||||
});
|
||||
|
||||
const first = vi.fn();
|
||||
const second = vi.fn();
|
||||
router.addOnTierChange(first);
|
||||
router.setOnTierChange(second);
|
||||
|
||||
router.setTier('fast');
|
||||
|
||||
expect(first).toHaveBeenCalledWith('fast');
|
||||
expect(second).toHaveBeenCalledWith('fast');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -67,7 +67,7 @@ export class ModelRouter implements ModelClient {
|
||||
}
|
||||
|
||||
setOnTierChange(callback: (tier: ModelTier) => void): void {
|
||||
this.tierChangeListeners = [callback];
|
||||
this.addOnTierChange(callback);
|
||||
}
|
||||
|
||||
addOnTierChange(callback: (tier: ModelTier) => void): void {
|
||||
|
||||
Reference in New Issue
Block a user