gaoding-cli 1.0.0-alpha.7 → 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 (77) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +47 -60
  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 +11 -44
  6. package/dist/src/api/creative-client.d.ts +34 -0
  7. package/dist/src/api/creative-client.js +184 -0
  8. package/dist/src/api/dam-client.d.ts +0 -7
  9. package/dist/src/api/dam-client.js +0 -17
  10. package/dist/src/api/direct-client.d.ts +9 -2
  11. package/dist/src/api/direct-client.js +45 -18
  12. package/dist/src/api/hub-client.d.ts +11 -8
  13. package/dist/src/api/hub-client.js +17 -18
  14. package/dist/src/api/usage-client.d.ts +4 -4
  15. package/dist/src/api/usage-client.js +9 -49
  16. package/dist/src/auth/credential-store-v2.d.ts +0 -1
  17. package/dist/src/auth/credential-store-v2.js +0 -6
  18. package/dist/src/commands/auth.js +17 -53
  19. package/dist/src/commands/creative.d.ts +8 -0
  20. package/dist/src/commands/creative.js +178 -0
  21. package/dist/src/commands/dam.js +270 -127
  22. package/dist/src/commands/org.js +31 -47
  23. package/dist/src/commands/skills.js +33 -118
  24. package/dist/src/commands/update.js +11 -82
  25. package/dist/src/commands/usage.d.ts +1 -1
  26. package/dist/src/commands/usage.js +10 -21
  27. package/dist/src/commands/workflows.d.ts +1 -1
  28. package/dist/src/commands/workflows.js +299 -197
  29. package/dist/src/core/auth/auth-guard.d.ts +21 -0
  30. package/dist/src/core/auth/auth-guard.js +121 -0
  31. package/dist/src/core/auth/org-manager.d.ts +2 -1
  32. package/dist/src/core/auth/org-manager.js +61 -6
  33. package/dist/src/core/output/envelope.d.ts +1 -0
  34. package/dist/src/core/output/envelope.js +76 -6
  35. package/dist/src/creative/contract.d.ts +1060 -0
  36. package/dist/src/creative/contract.js +722 -0
  37. package/dist/src/creative/media.d.ts +19 -0
  38. package/dist/src/creative/media.js +83 -0
  39. package/dist/src/creative/protocol.d.ts +60 -0
  40. package/dist/src/creative/protocol.js +337 -0
  41. package/dist/src/io.d.ts +0 -2
  42. package/dist/src/io.js +0 -8
  43. package/dist/src/middleware/auth.d.ts +6 -2
  44. package/dist/src/middleware/auth.js +25 -63
  45. package/dist/src/middleware/error-handler.d.ts +8 -0
  46. package/dist/src/middleware/error-handler.js +61 -57
  47. package/dist/src/program.d.ts +1 -0
  48. package/dist/src/program.js +137 -122
  49. package/dist/src/registry/agent-contracts.d.ts +14 -34
  50. package/dist/src/registry/agent-contracts.js +209 -297
  51. package/dist/src/registry/direct-registry.d.ts +0 -5
  52. package/dist/src/registry/direct-registry.js +0 -19
  53. package/dist/src/registry/registry-client.d.ts +0 -21
  54. package/dist/src/registry/registry-client.js +1 -40
  55. package/dist/src/utils/capability-presenter.js +6 -29
  56. package/dist/src/utils/config.d.ts +2 -2
  57. package/dist/src/utils/config.js +1 -1
  58. package/dist/src/utils/help-verify.d.ts +1 -3
  59. package/dist/src/utils/help-verify.js +1 -25
  60. package/dist/src/utils/sensitive-path.js +1 -4
  61. package/package.json +4 -3
  62. package/skills/gd-cli/SKILL.md +13 -12
  63. package/skills/gd-cli/references/auth.md +9 -10
  64. package/skills/gd-cli/references/creative.md +47 -0
  65. package/skills/gd-cli/references/entitlement.md +3 -3
  66. package/skills/gd-cli/references/errors.md +10 -3
  67. package/skills/gd-cli/references/org.md +3 -3
  68. package/skills/gd-cli/references/sop.md +8 -8
  69. package/skills/gd-cli/references/update.md +4 -3
  70. package/skills/gd-cli/references/workflows.md +7 -6
  71. package/dist/src/commands/models.d.ts +0 -2
  72. package/dist/src/commands/models.js +0 -78
  73. package/dist/src/commands/tools.d.ts +0 -4
  74. package/dist/src/commands/tools.js +0 -383
  75. package/dist/src/utils/list-output-format.d.ts +0 -10
  76. package/dist/src/utils/list-output-format.js +0 -34
  77. package/skills/gd-cli/references/tools.md +0 -29
