@dungsil/dsh-plugin-cli-proxy-api 0.2.1 → 0.2.3
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/dist/client.js +59 -35
- package/dist/index.js +3 -3
- package/package.json +24 -23
package/dist/client.js
CHANGED
|
@@ -19,12 +19,13 @@ function installStyles(css) {
|
|
|
19
19
|
return () => style.remove();
|
|
20
20
|
}
|
|
21
21
|
// ../../tools/ui/src/settings.tsx
|
|
22
|
-
/**
|
|
22
|
+
/** Decorate matching navigation rows in both the rc.5 and 0.2.2 settings shells. */
|
|
23
23
|
function installSettingsIcon(id, labels, icon) {
|
|
24
24
|
const attribute = "data-dsh-settings-icon";
|
|
25
25
|
const selector = `[${attribute}="${id}"]`;
|
|
26
26
|
const removeStyles = installStyles(`
|
|
27
|
-
${selector} > svg
|
|
27
|
+
${selector} > svg,
|
|
28
|
+
${selector} > [aria-hidden="true"]:not([data-dsh-settings-icon-glyph]) { display: none; }
|
|
28
29
|
${typeof icon === "string" ? `${selector}::before { content: ''; display: block; flex: none; width: 16px; height: 16px; background: currentColor; mask: url("data:image/svg+xml,${encodeURIComponent(icon)}") center / contain no-repeat; }` : ""}
|
|
29
30
|
${selector} > [data-dsh-settings-icon-glyph] { display: inline-flex; flex: none; }
|
|
30
31
|
`);
|
|
@@ -89,6 +90,22 @@ function SettingsRow({ label, children }) {
|
|
|
89
90
|
}), children]
|
|
90
91
|
});
|
|
91
92
|
}
|
|
93
|
+
// ../../tools/ui/src/page.tsx
|
|
94
|
+
function PluginPage({ children, className = "", contentClassName = "" }) {
|
|
95
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
96
|
+
className: `dsh-plugin-page ${className}`,
|
|
97
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
98
|
+
className: `dsh-plugin-page-content ${contentClassName}`,
|
|
99
|
+
children
|
|
100
|
+
})
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// ../../tools/ui/src/page-styles.ts
|
|
104
|
+
const pageStyles = `
|
|
105
|
+
.dsh-plugin-page { box-sizing: border-box; height: 100%; min-height: 0; overflow: auto; padding: 24px; padding-inline-start: max(24px, var(--dsh-frame-leading-clearance, 0px)); }
|
|
106
|
+
.dsh-plugin-page-content { max-width: 960px; margin: 0 auto; }
|
|
107
|
+
.dsh-plugin-page h1 { margin: 0 0 24px; font-size: 20px; line-height: 28px; font-weight: 500; }
|
|
108
|
+
`;
|
|
92
109
|
// src/protocol.ts
|
|
93
110
|
const channel = "/api";
|
|
94
111
|
const endpointPrefix = "dungsil-cli-proxy-api/";
|
|
@@ -115,7 +132,7 @@ const copy = {
|
|
|
115
132
|
quotaLoadTitle: "Accounts are not available yet",
|
|
116
133
|
quotaLoadHint: "Accounts and quota load automatically with a saved management key. If loading fails, refresh accounts to try again.",
|
|
117
134
|
accountsObservedAt: "Accounts checked at",
|
|
118
|
-
quotaHint: "Accounts and quota load
|
|
135
|
+
quotaHint: "Accounts and quota load once and stay cached in memory when you reopen this panel. Refresh accounts to update all results. Connection changes clear the cache. Cooldown reset only clears proxy routing blocks; it does not refill quota. No paid inference or reset credits are used.",
|
|
119
136
|
refreshQuotaAccounts: "Refresh accounts",
|
|
120
137
|
searchAccounts: "Search name / provider",
|
|
121
138
|
refreshQuota: "Refresh quota",
|
|
@@ -184,7 +201,7 @@ const copy = {
|
|
|
184
201
|
quotaLoadTitle: "아직 계정 정보를 불러오지 못했습니다",
|
|
185
202
|
quotaLoadHint: "관리 키가 저장되어 있으면 계정과 할당량을 자동으로 불러옵니다. 불러오기에 실패했다면 계정을 새로고침하세요.",
|
|
186
203
|
accountsObservedAt: "계정 확인 시각",
|
|
187
|
-
quotaHint: "계정과
|
|
204
|
+
quotaHint: "계정과 할당량은 한 번 불러온 뒤 메모리에 캐시하며, 화면을 다시 열 때 그대로 표시합니다. 계정을 새로고침하면 전체 결과를 갱신합니다. 연결이 변경되면 캐시를 비웁니다. 대기 시간 초기화는 프록시의 라우팅 차단만 해제하며 할당량을 충전하지 않습니다. 유료 추론이나 초기화 크레딧을 사용하지 않습니다.",
|
|
188
205
|
refreshQuotaAccounts: "계정 새로고침",
|
|
189
206
|
searchAccounts: "이름 / 공급자 검색",
|
|
190
207
|
refreshQuota: "할당량 새로고침",
|
|
@@ -253,7 +270,7 @@ const copy = {
|
|
|
253
270
|
quotaLoadTitle: "暂未加载账户信息",
|
|
254
271
|
quotaLoadHint: "保存管理密钥后,账户和配额会自动加载。加载失败时,请刷新账户重试。",
|
|
255
272
|
accountsObservedAt: "账户检查时间",
|
|
256
|
-
quotaHint: "
|
|
273
|
+
quotaHint: "账户和配额加载一次后会缓存在内存中,重新打开此面板时直接显示。刷新账户可更新全部结果。连接变更会清除缓存。重置冷却时间仅解除代理路由限制,不会补充配额。不会使用付费推理或重置额度。",
|
|
257
274
|
refreshQuotaAccounts: "刷新账户",
|
|
258
275
|
searchAccounts: "搜索名称 / 提供商",
|
|
259
276
|
refreshQuota: "刷新配额",
|
|
@@ -684,6 +701,7 @@ function QuotaPanel({ accounts, quotas, fetchedAt, language, text, busy, canLoad
|
|
|
684
701
|
]
|
|
685
702
|
});
|
|
686
703
|
}
|
|
704
|
+
// src/quota-cache.ts
|
|
687
705
|
const quotaKey = (account) => JSON.stringify([account.name, account.authIndex]);
|
|
688
706
|
const connectionKey = (view) => JSON.stringify([
|
|
689
707
|
view.baseURL,
|
|
@@ -692,6 +710,9 @@ const connectionKey = (view) => JSON.stringify([
|
|
|
692
710
|
]);
|
|
693
711
|
var QuotaCache = class {
|
|
694
712
|
entry;
|
|
713
|
+
get connection() {
|
|
714
|
+
return this.entry?.view;
|
|
715
|
+
}
|
|
695
716
|
read(view) {
|
|
696
717
|
if (this.entry?.key !== connectionKey(view)) {
|
|
697
718
|
this.clear();
|
|
@@ -702,6 +723,7 @@ var QuotaCache = class {
|
|
|
702
723
|
write(view, snapshot) {
|
|
703
724
|
this.entry = {
|
|
704
725
|
key: connectionKey(view),
|
|
726
|
+
view,
|
|
705
727
|
snapshot
|
|
706
728
|
};
|
|
707
729
|
}
|
|
@@ -726,10 +748,6 @@ function subscribeQuotaGeneration(generation, cache, cancel, changed) {
|
|
|
726
748
|
changed(!!generation.getSnapshot());
|
|
727
749
|
});
|
|
728
750
|
}
|
|
729
|
-
function isQuotaCacheFresh(snapshot, now = Date.now()) {
|
|
730
|
-
const age = now - snapshot.fetchedAt;
|
|
731
|
-
return age >= 0 && age < 3e5;
|
|
732
|
-
}
|
|
733
751
|
async function loadQuotaSnapshot(list, fetch, signal, publish) {
|
|
734
752
|
signal.throwIfAborted();
|
|
735
753
|
const accounts = await list();
|
|
@@ -775,13 +793,10 @@ const inject = [
|
|
|
775
793
|
"locale",
|
|
776
794
|
"slots"
|
|
777
795
|
];
|
|
778
|
-
const styles = `${settingsStyles}${quotaStyles}
|
|
796
|
+
const styles = `${settingsStyles}${quotaStyles}${pageStyles}
|
|
779
797
|
.dsh-cli-proxy-icon { display: inline-flex; }
|
|
780
798
|
.dsh-cli-proxy-icon > svg { width: 100%; height: 100%; }
|
|
781
799
|
.dsh-cli-proxy { container-type: inline-size; color: var(--dsw-alias-label-primary); font: 14px/22px var(--dsw-font-family, system-ui); }
|
|
782
|
-
.dsh-cli-proxy-page { height: 100%; min-height: 0; box-sizing: border-box; overflow-y: auto; padding: 24px; padding-inline-start: max(24px, var(--dsh-frame-leading-clearance, 0px)); }
|
|
783
|
-
.dsh-cli-proxy-page > .dsh-cli-proxy { max-width: 960px; margin: 0 auto; }
|
|
784
|
-
.dsh-cli-proxy h1 { font-size: 20px; line-height: 28px; font-weight: 500; margin: 0 0 24px; }
|
|
785
800
|
.dsh-cli-proxy h3 { margin: 24px 0 0; font: inherit; color: var(--dsw-alias-label-secondary); }
|
|
786
801
|
.dsh-cli-proxy .controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; min-width: 0; max-width: 65%; }
|
|
787
802
|
.dsh-cli-proxy .controls > span:has(> input) { box-sizing: border-box; width: 280px; min-width: 0; max-width: 100%; }
|
|
@@ -807,18 +822,20 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
807
822
|
const id = (0, react.useId)();
|
|
808
823
|
const [connectionVersion, setConnectionVersion] = (0, react.useState)(0);
|
|
809
824
|
const connection = ctx.get("connection");
|
|
810
|
-
const
|
|
811
|
-
const
|
|
825
|
+
const cachedView = settings ? void 0 : cache.connection;
|
|
826
|
+
const cached = cachedView && cache.read(cachedView);
|
|
827
|
+
const [view, setView] = (0, react.useState)(cachedView);
|
|
828
|
+
const [baseURL, setBaseURL] = (0, react.useState)(cachedView?.baseURL ?? "");
|
|
812
829
|
const [apiKey, setAPIKey] = (0, react.useState)("");
|
|
813
830
|
const [managementKey, setManagementKey] = (0, react.useState)("");
|
|
814
831
|
const [removeAPIKey, setRemoveAPIKey] = (0, react.useState)(false);
|
|
815
832
|
const [removeManagementKey, setRemoveManagementKey] = (0, react.useState)(false);
|
|
816
|
-
const [synchronized, setSynchronized] = (0, react.useState)(
|
|
817
|
-
const [busy, setBusy] = (0, react.useState)(
|
|
833
|
+
const [synchronized, setSynchronized] = (0, react.useState)(!!cached);
|
|
834
|
+
const [busy, setBusy] = (0, react.useState)(!cached);
|
|
818
835
|
const [notice, setNotice] = (0, react.useState)();
|
|
819
|
-
const [quotaAccounts, setQuotaAccounts] = (0, react.useState)();
|
|
820
|
-
const [quotas, setQuotas] = (0, react.useState)({});
|
|
821
|
-
const [fetchedAt, setFetchedAt] = (0, react.useState)();
|
|
836
|
+
const [quotaAccounts, setQuotaAccounts] = (0, react.useState)(cached?.accounts);
|
|
837
|
+
const [quotas, setQuotas] = (0, react.useState)(cached?.quotas ?? {});
|
|
838
|
+
const [fetchedAt, setFetchedAt] = (0, react.useState)(cached?.fetchedAt);
|
|
822
839
|
const [uncertain, setUncertain] = (0, react.useState)(false);
|
|
823
840
|
const lock = (0, react.useRef)(true);
|
|
824
841
|
const lifetime = (0, react.useRef)();
|
|
@@ -831,6 +848,7 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
831
848
|
const describe = (0, react.useCallback)(async (controller) => {
|
|
832
849
|
setSynchronized(false);
|
|
833
850
|
const next = await call("describe", {}, controller);
|
|
851
|
+
cache.read(next);
|
|
834
852
|
setView(next);
|
|
835
853
|
setBaseURL(next.baseURL);
|
|
836
854
|
setSynchronized(true);
|
|
@@ -842,7 +860,7 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
842
860
|
setQuotas({});
|
|
843
861
|
setFetchedAt(void 0);
|
|
844
862
|
return next;
|
|
845
|
-
}, [call]);
|
|
863
|
+
}, [call, cache]);
|
|
846
864
|
const showSnapshot = (0, react.useCallback)((snapshot) => {
|
|
847
865
|
setQuotaAccounts(snapshot.accounts);
|
|
848
866
|
setQuotas(snapshot.quotas);
|
|
@@ -898,6 +916,20 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
898
916
|
(0, react.useEffect)(() => {
|
|
899
917
|
const controller = new AbortController();
|
|
900
918
|
lifetime.current = controller;
|
|
919
|
+
const restoreView = settings ? void 0 : cache.connection;
|
|
920
|
+
const restore = restoreView && cache.read(restoreView);
|
|
921
|
+
if (restore && restoreView) {
|
|
922
|
+
setView(restoreView);
|
|
923
|
+
setBaseURL(restoreView.baseURL);
|
|
924
|
+
setSynchronized(true);
|
|
925
|
+
showSnapshot(restore);
|
|
926
|
+
lock.current = false;
|
|
927
|
+
setBusy(false);
|
|
928
|
+
return () => {
|
|
929
|
+
controller.abort();
|
|
930
|
+
if (lifetime.current === controller) lifetime.current = void 0;
|
|
931
|
+
};
|
|
932
|
+
}
|
|
901
933
|
lock.current = true;
|
|
902
934
|
setBusy(true);
|
|
903
935
|
setSynchronized(false);
|
|
@@ -911,12 +943,7 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
911
943
|
setNotice(void 0);
|
|
912
944
|
describe(controller).then(async (next) => {
|
|
913
945
|
if (settings) return;
|
|
914
|
-
const cached = cache.read(next);
|
|
915
946
|
if (!next.managementKeySaved) return;
|
|
916
|
-
if (cached) {
|
|
917
|
-
showSnapshot(cached);
|
|
918
|
-
if (isQuotaCacheFresh(cached)) return;
|
|
919
|
-
}
|
|
920
947
|
await loadAccounts(next, controller);
|
|
921
948
|
}).catch(() => {
|
|
922
949
|
if (!controller.signal.aborted && lifetime.current === controller) setNotice("error");
|
|
@@ -1151,15 +1178,12 @@ function ProxyPage({ ctx, cache, settings = false }) {
|
|
|
1151
1178
|
});
|
|
1152
1179
|
}
|
|
1153
1180
|
function ProxyPanel({ ctx, cache }) {
|
|
1154
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1155
|
-
|
|
1156
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
cache
|
|
1161
|
-
})]
|
|
1162
|
-
})
|
|
1181
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(PluginPage, {
|
|
1182
|
+
contentClassName: "dsh-cli-proxy",
|
|
1183
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: "CLIProxyAPI" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProxyPage, {
|
|
1184
|
+
ctx,
|
|
1185
|
+
cache
|
|
1186
|
+
})]
|
|
1163
1187
|
});
|
|
1164
1188
|
}
|
|
1165
1189
|
function apply(ctx) {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { clientRequestSchema } from "@deepseek-ai/dsh-client-connection";
|
|
3
3
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
4
|
-
// ../../node_modules/.pnpm/@deepseek-ai+cosmokit@1.
|
|
4
|
+
// ../../node_modules/.pnpm/@deepseek-ai+cosmokit@1.9.0/node_modules/@deepseek-ai/cosmokit/lib/index.js
|
|
5
5
|
/** Return true when a value is `null` or `undefined`. */
|
|
6
6
|
function isNullable(value) {
|
|
7
7
|
return value === null || value === void 0;
|
|
@@ -254,7 +254,7 @@ var Time;
|
|
|
254
254
|
}
|
|
255
255
|
Time.template = template;
|
|
256
256
|
})(Time || (Time = {}));
|
|
257
|
-
// ../../node_modules/.pnpm/@deepseek-ai+schemastery@3.
|
|
257
|
+
// ../../node_modules/.pnpm/@deepseek-ai+schemastery@3.19.0/node_modules/@deepseek-ai/schemastery/lib/index.mjs
|
|
258
258
|
const kSchema = Symbol.for("schemastery");
|
|
259
259
|
const kValidationError = Symbol.for("ValidationError");
|
|
260
260
|
globalThis.__schemastery_index__ ??= 0;
|
|
@@ -1455,7 +1455,7 @@ function apply(ctx, config) {
|
|
|
1455
1455
|
ctx.effect(() => () => lifetime.abort());
|
|
1456
1456
|
const currentURL = () => serverURL(config.baseURL.get());
|
|
1457
1457
|
const ownerEntry = () => {
|
|
1458
|
-
const entries = ctx.configEditor.entries().filter((entry) => entry.fiber === ctx.fiber);
|
|
1458
|
+
const entries = ctx.configEditor.entries().filter((entry) => entry.fiber?.uid === ctx.fiber.uid);
|
|
1459
1459
|
if (entries.length !== 1) throw new Error("unavailable");
|
|
1460
1460
|
return entries[0];
|
|
1461
1461
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dungsil/dsh-plugin-cli-proxy-api",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "CLIProxyAPI model provider and owner-only management settings for DeepSeek Harness.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,39 +24,40 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@deepseek-ai/cordis": "4.0
|
|
28
|
-
"@deepseek-ai/dsh-app-boot": "0.2.
|
|
29
|
-
"@deepseek-ai/dsh-client-connection": "0.2.
|
|
30
|
-
"@deepseek-ai/dsh-client-locale": "0.2.
|
|
31
|
-
"@deepseek-ai/dsh-client-ui-layout": "0.2.
|
|
32
|
-
"@deepseek-ai/dsh-client-ui-
|
|
33
|
-
"@deepseek-ai/dsh-client-ui-
|
|
34
|
-
"@deepseek-ai/dsh-client-ui-
|
|
35
|
-
"@deepseek-ai/dsh-
|
|
36
|
-
"@deepseek-ai/dsh-
|
|
37
|
-
"@deepseek-ai/dsh-credentials": "0.2.
|
|
38
|
-
"@deepseek-ai/dsh-
|
|
39
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
40
|
-
"@deepseek-ai/
|
|
41
|
-
"@deepseek-ai/schemastery": "3.18.5",
|
|
27
|
+
"@deepseek-ai/cordis": "4.1.0",
|
|
28
|
+
"@deepseek-ai/dsh-app-boot": "0.2.2-rc.1",
|
|
29
|
+
"@deepseek-ai/dsh-client-connection": "0.2.2-rc.1",
|
|
30
|
+
"@deepseek-ai/dsh-client-locale": "0.2.2-rc.1",
|
|
31
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.2.2-rc.1",
|
|
32
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.2-rc.1",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.2-rc.1",
|
|
34
|
+
"@deepseek-ai/dsh-client-ui-sidebar": "0.2.2-rc.1",
|
|
35
|
+
"@deepseek-ai/dsh-config-editor": "0.2.2-rc.1",
|
|
36
|
+
"@deepseek-ai/dsh-credentials": "0.2.2-rc.1",
|
|
37
|
+
"@deepseek-ai/dsh-credentials-local": "0.2.2-rc.1",
|
|
38
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
39
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.2.2-rc.1",
|
|
40
|
+
"@deepseek-ai/schemastery": "3.19.0",
|
|
42
41
|
"@dungsil/dsh-tsconfig": "0.0.0",
|
|
43
42
|
"@dungsil/dsh-tsdown": "0.0.0",
|
|
44
43
|
"@dungsil/dsh-ui": "0.0.0",
|
|
45
44
|
"@types/react": "18.3.31",
|
|
45
|
+
"happy-dom": "21.0.4",
|
|
46
46
|
"react": "18.3.1",
|
|
47
|
+
"react-dom": "18.3.1",
|
|
47
48
|
"tsdown": "0.23.4"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@deepseek-ai/cordis": "^4.0.5",
|
|
51
|
-
"@deepseek-ai/dsh-client-connection": "^0.2.1-rc.5",
|
|
52
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-rc.5",
|
|
53
|
-
"@deepseek-ai/dsh-config-editor": "^0.2.1-rc.5",
|
|
54
|
-
"@deepseek-ai/dsh-credentials": "^0.2.1-rc.5",
|
|
55
|
-
"@deepseek-ai/dsh-llm": "^0.2.1-rc.5",
|
|
56
|
-
"@deepseek-ai/dsh-llm-pi-ai": "^0.2.1-rc.5"
|
|
52
|
+
"@deepseek-ai/dsh-client-connection": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-config-editor": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-credentials": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-llm": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
57
|
+
"@deepseek-ai/dsh-llm-pi-ai": "^0.2.1-rc.5 || ^0.2.2-rc.1"
|
|
57
58
|
},
|
|
58
59
|
"engines": {
|
|
59
|
-
"dsh": "^0.2.1-rc.5",
|
|
60
|
+
"dsh": "^0.2.1-rc.5 || ^0.2.2-rc.1",
|
|
60
61
|
"node": ">=24.9.0"
|
|
61
62
|
},
|
|
62
63
|
"dsh": {
|