llm-simple-router 0.9.14 → 0.9.15
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/admin/proxy-enhancement.d.ts +0 -2
- package/dist/admin/proxy-enhancement.js +16 -24
- package/dist/admin/routes.js +1 -1
- package/dist/admin/settings-import-export.js +0 -3
- package/dist/core/registry.d.ts +0 -11
- package/dist/db/index.d.ts +0 -2
- package/dist/db/index.js +0 -1
- package/dist/index.js +0 -8
- package/dist/proxy/enhancement/index.d.ts +1 -4
- package/dist/proxy/enhancement/index.js +3 -3
- package/dist/proxy/handler/proxy-handler.js +15 -27
- package/dist/proxy/pipeline-snapshot.d.ts +0 -11
- package/dist/proxy/proxy-logging.d.ts +0 -7
- package/dist/proxy/proxy-logging.js +0 -22
- package/dist/proxy/routing/enhancement-config.d.ts +0 -1
- package/dist/proxy/routing/enhancement-config.js +0 -2
- package/dist/proxy/transport/transport-fn.d.ts +0 -1
- package/dist/proxy/transport/transport-fn.js +0 -13
- package/frontend-dist/assets/{CardContent-BTxpErx_.js → CardContent-Be6PJLTw.js} +1 -1
- package/frontend-dist/assets/{CardTitle-DuW6MHMC.js → CardTitle-CRJTZxQY.js} +1 -1
- package/frontend-dist/assets/{CascadingModelSelect-CAv9_cK6.js → CascadingModelSelect-BR8cT6D3.js} +1 -1
- package/frontend-dist/assets/{Checkbox-Bov0jC2d.js → Checkbox-CG6gSglN.js} +1 -1
- package/frontend-dist/assets/{CollapsibleContent-ignsLSmA.js → CollapsibleContent-PqKToOXJ.js} +1 -1
- package/frontend-dist/assets/{CollapsibleTrigger-K-O5aS5D.js → CollapsibleTrigger-54P86ben.js} +1 -1
- package/frontend-dist/assets/{Dashboard-Byh_loe7.js → Dashboard-BfQfZ9Kk.js} +1 -1
- package/frontend-dist/assets/{Input-DMYJg0mG.js → Input-m8uNSwlX.js} +1 -1
- package/frontend-dist/assets/{Label-Oc3EnENu.js → Label-B9qJOqmM.js} +1 -1
- package/frontend-dist/assets/{Login-CLYNuFun.js → Login-CaTB96MJ.js} +1 -1
- package/frontend-dist/assets/Logs-Cj1tfIqy.js +1 -0
- package/frontend-dist/assets/{MappingList-BDJ3PU77.js → MappingList-B50LdkcQ.js} +1 -1
- package/frontend-dist/assets/{ModelCard-DwWmKLT8.js → ModelCard-CkagDRjG.js} +1 -1
- package/frontend-dist/assets/{ModelMappings-B9Kgw2uZ.js → ModelMappings-CYY5WVkD.js} +1 -1
- package/frontend-dist/assets/Monitor-KiI_k5-9.js +1 -0
- package/frontend-dist/assets/Providers-B4ZZLVlo.js +1 -0
- package/frontend-dist/assets/ProxyEnhancement-DWMm3hWL.js +1 -0
- package/frontend-dist/assets/{QuickSetup-DYVI5orW.js → QuickSetup-Bq1fyl-e.js} +1 -1
- package/frontend-dist/assets/RetryRules-mPS_yjl6.js +1 -0
- package/frontend-dist/assets/RouterKeys-CoBoji2w.js +1 -0
- package/frontend-dist/assets/{RovingFocusItem-BzUY2gsB.js → RovingFocusItem-D3o2cZhf.js} +1 -1
- package/frontend-dist/assets/Schedules-B__xbmnO.js +1 -0
- package/frontend-dist/assets/{Settings-P4uUO9v9.js → Settings-BsB8tW2L.js} +1 -1
- package/frontend-dist/assets/{Setup-CXwlz44a.js → Setup-BBBPhjkS.js} +1 -1
- package/frontend-dist/assets/{Switch-BdEmKbpM.js → Switch-C0YcvC2_.js} +1 -1
- package/frontend-dist/assets/TooltipTrigger-CSSSfg9G.js +3 -0
- package/frontend-dist/assets/{VisuallyHiddenInput-CaWxiN_J.js → VisuallyHiddenInput-DbZDRHYC.js} +1 -1
- package/frontend-dist/assets/{button-tBshdyhO.js → button-63IAyx7P.js} +2 -2
- package/frontend-dist/assets/{copy--LcebZO_.js → copy-BhmcyrsA.js} +1 -1
- package/frontend-dist/assets/dialog-D-rFpYq1.js +1 -0
- package/frontend-dist/assets/index-CGtIhjOG.css +1 -0
- package/frontend-dist/assets/{index-DLWlImkm.js → index-DPqLrV5W.js} +1 -1
- package/frontend-dist/assets/proxyEnhancement-B7EOptuN.js +1 -0
- package/frontend-dist/assets/proxyEnhancement-DyutPimF.js +1 -0
- package/frontend-dist/assets/{trash-2-BUsG5SFN.js → trash-2-MCpMHHuO.js} +1 -1
- package/frontend-dist/assets/{useClipboard-DoV11ZLg.js → useClipboard-DROrGh3V.js} +1 -1
- package/frontend-dist/assets/{useLogRetention-_c8HObDe.js → useLogRetention-Dj2-JudQ.js} +1 -1
- package/frontend-dist/index.html +3 -3
- package/package.json +1 -1
- package/dist/db/session-states.d.ts +0 -40
- package/dist/db/session-states.js +0 -37
- package/dist/proxy/enhancement/directive-parser.d.ts +0 -24
- package/dist/proxy/enhancement/directive-parser.js +0 -141
- package/dist/proxy/enhancement/enhancement-handler.d.ts +0 -40
- package/dist/proxy/enhancement/enhancement-handler.js +0 -471
- package/dist/proxy/enhancement/response-cleaner.d.ts +0 -5
- package/dist/proxy/enhancement/response-cleaner.js +0 -82
- package/dist/proxy/patch/router-cleanup.d.ts +0 -13
- package/dist/proxy/patch/router-cleanup.js +0 -64
- package/dist/proxy/response-transform.d.ts +0 -7
- package/dist/proxy/response-transform.js +0 -28
- package/dist/proxy/routing/model-state.d.ts +0 -30
- package/dist/proxy/routing/model-state.js +0 -115
- package/frontend-dist/assets/Logs-DNDdoBjz.js +0 -1
- package/frontend-dist/assets/Monitor-BJeXYuVI.js +0 -1
- package/frontend-dist/assets/Providers-D_kpZeYw.js +0 -1
- package/frontend-dist/assets/ProxyEnhancement-CC8DiK4r.js +0 -5
- package/frontend-dist/assets/RetryRules-BYUok9Yi.js +0 -1
- package/frontend-dist/assets/RouterKeys-Byen_qRe.js +0 -1
- package/frontend-dist/assets/Schedules-B8GwTjC6.js +0 -1
- package/frontend-dist/assets/TableHeader-BwbPx6um.js +0 -1
- package/frontend-dist/assets/TooltipTrigger-C_zGJ_WM.js +0 -1
- package/frontend-dist/assets/UnifiedRequestDialog-BqPiKnUw.js +0 -3
- package/frontend-dist/assets/dialog-CFIfggFY.js +0 -1
- package/frontend-dist/assets/index-Cuaqp0bp.css +0 -1
- package/frontend-dist/assets/proxyEnhancement-Ce12tTE4.js +0 -1
- package/frontend-dist/assets/proxyEnhancement-DZAnOVgK.js +0 -1
- /package/frontend-dist/assets/{UnifiedRequestDialog-C4MTxb25.css → TooltipTrigger-C4MTxb25.css} +0 -0
- /package/frontend-dist/assets/{common-BpwAv-lj.js → common-B3qJKqtt.js} +0 -0
- /package/frontend-dist/assets/{common-D96jEq-h.js → common-Dks6EROG.js} +0 -0
- /package/frontend-dist/assets/{constants-CVHpKrRN.js → constants-yM0YwP2s.js} +0 -0
- /package/frontend-dist/assets/{dashboard-DzlE5uZS.js → dashboard-BDCzVaDH.js} +0 -0
- /package/frontend-dist/assets/{dashboard-DVDFmK36.js → dashboard-CX0XIavm.js} +0 -0
- /package/frontend-dist/assets/{login-Sef1i0de.js → login-CO6SrdUn.js} +0 -0
- /package/frontend-dist/assets/{login-BTNL5nN5.js → login-DmmSnjUg.js} +0 -0
- /package/frontend-dist/assets/{logs-B-6cgV12.js → logs-84vguvAn.js} +0 -0
- /package/frontend-dist/assets/{logs-CBRLywRw.js → logs-kHiiojHO.js} +0 -0
- /package/frontend-dist/assets/{mappings-DQRteuwa.js → mappings-BlVL5Io-.js} +0 -0
- /package/frontend-dist/assets/{mappings-Cazz3EF4.js → mappings-CFnc8ote.js} +0 -0
- /package/frontend-dist/assets/{monitor-DeInYpBf.js → monitor-D8Q-8Pyu.js} +0 -0
- /package/frontend-dist/assets/{monitor-Baldqd3x.js → monitor-EZaS3J_S.js} +0 -0
- /package/frontend-dist/assets/{providers-D6mXnhF_.js → providers-IaCJ0SNi.js} +0 -0
- /package/frontend-dist/assets/{providers-CxmHNt5G.js → providers-sxzMxLKs.js} +0 -0
- /package/frontend-dist/assets/{quickSetup-xHkKkA6i.js → quickSetup-B8PU1MnU.js} +0 -0
- /package/frontend-dist/assets/{quickSetup-cCofuCNs.js → quickSetup-C19Dqeqg.js} +0 -0
- /package/frontend-dist/assets/{requestDetail-bH5SerEV.js → requestDetail-C17DBoKU.js} +0 -0
- /package/frontend-dist/assets/{requestDetail-OsCIcS79.js → requestDetail-S8eKxElp.js} +0 -0
- /package/frontend-dist/assets/{retryRules-CToGC6cR.js → retryRules-BjLh7gly.js} +0 -0
- /package/frontend-dist/assets/{retryRules-BXrRL52J.js → retryRules-Dq4CT4FE.js} +0 -0
- /package/frontend-dist/assets/{routerKeys-DbTg4OP1.js → routerKeys-C2qOaTmZ.js} +0 -0
- /package/frontend-dist/assets/{routerKeys-Be7OZCn0.js → routerKeys-Mav64y7d.js} +0 -0
- /package/frontend-dist/assets/{schedules-DRizOKfa.js → schedules-CtbtvVKi.js} +0 -0
- /package/frontend-dist/assets/{schedules-CPV0fmb-.js → schedules-n-vnm7qH.js} +0 -0
- /package/frontend-dist/assets/{settings-DCS-RTKl.js → settings-Br3uhWN6.js} +0 -0
- /package/frontend-dist/assets/{settings-C4zZB9GY.js → settings-CFwQUG5b.js} +0 -0
- /package/frontend-dist/assets/{setup-DmgXvgkY.js → setup-CDQOZeVA.js} +0 -0
- /package/frontend-dist/assets/{setup-CrjgRrYP.js → setup-QxV8Fdng.js} +0 -0
- /package/frontend-dist/assets/{sidebar-CLHUZFGw.js → sidebar-BZdTUdd2.js} +0 -0
- /package/frontend-dist/assets/{sidebar-DwNPVJOB.js → sidebar-SjlkZ2ii.js} +0 -0
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { FastifyPluginCallback } from "fastify";
|
|
2
2
|
import Database from "better-sqlite3";
|
|
3
|
-
import type { StateRegistry } from "../core/registry.js";
|
|
4
3
|
interface ProxyEnhancementOptions {
|
|
5
4
|
db: Database.Database;
|
|
6
|
-
stateRegistry?: StateRegistry;
|
|
7
5
|
}
|
|
8
6
|
export declare const adminProxyEnhancementRoutes: FastifyPluginCallback<ProxyEnhancementOptions>;
|
|
9
7
|
export {};
|
|
@@ -1,26 +1,32 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
|
-
import { setSetting } from "../db/settings.js";
|
|
2
|
+
import { getSetting, setSetting } from "../db/settings.js";
|
|
3
3
|
const UpdateProxyEnhancementSchema = Type.Object({
|
|
4
|
-
claude_code_enabled: Type.Boolean(),
|
|
5
4
|
tool_call_loop_enabled: Type.Boolean(),
|
|
6
5
|
stream_loop_enabled: Type.Boolean(),
|
|
7
6
|
tool_round_limit_enabled: Type.Boolean(),
|
|
8
7
|
});
|
|
9
|
-
const SessionParamsSchema = Type.Object({
|
|
10
|
-
keyId: Type.String(),
|
|
11
|
-
sessionId: Type.String(),
|
|
12
|
-
});
|
|
13
|
-
import { getSessionStates, getSessionHistory, } from "../db/session-states.js";
|
|
14
8
|
export const adminProxyEnhancementRoutes = (app, options, done) => {
|
|
15
|
-
const { db
|
|
9
|
+
const { db } = options;
|
|
16
10
|
app.get("/admin/api/proxy-enhancement", async (_request, reply) => {
|
|
17
|
-
const
|
|
11
|
+
const raw = getSetting(db, "proxy_enhancement");
|
|
12
|
+
const defaults = { tool_call_loop_enabled: false, stream_loop_enabled: false, tool_round_limit_enabled: true };
|
|
13
|
+
let config = defaults;
|
|
14
|
+
if (raw) {
|
|
15
|
+
try {
|
|
16
|
+
const parsed = JSON.parse(raw);
|
|
17
|
+
config = {
|
|
18
|
+
tool_call_loop_enabled: parsed.tool_call_loop_enabled ?? false,
|
|
19
|
+
stream_loop_enabled: parsed.stream_loop_enabled ?? false,
|
|
20
|
+
tool_round_limit_enabled: parsed.tool_round_limit_enabled ?? true,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch { /* eslint-disable-line taste/no-silent-catch -- invalid JSON, return defaults */ }
|
|
24
|
+
}
|
|
18
25
|
return reply.send(config);
|
|
19
26
|
});
|
|
20
27
|
app.put("/admin/api/proxy-enhancement", { schema: { body: UpdateProxyEnhancementSchema } }, async (request, reply) => {
|
|
21
28
|
const body = request.body;
|
|
22
29
|
const config = {
|
|
23
|
-
claude_code_enabled: body.claude_code_enabled,
|
|
24
30
|
tool_call_loop_enabled: body.tool_call_loop_enabled,
|
|
25
31
|
stream_loop_enabled: body.stream_loop_enabled,
|
|
26
32
|
tool_round_limit_enabled: body.tool_round_limit_enabled,
|
|
@@ -28,19 +34,5 @@ export const adminProxyEnhancementRoutes = (app, options, done) => {
|
|
|
28
34
|
setSetting(db, "proxy_enhancement", JSON.stringify(config));
|
|
29
35
|
return reply.send({ success: true });
|
|
30
36
|
});
|
|
31
|
-
app.get("/admin/api/session-states", async (_req, reply) => {
|
|
32
|
-
const states = getSessionStates(db);
|
|
33
|
-
return reply.send(states);
|
|
34
|
-
});
|
|
35
|
-
app.get("/admin/api/session-states/:keyId/:sessionId/history", { schema: { params: SessionParamsSchema } }, async (req, reply) => {
|
|
36
|
-
const { keyId, sessionId } = req.params;
|
|
37
|
-
const history = getSessionHistory(db, keyId, sessionId);
|
|
38
|
-
return reply.send(history);
|
|
39
|
-
});
|
|
40
|
-
app.delete("/admin/api/session-states/:keyId/:sessionId", { schema: { params: SessionParamsSchema } }, async (req, reply) => {
|
|
41
|
-
const { keyId, sessionId } = req.params;
|
|
42
|
-
stateRegistry?.deleteModelState(keyId, sessionId);
|
|
43
|
-
return reply.send({ success: true });
|
|
44
|
-
});
|
|
45
37
|
done();
|
|
46
38
|
};
|
package/dist/admin/routes.js
CHANGED
|
@@ -32,7 +32,7 @@ export const adminRoutes = (app, options, done) => {
|
|
|
32
32
|
app.register(adminRouterKeyRoutes, { db: options.db });
|
|
33
33
|
app.register(adminStatsRoutes, { db: options.db });
|
|
34
34
|
app.register(adminMetricsRoutes, { db: options.db });
|
|
35
|
-
app.register(adminProxyEnhancementRoutes, { db: options.db
|
|
35
|
+
app.register(adminProxyEnhancementRoutes, { db: options.db });
|
|
36
36
|
app.register(adminMonitorRoutes, { tracker: options.tracker });
|
|
37
37
|
app.register(adminSettingsRoutes, { db: options.db, logsDir: options.logsDir });
|
|
38
38
|
app.register(adminImportExportRoutes, { db: options.db, stateRegistry: options.stateRegistry, pluginRegistry: options.pluginRegistry });
|
|
@@ -9,10 +9,8 @@ const CONFIG_TABLES = [
|
|
|
9
9
|
"retry_rules",
|
|
10
10
|
"router_keys",
|
|
11
11
|
"settings",
|
|
12
|
-
"session_model_states",
|
|
13
12
|
"schedules",
|
|
14
13
|
"provider_model_info",
|
|
15
|
-
"session_model_history",
|
|
16
14
|
"provider_transform_rules",
|
|
17
15
|
];
|
|
18
16
|
// settings 表按 key 列的值过滤,不覆盖本地安全敏感配置
|
|
@@ -129,7 +127,6 @@ export const adminImportExportRoutes = (app, options, done) => {
|
|
|
129
127
|
stateRegistry.refreshRetryRules();
|
|
130
128
|
// 清除旧的 semaphore/adaptive/tracker 配置,按导入后的 DB 数据全量重建
|
|
131
129
|
stateRegistry.removeAllProviders();
|
|
132
|
-
stateRegistry.clearModelState();
|
|
133
130
|
stateRegistry.reinitializeProviders();
|
|
134
131
|
// 刷新 transform plugin 缓存(从 DB 重新加载规则 + 扫描插件目录)
|
|
135
132
|
if (options.pluginRegistry) {
|
package/dist/core/registry.d.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import type { ConcurrencyConfig } from "./types.js";
|
|
2
2
|
export type { ConcurrencyConfig };
|
|
3
|
-
export interface EnhancementConfig {
|
|
4
|
-
claude_code_enabled: boolean;
|
|
5
|
-
tool_call_loop_enabled: boolean;
|
|
6
|
-
stream_loop_enabled: boolean;
|
|
7
|
-
}
|
|
8
3
|
/** Provider 自适应/手动并发配置(DB 字段) */
|
|
9
4
|
export interface ProviderConcurrencyParams {
|
|
10
5
|
adaptive_enabled: number;
|
|
@@ -26,12 +21,6 @@ export interface StateRegistry {
|
|
|
26
21
|
active: number;
|
|
27
22
|
queued: number;
|
|
28
23
|
};
|
|
29
|
-
/** 清空所有会话模型状态(modelState.clearAll) */
|
|
30
|
-
clearModelState(): void;
|
|
31
|
-
/** 删除指定会话模型状态(modelState.delete) */
|
|
32
|
-
deleteModelState(keyId: string, sessionId: string): void;
|
|
33
|
-
/** 读取 proxy enhancement 配置 */
|
|
34
|
-
getEnhancementConfig(): EnhancementConfig;
|
|
35
24
|
/** 同步 provider 的自适应并发配置(AdaptiveController.syncProvider) */
|
|
36
25
|
syncAdaptiveProvider(providerId: string, params: ProviderConcurrencyParams): void;
|
|
37
26
|
/** 移除 provider 的自适应并发状态(AdaptiveController.remove) */
|
package/dist/db/index.d.ts
CHANGED
|
@@ -16,8 +16,6 @@ export { getStats } from "./stats.js";
|
|
|
16
16
|
export type { Stats } from "./stats.js";
|
|
17
17
|
export { getSetting, setSetting, isInitialized } from "./settings.js";
|
|
18
18
|
export { getDbMaxSizeMb, setDbMaxSizeMb, getLogTableMaxSizeMb, setLogTableMaxSizeMb, } from "./settings.js";
|
|
19
|
-
export { getSessionStates, getSessionState, getSessionHistory, upsertSessionState, insertSessionHistory, deleteSessionState, } from "./session-states.js";
|
|
20
|
-
export type { SessionModelState, SessionModelHistory, UpsertSessionStateInput, InsertSessionHistoryInput } from "./session-states.js";
|
|
21
19
|
export { insertWindow, getLatestWindow, getWindowsInRange, getWindowUsage, } from "./usage-windows.js";
|
|
22
20
|
export type { UsageWindow, WindowUsage } from "./usage-windows.js";
|
|
23
21
|
export { getModelContextWindowOverride, getModelInfoForProvider, setModelInfoForProvider, deleteAllModelInfoForProvider, getAllModelInfo, } from "./model-info.js";
|
package/dist/db/index.js
CHANGED
|
@@ -96,7 +96,6 @@ export { getMetricsSummary, getMetricsTimeseries, insertMetrics } from "./metric
|
|
|
96
96
|
export { getStats } from "./stats.js";
|
|
97
97
|
export { getSetting, setSetting, isInitialized } from "./settings.js";
|
|
98
98
|
export { getDbMaxSizeMb, setDbMaxSizeMb, getLogTableMaxSizeMb, setLogTableMaxSizeMb, } from "./settings.js";
|
|
99
|
-
export { getSessionStates, getSessionState, getSessionHistory, upsertSessionState, insertSessionHistory, deleteSessionState, } from "./session-states.js";
|
|
100
99
|
export { insertWindow, getLatestWindow, getWindowsInRange, getWindowUsage, } from "./usage-windows.js";
|
|
101
100
|
export { getModelContextWindowOverride, getModelInfoForProvider, setModelInfoForProvider, deleteAllModelInfoForProvider, getAllModelInfo, } from "./model-info.js";
|
|
102
101
|
export { getSchedulesByGroup, getActiveSchedulesForGroup, getScheduleById, getAllSchedules, createSchedule, updateSchedule, deleteSchedule, deleteSchedulesByGroup, } from "./schedules.js";
|
package/dist/index.js
CHANGED
|
@@ -22,9 +22,7 @@ import { adminRoutes } from "./admin/routes.js";
|
|
|
22
22
|
import { RetryRuleMatcher } from "./proxy/orchestration/retry-rules.js";
|
|
23
23
|
import { PluginRegistry } from "./proxy/transform/plugin-registry.js";
|
|
24
24
|
import { SemaphoreManager, AdaptiveController } from "@llm-router/core/concurrency";
|
|
25
|
-
import { loadEnhancementConfig } from "./proxy/routing/enhancement-config.js";
|
|
26
25
|
import { RequestTracker } from "@llm-router/core/monitor";
|
|
27
|
-
import { modelState } from "./proxy/routing/model-state.js";
|
|
28
26
|
import { UsageWindowTracker } from "./proxy/routing/usage-window-tracker.js";
|
|
29
27
|
import { SessionTracker, DEFAULT_LOOP_PREVENTION_CONFIG } from "@llm-router/core/loop-prevention";
|
|
30
28
|
import { scheduleLogCleanup } from "./db/log-cleaner.js";
|
|
@@ -206,8 +204,6 @@ export async function buildApp(options) {
|
|
|
206
204
|
? null
|
|
207
205
|
: new LogFileWriter(logsDir, { enabled: getDetailLogEnabled(db) });
|
|
208
206
|
container.register(SERVICE_KEYS.logFileWriter, () => logFileWriter);
|
|
209
|
-
// 注入 DB 到 modelState 单例,启用会话级持久化
|
|
210
|
-
modelState.init(db);
|
|
211
207
|
// 注册 AdaptiveController(依赖已注册的 semaphoreManager)
|
|
212
208
|
container.register(SERVICE_KEYS.adaptiveController, (c) => {
|
|
213
209
|
const ac = new AdaptiveController(c.resolve(SERVICE_KEYS.semaphoreManager), app.log);
|
|
@@ -240,9 +236,6 @@ export async function buildApp(options) {
|
|
|
240
236
|
removeProvider: (providerId) => semaphoreManager.remove(providerId),
|
|
241
237
|
removeAllProviders: () => semaphoreManager.removeAll(),
|
|
242
238
|
getProviderStatus: (providerId) => semaphoreManager.getStatus(providerId),
|
|
243
|
-
clearModelState: () => modelState.clearAll(),
|
|
244
|
-
deleteModelState: (keyId, sessionId) => modelState.delete(keyId, sessionId),
|
|
245
|
-
getEnhancementConfig: () => loadEnhancementConfig(db),
|
|
246
239
|
syncAdaptiveProvider: (providerId, cfg) => adaptiveController.syncProvider(providerId, cfg),
|
|
247
240
|
removeAdaptiveProvider: (providerId) => adaptiveController.remove(providerId),
|
|
248
241
|
getAdaptiveStatus: (providerId) => adaptiveController.getStatus(providerId),
|
|
@@ -293,7 +286,6 @@ export async function buildApp(options) {
|
|
|
293
286
|
tracker.stopPushInterval();
|
|
294
287
|
// 关闭所有 SSE 长连接,防止 app.close() 因 hijack 的连接无限等待
|
|
295
288
|
tracker.closeAllClients();
|
|
296
|
-
modelState.clearAll();
|
|
297
289
|
semaphoreManager.removeAll();
|
|
298
290
|
const sessionTracker = container.resolve(SERVICE_KEYS.sessionTracker);
|
|
299
291
|
sessionTracker.stop();
|
|
@@ -1,4 +1 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type { EnhancementResult, EnhancementMeta, RouterKeyInfo } from "./enhancement-handler.js";
|
|
3
|
-
export { parseDirective, parseToolResult, TOOL_USE_ID_PREFIX, TOOL_USE_ID_PROVIDER_PREFIX } from "./directive-parser.js";
|
|
4
|
-
export { cleanRouterResponses } from "./response-cleaner.js";
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
export {};
|
|
2
|
+
// enhancement 模块已清空 — select-model 功能已整体移除
|
|
3
|
+
// 保留空模块以避免其他文件的 import 断裂(如有遗漏引用会在此暴露)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import { HTTP_UNPROCESSABLE_ENTITY } from "../../core/constants.js";
|
|
3
|
-
import { getProviderById, insertRequestLog,
|
|
3
|
+
import { getProviderById, insertRequestLog, updateLogStreamContent, updateLogClientStatus } from "../../db/index.js";
|
|
4
4
|
import { decrypt } from "../../utils/crypto.js";
|
|
5
5
|
import { getSetting } from "../../db/settings.js";
|
|
6
6
|
import { resolveMapping } from "../routing/mapping-resolver.js";
|
|
7
|
-
import { applyEnhancement } from "../enhancement/enhancement-handler.js";
|
|
8
7
|
import { SemaphoreQueueFullError, SemaphoreTimeoutError } from "@llm-router/core";
|
|
9
|
-
import { logResilienceResult, collectTransportMetrics,
|
|
8
|
+
import { logResilienceResult, collectTransportMetrics, sanitizeHeadersForLog, } from "../proxy-logging.js";
|
|
10
9
|
import { buildUpstreamHeaders, buildUpstreamUrl } from "../proxy-core.js";
|
|
11
10
|
import { ProviderSwitchNeeded } from "../types.js";
|
|
12
11
|
import { insertRejectedLog } from "../log-helpers.js";
|
|
@@ -16,7 +15,6 @@ import { applyOverflowRedirect } from "../routing/overflow.js";
|
|
|
16
15
|
import { parseModels } from "../../config/model-context.js";
|
|
17
16
|
import { applyProviderPatches } from "../patch/index.js";
|
|
18
17
|
import { PipelineSnapshot } from "../pipeline-snapshot.js";
|
|
19
|
-
import { maybeInjectModelInfoTag } from "../response-transform.js";
|
|
20
18
|
import { applyToolRoundLimit } from "../patch/tool-round-limiter.js";
|
|
21
19
|
import { loadEnhancementConfig } from "../routing/enhancement-config.js";
|
|
22
20
|
import { getTransportStatusCode, serializeBlocksForStorage, extractLastToolUse } from "./proxy-handler-utils.js";
|
|
@@ -30,7 +28,7 @@ function rejectAndReply(reply, params, error, errorMessage, providerId) {
|
|
|
30
28
|
statusCode: error.statusCode, errorMessage, startTime: params.startTime,
|
|
31
29
|
isStream: params.isStream, routerKeyId: params.routerKeyId,
|
|
32
30
|
originalBody: params.originalBody, clientHeaders: params.clientHeaders,
|
|
33
|
-
providerId, originalModel:
|
|
31
|
+
providerId, originalModel: null,
|
|
34
32
|
isFailover: params.isFailover, originalRequestId: params.originalRequestId,
|
|
35
33
|
sessionId: params.sessionId, pipelineSnapshot: params.pipelineSnapshot,
|
|
36
34
|
matcher: params.matcher, logFileWriter: params.logFileWriter,
|
|
@@ -57,13 +55,10 @@ export async function handleProxyRequest(request, reply, apiType, upstreamPath,
|
|
|
57
55
|
const reqBody = request.body;
|
|
58
56
|
const rawBody = reqBody ? JSON.parse(JSON.stringify(reqBody)) : {};
|
|
59
57
|
const snapshot = new PipelineSnapshot();
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
snapshot.add({ stage: "enhancement", router_tags_stripped: enhMeta.router_tags_stripped, directive: enhMeta.directive });
|
|
63
|
-
// tool round limiter 阶段 — 检测连续工具调用轮数,超阈值时注入提示词
|
|
64
|
-
let pipelineBody = enhancedBody;
|
|
58
|
+
let pipelineBody = request.body;
|
|
59
|
+
const effectiveModel = clientModel;
|
|
65
60
|
if (enhancementConfig.tool_round_limit_enabled) {
|
|
66
|
-
const roundResult = applyToolRoundLimit(
|
|
61
|
+
const roundResult = applyToolRoundLimit(pipelineBody, apiType);
|
|
67
62
|
if (roundResult.injected) {
|
|
68
63
|
pipelineBody = roundResult.body;
|
|
69
64
|
snapshot.add({ stage: "tool_round_limit", action: "inject_warning", rounds: roundResult.rounds });
|
|
@@ -110,14 +105,12 @@ export async function handleProxyRequest(request, reply, apiType, upstreamPath,
|
|
|
110
105
|
}
|
|
111
106
|
}
|
|
112
107
|
}
|
|
113
|
-
if (interceptResponse)
|
|
114
|
-
return handleIntercept(deps.db, apiType, request, reply, interceptResponse, clientModel, sessionId, snapshot.toJSON(), matcher, logFileWriter);
|
|
115
108
|
return executeFailoverLoop({
|
|
116
109
|
request, reply, apiType, upstreamPath, errors, deps, options,
|
|
117
|
-
effectiveModel,
|
|
110
|
+
effectiveModel,
|
|
118
111
|
pipelineBody,
|
|
119
112
|
rawBody,
|
|
120
|
-
baseStages:
|
|
113
|
+
baseStages: [],
|
|
121
114
|
sessionId,
|
|
122
115
|
streamLoopEnabled: enhancementConfig.stream_loop_enabled,
|
|
123
116
|
matcher, logFileWriter,
|
|
@@ -125,7 +118,7 @@ export async function handleProxyRequest(request, reply, apiType, upstreamPath,
|
|
|
125
118
|
}
|
|
126
119
|
// ---------- Failover loop ----------
|
|
127
120
|
async function executeFailoverLoop(ctx) {
|
|
128
|
-
const { request, reply, apiType, upstreamPath, errors, deps, options, effectiveModel,
|
|
121
|
+
const { request, reply, apiType, upstreamPath, errors, deps, options, effectiveModel, pipelineBody, rawBody, baseStages, sessionId, streamLoopEnabled, matcher, logFileWriter } = ctx;
|
|
129
122
|
const tracker = deps.container.resolve(SERVICE_KEYS.tracker);
|
|
130
123
|
const usageWindowTracker = deps.container.resolve(SERVICE_KEYS.usageWindowTracker);
|
|
131
124
|
const config = getConfig();
|
|
@@ -148,7 +141,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
148
141
|
const iterationSnapshot = new PipelineSnapshot(baseStages);
|
|
149
142
|
const rCtx = {
|
|
150
143
|
db: deps.db, logId, apiType, model: effectiveModel,
|
|
151
|
-
startTime, isStream, routerKeyId, originalBody: rawBody, clientHeaders: cliHdrs,
|
|
144
|
+
startTime, isStream, routerKeyId, originalBody: rawBody, clientHeaders: cliHdrs,
|
|
152
145
|
isFailover: isFailoverIteration, originalRequestId: isFailoverIteration ? rootLogId : null, sessionId,
|
|
153
146
|
pipelineSnapshot: iterationSnapshot.toJSON(),
|
|
154
147
|
matcher, logFileWriter,
|
|
@@ -285,7 +278,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
285
278
|
} : undefined;
|
|
286
279
|
const transportFn = buildTransportFn({
|
|
287
280
|
provider, apiKey, body: patchedBody, cliHdrs, reply, upstreamPath: effectiveUpstreamPath, apiType: effectiveApiType,
|
|
288
|
-
isStream, startTime, logId, effectiveModel,
|
|
281
|
+
isStream, startTime, logId, effectiveModel,
|
|
289
282
|
streamTimeoutMs: config.STREAM_TIMEOUT_MS, tracker, matcher, request,
|
|
290
283
|
streamLoopEnabled, formatTransform, responseTransform, injectedHeaders,
|
|
291
284
|
});
|
|
@@ -294,7 +287,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
294
287
|
const resilienceResult = await deps.orchestrator.handle(request, reply, apiType, { resolved, provider, clientModel: effectiveModel, isStream, trackerId: logId, sessionId, clientRequest: clientReq, upstreamRequest: upstreamReqBase, concurrencyOverride }, { retryBaseDelayMs: config.RETRY_BASE_DELAY_MS, isFailover, ruleMatcher: matcher, transportFn });
|
|
295
288
|
const lastLogId = logResilienceResult(deps.db, {
|
|
296
289
|
apiType, model: effectiveModel, providerId: provider.id, isStream,
|
|
297
|
-
clientReq, upstreamReqBase, logId, routerKeyId, originalModel, sessionId,
|
|
290
|
+
clientReq, upstreamReqBase, logId, routerKeyId, originalModel: null, sessionId,
|
|
298
291
|
failover: { isFailoverIteration, rootLogId: rootLogId },
|
|
299
292
|
pipelineSnapshot,
|
|
300
293
|
matcher, logFileWriter,
|
|
@@ -329,12 +322,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
329
322
|
const tr = resilienceResult.result;
|
|
330
323
|
if (tr.kind === "success") {
|
|
331
324
|
// response transform — 注入 model info tag
|
|
332
|
-
|
|
333
|
-
if (respMeta.model_info_tag_injected) {
|
|
334
|
-
iterationSnapshot.add({ stage: "response_transform", model_info_tag_injected: true });
|
|
335
|
-
updateLogPipelineSnapshot(deps.db, lastLogId, iterationSnapshot.toJSON());
|
|
336
|
-
}
|
|
337
|
-
return reply.code(tr.statusCode).send(finalBody);
|
|
325
|
+
return reply.code(tr.statusCode).send(tr.body);
|
|
338
326
|
}
|
|
339
327
|
if (tr.kind === "throw" || (tr.kind === "error" && tr.statusCode >= HTTP_ERROR_THRESHOLD)) {
|
|
340
328
|
const err = errors.upstreamConnectionFailed();
|
|
@@ -355,7 +343,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
355
343
|
const fakeResult = e.lastResult ?? { kind: "throw", error: new Error("provider switch") };
|
|
356
344
|
logResilienceResult(deps.db, {
|
|
357
345
|
apiType, model: effectiveModel, providerId: provider.id, isStream,
|
|
358
|
-
clientReq, upstreamReqBase, logId, routerKeyId, originalModel, sessionId,
|
|
346
|
+
clientReq, upstreamReqBase, logId, routerKeyId, originalModel: null, sessionId,
|
|
359
347
|
failover: { isFailoverIteration, rootLogId: rootLogId },
|
|
360
348
|
pipelineSnapshot,
|
|
361
349
|
matcher, logFileWriter,
|
|
@@ -379,7 +367,7 @@ async function executeFailoverLoop(ctx) {
|
|
|
379
367
|
error_message: errMsg || "Upstream connection failed", created_at: new Date().toISOString(),
|
|
380
368
|
client_request: clientReq, upstream_request: upstreamReqBase,
|
|
381
369
|
is_failover: isFailoverIteration ? 1 : 0, original_request_id: isFailoverIteration ? rootLogId : null,
|
|
382
|
-
router_key_id: routerKeyId, original_model:
|
|
370
|
+
router_key_id: routerKeyId, original_model: null,
|
|
383
371
|
session_id: sessionId,
|
|
384
372
|
pipeline_snapshot: pipelineSnapshot,
|
|
385
373
|
}, (matcher || logFileWriter) ? {
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
export interface DirectiveMeta {
|
|
2
|
-
type: "select_model" | "router_model" | "router_command";
|
|
3
|
-
value: string;
|
|
4
|
-
}
|
|
5
1
|
export type StageRecord = {
|
|
6
|
-
stage: "enhancement";
|
|
7
|
-
router_tags_stripped: number;
|
|
8
|
-
directive: DirectiveMeta | null;
|
|
9
|
-
} | {
|
|
10
2
|
stage: "tool_round_limit";
|
|
11
3
|
action: string;
|
|
12
4
|
rounds: number;
|
|
@@ -28,9 +20,6 @@ export type StageRecord = {
|
|
|
28
20
|
} | {
|
|
29
21
|
stage: "provider_patch";
|
|
30
22
|
types: string[];
|
|
31
|
-
} | {
|
|
32
|
-
stage: "response_transform";
|
|
33
|
-
model_info_tag_injected: boolean;
|
|
34
23
|
};
|
|
35
24
|
export declare class PipelineSnapshot {
|
|
36
25
|
private readonly stages;
|
|
@@ -6,13 +6,6 @@ import type { ResilienceAttempt } from "../core/types.js";
|
|
|
6
6
|
import type { TransportResult } from "./types.js";
|
|
7
7
|
/** 日志存储前脱敏 Authorization / x-api-key header,避免 API Key 被持久化 */
|
|
8
8
|
export declare function sanitizeHeadersForLog(headers: Record<string, string>): Record<string, string>;
|
|
9
|
-
export declare function handleIntercept(db: Database.Database, apiType: "openai" | "openai-responses" | "anthropic", request: FastifyRequest, reply: import("fastify").FastifyReply, interceptResponse: {
|
|
10
|
-
statusCode: number;
|
|
11
|
-
body: unknown;
|
|
12
|
-
meta?: unknown;
|
|
13
|
-
}, clientModel: string, sessionId?: string, pipelineSnapshot?: string, matcher?: {
|
|
14
|
-
test: (statusCode: number, body: string) => boolean;
|
|
15
|
-
} | null, logFileWriter?: LogFileWriter | null): import("fastify").FastifyReply;
|
|
16
9
|
export declare function logResilienceResult(db: Database.Database, params: {
|
|
17
10
|
apiType: "openai" | "openai-responses" | "anthropic";
|
|
18
11
|
model: string;
|
|
@@ -17,28 +17,6 @@ export function sanitizeHeadersForLog(headers) {
|
|
|
17
17
|
return sanitized;
|
|
18
18
|
}
|
|
19
19
|
// ---------- Logging helpers (extracted from proxy-core) ----------
|
|
20
|
-
export function handleIntercept(db, apiType, request, reply, interceptResponse, clientModel, sessionId, pipelineSnapshot, matcher, logFileWriter) {
|
|
21
|
-
const logId = randomUUID();
|
|
22
|
-
const isStream = request.body.stream === true;
|
|
23
|
-
const respBody = JSON.stringify(interceptResponse.body);
|
|
24
|
-
const writeContext = (matcher || logFileWriter) ? {
|
|
25
|
-
matcher, logFileWriter, responseBody: respBody,
|
|
26
|
-
} : undefined;
|
|
27
|
-
insertRequestLog(db, {
|
|
28
|
-
id: logId, api_type: apiType, model: clientModel, provider_id: "router",
|
|
29
|
-
status_code: interceptResponse.statusCode, latency_ms: 0,
|
|
30
|
-
is_stream: isStream ? 1 : 0, error_message: null,
|
|
31
|
-
created_at: new Date().toISOString(),
|
|
32
|
-
client_request: JSON.stringify({ headers: request.headers, body: request.body }),
|
|
33
|
-
upstream_request: interceptResponse.meta ? JSON.stringify(interceptResponse.meta) : null,
|
|
34
|
-
upstream_response: JSON.stringify({ statusCode: interceptResponse.statusCode, body: respBody }),
|
|
35
|
-
is_retry: 0, is_failover: 0, original_request_id: null,
|
|
36
|
-
router_key_id: request.routerKey?.id ?? null, original_model: null,
|
|
37
|
-
session_id: sessionId,
|
|
38
|
-
pipeline_snapshot: pipelineSnapshot ?? null,
|
|
39
|
-
}, writeContext);
|
|
40
|
-
return reply.code(interceptResponse.statusCode).send(interceptResponse.body);
|
|
41
|
-
}
|
|
42
20
|
// ---------- New-architecture logging ----------
|
|
43
21
|
export function logResilienceResult(db, params, attempts, result, startTime) {
|
|
44
22
|
const isFailoverIteration = params.failover?.isFailoverIteration ?? false;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { getSetting } from "../../db/settings.js";
|
|
2
2
|
const DEFAULT_CONFIG = {
|
|
3
|
-
claude_code_enabled: false,
|
|
4
3
|
tool_call_loop_enabled: false,
|
|
5
4
|
stream_loop_enabled: false,
|
|
6
5
|
tool_round_limit_enabled: true,
|
|
@@ -13,7 +12,6 @@ export function loadEnhancementConfig(db) {
|
|
|
13
12
|
try {
|
|
14
13
|
const parsed = JSON.parse(raw);
|
|
15
14
|
return {
|
|
16
|
-
claude_code_enabled: parsed.claude_code_enabled ?? false,
|
|
17
15
|
tool_call_loop_enabled: parsed.tool_call_loop_enabled ?? false,
|
|
18
16
|
stream_loop_enabled: parsed.stream_loop_enabled ?? false,
|
|
19
17
|
tool_round_limit_enabled: parsed.tool_round_limit_enabled ?? true,
|
|
@@ -5,7 +5,6 @@ import { buildUpstreamHeaders } from "../proxy-core.js";
|
|
|
5
5
|
import { StreamLoopGuard } from "@llm-router/core/loop-prevention";
|
|
6
6
|
import { NGramLoopDetector } from "@llm-router/core/loop-prevention";
|
|
7
7
|
import { UPSTREAM_SUCCESS } from "../types.js";
|
|
8
|
-
import { buildModelInfoTag } from "../enhancement/enhancement-handler.js";
|
|
9
8
|
import { DEFAULT_MAX_RAW as STREAM_CONTENT_MAX_RAW, DEFAULT_MAX_TEXT as STREAM_CONTENT_MAX_TEXT } from "@llm-router/core/monitor";
|
|
10
9
|
const LOOP_DETECTOR_N = 6;
|
|
11
10
|
const LOOP_DETECTOR_WINDOW_SIZE = 1000;
|
|
@@ -70,18 +69,6 @@ export function buildTransportFn(p) {
|
|
|
70
69
|
if (p.responseTransform && "body" in result && result.body) {
|
|
71
70
|
result = { ...result, body: p.responseTransform(result.body) };
|
|
72
71
|
}
|
|
73
|
-
if (p.originalModel && result.kind === "success" && result.statusCode === UPSTREAM_SUCCESS) {
|
|
74
|
-
try {
|
|
75
|
-
const bodyObj = JSON.parse(result.body);
|
|
76
|
-
if (bodyObj.content?.[0]?.text) {
|
|
77
|
-
bodyObj.content[0].text += `\n\n${buildModelInfoTag(p.effectiveModel)}`;
|
|
78
|
-
return { ...result, body: JSON.stringify(bodyObj) };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
catch {
|
|
82
|
-
p.request.log.warn("Failed to inject model-info tag into non-JSON response");
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
72
|
return result;
|
|
86
73
|
};
|
|
87
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Bt as e,Q as t,Rt as n,Y as r,pt as i,r as a,ut as o}from"./button-
|
|
1
|
+
import{Bt as e,Q as t,Rt as n,Y as r,pt as i,r as a,ut as o}from"./button-63IAyx7P.js";var s=[`data-size`],c=t({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(t){let c=t;return(l,u)=>(o(),r(`div`,{"data-slot":`card`,"data-size":t.size,class:e(n(a)(`ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col`,c.class))},[i(l.$slots,`default`)],10,s))}}),l=t({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let s=t;return(t,c)=>(o(),r(`div`,{"data-slot":`card-content`,class:e(n(a)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[i(t.$slots,`default`)],2))}});export{c as n,l as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Bt as e,Q as t,Rt as n,Y as r,pt as i,r as a,ut as o}from"./button-
|
|
1
|
+
import{Bt as e,Q as t,Rt as n,Y as r,pt as i,r as a,ut as o}from"./button-63IAyx7P.js";var s=t({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let s=t;return(t,c)=>(o(),r(`div`,{"data-slot":`card-header`,class:e(n(a)(`gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]`,s.class))},[i(t.$slots,`default`)],2))}}),c=t({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(t){let s=t;return(t,c)=>(o(),r(`div`,{"data-slot":`card-title`,class:e(n(a)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[i(t.$slots,`default`)],2))}});export{s as n,c as t};
|
package/frontend-dist/assets/{CascadingModelSelect-CAv9_cK6.js → CascadingModelSelect-BR8cT6D3.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Bt as e,Ct as t,F as n,G as r,J as i,K as a,M as o,Q as s,Rt as c,U as l,Ut as u,Y as d,Z as f,ft as p,jt as m,q as h,ut as g}from"./button-
|
|
1
|
+
import{Bt as e,Ct as t,F as n,G as r,J as i,K as a,M as o,Q as s,Rt as c,U as l,Ut as u,Y as d,Z as f,ft as p,jt as m,q as h,ut as g}from"./button-63IAyx7P.js";import{_,tt as v,v as y,y as b}from"./index-DPqLrV5W.js";var x=o(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]),S=o(`plus`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]),C=[`onMouseenter`],w={class:`truncate max-w-40`},T={key:0,class:`ml-1 text-[10px] px-1 py-px rounded bg-emerald-500/15 text-emerald-400 shrink-0`},E=[`onMouseenter`],D=[`onClick`],O={class:`truncate`},k={key:0,class:`shrink-0 text-xs text-muted-foreground`},A={key:0,class:`px-2 py-1.5 text-sm text-muted-foreground`},j=s({__name:`CascadingSelect`,props:{groups:{},modelValue:{},placeholder:{default:``},compact:{type:Boolean,default:!1}},emits:[`update:modelValue`],setup(o,{emit:s}){let{t:S}=n(),j=o,M=r(()=>j.placeholder||S(`common.selectPlaceholder`)),N=s,P=m(!1),F=m(null),I=r(()=>{if(!j.modelValue)return``;let e=j.groups.find(e=>e.key===j.modelValue.groupKey);if(!e)return``;let t=e.options.find(e=>e.value===j.modelValue.value);return t?`${e.label} / ${t.label}`:``});function L(e,t){N(`update:modelValue`,{groupKey:e,value:t}),P.value=!1}function R(e){P.value=e,e||(F.value=null)}return(n,r)=>(g(),h(c(b),{open:P.value,"onUpdate:open":R},{default:t(()=>[f(c(_),{"as-child":``},{default:t(()=>[a(`div`,{class:e([`flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background cursor-pointer hover:bg-accent hover:text-accent-foreground`,[o.compact?`h-8 text-xs px-2.5 py-1`:`h-10 text-sm px-3 py-2`,{"ring-2 ring-ring ring-offset-2":P.value}]])},[a(`span`,{class:e([`truncate`,o.modelValue?`text-foreground`:`text-muted-foreground`])},u(I.value||M.value),3),f(c(v),{class:`h-4 w-4 shrink-0 opacity-50`})],2)]),_:1}),f(c(y),{align:`start`,"side-offset":4,class:`z-[200] w-auto min-w-56 overflow-visible p-1`},{default:t(()=>[(g(!0),d(l,null,p(o.groups,t=>(g(),d(`div`,{key:t.key,class:e([`relative flex cursor-pointer items-center justify-between rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground`,{"bg-accent text-accent-foreground z-10":F.value===t.key}]),onMouseenter:e=>F.value=t.key},[a(`span`,w,u(t.label),1),t.badge?(g(),d(`span`,T,u(t.badge),1)):i(``,!0),f(c(x),{class:`ml-1 h-4 w-4 shrink-0 opacity-50`}),F.value===t.key&&t.options.length>0?(g(),d(`div`,{key:1,class:`absolute left-full top-0 ml-0.5 min-w-48 rounded-md border bg-popover p-1 text-popover-foreground shadow-md`,onMouseenter:e=>F.value=t.key},[(g(!0),d(l,null,p(t.options,n=>(g(),d(`div`,{key:n.value,class:e([`flex cursor-pointer items-center justify-between gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground`,{"bg-accent text-accent-foreground":o.modelValue?.groupKey===t.key&&o.modelValue?.value===n.value}]),onClick:e=>L(t.key,n.value)},[a(`span`,O,u(n.label),1),n.tag?(g(),d(`span`,k,u(n.tag),1)):i(``,!0)],10,D))),128))],40,E)):i(``,!0)],42,C))),128)),o.groups.length===0?(g(),d(`div`,A,u(c(S)(`common.noOptions`)),1)):i(``,!0)]),_:1})]),_:1},8,[`open`]))}}),M=s({__name:`CascadingModelSelect`,props:{providers:{},modelValue:{},placeholder:{default:``},compact:{type:Boolean}},emits:[`update:modelValue`],setup(e,{emit:t}){let{t:i}=n(),a=e,o=r(()=>a.placeholder||i(`mappings.selectProviderModel`)),s=t;function c(e){return e>=1e6?`${e/1e6}M`:`${e/1e3}K`}let l=r(()=>a.providers.map(e=>({key:e.provider.id,label:e.provider.name,badge:e.isNew?i(`common.new`):void 0,options:e.models.map(e=>({value:e.name,label:e.name,tag:c(e.contextWindow)}))}))),u=r(()=>a.modelValue?{groupKey:a.modelValue.provider_id,value:a.modelValue.model}:void 0);function d(e){s(`update:modelValue`,{provider_id:e.groupKey,model:e.value})}return(t,n)=>(g(),h(j,{groups:l.value,"model-value":u.value,placeholder:o.value,compact:e.compact,"onUpdate:modelValue":d},null,8,[`groups`,`model-value`,`placeholder`,`compact`]))}});export{S as n,M as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ct as e,G as t,H as n,J as r,Q as i,Rt as a,V as o,Vt as s,Z as c,at as l,et as u,ht as d,i as f,m as p,o as m,pt as h,q as g,r as _,ut as v,x as y}from"./button-
|
|
1
|
+
import{Ct as e,G as t,H as n,J as r,Q as i,Rt as a,V as o,Vt as s,Z as c,at as l,et as u,ht as d,i as f,m as p,o as m,pt as h,q as g,r as _,ut as v,x as y}from"./button-63IAyx7P.js";import{t as b}from"./VisuallyHiddenInput-DbZDRHYC.js";import{t as x}from"./RovingFocusItem-D3o2cZhf.js";import{B as S,G as C,H as w,L as T,Y as E,nt as D,q as O}from"./index-DPqLrV5W.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=O(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=O(`CheckboxRoot`),I=i({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(i,{emit:s}){let c=i,u=s,{forwardRef:_,currentElement:y}=m(),S=A(null),T=p(c,`modelValue`,u,{defaultValue:c.defaultValue??c.falseValue,passive:c.modelValue===void 0}),D=t(()=>S?.disabled.value||c.disabled),O=t(()=>E(T.value,c.trueValue)),j=t(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,c.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=c.trueValue:T.value=O.value?c.falseValue:c.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,c.value)){let t=e.findIndex(e=>E(e,c.value));e.splice(t,1)}else e.push(c.value);S.modelValue.value=e}}let I=w(y),L=t(()=>c.id&&y.value?document.querySelector(`[for="${c.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(t,i)=>(v(),g(d(a(S)?.rovingFocus.value?a(x):a(f)),l(t.$attrs,{id:t.id,ref:a(_),role:`checkbox`,"as-child":t.asChild,as:t.as,type:t.as===`button`?`button`:void 0,"aria-checked":a(M)(j.value)?`mixed`:j.value,"aria-required":t.required,"aria-label":t.$attrs[`aria-label`]||L.value,"data-state":a(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:a(S)?.rovingFocus.value?!D.value:void 0,onKeydown:o(n(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:e(()=>[h(t.$slots,`default`,{modelValue:a(T),state:j.value}),a(I)&&t.name&&!a(S)?(v(),g(a(b),{key:0,type:`checkbox`,checked:!!j.value,name:t.name,value:t.value,disabled:D.value,required:t.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):r(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=i({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(t){let{forwardRef:n}=m(),r=P();return(t,i)=>(v(),g(a(T),{present:t.forceMount||a(M)(a(r).state.value)||a(r).state.value===!0},{default:e(()=>[c(a(f),l({ref:a(n),"data-state":a(N)(a(r).state.value),"data-disabled":a(r).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":t.asChild,as:t.as},t.$attrs),{default:e(()=>[h(t.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=i({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(t,{emit:n}){let r=t,i=n,o=S(y(r,`class`),i);return(t,n)=>(v(),g(a(I),l({"data-slot":`checkbox`},a(o),{class:a(_)(`border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-md border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50`,r.class)}),{default:e(n=>[c(a(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:e(()=>[h(t.$slots,`default`,s(u(n)),()=>[c(a(D))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
|
package/frontend-dist/assets/{CollapsibleContent-ignsLSmA.js → CollapsibleContent-PqKToOXJ.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ct as e,G as t,It as n,J as r,Q as i,Rt as a,Vt as o,Z as s,at as c,bt as l,ct as u,d,et as f,i as p,jt as m,m as h,o as g,ot as _,pt as v,q as y,ut as b}from"./button-
|
|
1
|
+
import{Ct as e,G as t,It as n,J as r,Q as i,Rt as a,Vt as o,Z as s,at as c,bt as l,ct as u,d,et as f,i as p,jt as m,m as h,o as g,ot as _,pt as v,q as y,ut as b}from"./button-63IAyx7P.js";import{B as x,L as S,q as C,z as w}from"./index-DPqLrV5W.js";var[T,E]=C(`CollapsibleRoot`),D=i({__name:`CollapsibleRoot`,props:{defaultOpen:{type:Boolean,required:!1,default:!1},open:{type:Boolean,required:!1,default:void 0},disabled:{type:Boolean,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:open`],setup(t,{expose:r,emit:i}){let o=t,s=h(o,`open`,i,{defaultValue:o.defaultOpen,passive:o.open===void 0}),{disabled:c,unmountOnHide:l}=n(o);return E({contentId:``,disabled:c,open:s,unmountOnHide:l,onOpenToggle:()=>{c.value||(s.value=!s.value)}}),r({open:s}),g(),(t,n)=>(b(),y(a(p),{as:t.as,"as-child":o.asChild,"data-state":a(s)?`open`:`closed`,"data-disabled":a(c)?``:void 0},{default:e(()=>[v(t.$slots,`default`,{open:a(s)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=i({inheritAttrs:!1,__name:`CollapsibleContent`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`contentFound`],setup(n,{emit:i}){let o=n,f=i,h=T();h.contentId||=w(void 0,`reka-collapsible-content`);let x=m(),{forwardRef:C,currentElement:E}=g(),D=m(0),O=m(0),k=t(()=>h.open.value),A=m(k.value),j=m();l(()=>[k.value,x.value?.present],async()=>{await _();let e=E.value;if(!e)return;j.value=j.value||{transitionDuration:e.style.transitionDuration,animationName:e.style.animationName},e.style.transitionDuration=`0s`,e.style.animationName=`none`;let t=e.getBoundingClientRect();O.value=t.height,D.value=t.width,A.value||(e.style.transitionDuration=j.value.transitionDuration,e.style.animationName=j.value.animationName)},{immediate:!0});let M=t(()=>A.value&&h.open.value);return u(()=>{requestAnimationFrame(()=>{A.value=!1})}),d(E,`beforematch`,e=>{requestAnimationFrame(()=>{h.onOpenToggle(),f(`contentFound`)})}),(t,n)=>(b(),y(a(S),{ref_key:`presentRef`,ref:x,present:t.forceMount||a(h).open.value,"force-mount":!0},{default:e(({present:n})=>[s(a(p),c(t.$attrs,{id:a(h).contentId,ref:a(C),"as-child":o.asChild,as:t.as,hidden:n?void 0:a(h).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:a(h).open.value?`open`:`closed`,"data-disabled":a(h).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:e(()=>[!a(h).unmountOnHide.value||n?v(t.$slots,`default`,{key:0}):r(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=i({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(t,{emit:n}){let r=x(t,n);return(t,n)=>(b(),y(a(D),c({"data-slot":`collapsible`},a(r)),{default:e(e=>[v(t.$slots,`default`,o(f(e)))]),_:3},16))}}),A=i({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(t){let n=t;return(t,r)=>(b(),y(a(O),c({"data-slot":`collapsible-content`},n),{default:e(()=>[v(t.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
|
package/frontend-dist/assets/{CollapsibleTrigger-K-O5aS5D.js → CollapsibleTrigger-54P86ben.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ct as e,Q as t,Rt as n,at as r,i,o as a,pt as o,q as s,ut as c}from"./button-
|
|
1
|
+
import{Ct as e,Q as t,Rt as n,at as r,i,o as a,pt as o,q as s,ut as c}from"./button-63IAyx7P.js";import{r as l}from"./CollapsibleContent-PqKToOXJ.js";var u=t({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(t){let r=t;a();let u=l();return(t,a)=>(c(),s(n(i),{type:t.as===`button`?`button`:void 0,as:t.as,"as-child":r.asChild,"aria-controls":n(u).contentId,"aria-expanded":n(u).open.value,"data-state":n(u).open.value?`open`:`closed`,"data-disabled":n(u).disabled?.value?``:void 0,disabled:n(u).disabled?.value,onClick:n(u).onOpenToggle},{default:e(()=>[o(t.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=t({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(t){let i=t;return(t,a)=>(c(),s(n(u),r({"data-slot":`collapsible-trigger`},i),{default:e(()=>[o(t.$slots,`default`)]),_:3},16))}});export{d as t};
|