refactor(llm): remove isDailyLimitReached from downstream consumers

The LlmService interface no longer exposes isDailyLimitReached — model
switching is handled internally. Remove all checks in thoughtSystem,
inventionSystem, narrationService, and thoughtGenerator. Update mocks
in test files to match the new interface and remove obsolete daily-limit
test cases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
root
2026-03-09 16:03:09 +00:00
parent 5c9edbde3c
commit 1acfc78e13
9 changed files with 16 additions and 57 deletions
@@ -9,7 +9,9 @@ function mockLlmService(overrides: Partial<LlmService> = {}): LlmService {
generate: vi.fn().mockResolvedValue('LLM narration text'),
queueDepth: vi.fn().mockReturnValue(0),
clear: vi.fn(),
isDailyLimitReached: vi.fn().mockReturnValue(false),
activeModel: vi.fn().mockReturnValue('test-model'),
usageStats: vi.fn().mockReturnValue({}),
usageSummary: vi.fn().mockReturnValue(''),
...overrides,
};
}
@@ -90,14 +92,6 @@ describe('NarrationService', () => {
expect(llm.generate).not.toHaveBeenCalled();
});
it('does not queue LLM when daily limit is reached', () => {
llm = mockLlmService({ isDailyLimitReached: vi.fn().mockReturnValue(true) });
const service = createNarrationService(llm);
service.recordInteraction(makeRecord({ isPriority: true }));
expect(llm.generate).not.toHaveBeenCalled();
});
it('rolling buffer caps at 50', () => {
const service = createNarrationService(llm);
for (let i = 0; i < 55; i++) {
@@ -7,7 +7,9 @@ function mockLlmService(overrides: Partial<LlmService> = {}): LlmService {
generate: vi.fn().mockResolvedValue(null),
queueDepth: vi.fn().mockReturnValue(0),
clear: vi.fn(),
isDailyLimitReached: vi.fn().mockReturnValue(false),
activeModel: vi.fn().mockReturnValue('test-model'),
usageStats: vi.fn().mockReturnValue({}),
usageSummary: vi.fn().mockReturnValue(''),
...overrides,
};
}
@@ -98,17 +100,4 @@ describe('generateBatchedThoughts', () => {
expect(result).toEqual([]);
});
it('returns empty array when daily limit reached', async () => {
const llm = mockLlmService({
isDailyLimitReached: vi.fn().mockReturnValue(true),
});
const requests: ThoughtRequest[] = [
{ entityId: 1, name: 'A', personality: '', currentState: '', recentEvents: '' },
];
const result = await generateBatchedThoughts(requests, llm);
expect(result).toEqual([]);
expect(llm.generate).not.toHaveBeenCalled();
});
});
+1 -2
View File
@@ -62,8 +62,7 @@ export function createNarrationService(llmService: LlmService): NarrationService
if (persistFn) persistFn(event);
service.onEventCreated?.(event);
const shouldQueueLlm =
(record.isProposal || record.isPriority) && !llmService.isDailyLimitReached();
const shouldQueueLlm = record.isProposal || record.isPriority;
if (shouldQueueLlm) {
const variables: Record<string, string> = {
-1
View File
@@ -19,7 +19,6 @@ export async function generateBatchedThoughts(
llmService: LlmService,
): Promise<ThoughtResult[]> {
if (requests.length === 0) return [];
if (llmService.isDailyLimitReached()) return [];
const npcList = requests
.map((r, i) =>
@@ -41,7 +41,9 @@ describe('invention integration', () => {
generate: generateMock,
queueDepth: () => 0,
clear: () => {},
isDailyLimitReached: () => false,
activeModel: () => 'test-model',
usageStats: () => ({}),
usageSummary: () => '',
};
const narrationEvents: any[] = [];
@@ -14,7 +14,9 @@ function createMockLlm(): LlmService {
generate: vi.fn().mockResolvedValue(null),
queueDepth: () => 0,
clear: () => {},
isDailyLimitReached: () => false,
activeModel: () => 'test-model',
usageStats: () => ({}),
usageSummary: () => '',
};
}
@@ -154,16 +156,4 @@ describe('inventionSystem', () => {
expect(itemRegistry.getAll().length).toBe(5);
});
it('skips when daily LLM limit reached', () => {
const { world } = setupWorld();
addNPC(world, { inv: new Map([['log', 5]]) });
const llm = createMockLlm();
(llm as any).isDailyLimitReached = () => true;
const system = createInventionSystem(llm, createMockNarration(), createEventMemoryService());
vi.spyOn(Math, 'random').mockReturnValue(0);
system.update(world, 100);
expect(llm.generate).not.toHaveBeenCalled();
vi.restoreAllMocks();
});
});
@@ -9,7 +9,9 @@ function mockLlmService(overrides: Partial<LlmService> = {}): LlmService {
generate: vi.fn().mockResolvedValue(null),
queueDepth: vi.fn().mockReturnValue(0),
clear: vi.fn(),
isDailyLimitReached: vi.fn().mockReturnValue(false),
activeModel: vi.fn().mockReturnValue('test-model'),
usageStats: vi.fn().mockReturnValue({}),
usageSummary: vi.fn().mockReturnValue(''),
...overrides,
};
}
@@ -118,16 +120,4 @@ describe('ThoughtSystem', () => {
expect(llm.generate).toHaveBeenCalledOnce(); // still just once — cooldown not expired yet
});
it('does not generate when daily limit reached', () => {
llm = mockLlmService({
isDailyLimitReached: vi.fn().mockReturnValue(true),
});
const system = createThoughtSystem(llm);
const e = makeNpc(world, 'Bjorn');
followedIds.add(e);
system.update(world, followedIds, 900);
expect(llm.generate).not.toHaveBeenCalled();
});
});
-3
View File
@@ -31,9 +31,6 @@ export function createInventionSystem(
// Only check on interval ticks
if (tick % industryConfig.inventionCheckInterval !== 0) return;
// Skip if daily limit reached
if (llmService.isDailyLimitReached()) return;
const itemRegistry = world.getSingleton<ItemRegistry>('itemRegistry');
const recipeRegistry = world.getSingleton<RecipeRegistry>('recipeRegistry');
const timeline = world.getSingleton<InventionTimeline>('inventionTimeline');
-1
View File
@@ -36,7 +36,6 @@ export function createThoughtSystem(
lastPeriodicTick = tick;
if (pendingGeneration) return;
if (llmService.isDailyLimitReached()) return;
const eligible: { entityId: EntityId; context: ThoughtContext }[] = [];
const npcs = world.query('npcBrain', 'name', 'stats', 'needs');