gaoding-cli 1.0.0-alpha.8 → 1.0.0-alpha.9

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 (45) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +47 -64
  3. package/dist/bin/gd-cli.js +2 -2
  4. package/dist/src/api/app-runner.d.ts +1 -4
  5. package/dist/src/api/app-runner.js +10 -42
  6. package/dist/src/api/dam-client.d.ts +0 -7
  7. package/dist/src/api/dam-client.js +0 -17
  8. package/dist/src/commands/auth.js +5 -41
  9. package/dist/src/commands/creative.js +37 -45
  10. package/dist/src/commands/dam.js +248 -110
  11. package/dist/src/commands/org.js +17 -39
  12. package/dist/src/commands/skills.js +24 -114
  13. package/dist/src/commands/update.js +10 -85
  14. package/dist/src/commands/usage.js +4 -17
  15. package/dist/src/commands/workflows.d.ts +1 -1
  16. package/dist/src/commands/workflows.js +283 -199
  17. package/dist/src/core/output/envelope.d.ts +1 -0
  18. package/dist/src/core/output/envelope.js +76 -6
  19. package/dist/src/creative/contract.d.ts +28 -80
  20. package/dist/src/creative/contract.js +23 -44
  21. package/dist/src/creative/protocol.js +6 -6
  22. package/dist/src/io.d.ts +0 -2
  23. package/dist/src/io.js +0 -8
  24. package/dist/src/middleware/error-handler.d.ts +7 -1
  25. package/dist/src/middleware/error-handler.js +59 -54
  26. package/dist/src/program.d.ts +1 -0
  27. package/dist/src/program.js +138 -41
  28. package/dist/src/registry/agent-contracts.d.ts +14 -26
  29. package/dist/src/registry/agent-contracts.js +214 -64
  30. package/dist/src/utils/capability-presenter.js +6 -29
  31. package/dist/src/utils/config.d.ts +2 -2
  32. package/dist/src/utils/config.js +1 -1
  33. package/dist/src/utils/sensitive-path.js +1 -4
  34. package/package.json +2 -1
  35. package/skills/gd-cli/SKILL.md +6 -6
  36. package/skills/gd-cli/references/auth.md +3 -10
  37. package/skills/gd-cli/references/creative.md +11 -11
  38. package/skills/gd-cli/references/entitlement.md +2 -2
  39. package/skills/gd-cli/references/errors.md +4 -4
  40. package/skills/gd-cli/references/org.md +3 -3
  41. package/skills/gd-cli/references/sop.md +5 -5
  42. package/skills/gd-cli/references/update.md +4 -3
  43. package/skills/gd-cli/references/workflows.md +6 -5
  44. package/dist/src/utils/list-output-format.d.ts +0 -10
  45. package/dist/src/utils/list-output-format.js +0 -34
package/CHANGELOG.md CHANGED
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [1.0.0-alpha.9] - 2026-08-01
9
+
10
+ ### Changed
11
+
12
+ - 根命令仅保留 `--version` 和 `--help`,机器可读的 `--json` 收敛到确有脚本消费价值的叶子命令。
13
+ - `skills install` 与 `skills uninstall` 在未指定目标时默认处理全部 Agent,且不再二次确认;`update` 收敛为无选项动作。
14
+ - Creative 使用语义化的 `question_message_id`,并收紧输入、输出 Schema 与错误响应契约。
15
+ - Workflow 固定内部并发为 2,并由 CLI 选项显式授权敏感路径。
16
+
17
+ ### Removed
18
+
19
+ - 删除根级 `--format`、`--json`、`--no-input` 和 `--yes`,以及不再具有明确语义的重复输出选项。
20
+
21
+ ### Security
22
+
23
+ - DAM 公开结果改为白名单 DTO,并过滤私网地址、危险协议、userinfo 与敏感查询参数。
24
+ - 公共错误响应改为字段白名单,不再透传后端 `detail` 或内部 Tool/App 路由信息。
25
+
8
26
  ## [1.0.0-alpha.8] - 2026-08-01
9
27
 
10
28
  ### Added
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # gaoding-cli
2
2
 
3
- GD CLI 是稿定设计能力的命令行入口,为用户、脚本、CI 和 Agent 提供登录、组织切换、统一 Creative 创作、多步骤 Workflow 和 DAM 素材管理能力。
3
+ GD CLI 是稿定设计能力的命令行入口,为用户、脚本、CI 和 Agent 提供认证、组织切换、统一 Creative 创作、多步骤 Workflow 和 DAM 素材管理。
4
4
 
