@moguiyu/dsh-tavily 0.1.5 → 0.1.7
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 +8 -10
- package/package.json +1 -1
- package/src/client.js +8 -10
- package/src/index.js +26 -8
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 = {
|
|
@@ -64,16 +64,15 @@ window.__ModuleLoader__.load({
|
|
|
64
64
|
}, react.createElement('span', { style: { position: 'absolute', top: 2, left: checked === true ? 18 : 2, width: 14, height: 14, borderRadius: 7, background: '#fff', transition: 'left .12s ease' } }))
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
function UsageCircle({ percent, size, label }) {
|
|
67
|
+
function UsageCircle({ percent, size, label, onClick }) {
|
|
68
68
|
const radius = 15
|
|
69
69
|
const circumference = 2 * Math.PI * radius
|
|
70
70
|
const pct = percent != null ? Math.min(100, Math.max(0, percent)) : 0
|
|
71
|
-
const warn = pct > 85
|
|
72
71
|
const dim = size || 44
|
|
73
|
-
return react.createElement('
|
|
72
|
+
return react.createElement('button', { type: 'button', title: 'Reload usage', 'aria-label': 'Reload usage', onClick: onClick, style: { position: 'relative', width: dim, height: dim, border: 'none', background: 'transparent', padding: 0, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' } },
|
|
74
73
|
react.createElement('svg', { width: dim, height: dim, viewBox: '0 0 40 40' },
|
|
75
74
|
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke: 'var(--dsw-alias-border-l2)', strokeWidth: 4 }),
|
|
76
|
-
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke:
|
|
75
|
+
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke: 'var(--dsw-alias-state-success-primary)', strokeWidth: 4, strokeLinecap: 'round', strokeDasharray: circumference, strokeDashoffset: circumference - (pct / 100) * circumference, transform: 'rotate(-90 20 20)' })
|
|
77
76
|
),
|
|
78
77
|
react.createElement('span', { style: { position: 'absolute', fontSize: 11, fontWeight: 600, color: 'var(--dsw-alias-label-primary)' } }, label != null ? label : (percent != null ? percent + '%' : '—'))
|
|
79
78
|
)
|
|
@@ -362,7 +361,7 @@ window.__ModuleLoader__.load({
|
|
|
362
361
|
)
|
|
363
362
|
),
|
|
364
363
|
react.createElement('td', { style: cellStyle },
|
|
365
|
-
react.createElement(UsageCircle, { percent: pct, label: pct != null ? pct + '%' : (usageRow && usageRow.ok && usageRow.planUsage != null ? String(usageRow.planUsage) : '—') })
|
|
364
|
+
react.createElement(UsageCircle, { percent: pct, label: pct != null ? pct + '%' : (usageRow && usageRow.ok && usageRow.planUsage != null ? String(usageRow.planUsage) : '—'), onClick: refresh })
|
|
366
365
|
),
|
|
367
366
|
react.createElement('td', { style: Object.assign({}, cellStyle, { color: 'var(--dsw-alias-label-tertiary)', whiteSpace: 'nowrap' }) }, formatDate(key.savedAt)),
|
|
368
367
|
react.createElement('td', { style: cellStyle },
|
|
@@ -410,7 +409,6 @@ window.__ModuleLoader__.load({
|
|
|
410
409
|
),
|
|
411
410
|
react.createElement('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } },
|
|
412
411
|
react.createElement('button', { type: 'button', style: btn, onClick: () => setAdds((current) => [...current, { id: 'add-' + Date.now() + '-' + Math.random().toString(36).slice(2, 7), value: '' }]), disabled: busy }, '+ Add key'),
|
|
413
|
-
react.createElement('button', { type: 'button', style: btn, onClick: refresh, disabled: busy }, 'Refresh usage')
|
|
414
412
|
),
|
|
415
413
|
react.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 6 } },
|
|
416
414
|
react.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
|
|
@@ -424,7 +422,7 @@ window.__ModuleLoader__.load({
|
|
|
424
422
|
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))
|
|
425
423
|
),
|
|
426
424
|
react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' } },
|
|
427
|
-
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected
|
|
425
|
+
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected.'
|
|
428
426
|
)
|
|
429
427
|
),
|
|
430
428
|
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.7",
|
|
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 = {
|
|
@@ -69,16 +69,15 @@ export function factory(require) {
|
|
|
69
69
|
}, react.createElement('span', { style: { position: 'absolute', top: 2, left: checked === true ? 18 : 2, width: 14, height: 14, borderRadius: 7, background: '#fff', transition: 'left .12s ease' } }))
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
function UsageCircle({ percent, size, label }) {
|
|
72
|
+
function UsageCircle({ percent, size, label, onClick }) {
|
|
73
73
|
const radius = 15
|
|
74
74
|
const circumference = 2 * Math.PI * radius
|
|
75
75
|
const pct = percent != null ? Math.min(100, Math.max(0, percent)) : 0
|
|
76
|
-
const warn = pct > 85
|
|
77
76
|
const dim = size || 44
|
|
78
|
-
return react.createElement('
|
|
77
|
+
return react.createElement('button', { type: 'button', title: 'Reload usage', 'aria-label': 'Reload usage', onClick: onClick, style: { position: 'relative', width: dim, height: dim, border: 'none', background: 'transparent', padding: 0, cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center' } },
|
|
79
78
|
react.createElement('svg', { width: dim, height: dim, viewBox: '0 0 40 40' },
|
|
80
79
|
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke: 'var(--dsw-alias-border-l2)', strokeWidth: 4 }),
|
|
81
|
-
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke:
|
|
80
|
+
react.createElement('circle', { cx: 20, cy: 20, r: radius, fill: 'none', stroke: 'var(--dsw-alias-state-success-primary)', strokeWidth: 4, strokeLinecap: 'round', strokeDasharray: circumference, strokeDashoffset: circumference - (pct / 100) * circumference, transform: 'rotate(-90 20 20)' })
|
|
82
81
|
),
|
|
83
82
|
react.createElement('span', { style: { position: 'absolute', fontSize: 11, fontWeight: 600, color: 'var(--dsw-alias-label-primary)' } }, label != null ? label : (percent != null ? percent + '%' : '—'))
|
|
84
83
|
)
|
|
@@ -367,7 +366,7 @@ export function factory(require) {
|
|
|
367
366
|
)
|
|
368
367
|
),
|
|
369
368
|
react.createElement('td', { style: cellStyle },
|
|
370
|
-
react.createElement(UsageCircle, { percent: pct, label: pct != null ? pct + '%' : (usageRow && usageRow.ok && usageRow.planUsage != null ? String(usageRow.planUsage) : '—') })
|
|
369
|
+
react.createElement(UsageCircle, { percent: pct, label: pct != null ? pct + '%' : (usageRow && usageRow.ok && usageRow.planUsage != null ? String(usageRow.planUsage) : '—'), onClick: refresh })
|
|
371
370
|
),
|
|
372
371
|
react.createElement('td', { style: Object.assign({}, cellStyle, { color: 'var(--dsw-alias-label-tertiary)', whiteSpace: 'nowrap' }) }, formatDate(key.savedAt)),
|
|
373
372
|
react.createElement('td', { style: cellStyle },
|
|
@@ -415,7 +414,6 @@ export function factory(require) {
|
|
|
415
414
|
),
|
|
416
415
|
react.createElement('div', { style: { display: 'flex', gap: 8, alignItems: 'center', flexWrap: 'wrap' } },
|
|
417
416
|
react.createElement('button', { type: 'button', style: btn, onClick: () => setAdds((current) => [...current, { id: 'add-' + Date.now() + '-' + Math.random().toString(36).slice(2, 7), value: '' }]), disabled: busy }, '+ Add key'),
|
|
418
|
-
react.createElement('button', { type: 'button', style: btn, onClick: refresh, disabled: busy }, 'Refresh usage')
|
|
419
417
|
),
|
|
420
418
|
react.createElement('div', { style: { display: 'flex', flexDirection: 'column', gap: 6 } },
|
|
421
419
|
react.createElement('div', { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
|
|
@@ -429,7 +427,7 @@ export function factory(require) {
|
|
|
429
427
|
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))
|
|
430
428
|
),
|
|
431
429
|
react.createElement('p', { style: { margin: 0, fontSize: 12, color: 'var(--dsw-alias-label-tertiary)' } },
|
|
432
|
-
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected
|
|
430
|
+
(STRATEGIES.find((option) => option.id === strategy) || STRATEGIES[0]).hint + ' Saved immediately when selected.'
|
|
433
431
|
)
|
|
434
432
|
),
|
|
435
433
|
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()
|
|
@@ -422,9 +440,9 @@ function applyBackend(ctx) {
|
|
|
422
440
|
const perKey = []
|
|
423
441
|
for (const key of keys) {
|
|
424
442
|
try {
|
|
425
|
-
const usage = await
|
|
443
|
+
const usage = await fetchUsageDetailsFor(key)
|
|
426
444
|
perKey.push(usage !== null
|
|
427
|
-
? { ok: true, usage
|
|
445
|
+
? { ok: true, ...usage }
|
|
428
446
|
: { ok: false, error: 'usage unavailable' })
|
|
429
447
|
} catch (error) {
|
|
430
448
|
perKey.push({ ok: false, error: String(error && error.message ? error.message : error) })
|
|
@@ -438,8 +456,8 @@ function applyBackend(ctx) {
|
|
|
438
456
|
keys: keys.length,
|
|
439
457
|
okKeys: okRows.length,
|
|
440
458
|
usage: okRows.reduce((sum, row) => sum + (row.usage || 0), 0),
|
|
441
|
-
planUsage:
|
|
442
|
-
planLimit: null,
|
|
459
|
+
planUsage: okRows.reduce((sum, row) => sum + (row.planUsage || 0), 0),
|
|
460
|
+
planLimit: okRows.every((row) => row.planLimit !== null) ? okRows.reduce((sum, row) => sum + row.planLimit, 0) : null,
|
|
443
461
|
},
|
|
444
462
|
})
|
|
445
463
|
} catch (error) {
|