@numa-tech/numa 1.11.10
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 +602 -0
- package/THIRD_PARTY_NOTICES.md +13 -0
- package/assets/codex-shortcut-icon.icns +0 -0
- package/assets/codex-shortcut-icon.ico +0 -0
- package/dist/app-config.d.ts +26 -0
- package/dist/app-config.js +135 -0
- package/dist/app-config.js.map +1 -0
- package/dist/backend.d.ts +16 -0
- package/dist/backend.js +106 -0
- package/dist/backend.js.map +1 -0
- package/dist/branding.d.ts +7 -0
- package/dist/branding.js +13 -0
- package/dist/branding.js.map +1 -0
- package/dist/chatgpt-console.d.ts +53 -0
- package/dist/chatgpt-console.js +105 -0
- package/dist/chatgpt-console.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +451 -0
- package/dist/cli.js.map +1 -0
- package/dist/codex-auth-agent.d.ts +60 -0
- package/dist/codex-auth-agent.js +331 -0
- package/dist/codex-auth-agent.js.map +1 -0
- package/dist/codex-commands.d.ts +2 -0
- package/dist/codex-commands.js +528 -0
- package/dist/codex-commands.js.map +1 -0
- package/dist/codex-legacy-cleanup.d.ts +5 -0
- package/dist/codex-legacy-cleanup.js +77 -0
- package/dist/codex-legacy-cleanup.js.map +1 -0
- package/dist/codex-process.d.ts +13 -0
- package/dist/codex-process.js +193 -0
- package/dist/codex-process.js.map +1 -0
- package/dist/codex-protocol.d.ts +352 -0
- package/dist/codex-protocol.js +116 -0
- package/dist/codex-protocol.js.map +1 -0
- package/dist/codex-quota-cache.d.ts +20 -0
- package/dist/codex-quota-cache.js +82 -0
- package/dist/codex-quota-cache.js.map +1 -0
- package/dist/codex-selection.d.ts +18 -0
- package/dist/codex-selection.js +47 -0
- package/dist/codex-selection.js.map +1 -0
- package/dist/codex-service-client.d.ts +11 -0
- package/dist/codex-service-client.js +91 -0
- package/dist/codex-service-client.js.map +1 -0
- package/dist/codex-shortcuts.d.ts +43 -0
- package/dist/codex-shortcuts.js +429 -0
- package/dist/codex-shortcuts.js.map +1 -0
- package/dist/codex-tui.d.ts +15 -0
- package/dist/codex-tui.js +235 -0
- package/dist/codex-tui.js.map +1 -0
- package/dist/command-catalog.d.ts +9 -0
- package/dist/command-catalog.js +206 -0
- package/dist/command-catalog.js.map +1 -0
- package/dist/config-page.d.ts +2 -0
- package/dist/config-page.js +51 -0
- package/dist/config-page.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +99 -0
- package/dist/config.js.map +1 -0
- package/dist/identity.d.ts +23 -0
- package/dist/identity.js +78 -0
- package/dist/identity.js.map +1 -0
- package/dist/media/client.d.ts +79 -0
- package/dist/media/client.js +175 -0
- package/dist/media/client.js.map +1 -0
- package/dist/media/commands.d.ts +2 -0
- package/dist/media/commands.js +193 -0
- package/dist/media/commands.js.map +1 -0
- package/dist/media/errors.d.ts +8 -0
- package/dist/media/errors.js +37 -0
- package/dist/media/errors.js.map +1 -0
- package/dist/media/schemas.d.ts +62 -0
- package/dist/media/schemas.js +71 -0
- package/dist/media/schemas.js.map +1 -0
- package/dist/media/transfers.d.ts +38 -0
- package/dist/media/transfers.js +169 -0
- package/dist/media/transfers.js.map +1 -0
- package/dist/oauth.d.ts +30 -0
- package/dist/oauth.js +295 -0
- package/dist/oauth.js.map +1 -0
- package/dist/private-file.d.ts +3 -0
- package/dist/private-file.js +51 -0
- package/dist/private-file.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +197 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/web-console-page.d.ts +3 -0
- package/dist/web-console-page.js +59 -0
- package/dist/web-console-page.js.map +1 -0
- package/dist/web-console.d.ts +22 -0
- package/dist/web-console.js +335 -0
- package/dist/web-console.js.map +1 -0
- package/examples/claude-desktop-installed-binary.json +11 -0
- package/examples/claude-desktop-npx.json +12 -0
- package/examples/codex-installed-binary.json +11 -0
- package/examples/codex-npx.json +12 -0
- package/package.json +67 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { constants } from "node:fs";
|
|
2
|
+
import { access, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
export const DEFAULT_REGISTRY_URL = "https://registry.npmjs.org/";
|
|
7
|
+
export const LEGACY_PRIVATE_REGISTRY_URL = "https://packages.aliyun.com/60371955c4393f5ed3b7baa8/npm/npm-registry/";
|
|
8
|
+
export const DEFAULT_API_BASE_URL = "https://apps-gw-prd.mcisaas.com/mci-devops-platform";
|
|
9
|
+
export const DEFAULT_APP_CONFIG = {
|
|
10
|
+
schemaVersion: 2,
|
|
11
|
+
locale: "zh-CN",
|
|
12
|
+
output: "text",
|
|
13
|
+
apiBaseUrl: DEFAULT_API_BASE_URL,
|
|
14
|
+
registryUrl: DEFAULT_REGISTRY_URL,
|
|
15
|
+
checkUpdates: true
|
|
16
|
+
};
|
|
17
|
+
export function appConfigDirectory() {
|
|
18
|
+
if (process.env.NUMA_CONFIG_DIR)
|
|
19
|
+
return process.env.NUMA_CONFIG_DIR;
|
|
20
|
+
if (process.platform === "win32") {
|
|
21
|
+
return join(process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"), "numa");
|
|
22
|
+
}
|
|
23
|
+
return join(process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config"), "numa");
|
|
24
|
+
}
|
|
25
|
+
export function appConfigPath() {
|
|
26
|
+
return join(appConfigDirectory(), "config.json");
|
|
27
|
+
}
|
|
28
|
+
function normalizeConfig(value) {
|
|
29
|
+
const migrateLegacyRegistry = value?.schemaVersion !== 2 &&
|
|
30
|
+
value?.registryUrl === LEGACY_PRIVATE_REGISTRY_URL;
|
|
31
|
+
const normalized = {
|
|
32
|
+
...DEFAULT_APP_CONFIG,
|
|
33
|
+
...(value ?? {}),
|
|
34
|
+
schemaVersion: 2,
|
|
35
|
+
...(migrateLegacyRegistry ? { registryUrl: DEFAULT_REGISTRY_URL } : {})
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
...normalized,
|
|
39
|
+
// Older installations persisted an empty value before the production
|
|
40
|
+
// platform URL became the default.
|
|
41
|
+
apiBaseUrl: normalized.apiBaseUrl.trim() || DEFAULT_API_BASE_URL
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export async function loadAppConfig() {
|
|
45
|
+
try {
|
|
46
|
+
return normalizeConfig(JSON.parse(await readFile(appConfigPath(), "utf8")));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
if (error.code === "ENOENT")
|
|
50
|
+
return { ...DEFAULT_APP_CONFIG };
|
|
51
|
+
throw new Error(`无法读取 CLI 配置 ${appConfigPath()}: ${error.message}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function loadAppConfigSync() {
|
|
55
|
+
try {
|
|
56
|
+
return normalizeConfig(JSON.parse(readFileSync(appConfigPath(), "utf8")));
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error.code === "ENOENT")
|
|
60
|
+
return { ...DEFAULT_APP_CONFIG };
|
|
61
|
+
throw new Error(`无法读取 CLI 配置 ${appConfigPath()}: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export async function hasAppConfig() {
|
|
65
|
+
try {
|
|
66
|
+
await access(appConfigPath(), constants.F_OK);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
export async function saveAppConfig(config) {
|
|
74
|
+
const now = new Date().toISOString();
|
|
75
|
+
const saved = {
|
|
76
|
+
...normalizeConfig(config),
|
|
77
|
+
initializedAt: config.initializedAt ?? now,
|
|
78
|
+
updatedAt: now
|
|
79
|
+
};
|
|
80
|
+
const path = appConfigPath();
|
|
81
|
+
await mkdir(dirname(path), { recursive: true });
|
|
82
|
+
const temporaryPath = `${path}.${process.pid}.tmp`;
|
|
83
|
+
await writeFile(temporaryPath, `${JSON.stringify(saved, null, 2)}\n`, { mode: 0o600 });
|
|
84
|
+
await rename(temporaryPath, path);
|
|
85
|
+
return saved;
|
|
86
|
+
}
|
|
87
|
+
export async function resetAppConfig() {
|
|
88
|
+
await rm(appConfigPath(), { force: true });
|
|
89
|
+
}
|
|
90
|
+
export const CONFIG_KEYS = [
|
|
91
|
+
"locale",
|
|
92
|
+
"output",
|
|
93
|
+
"apiBaseUrl",
|
|
94
|
+
"registryUrl",
|
|
95
|
+
"checkUpdates"
|
|
96
|
+
];
|
|
97
|
+
export function updateConfigValue(config, expression) {
|
|
98
|
+
const separator = expression.indexOf("=");
|
|
99
|
+
if (separator < 1)
|
|
100
|
+
throw new Error(`配置格式应为 key=value,收到: ${expression}`);
|
|
101
|
+
const key = expression.slice(0, separator);
|
|
102
|
+
const rawValue = expression.slice(separator + 1).trim();
|
|
103
|
+
if (!CONFIG_KEYS.includes(key)) {
|
|
104
|
+
throw new Error(`未知配置项 ${key}。可用项: ${CONFIG_KEYS.join(", ")}`);
|
|
105
|
+
}
|
|
106
|
+
if (key === "locale") {
|
|
107
|
+
if (rawValue !== "zh-CN" && rawValue !== "en-US")
|
|
108
|
+
throw new Error("locale 只能是 zh-CN 或 en-US");
|
|
109
|
+
return { ...config, locale: rawValue };
|
|
110
|
+
}
|
|
111
|
+
if (key === "output") {
|
|
112
|
+
if (rawValue !== "text" && rawValue !== "json")
|
|
113
|
+
throw new Error("output 只能是 text 或 json");
|
|
114
|
+
return { ...config, output: rawValue };
|
|
115
|
+
}
|
|
116
|
+
if (key === "checkUpdates") {
|
|
117
|
+
if (!["true", "false"].includes(rawValue))
|
|
118
|
+
throw new Error("checkUpdates 只能是 true 或 false");
|
|
119
|
+
return { ...config, checkUpdates: rawValue === "true" };
|
|
120
|
+
}
|
|
121
|
+
if (key === "apiBaseUrl" && rawValue) {
|
|
122
|
+
const url = new URL(rawValue);
|
|
123
|
+
if (!["http:", "https:"].includes(url.protocol))
|
|
124
|
+
throw new Error("apiBaseUrl 必须是 HTTP(S) URL");
|
|
125
|
+
}
|
|
126
|
+
if (key === "registryUrl") {
|
|
127
|
+
const url = new URL(rawValue);
|
|
128
|
+
if (!["http:", "https:"].includes(url.protocol))
|
|
129
|
+
throw new Error("registryUrl 必须是 HTTP(S) URL");
|
|
130
|
+
if (url.username || url.password)
|
|
131
|
+
throw new Error("registryUrl 不能包含用户名或密码");
|
|
132
|
+
}
|
|
133
|
+
return { ...config, [key]: rawValue };
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=app-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-config.js","sourceRoot":"","sources":["../src/app-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuthConfig } from "./config.js";
|
|
2
|
+
export interface BackendRequestInput {
|
|
3
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
4
|
+
path?: string;
|
|
5
|
+
url?: string;
|
|
6
|
+
headers?: Record<string, string>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
}
|
|
9
|
+
export interface BackendResponse {
|
|
10
|
+
status: number;
|
|
11
|
+
statusText: string;
|
|
12
|
+
headers: Record<string, string>;
|
|
13
|
+
body: unknown;
|
|
14
|
+
}
|
|
15
|
+
export declare function resolveBackendUrl(config: AuthConfig, input: BackendRequestInput): string;
|
|
16
|
+
export declare function authenticatedBackendRequest(config: AuthConfig, input: BackendRequestInput): Promise<BackendResponse>;
|
package/dist/backend.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { fetchWithKeycloakIdentity } from "./oauth.js";
|
|
2
|
+
function validatedBackendBaseUrl(config) {
|
|
3
|
+
if (!config.backendBaseUrl) {
|
|
4
|
+
throw new Error("NUMA_BACKEND_BASE_URL is required for authenticated backend requests.");
|
|
5
|
+
}
|
|
6
|
+
const baseUrl = new URL(config.backendBaseUrl);
|
|
7
|
+
if (!["http:", "https:"].includes(baseUrl.protocol) || baseUrl.username || baseUrl.password) {
|
|
8
|
+
throw new Error("NUMA_BACKEND_BASE_URL must be an HTTP(S) URL without embedded credentials.");
|
|
9
|
+
}
|
|
10
|
+
if (baseUrl.search || baseUrl.hash) {
|
|
11
|
+
throw new Error("NUMA_BACKEND_BASE_URL must not contain query parameters or a fragment.");
|
|
12
|
+
}
|
|
13
|
+
return baseUrl;
|
|
14
|
+
}
|
|
15
|
+
function backendServicePrefix(baseUrl) {
|
|
16
|
+
return baseUrl.pathname.replace(/\/+$/u, "");
|
|
17
|
+
}
|
|
18
|
+
function assertSameBackendService(baseUrl, candidate) {
|
|
19
|
+
if (!["http:", "https:"].includes(candidate.protocol) || candidate.username || candidate.password) {
|
|
20
|
+
throw new Error("Backend URL must be an HTTP(S) URL without embedded credentials.");
|
|
21
|
+
}
|
|
22
|
+
if (candidate.origin !== baseUrl.origin) {
|
|
23
|
+
throw new Error("Authenticated backend requests are restricted to the configured backend origin.");
|
|
24
|
+
}
|
|
25
|
+
const prefix = backendServicePrefix(baseUrl);
|
|
26
|
+
if (prefix && candidate.pathname !== prefix && !candidate.pathname.startsWith(`${prefix}/`)) {
|
|
27
|
+
throw new Error("Authenticated backend requests are restricted to the configured backend service path.");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function containsPathTraversal(path) {
|
|
31
|
+
let decodedPath = path.split(/[?#]/u, 1)[0] ?? path;
|
|
32
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
33
|
+
try {
|
|
34
|
+
decodedPath = decodeURIComponent(decodedPath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new Error("Backend path contains invalid percent encoding.");
|
|
38
|
+
}
|
|
39
|
+
if (decodedPath.split(/[\\/]/u).some((segment) => segment === "." || segment === ".."))
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
export function resolveBackendUrl(config, input) {
|
|
45
|
+
const baseUrl = validatedBackendBaseUrl(config);
|
|
46
|
+
if (input.url) {
|
|
47
|
+
if (!config.allowAbsoluteBackendUrls) {
|
|
48
|
+
throw new Error("Absolute backend URLs are disabled. Set NUMA_BACKEND_ALLOW_ABSOLUTE_URLS=true to allow them.");
|
|
49
|
+
}
|
|
50
|
+
const candidate = new URL(input.url);
|
|
51
|
+
assertSameBackendService(baseUrl, candidate);
|
|
52
|
+
return candidate.toString();
|
|
53
|
+
}
|
|
54
|
+
if (!input.path)
|
|
55
|
+
throw new Error("Either path or url is required.");
|
|
56
|
+
if (!input.path.startsWith("/") ||
|
|
57
|
+
input.path.startsWith("//") ||
|
|
58
|
+
input.path.startsWith("/\\") ||
|
|
59
|
+
input.path.includes("\\") ||
|
|
60
|
+
/[\u0000-\u001f\u007f]/u.test(input.path) ||
|
|
61
|
+
containsPathTraversal(input.path)) {
|
|
62
|
+
throw new Error("Backend path must be an absolute same-origin path beginning with one '/'.");
|
|
63
|
+
}
|
|
64
|
+
const prefix = backendServicePrefix(baseUrl);
|
|
65
|
+
const alreadyPrefixed = Boolean(prefix && (input.path === prefix || input.path.startsWith(`${prefix}/`)));
|
|
66
|
+
const candidate = new URL(alreadyPrefixed ? input.path : `${prefix}${input.path}`, baseUrl.origin);
|
|
67
|
+
assertSameBackendService(baseUrl, candidate);
|
|
68
|
+
return candidate.toString();
|
|
69
|
+
}
|
|
70
|
+
export async function authenticatedBackendRequest(config, input) {
|
|
71
|
+
const url = resolveBackendUrl(config, input);
|
|
72
|
+
const headers = {
|
|
73
|
+
...(input.headers ?? {})
|
|
74
|
+
};
|
|
75
|
+
if (input.body != null && !Object.keys(headers).some((key) => key.toLowerCase() === "content-type")) {
|
|
76
|
+
headers["Content-Type"] = "application/json";
|
|
77
|
+
}
|
|
78
|
+
const requestBody = input.body == null
|
|
79
|
+
? undefined
|
|
80
|
+
: typeof input.body === "string"
|
|
81
|
+
? input.body
|
|
82
|
+
: JSON.stringify(input.body);
|
|
83
|
+
const response = await fetchWithKeycloakIdentity(config, url, () => ({
|
|
84
|
+
method: input.method,
|
|
85
|
+
headers,
|
|
86
|
+
body: requestBody
|
|
87
|
+
}));
|
|
88
|
+
const responseText = await response.text();
|
|
89
|
+
let body = responseText;
|
|
90
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
91
|
+
if (contentType.includes("application/json") && responseText) {
|
|
92
|
+
try {
|
|
93
|
+
body = JSON.parse(responseText);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
body = responseText;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
status: response.status,
|
|
101
|
+
statusText: response.statusText,
|
|
102
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
103
|
+
body
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const PRODUCT_NAME = "Numa";
|
|
2
|
+
export declare const CLI_NAME = "numa";
|
|
3
|
+
export declare const ORGANIZATION_NAME = "numa-tech";
|
|
4
|
+
export declare const PACKAGE_NAME = "@numa-tech/numa";
|
|
5
|
+
export declare const CODEX_SHORTCUT_NAME = "numa-codex";
|
|
6
|
+
export declare const CODEX_APP_NAME = "Numa Codex";
|
|
7
|
+
export declare const PACKAGE_VERSION: string;
|
package/dist/branding.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
3
|
+
export const PRODUCT_NAME = "Numa";
|
|
4
|
+
export const CLI_NAME = "numa";
|
|
5
|
+
export const ORGANIZATION_NAME = "numa-tech";
|
|
6
|
+
export const PACKAGE_NAME = "@numa-tech/numa";
|
|
7
|
+
export const CODEX_SHORTCUT_NAME = "numa-codex";
|
|
8
|
+
export const CODEX_APP_NAME = "Numa Codex";
|
|
9
|
+
export const PACKAGE_VERSION = manifest.version ?? "0.0.0";
|
|
10
|
+
if (manifest.name !== PACKAGE_NAME) {
|
|
11
|
+
throw new Error(`包标识不一致:预期 ${PACKAGE_NAME},实际 ${manifest.name ?? "未设置"}`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=branding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branding.js","sourceRoot":"","sources":["../src/branding.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAOvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CACzB,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC/C,CAAC;AAErB,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;AACnC,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC/B,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAC7C,MAAM,CAAC,MAAM,YAAY,GAAG,iBAAiB,CAAC;AAC9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,YAAY,CAAC;AAChD,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;AAC3C,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,IAAI,OAAO,CAAC;AAE3D,IAAI,QAAQ,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;IACnC,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,OAAO,QAAQ,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { type AccountStorageV3 } from "codex-multi-auth/storage";
|
|
2
|
+
import { type AuthConfig } from "./config.js";
|
|
3
|
+
import type { CodexAccountListResponse, CodexAccountSummary, CodexQuotaSnapshotView } from "./codex-protocol.js";
|
|
4
|
+
import { loadCodexQuotaUploads, type CodexQuotaUpload } from "./codex-quota-cache.js";
|
|
5
|
+
import { type CodexSelection } from "./codex-selection.js";
|
|
6
|
+
export interface LocalChatgptAccount {
|
|
7
|
+
id: string;
|
|
8
|
+
accountId?: string;
|
|
9
|
+
label: string;
|
|
10
|
+
email?: string;
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
selected: boolean;
|
|
13
|
+
accessExpiresAt?: number;
|
|
14
|
+
quota?: CodexQuotaUpload;
|
|
15
|
+
}
|
|
16
|
+
export interface LocalChatgptState {
|
|
17
|
+
status: "READY";
|
|
18
|
+
readAt: number;
|
|
19
|
+
total: number;
|
|
20
|
+
available: number;
|
|
21
|
+
accounts: LocalChatgptAccount[];
|
|
22
|
+
}
|
|
23
|
+
export interface RemoteChatgptState {
|
|
24
|
+
status: "SUCCESS" | "FAILED" | "NOT_CONFIGURED";
|
|
25
|
+
serviceUrl?: string;
|
|
26
|
+
syncedAt: number;
|
|
27
|
+
accounts: Array<CodexAccountSummary & {
|
|
28
|
+
quota?: CodexQuotaSnapshotView | null;
|
|
29
|
+
}>;
|
|
30
|
+
defaultAccountId?: string | null;
|
|
31
|
+
error?: {
|
|
32
|
+
code: string;
|
|
33
|
+
message: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
interface LocalChatgptDependencies {
|
|
37
|
+
loadStorage?: () => Promise<{
|
|
38
|
+
storage: AccountStorageV3 | null;
|
|
39
|
+
storagePath: string;
|
|
40
|
+
}>;
|
|
41
|
+
loadQuota?: typeof loadCodexQuotaUploads;
|
|
42
|
+
now?: () => number;
|
|
43
|
+
}
|
|
44
|
+
interface RemoteChatgptDependencies {
|
|
45
|
+
loadSelection?: () => Promise<CodexSelection | undefined>;
|
|
46
|
+
loadAuthConfig?: () => AuthConfig;
|
|
47
|
+
listAccounts?: (authConfig: AuthConfig, serviceUrl: string, allowInsecurePoc: boolean) => Promise<CodexAccountListResponse>;
|
|
48
|
+
explicitServiceUrl?: string;
|
|
49
|
+
now?: () => number;
|
|
50
|
+
}
|
|
51
|
+
export declare function loadLocalChatgptState(dependencies?: LocalChatgptDependencies): Promise<LocalChatgptState>;
|
|
52
|
+
export declare function loadRemoteChatgptState(dependencies?: RemoteChatgptDependencies): Promise<RemoteChatgptState>;
|
|
53
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
import { getStoragePath, loadAccounts, setStoragePath } from "codex-multi-auth/storage";
|
|
4
|
+
import { loadConfig } from "./config.js";
|
|
5
|
+
import { loadCodexQuotaUploads } from "./codex-quota-cache.js";
|
|
6
|
+
import { listRemoteCodexAccounts } from "./codex-service-client.js";
|
|
7
|
+
import { loadCodexSelection } from "./codex-selection.js";
|
|
8
|
+
function safeLocalId(identity) {
|
|
9
|
+
return `local_${createHash("sha256").update(identity).digest("hex").slice(0, 16)}`;
|
|
10
|
+
}
|
|
11
|
+
function selectedIndex(storage) {
|
|
12
|
+
return storage.pinnedAccountIndex ?? storage.activeIndexByFamily?.codex ?? storage.activeIndex;
|
|
13
|
+
}
|
|
14
|
+
async function defaultStorage() {
|
|
15
|
+
setStoragePath(null);
|
|
16
|
+
return { storage: await loadAccounts(), storagePath: getStoragePath() };
|
|
17
|
+
}
|
|
18
|
+
export async function loadLocalChatgptState(dependencies = {}) {
|
|
19
|
+
const loadStorage = dependencies.loadStorage ?? defaultStorage;
|
|
20
|
+
const loadQuota = dependencies.loadQuota ?? loadCodexQuotaUploads;
|
|
21
|
+
const now = dependencies.now ?? Date.now;
|
|
22
|
+
const { storage, storagePath } = await loadStorage();
|
|
23
|
+
if (!storage) {
|
|
24
|
+
return { status: "READY", readAt: now(), total: 0, available: 0, accounts: [] };
|
|
25
|
+
}
|
|
26
|
+
const quota = await loadQuota(storagePath, storage.accounts);
|
|
27
|
+
const active = selectedIndex(storage);
|
|
28
|
+
const accounts = storage.accounts.map((account, index) => {
|
|
29
|
+
const identity = account.accountId?.trim() ||
|
|
30
|
+
account.email?.trim().toLowerCase() ||
|
|
31
|
+
`${account.addedAt}:${index}`;
|
|
32
|
+
return {
|
|
33
|
+
id: safeLocalId(identity),
|
|
34
|
+
...(account.accountId?.trim() ? { accountId: account.accountId.trim() } : {}),
|
|
35
|
+
label: account.accountLabel?.trim() ||
|
|
36
|
+
account.email?.trim() ||
|
|
37
|
+
`ChatGPT 账号 ${index + 1}`,
|
|
38
|
+
...(account.email?.trim() ? { email: account.email.trim() } : {}),
|
|
39
|
+
enabled: account.enabled !== false,
|
|
40
|
+
selected: index === active,
|
|
41
|
+
...(account.expiresAt && account.expiresAt > 0 ? { accessExpiresAt: account.expiresAt } : {}),
|
|
42
|
+
...(quota[index] ? { quota: quota[index] } : {})
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
status: "READY",
|
|
47
|
+
readAt: now(),
|
|
48
|
+
total: accounts.length,
|
|
49
|
+
available: accounts.filter((account) => account.enabled).length,
|
|
50
|
+
accounts
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function appendApiPath(rawUrl) {
|
|
54
|
+
const url = rawUrl.replace(/\/+$/, "");
|
|
55
|
+
return /\/api$/u.test(url) ? url : `${url}/api`;
|
|
56
|
+
}
|
|
57
|
+
async function resolveRemoteTarget(dependencies) {
|
|
58
|
+
const loadSelection = dependencies.loadSelection ?? loadCodexSelection;
|
|
59
|
+
const config = (dependencies.loadAuthConfig ?? loadConfig)();
|
|
60
|
+
const selection = await loadSelection();
|
|
61
|
+
const explicit = dependencies.explicitServiceUrl ?? process.env.NUMA_CODEX_SERVICE_URL?.trim();
|
|
62
|
+
const serviceUrl = explicit || selection?.serviceUrl ||
|
|
63
|
+
(config.backendBaseUrl ? appendApiPath(config.backendBaseUrl) : undefined);
|
|
64
|
+
if (!serviceUrl)
|
|
65
|
+
return undefined;
|
|
66
|
+
return {
|
|
67
|
+
serviceUrl,
|
|
68
|
+
allowInsecurePoc: explicit ? false : Boolean(selection?.allowInsecurePoc)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function safeRemoteError(error) {
|
|
72
|
+
const candidate = error;
|
|
73
|
+
const code = typeof candidate?.code === "string" ? candidate.code : "remote_sync_failed";
|
|
74
|
+
const message = typeof candidate?.message === "string" ? candidate.message : String(error);
|
|
75
|
+
return { code: code.slice(0, 80), message: message.slice(0, 320) };
|
|
76
|
+
}
|
|
77
|
+
export async function loadRemoteChatgptState(dependencies = {}) {
|
|
78
|
+
const now = dependencies.now ?? Date.now;
|
|
79
|
+
let target;
|
|
80
|
+
try {
|
|
81
|
+
target = await resolveRemoteTarget(dependencies);
|
|
82
|
+
if (!target) {
|
|
83
|
+
return { status: "NOT_CONFIGURED", syncedAt: now(), accounts: [] };
|
|
84
|
+
}
|
|
85
|
+
const config = (dependencies.loadAuthConfig ?? loadConfig)();
|
|
86
|
+
const response = await (dependencies.listAccounts ?? listRemoteCodexAccounts)(config, target.serviceUrl, target.allowInsecurePoc);
|
|
87
|
+
return {
|
|
88
|
+
status: "SUCCESS",
|
|
89
|
+
serviceUrl: target.serviceUrl,
|
|
90
|
+
syncedAt: now(),
|
|
91
|
+
accounts: response.accounts,
|
|
92
|
+
defaultAccountId: response.defaultAccountId
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
return {
|
|
97
|
+
status: "FAILED",
|
|
98
|
+
...(target ? { serviceUrl: target.serviceUrl } : {}),
|
|
99
|
+
syncedAt: now(),
|
|
100
|
+
accounts: [],
|
|
101
|
+
error: safeRemoteError(error)
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=chatgpt-console.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chatgpt-console.js","sourceRoot":"","sources":["../src/chatgpt-console.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED