@jeffusion/bungee-core 5.15.0 → 5.15.1
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/dist/main.js +39 -39
- package/dist/plugins/key-access/manifest.json +9 -2
- package/dist/plugins/local-accounts/manifest.json +13 -7
- package/dist/plugins/token-budget/manifest.json +11 -4
- package/dist/plugins/token-budget/ui/KeyPolicy.svelte +1 -1
- package/dist/plugins/token-stats/manifest.json +1 -5
- package/dist/plugins/token-stats/ui/TokenStatsChart.svelte +5 -2
- package/dist/plugins/token-stats/ui/TokenStatsMetric.svelte +11 -15
- package/dist/plugins/token-stats/ui/TokenStatsPage.svelte +0 -3
- package/package.json +2 -2
|
@@ -107,8 +107,15 @@
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
],
|
|
110
|
-
"
|
|
111
|
-
|
|
110
|
+
"navigation": [
|
|
111
|
+
{
|
|
112
|
+
"label": "metadata.name",
|
|
113
|
+
"path": "/settings",
|
|
114
|
+
"component": "KeyAccessKeyPolicy",
|
|
115
|
+
"icon": "shield",
|
|
116
|
+
"target": "header"
|
|
117
|
+
}
|
|
118
|
+
]
|
|
112
119
|
},
|
|
113
120
|
"metadata": {
|
|
114
121
|
"name": "metadata.name",
|
|
@@ -76,9 +76,15 @@
|
|
|
76
76
|
"capability": "self.password"
|
|
77
77
|
}
|
|
78
78
|
],
|
|
79
|
-
"navigation": [
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
"navigation": [
|
|
80
|
+
{
|
|
81
|
+
"label": "metadata.name",
|
|
82
|
+
"path": "/settings",
|
|
83
|
+
"component": "LocalAccountsSettings",
|
|
84
|
+
"icon": "manage_accounts",
|
|
85
|
+
"target": "header"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
82
88
|
},
|
|
83
89
|
"metadata": {
|
|
84
90
|
"name": "metadata.name",
|
|
@@ -88,10 +94,10 @@
|
|
|
88
94
|
"configSchema": [],
|
|
89
95
|
"translations": {
|
|
90
96
|
"zh-CN": {
|
|
91
|
-
"metadata.name": "
|
|
97
|
+
"metadata.name": "认证管理",
|
|
92
98
|
"metadata.description": "可选的单管理员账号密码认证",
|
|
93
99
|
"login.title": "账号登录",
|
|
94
|
-
"login.description": "
|
|
100
|
+
"login.description": "使用认证管理插件中设置的唯一管理员账号。",
|
|
95
101
|
"login.username": "账号",
|
|
96
102
|
"login.password": "密码",
|
|
97
103
|
"login.busy": "正在建立登录会话…",
|
|
@@ -122,7 +128,7 @@
|
|
|
122
128
|
"settings.accountTag": "账号",
|
|
123
129
|
"settings.passwordTag": "密码",
|
|
124
130
|
"settings.loading": "正在读取管理员账号",
|
|
125
|
-
"settings.accountDescription": "
|
|
131
|
+
"settings.accountDescription": "认证管理使用此唯一管理员账号。停用插件后恢复匿名管理访问。",
|
|
126
132
|
"settings.passwordTitle": "修改登录密码",
|
|
127
133
|
"settings.passwordDescription": "修改后当前登录会话失效,需要重新登录。",
|
|
128
134
|
"settings.currentPassword": "当前密码",
|
|
@@ -151,7 +157,7 @@
|
|
|
151
157
|
"session.reload": "重新读取"
|
|
152
158
|
},
|
|
153
159
|
"en": {
|
|
154
|
-
"metadata.name": "Management
|
|
160
|
+
"metadata.name": "Authentication Management",
|
|
155
161
|
"metadata.description": "Optional username and password authentication for a single administrator",
|
|
156
162
|
"login.title": "Account sign-in",
|
|
157
163
|
"login.description": "Use the sole administrator account configured in the management authentication plugin.",
|
|
@@ -91,8 +91,15 @@
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
],
|
|
94
|
-
"
|
|
95
|
-
|
|
94
|
+
"navigation": [
|
|
95
|
+
{
|
|
96
|
+
"label": "metadata.name",
|
|
97
|
+
"path": "/settings",
|
|
98
|
+
"component": "TokenBudgetKeyPolicy",
|
|
99
|
+
"icon": "shield",
|
|
100
|
+
"target": "header"
|
|
101
|
+
}
|
|
102
|
+
]
|
|
96
103
|
},
|
|
97
104
|
"metadata": {
|
|
98
105
|
"name": "metadata.name",
|
|
@@ -191,7 +198,7 @@
|
|
|
191
198
|
"status.exhausted": "Budget exhausted"
|
|
192
199
|
},
|
|
193
200
|
"zh-CN": {
|
|
194
|
-
"metadata.name": "Token
|
|
201
|
+
"metadata.name": "Token预算",
|
|
195
202
|
"plugin.description": "按 Key 设置 UTC 每日、每周、每月或累计 Token 与美元预算,并查看计量账本。",
|
|
196
203
|
"ui.key": "API Key",
|
|
197
204
|
"ui.search": "搜索 API Key",
|
|
@@ -218,7 +225,7 @@
|
|
|
218
225
|
"status.unlimited": "不限制",
|
|
219
226
|
"reason.notReady": "插件尚未就绪,暂不可修改。",
|
|
220
227
|
"ui.title": "API Key 预算",
|
|
221
|
-
"ui.tag": "Token
|
|
228
|
+
"ui.tag": "Token预算",
|
|
222
229
|
"ui.description": "为每个 API Key 设置 Token 或 USD 预算,按每日、每周、每月或累计限制。未配置的 Key 不受预算限制。",
|
|
223
230
|
"ui.behavior": "额度用尽后拒绝新请求;已接纳请求继续,最终用量可能超过额度。",
|
|
224
231
|
"ui.loading": "正在读取预算",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
<div class="flex flex-wrap items-center gap-3">
|
|
83
83
|
<label class="flex-1 min-w-0"><span class="sr-only">{t('ui.search')}</span><Input placeholder={t('ui.searchPlaceholder')} bind:value={search} /></label>
|
|
84
84
|
<button class="nx-btn-ghost" disabled={loading || saving} onclick={refresh}>{t('ui.refresh')}</button>
|
|
85
|
-
<a class="nx-btn-ghost" href="/#/
|
|
85
|
+
<a class="nx-btn-ghost" href="/#/extensions/key-access/settings">{t('ui.manageKeys')}</a>
|
|
86
86
|
</div>
|
|
87
87
|
</div>
|
|
88
88
|
{#if feedback}<p role="status" class="text-sm text-emerald-400 mb-3">{t(feedback)}</p>{/if}
|
|
@@ -178,8 +178,6 @@
|
|
|
178
178
|
"ui.input": "Input",
|
|
179
179
|
"ui.output": "Output",
|
|
180
180
|
"ui.estimatedCostUsd": "Est. cost · USD",
|
|
181
|
-
"ui.includesEstimate": "incl. estimate",
|
|
182
|
-
"ui.reportingIncomplete": "Some usage records were lost. Reported totals may be incomplete.",
|
|
183
181
|
"ui.unknownValue": "Unknown",
|
|
184
182
|
"ui.unknownModel": "Unknown model",
|
|
185
183
|
"ui.otherModels": "Other",
|
|
@@ -293,8 +291,6 @@
|
|
|
293
291
|
"ui.input": "输入",
|
|
294
292
|
"ui.output": "输出",
|
|
295
293
|
"ui.estimatedCostUsd": "费用估算 · USD",
|
|
296
|
-
"ui.includesEstimate": "含估算",
|
|
297
|
-
"ui.reportingIncomplete": "部分用量记录丢失,统计总量可能不完整。",
|
|
298
294
|
"ui.unknownValue": "未知",
|
|
299
295
|
"ui.unknownModel": "未知模型",
|
|
300
296
|
"ui.otherModels": "其他",
|
|
@@ -353,7 +349,7 @@
|
|
|
353
349
|
"settings.mappingUnavailable": "目标模型已不在价格目录中,费用将显示未知;请选择其他模型或移除此映射。",
|
|
354
350
|
"widgets.overview.title": "Token 概览",
|
|
355
351
|
"widgets.time.title": "Token 趋势",
|
|
356
|
-
"page.title": "Token
|
|
352
|
+
"page.title": "Token统计",
|
|
357
353
|
"page.viewModels": "查看模型统计",
|
|
358
354
|
"ui.refresh": "刷新",
|
|
359
355
|
"ui.previousInterval": "较上个{interval}",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
$effect(() => {
|
|
24
24
|
const report = onHeaderChange;
|
|
25
25
|
const header = { summary: selectedRange, refresh: { label: t('ui.refresh'), busy: state.busy,
|
|
26
|
-
disabled: !resource, run: () => { void resource?.refresh(); } } };
|
|
26
|
+
disabled: !resource, run: () => { void resource?.refresh(); } }, actions: headerActions };
|
|
27
27
|
untrack(() => report?.(header));
|
|
28
28
|
});
|
|
29
29
|
onMount(() => {
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
});
|
|
33
33
|
</script>
|
|
34
34
|
|
|
35
|
+
{#snippet headerActions()}
|
|
36
|
+
<a href={`/#/extensions/${pluginName}/statistics`} class="inline-flex shrink-0 items-center gap-1 whitespace-nowrap text-[11px] text-zinc-400 hover:text-nexus-300 hover:underline">{t('page.viewModels')} <span>→</span></a>
|
|
37
|
+
{/snippet}
|
|
38
|
+
|
|
35
39
|
<div class="flex h-full min-h-0 flex-col gap-2" data-testid="plugin-widget-token-stats">
|
|
36
40
|
{#if state.error}<p role="alert" class="shrink-0 text-xs text-red-300">{t('ui.loadFailed')}</p>{/if}
|
|
37
41
|
{#if state.busy && !state.data}
|
|
@@ -45,5 +49,4 @@
|
|
|
45
49
|
<div class="min-h-0 flex-1"><UsageTimeChart stats={state.data} range={selectedRange} refreshedAt={state.refreshedAt} {pluginName} /></div>
|
|
46
50
|
{/if}
|
|
47
51
|
{/if}
|
|
48
|
-
<a href={`/#/extensions/${pluginName}/statistics`} class="shrink-0 self-end text-[11px] text-zinc-400 hover:text-nexus-300 hover:underline">{t('page.viewModels')} →</a>
|
|
49
52
|
</div>
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
import { isLoading } from 'svelte-i18n';
|
|
4
4
|
import { _, formatCompactNumber, type TimeRange } from '@bungee/plugin-sdk';
|
|
5
5
|
import { getPluginText } from '$utils/plugin-i18n';
|
|
6
|
-
import { LoadingIndicator } from '$components/industrial';
|
|
7
6
|
import KpiTrendValue from '$components/industrial/KpiTrendValue.svelte';
|
|
8
7
|
import type { NativeWidgetHeaderChange } from '$components/native-widgets/widget-header';
|
|
9
|
-
import {
|
|
8
|
+
import { formatEstimatedUsd, formatTokenCount, usagePresentation } from './labels';
|
|
10
9
|
import { getStatsResource } from './stats';
|
|
11
10
|
import type { StatsState, StatsResource } from './stats-resource';
|
|
12
11
|
import { overviewTrends } from './overview-trends';
|
|
@@ -40,6 +39,11 @@
|
|
|
40
39
|
</script>
|
|
41
40
|
|
|
42
41
|
{#snippet trendFooter()}
|
|
42
|
+
{#if state.error}
|
|
43
|
+
<p role="alert" class="text-xs text-red-300">{t('ui.loadFailed')}</p>
|
|
44
|
+
{:else if usage?.state === 'empty'}
|
|
45
|
+
<p class="text-[10px] text-zinc-400" data-testid="token-stats-empty">{t('ui.noData')}</p>
|
|
46
|
+
{:else}
|
|
43
47
|
<div class="overview-trends w-full" data-testid="token-stats-overview-trends">
|
|
44
48
|
{#each trends as item}
|
|
45
49
|
{@const value = item.isNew ? t('ui.newActivity') : item.percent == null ? '—' : `${item.percent >= 0 ? '+' : ''}${item.percent.toFixed(1)}%`}
|
|
@@ -50,14 +54,13 @@
|
|
|
50
54
|
</div>
|
|
51
55
|
{/each}
|
|
52
56
|
</div>
|
|
57
|
+
{/if}
|
|
53
58
|
{/snippet}
|
|
54
59
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
{
|
|
59
|
-
<p role="alert" class="text-xs text-red-300">{t('ui.loadFailed')}</p>
|
|
60
|
-
{:else}
|
|
60
|
+
<!-- Keep the same intrinsic metric geometry while requests are pending or fail.
|
|
61
|
+
Desktop GridStack derives its shared row height from this content. -->
|
|
62
|
+
<div class="kpi-metric-row w-full min-w-0" data-testid="token-stats-overview" aria-busy={state.busy}>
|
|
63
|
+
{#if state.busy && !state.data}<span role="status" class="sr-only">{t('ui.loading')}</span>{/if}
|
|
61
64
|
<div class="kpi-metric-row overview-metrics">
|
|
62
65
|
{#each ['input', 'output', 'cost'] as metric}
|
|
63
66
|
{@const fullValue = metric === 'cost' ? formatEstimatedUsd(state.data?.estimatedCostUsd)
|
|
@@ -69,16 +72,9 @@
|
|
|
69
72
|
<div class="min-w-0" data-testid={`token-stats-metric-${metric}`}>
|
|
70
73
|
<div class="nx-label mb-2">{t(metric === 'cost' ? 'ui.estimatedCostUsd' : `ui.${metric}`)}</div>
|
|
71
74
|
<div class="overview-value nx-metric text-zinc-50" title={fullValue} aria-label={fullValue}>{value}</div>
|
|
72
|
-
{#if metric !== 'cost' && state.data && (estimatedTokens(state.data, metric as 'input' | 'output') ?? 0) > 0}
|
|
73
|
-
<p class="mt-1 text-[10px] text-zinc-400">{t('ui.includesEstimate')}</p>
|
|
74
|
-
{/if}
|
|
75
75
|
</div>
|
|
76
76
|
{/each}
|
|
77
77
|
</div>
|
|
78
|
-
{#if state.data?.reportingIncomplete}<p role="status" class="mt-2 text-xs text-amber-300">{t('ui.reportingIncomplete')}</p>{/if}
|
|
79
|
-
{#if state.error}<p role="alert" class="mt-2 text-xs text-red-300">{t('ui.loadFailed')}</p>
|
|
80
|
-
{:else if usage?.state === 'empty'}<p class="mt-2 text-[10px] text-zinc-400" data-testid="token-stats-empty">{t('ui.noData')}</p>{/if}
|
|
81
|
-
{/if}
|
|
82
78
|
</div>
|
|
83
79
|
|
|
84
80
|
<style>
|
|
@@ -97,9 +97,6 @@
|
|
|
97
97
|
<span>{t('ui.loadFailed')}</span><Button variant="ghost" size="sm" onclick={refresh} disabled={busy}>{t('page.retry')}</Button>
|
|
98
98
|
</div>
|
|
99
99
|
{/if}
|
|
100
|
-
{#if models.data?.reportingIncomplete || time.data?.reportingIncomplete}
|
|
101
|
-
<p role="status" class="border-l-2 border-amber-500 px-3 py-2 text-xs text-amber-300">{t('ui.reportingIncomplete')}</p>
|
|
102
|
-
{/if}
|
|
103
100
|
{#if models.busy && !models.data}
|
|
104
101
|
<LoadingIndicator label={t('ui.loading')} height="sm" />
|
|
105
102
|
{:else if models.data}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jeffusion/bungee-core",
|
|
3
|
-
"version": "5.15.
|
|
3
|
+
"version": "5.15.1",
|
|
4
4
|
"description": "Bungee reverse proxy core engine",
|
|
5
5
|
"main": "./dist/main.js",
|
|
6
6
|
"types": "./dist/main.d.ts",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"test": "bun test"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@jeffusion/bungee-types": "^5.15.
|
|
15
|
+
"@jeffusion/bungee-types": "^5.15.1",
|
|
16
16
|
"@types/lodash-es": "^4.17.12",
|
|
17
17
|
"acorn": "^8.15.0",
|
|
18
18
|
"canonicalize": "3.0.0",
|