diff --git a/api/app/clients/specs/BaseClient.test.js b/api/app/clients/specs/BaseClient.test.js index df9b5d1e3c..fd5b9aeb8a 100644 --- a/api/app/clients/specs/BaseClient.test.js +++ b/api/app/clients/specs/BaseClient.test.js @@ -1240,6 +1240,80 @@ describe('BaseClient', () => { }); }); + /** + * The `transactions.enabled` guard lives in `createTransaction`, which reads it off + * the object it is handed. Dropping the config anywhere between here and there + * silently re-enables the writes rather than failing, so pin the wiring itself. + */ + describe('recordTokenUsage transactions config', () => { + let priorEndpoint; + let priorEndpointType; + + const arrangeFallbackPath = () => { + TestClient.getTokenCountForResponse = jest.fn().mockReturnValue(50); + TestClient.recordTokenUsage = jest.fn().mockResolvedValue(undefined); + TestClient.buildMessages.mockReturnValue({ + prompt: [], + tokenCountMap: { res: 50 }, + }); + }; + + /** `options` is shared across this file's tests, so an endpoint left behind by an earlier + * case would route the balance-enabled arrangement into `checkBalance`. */ + beforeEach(() => { + priorEndpoint = TestClient.options.endpoint; + priorEndpointType = TestClient.options.endpointType; + delete TestClient.options.endpoint; + delete TestClient.options.endpointType; + }); + + afterEach(() => { + delete TestClient.options.req; + TestClient.options.endpoint = priorEndpoint; + TestClient.options.endpointType = priorEndpointType; + }); + + test('should forward the resolved transactions config to recordTokenUsage', async () => { + TestClient.options.req = { config: { transactions: { enabled: false } } }; + arrangeFallbackPath(); + + await TestClient.sendMessage('Hello', {}); + + expect(TestClient.recordTokenUsage).toHaveBeenCalledWith( + expect.objectContaining({ + transactions: { enabled: false }, + }), + ); + }); + + test('should default to enabled transactions when no app config is present', async () => { + arrangeFallbackPath(); + + await TestClient.sendMessage('Hello', {}); + + expect(TestClient.recordTokenUsage).toHaveBeenCalledWith( + expect.objectContaining({ + transactions: { enabled: true }, + }), + ); + }); + + test('should forward transactions as enabled when balance tracking overrides the setting', async () => { + TestClient.options.req = { + config: { transactions: { enabled: false }, balance: { enabled: true } }, + }; + arrangeFallbackPath(); + + await TestClient.sendMessage('Hello', {}); + + expect(TestClient.recordTokenUsage).toHaveBeenCalledWith( + expect.objectContaining({ + transactions: { enabled: true }, + }), + ); + }); + }); + describe('getMessagesWithinTokenLimit with instructions', () => { test('should always include instructions when present', async () => { TestClient.maxContextTokens = 50;