From c44d11ebf4047cdb4cdc5f1560af5d185e893812 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 12 Aug 2026 23:42:23 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=BE=20test:=20Pin=20the=20Transactions?= =?UTF-8?q?=20Config=20Wiring=20on=20the=20Fallback=20Path=20(#14779)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #14774. Its tests cover `AgentClient.recordTokenUsage` in isolation, so the `BaseClient` half of the fix was unpinned: deleting the `transactions` property from the call site restored the bug with the suite still green. These cases drive `sendMessage` with a real app config on `req` and assert the resolved value reaches `recordTokenUsage` — disabled, the default when no config is present, and the balance-enabled override that force-enables it. Each fails if either half of #14774 is reverted. They also isolate `options.endpoint` for the block. `options` is shared across this file, and an endpoint left behind by an earlier case routes the balance-enabled arrangement into `checkBalance`. --- api/app/clients/specs/BaseClient.test.js | 74 ++++++++++++++++++++++++ 1 file changed, 74 insertions(+) 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;