@gaoding/cli 0.0.0 → 1.0.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 (136) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -3
  3. package/contracts/operations/agent.send/input.schema.json +353 -0
  4. package/contracts/operations/agent.send/output.schema.json +271 -0
  5. package/contracts/operations/auth.status/input.schema.json +7 -0
  6. package/contracts/operations/auth.status/output.schema.json +132 -0
  7. package/contracts/operations/dam.copy/input.schema.json +19 -0
  8. package/contracts/operations/dam.copy/output.schema.json +19 -0
  9. package/contracts/operations/dam.delete/input.schema.json +23 -0
  10. package/contracts/operations/dam.delete/output.schema.json +6 -0
  11. package/contracts/operations/dam.download/input.schema.json +14 -0
  12. package/contracts/operations/dam.download/output.schema.json +25 -0
  13. package/contracts/operations/dam.folder.list/input.schema.json +15 -0
  14. package/contracts/operations/dam.folder.list/output.schema.json +37 -0
  15. package/contracts/operations/dam.get/input.schema.json +16 -0
  16. package/contracts/operations/dam.get/output.schema.json +46 -0
  17. package/contracts/operations/dam.list/input.schema.json +44 -0
  18. package/contracts/operations/dam.list/output.schema.json +71 -0
  19. package/contracts/operations/dam.move/input.schema.json +19 -0
  20. package/contracts/operations/dam.move/output.schema.json +18 -0
  21. package/contracts/operations/dam.recycle.list/input.schema.json +13 -0
  22. package/contracts/operations/dam.recycle.list/output.schema.json +34 -0
  23. package/contracts/operations/dam.recycle.restore/input.schema.json +14 -0
  24. package/contracts/operations/dam.recycle.restore/output.schema.json +6 -0
  25. package/contracts/operations/dam.rename/input.schema.json +18 -0
  26. package/contracts/operations/dam.rename/output.schema.json +18 -0
  27. package/contracts/operations/dam.repository.list/input.schema.json +8 -0
  28. package/contracts/operations/dam.repository.list/output.schema.json +52 -0
  29. package/contracts/operations/dam.search/input.schema.json +46 -0
  30. package/contracts/operations/dam.search/output.schema.json +71 -0
  31. package/contracts/operations/dam.tag.list/input.schema.json +12 -0
  32. package/contracts/operations/dam.tag.list/output.schema.json +26 -0
  33. package/contracts/operations/dam.upload/input.schema.json +31 -0
  34. package/contracts/operations/dam.upload/output.schema.json +46 -0
  35. package/contracts/operations/editor.apply/input.schema.json +134 -0
  36. package/contracts/operations/editor.apply/output.schema.json +15 -0
  37. package/contracts/operations/editor.connect/input.schema.json +15 -0
  38. package/contracts/operations/editor.connect/output.schema.json +17 -0
  39. package/contracts/operations/editor.disconnect/input.schema.json +8 -0
  40. package/contracts/operations/editor.disconnect/output.schema.json +14 -0
  41. package/contracts/operations/editor.save/input.schema.json +8 -0
  42. package/contracts/operations/editor.save/output.schema.json +23 -0
  43. package/contracts/operations/editor.screenshot/input.schema.json +8 -0
  44. package/contracts/operations/editor.screenshot/output.schema.json +16 -0
  45. package/contracts/operations/editor.snapshot/input.schema.json +8 -0
  46. package/contracts/operations/editor.snapshot/output.schema.json +113 -0
  47. package/contracts/operations/model.get/input.schema.json +18 -0
  48. package/contracts/operations/model.get/output.schema.json +191 -0
  49. package/contracts/operations/model.list/input.schema.json +15 -0
  50. package/contracts/operations/model.list/output.schema.json +111 -0
  51. package/contracts/operations/org.current/input.schema.json +7 -0
  52. package/contracts/operations/org.current/output.schema.json +49 -0
  53. package/contracts/operations/org.list/input.schema.json +7 -0
  54. package/contracts/operations/org.list/output.schema.json +71 -0
  55. package/contracts/operations/tool.call/input.schema.json +35 -0
  56. package/contracts/operations/tool.call/output.schema.json +129 -0
  57. package/contracts/operations/tool.list/input.schema.json +7 -0
  58. package/contracts/operations/tool.list/output.schema.json +45 -0
  59. package/dist/bin/gd-cli.js +60 -0
  60. package/dist/bin/postinstall.js +42 -0
  61. package/dist/src/bootstrap/create-cli.js +112 -0
  62. package/dist/src/bootstrap/create-runtime.js +290 -0
  63. package/dist/src/bootstrap/validators.js +157 -0
  64. package/dist/src/cli/action-binding.js +109 -0
  65. package/dist/src/cli/agent-commands.js +49 -0
  66. package/dist/src/cli/auth-commands.js +55 -0
  67. package/dist/src/cli/dam-commands.js +469 -0
  68. package/dist/src/cli/editor-commands.js +73 -0
  69. package/dist/src/cli/errors.js +157 -0
  70. package/dist/src/cli/model-commands.js +61 -0
  71. package/dist/src/cli/org-commands.js +58 -0
  72. package/dist/src/cli/presenter.js +105 -0
  73. package/dist/src/cli/prompt.js +30 -0
  74. package/dist/src/cli/tool-commands.js +77 -0
  75. package/dist/src/cli/update-command.js +14 -0
  76. package/dist/src/contracts/schema.js +4 -0
  77. package/dist/src/features/agent/creative-agent-adapter.js +36 -0
  78. package/dist/src/features/agent/creative-protocol.js +432 -0
  79. package/dist/src/features/agent/creative-stream.js +127 -0
  80. package/dist/src/features/agent/use-cases.js +150 -0
  81. package/dist/src/features/auth/access-policy.js +101 -0
  82. package/dist/src/features/auth/credential-store.js +62 -0
  83. package/dist/src/features/auth/sso-service.js +194 -0
  84. package/dist/src/features/auth/state.js +129 -0
  85. package/dist/src/features/auth/use-cases.js +136 -0
  86. package/dist/src/features/dam/asset-projection.js +278 -0
  87. package/dist/src/features/dam/dam-api-adapter.js +562 -0
  88. package/dist/src/features/dam/file-downloader.js +242 -0
  89. package/dist/src/features/dam/object-storage.js +193 -0
  90. package/dist/src/features/dam/operation-executor.js +72 -0
  91. package/dist/src/features/dam/registered-uploader.js +247 -0
  92. package/dist/src/features/dam/repository-catalog.js +127 -0
  93. package/dist/src/features/dam/storage-upload.js +141 -0
  94. package/dist/src/features/dam/transient-uploader.js +17 -0
  95. package/dist/src/features/dam/use-cases.js +470 -0
  96. package/dist/src/features/editor/bridge-client.js +109 -0
  97. package/dist/src/features/editor/bridge-process.js +222 -0
  98. package/dist/src/features/editor/bridge-server.js +337 -0
  99. package/dist/src/features/editor/protocol.js +1 -0
  100. package/dist/src/features/editor/public-url.js +36 -0
  101. package/dist/src/features/editor/session-state.js +78 -0
  102. package/dist/src/features/editor/session.js +207 -0
  103. package/dist/src/features/editor/use-cases.js +88 -0
  104. package/dist/src/features/org/org-service.js +76 -0
  105. package/dist/src/features/org/use-cases.js +156 -0
  106. package/dist/src/features/skill/bundled-skills.js +55 -0
  107. package/dist/src/features/skill/installer.js +271 -0
  108. package/dist/src/features/tool/catalog.js +83 -0
  109. package/dist/src/features/tool/dynamic-schema.js +128 -0
  110. package/dist/src/features/tool/mns-catalog-adapter.js +265 -0
  111. package/dist/src/features/tool/tool-api-adapter.js +352 -0
  112. package/dist/src/features/tool/use-cases.js +177 -0
  113. package/dist/src/features/update/latest-version.js +37 -0
  114. package/dist/src/features/update/update-notification.js +262 -0
  115. package/dist/src/features/update/update-service.js +183 -0
  116. package/dist/src/platform/json-input.js +67 -0
  117. package/dist/src/platform/local-json-file.js +59 -0
  118. package/dist/src/platform/open-browser.js +8 -0
  119. package/dist/src/platform/redact.js +80 -0
  120. package/dist/src/platform/remote-error-evidence.js +80 -0
  121. package/dist/src/platform/remote-protocol.js +10 -0
  122. package/dist/src/platform/safe-upload-file.js +146 -0
  123. package/dist/src/platform/signature.js +20 -0
  124. package/dist/src/platform/signed-http-transport.js +143 -0
  125. package/dist/src/platform/url-safety.js +100 -0
  126. package/dist/src/telemetry/invocation.js +156 -0
  127. package/dist/src/telemetry/sls-sink.js +31 -0
  128. package/package.json +54 -8
  129. package/skills/gd-cli/SKILL.md +15 -0
  130. package/skills/gd-cli/references/auth-org.md +9 -0
  131. package/skills/gd-cli/references/creation.md +115 -0
  132. package/skills/gd-cli/references/dam.md +52 -0
  133. package/skills/gd-cli/references/editor.md +254 -0
  134. package/skills/gd-cli/references/errors.md +13 -0
  135. package/skills/gd-cli/references/update.md +13 -0
  136. package/index.js +0 -3
@@ -0,0 +1,100 @@
1
+ import { isIP } from "node:net";
2
+ export class UrlSafetyError extends Error {
3
+ constructor() {
4
+ super("URL 不可用于远程素材。");
5
+ this.name = "UrlSafetyError";
6
+ }
7
+ }
8
+ function fail() {
9
+ throw new UrlSafetyError();
10
+ }
11
+ function parseIpv4(hostname) {
12
+ if (isIP(hostname) !== 4)
13
+ return null;
14
+ return hostname.split(".").map(Number);
15
+ }
16
+ function isPrivateIpv4(parts) {
17
+ const first = parts[0] ?? -1;
18
+ const second = parts[1] ?? -1;
19
+ return first === 0
20
+ || first === 10
21
+ || first === 127
22
+ || (first === 169 && second === 254)
23
+ || (first === 172 && second >= 16 && second <= 31)
24
+ || (first === 192 && second === 168);
25
+ }
26
+ function expandIpv6(hostname) {
27
+ if (isIP(hostname) !== 6)
28
+ return null;
29
+ const [left = "", right = "", ...rest] = hostname.split("::");
30
+ if (rest.length > 0)
31
+ return null;
32
+ const leftParts = left === "" ? [] : left.split(":");
33
+ const rightParts = right === "" ? [] : right.split(":");
34
+ const missing = 8 - leftParts.length - rightParts.length;
35
+ if (!hostname.includes("::") && missing !== 0)
36
+ return null;
37
+ if (hostname.includes("::") && missing < 1)
38
+ return null;
39
+ const values = [
40
+ ...leftParts,
41
+ ...Array.from({ length: missing }, () => "0"),
42
+ ...rightParts
43
+ ].map((part) => Number.parseInt(part, 16));
44
+ return values.length === 8 && values.every((part) => Number.isInteger(part))
45
+ ? values
46
+ : null;
47
+ }
48
+ function isPrivateIpv6(parts) {
49
+ const first = parts[0] ?? -1;
50
+ const unspecified = parts.every((part) => part === 0);
51
+ const loopback = parts.slice(0, 7).every((part) => part === 0) && parts[7] === 1;
52
+ const uniqueLocal = (first & 0xfe00) === 0xfc00;
53
+ const linkLocal = (first & 0xffc0) === 0xfe80;
54
+ const mappedIpv4 = parts.slice(0, 5).every((part) => part === 0)
55
+ && parts[5] === 0xffff;
56
+ if (mappedIpv4) {
57
+ const high = parts[6] ?? 0;
58
+ const low = parts[7] ?? 0;
59
+ return isPrivateIpv4([
60
+ high >> 8,
61
+ high & 0xff,
62
+ low >> 8,
63
+ low & 0xff
64
+ ]);
65
+ }
66
+ return unspecified || loopback || uniqueLocal || linkLocal;
67
+ }
68
+ export function parseSafeRemoteAssetUrl(value) {
69
+ let url;
70
+ try {
71
+ url = new URL(value);
72
+ }
73
+ catch {
74
+ return fail();
75
+ }
76
+ if ((url.protocol !== "http:" && url.protocol !== "https:")
77
+ || url.username !== ""
78
+ || url.password !== "") {
79
+ return fail();
80
+ }
81
+ const hostname = url.hostname
82
+ .replace(/^\[|\]$/g, "")
83
+ .replace(/[.]+$/, "")
84
+ .toLowerCase();
85
+ if (hostname === "localhost"
86
+ || hostname.endsWith(".localhost")
87
+ || hostname.endsWith(".local")
88
+ || hostname === "metadata"
89
+ || hostname === "metadata.google.internal"
90
+ || hostname === "169.254.169.254") {
91
+ return fail();
92
+ }
93
+ const ipv4 = parseIpv4(hostname);
94
+ if (ipv4 !== null && isPrivateIpv4(ipv4))
95
+ return fail();
96
+ const ipv6 = expandIpv6(hostname);
97
+ if (ipv6 !== null && isPrivateIpv6(ipv6))
98
+ return fail();
99
+ return url;
100
+ }
@@ -0,0 +1,156 @@
1
+ const detailedStages = {
2
+ "auth.login": new Set(["authorize", "wait", "identity", "bind"]),
3
+ "org.switch": new Set(["list", "bind"]),
4
+ "agent.send:execute": new Set(["catalog", "upload", "execute", "result"]),
5
+ "tool.call:execute": new Set(["catalog", "upload", "intent", "submit", "wait"]),
6
+ "dam.upload": new Set(["inspect", "repository", "prepare", "upload", "persist", "wait"]),
7
+ update: new Set(["registry", "install", "sync", "verify"])
8
+ };
9
+ export function createTelemetryInvocation(options) {
10
+ const traceId = options.traceIdFactory();
11
+ const startedAt = options.now();
12
+ let definition;
13
+ const context = {};
14
+ const stages = [];
15
+ return {
16
+ traceId,
17
+ get selected() {
18
+ return definition !== undefined;
19
+ },
20
+ traceparent() {
21
+ return `00-${traceId}-${options.spanIdFactory()}-${traceFlags(definition)}`;
22
+ },
23
+ select(nextDefinition) {
24
+ definition = nextDefinition;
25
+ },
26
+ annotate(annotation) {
27
+ if (annotation.account_id !== undefined)
28
+ context.account_id = annotation.account_id;
29
+ if (annotation.organization_id !== undefined) {
30
+ context.organization_id = annotation.organization_id;
31
+ }
32
+ if (annotation.tool_name !== undefined)
33
+ context.tool_name = annotation.tool_name;
34
+ if (annotation.model_id !== undefined)
35
+ context.model_id = annotation.model_id;
36
+ if (annotation.content_id !== undefined)
37
+ context.content_id = annotation.content_id;
38
+ if (annotation.task_id !== undefined)
39
+ context.task_id = annotation.task_id;
40
+ if (annotation.dify_task_id !== undefined) {
41
+ context.dify_task_id = annotation.dify_task_id;
42
+ }
43
+ if (annotation.parameters !== undefined) {
44
+ context.parameters = { ...annotation.parameters };
45
+ }
46
+ },
47
+ async stage(name, run) {
48
+ const stageStartedAt = options.now();
49
+ try {
50
+ const result = await run();
51
+ stages.push({
52
+ name,
53
+ durationMs: elapsed(options.now(), stageStartedAt),
54
+ outcome: "success"
55
+ });
56
+ return result;
57
+ }
58
+ catch (error) {
59
+ const classification = options.classifyError(error);
60
+ stages.push({
61
+ name,
62
+ durationMs: elapsed(options.now(), stageStartedAt),
63
+ outcome: classification.outcome,
64
+ error,
65
+ ...(classification.errorCode === undefined
66
+ ? {}
67
+ : { errorCode: classification.errorCode }),
68
+ ...(classification.httpStatus === undefined
69
+ ? {}
70
+ : { httpStatus: classification.httpStatus })
71
+ });
72
+ throw error;
73
+ }
74
+ },
75
+ finish(completion) {
76
+ if (!definition)
77
+ return [];
78
+ const selectedDefinition = definition;
79
+ const mode = selectedDefinition.mode?.();
80
+ const allowedStages = detailedStages[stageKey(selectedDefinition.operation, mode)];
81
+ const stageEvents = allowedStages
82
+ ? stages
83
+ .filter((stage) => allowedStages.has(stage.name))
84
+ .map((stage) => ({
85
+ schema_version: "2",
86
+ event_name: "stage_finished",
87
+ trace_id: traceId,
88
+ operation: selectedDefinition.operation,
89
+ stage: stage.name,
90
+ outcome: stage.outcome,
91
+ duration_ms: stage.durationMs,
92
+ ...(stage.errorCode === undefined ? {} : { error_code: stage.errorCode }),
93
+ ...(stage.httpStatus === undefined ? {} : { http_status: stage.httpStatus })
94
+ }))
95
+ : [];
96
+ const command = {
97
+ schema_version: "2",
98
+ event_name: "command_finished",
99
+ trace_id: traceId,
100
+ operation: selectedDefinition.operation,
101
+ ...(mode === undefined ? {} : { mode }),
102
+ outcome: completion.outcome,
103
+ duration_ms: elapsed(options.now(), startedAt),
104
+ cli_version: options.cliVersion,
105
+ os: options.runtime.os,
106
+ arch: options.runtime.arch,
107
+ node_major: options.runtime.nodeMajor,
108
+ ...(context.account_id === undefined ? {} : { account_id: context.account_id }),
109
+ ...(context.organization_id === undefined
110
+ ? {}
111
+ : { organization_id: context.organization_id }),
112
+ ...(context.tool_name === undefined ? {} : { tool_name: context.tool_name }),
113
+ ...(context.model_id === undefined ? {} : { model_id: context.model_id }),
114
+ ...(context.content_id === undefined ? {} : { content_id: context.content_id }),
115
+ ...(context.task_id === undefined ? {} : { task_id: context.task_id }),
116
+ ...(context.dify_task_id === undefined
117
+ ? {}
118
+ : { dify_task_id: context.dify_task_id }),
119
+ ...(context.parameters === undefined
120
+ ? {}
121
+ : { parameters: { ...context.parameters } }),
122
+ ...(completion.outcome === "failure"
123
+ ? {
124
+ error_code: completion.errorCode,
125
+ error_message: completion.errorMessage,
126
+ failure_stage: stages.find((stage) => stage.error === completion.error)?.name
127
+ ?? "unknown",
128
+ ...(completion.httpStatus === undefined
129
+ ? {}
130
+ : { http_status: completion.httpStatus }),
131
+ ...(completion.remoteErrorCode === undefined
132
+ ? {}
133
+ : { remote_error_code: completion.remoteErrorCode }),
134
+ ...(completion.remoteErrorBody === undefined
135
+ ? {}
136
+ : { remote_error_body: completion.remoteErrorBody })
137
+ }
138
+ : {})
139
+ };
140
+ return [...stageEvents, command];
141
+ }
142
+ };
143
+ }
144
+ function traceFlags(definition) {
145
+ if (definition === undefined)
146
+ return "00";
147
+ const paidExecution = (definition.operation === "agent.send"
148
+ || definition.operation === "tool.call") && definition.mode?.() === "execute";
149
+ return paidExecution ? "01" : "00";
150
+ }
151
+ function stageKey(operation, mode) {
152
+ return mode === undefined ? operation : `${operation}:${mode}`;
153
+ }
154
+ function elapsed(now, startedAt) {
155
+ return Math.max(0, now - startedAt);
156
+ }
@@ -0,0 +1,31 @@
1
+ const trackingUrl = new URL("https://gaoding-log-ai-gpu.cn-hangzhou.log.aliyuncs.com/logstores/gd-cli/track?APIVersion=0.6.0");
2
+ const TIMEOUT_MS = 2_000;
3
+ export function createSlsTelemetrySink(options) {
4
+ return {
5
+ async send(events) {
6
+ if (events.length === 0)
7
+ return;
8
+ try {
9
+ await options.fetch(trackingUrl, {
10
+ method: "POST",
11
+ headers: { "Content-Type": "application/json" },
12
+ body: JSON.stringify({ __logs__: events.map(wireEvent) }),
13
+ redirect: "error",
14
+ signal: AbortSignal.timeout(TIMEOUT_MS)
15
+ });
16
+ }
17
+ catch {
18
+ // Telemetry must never change command behavior.
19
+ }
20
+ }
21
+ };
22
+ }
23
+ function wireEvent(event) {
24
+ const wire = {};
25
+ for (const [key, value] of Object.entries(event)) {
26
+ if (value === undefined)
27
+ continue;
28
+ wire[key] = key === "parameters" ? JSON.stringify(value) : String(value);
29
+ }
30
+ return wire;
31
+ }
package/package.json CHANGED
@@ -1,16 +1,62 @@
1
1
  {
2
2
  "name": "@gaoding/cli",
3
- "version": "0.0.0",
4
- "description": "Placeholder package for the Gaoding CLI.",
5
- "main": "index.js",
3
+ "version": "1.0.0",
4
+ "description": "Gaoding command-line interface for agents and people.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "publishConfig": {
8
+ "access": "public",
9
+ "registry": "https://registry.npmjs.org/",
10
+ "tag": "latest"
11
+ },
12
+ "engines": {
13
+ "node": ">=20.0.0"
14
+ },
15
+ "bin": {
16
+ "gd-cli": "dist/bin/gd-cli.js"
17
+ },
6
18
  "files": [
7
- "index.js"
19
+ "contracts",
20
+ "dist",
21
+ "skills",
22
+ "README.md",
23
+ "LICENSE"
8
24
  ],
