llm-simple-router 0.10.9 → 0.10.10

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.
Files changed (48) hide show
  1. package/dist/admin/proxy-enhancement.js +2 -0
  2. package/dist/core/container.d.ts +0 -1
  3. package/dist/core/container.js +0 -1
  4. package/dist/db/logs.d.ts +0 -8
  5. package/dist/db/logs.js +2 -23
  6. package/dist/db/metrics.d.ts +0 -10
  7. package/dist/db/metrics.js +2 -19
  8. package/dist/index.js +0 -16
  9. package/dist/proxy/handler/failover-loop.js +2 -2
  10. package/frontend-dist/assets/{CardContent-VHoT9rgw.js → CardContent-qcSyH2wC.js} +1 -1
  11. package/frontend-dist/assets/{CardTitle-BSx_tBcL.js → CardTitle-BiP1PaEJ.js} +1 -1
  12. package/frontend-dist/assets/{Checkbox-TieofFS-.js → Checkbox-DffzDfGN.js} +1 -1
  13. package/frontend-dist/assets/{CollapsibleContent-Dnt-UfRz.js → CollapsibleContent-BLcA_5sz.js} +1 -1
  14. package/frontend-dist/assets/{CollapsibleTrigger-NW8lciwZ.js → CollapsibleTrigger-CFNX8ZWv.js} +1 -1
  15. package/frontend-dist/assets/{Dashboard-BbzVyAgq.js → Dashboard-DuRjJaT-.js} +1 -1
  16. package/frontend-dist/assets/{Input-BRW038ir.js → Input-D_nV5NLw.js} +1 -1
  17. package/frontend-dist/assets/{Label-D7a61NN6.js → Label-DWvRM0Of.js} +1 -1
  18. package/frontend-dist/assets/{Login-CQtZ3Okd.js → Login-CgiCloZ_.js} +1 -1
  19. package/frontend-dist/assets/{Logs-DYTA66To.js → Logs-XcxKaNRX.js} +1 -1
  20. package/frontend-dist/assets/{MappingEntryEditor-CHFARLUr.js → MappingEntryEditor-DIoQxGfs.js} +1 -1
  21. package/frontend-dist/assets/{ModelCard-DArtFLqF.js → ModelCard-Cm7JtPFg.js} +1 -1
  22. package/frontend-dist/assets/{ModelMappings-dT8omnXQ.js → ModelMappings-CvNdZ4UC.js} +1 -1
  23. package/frontend-dist/assets/{Monitor-B5BNg5oz.js → Monitor-_pspFE5H.js} +1 -1
  24. package/frontend-dist/assets/{Providers-DLd-sAsh.js → Providers-B__y99yf.js} +1 -1
  25. package/frontend-dist/assets/{ProxyEnhancement-D3s6ihsi.js → ProxyEnhancement-Bsp6wbOU.js} +1 -1
  26. package/frontend-dist/assets/{QuickSetup-BjLJXdQm.js → QuickSetup-CLirza5Z.js} +1 -1
  27. package/frontend-dist/assets/{RetryRules-C5LT8jA4.js → RetryRules-D7TEvRsa.js} +1 -1
  28. package/frontend-dist/assets/{RouterKeys-VDfx0YUM.js → RouterKeys-xsdh_HcW.js} +1 -1
  29. package/frontend-dist/assets/{RovingFocusItem-Dvp7T0YJ.js → RovingFocusItem-D2UUj3n_.js} +1 -1
  30. package/frontend-dist/assets/{Schedules-CGk4VMEW.js → Schedules-D7GDAZXY.js} +1 -1
  31. package/frontend-dist/assets/{Settings-C0Bq5Vlz.js → Settings-BI_ABQ8W.js} +1 -1
  32. package/frontend-dist/assets/{Setup-CkKRbnLE.js → Setup-C8a8Q9z2.js} +1 -1
  33. package/frontend-dist/assets/{Switch-DPzewpLO.js → Switch-DhyEtE7A.js} +1 -1
  34. package/frontend-dist/assets/{TooltipTrigger-CySCLI9s.js → TooltipTrigger-BVNmzsHP.js} +1 -1
  35. package/frontend-dist/assets/{TransformRulesForm-BFhiXjTu.js → TransformRulesForm--5C_xErR.js} +1 -1
  36. package/frontend-dist/assets/{UnifiedRequestDialog-COo6SGUN.js → UnifiedRequestDialog-O6Ld5DZI.js} +1 -1
  37. package/frontend-dist/assets/{VisuallyHiddenInput-D7rPKtIA.js → VisuallyHiddenInput-CPQ662FS.js} +1 -1
  38. package/frontend-dist/assets/{button-Cd7Qd3fz.js → button-BWSfarSC.js} +2 -2
  39. package/frontend-dist/assets/{copy-JcgwJljq.js → copy-DOxEdrz9.js} +1 -1
  40. package/frontend-dist/assets/{dialog-BZpiHm7Q.js → dialog--eSL5k5e.js} +1 -1
  41. package/frontend-dist/assets/{index-D6ACTK1W.js → index-B9huoJLE.js} +2 -2
  42. package/frontend-dist/assets/{trash-2-CJq-sfA4.js → trash-2-CNeuAYsm.js} +1 -1
  43. package/frontend-dist/assets/{useClipboard-C2mKqlsb.js → useClipboard-CnSGwYPF.js} +1 -1
  44. package/frontend-dist/assets/{useLogRetention-DYo82fwB.js → useLogRetention-Dul_BUBe.js} +1 -1
  45. package/frontend-dist/index.html +2 -2
  46. package/package.json +1 -1
  47. package/dist/db/log-write-buffer.d.ts +0 -43
  48. package/dist/db/log-write-buffer.js +0 -91