5
5
  ## Requirements
6
6
 
@@ -9,95 +9,91 @@ GD CLI 是稿定设计能力的命令行入口,为用户、脚本、CI 和 Age
9
9
 
10
10
  ## Installation
11
11
 
12
- 默认使用全局安装:
13
-
14
12
  ```bash
15
13
  npm install -g gaoding-cli
16
14
  gd-cli skills install
17
15
  gd-cli auth login
18
16
  ```
19
17
 
20
- Agent 的安装与接入规则以[官方 Agent 安装文档](https://www.gaoding.com/cli/install.md)为准。
18
+ `npm install -g gaoding-cli` 只安装 CLI。执行 `gd-cli skills install` 才会安装 Agent Skill;不传参数时安装到全部已知 Agent target。详细规则见[官方 Agent 安装文档](https://www.gaoding.com/cli/install.md)
21
19
 
22
- 非交互 Agent 或 CI 需要显式指定目标并完成确认:
20
+ Agent 或 CI 中,可指定一个或多个 target;安装和卸载均为人类可读输出,用 `skills status --json` 检查机器状态:
23
21
 
24
22
  ```bash
25
- gd-cli skills install --agent codex --yes --format json
26
- gd-cli auth login --no-browser --format json
23
+ gd-cli skills install --agent codex
24
+ gd-cli skills status --json
25
+ gd-cli auth login --no-browser
27
26
  ```
28
27
 
29
- `npm install -g gaoding-cli` 只安装 CLI,不会修改任何 Agent 目录。只有显式执行 `gd-cli skills install` 才会安装 Agent Skill。
30
-
31
28
  ## Quick Start
32
29
 
33
30
  ```bash
34
- gd-cli auth status
35
-
36
- gd-cli org list
31
+ gd-cli auth status --json
32
+ gd-cli org list --json
37
33
  gd-cli org switch --org <org-id>
38
34
 
39
- gd-cli creative schema --format json
40
- gd-cli creative examples --format json
41
- gd-cli creative run --prompt "为夏季运动鞋生成一张户外通勤广告图" --format json
35
+ gd-cli creative schema --json
36
+ gd-cli creative examples
37
+ gd-cli creative run --prompt "为夏季运动鞋生成一张户外通勤广告图" --json
42
38
 
43
- gd-cli workflows list
39
+ gd-cli workflows list --json
44
40
  gd-cli workflows run listing-gallery \
45
41
  --image ./product.jpg \
46
- --brief "夏季运动鞋,轻量缓震,适合通勤"
42
+ --brief "夏季运动鞋,轻量缓震,适合通勤" \
43
+ --json
47
44
 
48
- gd-cli dam upload ./product.jpg
45
+ gd-cli dam upload ./product.jpg --json
49
46
  ```
50
47
 
51
48
  ## Commands
52
49
 
50
+ 使用 `gd-cli --help` 查看一级命令,再使用 `gd-cli <command> --help` 查看子命令和选项。
51
+
53
52
  | Command | Purpose |
54
53
  | --- | --- |
55
- | `auth` | 登录、退出和查看本地认证状态 |
56
- | `org` | 查看和切换当前组织 |
57
- | `creative` | 统一发起图片、视频和文本创作 |
58
- | `workflows` | 运行多步骤创意生产流程 |
59
- | `skills` | 安装和管理 `gd-cli` Agent Skill |
60
- | `dam` | 上传、查询和删除 DAM 素材 |
61
- | `update` | 检查和升级全局 CLI |
62
- | `org credits` | 查询当前组织稿豆余额 |
54
+ | `auth login [--no-browser]` | 登录;输出面向人 |
55
+ | `auth logout` | 退出登录;输出面向人 |
56
+ | `auth status --json` | 查询认证状态 |
57
+ | `org list/current/credits --json` | 查询组织和稿豆余额 |
58
+ | `org switch [--org]` | 切换组织;输出面向人 |
59
+ | `creative run [--prompt|--input] [--json]` | 发起或继续创作 |
60
+ | `creative schema [--json]` | 查看创作 Schema |
61
+ | `creative examples` | 查看完整可运行示例 |
62
+ | `workflows list [--json]` | 列出 Workflow |
63
+ | `workflows schema <workflow-id> [--json]` | 查看 Workflow Schema |
64
+ | `workflows examples <workflow-id>` | 查看完整可运行示例 |
65
+ | `workflows run <workflow-id> [--json]` | 执行 Workflow |
66
+ | `skills install/uninstall [--agent <id> | --all]` | 管理 Agent Skill |
67
+ | `skills status --json` | 查询 Skill 状态 |
68
+ | `skills update` | 刷新已安装 Skill |
69
+ | `dam upload/list/search/get --json` | 管理和查询素材 |
70
+ | `dam delete` | 删除素材;输出面向人 |
71
+ | `update` | 检查并升级全局 CLI |
72
+
73
+ 默认不会因为 stdin/stdout 不是 TTY 而切换为 JSON。只有支持 `--json` 的叶命令在显式传入该选项时才输出机器可读结果。
63
74
 
64
75
  ## Agent And Script Usage
65
76
 
66
- 核心命令支持 `--format json`,便于脚本和 Agent 解析。Creative 接收目标描述、媒体、结构化约束和连续会话信息,由 GD Agent 理解并完成创作;CLI 对使用者表现为一次输入、一次最终输出。
67
-
68
- Creative 的完整输入和输出结构使用本地静态 Schema 发现:
77
+ Creative 使用 `--prompt` `--input`。媒体、结构化约束或连续会话输入使用 JSON 文件或 stdin:
69
78
 
70
79
  ```bash
71
- gd-cli creative schema --format json
72
- gd-cli creative examples --format json
80
+ gd-cli creative run --prompt "为夏季运动鞋生成三条简洁的电商标题" --json
81
+ gd-cli creative run --input creative-request.json --json
82
+ cat creative-request.json | gd-cli creative run --input - --json
73
83
  ```
74
84
 
75
- 纯文本请求可以直接使用 `--prompt`;包含媒体、`parameters` 或连续会话信息时使用 JSON 输入:
85
+ 遇到 `finish_reason=requires_input` 时,回传结果中的 `conversation_id`、`question_message_id` 和 `answers`。完整字段由 `gd-cli creative schema --json` 定义。
76
86
 
77
- ```bash
78
- gd-cli creative run --prompt "为夏季运动鞋生成三条简洁的电商标题" --format json
79
- gd-cli creative run --input creative-request.json --format json
80
- cat creative-request.json | gd-cli creative run --input - --format json
81
- ```
82
-
83
- 多步骤交付使用 `workflows run`:
84
-
85
- ```bash
86
- gd-cli workflows run listing-gallery \
87
- --image ./product.jpg \
88
- --brief "运动鞋上架素材包" \
89
- --output-dir ./output \
90
- --format json
91
- ```
87
+ Workflow 的可用场景可通过 `gd-cli workflows list --json` 查看;特定输入/输出通过 `gd-cli workflows schema <workflow-id> --json` 查看。
92
88
 
93
89
  ## Agent Skill
94
90
 
95
- `gd-cli skills install` 将静态 Skill 安装到 `~/.agents/skills/gd-cli`,再为选中的 Agent 创建 link。常用维护命令:
91
+ `gd-cli skills install` 将静态 Skill 安装到 `~/.agents/skills/gd-cli`,并为选择的 Agent 创建链接。常用维护命令:
96
92
 
97
93
  ```bash
98
- gd-cli skills status --format json
94
+ gd-cli skills status --json
99
95
  gd-cli skills update
100
- gd-cli skills uninstall --all --yes
96
+ gd-cli skills uninstall --all
101
97
  ```
102
98
 
103
99
  CLI 全局升级后,只在 canonical Skill 已安装时自动刷新它;本地项目安装、`npm link` 和 `npx` 运行不会修改全局 CLI。
@@ -109,23 +105,10 @@ npm install
109
105
  npm run build
110
106
  npm test
111
107
  npm run start -- --help
112
- ```
113
-
114
- 本地开发使用独立的 `gd-cli-dev`:
115
-
116
- ```bash
117
- npm run dev:setup
118
- npm run dev
119
- gd-cli-dev --help
120
- ```
121
-
122
- 默认 smoke test 不登录、不调用付费生成能力:
123
-
124
- ```bash
125
108
  npm run smoke:cli
126
109
  ```
127
110
 
128
- 真实接口测试会使用本机登录凭证,并可能消耗额度:
111
+ 真实接口 smoke 会使用本机登录凭证,并可能消耗额度:
129
112
 
130
113
  ```bash
131
114
  gd-cli auth login
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { createProgram } from "../src/program.js";
2
+ import { createProgram, parseProgram } from "../src/program.js";
3
3
  async function main() {
4
4
  const program = await createProgram();
5
- await program.parseAsync(process.argv);
5
+ await parseProgram(program, process.argv);
6
6
  }
7
7
  main().catch((err) => {
8
8
  console.error(err.message);
@@ -1,10 +1,7 @@
1
1
  import { HubClient } from "./hub-client.js";
2
2
  import type { TaskResult } from "./task-poller.js";
3
3
  interface RunOptions {
4
- async?: boolean;
5
- timeout?: number;
6
- outputDir?: string;
7
- concurrency?: number;
4
+ allowSensitivePath?: boolean;
8
5
  onStepStart?: (step: AppStepPublicRecord) => void;
9
6
  onStepComplete?: (step: AppStepPublicRecord, result?: TaskResult) => void;
10
7
  }
@@ -1,23 +1,5 @@
1
1
  import { DirectToolInvoker } from "./direct-tools.js";
2
2
  import { DirectApiError } from "./direct-client.js";
3
- /** 多步 App 含多次生图/对话,默认至少等待 10 分钟 */
4
- const APP_RUN_MIN_WAIT_SEC = 600;
5
- function resolveAppWaitTimeout(explicit, estimatedSeconds) {
6
- if (explicit !== undefined && Number.isFinite(explicit) && explicit > 0) {
7
- return Math.floor(explicit);
8
- }
9
- const est = Number(estimatedSeconds);
10
- if (Number.isFinite(est) && est > APP_RUN_MIN_WAIT_SEC) {
11
- return Math.ceil(est);
12
- }
13
- return APP_RUN_MIN_WAIT_SEC;
14
- }
15
- function resolveConcurrency(value) {
16
- const numeric = Number(value);
17
- if (!Number.isFinite(numeric) || numeric <= 0)
18
- return 2;
19
- return Math.max(1, Math.min(4, Math.floor(numeric)));
20
- }
21
3
  async function mapWithConcurrency(items, concurrency, worker) {
22
4
  let next = 0;
23
5
  const runners = Array.from({ length: Math.min(concurrency, items.length) }, async () => {
@@ -170,15 +152,6 @@ export class AppRunner {
170
152
  void client;
171
153
  }
172
154
  async run(appId, params, options = {}) {
173
- if (options.async) {
174
- return {
175
- task_id: `app-${appId}-${Date.now()}`,
176
- status: "failed",
177
- message: "本地 App workflow 暂不支持 --async,请去掉 --async 直接运行。",
178
- };
179
- }
180
- void resolveAppWaitTimeout(options.timeout, undefined);
181
- void options.outputDir;
182
155
  try {
183
156
  if (appId === "listing-gallery")
184
157
  return await this.runListingGallery(params, options);
@@ -208,7 +181,7 @@ export class AppRunner {
208
181
  detail_image: "4:5",
209
182
  lifestyle_image: "4:5",
210
183
  });
211
- const prepared = await this.prepareProduct(ctx, image, allowSensitivePath(params));
184
+ const prepared = await this.prepareProduct(ctx, image, options.allowSensitivePath === true);
212
185
  const title = await this.generateTitle(ctx, brief);
213
186
  const titleText = outputString(title, "text", false) || brief;
214
187
  const promptPlan = await this.optimizePrompt(ctx, "prompt_plan", "生成图库素材规划", `为电商 Listing 图库生成素材规划:${brief}。品类判断:${profile.label}。需要覆盖白底主图、单卖点证明图、材质/结构细节图、生活方式图;${copyPlanningGuidance(copyPlan)}每张图只回答一个购买问题,不生成假认证和不可验证参数。`, prepared.cutoutUrl, `Listing 图库素材规划:主图、卖点图、细节图、生活方式图。品类:${profile.label}。商品卖点:${brief}`);
@@ -310,7 +283,7 @@ export class AppRunner {
310
283
  overlayCopy: overlayCopy.lifestyle_image,
311
284
  }),
312
285
  },
313
- ], options);
286
+ ]);
314
287
  return ctx.completed();
315
288
  }
316
289
  async runPdpAPlus(params, options) {
@@ -326,7 +299,7 @@ export class AppRunner {
326
299
  usage_module: "4:5",
327
300
  comparison_module: "1:1",
328
301
  });
329
- const prepared = await this.prepareProduct(ctx, image, allowSensitivePath(params));
302
+ const prepared = await this.prepareProduct(ctx, image, options.allowSensitivePath === true);
330
303
  const title = await this.generateTitle(ctx, brief);
331
304
  const titleText = outputString(title, "text", false) || brief;
332
305
  const promptPlan = await this.optimizePrompt(ctx, "prompt_plan", "生成详情页模块规划", `为电商详情页/A+模块生成购买说服顺序:${brief}。品类判断:${profile.label}。模块包含首屏、痛点解决、结构/细节证明、真实使用场景、对比规格;${copyPlanningGuidance(copyPlan)}不编造参数和认证。`, prepared.cutoutUrl, `详情页模块规划:首屏、痛点、结构细节、使用场景、对比规格。品类:${profile.label}。商品信息:${brief}`);
@@ -451,7 +424,7 @@ export class AppRunner {
451
424
  overlayCopy: overlayCopy.comparison_module,
452
425
  }),
453
426
  },
454
- ], options);
427
+ ]);
455
428
  return ctx.completed();
456
429
  }
457
430
  async runSocialSeedingPack(params, options) {
@@ -464,7 +437,7 @@ export class AppRunner {
464
437
  cover_image: "3:4",
465
438
  scene_image: "9:16",
466
439
  });
467
- const prepared = await this.prepareProduct(ctx, image, allowSensitivePath(params));
440
+ const prepared = await this.prepareProduct(ctx, image, options.allowSensitivePath === true);
468
441
  const title = await this.generateTitle(ctx, brief);
469
442
  const titleText = outputString(title, "text", false) || brief;
470
443
  const xhsCaption = buildXhsCaption(titleText, brief);
@@ -534,7 +507,7 @@ export class AppRunner {
534
507
  overlayCopy: overlayCopy.scene_image,
535
508
  }),
536
509
  },
537
- ], options);
510
+ ]);
538
511
  return ctx.completed();
539
512
  }
540
513
  async runCampaignKvPack(params, options) {
@@ -544,7 +517,7 @@ export class AppRunner {
544
517
  const ratios = parseRatioList(params.ratios ?? params.ratio, ["16:9", "1:1", "4:5"]);
545
518
  const profile = inferProductCategoryProfile(brief);
546
519
  const copyPlan = resolveCopyPlan(params, brief);
547
- const prepared = await this.prepareProduct(ctx, image, allowSensitivePath(params));
520
+ const prepared = await this.prepareProduct(ctx, image, options.allowSensitivePath === true);
548
521
  const title = await this.generateTitle(ctx, brief);
549
522
  const titleText = outputString(title, "text", false) || brief;
550
523
  const promptPlan = await this.optimizePrompt(ctx, "prompt_plan", "生成 Campaign KV 主视觉提示词", `为新品 Campaign KV 生成${copyPlan.mode === "no-text" ? "无字主视觉" : "可直接投放主视觉"}提示词:${brief}。品类判断:${profile.label}。要求一个清晰记忆符号,可裁切到官网、社媒、电商活动和投放;${copyPlanningGuidance(copyPlan)}不改 logo、不生成假促销标。`, prepared.cutoutUrl, copyPlan.mode === "no-text"
@@ -595,11 +568,11 @@ export class AppRunner {
595
568
  overlayCopy: String(overlayCopy[key] ?? ""),
596
569
  }),
597
570
  };
598
- }), options);
571
+ }));
599
572
  return ctx.completed();
