@pactor-app/skills 1.34.0 → 1.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/package.json +1 -1
  2. package/pactor-prd/SKILL.md +18 -21
  3. package/pactor-prd/references/acceptance-checklist.md +1 -1
  4. package/pactor-prd/references/data-api.md +35 -0
  5. package/pactor-prd/references/incremental-wireframe-delta.md +8 -9
  6. package/pactor-prd/references/page-inventory-and-files.md +2 -2
  7. package/pactor-prd/references/page-templates.md +59 -12
  8. package/pactor-prd/references/project-structure.md +1 -1
  9. package/pactor-prd/template/README.md +4 -4
  10. package/pactor-prd/template/app/api/d/[...parts]/route.ts +80 -0
  11. package/pactor-prd/template/app/layout.tsx +1 -3
  12. package/pactor-prd/template/next.config.js +2 -2
  13. package/pactor-prd/template/pnpm-lock.yaml +97 -97
  14. package/pactor-prd/template/src/pactor/App.tsx +3 -2
  15. package/pactor-prd/template/src/pactor/actions.ts +5 -431
  16. package/pactor-prd/template/src/pactor/config.ts +12 -4
  17. package/pactor-prd/template/src/server/yaml/common/dashboard.yaml +1 -1
  18. package/pactor-prd/template/src/server/yaml/common/login.yaml +46 -75
  19. package/pactor-prd/template/src/server/yaml/models/data-list.yaml +4 -4
  20. package/pactor-prd/template/src/server/yaml/provider/provider-detail.yaml +2 -2
  21. package/pactor-prd/template/src/server/yaml/provider/provider-edit.yaml +1 -1
  22. package/pactor-prd/template/src/server/yaml/provider/provider-list.yaml +1 -1
  23. package/pactor-prd/template/src/server/yaml/route/route-detail.yaml +1 -1
  24. package/pactor-prd/template/src/server/yaml/route/route-edit.yaml +1 -1
  25. package/pactor-prd/template/src/server/yaml/route/route-list.yaml +1 -1
  26. package/pactor-prd/template/src/server/yaml/sitemap.yaml +2 -6
  27. package/pactor-prd/references/mock-data-routes.md +0 -66
  28. package/pactor-prd/template/app/api/data/[...parts]/route.ts +0 -160
  29. package/pactor-prd/template/app/login.css +0 -122
  30. package/pactor-prd/template/src/pactor/mocks/audit-mock.ts +0 -403
  31. package/pactor-prd/template/src/pactor/mocks/call-logs-mock.ts +0 -875
  32. package/pactor-prd/template/src/pactor/mocks/client-debug-mock.ts +0 -188
  33. package/pactor-prd/template/src/pactor/mocks/client-templates-mock.ts +0 -497
  34. package/pactor-prd/template/src/pactor/mocks/clients-mock.ts +0 -483
  35. package/pactor-prd/template/src/pactor/mocks/costs-mock.ts +0 -406
  36. package/pactor-prd/template/src/pactor/mocks/dashboard-mock.ts +0 -192
  37. package/pactor-prd/template/src/pactor/mocks/data-list-mock.ts +0 -84
  38. package/pactor-prd/template/src/pactor/mocks/model-debug-mock.ts +0 -144
  39. package/pactor-prd/template/src/pactor/mocks/models-mock.ts +0 -799
  40. package/pactor-prd/template/src/pactor/mocks/ops-usage-mock.ts +0 -806
  41. package/pactor-prd/template/src/pactor/mocks/providers-mock.ts +0 -424
  42. package/pactor-prd/template/src/pactor/mocks/routes-mock.ts +0 -604
  43. package/pactor-prd/template/src/pactor/services.ts +0 -200
