Skip to content

Commit ce02a30

Browse files
author
Theodore Li
committed
Migrate knowledge unit tests
1 parent 68da290 commit ce02a30

File tree

7 files changed

+229
-174
lines changed

7 files changed

+229
-174
lines changed

apps/sim/executor/handlers/generic/generic-handler.test.ts

Lines changed: 0 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -148,165 +148,4 @@ describe('GenericBlockHandler', () => {
148148
)
149149
})
150150

151-
describe('Knowledge block cost tracking', () => {
152-
beforeEach(() => {
153-
// Set up knowledge block mock
154-
mockBlock = {
155-
...mockBlock,
156-
config: { tool: 'knowledge_search', params: {} },
157-
}
158-
159-
mockTool = {
160-
...mockTool,
161-
id: 'knowledge_search',
162-
name: 'Knowledge Search',
163-
}
164-
165-
mockGetTool.mockImplementation((toolId) => {
166-
if (toolId === 'knowledge_search') {
167-
return mockTool
168-
}
169-
return undefined
170-
})
171-
})
172-
173-
it.concurrent(
174-
'should pass through cost information from knowledge tools unchanged',
175-
async () => {
176-
const inputs = { query: 'test query' }
177-
// Tool's transformResponse already restructures cost, so executeTool returns restructured data
178-
const mockToolResponse = {
179-
success: true,
180-
output: {
181-
results: [],
182-
query: 'test query',
183-
totalResults: 0,
184-
cost: {
185-
input: 0.00001042,
186-
output: 0,
187-
total: 0.00001042,
188-
},
189-
tokens: {
190-
input: 521,
191-
output: 0,
192-
total: 521,
193-
},
194-
model: 'text-embedding-3-small',
195-
},
196-
}
197-
198-
mockExecuteTool.mockResolvedValue(mockToolResponse)
199-
200-
const result = await handler.execute(mockContext, mockBlock, inputs)
201-
202-
// Generic handler passes through output unchanged
203-
expect(result).toEqual({
204-
results: [],
205-
query: 'test query',
206-
totalResults: 0,
207-
cost: {
208-
input: 0.00001042,
209-
output: 0,
210-
total: 0.00001042,
211-
},
212-
tokens: {
213-
input: 521,
214-
output: 0,
215-
total: 521,
216-
},
217-
model: 'text-embedding-3-small',
218-
})
219-
}
220-
)
221-
222-
it.concurrent('should pass through knowledge_upload_chunk output unchanged', async () => {
223-
// Update to upload_chunk tool
224-
mockBlock.config.tool = 'knowledge_upload_chunk'
225-
mockTool.id = 'knowledge_upload_chunk'
226-
mockTool.name = 'Knowledge Upload Chunk'
227-
228-
mockGetTool.mockImplementation((toolId) => {
229-
if (toolId === 'knowledge_upload_chunk') {
230-
return mockTool
231-
}
232-
return undefined
233-
})
234-
235-
const inputs = { content: 'test content' }
236-
// Tool's transformResponse already restructures cost
237-
const mockToolResponse = {
238-
success: true,
239-
output: {
240-
data: {
241-
id: 'chunk-123',
242-
content: 'test content',
243-
chunkIndex: 0,
244-
},
245-
message: 'Successfully uploaded chunk',
246-
documentId: 'doc-123',
247-
cost: {
248-
input: 0.00000521,
249-
output: 0,
250-
total: 0.00000521,
251-
},
252-
tokens: {
253-
input: 260,
254-
output: 0,
255-
total: 260,
256-
},
257-
model: 'text-embedding-3-small',
258-
},
259-
}
260-
261-
mockExecuteTool.mockResolvedValue(mockToolResponse)
262-
263-
const result = await handler.execute(mockContext, mockBlock, inputs)
264-
265-
// Generic handler passes through output unchanged
266-
expect(result).toEqual({
267-
data: {
268-
id: 'chunk-123',
269-
content: 'test content',
270-
chunkIndex: 0,
271-
},
272-
message: 'Successfully uploaded chunk',
273-
documentId: 'doc-123',
274-
cost: {
275-
input: 0.00000521,
276-
output: 0,
277-
total: 0.00000521,
278-
},
279-
tokens: {
280-
input: 260,
281-
output: 0,
282-
total: 260,
283-
},
284-
model: 'text-embedding-3-small',
285-
})
286-
})
287-
288-
it('should pass through output unchanged for knowledge tools without cost info', async () => {
289-
const inputs = { query: 'test query' }
290-
const mockToolResponse = {
291-
success: true,
292-
output: {
293-
results: [],
294-
query: 'test query',
295-
totalResults: 0,
296-
// No cost information
297-
},
298-
}
299-
300-
mockExecuteTool.mockResolvedValue(mockToolResponse)
301-
302-
const result = await handler.execute(mockContext, mockBlock, inputs)
303-
304-
// Should return original output unchanged
305-
expect(result).toEqual({
306-
results: [],
307-
query: 'test query',
308-
totalResults: 0,
309-
})
310-
})
311-
})
312151
})