600
573
  }
601
- async generateImageJobs(ctx, jobs, options) {
602
- await mapWithConcurrency(jobs, resolveConcurrency(options.concurrency), async (job) => {
574
+ async generateImageJobs(ctx, jobs) {
575
+ await mapWithConcurrency(jobs, 2, async (job) => {
603
576
  const result = await this.generateImage(ctx, job.key, job.stepName, job.prompt, job.image, job.ratio, job.model);
604
577
  ctx.outputs[job.key] = result.outputs;
605
578
  ctx.addAsset(job.label, job.key, result);
@@ -1159,11 +1132,6 @@ function optionalString(value) {
1159
1132
  const normalized = value.trim();
1160
1133
  return normalized ? normalized : undefined;
1161
1134
  }
1162
- function allowSensitivePath(params) {
1163
- return (params.allow_sensitive_path === true ||
1164
- params.allowSensitivePath === true ||
1165
- params["allow-sensitive-path"] === true);
1166
- }
1167
1135
  function outputString(result, key, required = true) {
1168
1136
  const outputs = result.outputs;
1169
1137
  const value = outputs?.[key];
@@ -42,7 +42,6 @@ export interface DamSearchOptions {
42
42
  pageSize?: number;
43
43
  page?: number;
44
44
  cursor?: string;
45
- raw?: boolean;
46
45
  allowEmptyKeyword?: boolean;
47
46
  }
48
47
  export interface DamSearchAsset {
@@ -74,12 +73,6 @@ export interface DamSearchResult {
74
73
  finish: boolean;
75
74
  next_cursor?: string;
76
75
  assets: DamSearchAsset[];
77
- debug?: {
78
- source: {
79
- endpoint: string;
80
- raw?: unknown;
81
- };
82
- };
83
76
  }
84
77
  interface DamCover {
85
78
  url?: string;
@@ -4,7 +4,6 @@ import { basename, extname, resolve } from "node:path";
4
4
  import OSS from "ali-oss";
5
5
  import sharp from "sharp";
6
6
  import { DirectApiClient, DirectApiError, unwrapEnvelope } from "./direct-client.js";
7
- import { isDebug, isVerbose } from "../utils/config.js";
8
7
  import { assertSafeUploadPath } from "../utils/sensitive-path.js";
9
8
  import { assertSafeHttpUrl } from "../utils/url-safety.js";
10
9
  import { redactSensitiveText } from "../utils/redact.js";
@@ -140,12 +139,9 @@ export class DamClient {
140
139
  try {
141
140
  const response = await this.client.post("/dam/asset/v2/search/simple", payload);
142
141
  return normalizeSearchResponse(response, {
143
- endpoint: "/dam/asset/v2/search/simple",
144
142
  query,
145
143
  repositoryIds,
146
144
  payload,
147
- includeDebug: options.raw === true || isVerbose() || isDebug(),
148
- includeRaw: options.raw === true,
149
145
  });
150
146
  }
151
147
  catch (error) {
@@ -153,12 +149,9 @@ export class DamClient {
153
149
  throw error;
154
150
  const response = await this.client.post("/dam/asset/search", payload);
155
151
  return normalizeSearchResponse(response, {
156
- endpoint: "/dam/asset/search",
157
152
  query,
158
153
  repositoryIds,
159
154
  payload,
160
- includeDebug: options.raw === true || isVerbose() || isDebug(),
161
- includeRaw: options.raw === true,
162
155
  });
163
156
  }
164
157
  }
@@ -307,16 +300,6 @@ function normalizeSearchResponse(response, context) {
307
300
  finish,
308
301
  next_cursor: nextCursor,
309
302
  assets: rawItems.map(normalizeSearchAsset).filter((item) => item.asset_id),
310
- ...(context.includeDebug
311
- ? {
312
- debug: {
313
- source: {
314
- endpoint: context.endpoint,
315
- ...(context.includeRaw ? { raw: response } : {}),
316
- },
317
- },
318
- }
319
- : {}),
320
303
  };
321
304
  }
322
305
  function extractSearchContainer(value) {
@@ -3,10 +3,7 @@ import { withErrorHandler } from "../middleware/error-handler.js";
3
3
  import { createAuthProvider } from "../core/auth/auth-provider.js";
4
4
  import { CredentialStoreV2 } from "../auth/credential-store-v2.js";
5
5
  import { resolveEndpoints, isVerbose, isDebug } from "../utils/config.js";
6
- import { getIO } from "../io.js";
7
6
  import { emitJson, wrapEnvelope } from "../core/output/envelope.js";
8
- import { setStaticHelp } from "../utils/static-help.js";
9
- import { resolveInvokeOutputFormat } from "../utils/list-output-format.js";
10
7
  import { setAuthRequirement } from "../middleware/auth.js";
11
8
  const loginAction = withErrorHandler(async (options) => {
12
9
  if (isVerbose() || isDebug()) {
@@ -15,22 +12,8 @@ const loginAction = withErrorHandler(async (options) => {
15
12
  }
16
13
  const provider = await createAuthProvider();
17
14
  const result = await provider.login({
18
- orgId: options.org,
19
- noBrowser: !!options.noBrowser,
20
- scope: options.scope,
21
- env: options.env,
15
+ noBrowser: options.browser === false,
22
16
  });
23
- const io = getIO();
24
- if (io.prefersJsonOutput()) {
25
- emitJson(wrapEnvelope({
26
- mode: provider.mode,
27
- logged_in: true,
28
- user: result.credentials.user,
29
- org: result.org,
30
- next_steps: result.org ? [] : ["gd-cli org switch"],
31
- }, { command: "auth login" }));
32
- return;
33
- }
34
17
  console.log(chalk.green("\n✓ 授权成功,可以开始使用稿定能力进行创意生产\n"));
35
18
  if (!result.org) {
36
19
  console.log(chalk.yellow(" 尚未选择当前组织,请执行 gd-cli org switch 后再调用 Creative / Workflows / DAM。"));
@@ -38,13 +21,12 @@ const loginAction = withErrorHandler(async (options) => {
38
21
  });
39
22
  const statusAction = withErrorHandler(async (_opts, command) => {
40
23
  const cmd = command;
41
- const format = resolveInvokeOutputFormat(cmd);
42
- const io = getIO();
24
+ const json = cmd.opts().json === true;
43
25
  const store = new CredentialStoreV2();
44
26
  const creds = store.read();
45
27
  const ep = resolveEndpoints();
46
28
  if (!creds) {
47
- if (io.prefersJsonOutput(format)) {
29
+ if (json) {
48
30
  emitJson(wrapEnvelope({
49
31
  logged_in: false,
50
32
  environment: { active: ep.active_env },
@@ -57,7 +39,7 @@ const statusAction = withErrorHandler(async (_opts, command) => {
57
39
  return;
58
40
  }
59
41
  const payload = buildStatusPayload(creds, store);
60
- if (io.prefersJsonOutput(format)) {
42
+ if (json) {
61
43
  emitJson(wrapEnvelope(payload, { command: "auth status" }));
62
44
  return;
63
45
  }
@@ -67,24 +49,15 @@ const logoutAction = withErrorHandler(async () => {
67
49
  const provider = await createAuthProvider();
68
50
  await provider.logout();
69
51
  new CredentialStoreV2().delete();
70
- const io = getIO();
71
- if (io.prefersJsonOutput()) {
72
- emitJson(wrapEnvelope({ logged_out: true }, { command: "auth logout" }));
73
- return;
74
- }
75
52
  console.log(chalk.green("✓ 已取消授权,可以重新执行 gd-cli auth login 进行授权。\n"));
76
53
  });
77
54
  export function registerAuthCommand(program) {
78
55
  const auth = program
79
56
  .command("auth")
80
57
  .description("登录、退出、查看登录状态");
81
- setStaticHelp(auth, AUTH_HELP);
82
58
  const login = auth
83
59
  .command("login")
84
60
  .description("浏览器/扫码授权登录")
85
- .option("--org <org-id>", "登录后直接选择当前组织")
86
- .option("--env <env>", "环境标识 cursor / claude / ci")
87
- .option("--scope <scope>", "授权范围,逗号分隔")
88
61
  .option("--no-browser", "不自动打开浏览器")
89
62
  .action(loginAction);
90
63
  setAuthRequirement(login, "none");
@@ -96,19 +69,10 @@ export function registerAuthCommand(program) {
96
69
  const status = auth
97
70
  .command("status")
98
71
  .description("查看授权状态")
72
+ .option("--json", "输出机器可读 JSON")
99
73
  .action(statusAction);
100
74
  setAuthRequirement(status, "none");
101
75
  }
102
- const AUTH_HELP = `
103
- Usage: gd-cli auth [options] [command]
104
-
105
- 登录、退出、查看登录状态
106
-
107
- Commands:
108
- login 浏览器/扫码授权登录
109
- logout 取消授权
110
- status 查看授权状态
111
- `;
112
76
  function buildStatusPayload(creds, store) {
113
77
  const ep = resolveEndpoints();
114
78
  const credentialExpired = store.isAkExpired();