@dsh-plus/llm-pi 0.1.26 → 0.1.27

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/lib/client.js CHANGED
@@ -168,7 +168,10 @@ window.__ModuleLoader__.load({
168
168
  confirm: "Confirm",
169
169
  cancel: "Cancel"
170
170
  };
171
- /** own 覆盖同键合并(返回新对象,入参不可变)。 */
171
+ /**
172
+ * own 覆盖同键合并(返回新对象,入参不可变)。
173
+ * 返回类型保留两侧键集合,调用方据此派生 DictKey。
174
+ */
172
175
  function mergeDict(base, own) {
173
176
  return {
174
177
  ...base,
package/lib/index.d.ts CHANGED
@@ -4,13 +4,13 @@ import { Context } from "@deepseek-ai/cordis";
4
4
  /** settings 命名空间(字面量即合法命名空间,0.1.2-alpha.2 起编译期校验;webui 配置卡片与插件运行期读取同一份)。 */
5
5
  declare const SETTINGS_NS = "dsh-plus-llm-pi";
6
6
  /** 本插件可为手写 route 提供的协议实现(与官方 PROTOCOLS 表一致)。 */
7
- declare const PROTOCOL_IDS: readonly ["openai-completions", "openai-responses", "anthropic-messages"];
7
+ declare const PROTOCOL_IDS: readonly ['openai-completions', 'openai-responses', 'anthropic-messages'];
8
8
  type ProtocolId = (typeof PROTOCOL_IDS)[number];
9
9
  /** pi-ai 思考档位,升级序。 */
10
- declare const THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
11
- declare const MODALITIES: readonly ["text", "image"];
10
+ declare const THINKING_LEVELS: readonly ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];
11
+ declare const MODALITIES: readonly ['text', 'image'];
12
12
  /** 路由适配器种类:pi = PiAiAdapter(默认);deepseek = 官方 DeepSeekAdapter(文件通道)。 */
13
- declare const ADAPTER_KINDS: readonly ["pi", "deepseek"];
13
+ declare const ADAPTER_KINDS: readonly ['pi', 'deepseek'];
14
14
  type AdapterKind = (typeof ADAPTER_KINDS)[number];
15
15
  type ThinkingLevel = (typeof THINKING_LEVELS)[number];
16
16
  type Modality = (typeof MODALITIES)[number];
@@ -35,6 +35,13 @@ interface ProviderProfileConfig {
35
35
  extends?: string;
36
36
  displayName?: string;
37
37
  api?: ProtocolId;
38
+ /**
39
+ * 端点;缺省继承 extends 源 provider 的端点。
40
+ *
41
+ * 不并 `| undefined`:schemastery 的输入契约用 null 表示「显式置空」,省略即未设置;
42
+ * 消费方按 `baseURL ?? 默认值` 处理。并上 undefined 会与 ObjectS 的 `string | null`
43
+ * 冲突(exactOptionalPropertyTypes 下二者不可互赋)。
44
+ */
38
45
  baseURL?: string;
39
46
  apiKeyEnv?: string;
40
47
  headers?: Record<string, string>;
@@ -89,7 +96,7 @@ declare const Config: z<LlmPiConfigInput, LlmPiConfig>;
89
96
  //#endregion
90
97
  //#region src/index.d.ts
91
98
  declare const name = "dsh-plus-llm-pi";
92
- declare const inject: readonly ["credentials", "llm"];
99
+ declare const inject: readonly ['credentials', 'llm'];
93
100
  declare function apply(ctx: Context, config: LlmPiConfig): Promise<void>;
94
101
  //#endregion
95
102
  export { Config, type LlmPiConfig, type ModelEntryConfig, type ProviderProfileConfig, SETTINGS_NS, apply, inject, name };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plus/llm-pi",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "dsh-plus service+ui plugin: 基于 PiAiAdapter 的自定义 LLM 路由(全量 compat、模型继承、models.dev 目录兜底)",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "https-proxy-agent": "^9.1.0",
35
- "@dsh-plus/shared": "0.1.15"
35
+ "@dsh-plus/shared": "0.1.16"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@deepseek-ai/cordis": "^4.0.2",
@@ -26,15 +26,16 @@ import {
26
26
  type ProviderDraft,
27
27
  toPatch,
28
28
  } from './draft.ts'
29
+ import type { Translate } from './i18n.ts'
29
30
  import { ProvidersSection } from './views/providers.tsx'
30
31
 
31
32
  export interface CardProps {
32
- t(key: string): string
33
+ t: Translate
33
34
  scope: Scope
34
35
  api: NamespaceSettingsApi
35
36
  }
36
37
 
37
- function modelsDevText(status: WireModelsDevStatus | null, t: (key: string) => string): string {
38
+ function modelsDevText(status: WireModelsDevStatus | null, t: Translate): string {
38
39
  if (status === null) return t('modelsDevEmpty')
39
40
  if (status.error !== null) return `${t('modelsDevError')}${status.error}`
40
41
  if (status.fetchedAt === null) return t('modelsDevEmpty')
@@ -18,11 +18,11 @@ import type { Context } from '@deepseek-ai/cordis'
18
18
  import {
19
19
  createNamespaceApi,
20
20
  createSettingsScope,
21
- type SettingsRemoteFace,
21
+ type PluginClientContext,
22
22
  } from '@dsh-plus/shared/client'
23
23
  import { SETTINGS_NS } from '../ns.ts'
24
24
  import { LlmPiCard } from './card.tsx'
25
- import { en, NS, zh } from './i18n.ts'
25
+ import { type DictKey, en, NS, zh } from './i18n.ts'
26
26
  import { injectStyle } from './styles.ts'
27
27
 
28
28
  export const name = 'dsh-plus-llm-pi'
@@ -30,28 +30,8 @@ export const name = 'dsh-plus-llm-pi'
30
30
  /** 浏览器半需要的 cordis 服务 key(loader 据此注入;package.json 的 dsh.client.inject 管包加载顺序)。 */
31
31
  export const inject = ['slots', 'locale', 'remote', 'remote.settings'] as const
32
32
 
33
- interface SlotsLike {
34
- inject(key: string, callback: () => unknown): unknown
35
- register(options: Record<string, unknown>, component: unknown): () => void
36
- }
37
-
38
- interface LocaleLike {
39
- register(ns: string, dict: { zh: Record<string, string>; en: Record<string, string> }): () => void
40
- bind(ns: string): (key: string) => string
41
- }
42
-
43
- interface RemoteLike {
44
- settings: SettingsRemoteFace
45
- $on(event: string, listener: (payload?: unknown) => void): () => void
46
- }
47
-
48
- interface ClientContext {
49
- slots: SlotsLike
50
- locale: LocaleLike
51
- get(key: 'remote'): RemoteLike
52
- on(event: string, listener: () => void): () => void
53
- effect(execute: () => () => void, label?: string): unknown
54
- }
33
+ /** 宿主窄面收编在 @dsh-plus/shared/client;TKey 传入本包 DictKey 使键名受检。 */
34
+ type ClientContext = PluginClientContext<DictKey>
55
35
 
56
36
  export function apply(ctx: Context): void {
57
37
  const c = ctx as unknown as ClientContext
@@ -7,7 +7,7 @@ import { commonEn, commonZh, mergeDict } from '@dsh-plus/shared/client'
7
7
 
8
8
  export const NS = 'dsh-plus-llm-pi'
9
9
 
10
- const ownZh: Record<string, string> = {
10
+ const ownZh = {
11
11
  title: 'LLM 路由(llm-pi)',
12
12
  description: '自定义 LLM 路由:协议、compat、模型目录与 models.dev 目录兜底。',
13
13
  enabled: '启用插件',
@@ -86,9 +86,9 @@ const ownZh: Record<string, string> = {
86
86
  catalogFailed: '目录加载失败。',
87
87
  saveOk: '已保存。',
88
88
  saveFailed: '保存失败:',
89
- }
89
+ } as const
90
90
 
91
- const ownEn: Record<string, string> = {
91
+ const ownEn = {
92
92
  title: 'LLM routes (llm-pi)',
93
93
  description: 'Custom LLM routes: protocol, compat, model catalog and models.dev fallback.',
94
94
  enabled: 'Enable plugin',
@@ -169,7 +169,13 @@ const ownEn: Record<string, string> = {
169
169
  catalogFailed: 'Failed to load catalog.',
170
170
  saveOk: 'Saved.',
171
171
  saveFailed: 'Save failed: ',
172
- }
172
+ } as const
173
173
 
174
- export const zh: Record<string, string> = mergeDict(commonZh, ownZh)
175
- export const en: Record<string, string> = mergeDict(commonEn, ownEn)
174
+ export type DictKey = keyof typeof commonZh | keyof typeof ownZh
175
+
176
+ /** 卡片/面板共用的翻译函数类型(slot 注入的 bind 结果按此消费)。 */
177
+ export type Translate = (key: DictKey) => string
178
+
179
+ // 标注为 Record<DictKey, string>:en 缺任一键即编译期报错(中英强制对齐)。
180
+ export const zh: Record<DictKey, string> = mergeDict(commonZh, ownZh)
181
+ export const en: Record<DictKey, string> = mergeDict(commonEn, ownEn)
@@ -9,6 +9,7 @@ import type { ReactElement } from 'react'
9
9
 
10
10
  import { COMPAT_FALLBACK_API, compatFieldSpec, compatFieldsOf } from '../constants.ts'
11
11
  import { CollapseSection, JsonField, SelectField } from '../fields.tsx'
12
+ import type { Translate } from '../i18n.ts'
12
13
 
13
14
  /** api 变更后裁剪 compat:只保留新渲染组的字段,避免保存时被后端拒绝。 */
14
15
  export function pruneCompatForApi(
@@ -31,7 +32,7 @@ export interface CompatEditorProps {
31
32
  epoch: number
32
33
  disabled?: boolean
33
34
  wide?: boolean
34
- t(key: string): string
35
+ t: Translate
35
36
  onEdit(next: Record<string, unknown>): void
36
37
  }
37
38
 
@@ -11,11 +11,12 @@ import { fetchCatalog, type WireModelsDevStatus } from '../api.ts'
11
11
  import { MODALITIES, THINKING_LEVELS } from '../constants.ts'
12
12
  import { emptyModelDraft, type ModelDraft, type ReasoningDraft } from '../draft.ts'
13
13
  import { TextField } from '../fields.tsx'
14
+ import type { Translate } from '../i18n.ts'
14
15
  import { CompatEditor } from './compat.tsx'
15
16
 
16
17
  type CatalogSource = 'builtin' | 'models-dev'
17
18
 
18
- function catalogNote(status: WireModelsDevStatus | undefined, t: (key: string) => string): string {
19
+ function catalogNote(status: WireModelsDevStatus | undefined, t: Translate): string {
19
20
  if (status === undefined) return ''
20
21
  if (status.error !== null) return `${t('modelsDevError')}${status.error}`
21
22
  return `${t('modelsDevStatusLine')}:${status.providers} 个 provider,快照 ${status.fetchedAt ?? '-'}`
@@ -29,7 +30,7 @@ export interface ModelsTableProps {
29
30
  models: ModelDraft[]
30
31
  epoch: number
31
32
  disabled?: boolean
32
- t(key: string): string
33
+ t: Translate
33
34
  onModels(next: ModelDraft[]): void
34
35
  }
35
36
 
@@ -158,7 +159,7 @@ export interface ModelRowProps {
158
159
  listId: string
159
160
  epoch: number
160
161
  disabled?: boolean
161
- t(key: string): string
162
+ t: Translate
162
163
  onPatch(patch: Partial<ModelDraft>): void
163
164
  onRemove(): void
164
165
  }
@@ -268,7 +269,7 @@ export interface ReasoningEditorProps {
268
269
  idPrefix: string
269
270
  value: ReasoningDraft
270
271
  disabled?: boolean
271
- t(key: string): string
272
+ t: Translate
272
273
  onEdit(next: ReasoningDraft): void
273
274
  }
274
275
 
@@ -17,13 +17,14 @@ import {
17
17
  } from '../constants.ts'
18
18
  import type { ProviderDraft } from '../draft.ts'
19
19
  import { SelectField, TextField } from '../fields.tsx'
20
+ import type { Translate } from '../i18n.ts'
20
21
  import { pruneCompatForApi } from './compat.tsx'
21
22
 
22
23
  export interface ProviderScalarFieldsProps {
23
24
  id: string
24
25
  draft: ProviderDraft
25
26
  disabled?: boolean
26
- t(key: string): string
27
+ t: Translate
27
28
  onPatch(patch: Partial<ProviderDraft>): void
28
29
  }
29
30
 
@@ -10,6 +10,7 @@ import { type ReactElement, useState } from 'react'
10
10
 
11
11
  import type { ProviderDraft } from '../draft.ts'
12
12
  import { CollapseSection, JsonField, KeyValueEditor } from '../fields.tsx'
13
+ import type { Translate } from '../i18n.ts'
13
14
  import { CompatEditor } from './compat.tsx'
14
15
  import { ModelsTable } from './models.tsx'
15
16
  import { ProviderScalarFields, ProviderSelectFields } from './provider-fields.tsx'
@@ -18,7 +19,7 @@ export interface ProvidersSectionProps {
18
19
  providers: Record<string, ProviderDraft>
19
20
  epoch: number
20
21
  disabled?: boolean
21
- t(key: string): string
22
+ t: Translate
22
23
  onAddRoute(key: string): void
23
24
  onRemoveRoute(route: string): void
24
25
  onPatchProvider(route: string, patch: Partial<ProviderDraft>): void
@@ -86,7 +87,7 @@ export interface ProviderSectionProps {
86
87
  draft: ProviderDraft
87
88
  epoch: number
88
89
  disabled?: boolean
89
- t(key: string): string
90
+ t: Translate
90
91
  onRemove(): void
91
92
  onPatch(patch: Partial<ProviderDraft>): void
92
93
  }
package/src/config.ts CHANGED
@@ -90,6 +90,13 @@ export interface ProviderProfileConfig {
90
90
  extends?: string
91
91
  displayName?: string
92
92
  api?: ProtocolId
93
+ /**
94
+ * 端点;缺省继承 extends 源 provider 的端点。
95
+ *
96
+ * 不并 `| undefined`:schemastery 的输入契约用 null 表示「显式置空」,省略即未设置;
97
+ * 消费方按 `baseURL ?? 默认值` 处理。并上 undefined 会与 ObjectS 的 `string | null`
98
+ * 冲突(exactOptionalPropertyTypes 下二者不可互赋)。
99
+ */
93
100
  baseURL?: string
94
101
  apiKeyEnv?: string
95
102
  headers?: Record<string, string>