dsh-kenari-plugin 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +281 -0
  3. package/README.md +283 -0
  4. package/assets/kenari-favicon-128.png +0 -0
  5. package/assets/kenari-favicon-256.png +0 -0
  6. package/client/index.js +1998 -0
  7. package/cordis.patch.yml +137 -0
  8. package/lib/billing.d.ts +120 -0
  9. package/lib/billing.d.ts.map +1 -0
  10. package/lib/billing.js +209 -0
  11. package/lib/billing.js.map +1 -0
  12. package/lib/catalog-view.d.ts +78 -0
  13. package/lib/catalog-view.d.ts.map +1 -0
  14. package/lib/catalog-view.js +113 -0
  15. package/lib/catalog-view.js.map +1 -0
  16. package/lib/catalog.d.ts +239 -0
  17. package/lib/catalog.d.ts.map +1 -0
  18. package/lib/catalog.js +445 -0
  19. package/lib/catalog.js.map +1 -0
  20. package/lib/default-route.d.ts +35 -0
  21. package/lib/default-route.d.ts.map +1 -0
  22. package/lib/default-route.js +111 -0
  23. package/lib/default-route.js.map +1 -0
  24. package/lib/errors.d.ts +29 -0
  25. package/lib/errors.d.ts.map +1 -0
  26. package/lib/errors.js +74 -0
  27. package/lib/errors.js.map +1 -0
  28. package/lib/favicon.d.ts +24 -0
  29. package/lib/favicon.d.ts.map +1 -0
  30. package/lib/favicon.js +68 -0
  31. package/lib/favicon.js.map +1 -0
  32. package/lib/http.d.ts +104 -0
  33. package/lib/http.d.ts.map +1 -0
  34. package/lib/http.js +247 -0
  35. package/lib/http.js.map +1 -0
  36. package/lib/index.d.ts +83 -0
  37. package/lib/index.d.ts.map +1 -0
  38. package/lib/index.js +285 -0
  39. package/lib/index.js.map +1 -0
  40. package/lib/llm/adapter.d.ts +78 -0
  41. package/lib/llm/adapter.d.ts.map +1 -0
  42. package/lib/llm/adapter.js +429 -0
  43. package/lib/llm/adapter.js.map +1 -0
  44. package/lib/llm/candidates.d.ts +57 -0
  45. package/lib/llm/candidates.d.ts.map +1 -0
  46. package/lib/llm/candidates.js +86 -0
  47. package/lib/llm/candidates.js.map +1 -0
  48. package/lib/llm/recovery.d.ts +48 -0
  49. package/lib/llm/recovery.d.ts.map +1 -0
  50. package/lib/llm/recovery.js +118 -0
  51. package/lib/llm/recovery.js.map +1 -0
  52. package/lib/llm/retry.d.ts +35 -0
  53. package/lib/llm/retry.d.ts.map +1 -0
  54. package/lib/llm/retry.js +53 -0
  55. package/lib/llm/retry.js.map +1 -0
  56. package/lib/plans.d.ts +59 -0
  57. package/lib/plans.d.ts.map +1 -0
  58. package/lib/plans.js +118 -0
  59. package/lib/plans.js.map +1 -0
  60. package/lib/session-title.d.ts +63 -0
  61. package/lib/session-title.d.ts.map +1 -0
  62. package/lib/session-title.js +280 -0
  63. package/lib/session-title.js.map +1 -0
  64. package/lib/settings.d.ts +35 -0
  65. package/lib/settings.d.ts.map +1 -0
  66. package/lib/settings.js +78 -0
  67. package/lib/settings.js.map +1 -0
  68. package/lib/tools/account.d.ts +11 -0
  69. package/lib/tools/account.d.ts.map +1 -0
  70. package/lib/tools/account.js +132 -0
  71. package/lib/tools/account.js.map +1 -0
  72. package/lib/tools/billing.d.ts +10 -0
  73. package/lib/tools/billing.d.ts.map +1 -0
  74. package/lib/tools/billing.js +100 -0
  75. package/lib/tools/billing.js.map +1 -0
  76. package/lib/tools/count-tokens.d.ts +11 -0
  77. package/lib/tools/count-tokens.d.ts.map +1 -0
  78. package/lib/tools/count-tokens.js +84 -0
  79. package/lib/tools/count-tokens.js.map +1 -0
  80. package/lib/tools/data.d.ts +12 -0
  81. package/lib/tools/data.d.ts.map +1 -0
  82. package/lib/tools/data.js +205 -0
  83. package/lib/tools/data.js.map +1 -0
  84. package/lib/tools/docs.d.ts +13 -0
  85. package/lib/tools/docs.d.ts.map +1 -0
  86. package/lib/tools/docs.js +209 -0
  87. package/lib/tools/docs.js.map +1 -0
  88. package/lib/tools/documents.d.ts +10 -0
  89. package/lib/tools/documents.d.ts.map +1 -0
  90. package/lib/tools/documents.js +118 -0
  91. package/lib/tools/documents.js.map +1 -0
  92. package/lib/tools/media.d.ts +28 -0
  93. package/lib/tools/media.d.ts.map +1 -0
  94. package/lib/tools/media.js +599 -0
  95. package/lib/tools/media.js.map +1 -0
  96. package/lib/tools/shared.d.ts +89 -0
  97. package/lib/tools/shared.d.ts.map +1 -0
  98. package/lib/tools/shared.js +128 -0
  99. package/lib/tools/shared.js.map +1 -0
  100. package/lib/tools/x-search.d.ts +11 -0
  101. package/lib/tools/x-search.d.ts.map +1 -0
  102. package/lib/tools/x-search.js +129 -0
  103. package/lib/tools/x-search.js.map +1 -0
  104. package/lib/web/fallback.d.ts +39 -0
  105. package/lib/web/fallback.d.ts.map +1 -0
  106. package/lib/web/fallback.js +79 -0
  107. package/lib/web/fallback.js.map +1 -0
  108. package/lib/web/fetch.d.ts +19 -0
  109. package/lib/web/fetch.d.ts.map +1 -0
  110. package/lib/web/fetch.js +41 -0
  111. package/lib/web/fetch.js.map +1 -0
  112. package/lib/web/search.d.ts +21 -0
  113. package/lib/web/search.d.ts.map +1 -0
  114. package/lib/web/search.js +47 -0
  115. package/lib/web/search.js.map +1 -0
  116. package/package.json +84 -0
