@moguiyu/dsh-tavily 0.1.6 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +7 -5
- package/package.json +1 -1
- package/src/client.js +7 -5
- package/src/index.js +56 -15
package/lib/client.js
CHANGED
|
@@ -7,9 +7,9 @@ window.__ModuleLoader__.load({
|
|
|
7
7
|
const inject = ['slots']
|
|
8
8
|
|
|
9
9
|
const STRATEGIES = [
|
|
10
|
-
{ id: 'rotate', label: '
|
|
11
|
-
{ id: 'low-usage-first', label: 'Lowest usage first', hint: '
|
|
12
|
-
{ id: 'high-usage-first', label: 'Highest usage first', hint: '
|
|
10
|
+
{ id: 'rotate', label: 'Round-robin', hint: 'Use keys in turn; on HTTP 401/429 the next key is tried automatically.' },
|
|
11
|
+
{ id: 'low-usage-first', label: 'Lowest usage first', hint: 'Re-orders keys by current Tavily usage, least-used first. The first key becomes primary.' },
|
|
12
|
+
{ id: 'high-usage-first', label: 'Highest usage first', hint: 'Re-orders keys by current Tavily usage, most-used first. The first key becomes primary.' }
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
const ICONS = {
|
|
@@ -338,7 +338,9 @@ window.__ModuleLoader__.load({
|
|
|
338
338
|
const isRemoved = removing[masked] === true
|
|
339
339
|
const isReplacing = replacing[masked] === true
|
|
340
340
|
const isRevealed = typeof revealed[masked] === 'string'
|
|
341
|
-
const usageRow = usage !== null && usage.ok === true
|
|
341
|
+
const usageRow = usage !== null && usage.ok === true
|
|
342
|
+
? (usage.perKey.find((row) => row.masked === masked) || usage.perKey[index])
|
|
343
|
+
: null
|
|
342
344
|
const pct = usageRow && usageRow.ok && usageRow.planLimit != null && usageRow.planLimit > 0 && usageRow.planUsage != null
|
|
343
345
|
? Math.min(100, Math.round((usageRow.planUsage / usageRow.planLimit) * 100))
|
|
344
346
|
: null
|
|
@@ -422,7 +424,7 @@ window.__ModuleLoader__.load({
|
|
|
422
424
|
notice !== null && react.createElement('span', { style: { fontSize: 13, color: notice.ok ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' } }, notice.ok ? notice.ok : String(notice.error))
|
|
423
425
|
),
|
|
424
426
|
react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' } },
|
|
425
|
-
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected
|
|
427
|
+
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected.'
|
|
426
428
|
)
|
|
427
429
|
),
|
|
428
430
|
usageError !== null && react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-state-error-primary)' } }, String(usageError)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moguiyu/dsh-tavily",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Tavily Search for DSH: multiple API keys, rotation/failover, usage gauge, settings card, and web_search toggle in one plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
package/src/client.js
CHANGED
|
@@ -12,9 +12,9 @@ export function factory(require) {
|
|
|
12
12
|
const inject = ['slots']
|
|
13
13
|
|
|
14
14
|
const STRATEGIES = [
|
|
15
|
-
{ id: 'rotate', label: '
|
|
16
|
-
{ id: 'low-usage-first', label: 'Lowest usage first', hint: '
|
|
17
|
-
{ id: 'high-usage-first', label: 'Highest usage first', hint: '
|
|
15
|
+
{ id: 'rotate', label: 'Round-robin', hint: 'Use keys in turn; on HTTP 401/429 the next key is tried automatically.' },
|
|
16
|
+
{ id: 'low-usage-first', label: 'Lowest usage first', hint: 'Re-orders keys by current Tavily usage, least-used first. The first key becomes primary.' },
|
|
17
|
+
{ id: 'high-usage-first', label: 'Highest usage first', hint: 'Re-orders keys by current Tavily usage, most-used first. The first key becomes primary.' }
|
|
18
18
|
]
|
|
19
19
|
|
|
20
20
|
const ICONS = {
|
|
@@ -343,7 +343,9 @@ export function factory(require) {
|
|
|
343
343
|
const isRemoved = removing[masked] === true
|
|
344
344
|
const isReplacing = replacing[masked] === true
|
|
345
345
|
const isRevealed = typeof revealed[masked] === 'string'
|
|
346
|
-
const usageRow = usage !== null && usage.ok === true
|
|
346
|
+
const usageRow = usage !== null && usage.ok === true
|
|
347
|
+
? (usage.perKey.find((row) => row.masked === masked) || usage.perKey[index])
|
|
348
|
+
: null
|
|
347
349
|
const pct = usageRow && usageRow.ok && usageRow.planLimit != null && usageRow.planLimit > 0 && usageRow.planUsage != null
|
|
348
350
|
? Math.min(100, Math.round((usageRow.planUsage / usageRow.planLimit) * 100))
|
|
349
351
|
: null
|
|
@@ -427,7 +429,7 @@ export function factory(require) {
|
|
|
427
429
|
notice !== null && react.createElement('span', { style: { fontSize: 13, color: notice.ok ? 'var(--dsw-alias-state-success-primary)' : 'var(--dsw-alias-state-error-primary)' } }, notice.ok ? notice.ok : String(notice.error))
|
|
428
430
|
),
|
|
429
431
|
react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' } },
|
|
430
|
-
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected
|
|
432
|
+
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected.'
|
|
431
433
|
)
|
|
432
434
|
),
|
|
433
435
|
usageError !== null && react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-state-error-primary)' } }, String(usageError)),
|
package/src/index.js
CHANGED
|
@@ -306,7 +306,7 @@ function readBody(req) {
|
|
|
306
306
|
})
|
|
307
307
|
}
|
|
308
308
|
|
|
309
|
-
async function
|
|
309
|
+
async function fetchUsageDetailsFor(key) {
|
|
310
310
|
try {
|
|
311
311
|
const controller = new AbortController()
|
|
312
312
|
const timer = setTimeout(() => controller.abort(), 15000)
|
|
@@ -323,14 +323,32 @@ async function fetchUsageFor(key) {
|
|
|
323
323
|
const json = await response.json()
|
|
324
324
|
const account = json !== null && typeof json === 'object' ? json.account : undefined
|
|
325
325
|
const keyUsage = json !== null && typeof json === 'object' ? json.key : undefined
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
326
|
+
const usage = keyUsage !== undefined && typeof keyUsage.usage === 'number'
|
|
327
|
+
? keyUsage.usage
|
|
328
|
+
: (account !== undefined && typeof account.plan_usage === 'number' ? account.plan_usage : null)
|
|
329
|
+
const planUsage = account !== undefined && typeof account.plan_usage === 'number'
|
|
330
|
+
? account.plan_usage
|
|
331
|
+
: (keyUsage !== undefined && typeof keyUsage.usage === 'number' ? keyUsage.usage : null)
|
|
332
|
+
const planLimit = account !== undefined && typeof account.plan_limit === 'number'
|
|
333
|
+
? account.plan_limit
|
|
334
|
+
: (keyUsage !== undefined && typeof keyUsage.limit === 'number' ? keyUsage.limit
|
|
335
|
+
: (keyUsage !== undefined && typeof keyUsage.plan_limit === 'number' ? keyUsage.plan_limit : null))
|
|
336
|
+
const currentPlan = account !== undefined && typeof account.plan === 'string'
|
|
337
|
+
? account.plan
|
|
338
|
+
: (keyUsage !== undefined && typeof keyUsage.plan === 'string' ? keyUsage.plan : null)
|
|
339
|
+
if (usage === null && planUsage === null) return null
|
|
340
|
+
return { usage, planUsage, planLimit, currentPlan }
|
|
329
341
|
} catch {
|
|
330
342
|
return null
|
|
331
343
|
}
|
|
332
344
|
}
|
|
333
345
|
|
|
346
|
+
async function fetchUsageFor(key) {
|
|
347
|
+
const details = await fetchUsageDetailsFor(key)
|
|
348
|
+
if (details === null) return null
|
|
349
|
+
return details.usage !== null ? details.usage : details.planUsage
|
|
350
|
+
}
|
|
351
|
+
|
|
334
352
|
async function collectStoredKeys(credentials) {
|
|
335
353
|
const out = []
|
|
336
354
|
const seen = new Set()
|
|
@@ -382,11 +400,24 @@ function applyBackend(ctx) {
|
|
|
382
400
|
}
|
|
383
401
|
}
|
|
384
402
|
}
|
|
403
|
+
const primaryMasked = keys.length > 0 ? maskValue(keys[0]) : null
|
|
404
|
+
const display = keys.map((value) => {
|
|
405
|
+
const masked = maskValue(value)
|
|
406
|
+
return {
|
|
407
|
+
masked,
|
|
408
|
+
savedAt: keySavedAt[masked] !== undefined ? keySavedAt[masked] : null,
|
|
409
|
+
}
|
|
410
|
+
}).sort((a, b) => {
|
|
411
|
+
if (a.savedAt === b.savedAt) return 0
|
|
412
|
+
if (a.savedAt === null) return 1
|
|
413
|
+
if (b.savedAt === null) return -1
|
|
414
|
+
return a.savedAt < b.savedAt ? -1 : 1
|
|
415
|
+
})
|
|
385
416
|
return {
|
|
386
|
-
keys:
|
|
387
|
-
masked:
|
|
388
|
-
savedAt:
|
|
389
|
-
primary:
|
|
417
|
+
keys: display.map((entry) => ({
|
|
418
|
+
masked: entry.masked,
|
|
419
|
+
savedAt: entry.savedAt,
|
|
420
|
+
primary: entry.masked === primaryMasked,
|
|
390
421
|
})),
|
|
391
422
|
strategy: isValidStrategy(state.strategy) ? state.strategy : 'rotate',
|
|
392
423
|
}
|
|
@@ -419,15 +450,25 @@ function applyBackend(ctx) {
|
|
|
419
450
|
try {
|
|
420
451
|
const keys = await collectStoredKeys(credentials)
|
|
421
452
|
if (keys.length === 0) return send(res, 200, { ok: false, error: 'no Tavily API key configured' })
|
|
453
|
+
const state = readState(MANAGER_STATE)
|
|
454
|
+
const keySavedAt = state.keySavedAt !== undefined && typeof state.keySavedAt === 'object' ? state.keySavedAt : {}
|
|
455
|
+
const orderedKeys = keys.slice().sort((a, b) => {
|
|
456
|
+
const am = keySavedAt[maskValue(a)] !== undefined ? keySavedAt[maskValue(a)] : null
|
|
457
|
+
const bm = keySavedAt[maskValue(b)] !== undefined ? keySavedAt[maskValue(b)] : null
|
|
458
|
+
if (am === bm) return 0
|
|
459
|
+
if (am === null) return 1
|
|
460
|
+
if (bm === null) return -1
|
|
461
|
+
return am < bm ? -1 : 1
|
|
462
|
+
})
|
|
422
463
|
const perKey = []
|
|
423
|
-
for (const key of
|
|
464
|
+
for (const key of orderedKeys) {
|
|
424
465
|
try {
|
|
425
|
-
const usage = await
|
|
466
|
+
const usage = await fetchUsageDetailsFor(key)
|
|
426
467
|
perKey.push(usage !== null
|
|
427
|
-
? { ok: true,
|
|
428
|
-
: { ok: false, error: 'usage unavailable' })
|
|
468
|
+
? { ok: true, masked: maskValue(key), ...usage }
|
|
469
|
+
: { ok: false, masked: maskValue(key), error: 'usage unavailable' })
|
|
429
470
|
} catch (error) {
|
|
430
|
-
perKey.push({ ok: false, error: String(error && error.message ? error.message : error) })
|
|
471
|
+
perKey.push({ ok: false, masked: maskValue(key), error: String(error && error.message ? error.message : error) })
|
|
431
472
|
}
|
|
432
473
|
}
|
|
433
474
|
const okRows = perKey.filter((row) => row.ok)
|
|
@@ -438,8 +479,8 @@ function applyBackend(ctx) {
|
|
|
438
479
|
keys: keys.length,
|
|
439
480
|
okKeys: okRows.length,
|
|
440
481
|
usage: okRows.reduce((sum, row) => sum + (row.usage || 0), 0),
|
|
441
|
-
planUsage:
|
|
442
|
-
planLimit: null,
|
|
482
|
+
planUsage: okRows.reduce((sum, row) => sum + (row.planUsage || 0), 0),
|
|
483
|
+
planLimit: okRows.every((row) => row.planLimit !== null) ? okRows.reduce((sum, row) => sum + row.planLimit, 0) : null,
|
|
443
484
|
},
|
|
444
485
|
})
|
|
445
486
|
} catch (error) {
|