@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 +4 -1
- package/lib/index.d.ts +12 -5
- package/package.json +2 -2
- package/src/client/card.tsx +3 -2
- package/src/client/client.ts +4 -24
- package/src/client/i18n.ts +12 -6
- package/src/client/views/compat.tsx +2 -1
- package/src/client/views/models.tsx +5 -4
- package/src/client/views/provider-fields.tsx +2 -1
- package/src/client/views/providers.tsx +3 -2
- package/src/config.ts +7 -0
package/lib/client.js
CHANGED
|
@@ -168,7 +168,10 @@ window.__ModuleLoader__.load({
|
|
|
168
168
|
confirm: "Confirm",
|
|
169
169
|
cancel: "Cancel"
|
|
170
170
|
};
|
|
171
|
-
/**
|
|
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 [
|
|
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 [
|
|
11
|
-
declare const MODALITIES: readonly [
|
|
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 [
|
|
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 [
|
|
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.
|
|
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.
|
|
35
|
+
"@dsh-plus/shared": "0.1.16"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@deepseek-ai/cordis": "^4.0.2",
|
package/src/client/card.tsx
CHANGED
|
@@ -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
|
|
33
|
+
t: Translate
|
|
33
34
|
scope: Scope
|
|
34
35
|
api: NamespaceSettingsApi
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
function modelsDevText(status: WireModelsDevStatus | null, t:
|
|
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')
|
package/src/client/client.ts
CHANGED
|
@@ -18,11 +18,11 @@ import type { Context } from '@deepseek-ai/cordis'
|
|
|
18
18
|
import {
|
|
19
19
|
createNamespaceApi,
|
|
20
20
|
createSettingsScope,
|
|
21
|
-
type
|
|
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
|
-
|
|
34
|
-
|
|
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
|
package/src/client/i18n.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
175
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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>
|