@gaoding/cli 1.1.0 → 1.2.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.
Files changed (38) hide show
  1. package/dist/bin/gd-cli.js +2 -1
  2. package/dist/bin/insmind-cli.js +60 -0
  3. package/dist/bin/postinstall.js +1 -1
  4. package/dist/src/bootstrap/create-cli.js +14 -4
  5. package/dist/src/bootstrap/create-runtime.js +88 -30
  6. package/dist/src/bootstrap/validators.js +9 -5
  7. package/dist/src/cli/agent-commands.js +5 -4
  8. package/dist/src/cli/auth-commands.js +13 -10
  9. package/dist/src/cli/credits-command.js +23 -0
  10. package/dist/src/cli/dam-commands.js +70 -69
  11. package/dist/src/cli/editor-commands.js +12 -11
  12. package/dist/src/cli/errors.js +49 -9
  13. package/dist/src/cli/model-commands.js +6 -5
  14. package/dist/src/cli/presenter.js +24 -6
  15. package/dist/src/cli/tool-commands.js +7 -6
  16. package/dist/src/cli/update-command.js +4 -3
  17. package/dist/src/features/auth/credential-store.js +1 -1
  18. package/dist/src/features/auth/sso-service.js +3 -1
  19. package/dist/src/features/auth/use-cases.js +38 -12
  20. package/dist/src/features/credits/use-cases.js +52 -0
  21. package/dist/src/features/dam/storage-upload.js +1 -1
  22. package/dist/src/features/editor/bridge-process.js +11 -4
  23. package/dist/src/features/editor/session-state.js +1 -1
  24. package/dist/src/features/editor/session.js +14 -8
  25. package/dist/src/features/org/use-cases.js +7 -0
  26. package/dist/src/features/skill/bundled-skills.js +13 -5
  27. package/dist/src/features/tool/catalog.js +13 -13
  28. package/dist/src/features/tool/use-cases.js +3 -3
  29. package/dist/src/features/update/latest-version.js +2 -2
  30. package/dist/src/features/update/update-notification.js +10 -3
  31. package/dist/src/features/update/update-service.js +57 -23
  32. package/dist/src/platform/signed-http-transport.js +1 -0
  33. package/dist/src/product/billing.js +45 -0
  34. package/dist/src/product/config.js +83 -0
  35. package/dist/src/product/locale.js +38 -0
  36. package/dist/src/product/text.js +3 -0
  37. package/dist/src/telemetry/sls-sink.js +1 -2
  38. package/package.json +5 -5
