@lynn123411/dsh-a6api 1.0.1 → 1.1.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.
- package/README.md +3 -2
- package/lib/client.js +223 -16
- package/lib/client.js.map +3 -3
- package/lib/index.js +71 -0
- package/lib/index.js.map +2 -2
- package/lib/types/client/store.d.ts +6 -1
- package/lib/types/server/a6api-client.d.ts +8 -0
- package/lib/types/types.d.ts +8 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @lynn123411/dsh-a6api
|
|
2
2
|
|
|
3
|
-
A6API 多模型聚合站深度接入插件:将 A6API 聚合网关无缝注册为 DSH 原生 LLM 提供商,提供多标签页分类视图(可用模型 / 账户资产 / 基础配置)、实时美元与人民币真实余额监控、Token
|
|
3
|
+
A6API 多模型聚合站深度接入插件:将 A6API 聚合网关无缝注册为 DSH 原生 LLM 提供商,提供多标签页分类视图(可用模型 / 账户资产 / 基础配置)、实时美元与人民币真实余额监控、Token 授权模型白名单自动拉取、实时路由探针、全真 1:1 复刻 A6API 官方模型市场维度的全景商户指标卡片与官方 vs 商户价格比对表,以及标题栏价格波动实时胶囊一键直达官网。
|
|
4
4
|
|
|
5
5
|
## 特性
|
|
6
6
|
|
|
@@ -10,9 +10,10 @@ A6API 多模型聚合站深度接入插件:将 A6API 聚合网关无缝注册
|
|
|
10
10
|
- **真实账户资产看板与调用明细**:在「账户资产」页面实时呈现真实可用余额(美元及折合人民币)、历史总消耗、累计请求次数,并实时捕获展示近期模型请求的路由明细快照(时间、模型、命中商户渠道、总耗时、Token 消耗及状态)。
|
|
11
11
|
- **原生提供商动态注册与一键加入 DSH**:自动向 DSH LLM 运行时注入 `a6api` 目录,在「可用模型」列表点击「添加到 DSH」即可将模型自动增量同步至 `settings.yaml` 与 DSH 对话选择器。
|
|
12
12
|
- **节点切换与凭据一站式配置**:在「基础配置」页面支持 CDN 推荐节点(`https://api.a6api.com`)、直连备用节点(`https://a6.a6api.com`)与自定义网关节点自由切换,提供 API Key 与系统访问令牌密码显隐切换及获取教程。
|
|
13
|
+
- **价格波动实时胶囊**:标题栏余额右侧常驻「价格波动:n」胶囊(白底,仅数字变色:`0` 绿/`n>0` 红/`--` 灰),基于 `GET /api/marketplace/price-notices` 的待处理数 `pendingCount` 每 60s 轻轮询(与余额同频,仅计不处置),`n>0` 时一键新标签跳 `https://a6api.com/console/token`,未配置/失效或 `0` 时置灰不可点,满足“只监听不处置”的轻量诉求。
|
|
13
14
|
|
|
14
15
|
## 安装
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
18
|
dsh plugin --profile web add @lynn123411/dsh-a6api
|
|
18
|
-
```
|
|
19
|
+
```
|
package/lib/client.js
CHANGED
|
@@ -45,10 +45,12 @@ var A6ApiStore = class {
|
|
|
45
45
|
dshConfiguredModels: [],
|
|
46
46
|
recentLogs: [],
|
|
47
47
|
probingModelNames: /* @__PURE__ */ new Set(),
|
|
48
|
-
error: null
|
|
48
|
+
error: null,
|
|
49
|
+
priceFluctuation: { pendingCount: 0, unseenCount: 0, totalCount: 0, updatedAt: null }
|
|
49
50
|
};
|
|
50
51
|
listeners = /* @__PURE__ */ new Set();
|
|
51
52
|
autoRefreshTimer = null;
|
|
53
|
+
pricePollTimer = null;
|
|
52
54
|
constructor() {
|
|
53
55
|
this.startAutoRefresh();
|
|
54
56
|
}
|
|
@@ -85,6 +87,13 @@ var A6ApiStore = class {
|
|
|
85
87
|
this.state.recentLogs = data.recentLogs;
|
|
86
88
|
}
|
|
87
89
|
this.state.error = null;
|
|
90
|
+
if (this.state.config?.hasToken) {
|
|
91
|
+
const last = this.state.priceFluctuation?.updatedAt;
|
|
92
|
+
if (!last || Date.now() - last > 1e4) {
|
|
93
|
+
this.fetchPriceFluctuation().catch(() => {
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
88
97
|
}
|
|
89
98
|
}
|
|
90
99
|
} catch (err) {
|
|
@@ -127,6 +136,38 @@ var A6ApiStore = class {
|
|
|
127
136
|
} catch {
|
|
128
137
|
}
|
|
129
138
|
}
|
|
139
|
+
async fetchPriceFluctuation() {
|
|
140
|
+
try {
|
|
141
|
+
const res = await fetch("/api/dsh-a6api/price-fluctuation");
|
|
142
|
+
if (res.ok) {
|
|
143
|
+
const json = await res.json();
|
|
144
|
+
if (json?.data) {
|
|
145
|
+
const d = json.data;
|
|
146
|
+
const hasAuth = d.hasAuth !== false && !d.authError;
|
|
147
|
+
if (!hasAuth) {
|
|
148
|
+
const next2 = { pendingCount: 0, unseenCount: 0, totalCount: 0, updatedAt: Date.now(), hasAuth: false, authError: Boolean(d.authError) };
|
|
149
|
+
if (JSON.stringify(next2) !== JSON.stringify(this.state.priceFluctuation)) {
|
|
150
|
+
this.state.priceFluctuation = next2;
|
|
151
|
+
this.notify();
|
|
152
|
+
}
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const pending = Number(d.pendingCount ?? 0);
|
|
156
|
+
const unseen = Number(d.unseenCount ?? 0);
|
|
157
|
+
const total = Number(d.totalCount ?? 0);
|
|
158
|
+
const next = { pendingCount: pending, unseenCount: unseen, totalCount: total, updatedAt: Date.now(), hasAuth: true, authError: false };
|
|
159
|
+
if (pending !== this.state.priceFluctuation.pendingCount || unseen !== this.state.priceFluctuation.unseenCount || this.state.priceFluctuation.hasAuth === false || this.state.priceFluctuation.updatedAt === null) {
|
|
160
|
+
this.state.priceFluctuation = next;
|
|
161
|
+
this.notify();
|
|
162
|
+
} else if (this.state.priceFluctuation.updatedAt === null) {
|
|
163
|
+
this.state.priceFluctuation = next;
|
|
164
|
+
this.notify();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
} catch {
|
|
169
|
+
}
|
|
170
|
+
}
|
|
130
171
|
async probeModel(modelName) {
|
|
131
172
|
this.state.probingModelNames.add(modelName);
|
|
132
173
|
this.state.models = this.state.models.map(
|
|
@@ -243,6 +284,31 @@ var A6ApiStore = class {
|
|
|
243
284
|
this.refreshBalance().catch(() => {
|
|
244
285
|
});
|
|
245
286
|
}, 6e4);
|
|
287
|
+
if (this.pricePollTimer) clearInterval(this.pricePollTimer);
|
|
288
|
+
this.pricePollTimer = setInterval(() => {
|
|
289
|
+
if (this.state.config?.hasToken) {
|
|
290
|
+
this.fetchPriceFluctuation().catch(() => {
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}, 60 * 1e3);
|
|
294
|
+
}
|
|
295
|
+
stopAutoRefresh() {
|
|
296
|
+
if (this.autoRefreshTimer) {
|
|
297
|
+
clearInterval(this.autoRefreshTimer);
|
|
298
|
+
this.autoRefreshTimer = null;
|
|
299
|
+
}
|
|
300
|
+
if (this.pricePollTimer) {
|
|
301
|
+
clearInterval(this.pricePollTimer);
|
|
302
|
+
this.pricePollTimer = null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
initPricePolling() {
|
|
306
|
+
if (this.pricePollTimer) return;
|
|
307
|
+
this.startAutoRefresh();
|
|
308
|
+
if (this.state.config?.hasToken) {
|
|
309
|
+
this.fetchPriceFluctuation().catch(() => {
|
|
310
|
+
});
|
|
311
|
+
}
|
|
246
312
|
}
|
|
247
313
|
};
|
|
248
314
|
var store = new A6ApiStore();
|
|
@@ -920,21 +986,61 @@ var A6ApiSettingsPanel = () => {
|
|
|
920
986
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-a6-container", children: [
|
|
921
987
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-a6-main-header", children: [
|
|
922
988
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-a6-header-text", children: [
|
|
923
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "dsh-a6-main-title", children: "
|
|
989
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "dsh-a6-main-title", children: "A6api" }),
|
|
924
990
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "dsh-a6-main-subtitle", children: "\u805A\u5408\u5168\u7403\u4E3B\u6D41\u4E0E\u9AD8\u6027\u4EF7\u6BD4\u6A21\u578B\uFF0C\u5B9E\u65F6\u76D1\u63A7\u5546\u6237\u6307\u6807\u3001\u4EF7\u683C\u500D\u7387\u4E0E\u8D26\u6237\u8D44\u4EA7\u3002" })
|
|
925
991
|
] }),
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
992
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-a6-header-badges", children: [
|
|
993
|
+
state.balance?.hasAccountAuth && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
994
|
+
"div",
|
|
995
|
+
{
|
|
996
|
+
className: "dsh-a6-header-balance-badge",
|
|
997
|
+
onClick: () => setActiveTab("account"),
|
|
998
|
+
title: "\u70B9\u51FB\u5207\u6362\u81F3\u300C\u8D26\u6237\u8D44\u4EA7\u300D\u9875\u9762",
|
|
999
|
+
children: [
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-a6-hb-label", children: "\u8D26\u6237\u4F59\u989D:" }),
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-a6-hb-amount", children: state.balance.accountBalanceFormatted })
|
|
1002
|
+
]
|
|
1003
|
+
}
|
|
1004
|
+
),
|
|
1005
|
+
(() => {
|
|
1006
|
+
const n = state.priceFluctuation?.pendingCount ?? 0;
|
|
1007
|
+
const pf = state.priceFluctuation;
|
|
1008
|
+
const hasAuth = pf?.hasAuth !== false && !pf?.authError && Boolean(state.config?.hasToken);
|
|
1009
|
+
const isAuthError = Boolean(pf?.authError);
|
|
1010
|
+
const isZero = n === 0;
|
|
1011
|
+
const isDisabled = !hasAuth || isZero;
|
|
1012
|
+
const cls = isDisabled ? !hasAuth ? "dsh-a6-price-pill disabled" : "dsh-a6-price-pill is-zero is-disabled-zero" : "dsh-a6-price-pill has-change";
|
|
1013
|
+
const title = !hasAuth ? isAuthError ? "\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\u5DF2\u5931\u6548\uFF0C\u8BF7\u524D\u5F80\u57FA\u7840\u914D\u7F6E\u66F4\u65B0" : "\u672A\u914D\u7F6E\u7CFB\u7EDF\u8BBF\u95EE\u4EE4\u724C\uFF0C\u65E0\u6CD5\u83B7\u53D6\u4EF7\u683C\u53D8\u52A8" : isZero ? "\u6682\u65E0\u4EF7\u683C\u53D8\u52A8" : `\u6709 ${n} \u6761\u4EF7\u683C\u53D8\u52A8\u5F85\u5904\u7406\uFF0C\u70B9\u51FB\u524D\u5F80\u5B98\u7F51\u5904\u7406`;
|
|
1014
|
+
const onClick = () => {
|
|
1015
|
+
if (isDisabled) return;
|
|
1016
|
+
window.open("https://a6api.com/console/token", "_blank", "noopener");
|
|
1017
|
+
};
|
|
1018
|
+
const onKeyDown = (e) => {
|
|
1019
|
+
if (isDisabled) return;
|
|
1020
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1021
|
+
e.preventDefault();
|
|
1022
|
+
onClick();
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1026
|
+
"div",
|
|
1027
|
+
{
|
|
1028
|
+
className: cls,
|
|
1029
|
+
onClick: isDisabled ? void 0 : onClick,
|
|
1030
|
+
onKeyDown,
|
|
1031
|
+
tabIndex: isDisabled ? -1 : 0,
|
|
1032
|
+
title,
|
|
1033
|
+
role: "button",
|
|
1034
|
+
"aria-disabled": isDisabled,
|
|
1035
|
+
style: isDisabled ? { cursor: "not-allowed" } : void 0,
|
|
1036
|
+
children: [
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-a6-price-pill-label", children: "\u4EF7\u683C\u6CE2\u52A8\uFF1A" }),
|
|
1038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "dsh-a6-price-pill-count", children: !hasAuth ? "--" : n })
|
|
1039
|
+
]
|
|
1040
|
+
}
|
|
1041
|
+
);
|
|
1042
|
+
})()
|
|
1043
|
+
] })
|
|
938
1044
|
] }),
|
|
939
1045
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "dsh-a6-nav-tabs", children: [
|
|
940
1046
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
@@ -1148,6 +1254,13 @@ var main_default = `/* A6API Plugin Styles - Clean Professional DSH Native Theme
|
|
|
1148
1254
|
transition: all 0.15s;
|
|
1149
1255
|
}
|
|
1150
1256
|
|
|
1257
|
+
.dsh-a6-header-badges {
|
|
1258
|
+
display: inline-flex;
|
|
1259
|
+
align-items: center;
|
|
1260
|
+
gap: 8px;
|
|
1261
|
+
flex-wrap: wrap;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1151
1264
|
.dsh-a6-header-balance-badge:hover {
|
|
1152
1265
|
border-color: #10b981;
|
|
1153
1266
|
background: rgba(16, 185, 129, 0.04);
|
|
@@ -1158,6 +1271,91 @@ var main_default = `/* A6API Plugin Styles - Clean Professional DSH Native Theme
|
|
|
1158
1271
|
color: var(--dsw-alias-label-secondary, #64748b);
|
|
1159
1272
|
}
|
|
1160
1273
|
|
|
1274
|
+
.dsh-a6-price-pill {
|
|
1275
|
+
display: inline-flex;
|
|
1276
|
+
align-items: center;
|
|
1277
|
+
gap: 6px;
|
|
1278
|
+
padding: 5px 12px;
|
|
1279
|
+
border-radius: 16px;
|
|
1280
|
+
border: 1px solid var(--dsw-alias-border-l2, #e2e8f0);
|
|
1281
|
+
cursor: pointer;
|
|
1282
|
+
font-size: 12px;
|
|
1283
|
+
font-weight: 500;
|
|
1284
|
+
line-height: 1;
|
|
1285
|
+
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);
|
|
1286
|
+
transition: all 0.15s;
|
|
1287
|
+
user-select: none;
|
|
1288
|
+
/* \u4E0E\u8D26\u6237\u4F59\u989D\u80F6\u56CA\u7B49\u9AD8\uFF1A\u7EE7\u627F\u540C\u6837\u5185\u8FB9\u8DDD\u4E0E\u884C\u9AD8\uFF0C\u907F\u514D\u89C6\u89C9\u5927\u5C0F\u5DEE\u5F02 */
|
|
1289
|
+
min-height: 28px;
|
|
1290
|
+
box-sizing: border-box;
|
|
1291
|
+
}
|
|
1292
|
+
|
|
1293
|
+
.dsh-a6-price-pill.is-zero {
|
|
1294
|
+
background: var(--dsw-alias-bg-layer-2, #ffffff);
|
|
1295
|
+
border-color: var(--dsw-alias-border-l2, #e2e8f0);
|
|
1296
|
+
color: var(--dsw-alias-label-secondary, #64748b);
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
.dsh-a6-price-pill.is-zero:hover {
|
|
1300
|
+
border-color: #10b981;
|
|
1301
|
+
background: rgba(16, 185, 129, 0.04);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
.dsh-a6-price-pill.is-zero.is-disabled-zero:hover {
|
|
1305
|
+
border-color: var(--dsw-alias-border-l2, #e2e8f0);
|
|
1306
|
+
background: var(--dsw-alias-bg-layer-2, #ffffff);
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
.dsh-a6-price-pill.has-change {
|
|
1310
|
+
background: var(--dsw-alias-bg-layer-2, #ffffff);
|
|
1311
|
+
border-color: var(--dsw-alias-border-l2, #e2e8f0);
|
|
1312
|
+
color: var(--dsw-alias-label-secondary, #64748b);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
.dsh-a6-price-pill.has-change:hover {
|
|
1316
|
+
border-color: #ef4444;
|
|
1317
|
+
background: rgba(239, 68, 68, 0.03);
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
.dsh-a6-price-pill.is-disabled-zero {
|
|
1321
|
+
cursor: not-allowed;
|
|
1322
|
+
opacity: 0.9;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
.dsh-a6-price-pill.disabled {
|
|
1326
|
+
background: var(--dsw-alias-bg-layer-1, rgba(0,0,0,0.04));
|
|
1327
|
+
border-color: var(--dsw-alias-border-l3, #cbd5e1);
|
|
1328
|
+
color: var(--dsw-alias-label-tertiary, #94a3b8);
|
|
1329
|
+
cursor: not-allowed;
|
|
1330
|
+
opacity: 0.85;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
.dsh-a6-price-pill-label {
|
|
1334
|
+
font-size: 12px;
|
|
1335
|
+
font-weight: 500;
|
|
1336
|
+
color: var(--dsw-alias-label-secondary, #64748b);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
.dsh-a6-price-pill-count {
|
|
1340
|
+
font-size: 13px;
|
|
1341
|
+
font-weight: 700;
|
|
1342
|
+
min-width: 8px;
|
|
1343
|
+
text-align: center;
|
|
1344
|
+
line-height: 1;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
.dsh-a6-price-pill.is-zero .dsh-a6-price-pill-count {
|
|
1348
|
+
color: #10b981;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
.dsh-a6-price-pill.has-change .dsh-a6-price-pill-count {
|
|
1352
|
+
color: #ef4444;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
.dsh-a6-price-pill.disabled .dsh-a6-price-pill-count {
|
|
1356
|
+
color: var(--dsw-alias-label-tertiary, #94a3b8);
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1161
1359
|
.dsh-a6-hb-amount {
|
|
1162
1360
|
font-size: 13px;
|
|
1163
1361
|
font-weight: 700;
|
|
@@ -2512,6 +2710,15 @@ function injectStyles() {
|
|
|
2512
2710
|
function apply(ctx) {
|
|
2513
2711
|
injectStyles();
|
|
2514
2712
|
if (typeof window === "undefined") return;
|
|
2713
|
+
try {
|
|
2714
|
+
setTimeout(() => {
|
|
2715
|
+
try {
|
|
2716
|
+
store.initPricePolling();
|
|
2717
|
+
} catch {
|
|
2718
|
+
}
|
|
2719
|
+
}, 1500);
|
|
2720
|
+
} catch {
|
|
2721
|
+
}
|
|
2515
2722
|
try {
|
|
2516
2723
|
const slots = ctx?.slots || (ctx?.get ? ctx.get("slots") : null);
|
|
2517
2724
|
if (!slots || typeof slots.inject !== "function") return;
|
|
@@ -2520,8 +2727,8 @@ function apply(ctx) {
|
|
|
2520
2727
|
{
|
|
2521
2728
|
name: "settings.section",
|
|
2522
2729
|
id: "dsh-a6api",
|
|
2523
|
-
order:
|
|
2524
|
-
label: () => "
|
|
2730
|
+
order: 11,
|
|
2731
|
+
label: () => "A6api"
|
|
2525
2732
|
},
|
|
2526
2733
|
A6ApiSettingsPanel
|
|
2527
2734
|
);
|