gaoding-cli 1.0.0-alpha.5
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 +88 -0
- package/LICENSE +21 -0
- package/README.md +136 -0
- package/SECURITY.md +34 -0
- package/dist/bin/gd-cli.d.ts +2 -0
- package/dist/bin/gd-cli.js +10 -0
- package/dist/src/api/app-runner.d.ts +33 -0
- package/dist/src/api/app-runner.js +1177 -0
- package/dist/src/api/dam-client.d.ts +111 -0
- package/dist/src/api/dam-client.js +897 -0
- package/dist/src/api/direct-auth.d.ts +3 -0
- package/dist/src/api/direct-auth.js +11 -0
- package/dist/src/api/direct-client.d.ts +27 -0
- package/dist/src/api/direct-client.js +151 -0
- package/dist/src/api/direct-tools.d.ts +43 -0
- package/dist/src/api/direct-tools.js +1155 -0
- package/dist/src/api/hub-client.d.ts +20 -0
- package/dist/src/api/hub-client.js +99 -0
- package/dist/src/api/sso-client.d.ts +60 -0
- package/dist/src/api/sso-client.js +140 -0
- package/dist/src/api/task-poller.d.ts +38 -0
- package/dist/src/api/task-poller.js +72 -0
- package/dist/src/api/tool-invoker.d.ts +12 -0
- package/dist/src/api/tool-invoker.js +11 -0
- package/dist/src/api/usage-client.d.ts +39 -0
- package/dist/src/api/usage-client.js +179 -0
- package/dist/src/auth/credential-store-v2.d.ts +12 -0
- package/dist/src/auth/credential-store-v2.js +59 -0
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +191 -0
- package/dist/src/commands/dam.d.ts +2 -0
- package/dist/src/commands/dam.js +293 -0
- package/dist/src/commands/models.d.ts +2 -0
- package/dist/src/commands/models.js +78 -0
- package/dist/src/commands/org.d.ts +2 -0
- package/dist/src/commands/org.js +137 -0
- package/dist/src/commands/skills.d.ts +2 -0
- package/dist/src/commands/skills.js +213 -0
- package/dist/src/commands/tools.d.ts +4 -0
- package/dist/src/commands/tools.js +383 -0
- package/dist/src/commands/update.d.ts +2 -0
- package/dist/src/commands/update.js +167 -0
- package/dist/src/commands/usage.d.ts +7 -0
- package/dist/src/commands/usage.js +43 -0
- package/dist/src/commands/workflows.d.ts +3 -0
- package/dist/src/commands/workflows.js +398 -0
- package/dist/src/core/auth/auth-provider.d.ts +8 -0
- package/dist/src/core/auth/auth-provider.js +12 -0
- package/dist/src/core/auth/device-oauth-provider.d.ts +12 -0
- package/dist/src/core/auth/device-oauth-provider.js +124 -0
- package/dist/src/core/auth/org-manager.d.ts +26 -0
- package/dist/src/core/auth/org-manager.js +224 -0
- package/dist/src/core/auth/signature.d.ts +19 -0
- package/dist/src/core/auth/signature.js +33 -0
- package/dist/src/core/auth/types.d.ts +52 -0
- package/dist/src/core/auth/types.js +3 -0
- package/dist/src/core/output/cli-error.d.ts +5 -0
- package/dist/src/core/output/cli-error.js +8 -0
- package/dist/src/core/output/detector.d.ts +5 -0
- package/dist/src/core/output/detector.js +14 -0
- package/dist/src/core/output/engine.d.ts +32 -0
- package/dist/src/core/output/engine.js +77 -0
- package/dist/src/core/output/envelope.d.ts +40 -0
- package/dist/src/core/output/envelope.js +119 -0
- package/dist/src/core/output/index.d.ts +4 -0
- package/dist/src/core/output/index.js +4 -0
- package/dist/src/core/output/live-display.d.ts +15 -0
- package/dist/src/core/output/live-display.js +111 -0
- package/dist/src/core/output/result-card.d.ts +18 -0
- package/dist/src/core/output/result-card.js +39 -0
- package/dist/src/core/prompt/index.d.ts +31 -0
- package/dist/src/core/prompt/index.js +36 -0
- package/dist/src/io.d.ts +14 -0
- package/dist/src/io.js +31 -0
- package/dist/src/middleware/auth.d.ts +3 -0
- package/dist/src/middleware/auth.js +74 -0
- package/dist/src/middleware/error-handler.d.ts +3 -0
- package/dist/src/middleware/error-handler.js +431 -0
- package/dist/src/middleware/interactive-params.d.ts +14 -0
- package/dist/src/middleware/interactive-params.js +53 -0
- package/dist/src/middleware/output.d.ts +14 -0
- package/dist/src/middleware/output.js +546 -0
- package/dist/src/models/model-catalog.d.ts +26 -0
- package/dist/src/models/model-catalog.js +216 -0
- package/dist/src/program.d.ts +2 -0
- package/dist/src/program.js +152 -0
- package/dist/src/registry/agent-contracts.d.ts +43 -0
- package/dist/src/registry/agent-contracts.js +483 -0
- package/dist/src/registry/app-loader.d.ts +2 -0
- package/dist/src/registry/app-loader.js +70 -0
- package/dist/src/registry/direct-registry.d.ts +11 -0
- package/dist/src/registry/direct-registry.js +234 -0
- package/dist/src/registry/registry-cache.d.ts +10 -0
- package/dist/src/registry/registry-cache.js +52 -0
- package/dist/src/registry/registry-client.d.ts +28 -0
- package/dist/src/registry/registry-client.js +50 -0
- package/dist/src/registry/types.d.ts +69 -0
- package/dist/src/registry/types.js +1 -0
- package/dist/src/tty/auth-presenter.d.ts +3 -0
- package/dist/src/tty/auth-presenter.js +21 -0
- package/dist/src/update/install-source.d.ts +19 -0
- package/dist/src/update/install-source.js +139 -0
- package/dist/src/update/notifier.d.ts +2 -0
- package/dist/src/update/notifier.js +59 -0
- package/dist/src/update/update-checker.d.ts +22 -0
- package/dist/src/update/update-checker.js +110 -0
- package/dist/src/update/version.d.ts +9 -0
- package/dist/src/update/version.js +52 -0
- package/dist/src/utils/agent-skill-installer.d.ts +57 -0
- package/dist/src/utils/agent-skill-installer.js +389 -0
- package/dist/src/utils/capability-metadata.d.ts +18 -0
- package/dist/src/utils/capability-metadata.js +88 -0
- package/dist/src/utils/capability-presenter.d.ts +4 -0
- package/dist/src/utils/capability-presenter.js +190 -0
- package/dist/src/utils/config.d.ts +16 -0
- package/dist/src/utils/config.js +54 -0
- package/dist/src/utils/credential-permissions.d.ts +2 -0
- package/dist/src/utils/credential-permissions.js +22 -0
- package/dist/src/utils/ecommerce-input-guidance.d.ts +15 -0
- package/dist/src/utils/ecommerce-input-guidance.js +85 -0
- package/dist/src/utils/endpoints.d.ts +52 -0
- package/dist/src/utils/endpoints.js +258 -0
- package/dist/src/utils/enrich-upload-params.d.ts +6 -0
- package/dist/src/utils/enrich-upload-params.js +11 -0
- package/dist/src/utils/entitlement.d.ts +17 -0
- package/dist/src/utils/entitlement.js +146 -0
- package/dist/src/utils/gd-home.d.ts +7 -0
- package/dist/src/utils/gd-home.js +26 -0
- package/dist/src/utils/help-verify.d.ts +9 -0
- package/dist/src/utils/help-verify.js +41 -0
- package/dist/src/utils/input-json.d.ts +3 -0
- package/dist/src/utils/input-json.js +61 -0
- package/dist/src/utils/list-output-format.d.ts +10 -0
- package/dist/src/utils/list-output-format.js +34 -0
- package/dist/src/utils/logger.d.ts +6 -0
- package/dist/src/utils/logger.js +19 -0
- package/dist/src/utils/matting-compose.d.ts +10 -0
- package/dist/src/utils/matting-compose.js +45 -0
- package/dist/src/utils/open-browser.d.ts +1 -0
- package/dist/src/utils/open-browser.js +4 -0
- package/dist/src/utils/output-path.d.ts +5 -0
- package/dist/src/utils/output-path.js +70 -0
- package/dist/src/utils/redact.d.ts +3 -0
- package/dist/src/utils/redact.js +96 -0
- package/dist/src/utils/reference-image.d.ts +8 -0
- package/dist/src/utils/reference-image.js +43 -0
- package/dist/src/utils/resolve-app-local-images.d.ts +8 -0
- package/dist/src/utils/resolve-app-local-images.js +84 -0
- package/dist/src/utils/sensitive-path.d.ts +6 -0
- package/dist/src/utils/sensitive-path.js +69 -0
- package/dist/src/utils/settings-store.d.ts +42 -0
- package/dist/src/utils/settings-store.js +50 -0
- package/dist/src/utils/sleep.d.ts +1 -0
- package/dist/src/utils/sleep.js +3 -0
- package/dist/src/utils/spinner.d.ts +2 -0
- package/dist/src/utils/spinner.js +4 -0
- package/dist/src/utils/static-help.d.ts +2 -0
- package/dist/src/utils/static-help.js +3 -0
- package/dist/src/utils/tool-display.d.ts +10 -0
- package/dist/src/utils/tool-display.js +55 -0
- package/dist/src/utils/transient-network-error.d.ts +4 -0
- package/dist/src/utils/transient-network-error.js +40 -0
- package/dist/src/utils/url-safety.d.ts +6 -0
- package/dist/src/utils/url-safety.js +67 -0
- package/dist/src/utils/write-app-deliverables.d.ts +18 -0
- package/dist/src/utils/write-app-deliverables.js +386 -0
- package/package.json +91 -0
- package/skills/gd-cli/SKILL.md +57 -0
- package/skills/gd-cli/references/auth.md +31 -0
- package/skills/gd-cli/references/deliverables.md +22 -0
- package/skills/gd-cli/references/entitlement.md +21 -0
- package/skills/gd-cli/references/errors.md +19 -0
- package/skills/gd-cli/references/org.md +18 -0
- package/skills/gd-cli/references/sop.md +25 -0
- package/skills/gd-cli/references/tools.md +29 -0
- package/skills/gd-cli/references/update.md +16 -0
- package/skills/gd-cli/references/workflows.md +22 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export { CREDENTIALS_FILE, DEFAULT_GD_DIR, GD_DIR, REGISTRY_CACHE_FILE, SETTINGS_FILE, hasCustomGdHome, resolveGdHome, } from "./gd-home.js";
|
|
2
|
+
export { resolveApiBase, resolveApiBaseInfo, resolveSsoBase, resolveAuthPageOrigin, resolveEndpoints, resolveActiveEnv, buildDeviceAuthPageUrls, AUTH_PAGE_PATH, } from "./endpoints.js";
|
|
3
|
+
export declare const PROD_API_BASE = "https://gdcli.gaoding.com/api";
|
|
4
|
+
/** @deprecated Use GD_DIR */
|
|
5
|
+
export declare const GDHUB_DIR: string;
|
|
6
|
+
/** Migrate credentials from the early internal storage directory when present. */
|
|
7
|
+
export declare function migrateCredentialsIfNeeded(): void;
|
|
8
|
+
export declare const CLI_VERSION = "1.0.0-alpha.5";
|
|
9
|
+
export declare const CLI_PACKAGE_NAME = "gaoding-cli";
|
|
10
|
+
export declare const CLI_USER_AGENT = "gd-cli/1.0.0-alpha.5";
|
|
11
|
+
export declare const GDHUB_CLI_CLIENT_ID = "gdhub-cli";
|
|
12
|
+
export declare const DEFAULT_SCOPE: readonly ["scene-executor", "run:scene-app", "use:tools", "export", "read:public"];
|
|
13
|
+
export declare const CACHE_TTL_MS: number;
|
|
14
|
+
export declare const WEB_ORIGIN = "https://gaoding.art";
|
|
15
|
+
export declare function isVerbose(): boolean;
|
|
16
|
+
export declare function isDebug(): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { ensureCredentialDir, ensureCredentialFile } from "./credential-permissions.js";
|
|
5
|
+
import { CREDENTIALS_FILE, GD_DIR, REGISTRY_CACHE_FILE, hasCustomGdHome, } from "./gd-home.js";
|
|
6
|
+
export { CREDENTIALS_FILE, DEFAULT_GD_DIR, GD_DIR, REGISTRY_CACHE_FILE, SETTINGS_FILE, hasCustomGdHome, resolveGdHome, } from "./gd-home.js";
|
|
7
|
+
export { resolveApiBase, resolveApiBaseInfo, resolveSsoBase, resolveAuthPageOrigin, resolveEndpoints, resolveActiveEnv, buildDeviceAuthPageUrls, AUTH_PAGE_PATH, } from "./endpoints.js";
|
|
8
|
+
export const PROD_API_BASE = "https://gdcli.gaoding.com/api";
|
|
9
|
+
/** @deprecated Use GD_DIR */
|
|
10
|
+
export const GDHUB_DIR = GD_DIR;
|
|
11
|
+
const LEGACY_DIR = path.join(os.homedir(), ".gdhub");
|
|
12
|
+
/** Migrate credentials from the early internal storage directory when present. */
|
|
13
|
+
export function migrateCredentialsIfNeeded() {
|
|
14
|
+
if (hasCustomGdHome())
|
|
15
|
+
return;
|
|
16
|
+
if (fs.existsSync(GD_DIR))
|
|
17
|
+
return;
|
|
18
|
+
if (!fs.existsSync(LEGACY_DIR))
|
|
19
|
+
return;
|
|
20
|
+
ensureCredentialDir(GD_DIR);
|
|
21
|
+
const legacyCreds = path.join(LEGACY_DIR, "credentials.json");
|
|
22
|
+
if (fs.existsSync(legacyCreds)) {
|
|
23
|
+
fs.copyFileSync(legacyCreds, CREDENTIALS_FILE);
|
|
24
|
+
ensureCredentialFile(CREDENTIALS_FILE);
|
|
25
|
+
}
|
|
26
|
+
const legacyCache = path.join(LEGACY_DIR, "registry-cache.json");
|
|
27
|
+
if (fs.existsSync(legacyCache)) {
|
|
28
|
+
fs.copyFileSync(legacyCache, REGISTRY_CACHE_FILE);
|
|
29
|
+
ensureCredentialFile(REGISTRY_CACHE_FILE);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function readEnv(key, legacyKey) {
|
|
33
|
+
return process.env[key] ?? process.env[legacyKey];
|
|
34
|
+
}
|
|
35
|
+
export const CLI_VERSION = "1.0.0-alpha.5";
|
|
36
|
+
export const CLI_PACKAGE_NAME = "gaoding-cli";
|
|
37
|
+
export const CLI_USER_AGENT = `gd-cli/${CLI_VERSION}`;
|
|
38
|
+
export const GDHUB_CLI_CLIENT_ID = "gdhub-cli";
|
|
39
|
+
export const DEFAULT_SCOPE = [
|
|
40
|
+
"scene-executor",
|
|
41
|
+
"run:scene-app",
|
|
42
|
+
"use:tools",
|
|
43
|
+
"export",
|
|
44
|
+
"read:public",
|
|
45
|
+
];
|
|
46
|
+
export const CACHE_TTL_MS = Number(readEnv("GD_CACHE_TTL", "GDHUB_CACHE_TTL") ?? 86400) * 1000;
|
|
47
|
+
export const WEB_ORIGIN = "https://gaoding.art";
|
|
48
|
+
export function isVerbose() {
|
|
49
|
+
return readEnv("GD_VERBOSE", "GDHUB_VERBOSE") === "1" || process.argv.includes("--verbose");
|
|
50
|
+
}
|
|
51
|
+
export function isDebug() {
|
|
52
|
+
const d = process.env.DEBUG ?? "";
|
|
53
|
+
return d.includes("gd") || d.includes("gdhub");
|
|
54
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
export function ensureCredentialDir(dir) {
|
|
3
|
+
if (!fs.existsSync(dir)) {
|
|
4
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
5
|
+
}
|
|
6
|
+
chmodIfPosix(dir, 0o700);
|
|
7
|
+
}
|
|
8
|
+
export function ensureCredentialFile(file) {
|
|
9
|
+
if (fs.existsSync(file)) {
|
|
10
|
+
chmodIfPosix(file, 0o600);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function chmodIfPosix(target, mode) {
|
|
14
|
+
if (process.platform === "win32")
|
|
15
|
+
return;
|
|
16
|
+
try {
|
|
17
|
+
fs.chmodSync(target, mode);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
/* Ignore filesystems that do not support POSIX modes. */
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface EcommerceInputGuidance {
|
|
2
|
+
required_fields: string[];
|
|
3
|
+
missing_required_fields: string[];
|
|
4
|
+
recommended_fields: string[];
|
|
5
|
+
missing_recommended_fields: string[];
|
|
6
|
+
assumed_defaults: string[];
|
|
7
|
+
clarification_required: boolean;
|
|
8
|
+
clarification_recommended: boolean;
|
|
9
|
+
questions: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function buildEcommerceInputGuidance(input: {
|
|
12
|
+
appId?: string;
|
|
13
|
+
brief?: unknown;
|
|
14
|
+
hasReferenceImage: boolean;
|
|
15
|
+
}): EcommerceInputGuidance;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export function buildEcommerceInputGuidance(input) {
|
|
2
|
+
const brief = typeof input.brief === "string" ? input.brief.trim() : "";
|
|
3
|
+
const missingRequired = [
|
|
4
|
+
...(input.hasReferenceImage ? [] : ["商品参考图"]),
|
|
5
|
+
...(brief ? [] : ["商品 brief"]),
|
|
6
|
+
];
|
|
7
|
+
const missingRecommended = recommendedMissingFields(brief);
|
|
8
|
+
return {
|
|
9
|
+
required_fields: ["商品参考图", "商品 brief"],
|
|
10
|
+
missing_required_fields: missingRequired,
|
|
11
|
+
recommended_fields: ["商品品类/名称", "核心卖点", "使用场景/目标人群", "目标平台或渠道", "必须出现的短文案"],
|
|
12
|
+
missing_recommended_fields: missingRecommended,
|
|
13
|
+
assumed_defaults: assumedDefaults(input.appId, missingRecommended),
|
|
14
|
+
clarification_required: missingRequired.length > 0,
|
|
15
|
+
clarification_recommended: missingRecommended.length > 0,
|
|
16
|
+
questions: buildQuestions(missingRequired, missingRecommended),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function recommendedMissingFields(brief) {
|
|
20
|
+
if (!brief)
|
|
21
|
+
return ["商品品类/名称", "核心卖点", "使用场景/目标人群", "目标平台或渠道", "必须出现的短文案"];
|
|
22
|
+
const missing = [];
|
|
23
|
+
if (!hasProductIdentity(brief))
|
|
24
|
+
missing.push("商品品类/名称");
|
|
25
|
+
if (!hasSellingPoint(brief))
|
|
26
|
+
missing.push("核心卖点");
|
|
27
|
+
if (!hasUsageContext(brief))
|
|
28
|
+
missing.push("使用场景/目标人群");
|
|
29
|
+
if (!hasPlatformContext(brief))
|
|
30
|
+
missing.push("目标平台或渠道");
|
|
31
|
+
if (!hasCopyRequirement(brief))
|
|
32
|
+
missing.push("必须出现的短文案");
|
|
33
|
+
return missing;
|
|
34
|
+
}
|
|
35
|
+
function assumedDefaults(appId, missing) {
|
|
36
|
+
const defaults = [];
|
|
37
|
+
if (missing.includes("核心卖点")) {
|
|
38
|
+
defaults.push("从商品品类推断 1-2 个常见购买利益点,画面用材质、结构、动作或场景证明。");
|
|
39
|
+
}
|
|
40
|
+
if (missing.includes("使用场景/目标人群")) {
|
|
41
|
+
defaults.push("按商品品类选择可信默认场景,例如桌面办公、通勤户外、梳妆台、厨房餐桌或居家空间。");
|
|
42
|
+
}
|
|
43
|
+
if (missing.includes("目标平台或渠道")) {
|
|
44
|
+
defaults.push(defaultPlatformForApp(appId));
|
|
45
|
+
}
|
|
46
|
+
if (missing.includes("必须出现的短文案")) {
|
|
47
|
+
defaults.push("自动从标题和首个卖点生成短文案;用户明确 no-text / layout-copy 时只输出后期排版文案。");
|
|
48
|
+
}
|
|
49
|
+
return defaults;
|
|
50
|
+
}
|
|
51
|
+
function defaultPlatformForApp(appId) {
|
|
52
|
+
if (appId === "social-seeding-pack")
|
|
53
|
+
return "默认按小红书封面和正文配图组织。";
|
|
54
|
+
if (appId === "campaign-kv-pack")
|
|
55
|
+
return "默认按官网横版、社媒方图和电商竖图组织。";
|
|
56
|
+
if (appId === "pdp-a-plus")
|
|
57
|
+
return "默认按详情页/A+模块组织购买说服顺序。";
|
|
58
|
+
return "默认按电商 Listing 图库组织主图、卖点图、细节图和生活方式图。";
|
|
59
|
+
}
|
|
60
|
+
function buildQuestions(required, recommended) {
|
|
61
|
+
if (required.length > 0) {
|
|
62
|
+
return required.map((field) => `请补充${field}。`);
|
|
63
|
+
}
|
|
64
|
+
return recommended.slice(0, 3).map((field) => `如需更准结果,可补充${field};未补充时将按品类默认生成。`);
|
|
65
|
+
}
|
|
66
|
+
function hasProductIdentity(brief) {
|
|
67
|
+
return /[\u4e00-\u9fa5A-Za-z0-9]{2,}(?:衣|鞋|包|灯|耳机|茶|饮|精华|面霜|收纳|桌|椅|机|器|瓶|杯|盒|套装|夹克|台灯|背包|跑鞋)/i
|
|
68
|
+
.test(brief);
|
|
69
|
+
}
|
|
70
|
+
function hasSellingPoint(brief) {
|
|
71
|
+
return /轻薄|透气|防晒|缓震|柔和|护眼|折叠|节省|收纳|清爽|低糖|复古|静音|可更换|防泼水|大容量|高辨识|材质|结构|卖点|利益点|核心/i
|
|
72
|
+
.test(brief);
|
|
73
|
+
}
|
|
74
|
+
function hasUsageContext(brief) {
|
|
75
|
+
return /适合|面向|人群|通勤|户外|办公|学习|阅读|桌面|居家|卧室|厨房|露营|旅行|学生|白领|小红书|场景|使用/i
|
|
76
|
+
.test(brief);
|
|
77
|
+
}
|
|
78
|
+
function hasPlatformContext(brief) {
|
|
79
|
+
return /淘宝|天猫|京东|亚马逊|Amazon|Shopify|小红书|抖音|官网|社媒|电商|Listing|详情页|A\+|PDP|Campaign|KV|投放|渠道/i
|
|
80
|
+
.test(brief);
|
|
81
|
+
}
|
|
82
|
+
function hasCopyRequirement(brief) {
|
|
83
|
+
return /标题|文案|短文案|字幕|带字|文字|无字|无文字|no[-\s]?text|render[-\s]?text|layout[-\s]?copy/i
|
|
84
|
+
.test(brief);
|
|
85
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type GdEnvName, type GdSettings } from "./settings-store.js";
|
|
2
|
+
export type { GdEnvName };
|
|
3
|
+
export declare const AUTH_PAGE_PATH = "/cli/device-authorization";
|
|
4
|
+
export interface EnvPreset {
|
|
5
|
+
hub_api_base: string;
|
|
6
|
+
/** SSO API root, for example https://gaoding.com/api/sso. */
|
|
7
|
+
sso_api_base: string;
|
|
8
|
+
/** Authorization page origin. It may differ from the SSO API host. */
|
|
9
|
+
auth_page_origin: string;
|
|
10
|
+
/** Web Origin / Referer used by business APIs. */
|
|
11
|
+
web_origin: string;
|
|
12
|
+
/** Default business channel id. */
|
|
13
|
+
channel_id: string;
|
|
14
|
+
/** Default business id. */
|
|
15
|
+
business_id: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ResolvedEndpoint {
|
|
18
|
+
value: string;
|
|
19
|
+
source: string;
|
|
20
|
+
}
|
|
21
|
+
export interface ResolvedEndpoints {
|
|
22
|
+
active_env: GdEnvName;
|
|
23
|
+
hub_api_base: ResolvedEndpoint;
|
|
24
|
+
sso_api_base: ResolvedEndpoint;
|
|
25
|
+
auth_page_origin: ResolvedEndpoint;
|
|
26
|
+
web_origin: ResolvedEndpoint;
|
|
27
|
+
channel_id: ResolvedEndpoint;
|
|
28
|
+
business_id: ResolvedEndpoint;
|
|
29
|
+
}
|
|
30
|
+
export declare function parseEnvName(name?: string): GdEnvName | null;
|
|
31
|
+
export declare function resolveActiveEnv(): GdEnvName;
|
|
32
|
+
export declare function resolveEndpoints(): ResolvedEndpoints;
|
|
33
|
+
export declare function resolveApiBase(): string;
|
|
34
|
+
export declare function resolveApiBaseInfo(): {
|
|
35
|
+
url: string;
|
|
36
|
+
source: string;
|
|
37
|
+
};
|
|
38
|
+
export declare function resolveSsoBase(): string;
|
|
39
|
+
export declare function resolveAuthPageOrigin(): string;
|
|
40
|
+
export declare function resolveWebOrigin(): string;
|
|
41
|
+
/** 由 authorize_code 生成本地约定的授权页链接(不依赖 SSO 返回的 verification_uri host) */
|
|
42
|
+
export declare function buildDeviceAuthPageUrls(authorizeCode: string): {
|
|
43
|
+
verification_uri: string;
|
|
44
|
+
verification_uri_complete: string;
|
|
45
|
+
};
|
|
46
|
+
export declare function getEnvPreset(name: GdEnvName): EnvPreset;
|
|
47
|
+
export declare function listEnvNames(): GdEnvName[];
|
|
48
|
+
export declare function applyEnvUse(env: GdEnvName, opts?: {
|
|
49
|
+
auth_page_origin?: string;
|
|
50
|
+
}): GdSettings;
|
|
51
|
+
export declare function setEnvOverride(key: keyof NonNullable<GdSettings["overrides"]>, value: string): GdSettings;
|
|
52
|
+
export declare function clearEnvOverrides(keys?: Array<keyof NonNullable<GdSettings["overrides"]>>): GdSettings;
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import { readSettings } from "./settings-store.js";
|
|
2
|
+
export const AUTH_PAGE_PATH = "/cli/device-authorization";
|
|
3
|
+
const PRODUCTION_PRESET = {
|
|
4
|
+
hub_api_base: "https://gdcli.gaoding.com/api",
|
|
5
|
+
sso_api_base: "https://www.gaoding.com/api/sso",
|
|
6
|
+
auth_page_origin: "https://www.gaoding.com",
|
|
7
|
+
web_origin: "https://gdcli.gaoding.com",
|
|
8
|
+
channel_id: "32",
|
|
9
|
+
business_id: "13",
|
|
10
|
+
};
|
|
11
|
+
const VALID_ENVS = new Set(["prod", "fat", "stage", "local"]);
|
|
12
|
+
function readEnv(key, legacyKey) {
|
|
13
|
+
const v = process.env[key];
|
|
14
|
+
if (v)
|
|
15
|
+
return v;
|
|
16
|
+
const gaodingKey = key.replace(/^GD_/, "GAODING_");
|
|
17
|
+
const gaodingValue = process.env[gaodingKey];
|
|
18
|
+
if (gaodingValue)
|
|
19
|
+
return gaodingValue;
|
|
20
|
+
if (legacyKey)
|
|
21
|
+
return process.env[legacyKey];
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
function normalizeBase(url) {
|
|
25
|
+
return url.replace(/\/$/, "");
|
|
26
|
+
}
|
|
27
|
+
function normalizeOrigin(url) {
|
|
28
|
+
const u = normalizeBase(url.trim());
|
|
29
|
+
try {
|
|
30
|
+
const parsed = new URL(u);
|
|
31
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return u;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function parseEnvName(name) {
|
|
38
|
+
const n = name?.toLowerCase()?.trim();
|
|
39
|
+
if (!n)
|
|
40
|
+
return null;
|
|
41
|
+
if (n === "production" || n === "remote")
|
|
42
|
+
return "prod";
|
|
43
|
+
if (n === "dev")
|
|
44
|
+
return "local";
|
|
45
|
+
if (VALID_ENVS.has(n))
|
|
46
|
+
return n;
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
export function resolveActiveEnv() {
|
|
50
|
+
const fromEnv = parseEnvName(readEnv("GD_ENV", "GDHUB_ENV"));
|
|
51
|
+
if (fromEnv)
|
|
52
|
+
return fromEnv;
|
|
53
|
+
const s = readSettings();
|
|
54
|
+
if (s.active_env && VALID_ENVS.has(s.active_env)) {
|
|
55
|
+
return s.active_env;
|
|
56
|
+
}
|
|
57
|
+
if (readEnv("GD_LOCAL_SERVER", "GDHUB_LOCAL_SERVER") === "1" ||
|
|
58
|
+
readEnv("GD_LOCAL_SERVER", "GDHUB_LOCAL_SERVER") === "true" ||
|
|
59
|
+
s.use_local_server === true) {
|
|
60
|
+
return "local";
|
|
61
|
+
}
|
|
62
|
+
return "prod";
|
|
63
|
+
}
|
|
64
|
+
function presetFor(env) {
|
|
65
|
+
if (env === "prod")
|
|
66
|
+
return { ...PRODUCTION_PRESET };
|
|
67
|
+
return {
|
|
68
|
+
...PRODUCTION_PRESET,
|
|
69
|
+
hub_api_base: "",
|
|
70
|
+
sso_api_base: "",
|
|
71
|
+
auth_page_origin: "",
|
|
72
|
+
web_origin: "",
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
export function resolveEndpoints() {
|
|
76
|
+
const active_env = resolveActiveEnv();
|
|
77
|
+
const preset = presetFor(active_env);
|
|
78
|
+
const settings = readSettings();
|
|
79
|
+
const overrides = settings.overrides ?? {};
|
|
80
|
+
return {
|
|
81
|
+
active_env,
|
|
82
|
+
hub_api_base: resolveHubEndpoint(active_env, preset, settings, overrides),
|
|
83
|
+
sso_api_base: resolveSimpleEndpoint({
|
|
84
|
+
key: "sso_api_base",
|
|
85
|
+
presetValue: preset.sso_api_base,
|
|
86
|
+
envKeys: ["GD_SSO_BASE", "GDHUB_SSO_BASE"],
|
|
87
|
+
settingsOverride: overrides.sso_api_base,
|
|
88
|
+
active_env,
|
|
89
|
+
}),
|
|
90
|
+
auth_page_origin: resolveSimpleEndpoint({
|
|
91
|
+
key: "auth_page_origin",
|
|
92
|
+
presetValue: preset.auth_page_origin,
|
|
93
|
+
envKeys: ["GD_AUTH_PAGE_ORIGIN", "GDHUB_AUTH_PAGE_ORIGIN"],
|
|
94
|
+
settingsOverride: overrides.auth_page_origin,
|
|
95
|
+
active_env,
|
|
96
|
+
normalizeAsOrigin: true,
|
|
97
|
+
}),
|
|
98
|
+
web_origin: resolveSimpleEndpoint({
|
|
99
|
+
key: "web_origin",
|
|
100
|
+
presetValue: preset.web_origin,
|
|
101
|
+
envKeys: ["GD_WEB_ORIGIN", "GD_ORIGIN"],
|
|
102
|
+
settingsOverride: overrides.web_origin,
|
|
103
|
+
active_env,
|
|
104
|
+
normalizeAsOrigin: true,
|
|
105
|
+
}),
|
|
106
|
+
channel_id: resolveSimpleEndpoint({
|
|
107
|
+
key: "channel_id",
|
|
108
|
+
presetValue: preset.channel_id,
|
|
109
|
+
envKeys: ["GD_CHANNEL_ID"],
|
|
110
|
+
settingsOverride: overrides.channel_id,
|
|
111
|
+
active_env,
|
|
112
|
+
}),
|
|
113
|
+
business_id: resolveSimpleEndpoint({
|
|
114
|
+
key: "business_id",
|
|
115
|
+
presetValue: preset.business_id,
|
|
116
|
+
envKeys: ["GD_BUSINESS_ID"],
|
|
117
|
+
settingsOverride: overrides.business_id,
|
|
118
|
+
active_env,
|
|
119
|
+
}),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function resolveHubEndpoint(active_env, preset, settings, overrides) {
|
|
123
|
+
const apiBase = readEnv("GD_API_BASE", "GDHUB_API_BASE");
|
|
124
|
+
if (apiBase?.trim()) {
|
|
125
|
+
return { value: normalizeBase(apiBase), source: "环境变量 GD_API_BASE" };
|
|
126
|
+
}
|
|
127
|
+
if (overrides.hub_api_base?.trim()) {
|
|
128
|
+
return {
|
|
129
|
+
value: normalizeBase(overrides.hub_api_base),
|
|
130
|
+
source: "settings.json overrides.hub_api_base",
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (settings.api_base?.trim()) {
|
|
134
|
+
return {
|
|
135
|
+
value: normalizeBase(settings.api_base),
|
|
136
|
+
source: "settings.json api_base(兼容)",
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (!preset.hub_api_base.trim()) {
|
|
140
|
+
throw missingEndpointError(active_env, "hub_api_base", [
|
|
141
|
+
"GD_API_BASE",
|
|
142
|
+
"GAODING_API_BASE",
|
|
143
|
+
]);
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
value: normalizeBase(preset.hub_api_base),
|
|
147
|
+
source: `预设 ${active_env}.hub_api_base`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function resolveSimpleEndpoint(opts) {
|
|
151
|
+
for (const k of opts.envKeys) {
|
|
152
|
+
if (!k)
|
|
153
|
+
continue;
|
|
154
|
+
const v = readEnv(k);
|
|
155
|
+
if (v?.trim()) {
|
|
156
|
+
const val = opts.normalizeAsOrigin ? normalizeOrigin(v) : normalizeBase(v);
|
|
157
|
+
return { value: val, source: `环境变量 ${k}` };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
if (opts.settingsOverride?.trim()) {
|
|
161
|
+
const val = opts.normalizeAsOrigin
|
|
162
|
+
? normalizeOrigin(opts.settingsOverride)
|
|
163
|
+
: normalizeBase(opts.settingsOverride);
|
|
164
|
+
return {
|
|
165
|
+
value: val,
|
|
166
|
+
source: `settings.json overrides.${opts.key}`,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
if (!opts.presetValue.trim()) {
|
|
170
|
+
throw missingEndpointError(opts.active_env, opts.key, opts.envKeys);
|
|
171
|
+
}
|
|
172
|
+
const val = opts.normalizeAsOrigin
|
|
173
|
+
? normalizeOrigin(opts.presetValue)
|
|
174
|
+
: normalizeBase(opts.presetValue);
|
|
175
|
+
return {
|
|
176
|
+
value: val,
|
|
177
|
+
source: `预设 ${opts.active_env}.${opts.key}`,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function missingEndpointError(env, key, envKeys) {
|
|
181
|
+
const readableKeys = envKeys
|
|
182
|
+
.filter(Boolean)
|
|
183
|
+
.map((item) => item.replace(/^GAODING_/, "GD_"))
|
|
184
|
+
.filter((item, index, arr) => arr.indexOf(item) === index)
|
|
185
|
+
.join(" / ");
|
|
186
|
+
return new Error(`缺少 ${env}.${key} 端点配置。请使用环境变量 ${readableKeys} 显式配置。`);
|
|
187
|
+
}
|
|
188
|
+
export function resolveApiBase() {
|
|
189
|
+
return resolveEndpoints().hub_api_base.value;
|
|
190
|
+
}
|
|
191
|
+
export function resolveApiBaseInfo() {
|
|
192
|
+
const e = resolveEndpoints().hub_api_base;
|
|
193
|
+
return { url: e.value, source: e.source };
|
|
194
|
+
}
|
|
195
|
+
export function resolveSsoBase() {
|
|
196
|
+
return resolveEndpoints().sso_api_base.value;
|
|
197
|
+
}
|
|
198
|
+
export function resolveAuthPageOrigin() {
|
|
199
|
+
return resolveEndpoints().auth_page_origin.value;
|
|
200
|
+
}
|
|
201
|
+
export function resolveWebOrigin() {
|
|
202
|
+
return resolveEndpoints().web_origin.value;
|
|
203
|
+
}
|
|
204
|
+
/** 由 authorize_code 生成本地约定的授权页链接(不依赖 SSO 返回的 verification_uri host) */
|
|
205
|
+
export function buildDeviceAuthPageUrls(authorizeCode) {
|
|
206
|
+
const origin = normalizeOrigin(resolveAuthPageOrigin());
|
|
207
|
+
const verification_uri = `${origin}${AUTH_PAGE_PATH}`;
|
|
208
|
+
const verification_uri_complete = `${origin}${AUTH_PAGE_PATH}?code=${encodeURIComponent(authorizeCode)}`;
|
|
209
|
+
return { verification_uri, verification_uri_complete };
|
|
210
|
+
}
|
|
211
|
+
export function getEnvPreset(name) {
|
|
212
|
+
return presetFor(name);
|
|
213
|
+
}
|
|
214
|
+
export function listEnvNames() {
|
|
215
|
+
return ["prod", "fat", "stage", "local"];
|
|
216
|
+
}
|
|
217
|
+
export function applyEnvUse(env, opts) {
|
|
218
|
+
const cur = readSettings();
|
|
219
|
+
const overrides = {
|
|
220
|
+
...cur.overrides,
|
|
221
|
+
};
|
|
222
|
+
if (opts?.auth_page_origin) {
|
|
223
|
+
overrides.auth_page_origin = normalizeOrigin(opts.auth_page_origin);
|
|
224
|
+
}
|
|
225
|
+
else if (env !== cur.active_env) {
|
|
226
|
+
delete overrides.auth_page_origin;
|
|
227
|
+
}
|
|
228
|
+
const next = {
|
|
229
|
+
...cur,
|
|
230
|
+
active_env: env,
|
|
231
|
+
overrides: Object.keys(overrides).length ? overrides : undefined,
|
|
232
|
+
};
|
|
233
|
+
delete next.use_local_server;
|
|
234
|
+
delete next.api_base;
|
|
235
|
+
return next;
|
|
236
|
+
}
|
|
237
|
+
export function setEnvOverride(key, value) {
|
|
238
|
+
const cur = readSettings();
|
|
239
|
+
const overrides = { ...cur.overrides, [key]: normalizeBase(value.trim()) };
|
|
240
|
+
if (key === "auth_page_origin" || key === "web_origin") {
|
|
241
|
+
overrides[key] = normalizeOrigin(value);
|
|
242
|
+
}
|
|
243
|
+
return { ...cur, overrides };
|
|
244
|
+
}
|
|
245
|
+
export function clearEnvOverrides(keys) {
|
|
246
|
+
const cur = readSettings();
|
|
247
|
+
if (!keys?.length) {
|
|
248
|
+
const { overrides: _o, ...rest } = cur;
|
|
249
|
+
return rest;
|
|
250
|
+
}
|
|
251
|
+
const overrides = { ...cur.overrides };
|
|
252
|
+
for (const k of keys)
|
|
253
|
+
delete overrides[k];
|
|
254
|
+
return {
|
|
255
|
+
...cur,
|
|
256
|
+
overrides: Object.keys(overrides).length ? overrides : undefined,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Upload parameter normalization hook.
|
|
3
|
+
* The current runtime accepts local file paths directly and uploads them when needed,
|
|
4
|
+
* so this hook intentionally leaves the input unchanged.
|
|
5
|
+
*/
|
|
6
|
+
export declare function enrichUploadParamsIfNeeded(toolName: string, opts: Record<string, unknown>, maxBytes?: number): Record<string, unknown>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const DEFAULT_MAX = 25 * 1024 * 1024;
|
|
2
|
+
/**
|
|
3
|
+
* Upload parameter normalization hook.
|
|
4
|
+
* The current runtime accepts local file paths directly and uploads them when needed,
|
|
5
|
+
* so this hook intentionally leaves the input unchanged.
|
|
6
|
+
*/
|
|
7
|
+
export function enrichUploadParamsIfNeeded(toolName, opts, maxBytes = DEFAULT_MAX) {
|
|
8
|
+
void toolName;
|
|
9
|
+
void maxBytes;
|
|
10
|
+
return opts;
|
|
11
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CliErrorBody } from "../core/output/envelope.js";
|
|
2
|
+
export declare const ENTITLEMENT_PRICING_URL = "https://www.gaoding.com/pricing";
|
|
3
|
+
export interface EntitlementIssue {
|
|
4
|
+
code: "ENTITLEMENT_INSUFFICIENT";
|
|
5
|
+
message: string;
|
|
6
|
+
hint: string;
|
|
7
|
+
pricing_url: string;
|
|
8
|
+
diagnostic_context?: Record<string, unknown>;
|
|
9
|
+
}
|
|
10
|
+
export declare function detectEntitlementIssue(input: {
|
|
11
|
+
code?: string;
|
|
12
|
+
errorName?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
detail?: unknown;
|
|
15
|
+
}): EntitlementIssue | undefined;
|
|
16
|
+
export declare function resolveEntitlementPricingUrl(): string;
|
|
17
|
+
export declare function entitlementCliError(issue: EntitlementIssue, detail?: unknown): CliErrorBody;
|