@@ -22,6 +22,8 @@ export function detectInstallSource(input) {
22
22
  const cwd = normalizePath(resolve(input.cwd));
23
23
  const userAgent = input.env.npm_config_user_agent ?? "";
24
24
  const npmExecPath = normalizePath(input.env.npm_execpath ?? "");
25
+ const packageName = input.packageName ?? "@gaoding/cli";
26
+ const encodedPackage = packageName.replace("/", "+").replace("@", "@");
25
27
  if (userAgent.startsWith("yarn/") || npmExecPath.includes("/yarn/")) {
26
28
  return unsupported("Yarn 安装不支持自动更新");
27
29
  }
@@ -35,16 +37,15 @@ export function detectInstallSource(input) {
35
37
  if (!isWithin(realBinaryPath, packageRoot)) {
36
38
  return unsupported("CLI binary 与 package 不匹配");
37
39
  }
38
- if (/\/global\/[^/]+\/\.pnpm\/@gaoding\+cli@[^/]+\/node_modules\/@gaoding\/cli$/u
39
- .test(packageRoot)
40
- || /\/v\d+\/[0-9a-f]+-[0-9a-f]+-[0-9a-f]{16}\/node_modules\/@gaoding\/cli$/u
41
- .test(packageRoot)
42
- || /\/v\d+\/[0-9a-f]+-[0-9a-f]+-[0-9a-f]{16}\/node_modules\/@gaoding\/cli\/dist\/bin\/gd-cli\.js$/u
43
- .test(binaryPath)) {
40
+ if (packageRoot.includes(`/global/`) && packageRoot.includes(`/.pnpm/${encodedPackage}@`)
41
+ || packageRoot.includes(`/node_modules/${packageName}`)
42
+ && /\/v\d+\/[0-9a-f]+-[0-9a-f]+-[0-9a-f]{16}\//u.test(packageRoot)
43
+ || binaryPath.includes(`/node_modules/${packageName}/dist/bin/${input.binaryName ?? "gd-cli"}.js`)
44
+ && /\/v\d+\/[0-9a-f]+-[0-9a-f]+-[0-9a-f]{16}\//u.test(binaryPath)) {
44
45
  return { kind: "global", manager: "pnpm", packageRoot: input.packageRoot };
45
46
  }
46
- if (packageRoot.endsWith("/lib/node_modules/@gaoding/cli")
47
- || packageRoot.endsWith("/npm/node_modules/@gaoding/cli")) {
47
+ if (packageRoot.endsWith(`/lib/node_modules/${packageName}`)
48
+ || packageRoot.endsWith(`/npm/node_modules/${packageName}`)) {
48
49
  return { kind: "global", manager: "npm", packageRoot: input.packageRoot };
49
50
  }
50
51
  return unsupported("无法确认 npm 或 pnpm 全局安装");
@@ -55,27 +56,46 @@ export function createUpdateService(options) {
55
56
  const syncSkills = options.syncSkills ?? syncBundledSkills;
56
57
  const verifySkills = options.verifySkills ?? verifyBundledSkills;
57
58
  const env = options.env ?? process.env;
59
+ const packageName = options.packageName ?? "@gaoding/cli";
60
+ const commandName = options.commandName ?? "gd-cli";
61
+ const insmind = packageName === "@insmind/cli";
58
62
  return {
59
63
  async run(signal) {
60
64
  signal.throwIfAborted();
61
65
  const owner = options.installationOwner
62
66
  ?? readInstallationOwner(options.packageRoot);
63
67
  if (owner === "workbuddy") {
64
- throw new UpdateError("UPDATE_FAILED", "此 gd-cli 由 WorkBuddy 连接器管理。", ["请在 WorkBuddy 中更新「稿定」连接器。"]);
68
+ throw new UpdateError("UPDATE_FAILED", insmind
69
+ ? "This insMind CLI installation is managed by WorkBuddy."
70
+ : "此 gd-cli 由 WorkBuddy 连接器管理。", [insmind
71
+ ? "Update the insMind connector in WorkBuddy."
72
+ : "请在 WorkBuddy 中更新「稿定」连接器。"]);
65
73
  }
66
74
  if (owner === "invalid") {
67
- throw new UpdateError("UPDATE_FAILED", "无法确认当前安装的托管信息。", ["请通过原安装渠道重新安装 gd-cli。"]);
75
+ throw new UpdateError("UPDATE_FAILED", insmind
76
+ ? "The current installation ownership metadata is invalid."
77
+ : "无法确认当前安装的托管信息。", [insmind
78
+ ? "Reinstall insmind-cli through its original installation channel."
79
+ : "请通过原安装渠道重新安装 gd-cli。"]);
68
80
  }
69
81
  const latest = await options.telemetry.stage("registry", async () => {
70
82
  try {
71
- const result = await fetchLatestVersion({ fetch: fetchPackage, signal });
83
+ const result = await fetchLatestVersion({
84
+ fetch: fetchPackage,
85
+ signal,
86
+ ...(options.registryUrl ? { registryUrl: options.registryUrl } : {})
87
+ });
72
88
  if (result.status !== "modified")
73
89
  throw new Error("Registry response not modified");
74
90
  return result.version;
75
91
  }
76
92
  catch (error) {
77
93
  rethrowAbort(signal);
78
- throw new UpdateError("UPDATE_FAILED", "无法获取 @gaoding/cli 最新版本。", ["请稍后重新执行 gd-cli update。"]);
94
+ throw new UpdateError("UPDATE_FAILED", options.commandName === undefined
95
+ ? "无法获取 @gaoding/cli 最新版本。"
96
+ : `Unable to get the latest ${packageName} version.`, [options.commandName === undefined
97
+ ? "请稍后重新执行 gd-cli update。"
98
+ : `Run ${commandName} update again later.`]);
79
99
  }
80
100
  });
81
101
  signal.throwIfAborted();
@@ -90,7 +110,11 @@ export function createUpdateService(options) {
90
110
  }
91
111
  catch (error) {
92
112
  rethrowAbort(signal);
93
- throw new UpdateError("UPDATE_FAILED", `gd-cli ${options.currentVersion} 无需更新,但 Agent Skill 同步失败。`, ["请解决冲突后重新执行 gd-cli update。"]);
113
+ throw new UpdateError("UPDATE_FAILED", insmind
114
+ ? `${commandName} ${options.currentVersion} is current, but Agent Skill synchronization failed.`
115
+ : `gd-cli ${options.currentVersion} 无需更新,但 Agent Skill 同步失败。`, [insmind
116
+ ? `Resolve the conflict and run ${commandName} update again.`
117
+ : "请解决冲突后重新执行 gd-cli update。"]);
94
118
  }
95
119
  });
96
120
  return { version: options.currentVersion, updated: false };
@@ -101,23 +125,29 @@ export function createUpdateService(options) {
101
125
  realBinaryPath: safeRealpath(binaryPath),
102
126
  packageRoot: options.packageRoot,
103
127
  cwd: options.cwd ?? process.cwd(),
104
- env
128
+ env,
129
+ packageName,
130
+ binaryName: commandName
105
131
  });
106
- const nextSteps = manualCommands(latest);
132
+ const nextSteps = manualCommands(latest, packageName);
107
133
  if (source.kind === "unsupported") {
108
- throw new UpdateError("UPDATE_FAILED", `当前安装方式不支持自动更新:${source.reason}。`, nextSteps);
134
+ throw new UpdateError("UPDATE_FAILED", insmind
135
+ ? "The current installation method does not support automatic updates."
136
+ : `当前安装方式不支持自动更新:${source.reason}。`, nextSteps);
109
137
  }
110
138
  const command = source.manager;
111
139
  const args = source.manager === "npm"
112
- ? ["install", "--global", "--allow-scripts=@gaoding/cli", `@gaoding/cli@${latest}`]
113
- : ["add", "--global", "--allow-build=@gaoding/cli", `@gaoding/cli@${latest}`];
140
+ ? ["install", "--global", `--allow-scripts=${packageName}`, `${packageName}@${latest}`]
141
+ : ["add", "--global", `--allow-build=${packageName}`, `${packageName}@${latest}`];
114
142
  await options.telemetry.stage("install", async () => {
115
143
  try {
116
144
  await runProcess(command, args, signal);
117
145
  }
118
146
  catch (error) {
119
147
  rethrowAbort(signal);
120
- throw new UpdateError("UPDATE_FAILED", `gd-cli 更新到 ${latest} 失败。`, nextSteps);
148
+ throw new UpdateError("UPDATE_FAILED", insmind
149
+ ? `Failed to update ${commandName} to ${latest}.`
150
+ : `gd-cli 更新到 ${latest} 失败。`, nextSteps);
121
151
  }
122
152
  });
123
153
  signal.throwIfAborted();
@@ -131,7 +161,11 @@ export function createUpdateService(options) {
131
161
  }
132
162
  catch (error) {
133
163
  rethrowAbort(signal);
134
- throw new UpdateError("UPDATE_PARTIAL", `gd-cli 已更新到 ${latest},但 Agent Skill 验收失败。`, ["请重新执行 gd-cli update。"]);
164
+ throw new UpdateError("UPDATE_PARTIAL", insmind
165
+ ? `${commandName} was updated to ${latest}, but Agent Skill verification failed.`
166
+ : `gd-cli 已更新到 ${latest},但 Agent Skill 验收失败。`, [insmind
167
+ ? `Run ${commandName} update again.`
168
+ : "请重新执行 gd-cli update。"]);
135
169
  }
136
170
  });
137
171
  return { version: latest, updated: true };
@@ -158,10 +192,10 @@ function spawnProcess(command, args, signal) {
158
192
  });
159
193
  });