@@ -1,21 +1,21 @@
1
1
  import { ApiError } from "../api/hub-client.js";
2
2
  import { DirectApiError } from "../api/direct-client.js";
3
- import { failedEnvelope, emitJson } from "../core/output/envelope.js";
3
+ import { failedEnvelope, emitJson, publicCliErrorBody, } from "../core/output/envelope.js";
4
4
  import { CliUsageError } from "../core/output/cli-error.js";
5
5
  import { isVerbose, isDebug } from "../utils/config.js";
6
6
  import { isTransientNetworkError } from "../utils/transient-network-error.js";
7
7
  import { detectEntitlementIssue, entitlementCliError, ENTITLEMENT_PRICING_URL, resolveEntitlementPricingUrl, } from "../utils/entitlement.js";
8
8
  import { redactSensitiveText, redactSensitiveValue } from "../utils/redact.js";
9
+ const jsonFailureProjectors = new WeakMap();
9
10
  const ERROR_GUIDES = {
10
11
  AUTH_MISSING: "请先登录:\n gd-cli auth login",
11
12
  AUTH_EXPIRED: "凭证已过期,请重新登录:\n gd-cli auth login",
12
13
  AUTH_REFRESH_FAILED: "凭证刷新失败:\n gd-cli auth login",
13
14
  AUTH_SCOPE_DENIED: "权限不足,请重新授权",
14
- ORG_BIND_EXPIRED: "组织绑定已过期:\n gd-cli org switch",
15
15
  ORG_INVALID: "当前组织无效:\n gd-cli org list",
16
16
  PARAM_MISSING: "查看命令帮助:\n gd-cli <command> --help",
17
17
  PARAM_INVALID: "参数值不合法,请检查参数格式",
18
- TOOL_NOT_FOUND: "工具不存在:\n gd-cli tools list",
18
+ TOOL_NOT_FOUND: "能力路由不存在,请检查输入或重试当前命令",
19
19
  APP_NOT_FOUND: "Workflow 不存在:\n gd-cli workflows list",
20
20
  TASK_NOT_FOUND: "任务不存在或已过期",
21
21
  RATE_LIMITED: "请求过于频繁,请稍后重试",
@@ -29,7 +29,7 @@ export function withErrorHandler(handler) {
29
29
  }
30
30
  catch (error) {
31
31
  if (shouldEmitJsonError(args)) {
32
- emitJson(failedEnvelope(redactSensitiveValue(toCliErrorBody(error))));
32
+ emitJsonFailure(commandFromArgs(args), error);
33
33
  process.exit(1);
34
34
  }
35
35
  if (error instanceof CliUsageError) {
@@ -81,22 +81,26 @@ export function withErrorHandler(handler) {
81
81
  }
82
82
  };
83
83
  }
84
- function shouldEmitJsonError(args) {
85
- let current = args.find(isCommandLike);
86
- while (current) {
87
- if (!isCommandLike(current))
88
- return false;
89
- const format = current.opts().format;
90
- const json = current.opts().json;
91
- if (json === true)
92
- return true;
93
- if (format === "json")
94
- return true;
95
- if (format)
96
- return false;
97
- current = current.parent;
98
- }
99
- return !process.stdout.isTTY;
84
+ export function shouldEmitJsonError(args) {
85
+ const command = commandFromArgs(args);
86
+ return command?.opts().json === true;
87
+ }
88
+ export function setJsonFailureProjector(command, projector) {
89
+ jsonFailureProjectors.set(command, projector);
90
+ }
91
+ export function jsonFailureEnvelopeFor(command, error) {
92
+ const body = redactSensitiveValue(toCliErrorBody(error));
93
+ const projector = command ? jsonFailureProjectors.get(command) : undefined;
94
+ if (projector)
95
+ return projector(body);
96
+ const commandName = command ? publicCommandName(command) : "";
97
+ return failedEnvelope(body, commandName ? { command: commandName } : undefined);
98
+ }
99
+ export function emitJsonFailure(command, error) {
100
+ emitJson(jsonFailureEnvelopeFor(command, error));
101
+ }
102
+ function commandFromArgs(args) {
103
+ return [...args].reverse().find(isCommandLike);
100
104
  }
101
105
  function isCommandLike(value) {
102
106
  return (!!value &&
@@ -104,7 +108,10 @@ function isCommandLike(value) {
104
108
  "opts" in value &&
105
109
  typeof value.opts === "function");
106
110
  }
107
- function toCliErrorBody(error) {
111
+ export function toCliErrorBody(error) {
112
+ return publicCliErrorBody(toCliErrorBodyInternal(error));
113
+ }
114
+ function toCliErrorBodyInternal(error) {
108
115
  if (error instanceof CliUsageError) {
109
116
  return error.body;
110
117
  }
@@ -128,38 +135,40 @@ function toCliErrorBody(error) {
128
135
  });
129
136
  if (entitlement)
130
137
  return redactSensitiveValue(entitlementCliError(entitlement, error.body));
131
- if (isToolRouteUnavailableMessage(parsed.message ?? error.message)) {
132
- return toolRouteUnavailableCliError(parsed.message ?? error.message, redactSensitiveValue(error.body));
138
+ if (parsed.message && isToolRouteUnavailableMessage(parsed.message)) {
139
+ return toolRouteUnavailableCliError(parsed.message, redactSensitiveValue(error.body));
133
140
  }
134
141
  return {
135
142
  code: parsed.code ?? `HTTP_${error.statusCode}`,
136
143
  type: error.statusCode === 401 ? "auth" : "business",
137
144
  message: parsed.message
138
145
  ? normalizeBusinessMessage(parsed.message)
139
- : redactSensitiveText(error.message),
146
+ : publicApiFailureMessage(error.statusCode),
140
147
  hint: redactSensitiveText(parsed.hint ?? directApiHint(parsed, error.url) ?? ""),
141
148
  retryable: false,
142
149
  detail: redactSensitiveValue(error.body),
143
150
  };
144
151
  }
145
152
  if (error instanceof ApiError) {
146
- const parsed = parseJsonObject(error.body);
147
- const code = stringField(parsed, "error_code") ?? stringField(parsed, "error") ?? "API_ERROR";
148
- const message = stringField(parsed, "message") ?? error.message;
153
+ const parsedBody = parseJsonObject(error.body);
154
+ const parsed = parseDirectApiErrorBody(parsedBody ?? error.body);
155
+ const code = parsed.code ?? "API_ERROR";
156
+ const message = parsed.message ?? publicApiFailureMessage(error.statusCode);
149
157
  const entitlement = detectEntitlementIssue({
150
158
  code,
151
159
  message,
152
- detail: parsed ?? error.body,
160
+ detail: parsedBody ?? error.body,
153
161
  });
154
- if (entitlement)
155
- return redactSensitiveValue(entitlementCliError(entitlement, parsed ?? error.body));
162
+ if (entitlement) {
163
+ return redactSensitiveValue(entitlementCliError(entitlement, parsedBody ?? error.body));
164
+ }
156
165
  return {
157
166
  code,
158
167
  type: code.startsWith("AUTH") ? "auth" : "business",
159
168
  message: redactSensitiveText(message),
160
- hint: redactSensitiveText(stringField(parsed, "suggestion") ?? errorGuide(code) ?? ""),
169
+ hint: redactSensitiveText(parsed.hint ?? errorGuide(code) ?? ""),
161
170
  retryable: false,
162
- detail: redactSensitiveValue(parsed ?? error.body),
171
+ detail: redactSensitiveValue(parsedBody ?? error.body),
163
172
  };
164
173
  }
165
174
  if (error instanceof Error) {
@@ -210,32 +219,10 @@ function printCliUsageError(body) {
210
219
  console.error(`\n 错误码: ${body.code}`);
211
220
  if (body.reason)
212
221
  console.error(` 原因: ${body.reason}`);
213
- const detail = body.detail && typeof body.detail === "object" && !Array.isArray(body.detail)
214
- ? body.detail
215
- : undefined;
216
- const appId = body.app_id ?? stringField(detail, "app_id");
217
- const toolId = body.tool_id ?? stringField(detail, "tool_id");
218
- if (appId)
219
- console.error(` Workflow: ${appId}`);
220
- if (toolId)
221
- console.error(` Tool: ${toolId}`);
222
- const missingTools = Array.isArray(body.missing_tools)
223
- ? body.missing_tools
224
- .map((item) => typeof item === "string"
225
- ? item
226
- : stringField(item, "id") ?? "")
227
- .filter(Boolean)
228
- : [];
229
- if (missingTools.length > 0) {
230
- console.error(` 缺失 Tool: ${missingTools.join(", ")}`);
231
- }
232
222
  if (body.hint)
233
223
  console.error(`\n 说明: ${body.hint}`);
234
224
  if (body.next_command)
235
225
  console.error(`\n 下一步: ${body.next_command}`);
236
- const listCommand = stringField(detail, "list_command");
237
- if (listCommand)
238
- console.error(` 查看状态: ${listCommand}`);
239
226
  console.error("");
240
227
  }
241
228
  function parseDirectApiErrorBody(body) {
@@ -250,12 +237,29 @@ function parseDirectApiErrorBody(body) {
250
237
  code: stringField(nestedError, "error_code") ??
251
238
  stringField(nestedError, "code") ??
252
239
  stringField(value, "error_code") ??
253
- stringField(value, "code"),
240
+ stringField(value, "code") ??
241
+ stringField(value, "error"),
254
242
  errorName: stringField(nestedError, "error_name") ??
255
243
  stringField(value, "error_name"),
256
244
  message: stringField(nestedError, "message") ?? stringField(value, "message"),
245
+ hint: stringField(nestedError, "suggestion") ??
246
+ stringField(nestedError, "hint") ??
247
+ stringField(value, "suggestion") ??
248
+ stringField(value, "hint"),
257
249
  };
258
250
  }
251
+ function publicApiFailureMessage(statusCode) {
252
+ return `业务请求失败(HTTP ${statusCode})`;
253
+ }
254
+ function publicCommandName(command) {
255
+ const names = [];
256
+ let current = command;
257
+ while (current.parent) {
258
+ names.unshift(current.name());
259
+ current = current.parent;
260
+ }
261
+ return names.join(" ");
262
+ }
259
263
  function parseJsonObject(value) {
260
264
  try {
261
265
  const parsed = JSON.parse(value);
@@ -367,7 +371,7 @@ function toolRouteUnavailableCliError(message, detail) {
367
371
  type: "business",
368
372
  message: normalizeToolRouteUnavailableMessage(message),
369
373
  reason: "tool-route-unavailable",
370
- hint: "当前 Tool 的平台生成路由不可用。Agent 应停止重试,不要切换模型、环境、团队或调用内部 raw.dify;请保留本次输入并联系平台确认能力配置。",
374
+ hint: "当前能力的生成路由不可用。请停止重试,不要切换模型、环境或团队;请保留本次输入并联系平台确认能力配置。",
371
375
  retryable: false,
372
376
  detail,
373
377
  };
@@ -386,7 +390,7 @@ function isToolRouteUnavailableMessage(message) {
386
390
  function normalizeToolRouteUnavailableMessage(message) {
387
391
  const normalized = normalizeBusinessMessage(message);
388
392
  if (/没有可用的工具|tool-intent 没有返回|tool intent 没有返回/i.test(normalized)) {
389
- return "当前 Tool 的平台生成路由不可用,未发起生成任务。";
393
+ return "当前能力的生成路由不可用,未发起生成任务。";
390
394
  }
391
395
  return normalized;
392
396
  }
@@ -1,2 +1,3 @@
1
1
  import { Command } from "commander";
2
2
  export declare function createProgram(): Promise<Command>;
3
+ export declare function parseProgram(program: Command, argv?: readonly string[]): Promise<void>;
@@ -1,152 +1,167 @@
1
- import { Command, Option } from "commander";
1
+ import { Command, CommanderError } from "commander";
2
2
  import { CLI_VERSION } from "./utils/config.js";
3
3
  import { registerAuthCommand } from "./commands/auth.js";
4
4
  import { registerOrgCommand } from "./commands/org.js";
5
5
  import { registerWorkflowsCommand } from "./commands/workflows.js";
6
- import { registerToolsCommand } from "./commands/tools.js";
6
+ import { registerCreativeCommand } from "./commands/creative.js";
7
7
  import { registerDamCommand } from "./commands/dam.js";
8
- import { registerModelsCommand } from "./commands/models.js";
9
8
  import { registerUpdateCommand } from "./commands/update.js";
10
9
  import { registerSkillsCommand } from "./commands/skills.js";
11
- import { registerUsageCommand } from "./commands/usage.js";
12
10
  import { maybeNotifyUpdate } from "./update/notifier.js";
13
- import { formatOutput } from "./middleware/output.js";
14
- import { buildManifest, buildTopExamples, rowsForManifest, } from "./registry/agent-contracts.js";
15
- import { resolveListOutputFormat } from "./utils/list-output-format.js";
16
- import { setStaticHelp } from "./utils/static-help.js";
11
+ import { installAuthPreflight } from "./middleware/auth.js";
12
+ import { CliUsageError } from "./core/output/cli-error.js";
13
+ import { emitJsonFailure } from "./middleware/error-handler.js";
17
14
  export async function createProgram() {
18
15
  const program = new Command();
19
16
  program
20
17
  .name("gd-cli")
21
18
  .usage("<command> [options]")
22
19
  .description("GD CLI — 让稿定成为 Agent 的创意生产引擎")
23
- .version(CLI_VERSION)
24
- .addOption(new Option("-f, --format <format>", "输出格式: human / table / json / text").choices(["json", "human", "table", "text"]))
25
- .addOption(new Option("--json", "等同于 --format json,推荐 Agent 和脚本使用"))
26
- .addOption(new Option("--no-input", "禁止交互,适合 CI / Agent"))
27
- .addOption(new Option("--yes", "跳过确认"))
28
- .addOption(new Option("--verbose", "输出详细日志").hideHelp().default(false));
29
- setStaticHelp(program, TOP_LEVEL_HELP);
30
- program
31
- .command("manifest")
32
- .description("输出 Agent 可解析的 gd-cli 能力清单")
33
- .action((_opts, command) => {
34
- const manifest = buildManifest("all");
35
- const format = resolveListOutputFormat(command);
36
- formatOutput(format === "json" ? manifest : rowsForManifest(manifest), format);
37
- });
38
- program
39
- .command("examples")
40
- .description("查看常用场景示例")
41
- .action((_opts, command) => {
42
- const examples = buildTopExamples();
43
- const format = resolveExplicitExamplesFormat(command);
44
- if (format === "json") {
45
- formatOutput(examples, "json");
46
- }
47
- else {
48
- printExamples(examples);
49
- }
50
- });
51
- const agent = program
52
- .command("agent", { hidden: true })
53
- .description("Agent 调用 gd-cli 的机器可读入口说明")
54
- .action(() => {
55
- console.log(AGENT_HELP.trim());
56
- });
57
- agent.addHelpText("afterAll", `\n${AGENT_HELP}`);
20
+ .version(CLI_VERSION);
58
21
  registerAuthCommand(program);
59
22
  registerOrgCommand(program);
23
+ registerCreativeCommand(program);
60
24
  registerWorkflowsCommand(program);
61
- registerToolsCommand(program);
62
25
  registerSkillsCommand(program);
63
- registerModelsCommand(program);
64
26
  registerDamCommand(program);
65
27
  registerUpdateCommand(program);
66
- registerUsageCommand(program);
28
+ installAuthPreflight(program);
67
29
  program.hook("postAction", async (_thisCommand, actionCommand) => {
68
30
  await maybeNotifyUpdate(actionCommand);
69
31
  });
70
32
  return program;
71
33
  }
72
- const TOP_LEVEL_HELP = `
73
- Usage: gd-cli <command> [options]
74
-
75
- GD CLI 让稿定成为 Agent 的创意生产引擎
76
-
77
- 核心命令:
78
- auth 登录、退出、查看登录状态
79
- org 查看和切换当前组织
80
- workflows 运行完整创意场景任务,例如商品上新、批量海报、内容矩阵
81
- tools 调用单项 AI 创意能力,例如生图、抠图、高清化、标题生成
82
- skills 安装和管理 gd-cli Agent Skill
83
- dam 素材管理,上传、查询、删除素材
84
- update 检查并升级 gd-cli
85
-
86
- 常用流程:
87
- gd-cli auth login 登录稿定账号
88
- gd-cli org list 查看可用组织
89
- gd-cli org switch 切换当前组织
90
- gd-cli workflows list 查看完整创意场景
91
- gd-cli tools list 查看单项 AI 创意能力
92
- gd-cli dam upload ./image.png 上传素材到 DAM
93
-
94
- 常用选项:
95
- -V, --version output the version number
96
- -f, --format <format> 输出格式: human / table / json / text
97
- --json 等同于 --format json,推荐 Agent 和脚本使用
98
- --no-input 禁止交互,适合 CI / Agent
99
- --yes 跳过确认
100
- -h, --help display help for command
101
-
102
- 更多:
103
- gd-cli examples 查看常用场景示例
104
- gd-cli manifest 可解析的能力清单
105
- `;
106
- const AGENT_HELP = `
107
- Agent 推荐入口:
108
- gd-cli manifest --format json 读取完整能力清单
109
- gd-cli workflows manifest --format json 读取 Workflows 清单
110
- gd-cli tools manifest --format json 读取 Tools 清单
111
- gd-cli workflows schema <workflow-id> --format json 查看 Workflow 输入/输出结构
112
- gd-cli tools schema <tool-id> --format json 查看 Tool 输入/输出结构
113
-
114
- 调用规则:
115
- 1. 优先用 --format json 或 --json。
116
- 2. 复杂输入用 --input <json-file> 或 stdin: cat input.json | gd-cli tools call <tool-id> - --json。
117
- 3. 完整业务场景优先选 workflows;单项能力选 tools;素材复用选 dam。
118
- 4. Agent 不切换模型、环境或组织;这些由 CLI 配置和用户显式命令管理。
119
- `;
120
- function resolveExplicitExamplesFormat(command) {
121
- const root = command.parent;
122
- const opts = (root?.opts() ?? {});
123
- if (opts.json)
124
- return "json";
125
- const source = root?.getOptionValueSource("format");
126
- return source && source !== "default" && source !== "implied"
127
- ? opts.format ?? "human"
128
- : "human";
129
- }
130
- function printExamples(payload) {
131
- const examples = Array.isArray(payload.examples) ? payload.examples : [];
132
- console.log("常用场景示例\n");
133
- examples.forEach((item, index) => {
134
- const record = item;
135
- console.log(`${index + 1}. ${String(record.title ?? "")}`);
136
- const description = record.description;
137
- if (typeof description === "string" && description.trim()) {
138
- console.log(` ${description.trim()}`);
34
+ export async function parseProgram(program, argv = process.argv) {
35
+ const userArgs = argv.slice(2);
36
+ const jsonLeaf = resolveExplicitJsonLeaf(program, userArgs);
37
+ const capturedErrors = [];
38
+ const configuredCommands = allCommands(program).map((command) => {
39
+ const output = command.configureOutput();
40
+ const writeErr = output.writeErr ?? ((text) => process.stderr.write(text));
41
+ command.configureOutput({
42
+ writeErr: (text) => capturedErrors.push({ text, write: writeErr }),
43
+ });
44
+ command.exitOverride();
45
+ return { command, writeErr };
46
+ });
47
+ let actionStarted = false;
48
+ program.hook("preAction", () => {
49
+ actionStarted = true;
50
+ });
51
+ try {
52
+ await program.parseAsync([...argv]);
53
+ }
54
+ catch (error) {
55
+ if (error instanceof CommanderError && error.exitCode === 0)
56
+ return;
57
+ if (!actionStarted && jsonLeaf) {
58
+ emitJsonFailure(jsonLeaf, parseFailure(error, jsonLeaf));
59
+ process.exitCode = error instanceof CommanderError
60
+ ? Math.max(1, error.exitCode)
61
+ : 1;
62
+ return;
63
+ }
64
+ for (const captured of capturedErrors)
65
+ captured.write(captured.text);
66
+ if (error instanceof CommanderError) {
67
+ process.exitCode = error.exitCode;
68
+ return;
69
+ }
70
+ throw error;
71
+ }
72
+ finally {
73
+ for (const { command, writeErr } of configuredCommands) {
74
+ command.configureOutput({ writeErr });
139
75
  }
140
- console.log("");
141
- console.log(` ${String(record.command ?? "")}`);
142
- const input = record.input_json;
143
- if (input && typeof input === "object" && Object.keys(input).length > 0) {
144
- console.log("");
145
- console.log(" input_json:");
146
- for (const [key, value] of Object.entries(input)) {
147
- console.log(` ${key}: ${String(value)}`);
76
+ }
77
+ }
78
+ function resolveExplicitJsonLeaf(program, args) {
79
+ let current = program;
80
+ let index = 0;
81
+ let commandIndex = -1;
82
+ while (current.commands.length > 0) {
83
+ let nextCommand;
84
+ while (index < args.length) {
85
+ const token = args[index];
86
+ if (token === "--")
87
+ return undefined;
88
+ if (token.startsWith("-")) {
89
+ index += optionWidth(current, args, index);
90
+ continue;
148
91
  }
92
+ nextCommand = current.commands.find((candidate) => candidate.name() === token || candidate.aliases().includes(token));
93
+ if (!nextCommand)
94
+ return undefined;
95
+ commandIndex = index;
96
+ index += 1;
97
+ break;
149
98
  }
150
- console.log("");
99
+ if (!nextCommand)
100
+ return undefined;
101
+ current = nextCommand;
102
+ }
103
+ if (commandIndex < 0 ||
104
+ !current.options.some((option) => option.long === "--json")) {
105
+ return undefined;
106
+ }
107
+ return hasExplicitJsonOption(current, args.slice(commandIndex + 1))
108
+ ? current
109
+ : undefined;
110
+ }
111
+ function hasExplicitJsonOption(command, args) {
112
+ for (let index = 0; index < args.length;) {
113
+ const token = args[index];
114
+ if (token === "--")
115
+ return false;
116
+ if (token === "--json")
117
+ return true;
118
+ index += optionWidth(command, args, index);
119
+ }
120
+ return false;
121
+ }
122
+ function optionWidth(command, args, index) {
123
+ const token = args[index];
124
+ const flag = token.includes("=") ? token.slice(0, token.indexOf("=")) : token;
125
+ const option = command.options.find((candidate) => candidate.long === flag || candidate.short === flag);
126
+ if (!option || token.includes("="))
127
+ return 1;
128
+ if (option.required)
129
+ return index + 1 < args.length ? 2 : 1;
130
+ if (option.optional &&
131
+ index + 1 < args.length &&
132
+ !args[index + 1].startsWith("-")) {
133
+ return 2;
134
+ }
135
+ return 1;
136
+ }
137
+ function parseFailure(error, command) {
138
+ const missingCodes = new Set([
139
+ "commander.missingArgument",
140
+ "commander.optionMissingArgument",
141
+ "commander.missingMandatoryOptionValue",
142
+ ]);
143
+ const code = error instanceof CommanderError && missingCodes.has(error.code)
144
+ ? "PARAM_MISSING"
145
+ : "PARAM_INVALID";
146
+ const rawMessage = error instanceof Error ? error.message : String(error);
147
+ const message = rawMessage.replace(/^error:\s*/i, "").trim() || "参数不合法";
148
+ return new CliUsageError({
149
+ code,
150
+ type: "validation",
151
+ message,
152
+ hint: `运行 gd-cli ${publicCommandName(command)} --help 查看参数说明。`,
153
+ retryable: false,
151
154
  });
152
155
  }
156
+ function publicCommandName(command) {
157
+ const names = [];
158
+ let current = command;
159
+ while (current.parent) {
160
+ names.unshift(current.name());
161
+ current = current.parent;
162
+ }
163
+ return names.join(" ");
164
+ }
165
+ function allCommands(root) {
166
+ return [root, ...root.commands.flatMap(allCommands)];
167
+ }
@@ -1,43 +1,23 @@
1
- import type { OutputSpec, ParamSpec } from "./types.js";
2
- import { type CapabilityPolicy, type CapabilitySource, type CapabilityStatus } from "../utils/capability-metadata.js";
3
- type CapabilityKind = "workflow" | "tool";
4
- type ManifestScope = "all" | "workflows" | "tools";
1
+ import type { ParamSpec } from "./types.js";
2
+ export declare const PUBLIC_WORKFLOW_MEDIA_PATTERN = "^kv_\\d+_\\d+$";
3
+ export interface PublicWorkflowOutputDefinition {
4
+ textFields: readonly string[];
5
+ mediaFields: readonly string[];
6
+ overlayFields: readonly string[];
7
+ ratioFields: readonly string[];
8
+ ratios: "record" | "array";
9
+ sellingPoints?: boolean;
10
+ mediaPattern?: string;
11
+ }
5
12
  export interface JsonSchemaObject {
6
13
  type: "object";
7
14
  properties: Record<string, Record<string, unknown>>;
8
15
  required: string[];
9
16
  additionalProperties?: boolean;
10
- }
11
- export interface CapabilityManifestCommand {
12
- id: string;
13
- type: CapabilityKind | "dam" | "org";
14
- category: string;
15
- title: string;
16
- description: string;
17
- canonical_command: string;
18
- input_schema_command?: string;
19
- examples_command?: string;
20
- output: "json";
21
- safe_for_agent: boolean;
22
- source: CapabilitySource;
23
- status: CapabilityStatus;
24
- policy: CapabilityPolicy;
25
- dependency_tools?: string[];
26
- affected_workflows?: string[];
27
- }
28
- export interface CapabilityManifest {
29
- name: "gd-cli";
30
- version: string;
31
- description: string;
32
- commands: CapabilityManifestCommand[];
17
+ patternProperties?: Record<string, Record<string, unknown>>;
33
18
  }
34
19
  export declare function buildInputJsonSchema(params: ParamSpec[], extraProperties?: Record<string, Record<string, unknown>>): JsonSchemaObject;
35
- export declare function buildOutputJsonSchema(output: OutputSpec): JsonSchemaObject;
36
- export declare function buildToolSchema(toolId: string): Record<string, unknown>;
20
+ export declare function resolvePublicWorkflowOutputDefinition(appId: string): PublicWorkflowOutputDefinition;
21
+ export declare function buildOutputJsonSchema(appId: string): JsonSchemaObject;
37
22
  export declare function buildWorkflowSchema(appId: string): Record<string, unknown>;
38
- export declare function buildToolExamples(toolId: string): Record<string, unknown>;
39
23
  export declare function buildWorkflowExamples(appId: string): Record<string, unknown>;
40
- export declare function buildManifest(scope?: ManifestScope): CapabilityManifest;
41
- export declare function rowsForManifest(manifest: CapabilityManifest): Record<string, string>[];
42
- export declare function buildTopExamples(): Record<string, unknown>;
43
- export {};