@@ -0,0 +1,113 @@
1
+ /**
2
+ * 浏览器侧模型浏览器的数据端点:`GET /api/kenari.models`。
3
+ *
4
+ * 为什么需要它:浏览器只装得下已经存在的 Remote 命名空间,而 dsh 没有任何一个
5
+ * 能承载"每模型能力标签 + 套餐归属"的命名空间(新增一个要动 dsh 的 api-remotes 装配)。
6
+ * 但 dsh 的 Connection 服务给了插件一个**同源 Fetch 路由**注册点,
7
+ * 于是浏览器可以直接读本端点的 JSON——数据仍全部在 Host 侧算,浏览器不解析 Kenari。
8
+ *
9
+ * 鉴权由 dsh 的 Connection 层负责(Host/Origin 围栏 + 浏览器会话),
10
+ * 所以这里假定"能到达本处理器就是可信的同源页面"。
11
+ * @module dsh-kenari-plugin/catalog-view
12
+ */
13
+ import { CAPABILITY_TAGS, capabilityTagsOf, displayNameOf, isChatCapable, isFreeModel, toModelProfile, } from './catalog.js';
14
+ import { coverageOf } from './plans.js';
15
+ /** 浏览器读取模型视图的路径(Connection 的 Fetch 路由要求落在 `/api/` 下)。 */
16
+ export const KENARI_MODEL_VIEW_PATH = '/api/kenari.models';
17
+ /** 目录行 → 浏览器视图行。 */
18
+ function toView(model, coverage) {
19
+ const covered = coverageOf(coverage, model.id);
20
+ return {
21
+ id: model.id,
22
+ name: displayNameOf(model),
23
+ ...(model.owned_by === undefined ? {} : { ownedBy: model.owned_by }),
24
+ ...(typeof model.context_length === 'number' ? { contextWindow: model.context_length } : {}),
25
+ free: isFreeModel(model),
26
+ beta: model.beta === true,
27
+ ...(typeof model.sunset_at === 'number' && model.sunset_at > 0 ? { sunsetAt: model.sunset_at } : {}),
28
+ chatCapable: isChatCapable(model),
29
+ endpoints: model.endpoints ?? [],
30
+ input: model.modalities?.input ?? [],
31
+ tags: capabilityTagsOf(model),
32
+ plans: covered.plans,
33
+ freeCachePlans: covered.freeCachePlans,
34
+ profile: toModelProfile(model),
35
+ };
36
+ }
37
+ /**
38
+ * 组装一次完整视图。
39
+ *
40
+ * 目录是必需事实(失败即端点失败);套餐表是可选事实(失败只标记 `plansError`),
41
+ * 因为模型目录公开且稳定,而套餐表是站点路由、形状随时可能变。
42
+ */
43
+ export async function buildCatalogView(deps, signal) {
44
+ const [catalogModels, embeddingModels] = await Promise.all([
45
+ deps.catalog.list(undefined, signal),
46
+ deps.catalog.list('embedding', signal),
47
+ ]);
48
+ const seen = new Set();
49
+ const models = [];
50
+ for (const model of [...catalogModels, ...embeddingModels]) {
51
+ if (seen.has(model.id))
52
+ continue;
53
+ seen.add(model.id);
54
+ models.push(model);
55
+ }
56
+ let plans = [];
57
+ let plansError;
58
+ let coverage = new Map();
59
+ try {
60
+ const listed = await deps.plans.list(signal);
61
+ coverage = await deps.plans.coverage(signal);
62
+ plans = listed.map((plan) => ({
63
+ id: plan.id,
64
+ name: plan.name,
65
+ ...(plan.priceIdr === undefined ? {} : { priceIdr: plan.priceIdr }),
66
+ modelCount: plan.scopeModels.length,
67
+ }));
68
+ }
69
+ catch (err) {
70
+ plansError = err instanceof Error ? err.message : String(err);
71
+ deps.http.logger?.warn(`kenari: 套餐表读取失败,模型视图只显示能力标签:${plansError}`);
72
+ }
73
+ return {
74
+ generatedAt: Date.now(),
75
+ plans,
76
+ ...(plansError === undefined ? {} : { plansError }),
77
+ tags: CAPABILITY_TAGS,
78
+ models: models.map((model) => toView(model, coverage)),
79
+ };
80
+ }
81
+ /** 一次 GET/HEAD 的响应;HEAD 只回头部(路由契约要求同时支持两者)。 */
82
+ async function viewResponse(deps, request) {
83
+ let body;
84
+ try {
85
+ body = await buildCatalogView(deps, request.signal);
86
+ }
87
+ catch (err) {
88
+ const message = err instanceof Error ? err.message : String(err);
89
+ deps.http.logger?.warn(`kenari: 模型视图端点失败:${message}`);
90
+ return Response.json({ error: message }, { status: 502 });
91
+ }
92
+ const headers = { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' };
93
+ if (request.method === 'HEAD')
94
+ return new Response(null, { status: 200, headers });
95
+ return new Response(JSON.stringify(body), { status: 200, headers });
96
+ }
97
+ /**
98
+ * 注册模型视图路由。
99
+ *
100
+ * `connection` 是 web profile 才有的服务,所以在缺它的部署里静默跳过——
101
+ * 插件其余能力(工具、web provider、设置节)不依赖浏览器。
102
+ */
103
+ export function registerCatalogView(ctx, deps) {
104
+ ctx.inject(['connection'], (connectionCtx) => {
105
+ connectionCtx.connection.fetch.register({
106
+ path: KENARI_MODEL_VIEW_PATH,
107
+ methods: ['GET', 'HEAD'],
108
+ requestBody: 'buffered',
109
+ fetch: (request) => viewResponse(deps, request),
110
+ });
111
+ });
112
+ }
113
+ //# sourceMappingURL=catalog-view.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-view.js","sourceRoot":"","sources":["../src/catalog-view.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Kenari 模型目录:`GET /v1/models` 同步 + TTL 缓存 + dsh 模型元数据映射。
3
+ *
4
+ * Kenari 目录是**唯一**的模型事实来源(价格、上下文窗口、模态、推理档位、下线时间)。
5
+ * 所有消费方(工具、设置卡片、LlmAdapter)都从这里取,避免各自解析 rc 期字段。
6
+ * 端点与字段名变动只改本文件。
7
+ * @module dsh-kenari-plugin/catalog
8
+ */
9
+ import type { KenariHttpDeps } from './http.js';
10
+ /** 专用能力目录的 modality 取值(`GET /v1/models?modality=`)。 */
11
+ export type KenariModality = 'embedding' | 'rerank' | 'moderation';
12
+ /** `pricing` 块:token 计价(micro-IDR per 1M tokens)。 */
13
+ export interface KenariPricing {
14
+ input?: number | null;
15
+ output?: number | null;
16
+ cache_read?: number | null;
17
+ cache_write?: number | null;
18
+ free?: boolean;
19
+ varies?: boolean;
20
+ currency?: string;
21
+ unit?: string;
22
+ }
23
+ /** `pricing_lines` 行:按端点的计费明细(图像/秒/千字符/请求等非 token 单位)。 */
24
+ export interface KenariPricingLine {
25
+ endpoint?: string;
26
+ billable?: string | null;
27
+ unit?: string;
28
+ variant?: string | null;
29
+ micro_idr?: number;
30
+ }
31
+ /** 目录模型行(字段宽松解析,rc 期缺字段不报错)。 */
32
+ export interface KenariModel {
33
+ id: string;
34
+ object?: string;
35
+ owned_by?: string;
36
+ name?: string;
37
+ /** epoch 秒;非空表示将下线(到期前仍正常服务)。 */
38
+ sunset_at?: number | null;
39
+ context_length?: number;
40
+ modalities?: {
41
+ input?: string[];
42
+ output?: string[];
43
+ };
44
+ reasoning?: boolean;
45
+ reasoning_options?: string[];
46
+ reasoning_toggle?: boolean;
47
+ tool_call?: boolean;
48
+ pricing?: KenariPricing;
49
+ pricing_lines?: KenariPricingLine[];
50
+ endpoints?: string[];
51
+ modality?: string;
52
+ beta?: boolean;
53
+ voices?: string[];
54
+ formats?: string[];
55
+ max_input_chars?: number;
56
+ max_prompt_chars?: number;
57
+ max_lyrics_chars?: number;
58
+ max_duration_secs?: number;
59
+ }
60
+ /** 解析后的模型条目:目录行 + 派生判断,消费方不再重复判定。 */
61
+ export interface ResolvedModel {
62
+ model: KenariModel;
63
+ id: string;
64
+ /** 是否免费(`:free` 后缀或 `pricing.free`)。 */
65
+ free: boolean;
66
+ /** 可用于会话(endpoints 含 chat)。 */
67
+ chatCapable: boolean;
68
+ /** 别名列表(含 `kenari/<id>` 限定形式与配置别名)。 */
69
+ aliases: string[];
70
+ /** 需要提示的警告(beta、即将下线)。 */
71
+ warnings: string[];
72
+ }
73
+ /** 目录解析失败时的可读原因(供工具与设置卡片展示)。 */
74
+ export declare class CatalogError extends Error {
75
+ constructor(message: string, options?: {
76
+ cause?: unknown;
77
+ });
78
+ }
79
+ /** 免费判定:`:free` 后缀或 `pricing.free`。 */
80
+ export declare function isFreeModel(model: KenariModel): boolean;
81
+ /** 会话可用判定:endpoints 含 `chat`;目录未给 endpoints 时按 modality 兜底。 */
82
+ export declare function isChatCapable(model: KenariModel): boolean;
83
+ /** dsh 只声明 text/image 两种输入模态;Kenari 的 audio/video/pdf 输入不映射(避免过度声明)。 */
84
+ export declare function inputModalitiesOf(model: KenariModel): ('text' | 'image')[];
85
+ /** 设置界面用来筛选与标注的能力标签;值就是标签文案本身。 */
86
+ export type CapabilityTag = 'image' | 'audio' | 'video' | 'pdf' | 'embedding';
87
+ /** 标签展示顺序(固定,避免每次渲染顺序漂移)。 */
88
+ export declare const CAPABILITY_TAGS: readonly CapabilityTag[];
89
+ /**
90
+ * 目录行 → 能力标签。
91
+ *
92
+ * 判定用的是**输入**能力与端点两处事实,因为 Kenari 对同一件事只在一处给字段:
93
+ * - 生成类(图像/视频/语音合成)只有 `endpoints`,`modalities.input` 仍是 text
94
+ * - 理解类(看图/听音频/读 PDF)只有 `modalities.input`
95
+ * - embedding 模型只在 `?modality=embedding` 目录里,带 `modality: 'embedding'`
96
+ * 所以两个来源都要看,且都只看事实、不猜(缺字段就不打标签)。
97
+ */
98
+ export declare function capabilityTagsOf(model: KenariModel): CapabilityTag[];
99
+ /**
100
+ * Kenari `reasoning_options` → pi-ai `reasoningEfforts`。
101
+ * Kenari 用 `none` 表示"支持但不发参数",dsh 的对应键是 `off`;其余同名直通。
102
+ * 两侧都不认识的取值直接丢弃——写进设置会让 schemastery 校验整节失败。
103
+ */
104
+ export declare function reasoningEffortsOf(model: KenariModel): Record<string, string> | undefined;
105
+ /**
106
+ * 一个模型的展示名。
107
+ *
108
+ * 目录里只有 8 个模型自带 `name`,而且**都不是会话模型**(语音、图像、视频那几个),
109
+ * 所以会话模型的展示名必须能从 id 还原。这里的推导不是猜:Kenari 给出 `name` 的那 8 个
110
+ * 模型与本函数的输出**逐字一致**(Veo 3.1 Lite、MiniMax Speech 2.8 Turbo、
111
+ * Nano Banana Pro…),`test/catalog-view.mjs` 用它们反测。
112
+ *
113
+ * dsh 的「显示名称」是纯展示字段(不参与请求),所以还原值即使不完美也只是可改的默认值。
114
+ */
115
+ export declare function displayNameOf(model: KenariModel): string;
116
+ /**
117
+ * 每请求最大输出 token 的推荐值。
118
+ *
119
+ * 目录里**没有**这个字段:对全部 76 行实测过,只有 `context_length`,没有
120
+ * `max_output_tokens` / `max_completion_tokens` / `top_provider`。所以它是推出来的:
121
+ *
122
+ * - **窗口的 1/4**:一次回答最多占多少窗口的常见取法,给提示词留 3/4,请求才不会被
123
+ * 自己的上限顶出窗口。厂商公开的比例落在 6%(Gemini 2.5 的 65k / 1M)到
124
+ * 32%(Claude 的 64k / 200k)之间,取 1/4 偏宽——写代码时"被截断"比"留得多"更常见。
125
+ * - **不设下限**:下限看着无害,其实会算错小窗口的模型。目录里 `bge-m3` 的窗口只有 8192,
126
+ * 若按 8192 兜底就等于把整个窗口都推荐成输出。(全部会话模型的窗口都 ≥128K,所以
127
+ * 真正的会话模型从来用不到下限。)
128
+ * - **向下取整到 1K**:窗口不都是 2 的幂(有 128000、255976 这种),直接算会得到
129
+ * 32000 / 63994 这类数字。向下取整同时保证推荐值不超过窗口的 1/4。
130
+ * - **上限 65536**:主流厂商公开的单次输出上限最大就在这一档,再大不代表任何真实能力。
131
+ * 实测网关自己不做这个校验(`max_tokens` 给到 262144 仍返回 200),dsh 也不会把它从
132
+ * 输入预算里扣掉,所以这个上限是"别写没有意义的数",不是"写了会出错"。
133
+ *
134
+ * 目录不公布窗口的模型(18 个,其中只有 `qwen3-8-max` 是会话模型)不写这个字段:
135
+ * 没有窗口可依据时,任何数值都是编的,不如沿用 pi-ai 自己的默认值。
136
+ */
137
+ export declare function recommendedMaxTokens(contextWindow: number | undefined): number | undefined;
138
+ /**
139
+ * 目录行 → pi-ai provider profile 的 model 条目。
140
+ *
141
+ * 这是「把目录里的模型加进 `llm-pi-ai` 路由」时写进用户设置的形状,
142
+ * 字段必须逐个来自目录:pi-ai 的 schema 会拒绝多余或拼错的键。
143
+ *
144
+ * `name` 与 `maxTokens` 都写:前者是 dsh 模型目录里那个「显示名称」框(不写就空着),
145
+ * 后者是每请求输出上限(不写则整条路由共用 pi-ai 的 `defaultMaxTokens` 32768,
146
+ * 于是每个模型看到的都是同一个数)。两者的推导见上面两个函数。
147
+ */
148
+ export declare function toModelProfile(model: KenariModel): {
149
+ id: string;
150
+ name: string;
151
+ contextWindow?: number;
152
+ maxTokens?: number;
153
+ input?: ('text' | 'image')[];
154
+ reasoningEfforts?: Record<string, string>;
155
+ };
156
+ /** micro-IDR → IDR/1M tokens 的十进制字符串(整数不带小数点)。 */
157
+ export declare function microToIdrPerMillion(micro: number): string;
158
+ /** token 价格行:免费与浮动单列,缺失如实说"未公布"。 */
159
+ export declare function formatTokenPrice(model: KenariModel): string;
160
+ /** 非 token 端点单价行;无常驻行时返回空数组。 */
161
+ export declare function formatPricingLines(model: KenariModel): string[];
162
+ /** 端点 → 命中的计费行(variant 优先精确匹配,缺失取第一档)。 */
163
+ export declare function priceLineOf(model: KenariModel, endpoint: string, variant?: string): KenariPricingLine | undefined;
164
+ /** 端点 → 可读单价(micro-IDR);variant 优先精确匹配,缺失取第一档。 */
165
+ export declare function unitPriceMicro(model: KenariModel, endpoint: string, variant?: string): number | undefined;
166
+ /** 计费单位的人读名称(回显口径用)。 */
167
+ export declare function unitLabel(unit: string | undefined): string;
168
+ /** 需要的计费单位(用于按量预估):单位与数量的语义由调用方声明。 */
169
+ export type BillingUnit = 'token_1m' | 'image' | 'second' | '1k_chars' | 'request' | 'megapixel' | 'song';
170
+ /** 按计费行单价 × 数量(数量以该行 unit 为单位)预估费用(micro-IDR)。 */
171
+ export declare function estimateMicro(model: KenariModel, endpoint: string, quantity: number, variant?: string): number | undefined;
172
+ /** 模型体检:beta 标注与下线告警(到期前仍服务,故只提示不拒绝)。 */
173
+ export declare function warningsOf(model: KenariModel, now?: number): string[];
174
+ /** 模型别名:`kenari/<id>` 限定形式 + 配置别名 + 去除限定后的裸 id。 */
175
+ export declare function aliasesOf(model: KenariModel, configured: Record<string, string>): string[];
176
+ /** 别名归一:去掉 `kenari/` 或 `kenari:` 限定前缀,再查配置别名表。 */
177
+ export declare function normalizeModelId(raw: string, configured: Record<string, string>): string;
178
+ /**
179
+ * 目录客户端:进程内 TTL 缓存(目录是公开端点,无需 key)。
180
+ * 并发请求合并到同一次抓取,避免工具族同时冷启动打爆目录端点。
181
+ */
182
+ export declare class KenariCatalog {
183
+ private readonly deps;
184
+ private cache;
185
+ private inflight;
186
+ constructor(deps: KenariHttpDeps);
187
+ /** 缓存有效期取自实时配置:设置页改完下一次读取即生效。 */
188
+ private get ttlMs();
189
+ /** 模型别名表取自实时配置。 */
190
+ private get aliases();
191
+ /** 目录抓取(公开端点):TTL 内直接命中缓存。 */
192
+ list(modality?: KenariModality, signal?: AbortSignal): Promise<KenariModel[]>;
193
+ /** 会话模型目录(endpoints 含 chat),缓存与 list 共用。 */
194
+ chatModels(signal?: AbortSignal): Promise<KenariModel[]>;
195
+ /**
196
+ * 目录解析:别名归一 → 精确匹配 → 大小写不敏感兜底。
197
+ *
198
+ * 默认(无 modality)目录只含 chat 与生成类模型;embedding / rerank /
199
+ * moderation 只在 `?modality=` 目录里。给了 modality 就只多查那一本,
200
+ * 没给则三本都查(各自的响应都走 TTL 缓存,故代价一次性)。
201
+ */
202
+ resolve(rawId: string, modality?: KenariModality, signal?: AbortSignal): Promise<ResolvedModel | undefined>;
203
+ /** 目录行 → 解析后条目。 */
204
+ describe(model: KenariModel): ResolvedModel;
205
+ /** 免费会话模型(`新账户默认 step-3-7-flash:free` 的选型依据)。 */
206
+ freeModels(signal?: AbortSignal): Promise<KenariModel[]>;
207
+ /** 清空缓存(测试与强制刷新用)。 */
208
+ invalidate(): void;
209
+ }
210
+ /** 目录行 → dsh `LlmModelInfo` 形状(adapter 的 listModels 与设置卡片共用)。 */
211
+ export declare function toLlmModelInfo(model: KenariModel, provider: string): {
212
+ provider: string;
213
+ id: string;
214
+ name: string;
215
+ description?: string;
216
+ inputModalities: ('text' | 'image')[];
217
+ };
218
+ /**
219
+ * 目录行 → dsh `LlmResolvedModelInfo` 形状:上下文窗口 + reasoning 档位 + 默认输出上限。
220
+ * `reasoning_options` 的每个值既是 dsh 的 effort id 也是 Kenari 线上的写法,故一一对应。
221
+ */
222
+ export declare function toResolvedModelInfo(model: KenariModel, provider: string): {
223
+ provider: string;
224
+ id: string;
225
+ name: string;
226
+ description?: string;
227
+ inputModalities: ('text' | 'image')[];
228
+ context?: {
229
+ contextWindow: number;
230
+ };
231
+ reasoning?: {
232
+ efforts: {
233
+ id: string;
234
+ name: string;
235
+ }[];
236
+ defaultEffort?: string;
237
+ };
238
+ };
239
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../src/catalog.ts"],"names":[],"mappings":"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"}