160
194
  }
161
- function manualCommands(version) {
195
+ function manualCommands(version, packageName = "@gaoding/cli") {
162
196
  return [
163
- `npm install --global --allow-scripts=@gaoding/cli @gaoding/cli@${version}`,
164
- `pnpm add --global --allow-build=@gaoding/cli @gaoding/cli@${version}`
197
+ `npm install --global --allow-scripts=${packageName} ${packageName}@${version}`,
198
+ `pnpm add --global --allow-build=${packageName} ${packageName}@${version}`
165
199
  ];
166
200
  }
167
201
  function containsTemporaryRunner(path) {
@@ -51,6 +51,7 @@ export function createSignedHttpTransport(options) {
51
51
  url.search = query;
52
52
  const timestamp = Math.floor(options.now().getTime() / 1000);
53
53
  const headers = {
54
+ ...options.businessHeaders,
54
55
  Accept: accept,
55
56
  "X-AccessKey": request.credential.accessKey,
56
57
  "X-Signature": signRequest({
@@ -0,0 +1,45 @@
1
+ export function withAgentBillingUnit(source, unit) {
2
+ if (unit === "gaodou")
3
+ return source;
4
+ return {
5
+ async send(input) {
6
+ const output = await source.send(input);
7
+ return {
8
+ ...output,
9
+ usage: {
10
+ ...output.usage,
11
+ cost: { ...output.usage.cost, unit },
12
+ items: output.usage.items.map((item) => ({
13
+ ...item,
14
+ cost: { ...item.cost, unit }
15
+ }))
16
+ }
17
+ };
18
+ }
19
+ };
20
+ }
21
+ export function withToolBillingUnit(source, unit) {
22
+ if (unit === "gaodou")
23
+ return source;
24
+ const model = (value) => (value.cost ? { ...value, cost: { ...value.cost, unit } } : value);
25
+ return {
26
+ listTools: (input) => source.listTools(input),
27
+ async listModels(input) {
28
+ const output = await source.listModels(input);
29
+ return { ...output, models: output.models.map(model) };
30
+ },
31
+ async getModel(input) {
32
+ return model(await source.getModel(input));
33
+ },
34
+ getArgumentsSchema: (input) => source.getArgumentsSchema(input),
35
+ async call(input) {
36
+ const output = await source.call(input);
37
+ return {
38
+ ...output,
39
+ usage: output.usage.cost
40
+ ? { ...output.usage, cost: { ...output.usage.cost, unit } }
41
+ : output.usage
42
+ };
43
+ }
44
+ };
45
+ }
@@ -0,0 +1,83 @@
1
+ import { defaultToolDefinitions } from "../features/tool/catalog.js";
2
+ function freezeProduct(config) {
3
+ Object.freeze(config.endpoints);
4
+ for (const tool of config.tools)
5
+ Object.freeze(tool);
6
+ Object.freeze(config.tools);
7
+ return Object.freeze(config);
8
+ }
9
+ const gaodingApi = new URL("https://gdcli.gaoding.com/api");
10
+ export const gaodingProduct = freezeProduct({
11
+ id: "gaoding",
12
+ displayName: "GaoDing",
13
+ commandName: "gd-cli",
14
+ description: "稿定命令行工具",
15
+ npmPackage: "@gaoding/cli",
16
+ skillName: "gd-cli",
17
+ stateDirectory: ".gd",
18
+ billingUnit: "gaodou",
19
+ deviceClientId: "gdhub-cli",
20
+ pricingUrl: new URL("https://www.gaoding.art/pricing"),
21
+ telemetryUrl: new URL("https://gaoding-log-ai-gpu.cn-hangzhou.log.aliyuncs.com/logstores/gd-cli/track?APIVersion=0.6.0"),
22
+ defaultEditorCreateUrl: new URL("https://www.gaoding.art/editor/canvas?mode=create&type=board"),
23
+ editorWorkUrl: new URL("https://www.gaoding.art/editor/canvas"),
24
+ restrictEditorTargets: false,
25
+ endpoints: {
26
+ orgApi: gaodingApi,
27
+ creditsApi: gaodingApi,
28
+ agentApi: gaodingApi,
29
+ mnsApi: gaodingApi,
30
+ toolApi: gaodingApi,
31
+ damApi: gaodingApi,
32
+ ssoApi: new URL("https://www.gaoding.com/api/sso"),
33
+ authPageOrigin: new URL("https://www.gaoding.art")
34
+ },
35
+ exposesOrganizations: true,
36
+ tools: defaultToolDefinitions
37
+ });
38
+ const insmindApi = new URL("https://gdcli.insmind.com/api");
39
+ export const insmindProduct = freezeProduct({
40
+ id: "insmind",
41
+ displayName: "insMind",
42
+ commandName: "insmind-cli",
43
+ description: "insMind command-line interface",
44
+ npmPackage: "@insmind/cli",
45
+ skillName: "insmind-cli",
46
+ stateDirectory: ".insmind",
47
+ billingUnit: "credit",
48
+ deviceClientId: "gdhub-cli",
49
+ pricingUrl: new URL("https://www.insmind.com/pricing"),
50
+ telemetryUrl: new URL("https://gaoding-log-ai-gpu-use.us-east-1.log.aliyuncs.com/logstores/gd-cli/track?APIVersion=0.6.0"),
51
+ defaultEditorCreateUrl: new URL("https://www.insmind.com/editor/canvas?mode=create&type=board"),
52
+ editorWorkUrl: new URL("https://www.insmind.com/editor/canvas"),
53
+ restrictEditorTargets: true,
54
+ endpoints: {
55
+ orgApi: insmindApi,
56
+ creditsApi: insmindApi,
57
+ agentApi: insmindApi,
58
+ mnsApi: insmindApi,
59
+ toolApi: insmindApi,
60
+ damApi: insmindApi,
61
+ ssoApi: new URL("https://www.insmind.com/api/sso"),
62
+ authPageOrigin: new URL("https://www.insmind.com")
63
+ },
64
+ exposesOrganizations: false,
65
+ localeEnvironmentVariable: "INSMIND_CLI_LOCALE",
66
+ tools: [
67
+ {
68
+ name: "image.generate",
69
+ title: "Image generation and editing",
70
+ description: "Generate or edit images with published image models using text and optional reference images."
71
+ },
72
+ {
73
+ name: "video.generate",
74
+ title: "Video generation",
75
+ description: "Generate videos with published video models using text and optional images, video, or audio."
76
+ },
77
+ {
78
+ name: "text.generate",
79
+ title: "Text generation",
80
+ description: "Generate text with published text models using text and optional images."
81
+ }
82
+ ]
83
+ });
@@ -0,0 +1,38 @@
1
+ const SUPPORTED_LOCALES = [
2
+ "de-DE", "en-US", "es-ES", "fr-FR", "id-ID", "it-IT", "ja-JP", "ko-KR",
3
+ "nl-NL", "pl-PL", "pt-BR", "ru-RU", "th-TH", "tr-TR", "vi-VN", "zh-CN", "zh-TW"
4
+ ];
5
+ export function localeOption(argv) {
6
+ const index = argv.indexOf("--locale");
7
+ if (index >= 0)
8
+ return argv[index + 1];
9
+ return argv.find((value) => value.startsWith("--locale="))?.slice("--locale=".length);
10
+ }
11
+ export function resolveProductLocale(options) {
12
+ const requested = options.explicit ?? options.environment ?? options.system ?? "en-US";
13
+ let canonical;
14
+ try {
15
+ canonical = Intl.getCanonicalLocales(requested.replace(/_/gu, "-"))[0] ?? "en-US";
16
+ }
17
+ catch {
18
+ canonical = "en-US";
19
+ }
20
+ const exact = SUPPORTED_LOCALES.find((value) => value.toLowerCase() === canonical.toLowerCase());
21
+ const language = canonical.split("-")[0]?.toLowerCase() ?? "en";
22
+ const matched = exact ?? SUPPORTED_LOCALES.find((value) => value.toLowerCase().startsWith(`${language}-`)) ?? "en-US";
23
+ const [normalizedLanguage, region = "US"] = matched.split("-");
24
+ return {
25
+ locale: matched,
26
+ language: normalizedLanguage,
27
+ market: region,
28
+ legalRegion: region
29
+ };
30
+ }
31
+ export function systemLocale() {
32
+ try {
33
+ return Intl.DateTimeFormat().resolvedOptions().locale;
34
+ }
35
+ catch {
36
+ return undefined;
37
+ }
38
+ }
@@ -0,0 +1,3 @@
1
+ export function productText(product, gaoding, insmind) {
2
+ return product.id === "insmind" ? insmind : gaoding;
3
+ }
@@ -1,4 +1,3 @@
1
- const trackingUrl = new URL("https://gaoding-log-ai-gpu.cn-hangzhou.log.aliyuncs.com/logstores/gd-cli/track?APIVersion=0.6.0");
2
1
  const TIMEOUT_MS = 2_000;
3
2
  export function createSlsTelemetrySink(options) {
4
3
  return {
@@ -6,7 +5,7 @@ export function createSlsTelemetrySink(options) {
6
5
  if (events.length === 0)
7
6
  return;
8
7
  try {
9
- await options.fetch(trackingUrl, {
8
+ await options.fetch(options.trackingUrl, {
10
9
  method: "POST",
11
10
  headers: { "Content-Type": "application/json" },
12
11
  body: JSON.stringify({ __logs__: events.map(wireEvent) }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gaoding/cli",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Gaoding command-line interface for agents and people.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "open": "11.0.0",
42
42
  "qrcode": "1.5.4",
43
43
  "semver": "7.8.5",
44
- "sharp": "0.35.3",
44
+ "sharp": "0.35.4",
45
45
  "ws": "8.21.1"
46
46
  },
47
47
  "devDependencies": {
@@ -55,8 +55,8 @@
55
55
  "vitest": "4.1.10"
56
56
  },
57
57
  "gaodingRelease": {
58
- "sourceCommit": "24e9f75334bea21d5d5fed4797a346c81b37c0b1",
59
- "pipelineId": "173862",
60
- "pipelineUrl": "https://git.intra.gaoding.com/gtt/gaoding-cli/-/pipelines/173862"
58
+ "sourceCommit": "b0fd52f34b217c15a54dfb8d6af44c0a5659c752",
59
+ "pipelineId": "180065",
60
+ "pipelineUrl": "https://git.intra.gaoding.com/gtt/gaoding-cli/-/pipelines/180065"
61
61
  }
62
62
  }