@@ -1,5 +1,6 @@
1
1
  import { Type } from "@sinclair/typebox";
2
2
  import { getSetting, setSetting } from "../db/settings.js";
3
+ import { clearEnhancementConfigCache } from "../proxy/routing/enhancement-config.js";
3
4
  const UpdateProxyEnhancementSchema = Type.Object({
4
5
  tool_call_loop_enabled: Type.Boolean(),
5
6
  stream_loop_enabled: Type.Boolean(),
@@ -35,6 +36,7 @@ export const adminProxyEnhancementRoutes = (app, options, done) => {
35
36
  tool_error_logging_enabled: body.tool_error_logging_enabled,
36
37
  };
37
38
  setSetting(db, "proxy_enhancement", JSON.stringify(config));
39
+ clearEnhancementConfigCache();
38
40
  return reply.send({ success: true });
39
41
  });
40
42
  done();
@@ -10,7 +10,6 @@ export declare const SERVICE_KEYS: {
10
10
  readonly pluginRegistry: "pluginRegistry";
11
11
  readonly formatRegistry: "formatRegistry";
12
12
  readonly logFileWriter: "logFileWriter";
13
- readonly logWriteBuffer: "logWriteBuffer";
14
13
  readonly proxyAgentFactory: "proxyAgentFactory";
15
14
  };
16
15
  export type ServiceKey = (typeof SERVICE_KEYS)[keyof typeof SERVICE_KEYS];
@@ -10,7 +10,6 @@ export const SERVICE_KEYS = {
10
10
  pluginRegistry: "pluginRegistry",
11
11
  formatRegistry: "formatRegistry",
12
12
  logFileWriter: "logFileWriter",
13
- logWriteBuffer: "logWriteBuffer",
14
13
  proxyAgentFactory: "proxyAgentFactory",
15
14
  };
16
15
  /**
package/dist/db/logs.d.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import Database from "better-sqlite3";
2
2
  import type { LogFileWriter } from "../storage/log-file-writer.js";
3
3
  import { type RetryMatcher } from "../proxy/log-detail-policy.js";
4
- import type { LogWriteBuffer } from "./log-write-buffer.js";
5
4
  export interface RequestLog {
6
5
  id: string;
7
6
  api_type: string;
@@ -55,13 +54,6 @@ export interface LogWriteContext {
55
54
  logFileWriter?: LogFileWriter | null;
56
55
  responseBody?: string | null;
57
56
  }
58
- /** 初始化日志缓冲(buildApp 时调用) */
59
- export declare function initLogBuffer(buffer: LogWriteBuffer): void;
60
- /** 停止日志缓冲,同步 flush 剩余数据(close 时调用) */
61
- export declare function stopLogBuffer(): void;
62
- /** 原始 DB INSERT 逻辑(无缓冲) */
63
- declare function rawInsertRequestLog(db: Database.Database, log: RequestLogInsert, writeContext?: LogWriteContext): void;
64
- export { rawInsertRequestLog };
65
57
  export declare function insertRequestLog(db: Database.Database, log: RequestLogInsert, writeContext?: LogWriteContext): void;