9
25
  "scripts": {
10
- "test": "node -e \"require('./index.js')\""
26
+ "contracts:build": "pnpm --filter @gaoding/gd-connector-contracts build",
27
+ "clean": "node -e \"for (const p of ['contracts', 'dist']) require('node:fs').rmSync(p, { recursive: true, force: true })\"",
28
+ "bundle:contracts": "node scripts/bundle-contracts.mjs",
29
+ "build": "pnpm contracts:build && pnpm clean && tsc -p tsconfig.build.json && pnpm bundle:contracts",
30
+ "test": "pnpm contracts:build && vitest run",
31
+ "typecheck": "pnpm contracts:build && tsc -p tsconfig.json",
32
+ "check": "pnpm contracts:build && vitest run && tsc -p tsconfig.json && pnpm clean && tsc -p tsconfig.build.json && pnpm bundle:contracts",
33
+ "prepack": "pnpm check",
34
+ "postinstall": "node -e \"const p='./dist/bin/postinstall.js'; if (require('node:fs').existsSync(p)) import(p)\""
11
35
  },
12
- "publishConfig": {
13
- "access": "public"
36
+ "dependencies": {
37
+ "ajv": "8.20.0",
38
+ "ajv-formats": "3.0.1",
39
+ "ali-oss": "6.23.0",
40
+ "commander": "14.0.3",
41
+ "open": "11.0.0",
42
+ "qrcode": "1.5.4",
43
+ "semver": "7.8.5",
44
+ "sharp": "0.35.3",
45
+ "ws": "8.21.1"
46
+ },
47
+ "devDependencies": {
48
+ "@gaoding/gd-connector-contracts": "workspace:*",
49
+ "@types/ali-oss": "6.23.3",
50
+ "@types/node": "24.13.3",
51
+ "@types/qrcode": "1.5.6",
52
+ "@types/semver": "7.7.1",
53
+ "@types/ws": "8.18.1",
54
+ "typescript": "7.0.2",
55
+ "vitest": "4.1.10"
14
56
  },
15
- "license": "UNLICENSED"
57
+ "gaodingRelease": {
58
+ "sourceCommit": "10a20a2c28b2eb959b8b62dbe692c6a54ec94b3f",
59
+ "pipelineId": "168684",
60
+ "pipelineUrl": "https://git.intra.gaoding.com/gtt/gaoding-cli/-/pipelines/168684"
61
+ }
16
62
  }
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: gd-cli
3
+ description: Use when creating images, videos or text with GD CLI, operating the focused Gaoding editor, or managing Gaoding DAM assets.
4
+ ---
5
+
6
+ # GD CLI
7
+
8
+ 按用户目标只读取对应参考:
9
+
10
+ - 按业务意图选择 Agent / Tool 创作路由、发现 Model 并生成图片、视频或文本:[创作](references/creation.md)
11
+ - 操作当前 AI+ Editor 作品:[编辑器](references/editor.md)
12
+ - 发现资源库、文件夹与标签,查询、上传、下载或单条目管理 DAM 资源:[素材管理](references/dam.md)
13
+ - 登录或选择组织:[登录与组织](references/auth-org.md)
14
+ - 处理输出、警告、失败或中断:[错误处理](references/errors.md)
15
+ - 更新 CLI 与随包 Agent Skill:[更新](references/update.md)
@@ -0,0 +1,9 @@
1
+ # 登录与组织
2
+
3
+ 1. 用 `gd-cli auth status` 检查登录状态;需要机器读取时使用 `--json`。
4
+ 2. 未登录时执行 `gd-cli auth login`,按终端提示在浏览器完成授权;无法自动打开浏览器时使用 `--no-browser`。
5
+ 3. 用 `gd-cli org list` 查看当前账号可用的组织,用 `gd-cli org current` 查看当前选择。
6
+ 4. 让用户从真实列表中选择,再执行 `gd-cli org switch --org <org-id>`;不要猜组织 ID。
7
+ 5. 用户要求退出或登录状态失效时执行 `gd-cli auth logout`;状态失效后重新登录。
8
+
9
+ 不要向用户索要或回显 Bearer Token、Cookie、AK、SK 或签名。组织不可用时先切换组织;仍无法恢复时退出后重新登录。
@@ -0,0 +1,115 @@
1
+ # 创作
2
+
3
+ ## Creation Route
4
+
5
+ 先判断 Creation Route,再选择或校验 Model。Model 和参数不决定 Agent 或 Tool 路由;两条路由都支持指定 Model 及其参数,`model list` 和 `model get` 是共享的实时发现能力。
6
+
7
+ - Agent:用户要的是业务交付物,或过程需要澄清、规划、多步骤、多产物或继续已有创作。下列十类业务意图通常优先走 Agent;它们只帮助选择 Creation Route,具体 Business Skill 由服务端 Agent 选择。
8
+ - Tool:任务是一个无需业务编排的原子单次图片、视频或文本调用,或用户明确要求直接调用 Tool。
9
+
10
+ 业务意图参考(语义匹配,不是只能逐字命中):
11
+
12
+ | 业务意图 | 常见说法 | 素材与边界 |
13
+ | --- | --- | --- |
14
+ | 电商主图套图 | 主图、主图套图、一套主图、主图设计、商品图 | 通常带商品图;区分场景图、海报、详情页、改图、包装设计和多角度图 |
15
+ | 电商详情页 | 详情页、电商详情、宝贝详情、产品详情、长图、卖点页、参数页、功能介绍、对比说明、购买理由 | 通常带商品图;出现“详情”类词时优先按电商详情页判断,不按主图套图处理 |
16
+ | 商品精修 | 精修、修一下、翻新、白底图、纯白背景、修复使用痕迹 | 必须提供商品实物图;加文字、去水印、抠图、局部编辑、海报、套版和仿图不按商品精修判断 |
17
+ | 电商模特 | 模特、试穿、上身、穿戴、佩戴、换模特、换姿势、换背景 | 商品图可选;没有商品图时可以生成纯模特 |
18
+ | 商品场景图 | 生成场景、换场景、换个背景、整合到一张图+背景 | 必须提供商品实物图;人像、风景和设计稿不算商品图,带卖点文字的主图不按商品场景图判断 |
19
+ | 主题照 | 主题照、写真、风格人像 | 人像图可选 |
20
+ | 形象照 | 形象照、职业照 | 人像图可选 |
21
+ | 证件照 | 证件照、报名照、头像照,包括换底色和改尺寸 | 人像图可选 |
22
+ | 电商图片提示词 | 写电商图片提示词、产品主图提示词 | 服务端按当前组织的 Business Skill 可用性处理 |
23
+ | 电商视频提示词 | 电商视频提示词、带货视频、产品宣传视频 | 服务端按当前组织的 Business Skill 可用性处理 |
24
+
25
+ 这些参考不在 CLI 选择具体 Business Skill,也不代替服务端实时可用性。业务意图成立但缺少必需素材时,仍使用 Agent 并请用户提供素材;不要因此降级为 Tool。指定 Model、分辨率、比例、时长等参数也不改变路由。
26
+
27
+ 状态映射:原“商品白底图”Business Skill 已下线,白底图或纯白背景需求按商品精修意图走 Agent;原“小红书人像封面”Business Skill 已下线,相关种草人像封面需求走 Agent 兜底。状态只解释路由,不表示 CLI 指定了服务端 Skill。
28
+
29
+ 典型判断:
30
+
31
+ - “指定 Model 的电商主图套图”仍使用 Agent,因为目标是业务交付物且可能需要多产物编排。
32
+ - “规划三种风格,再分别生成图片”使用 Agent,因为它包含规划和多步骤。
33
+ - “指定 Model 生成一只猫”使用 Tool,因为它只是原子单次调用,而不是因为指定了 Model。
34
+ - 用户明确要求直接调用某个 Tool 时,使用 Tool。
35
+
36
+ 不猜 Tool 名、Model 名或参数;以当前命令输出为准。用户询问推荐 Model、Model 能力、参数或稿豆价格时,先用 `model list` 筛选,再用 `model get` 核对实时详情。
37
+
38
+ ## Agent 创作
39
+
40
+ 先读取输入规范。需要指定 Model 时,也先读取实时 Model detail:
41
+
42
+ ```bash
43
+ gd-cli agent send --schema
44
+ gd-cli model list --tool <tool>
45
+ gd-cli model get <model>
46
+ gd-cli agent send --input request.json
47
+ ```
48
+
49
+ 将用户要求放在 Text Part。指定 Model 和动态参数时,只增加一个 Generation Constraints Part;`model` 使用 Model 机器标识,`arguments` 的字段和值取自 `model get`,并如实保留用户指定值:
50
+
51
+ ```json
52
+ {
53
+ "message": {
54
+ "parts": [
55
+ { "text": "<用户要求>" },
56
+ {
57
+ "data": {
58
+ "model": "<model>",
59
+ "arguments": {
60
+ "resolution": "2K"
61
+ }
62
+ }
63
+ }
64
+ ]
65
+ }
66
+ }
67
+ ```
68
+
69
+ `arguments` 可以在不指定 `model` 时单独提交,由服务端 Agent 选择 Model。指定 `model` 时,CLI 会按实时 Model detail 校验已提供参数;不要为了 Agent 调用补齐 Tool 的全部 required 字段。Prompt 使用 Text Part,素材使用独立 URL Part,不放入 `arguments`。素材保持消息 Part 的输入顺序;`metadata.role` 可标记 `reference`、`first_frame` 或 `last_frame`,不注入“首帧”或“尾帧”文本。例如:
70
+
71
+ ```json
72
+ {
73
+ "message": {
74
+ "parts": [
75
+ { "text": "生成一段转场视频" },
76
+ { "url": "file:///absolute/first.png", "metadata": { "role": "first_frame" } },
77
+ { "url": "file:///absolute/last.png", "metadata": { "role": "last_frame" } },
78
+ { "data": { "model": "<model>", "arguments": { "mode": "<value>" } } }
79
+ ]
80
+ }
81
+ }
82
+ ```
83
+
84
+ 也可用 `--input -` 从 stdin 读取 JSON。成功结果包含 `message` 和本轮实际稿豆消耗 `usage`;将最终文本、资源、服务端续作标识和实际消耗交付给用户。
85
+
86
+ ## Tool 创作
87
+
88
+ 按顺序执行:
89
+
90
+ ```bash
91
+ gd-cli tool list
92
+ gd-cli model list --tool <tool>
93
+ gd-cli model get <model>
94
+ gd-cli tool call <tool> --input request.json
95
+ ```
96
+
97
+ `tool list` 给出可用 Tool;`model list` 和 `model get` 给出当前可用 Model、说明、费用、预估耗时和结构化参数。`model get` 的 `parameters` 是所选 Model 的实际调用元数据:遵循 `required`、`type`、`description`,SELECT 参数使用 `options[].value`,required 参数带 `default` 时在用户未指定时显式传入默认值。`usageDescription` 描述跨字段规则,例如视频 mode 对首尾帧或素材字段的要求;这类组合不能只从单个字段推断。不要把列表值固化在提示或脚本中。
98
+
99
+ 按所选 Model detail 构造 JSON:提供全部 required 字段;SELECT 参数使用 `options[].value`;required 字段带 default 且用户未指定时,在输入中显式使用该 default。存在 width、height、resolution 等专用字段时,将用户要求写入对应结构化参数,不要只写在 prompt 中。`tool call <tool> --schema` 返回整个 Tool 下所有 Model 的参数并集,只用于 Tool 级发现;选定 Model 后以 `model get` 的参数和 `usageDescription` 为准。
100
+
101
+ 务必将 `model get <model>` 返回的 `model` 原样放在请求 JSON 的顶层 `model` 字段(即运行时的 `arguments.model`),与所选 Model 的参数字段并列;不要只复制 `parameters`。例如:
102
+
103
+ ```json
104
+ {
105
+ "model": "<model>",
106
+ "prompt": "<required prompt>",
107
+ "<parameter>": "<value>"
108
+ }
109
+ ```
110
+
111
+ 成功结果包含 `content` 和 `usage`。`content` 是文本或资源链接;`usage` 包含所选模型及模型目录公布的稿豆价格区间,不表示实际扣费。
112
+
113
+ ## 本地媒体
114
+
115
+ Agent 将本地媒体写成独立 `file://` URL Part;Tool 按所选 Model detail 写入对应媒体参数。CLI 会在内部通过 DAM 完成临时上传并把公网 URL 传给创作服务;不要自行伪造 URL,也不要读取用户未明确授权的路径。
@@ -0,0 +1,52 @@
1
+ # DAM 素材管理
2
+
3
+ ## 先发现,再操作
4
+
5
+ 任何资源库范围内的查询或写入都先运行:
6
+
7
+ ```bash
8
+ gd-cli org current
9
+ gd-cli dam repository list --json
10
+ ```
11
+
12
+ 只使用返回的 `repositories[].repository_id`。团队资源库的 `type` 为 `team`,企业资源库的 `type` 为 `enterprise`;不要使用名称、前端 URL、团队实体 ID 或历史值猜 ID。资源库不做 switch,`org switch` 只切换组织。
13
+
14
+ 需要文件夹或标签 ID 时继续发现:
15
+
16
+ ```bash
17
+ gd-cli dam folder list --repository-id <id> --json
18
+ gd-cli dam tag list --repository-id <id> --json
19
+ ```
20
+
21
+ 文件夹可用 `--parent-id`、`--query`、`--page` 和 `--page-size`;标签可用 `--query`。根文件夹 ID 为 `0`,涉及目标位置时必须显式传 `--target-folder-id 0`,不要把缺省值理解为根目录。
22
+
23
+ ## 查询与下载
24
+
25
+ ```bash
26
+ gd-cli dam list --repository-id <id> --json
27
+ gd-cli dam search <query> --repository-id <id> --json
28
+ gd-cli dam get <asset-id> --json
29
+ gd-cli dam download <asset-id> --repository-id <id> --output-dir ./downloads --json
30
+ ```
31
+
32
+ 跨资源库查询只在用户明确要求时使用 `--all-repositories`。列表或搜索按需增加文件夹、类型、格式、标签、数量和游标筛选。下载只支持一个素材,不支持文件夹下载,也不会覆盖已存在的同名文件。
33
+
34
+ ## 单条目写入
35
+
36
+ ```bash
37
+ gd-cli dam upload ./asset.png --repository-id <id> --folder-id <folder-id> --tag-ids <tag-id> --json
38
+ gd-cli dam rename <entry-id> --kind asset --title <new-title> --repository-id <id> --json
39
+ gd-cli dam copy <entry-id> --kind asset --repository-id <source-id> --target-repository-id <target-id> --target-folder-id <folder-id> --json
40
+ gd-cli dam move <entry-id> --kind asset --repository-id <source-id> --target-repository-id <target-id> --target-folder-id <folder-id> --json
41
+ gd-cli dam delete <asset-id> --repository-id <id>
42
+ ```
43
+
44
+ - `rename`、`move`、`copy` 的 `--kind` 只能是 `asset` 或 `folder`。
45
+ - 一次只处理一个素材或文件夹;不拆分或模拟批量操作。
46
+ - 上传受保护路径时,只有用户明确允许才加 `--allow-sensitive-path`;需要等待分析完成时加 `--wait-analysis`。
47
+ - 复制结果可能没有 `copied_entry_id`,这不表示失败;查询目标文件夹或目标资源库发现新副本,不要猜测新 ID,也不要再次提交 copy。
48
+ - 移动、复制或重命名若返回“已提交但未确认”,先查询目标位置并报告诊断 ID,不要立即重复提交。
49
+ - 删除默认移入回收站;只有用户明确要求永久删除时才加 `--permanent`。
50
+ - 回收站列表和恢复暂不可用,不要尝试不存在的 `dam recycle` 命令。
51
+
52
+ 写操作前确认资源库、条目 ID、类型和目标位置。优先从本轮 JSON 输出取得 ID,不从本地登录状态或旧输出替用户猜测。