@huaweidevtools/aishell-dsh-llm 0.0.6 → 0.0.8
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/LICENSE +1 -1
- package/README.md +10 -8
- package/lib/index.js +15 -18
- package/lib/types/adapter.d.ts +12 -2
- package/lib/types/index.d.ts +0 -4
- package/package.json +2 -2
package/LICENSE
CHANGED
|
@@ -186,7 +186,7 @@
|
|
|
186
186
|
same "printed page" as the copyright notice for easier
|
|
187
187
|
identification within third-party archives.
|
|
188
188
|
|
|
189
|
-
Copyright
|
|
189
|
+
Copyright 2026 Huawei Cloud AI Shell
|
|
190
190
|
|
|
191
191
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
192
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ User selects aishell/<model>
|
|
|
15
15
|
→ GatewayAdapter.stream(options)
|
|
16
16
|
|
|
17
17
|
Every request is signed directly with AK/SK (SDK-HMAC-SHA256):
|
|
18
|
-
→ credential store reads
|
|
18
|
+
→ credential store reads the AK/SK pair (one record; optional STS token)
|
|
19
19
|
→ sign(POST, host, /chat/completions, query, body) → signed headers
|
|
20
20
|
→ POST {baseUrl}/chat/completions (signed headers, OpenAI wire format)
|
|
21
21
|
→ parseSse → translate → StreamChunks
|
|
@@ -70,8 +70,7 @@ dsh plugin --profile <name> add @huaweidevtools/aishell-dsh-base
|
|
|
70
70
|
|
|
71
71
|
| Field | Type | Default | Description |
|
|
72
72
|
|---|---|---|---|
|
|
73
|
-
| `baseUrl` | `string?` | `https://
|
|
74
|
-
| `keyringService` | `string?` | `aishell-dsh` | Credential store service name. |
|
|
73
|
+
| `baseUrl` | `string?` | `https://openai.aishell.openbuildlab.com/v1` | Chat API base URL. `/chat/completions` and `/models` are appended, so a base carrying its own path segment is signed and requested in full. |
|
|
75
74
|
| `requestImagePixelBudget` | `number?` | `4194304` | Total-pixel cap one request image is scaled into. |
|
|
76
75
|
| `requestImageMaxBytes` | `number?` | `1048576` | Encoded-byte target for one request image. |
|
|
77
76
|
| `maxRequestImageBytes` | `number?` | `20971520` | Accumulated base64 image bytes one request accepts before the oldest images must be offloaded. |
|
|
@@ -87,11 +86,14 @@ The three image fields share `dsh-llm-pi-ai`'s defaults: the gateway publishes n
|
|
|
87
86
|
```sh
|
|
88
87
|
node --input-type=module -e "
|
|
89
88
|
import { createCredentialsStore } from '@huaweidevtools/aishell-dsh-credentials-store';
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
import { writeHuaweiCloud } from '@huaweidevtools/aishell-dsh-credentials-store/accounts';
|
|
90
|
+
|
|
91
|
+
// One record, one write. The pair and its optional STS token go in together.
|
|
92
|
+
writeHuaweiCloud(createCredentialsStore(), {
|
|
93
|
+
ak: 'your-ak',
|
|
94
|
+
sk: 'your-sk',
|
|
95
|
+
// securityToken: 'your-token', // only for temporary credentials
|
|
96
|
+
});
|
|
95
97
|
"
|
|
96
98
|
```
|
|
97
99
|
|
package/lib/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { requestImageDimensions } from "@deepseek-ai/dsh-attachment";
|
|
|
4
4
|
import { brandString } from "@deepseek-ai/dsh-brand";
|
|
5
5
|
import { EventSourceParserStream } from "eventsource-parser/stream";
|
|
6
6
|
import { sign } from "@huaweidevtools/aishell-dsh-credentials-store/signer";
|
|
7
|
+
import { readStoredPair } from "@huaweidevtools/aishell-dsh-credentials-store/accounts";
|
|
7
8
|
|
|
8
9
|
//#region ../../node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.5/node_modules/@deepseek-ai/cosmokit/lib/index.js
|
|
9
10
|
/** Return true when a value is `null` or `undefined`. */
|
|
@@ -1425,10 +1426,6 @@ const PROVIDER_DISPLAY_NAME = "AI Shell";
|
|
|
1425
1426
|
|
|
1426
1427
|
//#endregion
|
|
1427
1428
|
//#region src/adapter.ts
|
|
1428
|
-
/** Credential store account names for Huawei Cloud credentials. */
|
|
1429
|
-
const AK_ACCOUNT = "HW_ACCESS_KEY";
|
|
1430
|
-
const SK_ACCOUNT = "HW_SECRET_KEY";
|
|
1431
|
-
const TOKEN_ACCOUNT = "HW_SECURITY_TOKEN";
|
|
1432
1429
|
/**
|
|
1433
1430
|
* Whether a gateway error body reports an id the gateway does not carry.
|
|
1434
1431
|
*
|
|
@@ -1546,17 +1543,19 @@ var GatewayAdapter = class GatewayAdapter extends LlmAdapter {
|
|
|
1546
1543
|
hasCredentials() {
|
|
1547
1544
|
return this.readCredentials() !== void 0;
|
|
1548
1545
|
}
|
|
1549
|
-
/**
|
|
1546
|
+
/**
|
|
1547
|
+
* Read the AK/SK pair from the credential store.
|
|
1548
|
+
*
|
|
1549
|
+
* Delegates to the shared reader: this adapter, `aishell-e2b`,
|
|
1550
|
+
* `aishell-credentials` and `aishell-deploy` all read the same record, and a
|
|
1551
|
+
* local copy of that rule is how two of them end up disagreeing about what
|
|
1552
|
+
* "credentials are configured" means.
|
|
1553
|
+
*
|
|
1554
|
+
* Read per request, never captured — that is what makes a rotation in the
|
|
1555
|
+
* credential form apply to the very next call.
|
|
1556
|
+
*/
|
|
1550
1557
|
readCredentials() {
|
|
1551
|
-
|
|
1552
|
-
const sk = this.opts.keyring.get(SK_ACCOUNT);
|
|
1553
|
-
if (!ak || !sk) return void 0;
|
|
1554
|
-
const securityToken = this.opts.keyring.get(TOKEN_ACCOUNT);
|
|
1555
|
-
return {
|
|
1556
|
-
ak,
|
|
1557
|
-
sk,
|
|
1558
|
-
...securityToken ? { securityToken } : {}
|
|
1559
|
-
};
|
|
1558
|
+
return readStoredPair(this.opts.keyring);
|
|
1560
1559
|
}
|
|
1561
1560
|
/**
|
|
1562
1561
|
* Read credentials or throw `MISSING_CREDENTIAL` — every signing code path
|
|
@@ -1658,7 +1657,7 @@ GatewayAdapter.MODELS_TTL_MS = 6e4;
|
|
|
1658
1657
|
//#endregion
|
|
1659
1658
|
//#region src/index.ts
|
|
1660
1659
|
/** Default chat API base URL. Both `/chat/completions` and `/models` hang below `/v1`. */
|
|
1661
|
-
const DEFAULT_BASE_URL = "https://
|
|
1660
|
+
const DEFAULT_BASE_URL = "https://openai.aishell.openbuildlab.com/v1";
|
|
1662
1661
|
/**
|
|
1663
1662
|
* Default total-pixel cap one request image is scaled into, and the encoded
|
|
1664
1663
|
* byte target the encoder aims for. Both match the pi-ai defaults, for the
|
|
@@ -1686,7 +1685,6 @@ const DEFAULT_MAX_REQUEST_IMAGE_BYTES = 20971520;
|
|
|
1686
1685
|
*/
|
|
1687
1686
|
const Config = Schema.object({
|
|
1688
1687
|
baseUrl: Schema.string().default(DEFAULT_BASE_URL).volatile(),
|
|
1689
|
-
keyringService: Schema.string().volatile(),
|
|
1690
1688
|
requestImagePixelBudget: Schema.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_PIXEL_BUDGET).volatile(),
|
|
1691
1689
|
requestImageMaxBytes: Schema.number().step(1).min(1).default(DEFAULT_REQUEST_IMAGE_MAX_BYTES).volatile(),
|
|
1692
1690
|
maxRequestImageBytes: Schema.number().step(1).min(1).default(DEFAULT_MAX_REQUEST_IMAGE_BYTES).volatile()
|
|
@@ -1696,8 +1694,7 @@ const inject = ["llm"];
|
|
|
1696
1694
|
/** The provider route this plugin owns. */
|
|
1697
1695
|
const PROVIDER = "aishell";
|
|
1698
1696
|
function apply(ctx, config) {
|
|
1699
|
-
const
|
|
1700
|
-
const store = createCredentialsStore(keyringService === void 0 || keyringService === "" ? {} : { service: keyringService });
|
|
1697
|
+
const store = createCredentialsStore();
|
|
1701
1698
|
const adapter = new GatewayAdapter({
|
|
1702
1699
|
resolveBaseUrl: () => config.baseUrl.get(),
|
|
1703
1700
|
keyring: store,
|
package/lib/types/adapter.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import { type ImageRequestBudget } from './images.ts';
|
|
|
16
16
|
/** Adapter construction options. */
|
|
17
17
|
export interface GatewayAdapterOptions {
|
|
18
18
|
/**
|
|
19
|
-
* Resolve the current chat API base URL (e.g. `https://
|
|
19
|
+
* Resolve the current chat API base URL (e.g. `https://openai.aishell.openbuildlab.com/v1`).
|
|
20
20
|
*
|
|
21
21
|
* A reader, not a value, for the same reason `resolveAttachments` is: this
|
|
22
22
|
* plugin's whole Config is `Volatile`, so a settings edit is a
|
|
@@ -75,7 +75,17 @@ export declare class GatewayAdapter extends LlmAdapter {
|
|
|
75
75
|
* @returns whether both halves of the signing credential are present.
|
|
76
76
|
*/
|
|
77
77
|
hasCredentials(): boolean;
|
|
78
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Read the AK/SK pair from the credential store.
|
|
80
|
+
*
|
|
81
|
+
* Delegates to the shared reader: this adapter, `aishell-e2b`,
|
|
82
|
+
* `aishell-credentials` and `aishell-deploy` all read the same record, and a
|
|
83
|
+
* local copy of that rule is how two of them end up disagreeing about what
|
|
84
|
+
* "credentials are configured" means.
|
|
85
|
+
*
|
|
86
|
+
* Read per request, never captured — that is what makes a rotation in the
|
|
87
|
+
* credential form apply to the very next call.
|
|
88
|
+
*/
|
|
79
89
|
private readCredentials;
|
|
80
90
|
/**
|
|
81
91
|
* Read credentials or throw `MISSING_CREDENTIAL` — every signing code path
|
package/lib/types/index.d.ts
CHANGED
|
@@ -27,8 +27,6 @@ export type { GatewayAdapter, GatewayAdapterOptions } from './adapter.ts';
|
|
|
27
27
|
export interface Config {
|
|
28
28
|
/** Chat API base URL. Default: the public aishell gateway. */
|
|
29
29
|
readonly baseUrl: Volatile<string>;
|
|
30
|
-
/** Credential store service name; empty selects the default `'aishell-dsh'`. */
|
|
31
|
-
readonly keyringService: Volatile<string | undefined>;
|
|
32
30
|
/** Total-pixel cap one request image is projected into. */
|
|
33
31
|
readonly requestImagePixelBudget: Volatile<number>;
|
|
34
32
|
/** Encoded-byte target for one request image. */
|
|
@@ -47,13 +45,11 @@ export interface Config {
|
|
|
47
45
|
*/
|
|
48
46
|
export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
49
47
|
baseUrl: z<string, string, "volatile-defined">;
|
|
50
|
-
keyringService: z<string, string, "volatile">;
|
|
51
48
|
requestImagePixelBudget: z<number, number, "volatile-defined">;
|
|
52
49
|
requestImageMaxBytes: z<number, number, "volatile-defined">;
|
|
53
50
|
maxRequestImageBytes: z<number, number, "volatile-defined">;
|
|
54
51
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
55
52
|
baseUrl: z<string, string, "volatile-defined">;
|
|
56
|
-
keyringService: z<string, string, "volatile">;
|
|
57
53
|
requestImagePixelBudget: z<number, number, "volatile-defined">;
|
|
58
54
|
requestImageMaxBytes: z<number, number, "volatile-defined">;
|
|
59
55
|
maxRequestImageBytes: z<number, number, "volatile-defined">;
|
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.8",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -33,7 +33,7 @@
|
|
|
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.8"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@deepseek-ai/cordis": "^4.0.4",
|