@huaweidevtools/aishell-dsh-llm 0.0.3 → 0.0.5
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/README.md +2 -2
- package/lib/client.js +52 -20
- package/lib/types/client/index.d.ts +12 -6
- package/lib/types/client/locales.d.ts +30 -0
- package/lib/types/client/provider-row-shadow.d.ts +20 -7
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Besides the live route, the plugin declares `aishell` in the configurable-provid
|
|
|
6
6
|
|
|
7
7
|
## The Models-page row
|
|
8
8
|
|
|
9
|
-
The row itself is read-only: the profile has no fields the host editor knows how to write, and credentials are
|
|
9
|
+
The row itself is read-only: the profile has no fields the host editor knows how to write, and credentials are entered through the form the `aishell-credentials` chips open (the account chip beside the chat input, or the chip on a New Session page). The browser half therefore does not extend the row with a card — it shadows the row's header at runtime (`src/client/provider-row-shadow.ts`, the same approach `aishell-brand` uses for its digest-protected host residues): a status dot after the row's name (green when AK/SK are stored, warn when they are not, with the readiness copy as its hover title) and the header's Edit button hidden, because there is nothing to edit. A MutationObserver keeps the shadow applied across the page's re-renders; the shadow is re-installed on a locale switch so the hover copy follows the active language; disabling the plugin restores the official row exactly.
|
|
10
10
|
|
|
11
11
|
## How it works
|
|
12
12
|
|
|
@@ -80,7 +80,7 @@ The three image fields share `dsh-llm-pi-ai`'s defaults: the gateway publishes n
|
|
|
80
80
|
|
|
81
81
|
## Storing credentials
|
|
82
82
|
|
|
83
|
-
**Web UI (recommended):** Install `aishell-credentials` (or the `aishell-base` bundle) — the
|
|
83
|
+
**Web UI (recommended):** Install `aishell-credentials` (or the `aishell-base` bundle) — clicking the credentials button beside the chat input (or the one on a New Session page) opens a form with AK/SK/SecurityToken fields. Values are verified against Huawei Cloud IAM and transferred to the credential store; the button flips to the account name when they are stored.
|
|
84
84
|
|
|
85
85
|
**CLI fallback:**
|
|
86
86
|
|
package/lib/client.js
CHANGED
|
@@ -46,13 +46,6 @@ const ROW_DOT_CSS = [
|
|
|
46
46
|
" display: none !important;",
|
|
47
47
|
"}"
|
|
48
48
|
].join("\n");
|
|
49
|
-
/** Title copy for the dot, by readiness. The warn state keeps the
|
|
50
|
-
* actionable half — where to save AK/SK — because that is the one thing a
|
|
51
|
-
* fresh user cannot guess; the ready state needs nothing beyond itself. */
|
|
52
|
-
const DOT_TITLE = {
|
|
53
|
-
ok: "已就绪",
|
|
54
|
-
warn: "未就绪 — 凭据未配置(在 设置 → AI Shell 中保存 AK/SK)"
|
|
55
|
-
};
|
|
56
49
|
/** Every Edit button an aishell row renders (there is ordinarily one; a
|
|
57
50
|
* re-render that leaves a second copy gets both, so none stays visible). */
|
|
58
51
|
function findEditButtons(row) {
|
|
@@ -93,15 +86,15 @@ function isProviderRow(node) {
|
|
|
93
86
|
* `target` is the owning document, passed in because the stub DOM the specs
|
|
94
87
|
* run on keeps no `ownerDocument` link.
|
|
95
88
|
*/
|
|
96
|
-
function shadowRow(row, ready, target) {
|
|
89
|
+
function shadowRow(row, ready, titles, target) {
|
|
97
90
|
const identity = row.querySelector("[class*=\"rowIdentity\"]");
|
|
98
91
|
if (identity === null) return;
|
|
99
92
|
const state = ready ? "ok" : "warn";
|
|
100
93
|
const existing = identity.querySelector(`[${ROW_DOT_MARKER}]`);
|
|
101
94
|
const dot = existing ?? target.createElement("span");
|
|
102
95
|
dot.setAttribute(ROW_DOT_MARKER, state);
|
|
103
|
-
dot.setAttribute("title",
|
|
104
|
-
dot.setAttribute("aria-label",
|
|
96
|
+
dot.setAttribute("title", titles[state]);
|
|
97
|
+
dot.setAttribute("aria-label", titles[state]);
|
|
105
98
|
if (existing === null) {
|
|
106
99
|
dot.setAttribute("role", "img");
|
|
107
100
|
identity.appendChild(dot);
|
|
@@ -122,21 +115,23 @@ function unshadowRow(row) {
|
|
|
122
115
|
*
|
|
123
116
|
* `ready` is the credential fact as the browser half derives it from the
|
|
124
117
|
* settings namespace `aishell-credentials` owns (see `client/index.ts`);
|
|
125
|
-
* the
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
118
|
+
* `titles` is the dot's hover copy in the active locale (the installer
|
|
119
|
+
* translates; this module holds only the DOM work). Neither is read from any
|
|
120
|
+
* store here, so a later credential save or locale switch is a reinstall with
|
|
121
|
+
* the new values, not a re-derivation buried in here. Sweeps the page once,
|
|
122
|
+
* then observes the body so re-rendered rows are covered too. Returns the
|
|
123
|
+
* disposer that stops the observer and restores every row.
|
|
129
124
|
*/
|
|
130
|
-
function installProviderRowShadow(target, ready) {
|
|
125
|
+
function installProviderRowShadow(target, ready, titles) {
|
|
131
126
|
if (typeof target.querySelector !== "function" || typeof MutationObserver !== "function") return () => {};
|
|
132
127
|
/** Run the shadow over every provider row at or below `root`. */
|
|
133
128
|
const sweep = (root) => {
|
|
134
|
-
if (isElement(root) && isProviderRow(root)) shadowRow(root, ready, target);
|
|
135
|
-
for (const row of root.querySelectorAll("[class*=\"rowCard\"], [class*=\"setupCard\"]")) if (isProviderRow(row)) shadowRow(row, ready, target);
|
|
129
|
+
if (isElement(root) && isProviderRow(root)) shadowRow(root, ready, titles, target);
|
|
130
|
+
for (const row of root.querySelectorAll("[class*=\"rowCard\"], [class*=\"setupCard\"]")) if (isProviderRow(row)) shadowRow(row, ready, titles, target);
|
|
136
131
|
};
|
|
137
132
|
const sweepIfRow = (node) => {
|
|
138
133
|
if (isProviderRow(node)) {
|
|
139
|
-
shadowRow(node, ready, target);
|
|
134
|
+
shadowRow(node, ready, titles, target);
|
|
140
135
|
return;
|
|
141
136
|
}
|
|
142
137
|
for (let parent = node.parentElement; parent !== null; parent = parent.parentElement) sweep(parent);
|
|
@@ -160,20 +155,54 @@ function installProviderRowShadow(target, ready) {
|
|
|
160
155
|
};
|
|
161
156
|
}
|
|
162
157
|
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/client/locales.ts
|
|
160
|
+
/**
|
|
161
|
+
* aishell-llm locale dictionaries — the Models-page provider row's copy.
|
|
162
|
+
*
|
|
163
|
+
* The row shadow is a DOM patch, not a React render, so its strings do not
|
|
164
|
+
* ride the framework's locale seat: the install reads them through `t` at
|
|
165
|
+
* install time and repaints on a locale switch (the client half re-installs
|
|
166
|
+
* on `locale/change`). zh is the key-set source of truth; en mirrors it.
|
|
167
|
+
*
|
|
168
|
+
* @module @huaweidevtools/aishell-dsh-llm/client/locales
|
|
169
|
+
*/
|
|
170
|
+
/** Dictionary namespace owned by this plugin. */
|
|
171
|
+
const NS = "aishell-llm";
|
|
172
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
173
|
+
const zh = {
|
|
174
|
+
"provider.ready": "已就绪",
|
|
175
|
+
"provider.warn": "未就绪 — 凭据未配置(点击对话输入框上方的凭据按钮填写 AK/SK)"
|
|
176
|
+
};
|
|
177
|
+
/** English dictionary. */
|
|
178
|
+
const en = {
|
|
179
|
+
"provider.ready": "Ready",
|
|
180
|
+
"provider.warn": "Not ready — credentials missing (click the credentials button above the chat input to enter AK/SK)"
|
|
181
|
+
};
|
|
182
|
+
|
|
163
183
|
//#endregion
|
|
164
184
|
//#region src/client/index.ts
|
|
165
185
|
/** The settings namespace aishell-credentials owns (the shadow reads its status). */
|
|
166
186
|
const AISHELL_CREDENTIALS_NS = "aishell-client-credentials";
|
|
167
187
|
/** Required services. */
|
|
168
|
-
const inject = ["configForms"];
|
|
188
|
+
const inject = ["configForms", "locale"];
|
|
169
189
|
function apply(ctx) {
|
|
170
190
|
if (typeof document === "undefined") return;
|
|
191
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
192
|
+
zh,
|
|
193
|
+
en
|
|
194
|
+
}), "aishell-llm: dictionaries");
|
|
195
|
+
const t = ctx.locale.bind(NS);
|
|
171
196
|
const form = ctx.configForms.get(AISHELL_CREDENTIALS_NS);
|
|
172
197
|
let readiness = form.getSnapshot().value?.credentialsStored === true;
|
|
173
198
|
let disposeShadow;
|
|
199
|
+
const titles = () => ({
|
|
200
|
+
ok: t("provider.ready"),
|
|
201
|
+
warn: t("provider.warn")
|
|
202
|
+
});
|
|
174
203
|
const sync = () => {
|
|
175
204
|
disposeShadow?.();
|
|
176
|
-
disposeShadow = installProviderRowShadow(document, readiness);
|
|
205
|
+
disposeShadow = installProviderRowShadow(document, readiness, titles());
|
|
177
206
|
};
|
|
178
207
|
const derive = () => {
|
|
179
208
|
const next = form.getSnapshot().value?.credentialsStored === true;
|
|
@@ -190,6 +219,9 @@ function apply(ctx) {
|
|
|
190
219
|
};
|
|
191
220
|
}), "aishell-llm: models page provider row shadow");
|
|
192
221
|
ctx.effect(() => form.subscribe(derive), "aishell-llm: credential presence for the models row");
|
|
222
|
+
ctx.effect(() => ctx.on("locale/change", () => {
|
|
223
|
+
sync();
|
|
224
|
+
}), "aishell-llm: shadow locale repaint");
|
|
193
225
|
}
|
|
194
226
|
|
|
195
227
|
//#endregion
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* aishell LLM browser half — shadows the Models page's provider row.
|
|
3
3
|
*
|
|
4
4
|
* The page's row for the aishell family is read-only: its profile has no
|
|
5
|
-
* fields the host editor knows how to write, and its credentials
|
|
6
|
-
* `aishell-credentials`
|
|
7
|
-
* user is the one fact the old card extension distilled —
|
|
8
|
-
* the browser half paints it as a status dot beside the
|
|
9
|
-
* the header's Edit button (see
|
|
5
|
+
* fields the host editor knows how to write, and its credentials are entered
|
|
6
|
+
* through the credential form the `aishell-credentials` chips open. What the
|
|
7
|
+
* row should tell the user is the one fact the old card extension distilled —
|
|
8
|
+
* ready or not — so the browser half paints it as a status dot beside the
|
|
9
|
+
* row's name and hides the header's Edit button (see
|
|
10
|
+
* `client/provider-row-shadow.ts`).
|
|
10
11
|
*
|
|
11
12
|
* The readiness fact is read from the `aishell-client-credentials` settings
|
|
12
13
|
* namespace (`aishell-credentials` owns it; the shadow never names accounts
|
|
@@ -15,10 +16,15 @@
|
|
|
15
16
|
* installed standalone) shows no trace of the dot either — the fact is
|
|
16
17
|
* unknown, not false.
|
|
17
18
|
*
|
|
19
|
+
* The dot's hover copy rides this package's own locale namespace. The shadow
|
|
20
|
+
* is a DOM patch that does not re-render on a locale switch, so the install
|
|
21
|
+
* is redone on `locale/change` — the repaint is attribute writes over rows
|
|
22
|
+
* the sweep re-finds, not a page mutation.
|
|
23
|
+
*
|
|
18
24
|
* @module @huaweidevtools/aishell-dsh-llm/client
|
|
19
25
|
*/
|
|
20
26
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
21
|
-
export type { ProviderRowShadowDisposer, } from './provider-row-shadow.ts';
|
|
27
|
+
export type { ProviderRowShadowDisposer, ProviderRowTitles, } from './provider-row-shadow.ts';
|
|
22
28
|
export { installProviderRowShadow, ROW_DOT_MARKER, ROW_EDIT_HIDDEN, } from './provider-row-shadow.ts';
|
|
23
29
|
/** Required services. */
|
|
24
30
|
export declare const inject: string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* aishell-llm locale dictionaries — the Models-page provider row's copy.
|
|
3
|
+
*
|
|
4
|
+
* The row shadow is a DOM patch, not a React render, so its strings do not
|
|
5
|
+
* ride the framework's locale seat: the install reads them through `t` at
|
|
6
|
+
* install time and repaints on a locale switch (the client half re-installs
|
|
7
|
+
* on `locale/change`). zh is the key-set source of truth; en mirrors it.
|
|
8
|
+
*
|
|
9
|
+
* @module @huaweidevtools/aishell-dsh-llm/client/locales
|
|
10
|
+
*/
|
|
11
|
+
/** Dictionary namespace owned by this plugin. */
|
|
12
|
+
export declare const NS: "aishell-llm";
|
|
13
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
14
|
+
export declare const zh: {
|
|
15
|
+
readonly 'provider.ready': "已就绪";
|
|
16
|
+
readonly 'provider.warn': "未就绪 — 凭据未配置(点击对话输入框上方的凭据按钮填写 AK/SK)";
|
|
17
|
+
};
|
|
18
|
+
/** English dictionary. */
|
|
19
|
+
export declare const en: {
|
|
20
|
+
readonly 'provider.ready': "Ready";
|
|
21
|
+
readonly 'provider.warn': "Not ready — credentials missing (click the credentials button above the chat input to enter AK/SK)";
|
|
22
|
+
};
|
|
23
|
+
/** All keys (derived from the zh dictionary, the source of truth). */
|
|
24
|
+
export type AishellLlmLocaleKey = keyof typeof zh;
|
|
25
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
26
|
+
interface LocaleNamespaceMap {
|
|
27
|
+
'aishell-llm': AishellLlmLocaleKey;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
*
|
|
25
25
|
* 1. a status dot after the name — the host credential dot's own 8px
|
|
26
26
|
* geometry and success/warn colors, green when AK/SK are stored, warn
|
|
27
|
-
* when they are not, with the readiness copy
|
|
28
|
-
*
|
|
27
|
+
* when they are not, with the readiness copy (installer-supplied, so it
|
|
28
|
+
* follows the active locale) as its title;
|
|
29
29
|
* 2. the row's Edit button is hidden — the row is read-only, and the only
|
|
30
30
|
* control the header keeps is whatever the host itself decides (Remove,
|
|
31
31
|
* for user-added rows; this family's row is not removable). The hide is
|
|
@@ -53,15 +53,28 @@ export declare const ROW_DOT_MARKER = "data-aishell-provider-dot";
|
|
|
53
53
|
export declare const ROW_EDIT_HIDDEN = "data-aishell-edit-hidden";
|
|
54
54
|
/** The dot's own CSS: the host credential dot's geometry and palette. */
|
|
55
55
|
export declare const ROW_DOT_CSS: string;
|
|
56
|
+
/** Title copy for the dot, by readiness — supplied by the installer so it
|
|
57
|
+
* follows the active locale (this module is a DOM patch with no locale seat
|
|
58
|
+
* of its own). The warn state keeps the actionable half — where to enter
|
|
59
|
+
* AK/SK — because that is the one thing a fresh user cannot guess; the ready
|
|
60
|
+
* state needs nothing beyond itself. */
|
|
61
|
+
export interface ProviderRowTitles {
|
|
62
|
+
/** Hover copy when AK/SK are stored. */
|
|
63
|
+
readonly ok: string;
|
|
64
|
+
/** Hover copy when they are not. */
|
|
65
|
+
readonly warn: string;
|
|
66
|
+
}
|
|
56
67
|
/**
|
|
57
68
|
* Install the provider-row shadow on a document.
|
|
58
69
|
*
|
|
59
70
|
* `ready` is the credential fact as the browser half derives it from the
|
|
60
71
|
* settings namespace `aishell-credentials` owns (see `client/index.ts`);
|
|
61
|
-
* the
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
72
|
+
* `titles` is the dot's hover copy in the active locale (the installer
|
|
73
|
+
* translates; this module holds only the DOM work). Neither is read from any
|
|
74
|
+
* store here, so a later credential save or locale switch is a reinstall with
|
|
75
|
+
* the new values, not a re-derivation buried in here. Sweeps the page once,
|
|
76
|
+
* then observes the body so re-rendered rows are covered too. Returns the
|
|
77
|
+
* disposer that stops the observer and restores every row.
|
|
65
78
|
*/
|
|
66
|
-
export declare function installProviderRowShadow(target: Document, ready: boolean): ProviderRowShadowDisposer;
|
|
79
|
+
export declare function installProviderRowShadow(target: Document, ready: boolean, titles: ProviderRowTitles): ProviderRowShadowDisposer;
|
|
67
80
|
//# sourceMappingURL=provider-row-shadow.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huaweidevtools/aishell-dsh-llm",
|
|
3
3
|
"description": "aishell LLM gateway adapter for DSH — OpenAI-compatible, Huawei Cloud AK/SK auth via credential store",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.5",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,29 +33,32 @@
|
|
|
33
33
|
"license": "Apache-2.0",
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"eventsource-parser": "^3.0.0",
|
|
36
|
-
"@huaweidevtools/aishell-dsh-credentials-store": "0.0.
|
|
36
|
+
"@huaweidevtools/aishell-dsh-credentials-store": "0.0.5"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
40
|
-
"@deepseek-ai/dsh-attachment": "
|
|
41
|
-
"@deepseek-ai/dsh-brand": "
|
|
42
|
-
"@deepseek-ai/dsh-fs": "
|
|
43
|
-
"@deepseek-ai/dsh-llm": "
|
|
40
|
+
"@deepseek-ai/dsh-attachment": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
41
|
+
"@deepseek-ai/dsh-brand": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
42
|
+
"@deepseek-ai/dsh-fs": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
43
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
47
47
|
"@deepseek-ai/cordis-plugin-loader": "^1.0.5",
|
|
48
48
|
"@deepseek-ai/dsh-attachment": "0.2.0-rc.1",
|
|
49
|
-
"@deepseek-ai/dsh-brand": "
|
|
49
|
+
"@deepseek-ai/dsh-brand": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
50
|
+
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
50
51
|
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
51
53
|
"@deepseek-ai/dsh-fs": "0.2.0-rc.1",
|
|
52
|
-
"@deepseek-ai/dsh-llm": "
|
|
54
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.1 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1",
|
|
53
55
|
"@deepseek-ai/schemastery": "3.18.4"
|
|
54
56
|
},
|
|
55
57
|
"dsh": {
|
|
56
58
|
"client": {
|
|
57
59
|
"inject": [
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-settings"
|
|
60
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
61
|
+
"@deepseek-ai/dsh-client-locale"
|
|
59
62
|
],
|
|
60
63
|
"platform": "web"
|
|
61
64
|
},
|