apps/sim/tools/exa/answer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,9 @@ export const answerTool: ToolConfig<ExaAnswerParams, ExaAnswerResponse> = {
3838
type: 'custom',
3939
getCost: (_params, output) => {
4040
// Use _costDollars from Exa API response (internal field, stripped from final output)
41-
if (output._costDollars?.total) {
42-
return { cost: output._costDollars.total, metadata: { costDollars: output._costDollars } }
41+
const costDollars = output._costDollars as { total?: number } | undefined
42+
if (costDollars?.total) {
43+
return { cost: costDollars.total, metadata: { costDollars } }
4344
}
4445
// Fallback: $5/1000 requests
4546
logger.warn('Exa answer response missing costDollars, using fallback pricing')

apps/sim/tools/exa/find_similar_links.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@ export const findSimilarLinksTool: ToolConfig<
8787
type: 'custom',
8888
getCost: (_params, output) => {
8989
// Use _costDollars from Exa API response (internal field, stripped from final output)
90-
if (output._costDollars?.total) {
91-
return { cost: output._costDollars.total, metadata: { costDollars: output._costDollars } }
90+
const costDollars = output._costDollars as { total?: number } | undefined
91+
if (costDollars?.total) {
92+
return { cost: costDollars.total, metadata: { costDollars } }
9293
}
9394
// Fallback: $5/1000 (1-25 results) or $25/1000 (26-100 results)
9495
logger.warn('Exa find_similar_links response missing costDollars, using fallback pricing')
95-
const resultCount = output.similarLinks?.length || 0
96+
const similarLinks = output.similarLinks as unknown[] | undefined
97+
const resultCount = similarLinks?.length || 0
9698
return resultCount <= 25 ? 0.005 : 0.025
9799
},
98100
},

apps/sim/tools/exa/get_contents.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,14 @@ export const getContentsTool: ToolConfig<ExaGetContentsParams, ExaGetContentsRes
7272
type: 'custom',
7373
getCost: (_params, output) => {
7474
// Use _costDollars from Exa API response (internal field, stripped from final output)
75-
if (output._costDollars?.total) {
76-
return { cost: output._costDollars.total, metadata: { costDollars: output._costDollars } }
75+
const costDollars = output._costDollars as { total?: number } | undefined
76+
if (costDollars?.total) {
77+
return { cost: costDollars.total, metadata: { costDollars } }
7778
}
7879
// Fallback: $1/1000 pages
7980
logger.warn('Exa get_contents response missing costDollars, using fallback pricing')
80-
return (output.results?.length || 0) * 0.001
81+
const results = output.results as unknown[] | undefined
82+
return (results?.length || 0) * 0.001
8183
},
8284
},
8385
},

apps/sim/tools/exa/research.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ export const researchTool: ToolConfig<ExaResearchParams, ExaResearchResponse> =
4242
type: 'custom',
4343
getCost: (params, output) => {
4444
// Use _costDollars from Exa API response (internal field, stripped from final output)
45-
if (output._costDollars?.total) {
46-
return { cost: output._costDollars.total, metadata: { costDollars: output._costDollars } }
45+
const costDollars = output._costDollars as { total?: number } | undefined
46+
if (costDollars?.total) {
47+
return { cost: costDollars.total, metadata: { costDollars } }
4748
}
4849

4950
// Fallback to estimate if cost not available

apps/sim/tools/exa/search.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,9 @@ export const searchTool: ToolConfig<ExaSearchParams, ExaSearchResponse> = {
9797
type: 'custom',
9898
getCost: (params, output) => {
9999
// Use _costDollars from Exa API response (internal field, stripped from final output)
100-
if (output._costDollars?.total) {
101-
return { cost: output._costDollars.total, metadata: { costDollars: output._costDollars } }
100+
const costDollars = output._costDollars as { total?: number } | undefined
101+
if (costDollars?.total) {
102+
return { cost: costDollars.total, metadata: { costDollars } }
102103
}
103104

104105
// Fallback: estimate based on search type and result count
@@ -107,7 +108,8 @@ export const searchTool: ToolConfig<ExaSearchParams, ExaSearchResponse> = {
107108
if (isDeepSearch) {
108109
return 0.015
109110
}
110-
const resultCount = output.results?.length || 0
111+
const results = output.results as unknown[] | undefined
112+
const resultCount = results?.length || 0
111113
return resultCount <= 25 ? 0.005 : 0.025
112114
},
113115
},

0 commit comments

Comments
 (0)