@@ -1,799 +0,0 @@
1
- /**
2
- * Model 演示数据服务(MVP mock,静态页面)。
3
- * model.list / model.detail 注册为 Pactor service;接入真实后端后替换为
4
- * http / service 数据源,DSL 绑定路径保持不变。
5
- * 数据形态对齐 PRD《01-Model列表页》《02-Model详情页》《03-Model新增编辑页》(§7.2、§7.3)。
6
- */
7
-
8
- export type ModelStatus = "enabled" | "disabled";
9
- export type ModelType = "LLM" | "Embedding" | "Image" | "Audio";
10
-
11
- /** 标准价格分档:upto=null 表示无上限档(∞) */
12
- export interface ModelTier {
13
- upto: number | null;
14
- input: number;
15
- output: number;
16
- cacheRead: number | null;
17
- cacheWrite: number | null;
18
- }
19
-
20
- /** 定价时段倍率 */
21
- export interface TimeMultiplier {
22
- days: string;
23
- start: string;
24
- end: string;
25
- rate: number;
26
- }
27
-
28
- /** 供应商模型绑定(提供商 Tab):时段成本/计费倍率 */
29
- export interface SupplierTimeRate {
30
- days: string;
31
- start: string;
32
- end: string;
33
- cost: number;
34
- billing: number;
35
- }
36
-
37
- export interface SupplierModel {
38
- providerCode: string;
39
- providerName: string;
40
- /** 继承 Provider 品牌图标(Icon 白名单图标名) */
41
- providerIcon: string;
42
- providerModelId: string;
43
- weight: number;
44
- /** 供应商成本倍率 C(相对定价 Tab 标准价) */
45
- costRate: number;
46
- /** 模型计费倍率 M(相对定价 Tab 标准价) */
47
- billingRate: number;
48
- status: ModelStatus;
49
- /** 时段倍率;null = 未配置,使用默认 C / M */
50
- timeRates: SupplierTimeRate[] | null;
51
- /** 继承 Provider 密钥状态 */
52
- keyConfigured: boolean;
53
- lastProbe: { time: string; ok: boolean } | null;
54
- }
55
-
56
- /** 路由引用(路由引用 Tab) */
57
- export interface RouteRef {
58
- name: string;
59
- alias: string;
60
- type: string;
61
- weight: number;
62
- status: "启用" | "停用";
63
- health: "HEALTHY" | "UNHEALTHY";
64
- }
65
-
66
- /** 定价版本历史 */
67
- export interface PriceVersion {
68
- version: string;
69
- current: boolean;
70
- effective: string;
71
- summary: string;
72
- }
73
-
74
- /** 默认参数(默认参数 Tab + 编辑页「默认参数」区) */
75
- export interface ModelParams {
76
- temperature: string;
77
- topP: string;
78
- topK: string;
79
- maxTokens: string;
80
- frequencyPenalty: string;
81
- presencePenalty: string;
82
- reasoningEffort: string;
83
- seed: string;
84
- stopSequences: string;
85
- responseFormat: string;
86
- capabilities: string[];
87
- }
88
-
89
- export interface ModelRecord {
90
- code: string;
91
- name: string;
92
- providerCode: string;
93
- providerName: string;
94
- providerIcon: string;
95
- type: ModelType;
96
- typeLabel: string;
97
- releaseDate: string;
98
- contextWindow: number;
99
- /** 0 表示未设置(展示 —) */
100
- maxTokens: number;
101
- inputModalities: string[];
102
- outputModalities: string[];
103
- tags: string[];
104
- description: string;
105
- /** 元数据(JSON 文本) */
106
- metadata: string;
107
- status: ModelStatus;
108
- tiers: ModelTier[];
109
- timeMultipliers: TimeMultiplier[];
110
- currency: string;
111
- priceVersion: string;
112
- priceEffective: string;
113
- priceVersions: PriceVersion[];
114
- suppliers: SupplierModel[];
115
- routes: { total: number; active: number };
116
- routeRefs: RouteRef[];
117
- params: ModelParams;
118
- createdAt: string;
119
- updatedAt: string;
120
- operator: string;
121
- // ── 预计算摘要(表达式不适合拼接复合文案) ──
122
- /** 规格摘要:如 `256K · 32K`(上下文 · 最大输出) */
123
- specSummary: string;
124
- /** 定价摘要:默认档 如 `$0.2 / $1.6 /M`(输出为 0 时展示 —) */
125
- pricingSummary: string;
126
- /** 多档标识:如 `4档`;单档为空串 */
127
- tierLabel: string;
128
- /** 路由摘要:`N 条路由 · M 条活跃` 或 `未关联路由` */
129
- routeSummary: string;
130
- /** 模态预览:如 `T+I+V → T` */
131
- modalityPreview: string;
132
- inputModalitiesText: string;
133
- outputModalitiesText: string;
134
- tagsText: string;
135
- /** Provider 摘要:`阿里云百炼(主) · 共 N 个供应商模型` */
136
- providerSummary: string;
137
- /** 主供应商上游 Model ID(权重最高的启用实例) */
138
- primaryUpstreamId: string;
139
- /** 启用实例权重合计(展示文案) */
140
- supplierWeightTotal: string;
141
- /** 最近更新短日期(MM-DD) */
142
- shortDate: string;
143
- }
144
-
145
- export interface ModelListParams {
146
- /** all | LLM | Embedding | Image | Audio */
147
- type?: string;
148
- /** 厂商多选(Provider Code 列表) */
149
- providers?: string[];
150
- }
151
-
152
- /** 快筛 Chip 计数(数据构成口径,不随筛选变化) */
153
- export interface ModelCounts {
154
- all: { enabled: number; total: number };
155
- types: Record<ModelType, number>;
156
- providers: Record<string, number>;
157
- }
158
-
159
- /** 快筛 Chip 选项(ChipFilter 组件入项;文案在接口侧预计算) */
160
- export interface ModelChipOption {
161
- value: string;
162
- text: string;
163
- dot?: string;
164
- }
165
-
166
- export interface ModelListResult {
167
- items: ModelRecord[];
168
- total: number;
169
- counts: ModelCounts;
170
- /** 快筛 Chip 组:type 单选(含「全部」),providers 多选(含「全部」,点击清空) */
171
- filters: { type: ModelChipOption[]; providers: ModelChipOption[] };
172
- }
173
-
174
- const TYPE_LABELS: Record<ModelType, string> = {
175
- LLM: "大语言模型 (LLM)",
176
- Embedding: "Embedding",
177
- Image: "文生图 (Image)",
178
- Audio: "音频 (Audio)",
179
- };
180
-
181
- /** Token 数 → 短写法:256000 → 256K,1000000 → 1M,8192 → 8K */
182
- function formatTokens(n: number): string {
183
- if (n >= 1_000_000) {
184
- const v = n / 1_000_000;
185
- return `${v % 1 === 0 ? v : v.toFixed(1)}M`;
186
- }
187
- if (n >= 1_000) {
188
- const v = n / 1_000;
189
- return `${v % 1 === 0 ? v : v.toFixed(1)}K`;
190
- }
191
- return String(n);
192
- }
193
-
194
- function modalityLetter(m: string): string {
195
- return (
196
- { text: "T", image: "I", audio: "A", video: "V", file: "F" }[m] ??
197
- m[0].toUpperCase()
198
- );
199
- }
200
-
201
- function joinList(items: string[]): string {
202
- return items.join(" · ");
203
- }
204
-
205
- /** 列表卡/详情页摘要字段派生 */
206
- function derive(
207
- record: Omit<
208
- ModelRecord,
209
- | "typeLabel"
210
- | "specSummary"
211
- | "pricingSummary"
212
- | "tierLabel"
213
- | "routeSummary"
214
- | "modalityPreview"
215
- | "inputModalitiesText"
216
- | "outputModalitiesText"
217
- | "tagsText"
218
- | "providerSummary"
219
- | "primaryUpstreamId"
220
- | "supplierWeightTotal"
221
- | "shortDate"
222
- >,
223
- ): ModelRecord {
224
- const firstTier = record.tiers[0];
225
- const enabledSuppliers = record.suppliers.filter(
226
- (s) => s.status === "enabled",
227
- );
228
- const primary = enabledSuppliers[0] ?? record.suppliers[0];
229
- return {
230
- ...record,
231
- typeLabel: TYPE_LABELS[record.type],
232
- specSummary: `${formatTokens(record.contextWindow)} · ${record.maxTokens > 0 ? formatTokens(record.maxTokens) : "—"}`,
233
- pricingSummary: firstTier
234
- ? `$${firstTier.input} / $${firstTier.output > 0 ? firstTier.output : "—"} /M`
235
- : "未定价",
236
- tierLabel: record.tiers.length > 1 ? `${record.tiers.length}档` : "",
237
- routeSummary:
238
- record.routes.total === 0
239
- ? "未关联路由"
240
- : `${record.routes.total} 条路由 · ${record.routes.active} 条活跃`,
241
- modalityPreview: `${record.inputModalities.map(modalityLetter).join("+")} → ${record.outputModalities.map(modalityLetter).join("+")}`,
242
- inputModalitiesText: joinList(record.inputModalities),
243
- outputModalitiesText: joinList(record.outputModalities),
244
- tagsText: joinList(record.tags),
245
- providerSummary: primary
246
- ? `${primary.providerName}(主) · 共 ${record.suppliers.length} 个供应商模型`
247
- : "未绑定供应商模型",
248
- primaryUpstreamId: primary?.providerModelId ?? "—",
249
- supplierWeightTotal: String(
250
- enabledSuppliers.reduce((sum, s) => sum + s.weight, 0),
251
- ),
252
- shortDate: record.updatedAt.slice(5, 10),
253
- };
254
- }
255
-
256
- const MODELS: ModelRecord[] = [
257
- derive({
258
- code: "qwen3-vl-plus",
259
- name: "Qwen3-VL Plus",
260
- providerCode: "dashscope",
261
- providerName: "阿里云百炼",
262
- providerIcon: "cloud",
263
- type: "LLM",
264
- releaseDate: "2025-12-19",
265
- contextWindow: 256000,
266
- maxTokens: 32000,
267
- inputModalities: ["text", "image", "video"],
268
- outputModalities: ["text"],
269
- tags: ["free", "lite", "vision"],
270
- description:
271
- "A vision-language model for document, image, screen understanding and agentic visual tasks.",
272
- metadata: '{\n "vendor_tier": "plus"\n}',
273
- status: "enabled",
274
- tiers: [
275
- {
276
- upto: 32000,
277
- input: 0.2,
278
- output: 1.6,
279
- cacheRead: null,
280
- cacheWrite: null,
281
- },
282
- {
283
- upto: 128000,
284
- input: 0.4,
285
- output: 3.2,
286
- cacheRead: null,
287
- cacheWrite: null,
288
- },
289
- {
290
- upto: 1000000,
291
- input: 0.8,
292
- output: 6.4,
293
- cacheRead: null,
294
- cacheWrite: null,
295
- },
296
- { upto: null, input: 1.2, output: 9.6, cacheRead: 0.1, cacheWrite: 0.2 },
297
- ],
298
- timeMultipliers: [
299
- { days: "每天", start: "00:00", end: "08:00", rate: 0.8 },
300
- { days: "工作日", start: "09:00", end: "18:00", rate: 1.2 },
301
- ],
302
- currency: "USD",
303
- priceVersion: "3",
304
- priceEffective: "2026-09-01",
305
- priceVersions: [
306
- {
307
- version: "v3",
308
- current: true,
309
- effective: "2026-09-01",
310
- summary: "4档 · 2条时段倍率",
311
- },
312
- {
313
- version: "v2",
314
- current: false,
315
- effective: "2026-08-01",
316
- summary: "3档 · 1条时段倍率",
317
- },
318
- ],
319
- suppliers: [
320
- {
321
- providerCode: "dashscope",
322
- providerName: "阿里云百炼",
323
- providerIcon: "cloud",
324
- providerModelId: "qwen-vl-plus-latest",
325
- weight: 60,
326
- costRate: 1.0,
327
- billingRate: 1.2,
328
- status: "enabled",
329
- timeRates: [
330
- {
331
- days: "每天",
332
- start: "00:00",
333
- end: "08:00",
334
- cost: 0.8,
335
- billing: 0.9,
336
- },
337
- {
338
- days: "工作日",
339
- start: "09:00",
340
- end: "18:00",
341
- cost: 1.0,
342
- billing: 1.2,
343
- },
344
- ],
345
- keyConfigured: false,
346
- lastProbe: null,
347
- },
348
- {
349
- providerCode: "openai",
350
- providerName: "OpenAI",
351
- providerIcon: "zap",
352
- providerModelId: "gpt-4o-2024-08-06",
353
- weight: 40,
354
- costRate: 1.1,
355
- billingRate: 1.0,
356
- status: "enabled",
357
- timeRates: null,
358
- keyConfigured: true,
359
- lastProbe: { time: "2026-09-08 14:20", ok: true },
360
- },
361
- ],
362
- routes: { total: 2, active: 0 },
363
- routeRefs: [
364
- {
365
- name: "reasoning-default",
366
- alias: "reasoning",
367
- type: "多模型池",
368
- weight: 60,
369
- status: "启用",
370
- health: "HEALTHY",
371
- },
372
- {
373
- name: "general-chat",
374
- alias: "general",
375
- type: "单模型",
376
- weight: 100,
377
- status: "启用",
378
- health: "HEALTHY",
379
- },
380
- ],
381
- params: {
382
- temperature: "0.7",
383
- topP: "0.9",
384
- topK: "40",
385
- maxTokens: "4096",
386
- frequencyPenalty: "0",
387
- presencePenalty: "0",
388
- reasoningEffort: "medium",
389
- seed: "—",
390
- stopSequences: "[]",
391
- responseFormat: "text",
392
- capabilities: ["Streaming", "Tool Calling", "Vision"],
393
- },
394
- createdAt: "2026-06-01 10:00",
395
- updatedAt: "2026-09-05 14:20",
396
- operator: "张三",
397
- }),
398
- derive({
399
- code: "qwen3.5-flash",
400
- name: "Qwen3.5 Flash",
401
- providerCode: "dashscope",
402
- providerName: "阿里云百炼",
403
- providerIcon: "cloud",
404
- type: "LLM",
405
- releaseDate: "2026-03-10",
406
- contextWindow: 1000000,
407
- maxTokens: 64000,
408
- inputModalities: ["text"],
409
- outputModalities: ["text"],
410
- tags: ["free", "lite"],
411
- description: "轻量大语言模型,长上下文,低延迟,适合高频对话场景。",
412
- metadata: '{\n "vendor_tier": "flash"\n}',
413
- status: "enabled",
414
- tiers: [
415
- {
416
- upto: 128000,
417
- input: 0.1,
418
- output: 0.4,
419
- cacheRead: null,
420
- cacheWrite: null,
421
- },
422
- {
423
- upto: 512000,
424
- input: 0.2,
425
- output: 0.8,
426
- cacheRead: null,
427
- cacheWrite: null,
428
- },
429
- { upto: null, input: 0.3, output: 1.2, cacheRead: 0.05, cacheWrite: 0.1 },
430
- ],
431
- timeMultipliers: [
432
- { days: "每天", start: "00:00", end: "08:00", rate: 0.9 },
433
- ],
434
- currency: "USD",
435
- priceVersion: "2",
436
- priceEffective: "2026-08-15",
437
- priceVersions: [
438
- {
439
- version: "v2",
440
- current: true,
441
- effective: "2026-08-15",
442
- summary: "3档 · 1条时段倍率",
443
- },
444
- {
445
- version: "v1",
446
- current: false,
447
- effective: "2026-07-01",
448
- summary: "2档 · 无时段倍率",
449
- },
450
- ],
451
- suppliers: [
452
- {
453
- providerCode: "dashscope",
454
- providerName: "阿里云百炼",
455
- providerIcon: "cloud",
456
- providerModelId: "qwen3.5-flash",
457
- weight: 100,
458
- costRate: 1.0,
459
- billingRate: 1.0,
460
- status: "enabled",
461
- timeRates: null,
462
- keyConfigured: false,
463
- lastProbe: null,
464
- },
465
- ],
466
- routes: { total: 1, active: 1 },
467
- routeRefs: [
468
- {
469
- name: "general-chat",
470
- alias: "general",
471
- type: "单模型",
472
- weight: 100,
473
- status: "启用",
474
- health: "HEALTHY",
475
- },
476
- ],
477
- params: {
478
- temperature: "0.6",
479
- topP: "0.9",
480
- topK: "40",
481
- maxTokens: "8192",
482
- frequencyPenalty: "0",
483
- presencePenalty: "0",
484
- reasoningEffort: "low",
485
- seed: "—",
486
- stopSequences: "[]",
487
- responseFormat: "text",
488
- capabilities: ["Streaming", "Tool Calling"],
489
- },
490
- createdAt: "2026-06-15 09:30",
491
- updatedAt: "2026-09-08 11:05",
492
- operator: "李四",
493
- }),
494
- derive({
495
- code: "gemini-3-flash",
496
- name: "Gemini 3 Flash",
497
- providerCode: "gemini",
498
- providerName: "Google Gemini",
499
- providerIcon: "star",
500
- type: "LLM",
501
- releaseDate: "2026-01-22",
502
- contextWindow: 1000000,
503
- maxTokens: 64000,
504
- inputModalities: ["text", "image"],
505
- outputModalities: ["text"],
506
- tags: ["lite", "vision"],
507
- description: "Google Gemini 3 Flash:多模态输入,百万级上下文。",
508
- metadata: "{}",
509
- status: "enabled",
510
- tiers: [
511
- {
512
- upto: 200000,
513
- input: 0.15,
514
- output: 0.6,
515
- cacheRead: null,
516
- cacheWrite: null,
517
- },
518
- {
519
- upto: null,
520
- input: 0.3,
521
- output: 1.2,
522
- cacheRead: 0.03,
523
- cacheWrite: 0.05,
524
- },
525
- ],
526
- timeMultipliers: [],
527
- currency: "USD",
528
- priceVersion: "1",
529
- priceEffective: "2026-08-30",
530
- priceVersions: [
531
- {
532
- version: "v1",
533
- current: true,
534
- effective: "2026-08-30",
535
- summary: "2档 · 无时段倍率",
536
- },
537
- ],
538
- suppliers: [
539
- {
540
- providerCode: "gemini",
541
- providerName: "Google Gemini",
542
- providerIcon: "star",
543
- providerModelId: "gemini-3-flash",
544
- weight: 100,
545
- costRate: 1.0,
546
- billingRate: 1.0,
547
- status: "enabled",
548
- timeRates: null,
549
- keyConfigured: false,
550
- lastProbe: { time: "2026-08-30 20:10", ok: false },
551
- },
552
- ],
553
- routes: { total: 0, active: 0 },
554
- routeRefs: [],
555
- params: {
556
- temperature: "0.7",
557
- topP: "0.95",
558
- topK: "64",
559
- maxTokens: "8192",
560
- frequencyPenalty: "0",
561
- presencePenalty: "0",
562
- reasoningEffort: "medium",
563
- seed: "—",
564
- stopSequences: "[]",
565
- responseFormat: "text",
566
- capabilities: ["Streaming", "Tool Calling", "Vision"],
567
- },
568
- createdAt: "2026-07-02 16:00",
569
- updatedAt: "2026-08-30 20:10",
570
- operator: "张三",
571
- }),
572
- derive({
573
- code: "gpt-5",
574
- name: "GPT-5",
575
- providerCode: "openai",
576
- providerName: "OpenAI",
577
- providerIcon: "zap",
578
- type: "LLM",
579
- releaseDate: "2026-02-14",
580
- contextWindow: 512000,
581
- maxTokens: 64000,
582
- inputModalities: ["text", "image", "audio", "file"],
583
- outputModalities: ["text"],
584
- tags: ["pro"],
585
- description: "OpenAI GPT-5 旗舰模型,支持文本、图像、音频与文件输入。",
586
- metadata: '{\n "vendor_tier": "pro"\n}',
587
- status: "enabled",
588
- tiers: [
589
- { upto: null, input: 0.4, output: 1.8, cacheRead: 0.1, cacheWrite: 0.2 },
590
- ],
591
- timeMultipliers: [],
592
- currency: "USD",
593
- priceVersion: "1",
594
- priceEffective: "2026-09-10",
595
- priceVersions: [
596
- {
597
- version: "v1",
598
- current: true,
599
- effective: "2026-09-10",
600
- summary: "1档 · 无时段倍率",
601
- },
602
- ],
603
- suppliers: [
604
- {
605
- providerCode: "openai",
606
- providerName: "OpenAI",
607
- providerIcon: "zap",
608
- providerModelId: "gpt-5",
609
- weight: 100,
610
- costRate: 1.0,
611
- billingRate: 1.0,
612
- status: "enabled",
613
- timeRates: null,
614
- keyConfigured: true,
615
- lastProbe: { time: "2026-09-10 09:12", ok: true },
616
- },
617
- ],
618
- routes: { total: 2, active: 1 },
619
- routeRefs: [
620
- {
621
- name: "reasoning-default",
622
- alias: "reasoning",
623
- type: "多模型池",
624
- weight: 40,
625
- status: "启用",
626
- health: "HEALTHY",
627
- },
628
- {
629
- name: "coding-assistant",
630
- alias: "coding",
631
- type: "单模型",
632
- weight: 100,
633
- status: "启用",
634
- health: "HEALTHY",
635
- },
636
- ],
637
- params: {
638
- temperature: "0.5",
639
- topP: "0.9",
640
- topK: "—",
641
- maxTokens: "16384",
642
- frequencyPenalty: "0",
643
- presencePenalty: "0",
644
- reasoningEffort: "high",
645
- seed: "—",
646
- stopSequences: "[]",
647
- responseFormat: "text",
648
- capabilities: ["Streaming", "Tool Calling", "Vision", "JSON Schema"],
649
- },
650
- createdAt: "2026-07-20 14:00",
651
- updatedAt: "2026-09-10 09:12",
652
- operator: "王五",
653
- }),
654
- derive({
655
- code: "text-embedding-3-large",
656
- name: "Text Embedding 3 Large",
657
- providerCode: "openai",
658
- providerName: "OpenAI",
659
- providerIcon: "zap",
660
- type: "Embedding",
661
- releaseDate: "2024-03-15",
662
- contextWindow: 8192,
663
- maxTokens: 0,
664
- inputModalities: ["text"],
665
- outputModalities: ["text"],
666
- tags: ["embedding"],
667
- description: "OpenAI 文本向量模型,用于检索、聚类与语义相似度计算。",
668
- metadata: "{}",
669
- status: "disabled",
670
- tiers: [
671
- { upto: null, input: 0.1, output: 0, cacheRead: null, cacheWrite: null },
672
- ],
673
- timeMultipliers: [],
674
- currency: "USD",
675
- priceVersion: "1",
676
- priceEffective: "2026-07-01",
677
- priceVersions: [
678
- {
679
- version: "v1",
680
- current: true,
681
- effective: "2026-07-01",
682
- summary: "1档 · 无时段倍率",
683
- },
684
- ],
685
- suppliers: [
686
- {
687
- providerCode: "openai",
688
- providerName: "OpenAI",
689
- providerIcon: "zap",
690
- providerModelId: "text-embedding-3-large",
691
- weight: 100,
692
- costRate: 1.0,
693
- billingRate: 1.0,
694
- status: "enabled",
695
- timeRates: null,
696
- keyConfigured: true,
697
- lastProbe: { time: "2026-09-01 10:00", ok: true },
698
- },
699
- ],
700
- routes: { total: 0, active: 0 },
701
- routeRefs: [],
702
- params: {
703
- temperature: "—",
704
- topP: "—",
705
- topK: "—",
706
- maxTokens: "—",
707
- frequencyPenalty: "—",
708
- presencePenalty: "—",
709
- reasoningEffort: "—",
710
- seed: "—",
711
- stopSequences: "—",
712
- responseFormat: "—",
713
- capabilities: [],
714
- },
715
- createdAt: "2026-06-25 11:00",
716
- updatedAt: "2026-07-22 18:40",
717
- operator: "李四",
718
- }),
719
- ];
720
-
721
- /** 快筛选项常量:类型(单选)与厂商(多选,取有模型的 Provider) */
722
- export const MODEL_TYPE_OPTIONS: { value: string; label: string }[] = [
723
- { value: "all", label: "全部" },
724
- { value: "LLM", label: "大语言模型" },
725
- { value: "Image", label: "文生图" },
726
- { value: "Audio", label: "音频" },
727
- { value: "Embedding", label: "Embedding" },
728
- ];
729
-
730
- /** 厂商快筛:providers-with-models 的展示顺序(对齐 PRD 线框图) */
731
- export const MODEL_PROVIDER_FILTERS: { value: string; label: string }[] = [
732
- { value: "dashscope", label: "阿里云百炼" },
733
- { value: "gemini", label: "Google Gemini" },
734
- { value: "openai", label: "OpenAI" },
735
- ];
736
-
737
- /** 快筛计数:基于全量数据(构成口径,与当前筛选无关) */
738
- function computeCounts(): ModelCounts {
739
- return {
740
- all: {
741
- enabled: MODELS.filter((m) => m.status === "enabled").length,
742
- total: MODELS.length,
743
- },
744
- types: {
745
- LLM: MODELS.filter((m) => m.type === "LLM").length,
746
- Embedding: MODELS.filter((m) => m.type === "Embedding").length,
747
- Image: MODELS.filter((m) => m.type === "Image").length,
748
- Audio: MODELS.filter((m) => m.type === "Audio").length,
749
- },
750
- providers: MODEL_PROVIDER_FILTERS.reduce<Record<string, number>>(
751
- (acc, p) => {
752
- acc[p.value] = MODELS.filter((m) => m.providerCode === p.value).length;
753
- return acc;
754
- },
755
- {},
756
- ),
757
- };
758
- }
759
-
760
- /** 快筛 Chip 选项:由计数派生,文案在此预计算(表达式不支持复合文案拼接) */
761
- function computeFilters(counts: ModelCounts): ModelListResult["filters"] {
762
- return {
763
- type: [
764
- { value: "all", text: `全部 ${counts.all.total}` },
765
- ...MODEL_TYPE_OPTIONS.filter((o) => o.value !== "all").map((o) => ({
766
- value: o.value,
767
- text: `${o.label} ${counts.types[o.value as ModelType]}`,
768
- })),
769
- ],
770
- providers: [
771
- { value: "all", text: `全部 ${counts.all.total}` },
772
- ...MODEL_PROVIDER_FILTERS.map((p) => ({
773
- value: p.value,
774
- text: `${p.label} ${counts.providers[p.value]}`,
775
- })),
776
- ],
777
- };
778
- }
779
-
780
- /** model.list:类型单选 + 厂商多选取交集,按 Updated At 降序(「添加模型」卡置顶由页面保证) */
781
- export function queryModels(params: ModelListParams = {}): ModelListResult {
782
- const type = params.type ?? "all";
783
- const providers = params.providers ?? [];
784
- const items = MODELS.filter(
785
- (m) =>
786
- (type === "all" || m.type === type) &&
787
- (providers.length === 0 || providers.includes(m.providerCode)),
788
- ).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
789
- const counts = computeCounts();
790
- return { items, total: MODELS.length, counts, filters: computeFilters(counts) };
791
- }
792
-
793
- /** model.detail:按 Model Code 取详情;未命中返回 undefined(页面做空态) */
794
- export function getModel(code: string): ModelRecord | undefined {
795
- return MODELS.find((m) => m.code === code);
796
- }
797
-
798
- /** 全量 Model Code(静态导出 generateStaticParams 用) */
799
- export const MODEL_CODES: string[] = MODELS.map((m) => m.code);