@michengai/dsh-codex-ui 1.0.0 → 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/CHANGELOG.md +30 -0
- package/CHANGELOG.zh-CN.md +30 -0
- package/README.md +9 -5
- package/README.zh-CN.md +9 -5
- package/assets/screenshots/conversation-light.png +0 -0
- package/assets/screenshots/conversation.png +0 -0
- package/assets/screenshots/settings-about.png +0 -0
- package/assets/screenshots/settings-general-light.png +0 -0
- package/assets/usage-frame.html +1 -0
- package/lib/client.js +1239 -72
- package/lib/index.mjs +57 -3
- package/lib/usage-frame.css +1 -0
- package/lib/usage-frame.js +489 -0
- package/package.json +8 -5
package/lib/index.mjs
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import { apply as apply$1 } from "@deepseek-ai/dsh-client-ui-settings-general";
|
|
2
|
-
import { spawn } from "node:child_process";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
4
2
|
import { lstat, mkdir, open, readFile, realpath, rename, rm, unlink, writeFile } from "node:fs/promises";
|
|
5
|
-
import { homedir } from "node:os";
|
|
6
3
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep, win32 } from "node:path";
|
|
7
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { spawn } from "node:child_process";
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
8
|
import { randomBytes, randomUUID } from "node:crypto";
|
|
9
|
+
//#region src/usage-frame/contract.ts
|
|
10
|
+
/** 同源费用承载页与宿主之间的最小能力桥;不暴露 Context 或远程服务全集。 */
|
|
11
|
+
const USAGE_FRAME_PATH = "/api/dsh-codex-ui/usage/frame";
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/usage-frame-routes.ts
|
|
14
|
+
/** 提供经过宿主认证的同源费用承载资源;只读取固定文件,不代理计费 API。 */
|
|
15
|
+
const USAGE_FRAME_ROUTES = [
|
|
16
|
+
USAGE_FRAME_PATH,
|
|
17
|
+
`${USAGE_FRAME_PATH}.js`,
|
|
18
|
+
`${USAGE_FRAME_PATH}.css`,
|
|
19
|
+
"/api/dsh-codex-ui/usage/plugin.js"
|
|
20
|
+
];
|
|
21
|
+
async function usageFrameAsset(path, profileDir) {
|
|
22
|
+
const file = {
|
|
23
|
+
[USAGE_FRAME_PATH]: ["text/html; charset=utf-8", fileURLToPath(new URL("../assets/usage-frame.html", import.meta.url))],
|
|
24
|
+
[`${USAGE_FRAME_PATH}.js`]: ["text/javascript; charset=utf-8", fileURLToPath(new URL("./usage-frame.js", import.meta.url))],
|
|
25
|
+
[`${USAGE_FRAME_PATH}.css`]: ["text/css; charset=utf-8", fileURLToPath(new URL("./usage-frame.css", import.meta.url))],
|
|
26
|
+
"/api/dsh-codex-ui/usage/plugin.js": ["text/javascript; charset=utf-8", resolve(profileDir, "node_modules", "@kenz1117", "dsh-ui-usage-billing", "lib", "client.js")]
|
|
27
|
+
}[path];
|
|
28
|
+
if (!file) throw new Error("未知费用资源");
|
|
29
|
+
return {
|
|
30
|
+
contentType: file[0],
|
|
31
|
+
body: await readFile(file[1], "utf8")
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
9
35
|
//#region src/business-api.ts
|
|
10
36
|
const CODEX_UI_API_BASE = "/api/dsh-codex-ui";
|
|
11
37
|
const CODEX_UI_API_ENDPOINTS = Object.freeze({
|
|
@@ -1677,6 +1703,34 @@ function sessionMoveAuthenticationError(status, error) {
|
|
|
1677
1703
|
function apply(ctx) {
|
|
1678
1704
|
apply$1(ctx);
|
|
1679
1705
|
const host = hostServices(ctx);
|
|
1706
|
+
ctx.effect(() => {
|
|
1707
|
+
const disposers = USAGE_FRAME_ROUTES.map((path) => host.webServer.register({
|
|
1708
|
+
kind: "exact",
|
|
1709
|
+
path,
|
|
1710
|
+
handler: async (request, response) => {
|
|
1711
|
+
if (!authenticateBusinessRequest(ctx, request, response)) return;
|
|
1712
|
+
if (request.method !== "GET" && request.method !== "HEAD") {
|
|
1713
|
+
response.writeHead(405);
|
|
1714
|
+
response.end();
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1717
|
+
try {
|
|
1718
|
+
const asset = await usageFrameAsset(path, resolveDependencyRuntime(ctx).profileDir);
|
|
1719
|
+
response.writeHead(200, {
|
|
1720
|
+
"content-type": asset.contentType,
|
|
1721
|
+
"cache-control": "no-store",
|
|
1722
|
+
"x-content-type-options": "nosniff",
|
|
1723
|
+
"content-security-policy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:; connect-src 'self'; frame-ancestors 'self'"
|
|
1724
|
+
});
|
|
1725
|
+
response.end(request.method === "HEAD" ? void 0 : asset.body);
|
|
1726
|
+
} catch {
|
|
1727
|
+
response.writeHead(404, { "content-type": "text/plain; charset=utf-8" });
|
|
1728
|
+
response.end("费用插件或承载资源不可用。");
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
}));
|
|
1732
|
+
return () => disposers.forEach((dispose) => dispose());
|
|
1733
|
+
}, "michengai-codex-ui: usage frame");
|
|
1680
1734
|
ctx.effect(() => {
|
|
1681
1735
|
const foregroundExplorer = new ForegroundExplorer();
|
|
1682
1736
|
foregroundExplorer.warmup().catch((error) => ctx.logger.warn("foreground explorer warmup failed: %s", error));
|