Skip to content

Commit 945f7ea

Browse files
author
Theodore Li
committed
Add jina hosted key
1 parent 6c9bd07 commit 945f7ea

File tree

3 files changed

+106
-7
lines changed

3 files changed

+106
-7
lines changed

apps/sim/blocks/blocks/jina.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ export const JinaBlock: BlockConfig<ReadUrlResponse | SearchResponse> = {
144144
required: true,
145145
placeholder: 'Enter your Jina API key',
146146
password: true,
147+
hideWhenHosted: true,
147148
},
148149
],
149150
tools: {

apps/sim/tools/jina/read_url.ts

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { createLogger } from '@sim/logger'
12
import type { ReadUrlParams, ReadUrlResponse } from '@/tools/jina/types'
23
import type { ToolConfig } from '@/tools/types'
34

5+
const logger = createLogger('JinaReaderTool')
6+
47
export const readUrlTool: ToolConfig<ReadUrlParams, ReadUrlResponse> = {
58
id: 'jina_read_url',
69
name: 'Jina Reader',
@@ -159,25 +162,56 @@ export const readUrlTool: ToolConfig<ReadUrlParams, ReadUrlResponse> = {
159162
},
160163
},
161164

165+
hosting: {
166+
envKeyPrefix: 'JINA_API_KEY',
167+
apiKeyParam: 'apiKey',
168+
byokProviderId: 'jina',
169+
pricing: {
170+
type: 'custom',
171+
getCost: (_params, output) => {
172+
// Jina bills per output token — $0.20 per 1M tokens
173+
// Source: https://cloud.jina.ai/pricing (token-based billing)
174+
// x-tokens header is unreliable; falls back to content-length estimate (~4 chars/token)
175+
const tokens = output.tokensUsed as number
176+
const cost = tokens * 0.0000002
177+
return { cost, metadata: { tokensUsed: tokens } }
178+
},
179+
},
180+
rateLimit: {
181+
mode: 'per_request',
182+
requestsPerMinute: 200,
183+
},
184+
},
185+
162186
transformResponse: async (response: Response) => {
187+
let tokensUsed: number | undefined
188+
189+
const tokensHeader = response.headers.get('x-tokens')
190+
if (tokensHeader) {
191+
const parsed = parseInt(tokensHeader, 10)
192+
if (!isNaN(parsed)) {
193+
tokensUsed = parsed
194+
}
195+
}
196+
163197
const contentType = response.headers.get('content-type')
164198

165199
if (contentType?.includes('application/json')) {
166200
const data = await response.json()
201+
tokensUsed ??= data.data?.usage?.tokens ?? data.usage?.tokens
202+
const content = data.data?.content || data.content || JSON.stringify(data)
203+
tokensUsed ??= Math.ceil(content.length / 4)
167204
return {
168205
success: response.ok,
169-
output: {
170-
content: data.data?.content || data.content || JSON.stringify(data),
171-
},
206+
output: { content, tokensUsed },
172207
}
173208
}
174209

175210
const content = await response.text()
211+
tokensUsed ??= Math.ceil(content.length / 4)
176212
return {
177213
success: response.ok,
178-
output: {
179-
content,
180-
},
214+
output: { content, tokensUsed },
181215
}
182216
},
183217

@@ -186,5 +220,10 @@ export const readUrlTool: ToolConfig<ReadUrlParams, ReadUrlResponse> = {
186220
type: 'string',
187221
description: 'The extracted content from the URL, processed into clean, LLM-friendly text',
188222
},
223+
tokensUsed: {
224+
type: 'number',
225+
description: 'Number of Jina tokens consumed by this request',
226+
optional: true,
227+
},
189228
},
190229
}

apps/sim/tools/jina/search.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import { createLogger } from '@sim/logger'
12
import type { SearchParams, SearchResponse } from '@/tools/jina/types'
23
import { JINA_SEARCH_RESULT_OUTPUT_PROPERTIES } from '@/tools/jina/types'
34
import type { ToolConfig } from '@/tools/types'
45

6+
const logger = createLogger('JinaSearchTool')
7+
58
export const searchTool: ToolConfig<SearchParams, SearchResponse> = {
69
id: 'jina_search',
710
name: 'Jina Search',
@@ -147,12 +150,62 @@ export const searchTool: ToolConfig<SearchParams, SearchResponse> = {
147150
},
148151
},
149152

153+
hosting: {
154+
envKeyPrefix: 'JINA_API_KEY',
155+
apiKeyParam: 'apiKey',
156+
byokProviderId: 'jina',
157+
pricing: {
158+
type: 'custom',
159+
getCost: (_params, output) => {
160+
// Jina bills per output token — $0.20 per 1M tokens
161+
// Search costs a fixed minimum of 10,000 tokens per request
162+
// Source: https://cloud.jina.ai/pricing (token-based billing)
163+
// x-tokens header is unreliable; falls back to content-length estimate (~4 chars/token)
164+
const tokens = output.tokensUsed as number
165+
const cost = tokens * 0.0000002
166+
return { cost, metadata: { tokensUsed: tokens } }
167+
},
168+
},
169+
rateLimit: {
170+
mode: 'per_request',
171+
requestsPerMinute: 40,
172+
},
173+
},
174+
150175
transformResponse: async (response: Response) => {
151176
const data = await response.json()
152177

153-
// The API returns an array of results or a data object with results
178+
let tokensUsed: number | undefined
179+
const tokensHeader = response.headers.get('x-tokens')
180+
if (tokensHeader) {
181+
const parsed = parseInt(tokensHeader, 10)
182+
if (!isNaN(parsed) && parsed > 0) {
183+
tokensUsed = parsed
184+
}
185+
}
186+
154187
const results = Array.isArray(data) ? data : data.data || []
155188

189+
if (tokensUsed == null) {
190+
let total = 0
191+
for (const result of results) {
192+
if (result.usage?.tokens) {
193+
total += result.usage.tokens
194+
}
195+
}
196+
if (total > 0) {
197+
tokensUsed = total
198+
}
199+
}
200+
201+
if (tokensUsed == null) {
202+
let totalChars = 0
203+
for (const result of results) {
204+
totalChars += (result.content?.length ?? 0) + (result.title?.length ?? 0)
205+
}
206+
tokensUsed = Math.max(Math.ceil(totalChars / 4), 10000)
207+
}
208+
156209
return {
157210
success: response.ok,
158211
output: {
@@ -162,6 +215,7 @@ export const searchTool: ToolConfig<SearchParams, SearchResponse> = {
162215
url: result.url || '',
163216
content: result.content || '',
164217
})),
218+
tokensUsed,
165219
},
166220
}
167221
},
@@ -176,5 +230,10 @@ export const searchTool: ToolConfig<SearchParams, SearchResponse> = {
176230
properties: JINA_SEARCH_RESULT_OUTPUT_PROPERTIES,
177231
},
178232
},
233+
tokensUsed: {
234+
type: 'number',
235+
description: 'Number of Jina tokens consumed by this request',
236+
optional: true,
237+
},
179238
},
180239
}

0 commit comments

Comments
 (0)