feat(linkup): add fetch operation to the Linkup block - #8547
shauryajain21 wants to merge 2 commits into
Conversation
|
@shauryajain21 is attempting to deploy a commit to the Sim Team on Vercel. A member of the Team first needs to authorize it. |
|
| // Linkup pricing (https://docs.linkup.so/pages/documentation/platform/pricing): | ||
| // Standard: $0.001/call | ||
| // Standard + renderJs: $0.005/call | ||
| const renderJs = params.renderJs === true |
There was a problem hiding this comment.
Render pricing misses string switches
A workflow variable or legacy switch can pass Render JavaScript as the string 'true'. The request forwards that string, but this check charges the rendered rate only for boolean true. If Linkup accepts the string as enabling rendering, the call is billed at $0.001 instead of $0.005; if it rejects the string, the requested fetch fails. Convert the value consistently before building the request and calculating its cost.
| rawHtml: { | ||
| type: 'string', | ||
| description: 'The raw HTML of the webpage, when includeRawHtml is enabled', | ||
| optional: true, | ||
| }, |
There was a problem hiding this comment.
When Linkup omits rawHtml or favicon, the transform returns null for those fields, but both are declared only as optional strings. Consumers of the output schema can therefore expect a string or a missing field and receive null instead. Declare both outputs nullable, or omit them when absent.
| 'Search the web', | ||
| { text: 'for', field: 'q' }, |
There was a problem hiding this comment.
Legacy cards lose query placeholder
Saved blocks without an operation use this default sentence. When their query is empty, the new non-core clause disappears, leaving only “Search the web” where the card previously showed a Search Query placeholder. Keeping the query clause core would preserve that cue on existing cards.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| Authorization: `Bearer ${params.apiKey}`, | ||
| }), | ||
| body: (params) => { | ||
| const body: Record<string, any> = { |
There was a problem hiding this comment.
The new request body uses Record<string, any>, and the test helper repeats that cast. The repository’s TypeScript directive prohibits any and calls for precise types or unknown with guards. Please type these values to match their actual shapes before merging.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| describe('linkup block', () => { | ||
| const selectTool = (params: Record<string, unknown>) => | ||
| LinkupBlock.tools.config?.tool?.(params as never) | ||
|
|
||
| it('routes blocks saved before the operation dropdown to search', () => { | ||
| expect(selectTool({ q: 'latest news' })).toBe('linkup_search') | ||
| }) | ||
|
|
||
| it('routes each operation to its tool', () => { | ||
| expect(selectTool({ operation: 'linkup_search' })).toBe('linkup_search') | ||
| expect(selectTool({ operation: 'linkup_fetch' })).toBe('linkup_fetch') | ||
| }) |
There was a problem hiding this comment.
These tests call the block’s tool selector directly, so they cannot catch failures between a saved Linkup block and an executed Fetch request, including input conversion or hosted-key handling. The repository’s testing directive discourages tests that restate declarations and favors checks at the real boundary. Add execution-boundary coverage before merging.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
5a2f643 to
2c39728
Compare
Render JavaScript and the other fetch switches can arrive as strings from block inputs. Normalize them once so the request sends booleans and hosted pricing bills the same rendering decision. Declare rawHtml/favicon as nullable, type the request and response bodies, and cover the string cases plus an executor-level fetch run in tests.
Summary
Adds a Linkup Fetch tool (
linkup_fetch,POST https://api.linkup.so/v1/fetch) that returns a webpage as clean markdown, and exposes it as a second operation on the existing Linkup block. The block now has an operation dropdown (Search / Fetch) with operation-conditioned sub-blocks, following the same structure as the Exa block.tools/linkup/fetch.ts: paramsurl(required),renderJs,includeRawHtml,extractImages; outputsmarkdown,rawHtml,images[{alt, url}],favicon. Uses the same hosted-key / BYOK config aslinkup_search(LINKUP_API_KEY, providerlinkup), priced per Linkup's pricing: $0.001/call, $0.005 withrenderJs.operationdropdown defaulting tolinkup_search, fetch sub-blocks,tools.access+tools.config.tool, inputs/outputs, canvas sentences, and afetch-page-markdownskill.operation. Search fields are gated onoperation !== 'linkup_fetch'and the tool selector falls back tolinkup_search, so existing workflows keep rendering, serializing, and running as search. Thedefaultcanvas sentence still covers those blocks.tools/registry.ts; regenerated tool metadata, integration docs (integrations/linkup.mdx) andintegrations.json; added Fetch rows to the Linkup tab inplatform/costs.mdx.Usage: add a Linkup block, choose Fetch, set URL to
https://docs.linkup.so, then reference<linkup.markdown>downstream. Agents can also calllinkup_fetchas a tool.Type of Change
Testing
tools/linkup/linkup.test.ts(new, mocked): request body (url trimming, option passthrough incl. explicitfalse),transformResponsemapping and defaults, hosted pricing, block routing (including blocks with no stored operation), and condition visibility for legacy vs. fetch.bunx vitest run tools/linkup blocks/blocks.test.ts blocks/password-masking.test.ts blocks/registry-lookup.test.ts tools/metadata.test.ts tools/index.test.ts tools/model-input-selectors.test.ts tools/param-shape.test.ts lib/workflows/blocks lib/workflows/migrations: 22 files, 573 tests passing.bun run type-check(apps/sim),biome checkon changed files.check:canvas-sentences,tool-metadata:check,docs:check,deployment-config:check,integration-catalog:check,check:byok-providers,check:tool-param-reachability,check:tool-request-boundary,check:tool-registry-boundary,check:test-patterns,check-block-registry.ts: all pass.linkup_search(sourcedAnswer) andlinkup_fetch(withincludeRawHtml/extractImages) both return the expected outputs through the tool configs.Worth a look: the "not fetch" condition used for backwards compatibility with blocks that predate the operation dropdown.
Checklist
Screenshots/Videos