@jeffusion/bungee-core 5.9.0 → 5.11.0
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 +31348 -17337
- package/dist/plugins/ai-transformer/index.js.map +2 -2
- package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
- package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
- package/dist/plugins/chatgpt-oauth/control.js +513 -1
- package/dist/plugins/chatgpt-oauth/control.js.map +12 -4
- package/dist/plugins/chatgpt-oauth/index.js +511 -4
- package/dist/plugins/chatgpt-oauth/index.js.map +13 -5
- package/dist/plugins/chatgpt-oauth/manifest.json +19 -0
- package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
- package/dist/plugins/key-access/control.js.map +1 -1
- package/dist/plugins/key-access/index.js.map +3 -3
- package/dist/plugins/key-access/ingress.js.map +1 -1
- package/dist/plugins/key-rate-limit/index.js.map +2 -2
- package/dist/plugins/local-accounts/control.js +68 -18
- package/dist/plugins/local-accounts/control.js.map +4 -4
- package/dist/plugins/local-accounts/index.js.map +2 -2
- package/dist/plugins/local-accounts/manifest.json +48 -2
- package/dist/plugins/local-accounts/ui/Settings.svelte +73 -1
- package/dist/plugins/model-mapping/control.js +72 -17741
- package/dist/plugins/model-mapping/control.js.map +6 -58
- package/dist/plugins/model-mapping/index.js +32 -17433
- package/dist/plugins/model-mapping/index.js.map +6 -58
- package/dist/plugins/model-mapping/manifest.json +30 -14
- package/dist/plugins/models-dev/control.js +1042 -0
- package/dist/plugins/models-dev/control.js.map +16 -0
- package/dist/plugins/models-dev/index.js +15418 -0
- package/dist/plugins/models-dev/index.js.map +134 -0
- package/dist/plugins/models-dev/manifest.json +199 -0
- package/dist/plugins/models-dev/ui/ModelsDevSettings.svelte +120 -0
- package/dist/plugins/openai-messages-to-chat/index.js.map +2 -2
- package/dist/plugins/signature-repair/index.js.map +2 -2
- package/dist/plugins/token-budget/control.js +524 -9
- package/dist/plugins/token-budget/control.js.map +12 -4
- package/dist/plugins/token-budget/index.js +519 -12
- package/dist/plugins/token-budget/index.js.map +13 -6
- package/dist/plugins/token-budget/manifest.json +16 -2
- package/dist/plugins/token-metering/index.js +93 -2
- package/dist/plugins/token-metering/index.js.map +12 -6
- package/dist/plugins/token-stats/control.js +174 -312
- package/dist/plugins/token-stats/control.js.map +7 -7
- package/dist/plugins/token-stats/index.js +283 -486
- package/dist/plugins/token-stats/index.js.map +16 -12
- package/dist/plugins/token-stats/manifest.json +99 -12
- package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +76 -0
- package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +87 -0
- package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +136 -80
- package/dist/plugins/token-stats/ui/client-model-search.test.ts +58 -0
- package/dist/plugins/token-stats/ui/client-model-search.ts +16 -0
- package/dist/plugins/token-stats/ui/model-search.ts +45 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.test.ts +114 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.ts +17 -0
- package/package.json +2 -2
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "models-dev",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"schemaVersion": 2,
|
|
5
|
+
"artifactKind": "runtime-plugin",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"capabilities": [
|
|
8
|
+
"hooks",
|
|
9
|
+
"api",
|
|
10
|
+
"dynamicRuntimeLoad",
|
|
11
|
+
"controlPlane",
|
|
12
|
+
"nativeWidgetsStatic"
|
|
13
|
+
],
|
|
14
|
+
"uiExtensionMode": "native-static",
|
|
15
|
+
"engines": {
|
|
16
|
+
"bungee": "^5.0.0"
|
|
17
|
+
},
|
|
18
|
+
"runtimeScope": "global",
|
|
19
|
+
"control": {
|
|
20
|
+
"entry": "control.js",
|
|
21
|
+
"rpc": []
|
|
22
|
+
},
|
|
23
|
+
"builtin": true,
|
|
24
|
+
"author": "Bungee Team",
|
|
25
|
+
"ui": {
|
|
26
|
+
"components": [
|
|
27
|
+
{
|
|
28
|
+
"name": "ModelsDevSettings",
|
|
29
|
+
"entry": "ui/ModelsDevSettings.svelte"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"services": {
|
|
34
|
+
"provides": [
|
|
35
|
+
{
|
|
36
|
+
"id": "models-dev.catalog.v1",
|
|
37
|
+
"version": 1,
|
|
38
|
+
"process": "control",
|
|
39
|
+
"kind": "local"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "models-dev.catalog.snapshot.v1",
|
|
43
|
+
"version": 1,
|
|
44
|
+
"process": "control",
|
|
45
|
+
"kind": "snapshot"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "models-dev.catalog.v1",
|
|
49
|
+
"version": 1,
|
|
50
|
+
"process": "worker",
|
|
51
|
+
"kind": "local"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"consumes": [
|
|
55
|
+
{
|
|
56
|
+
"id": "models-dev.catalog.snapshot.v1",
|
|
57
|
+
"version": 1,
|
|
58
|
+
"process": "worker",
|
|
59
|
+
"plugin": "models-dev",
|
|
60
|
+
"kind": "snapshot"
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
"contributes": {
|
|
65
|
+
"api": [
|
|
66
|
+
{
|
|
67
|
+
"path": "/catalog/status",
|
|
68
|
+
"methods": [
|
|
69
|
+
"GET"
|
|
70
|
+
],
|
|
71
|
+
"handler": "getCatalogStatus",
|
|
72
|
+
"execution": "control",
|
|
73
|
+
"capability": "config.read"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"path": "/catalog/providers",
|
|
77
|
+
"methods": [
|
|
78
|
+
"GET"
|
|
79
|
+
],
|
|
80
|
+
"handler": "getCatalogProviders",
|
|
81
|
+
"execution": "control",
|
|
82
|
+
"capability": "config.read"
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"path": "/catalog/models",
|
|
86
|
+
"methods": [
|
|
87
|
+
"GET"
|
|
88
|
+
],
|
|
89
|
+
"handler": "getCatalogModels",
|
|
90
|
+
"execution": "control",
|
|
91
|
+
"capability": "config.read"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"path": "/catalog/settings",
|
|
95
|
+
"methods": [
|
|
96
|
+
"PUT"
|
|
97
|
+
],
|
|
98
|
+
"handler": "configureCatalog",
|
|
99
|
+
"execution": "control",
|
|
100
|
+
"capability": "config.write"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"path": "/catalog/refresh",
|
|
104
|
+
"methods": [
|
|
105
|
+
"POST"
|
|
106
|
+
],
|
|
107
|
+
"handler": "refreshCatalog",
|
|
108
|
+
"execution": "control",
|
|
109
|
+
"capability": "config.write"
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"settings": "/catalog/status",
|
|
113
|
+
"nativeSettingsComponent": "ModelsDevSettings"
|
|
114
|
+
},
|
|
115
|
+
"metadata": {
|
|
116
|
+
"name": "metadata.name",
|
|
117
|
+
"description": "plugin.description",
|
|
118
|
+
"icon": "cloud_download"
|
|
119
|
+
},
|
|
120
|
+
"configSchema": [],
|
|
121
|
+
"translations": {
|
|
122
|
+
"en": {
|
|
123
|
+
"metadata.name": "Models.dev Catalog",
|
|
124
|
+
"plugin.description": "Models and prices from models.dev for model selection and cost estimates",
|
|
125
|
+
"settings.title": "Catalog settings",
|
|
126
|
+
"settings.description": "Manage the shared models.dev catalog used for model choices and price estimates.",
|
|
127
|
+
"settings.autoRefresh": "Automatic refresh",
|
|
128
|
+
"settings.interval": "Refresh interval (hours)",
|
|
129
|
+
"settings.timeout": "Download timeout (seconds)",
|
|
130
|
+
"settings.increase": "Increase",
|
|
131
|
+
"settings.decrease": "Decrease",
|
|
132
|
+
"settings.save": "Save settings",
|
|
133
|
+
"settings.saving": "Saving",
|
|
134
|
+
"settings.saved": "Settings saved",
|
|
135
|
+
"settings.refresh": "Refresh now",
|
|
136
|
+
"settings.refreshing": "Refreshing",
|
|
137
|
+
"settings.catalog": "Model catalog",
|
|
138
|
+
"settings.state": "Status",
|
|
139
|
+
"settings.version": "Version",
|
|
140
|
+
"settings.lastSuccess": "Fetched at",
|
|
141
|
+
"settings.nextRefresh": "Next automatic refresh",
|
|
142
|
+
"settings.modelCount": "Models loaded",
|
|
143
|
+
"settings.providerCount": "Providers",
|
|
144
|
+
"settings.ready": "Available",
|
|
145
|
+
"settings.empty": "Not loaded yet",
|
|
146
|
+
"settings.stale": "Using last available catalog",
|
|
147
|
+
"settings.failed": "Unavailable",
|
|
148
|
+
"settings.never": "No record yet",
|
|
149
|
+
"settings.disabled": "Disabled",
|
|
150
|
+
"settings.error": "Operation failed. Please try again.",
|
|
151
|
+
"settings.invalid": "Enter whole numbers: 1–24 hours for the interval and 5–120 seconds for the timeout.",
|
|
152
|
+
"settings.failure": "Refresh failed. The last valid catalog is retained.",
|
|
153
|
+
"settings.timeoutError": "Download timed out",
|
|
154
|
+
"settings.networkError": "Network or source error",
|
|
155
|
+
"settings.invalid_catalogError": "Invalid catalog response",
|
|
156
|
+
"settings.storageError": "Unable to save the catalog",
|
|
157
|
+
"settings.snapshotError": "Unable to update the catalog",
|
|
158
|
+
"settings.retry": "Retry"
|
|
159
|
+
},
|
|
160
|
+
"zh-CN": {
|
|
161
|
+
"metadata.name": "models.dev 目录",
|
|
162
|
+
"plugin.description": "从 models.dev 获取模型目录,供模型选择和价格估算使用",
|
|
163
|
+
"settings.title": "目录设置",
|
|
164
|
+
"settings.description": "管理用于模型选择和价格估算的 models.dev 共用目录。",
|
|
165
|
+
"settings.autoRefresh": "自动刷新",
|
|
166
|
+
"settings.interval": "刷新间隔(小时)",
|
|
167
|
+
"settings.timeout": "下载超时(秒)",
|
|
168
|
+
"settings.increase": "增加",
|
|
169
|
+
"settings.decrease": "减少",
|
|
170
|
+
"settings.save": "保存设置",
|
|
171
|
+
"settings.saving": "正在保存",
|
|
172
|
+
"settings.saved": "设置已保存",
|
|
173
|
+
"settings.refresh": "立即刷新",
|
|
174
|
+
"settings.refreshing": "正在刷新",
|
|
175
|
+
"settings.catalog": "模型目录",
|
|
176
|
+
"settings.state": "状态",
|
|
177
|
+
"settings.version": "版本",
|
|
178
|
+
"settings.lastSuccess": "抓取时间",
|
|
179
|
+
"settings.nextRefresh": "下次自动刷新",
|
|
180
|
+
"settings.modelCount": "已加载模型",
|
|
181
|
+
"settings.providerCount": "提供商",
|
|
182
|
+
"settings.ready": "可用",
|
|
183
|
+
"settings.empty": "尚未加载",
|
|
184
|
+
"settings.stale": "使用上一次有效目录",
|
|
185
|
+
"settings.failed": "不可用",
|
|
186
|
+
"settings.never": "尚无记录",
|
|
187
|
+
"settings.disabled": "已关闭",
|
|
188
|
+
"settings.error": "操作失败,请稍后重试。",
|
|
189
|
+
"settings.invalid": "请输入整数:刷新间隔为 1–24 小时,超时时间为 5–120 秒。",
|
|
190
|
+
"settings.failure": "刷新失败,保留上一次有效目录。",
|
|
191
|
+
"settings.timeoutError": "下载超时",
|
|
192
|
+
"settings.networkError": "网络或数据源错误",
|
|
193
|
+
"settings.invalid_catalogError": "目录内容无效",
|
|
194
|
+
"settings.storageError": "目录保存失败",
|
|
195
|
+
"settings.snapshotError": "目录更新失败",
|
|
196
|
+
"settings.retry": "重试"
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { isLoading } from 'svelte-i18n';
|
|
4
|
+
import { getPluginText } from '$utils/plugin-i18n';
|
|
5
|
+
import { PanelCard, IndustrialToggle, LoadingIndicator } from '$components/industrial';
|
|
6
|
+
import { Button } from '$components/ui/button';
|
|
7
|
+
import { NumberInput } from '$components/ui/number-input';
|
|
8
|
+
import { Label } from '$components/ui/label';
|
|
9
|
+
import { requestPluginControl, _ } from '@bungee/plugin-sdk';
|
|
10
|
+
|
|
11
|
+
interface CatalogStatus {
|
|
12
|
+
state: 'empty' | 'ready' | 'stale' | 'failed'; version: number | null;
|
|
13
|
+
settings: { autoRefresh: boolean; intervalHours: number; timeoutSeconds: number };
|
|
14
|
+
refreshing: boolean; lastAttemptAt: number | null; lastSuccessAt: number | null;
|
|
15
|
+
nextRefreshAt: number | null; lastError: string | null; modelCount: number; providerCount: number;
|
|
16
|
+
}
|
|
17
|
+
let status = $state<CatalogStatus | null>(null);
|
|
18
|
+
let autoRefresh = $state(true);
|
|
19
|
+
let intervalHours = $state<number | undefined>(24);
|
|
20
|
+
let timeoutSeconds = $state<number | undefined>(15);
|
|
21
|
+
let loading = $state(true);
|
|
22
|
+
let busy = $state(false);
|
|
23
|
+
let saved = $state(false);
|
|
24
|
+
let error = $state('');
|
|
25
|
+
let loadError = $state(false);
|
|
26
|
+
let alive = false;
|
|
27
|
+
let polling = false;
|
|
28
|
+
let generation = 0;
|
|
29
|
+
const controller = new AbortController();
|
|
30
|
+
const t = (key: string) => $isLoading ? '' : getPluginText(`settings.${key}`, 'models-dev', (id, options) => $_(id, options));
|
|
31
|
+
const date = (value: number | null) => value === null ? t('never') : new Date(value).toLocaleString();
|
|
32
|
+
|
|
33
|
+
async function load(initial = false) {
|
|
34
|
+
if (polling || busy) return;
|
|
35
|
+
polling = true;
|
|
36
|
+
const version = generation;
|
|
37
|
+
try {
|
|
38
|
+
const result = await requestPluginControl<CatalogStatus>('models-dev', '/catalog/status', 'GET', undefined, controller.signal);
|
|
39
|
+
if (!alive || version !== generation) return;
|
|
40
|
+
// A poll started before a mutation must not overwrite its newer response.
|
|
41
|
+
if (!busy) status = result;
|
|
42
|
+
if (initial) {
|
|
43
|
+
autoRefresh = result.settings.autoRefresh;
|
|
44
|
+
intervalHours = result.settings.intervalHours;
|
|
45
|
+
timeoutSeconds = result.settings.timeoutSeconds;
|
|
46
|
+
}
|
|
47
|
+
loadError = false;
|
|
48
|
+
} catch { if (alive && version === generation) loadError = true; }
|
|
49
|
+
finally { if (alive) loading = false; polling = false; }
|
|
50
|
+
}
|
|
51
|
+
async function save() {
|
|
52
|
+
if (busy || !status) return;
|
|
53
|
+
saved = false;
|
|
54
|
+
const hours = Number(intervalHours), timeout = Number(timeoutSeconds);
|
|
55
|
+
if (intervalHours === undefined || timeoutSeconds === undefined || !Number.isInteger(hours) || hours < 1 || hours > 24 || !Number.isInteger(timeout) || timeout < 5 || timeout > 120) {
|
|
56
|
+
error = 'invalid'; return;
|
|
57
|
+
}
|
|
58
|
+
generation++; busy = true; error = '';
|
|
59
|
+
try {
|
|
60
|
+
const result = await requestPluginControl<CatalogStatus>('models-dev', '/catalog/settings', 'PUT',
|
|
61
|
+
{ autoRefresh, intervalHours: hours, timeoutSeconds: timeout }, controller.signal);
|
|
62
|
+
if (alive) { status = result; saved = true; }
|
|
63
|
+
} catch { if (alive) error = 'error'; }
|
|
64
|
+
finally { if (alive) busy = false; }
|
|
65
|
+
}
|
|
66
|
+
async function refresh() {
|
|
67
|
+
if (busy || status?.refreshing) return;
|
|
68
|
+
generation++; busy = true; error = '';
|
|
69
|
+
try {
|
|
70
|
+
const result = await requestPluginControl<CatalogStatus>('models-dev', '/catalog/refresh', 'POST', undefined, controller.signal);
|
|
71
|
+
if (alive) status = result;
|
|
72
|
+
} catch { if (alive) error = 'error'; }
|
|
73
|
+
finally { if (alive) busy = false; }
|
|
74
|
+
}
|
|
75
|
+
onMount(() => {
|
|
76
|
+
alive = true; void load(true);
|
|
77
|
+
const timer = setInterval(() => void load(), 1000);
|
|
78
|
+
return () => { alive = false; controller.abort(); clearInterval(timer); };
|
|
79
|
+
});
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<div class="space-y-6" data-testid="models-dev-settings">
|
|
83
|
+
<p class="text-sm text-zinc-400">{t('description')}</p>
|
|
84
|
+
{#if error || loadError}<p role="alert" class="text-sm text-red-400">{t(error || 'error')}</p>{/if}
|
|
85
|
+
{#if loading}<LoadingIndicator />
|
|
86
|
+
{:else if status}
|
|
87
|
+
<PanelCard title={t('title')}>
|
|
88
|
+
<form class="space-y-5" onsubmit={(event) => { event.preventDefault(); void save(); }}>
|
|
89
|
+
<div class="flex items-center justify-between gap-4 border-b border-carbon-600 pb-4">
|
|
90
|
+
<Label for="models-dev-auto">{t('autoRefresh')}</Label>
|
|
91
|
+
<IndustrialToggle id="models-dev-auto" label={t('autoRefresh')} bind:checked={autoRefresh} disabled={busy} />
|
|
92
|
+
</div>
|
|
93
|
+
<div class="grid gap-5 sm:grid-cols-2">
|
|
94
|
+
<div class="space-y-2"><Label for="models-dev-interval">{t('interval')}</Label>
|
|
95
|
+
<NumberInput id="models-dev-interval" data-testid="models-dev-interval" min={1} max={24} bind:value={intervalHours} disabled={busy} required
|
|
96
|
+
increaseLabel={`${t('increase')} ${t('interval')}`} decreaseLabel={`${t('decrease')} ${t('interval')}`} invalidMessage={t('invalid')} /></div>
|
|
97
|
+
<div class="space-y-2"><Label for="models-dev-timeout">{t('timeout')}</Label>
|
|
98
|
+
<NumberInput id="models-dev-timeout" data-testid="models-dev-timeout" min={5} max={120} bind:value={timeoutSeconds} disabled={busy} required
|
|
99
|
+
increaseLabel={`${t('increase')} ${t('timeout')}`} decreaseLabel={`${t('decrease')} ${t('timeout')}`} invalidMessage={t('invalid')} /></div>
|
|
100
|
+
</div>
|
|
101
|
+
<div class="flex items-center gap-4">
|
|
102
|
+
<Button type="submit" data-testid="models-dev-save" disabled={busy} aria-busy={busy}>{t(busy ? 'saving' : 'save')}</Button>
|
|
103
|
+
{#if saved}<span role="status" class="text-sm text-emerald-400">{t('saved')}</span>{/if}
|
|
104
|
+
</div>
|
|
105
|
+
</form>
|
|
106
|
+
</PanelCard>
|
|
107
|
+
<PanelCard title={t('catalog')}>
|
|
108
|
+
<div slot="actions"><Button variant="outline" data-testid="models-dev-refresh" disabled={busy || status.refreshing} aria-busy={status.refreshing} onclick={() => void refresh()}>{t(status.refreshing ? 'refreshing' : 'refresh')}</Button></div>
|
|
109
|
+
<dl class="grid gap-5 text-sm sm:grid-cols-2 lg:grid-cols-3">
|
|
110
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('state')}</dt><dd data-testid="models-dev-state">{t(status.state)}</dd></div>
|
|
111
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('version')}</dt><dd data-testid="models-dev-version">{status.version ?? t('never')}</dd></div>
|
|
112
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('lastSuccess')}</dt><dd data-testid="models-dev-fetched-at">{date(status.lastSuccessAt)}</dd></div>
|
|
113
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('modelCount')}</dt><dd>{status.modelCount}</dd></div>
|
|
114
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('providerCount')}</dt><dd>{status.providerCount}</dd></div>
|
|
115
|
+
<div class="space-y-2"><dt class="text-zinc-400">{t('nextRefresh')}</dt><dd>{status.nextRefreshAt === null ? t(status.settings.autoRefresh ? 'never' : 'disabled') : date(status.nextRefreshAt)}</dd></div>
|
|
116
|
+
</dl>
|
|
117
|
+
{#if status.lastError}<p role="status" data-testid="models-dev-error" class="mt-5 border-l-2 border-amber-400 pl-3 text-sm text-amber-400">{t(`${status.lastError}Error`)} · {t('failure')}</p>{/if}
|
|
118
|
+
</PanelCard>
|
|
119
|
+
{:else}<Button variant="outline" onclick={() => void load(true)}>{t('retry')}</Button>{/if}
|
|
120
|
+
</div>
|