Skip to content

Commit af94705

Browse files
committed
fix(exa): flag empty Get Contents configs in the editor, keep legacy research depth
- A saved research workflow with no stored model fell through to the Agent default of auto rather than the standard depth the old Research operation used. Legacy research now always maps to an effort level, defaulting to medium, and the legacy model sub-block carries the same default the old dropdown had. - Get Contents needed both selectors optional so the ids path is reachable, which left an empty config failing only at run time. URLs is now conditionally required, dropping the requirement when result IDs are supplied, so the editor flags the empty case. The exactly-one check in the request body stays as the backstop.
1 parent 914c9b2 commit af94705

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

apps/sim/blocks/blocks/exa.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ const CATEGORY_OPTIONS = [
2222
* carrying a stored research query forward — it drops any value whose sub-block
2323
* condition no longer matches.
2424
*/
25+
/** True when a sub-block holds a non-empty user value. */
26+
function hasValue(value: unknown): boolean {
27+
return typeof value === 'string' ? value.trim().length > 0 : value != null
28+
}
29+
2530
const LEGACY_RESEARCH_OPERATION = 'exa_research'
2631
const AGENT_OPERATIONS = ['exa_agent', LEGACY_RESEARCH_OPERATION]
2732

@@ -265,6 +270,17 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
265270
placeholder: 'Enter URLs to retrieve content from (comma-separated)...',
266271
description: 'Provide either URLs or Result IDs, not both',
267272
condition: { field: 'operation', value: 'exa_get_contents' },
273+
/**
274+
* Exactly one selector is needed. Inverting the operation match when
275+
* Result IDs are present makes the requirement fall away for this
276+
* operation, so the editor flags an empty config without blocking the
277+
* ids-only path.
278+
*/
279+
required: (values) => ({
280+
field: 'operation',
281+
value: 'exa_get_contents',
282+
not: hasValue(values?.ids),
283+
}),
268284
},
269285
{
270286
id: 'ids',
@@ -431,6 +447,7 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
431447
{ label: 'Pro', id: 'exa-research-pro' },
432448
],
433449
description: 'Retired Exa research model, carried over as an Agent effort level',
450+
value: () => 'exa-research',
434451
condition: { field: 'operation', value: LEGACY_RESEARCH_OPERATION },
435452
},
436453
{
@@ -578,8 +595,13 @@ export const ExaBlock: BlockConfig<ExaResponse> = {
578595
if (params.livecrawlTimeout) {
579596
result.livecrawlTimeout = Number(params.livecrawlTimeout)
580597
}
581-
/** Carry a retired research model over to the Agent API's effort scale. */
582-
if (params.operation === LEGACY_RESEARCH_OPERATION && params.model) {
598+
/**
599+
* Carry a retired research model over to the Agent API's effort scale.
600+
* The old Research operation defaulted to the standard model, so an
601+
* unset value maps to the same depth rather than falling through to
602+
* the Agent default of `auto`.
603+
*/
604+
if (params.operation === LEGACY_RESEARCH_OPERATION) {
583605
result.effort = RESEARCH_MODEL_TO_EFFORT[params.model as string] ?? 'medium'
584606
}
585607
return result

apps/sim/tools/exa/exa.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,23 @@ describe('exa block', () => {
178178
expect(params.effort).toBe('high')
179179
})
180180

181+
it('keeps the old standard research depth when no model was stored', () => {
182+
const params = ExaBlock.tools.config?.params?.({
183+
operation: 'exa_research',
184+
}) as Record<string, unknown>
185+
expect(params.effort).toBe('medium')
186+
})
187+
188+
it('requires URLs on Get Contents when no result IDs are supplied', () => {
189+
const urls = ExaBlock.subBlocks.find(
190+
(block) => block.id === 'urls' && block.condition?.value === 'exa_get_contents'
191+
)
192+
const required = urls?.required as (values?: Record<string, unknown>) => { not?: boolean }
193+
expect(required({}).not).toBe(false)
194+
expect(required({ ids: ' ' }).not).toBe(false)
195+
expect(required({ ids: 'id-1' }).not).toBe(true)
196+
})
197+
181198
it('keeps the legacy model sub-block so the serializer preserves its value', () => {
182199
const model = ExaBlock.subBlocks.find((block) => block.id === 'model')
183200
expect(model?.condition?.value).toBe('exa_research')

0 commit comments

Comments
 (0)