66
58
  export declare function getRequestLogs(db: Database.Database, options: {
67
59
  page: number;
package/dist/db/logs.js CHANGED
@@ -10,20 +10,7 @@ const LOG_LIST_SELECT = `rl.id, rl.api_type, rl.model, rl.provider_id, rl.status
10
10
  rm.input_tokens_estimated, rm.client_type, rm.cache_read_tokens_estimated,
11
11
  COALESCE(p.name, rl.provider_id) AS provider_name`;
12
12
  const LOG_LIST_JOIN = `LEFT JOIN providers p ON p.id = rl.provider_id LEFT JOIN request_metrics rm ON rm.request_log_id = rl.id`;
13
- /** 模块级缓冲实例,由 initLogBuffer 设置 */
14
- let logBuffer = null;
15
- /** 初始化日志缓冲(buildApp 时调用) */
16
- export function initLogBuffer(buffer) {
17
- logBuffer = buffer;
18
- }
19
- /** 停止日志缓冲,同步 flush 剩余数据(close 时调用) */
20
- export function stopLogBuffer() {
21
- if (logBuffer) {
22
- logBuffer.stop();
23
- logBuffer = null;
24
- }
25
- }
26
- /** 原始 DB INSERT 逻辑(无缓冲) */
13
+ /** DB INSERT 逻辑 */
27
14
  function rawInsertRequestLog(db, log, writeContext) {
28
15
  // 详情保留判定
29
16
  const preserveDetail = shouldPreserveDetail(log.status_code, writeContext?.responseBody ?? null, writeContext?.matcher ?? null, !!writeContext?.logFileWriter);
@@ -32,8 +19,6 @@ function rawInsertRequestLog(db, log, writeContext) {
32
19
  is_retry, is_failover, original_request_id, router_key_id, original_model, session_id, pipeline_snapshot)
33
20
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(log.id, log.api_type, log.model, log.provider_id, log.status_code, log.client_status_code ?? null, log.latency_ms, log.is_stream, log.error_message, log.created_at, preserveDetail ? (log.client_request ?? null) : null, preserveDetail ? (log.upstream_request ?? null) : null, preserveDetail ? (log.upstream_response ?? null) : null, log.is_retry ?? 0, log.is_failover ?? 0, log.original_request_id ?? null, log.router_key_id ?? null, log.original_model ?? null, log.session_id ?? null, log.pipeline_snapshot ?? null);
34
21
  }
35
- // 导出给 LogWriteBuffer 的原始插入函数引用
36
- export { rawInsertRequestLog };
37
22
  export function insertRequestLog(db, log, writeContext) {
38
23
  // 文件写入:始终同步调用(WriteStream 内部异步,不阻塞事件循环)
39
24
  if (writeContext?.logFileWriter) {
@@ -49,13 +34,7 @@ export function insertRequestLog(db, log, writeContext) {
49
34
  pipeline_snapshot: log.pipeline_snapshot ?? null,
50
35
  });
51
36
  }
52
- // DB INSERT:缓冲已初始化则走缓冲,否则走同步
53
- if (logBuffer) {
54
- logBuffer.pushLog(log, writeContext);
55
- }
56
- else {
57
- rawInsertRequestLog(db, log, writeContext);
58
- }
37
+ rawInsertRequestLog(db, log, writeContext);
59
38
  }
60
39
  function buildLogWhereClause(options, baseCondition) {
61
40
  let where = baseCondition;
@@ -1,5 +1,4 @@
1
1
  import Database from "better-sqlite3";
2
- import type { LogWriteBuffer } from "./log-write-buffer.js";
3
2
  export type MetricsPeriod = "1h" | "5h" | "6h" | "24h" | "7d" | "30d";
4
3
  export type MetricsMetric = "ttft" | "tps" | "text_tps" | "thinking_tps" | "tool_use_tps" | "non_thinking_tps" | "total_tps" | "tokens" | "cache_rate" | "request_count" | "input_tokens" | "output_tokens" | "cache_hit_tokens";
5
4
  export interface MetricsRow {
@@ -49,15 +48,6 @@ export type MetricsInsert = {
49
48
  non_thinking_tps?: number | null;
50
49
  total_tps?: number | null;
51
50
  };
52
- /** 设置缓冲实例(由 index.ts buildApp 调用,传入与 logs.ts 共享的 buffer) */
53
- export declare function setLogBuffer(buffer: LogWriteBuffer): void;
54
- /** 清除缓冲引用(由 stopLogBuffer 调用) */
55
- export declare function clearLogBuffer(): void;
56
- /** 原始 DB INSERT 逻辑(无缓冲) */
57
- declare function rawInsertMetrics(db: Database.Database, m: MetricsInsert & {
58
- id: string;
59
- }): void;
60
- export { rawInsertMetrics };
61
51
  export declare function insertMetrics(db: Database.Database, m: MetricsInsert): string;
62
52
  export interface MetricsSummaryRow {
63
53
  provider_id: string;
@@ -1,17 +1,7 @@
1
1
  import { randomUUID } from "crypto";
2
2
  import { MS_PER_SECOND } from "../core/constants.js";
3
3
  import { getCachedStmt } from "./helpers.js";
4
- /** 模块级缓冲实例,与 logs.ts 共享同一个 LogWriteBuffer */
5
- let logBuffer = null;
6
- /** 设置缓冲实例(由 index.ts buildApp 调用,传入与 logs.ts 共享的 buffer) */
7
- export function setLogBuffer(buffer) {
8
- logBuffer = buffer;
9
- }
10
- /** 清除缓冲引用(由 stopLogBuffer 调用) */
11
- export function clearLogBuffer() {
12
- logBuffer = null;
13
- }
14
- /** 原始 DB INSERT 逻辑(无缓冲) */
4
+ /** DB INSERT 逻辑 */
15
5
  function rawInsertMetrics(db, m) {
16
6
  getCachedStmt(db, `INSERT INTO request_metrics (id, request_log_id, provider_id, backend_model, api_type, router_key_id, status_code,
17
7
  input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens, ttft_ms, total_duration_ms, tokens_per_second, stop_reason, is_complete, input_tokens_estimated,
@@ -20,16 +10,9 @@ function rawInsertMetrics(db, m) {
20
10
  thinking_tps, total_tps, non_thinking_duration_ms, non_thinking_tps)
21
11
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(m.id, m.request_log_id, m.provider_id, m.backend_model, m.api_type, m.router_key_id ?? null, m.status_code ?? null, m.input_tokens ?? null, m.output_tokens ?? null, m.cache_creation_tokens ?? null, m.cache_read_tokens ?? null, m.ttft_ms ?? null, m.total_duration_ms ?? null, m.tokens_per_second ?? null, m.stop_reason ?? null, m.is_complete ?? 1, m.input_tokens_estimated ?? 0, m.client_type ?? 'unknown', m.cache_read_tokens_estimated ?? 0, m.thinking_tokens ?? null, m.text_tokens ?? null, m.tool_use_tokens ?? null, m.thinking_duration_ms ?? null, m.thinking_tps ?? null, m.total_tps ?? null, m.non_thinking_duration_ms ?? null, m.non_thinking_tps ?? null);
22
12
  }
23
- // 导出给 LogWriteBuffer 的原始插入函数引用
24
- export { rawInsertMetrics };
25
13
  export function insertMetrics(db, m) {
26
14
  const id = randomUUID();
27
- if (logBuffer) {
28
- logBuffer.pushMetrics({ ...m, id });
29
- }
30
- else {
31
- rawInsertMetrics(db, { ...m, id });
32
- }
15
+ rawInsertMetrics(db, { ...m, id });
33
16
  return id;
34
17
  }
35
18
  const PERIOD_OFFSET = {
package/dist/index.js CHANGED
@@ -5,11 +5,6 @@ import { existsSync } from "node:fs";
5
5
  import { randomUUID } from "crypto";
6
6
  import Fastify from "fastify";
7
7
  import { insertRequestLog } from "./db/logs.js";
8
- import { initLogBuffer, stopLogBuffer } from "./db/logs.js";
9
- import { setLogBuffer, clearLogBuffer } from "./db/metrics.js";
10
- import { LogWriteBuffer } from "./db/log-write-buffer.js";
11
- import { rawInsertRequestLog } from "./db/logs.js";
12
- import { rawInsertMetrics } from "./db/metrics.js";
13
8
  import { HTTP_NOT_FOUND, HTTP_INTERNAL_ERROR, getProxyApiType } from "./core/constants.js";
14
9
  import { API_CODE, apiError, isAdminApiResponse, statusToApiCode } from "./admin/api-response.js";
15
10
  const PROVIDER_DEFAULT_QUEUE_TIMEOUT_MS = 5000;
@@ -219,14 +214,6 @@ export async function buildApp(options) {
219
214
  ? null
220
215
  : new LogFileWriter(logsDir, { enabled: getDetailLogEnabled(db) });
221
216
  container.register(SERVICE_KEYS.logFileWriter, () => logFileWriter);
222
- // 日志 DB 写入缓冲(非 :memory: 模式)
223
- const logWriteBuffer = isMemoryDb
224
- ? null
225
- : new LogWriteBuffer(db, rawInsertRequestLog, rawInsertMetrics);
226
- if (logWriteBuffer) {
227
- initLogBuffer(logWriteBuffer);
228
- setLogBuffer(logWriteBuffer);
229
- }
230
217
  // 注册 AdaptiveController(依赖已注册的 semaphoreManager)
231
218
  container.register(SERVICE_KEYS.adaptiveController, (c) => {
232
219
  const ac = new AdaptiveController(c.resolve(SERVICE_KEYS.semaphoreManager), app.log);
@@ -343,9 +330,6 @@ export async function buildApp(options) {
343
330
  proxyAgentFactory.invalidateAll();
344
331
  const sessionTracker = container.resolve(SERVICE_KEYS.sessionTracker);
345
332
  sessionTracker.stop();
346
- // 同步 flush DB 日志缓冲(在 flush 文件缓冲之前)
347
- stopLogBuffer();
348
- clearLogBuffer();
349
333
  // Flush LogFileWriter 的 WriteStream 缓冲数据到磁盘
350
334
  await logFileWriter?.stop();
351
335
  // 等待活跃代理请求自然完成,超时后强制关闭所有连接。
@@ -393,10 +393,10 @@ export async function executeFailoverLoop(ctx, errors, deps, upstreamPath, adapt
393
393
  return reply;
394
394
  }
395
395
  // 其他未知错误
396
- const errMsg = e instanceof Error ? e.message : e instanceof Error ? e.message : JSON.stringify(e);
396
+ const errMsg = e instanceof Error ? e.message : JSON.stringify(e);
397
397
  request.log.debug({ logId, error: errMsg, action: "upstream_error" });
398
398
  insertRequestLog(db, {
399
- id: logId, api_type: clientApiType,
399
+ id: randomUUID(), api_type: clientApiType,
400
400
  model: clientModel, provider_id: provider.id,
401
401
  status_code: UPSTREAM_ERROR_STATUS, latency_ms: Date.now() - startTime, is_stream: isStream ? 1 : 0,
402
402
  error_message: errMsg || "Upstream connection failed", created_at: new Date().toISOString(),
@@ -1 +1 @@
1
- import{Ut as e,Vt as t,Z as n,et as r,ft as i,ht as a,r as o}from"./button-Cd7Qd3fz.js";var s=[`data-size`],c=r({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(r){let c=r;return(l,u)=>(i(),n(`div`,{"data-slot":`card`,"data-size":r.size,class:e(t(o)(`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))},[a(l.$slots,`default`)],10,s))}}),l=r({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-content`,class:e(t(o)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[a(r.$slots,`default`)],2))}});export{c as n,l as t};
1
+ import{Ut as e,Vt as t,Z as n,et as r,ft as i,ht as a,r as o}from"./button-BWSfarSC.js";var s=[`data-size`],c=r({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(r){let c=r;return(l,u)=>(i(),n(`div`,{"data-slot":`card`,"data-size":r.size,class:e(t(o)(`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))},[a(l.$slots,`default`)],10,s))}}),l=r({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-content`,class:e(t(o)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[a(r.$slots,`default`)],2))}});export{c as n,l as t};
@@ -1 +1 @@
1
- import{Ut as e,Vt as t,Z as n,et as r,ft as i,ht as a,r as o}from"./button-Cd7Qd3fz.js";var s=r({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-header`,class:e(t(o)(`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))},[a(r.$slots,`default`)],2))}}),c=r({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-title`,class:e(t(o)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[a(r.$slots,`default`)],2))}});export{s as n,c as t};
1
+ import{Ut as e,Vt as t,Z as n,et as r,ft as i,ht as a,r as o}from"./button-BWSfarSC.js";var s=r({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-header`,class:e(t(o)(`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))},[a(r.$slots,`default`)],2))}}),c=r({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(r){let s=r;return(r,c)=>(i(),n(`div`,{"data-slot":`card-title`,class:e(t(o)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[a(r.$slots,`default`)],2))}});export{s as n,c as t};
@@ -1 +1 @@
1
- import{$ as e,Tt as t,U as n,Vt as r,W as i,Wt as a,X as o,Y as s,_t as c,et as l,ft as u,ht as d,i as f,m as p,nt as m,o as h,q as g,r as _,st as v,x as y}from"./button-Cd7Qd3fz.js";import{t as b}from"./VisuallyHiddenInput-D7rPKtIA.js";import{t as x}from"./RovingFocusItem-Dvp7T0YJ.js";import{B as S,G as C,H as w,L as T,Y as E,q as D,ut as O}from"./index-D6ACTK1W.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=D(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=D(`CheckboxRoot`),I=l({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(e,{emit:a}){let l=e,m=a,{forwardRef:_,currentElement:y}=h(),S=A(null),T=p(l,`modelValue`,m,{defaultValue:l.defaultValue??l.falseValue,passive:l.modelValue===void 0}),D=g(()=>S?.disabled.value||l.disabled),O=g(()=>E(T.value,l.trueValue)),j=g(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,l.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=l.trueValue:T.value=O.value?l.falseValue:l.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,l.value)){let t=e.findIndex(e=>E(e,l.value));e.splice(t,1)}else e.push(l.value);S.modelValue.value=e}}let I=w(y),L=g(()=>l.id&&y.value?document.querySelector(`[for="${l.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(e,a)=>(u(),s(c(r(S)?.rovingFocus.value?r(x):r(f)),v(e.$attrs,{id:e.id,ref:r(_),role:`checkbox`,"as-child":e.asChild,as:e.as,type:e.as===`button`?`button`:void 0,"aria-checked":r(M)(j.value)?`mixed`:j.value,"aria-required":e.required,"aria-label":e.$attrs[`aria-label`]||L.value,"data-state":r(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:r(S)?.rovingFocus.value?!D.value:void 0,onKeydown:n(i(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:t(()=>[d(e.$slots,`default`,{modelValue:r(T),state:j.value}),r(I)&&e.name&&!r(S)?(u(),s(r(b),{key:0,type:`checkbox`,checked:!!j.value,name:e.name,value:e.value,disabled:D.value,required:e.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):o(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=l({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(n){let{forwardRef:i}=h(),a=P();return(n,o)=>(u(),s(r(T),{present:n.forceMount||r(M)(r(a).state.value)||r(a).state.value===!0},{default:t(()=>[e(r(f),v({ref:r(i),"data-state":r(N)(r(a).state.value),"data-disabled":r(a).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":n.asChild,as:n.as},n.$attrs),{default:t(()=>[d(n.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=l({__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(n,{emit:i}){let o=n,c=i,l=S(y(o,`class`),c);return(n,i)=>(u(),s(r(I),v({"data-slot":`checkbox`},r(l),{class:r(_)(`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`,o.class)}),{default:t(i=>[e(r(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:t(()=>[d(n.$slots,`default`,a(m(i)),()=>[e(r(O))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
1
+ import{$ as e,Tt as t,U as n,Vt as r,W as i,Wt as a,X as o,Y as s,_t as c,et as l,ft as u,ht as d,i as f,m as p,nt as m,o as h,q as g,r as _,st as v,x as y}from"./button-BWSfarSC.js";import{t as b}from"./VisuallyHiddenInput-CPQ662FS.js";import{t as x}from"./RovingFocusItem-D2UUj3n_.js";import{B as S,G as C,H as w,L as T,Y as E,q as D,ut as O}from"./index-B9huoJLE.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=D(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=D(`CheckboxRoot`),I=l({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(e,{emit:a}){let l=e,m=a,{forwardRef:_,currentElement:y}=h(),S=A(null),T=p(l,`modelValue`,m,{defaultValue:l.defaultValue??l.falseValue,passive:l.modelValue===void 0}),D=g(()=>S?.disabled.value||l.disabled),O=g(()=>E(T.value,l.trueValue)),j=g(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,l.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=l.trueValue:T.value=O.value?l.falseValue:l.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,l.value)){let t=e.findIndex(e=>E(e,l.value));e.splice(t,1)}else e.push(l.value);S.modelValue.value=e}}let I=w(y),L=g(()=>l.id&&y.value?document.querySelector(`[for="${l.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(e,a)=>(u(),s(c(r(S)?.rovingFocus.value?r(x):r(f)),v(e.$attrs,{id:e.id,ref:r(_),role:`checkbox`,"as-child":e.asChild,as:e.as,type:e.as===`button`?`button`:void 0,"aria-checked":r(M)(j.value)?`mixed`:j.value,"aria-required":e.required,"aria-label":e.$attrs[`aria-label`]||L.value,"data-state":r(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:r(S)?.rovingFocus.value?!D.value:void 0,onKeydown:n(i(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:t(()=>[d(e.$slots,`default`,{modelValue:r(T),state:j.value}),r(I)&&e.name&&!r(S)?(u(),s(r(b),{key:0,type:`checkbox`,checked:!!j.value,name:e.name,value:e.value,disabled:D.value,required:e.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):o(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=l({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(n){let{forwardRef:i}=h(),a=P();return(n,o)=>(u(),s(r(T),{present:n.forceMount||r(M)(r(a).state.value)||r(a).state.value===!0},{default:t(()=>[e(r(f),v({ref:r(i),"data-state":r(N)(r(a).state.value),"data-disabled":r(a).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":n.asChild,as:n.as},n.$attrs),{default:t(()=>[d(n.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=l({__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(n,{emit:i}){let o=n,c=i,l=S(y(o,`class`),c);return(n,i)=>(u(),s(r(I),v({"data-slot":`checkbox`},r(l),{class:r(_)(`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`,o.class)}),{default:t(i=>[e(r(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:t(()=>[d(n.$slots,`default`,a(m(i)),()=>[e(r(O))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
@@ -1 +1 @@
1
- import{$ as e,Nt as t,Rt as n,St as r,Tt as i,Vt as a,Wt as o,X as s,Y as c,ct as l,d as u,et as d,ft as f,ht as p,i as m,m as h,nt as g,o as _,q as v,st as y,ut as b}from"./button-Cd7Qd3fz.js";import{B as x,L as S,q as C,z as w}from"./index-D6ACTK1W.js";var[T,E]=C(`CollapsibleRoot`),D=d({__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(e,{expose:t,emit:r}){let o=e,s=h(o,`open`,r,{defaultValue:o.defaultOpen,passive:o.open===void 0}),{disabled:l,unmountOnHide:u}=n(o);return E({contentId:``,disabled:l,open:s,unmountOnHide:u,onOpenToggle:()=>{l.value||(s.value=!s.value)}}),t({open:s}),_(),(e,t)=>(f(),c(a(m),{as:e.as,"as-child":o.asChild,"data-state":a(s)?`open`:`closed`,"data-disabled":a(l)?``:void 0},{default:i(()=>[p(e.$slots,`default`,{open:a(s)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=d({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:o}){let d=n,h=o,g=T();g.contentId||=w(void 0,`reka-collapsible-content`);let x=t(),{forwardRef:C,currentElement:E}=_(),D=t(0),O=t(0),k=v(()=>g.open.value),A=t(k.value),j=t();r(()=>[k.value,x.value?.present],async()=>{await l();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=v(()=>A.value&&g.open.value);return b(()=>{requestAnimationFrame(()=>{A.value=!1})}),u(E,`beforematch`,e=>{requestAnimationFrame(()=>{g.onOpenToggle(),h(`contentFound`)})}),(t,n)=>(f(),c(a(S),{ref_key:`presentRef`,ref:x,present:t.forceMount||a(g).open.value,"force-mount":!0},{default:i(({present:n})=>[e(a(m),y(t.$attrs,{id:a(g).contentId,ref:a(C),"as-child":d.asChild,as:t.as,hidden:n?void 0:a(g).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:a(g).open.value?`open`:`closed`,"data-disabled":a(g).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:i(()=>[!a(g).unmountOnHide.value||n?p(t.$slots,`default`,{key:0}):s(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=d({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:t}){let n=x(e,t);return(e,t)=>(f(),c(a(D),y({"data-slot":`collapsible`},a(n)),{default:i(t=>[p(e.$slots,`default`,o(g(t)))]),_:3},16))}}),A=d({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,n)=>(f(),c(a(O),y({"data-slot":`collapsible-content`},t),{default:i(()=>[p(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
1
+ import{$ as e,Nt as t,Rt as n,St as r,Tt as i,Vt as a,Wt as o,X as s,Y as c,ct as l,d as u,et as d,ft as f,ht as p,i as m,m as h,nt as g,o as _,q as v,st as y,ut as b}from"./button-BWSfarSC.js";import{B as x,L as S,q as C,z as w}from"./index-B9huoJLE.js";var[T,E]=C(`CollapsibleRoot`),D=d({__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(e,{expose:t,emit:r}){let o=e,s=h(o,`open`,r,{defaultValue:o.defaultOpen,passive:o.open===void 0}),{disabled:l,unmountOnHide:u}=n(o);return E({contentId:``,disabled:l,open:s,unmountOnHide:u,onOpenToggle:()=>{l.value||(s.value=!s.value)}}),t({open:s}),_(),(e,t)=>(f(),c(a(m),{as:e.as,"as-child":o.asChild,"data-state":a(s)?`open`:`closed`,"data-disabled":a(l)?``:void 0},{default:i(()=>[p(e.$slots,`default`,{open:a(s)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=d({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:o}){let d=n,h=o,g=T();g.contentId||=w(void 0,`reka-collapsible-content`);let x=t(),{forwardRef:C,currentElement:E}=_(),D=t(0),O=t(0),k=v(()=>g.open.value),A=t(k.value),j=t();r(()=>[k.value,x.value?.present],async()=>{await l();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=v(()=>A.value&&g.open.value);return b(()=>{requestAnimationFrame(()=>{A.value=!1})}),u(E,`beforematch`,e=>{requestAnimationFrame(()=>{g.onOpenToggle(),h(`contentFound`)})}),(t,n)=>(f(),c(a(S),{ref_key:`presentRef`,ref:x,present:t.forceMount||a(g).open.value,"force-mount":!0},{default:i(({present:n})=>[e(a(m),y(t.$attrs,{id:a(g).contentId,ref:a(C),"as-child":d.asChild,as:t.as,hidden:n?void 0:a(g).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:a(g).open.value?`open`:`closed`,"data-disabled":a(g).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:i(()=>[!a(g).unmountOnHide.value||n?p(t.$slots,`default`,{key:0}):s(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=d({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:t}){let n=x(e,t);return(e,t)=>(f(),c(a(D),y({"data-slot":`collapsible`},a(n)),{default:i(t=>[p(e.$slots,`default`,o(g(t)))]),_:3},16))}}),A=d({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,n)=>(f(),c(a(O),y({"data-slot":`collapsible-content`},t),{default:i(()=>[p(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
@@ -1 +1 @@
1
- import{Tt as e,Vt as t,Y as n,et as r,ft as i,ht as a,i as o,o as s,st as c}from"./button-Cd7Qd3fz.js";import{r as l}from"./CollapsibleContent-Dnt-UfRz.js";var u=r({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(r){let c=r;s();let u=l();return(r,s)=>(i(),n(t(o),{type:r.as===`button`?`button`:void 0,as:r.as,"as-child":c.asChild,"aria-controls":t(u).contentId,"aria-expanded":t(u).open.value,"data-state":t(u).open.value?`open`:`closed`,"data-disabled":t(u).disabled?.value?``:void 0,disabled:t(u).disabled?.value,onClick:t(u).onOpenToggle},{default:e(()=>[a(r.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=r({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(r){let o=r;return(r,s)=>(i(),n(t(u),c({"data-slot":`collapsible-trigger`},o),{default:e(()=>[a(r.$slots,`default`)]),_:3},16))}});export{d as t};
1
+ import{Tt as e,Vt as t,Y as n,et as r,ft as i,ht as a,i as o,o as s,st as c}from"./button-BWSfarSC.js";import{r as l}from"./CollapsibleContent-BLcA_5sz.js";var u=r({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(r){let c=r;s();let u=l();return(r,s)=>(i(),n(t(o),{type:r.as===`button`?`button`:void 0,as:r.as,"as-child":c.asChild,"aria-controls":t(u).contentId,"aria-expanded":t(u).open.value,"data-state":t(u).open.value?`open`:`closed`,"data-disabled":t(u).disabled?.value?``:void 0,disabled:t(u).disabled?.value,onClick:t(u).onOpenToggle},{default:e(()=>[a(r.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=r({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(r){let o=r;return(r,s)=>(i(),n(t(u),c({"data-slot":`collapsible-trigger`},o),{default:e(()=>[a(r.$slots,`default`)]),_:3},16))}});export{d as t};