@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,129 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "ToolCallOutput",
4
+ "description": "创作工具同步返回的最终内容与所选模型成本。",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "content",
9
+ "usage"
10
+ ],
11
+ "properties": {
12
+ "content": {
13
+ "type": "array",
14
+ "description": "创作工具最终产出的文本或资源链接。",
15
+ "items": {
16
+ "oneOf": [
17
+ {
18
+ "$ref": "#/$defs/TextContent"
19
+ },
20
+ {
21
+ "$ref": "#/$defs/ResourceLink"
22
+ }
23
+ ]
24
+ }
25
+ },
26
+ "usage": {
27
+ "$ref": "#/$defs/ToolUsage",
28
+ "description": "本次调用所选模型及 Model Catalog 声明的成本。"
29
+ }
30
+ },
31
+ "$defs": {
32
+ "CostRange": {
33
+ "type": "object",
34
+ "additionalProperties": false,
35
+ "required": [
36
+ "unit",
37
+ "minimum",
38
+ "maximum"
39
+ ],
40
+ "properties": {
41
+ "unit": {
42
+ "const": "gaodou",
43
+ "description": "稿豆计价单位。"
44
+ },
45
+ "minimum": {
46
+ "type": "number",
47
+ "minimum": 0,
48
+ "description": "当前可用配置中的最低稿豆消耗。"
49
+ },
50
+ "maximum": {
51
+ "type": "number",
52
+ "minimum": 0,
53
+ "description": "当前可用配置中的最高稿豆消耗。"
54
+ }
55
+ }
56
+ },
57
+ "ToolUsage": {
58
+ "type": "object",
59
+ "additionalProperties": false,
60
+ "required": [
61
+ "model"
62
+ ],
63
+ "properties": {
64
+ "model": {
65
+ "type": "string",
66
+ "minLength": 1,
67
+ "pattern": ".*\\S.*",
68
+ "description": "本次调用选择的模型机器标识。"
69
+ },
70
+ "cost": {
71
+ "$ref": "#/$defs/CostRange",
72
+ "description": "Model Catalog 声明的稿豆消耗区间。"
73
+ }
74
+ }
75
+ },
76
+ "TextContent": {
77
+ "type": "object",
78
+ "additionalProperties": false,
79
+ "required": [
80
+ "type",
81
+ "text"
82
+ ],
83
+ "properties": {
84
+ "type": {
85
+ "const": "text",
86
+ "description": "文本内容的固定类型。"
87
+ },
88
+ "text": {
89
+ "type": "string",
90
+ "minLength": 1,
91
+ "pattern": ".*\\S.*",
92
+ "description": "创作工具返回的文本。"
93
+ }
94
+ }
95
+ },
96
+ "ResourceLink": {
97
+ "type": "object",
98
+ "additionalProperties": false,
99
+ "required": [
100
+ "type",
101
+ "uri",
102
+ "name"
103
+ ],
104
+ "properties": {
105
+ "type": {
106
+ "const": "resource_link",
107
+ "description": "资源链接的固定类型。"
108
+ },
109
+ "uri": {
110
+ "type": "string",
111
+ "format": "uri",
112
+ "description": "创作工具生成资源的 URI。"
113
+ },
114
+ "name": {
115
+ "type": "string",
116
+ "minLength": 1,
117
+ "pattern": ".*\\S.*",
118
+ "description": "资源的文件名。"
119
+ },
120
+ "mimeType": {
121
+ "type": "string",
122
+ "minLength": 1,
123
+ "pattern": ".*\\S.*",
124
+ "description": "资源的 MIME type。"
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "ToolListInput",
4
+ "description": "列出当前可用产品创作工具的输入。",
5
+ "type": "object",
6
+ "additionalProperties": false
7
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "ToolListResult",
4
+ "description": "当前可用的产品创作工具。",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": [
8
+ "tools"
9
+ ],
10
+ "properties": {
11
+ "tools": {
12
+ "type": "array",
13
+ "description": "当前至少有一个可用模型的产品创作工具。",
14
+ "items": {
15
+ "type": "object",
16
+ "additionalProperties": false,
17
+ "required": [
18
+ "name",
19
+ "title",
20
+ "description"
21
+ ],
22
+ "properties": {
23
+ "name": {
24
+ "type": "string",
25
+ "minLength": 1,
26
+ "pattern": ".*\\S.*",
27
+ "description": "调用创作工具时使用的机器标识。"
28
+ },
29
+ "title": {
30
+ "type": "string",
31
+ "minLength": 1,
32
+ "pattern": ".*\\S.*",
33
+ "description": "创作工具的展示名称。"
34
+ },
35
+ "description": {
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "pattern": ".*\\S.*",
39
+ "description": "创作工具的用途说明。"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env node
2
+ const controller = new AbortController();
3
+ const interrupt = () => controller.abort(new Error("SIGINT"));
4
+ process.once("SIGINT", interrupt);
5
+ let runtime;
6
+ let mapCliError;
7
+ let redact;
8
+ try {
9
+ // Register SIGINT before loading the CLI graph so a cold-start interrupt is
10
+ // converted into the same abort path as an interrupt during stdin reading.
11
+ const [cliModule, runtimeModule, errorsModule, redactModule] = await Promise.all([
12
+ import("../src/bootstrap/create-cli.js"),
13
+ import("../src/bootstrap/create-runtime.js"),
14
+ import("../src/cli/errors.js"),
15
+ import("../src/platform/redact.js")
16
+ ]);
17
+ const { createCli, executeCli } = cliModule;
18
+ const { createProductionRuntime } = runtimeModule;
19
+ mapCliError = errorsModule.mapCliError;
20
+ redact = redactModule.redact;
21
+ runtime = createProductionRuntime();
22
+ const program = createCli(runtime, { signal: controller.signal });
23
+ process.exitCode = await executeCli({
24
+ program,
25
+ argv: process.argv.slice(2),
26
+ presenter: runtime.presenter,
27
+ signal: controller.signal,
28
+ telemetry: runtime.telemetry,
29
+ telemetrySink: runtime.telemetrySink,
30
+ updateNotification: runtime.updateNotification
31
+ });
32
+ }
33
+ catch (error) {
34
+ // Dynamic module loading can fail before the error mapper is available.
35
+ // Keep that rare startup failure bounded and avoid an unhandled rejection.
36
+ if (mapCliError === undefined || redact === undefined) {
37
+ process.stderr.write("INTERNAL_ERROR: CLI 启动失败。\n");
38
+ process.exitCode = 1;
39
+ }
40
+ else {
41
+ const outcome = redact(mapCliError(error, { aborted: controller.signal.aborted }));
42
+ if (runtime) {
43
+ runtime.presenter.error(outcome, { json: process.argv.includes("--json") });
44
+ }
45
+ else if (outcome.kind === "interrupted") {
46
+ process.stderr.write("已取消。\n");
47
+ }
48
+ else if (process.argv.includes("--json")) {
49
+ process.stderr.write(`${JSON.stringify({ error: outcome.failure })}\n`);
50
+ }
51
+ else {
52
+ process.stderr.write(`${outcome.failure.code}: ${outcome.failure.message}\n`);
53
+ }
54
+ process.exitCode = outcome.exitCode;
55
+ }
56
+ }
57
+ finally {
58
+ process.removeListener("SIGINT", interrupt);
59
+ }
60
+ export {};
@@ -0,0 +1,42 @@
1
+ import { fileURLToPath } from "node:url";
2
+ import { resolve } from "node:path";
3
+ import { loadBundledSkills } from "../src/features/skill/bundled-skills.js";
4
+ import { syncBundledSkills } from "../src/features/skill/installer.js";
5
+ export function isSupportedGlobalLifecycle(env) {
6
+ const userAgent = env.npm_config_user_agent ?? "";
7
+ if (env.npm_config_global === "true") {
8
+ return /^(?:npm|pnpm)\//u.test(userAgent);
9
+ }
10
+ const initialDirectory = (env.INIT_CWD ?? "").replace(/\\/gu, "/");
11
+ return userAgent.startsWith("pnpm/")
12
+ && env.npm_command === "add"
13
+ && env.npm_lifecycle_event === "postinstall"
14
+ && env.npm_package_name === "@gaoding/cli"
15
+ && /\/v\d+\/[0-9a-f]+-[0-9a-f]+-[0-9a-f]{16}$/u.test(initialDirectory);
16
+ }
17
+ export async function runPostinstall(options = {}) {
18
+ const env = options.env ?? process.env;
19
+ if (!isSupportedGlobalLifecycle(env))
20
+ return;
21
+ const writeError = options.writeError ?? ((text) => process.stderr.write(text));
22
+ try {
23
+ const skills = (options.loadSkills ?? loadBundledSkills)(options.startFile ?? fileURLToPath(import.meta.url));
24
+ await (options.syncSkills ?? syncBundledSkills)(skills, {
25
+ env,
26
+ ...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
27
+ });
28
+ }
29
+ catch (error) {
30
+ writeError(`警告: ${oneLineMessage(error)}\n`);
31
+ }
32
+ }
33
+ function oneLineMessage(error) {
34
+ const value = error instanceof Error ? error.message : String(error);
35
+ return value.replace(/\s+/gu, " ").trim() || "Agent Skill 自动安装失败";
36
+ }
37
+ const entryPath = process.argv[1];
38
+ const isDirectEntry = entryPath !== undefined
39
+ && resolve(entryPath) === fileURLToPath(import.meta.url);
40
+ if (isDirectEntry || process.env.npm_lifecycle_event === "postinstall") {
41
+ void runPostinstall();
42
+ }
@@ -0,0 +1,112 @@
1
+ import { Command, CommanderError } from "commander";
2
+ import { assertAllLeafCommandsBound, configureActionEnvironment } from "../cli/action-binding.js";
3
+ import { registerAgentCommands } from "../cli/agent-commands.js";
4
+ import { registerAuthCommands } from "../cli/auth-commands.js";
5
+ import { classifyTelemetryError, isHelpOutcome, mapCliError } from "../cli/errors.js";
6
+ import { registerOrgCommands } from "../cli/org-commands.js";
7
+ import { registerToolCommands } from "../cli/tool-commands.js";
8
+ import { registerModelCommands } from "../cli/model-commands.js";
9
+ import { registerEditorCommands } from "../cli/editor-commands.js";
10
+ import { registerDamCommands } from "../cli/dam-commands.js";
11
+ import { registerUpdateCommand } from "../cli/update-command.js";
12
+ import { redact } from "../platform/redact.js";
13
+ export { assertAllLeafCommandsBound, bindAction } from "../cli/action-binding.js";
14
+ export function createCli(runtime, options) {
15
+ const program = new Command()
16
+ .name("gd-cli")
17
+ .description("稿定命令行工具")
18
+ .version(runtime.version)
19
+ .helpCommand(false)
20
+ .showHelpAfterError(false)
21
+ .showSuggestionAfterError(false)
22
+ .allowExcessArguments(false)
23
+ .exitOverride()
24
+ .configureOutput({
25
+ writeOut: runtime.io.writeOut,
26
+ writeErr: () => undefined
27
+ });
28
+ configureActionEnvironment(program, {
29
+ policies: runtime.accessPolicies,
30
+ signal: options.signal,
31
+ telemetry: runtime.telemetry,
32
+ updateNotification: runtime.updateNotification
33
+ });
34
+ registerAuthCommands(program, runtime);
35
+ registerOrgCommands(program, runtime);
36
+ registerAgentCommands(program, runtime);
37
+ registerToolCommands(program, runtime);
38
+ registerModelCommands(program, runtime);
39
+ registerEditorCommands(program, runtime);
40
+ registerDamCommands(program, runtime);
41
+ registerUpdateCommand(program, runtime);
42
+ assertAllLeafCommandsBound(program);
43
+ return program;
44
+ }
45
+ export async function executeCli(options) {
46
+ try {
47
+ await options.program.parseAsync(options.argv, { from: "user" });
48
+ await sendFinished(options, { outcome: "success" });
49
+ return 0;
50
+ }
51
+ catch (error) {
52
+ if (isHelpOutcome(error)) {
53
+ if (options.argv[0] !== "update") {
54
+ await checkUpdateNotification(options.updateNotification, options.signal);
55
+ }
56
+ if (options.signal.aborted) {
57
+ options.presenter.error({ kind: "interrupted", exitCode: 130 }, { json: options.argv.includes("--json") });
58
+ await sendFinished(options, { outcome: "interrupted" });
59
+ return 130;
60
+ }
61
+ return 0;
62
+ }
63
+ if (options.telemetry.selected && error instanceof CommanderError) {
64
+ try {
65
+ await options.telemetry.stage("input", () => { throw error; });
66
+ }
67
+ catch {
68
+ // The original Commander error is mapped and presented below.
69
+ }
70
+ }
71
+ const outcome = redact(mapCliError(error, { aborted: options.signal.aborted }));
72
+ const telemetryError = classifyTelemetryError(error);
73
+ const traceId = options.telemetry.selected
74
+ ? options.telemetry.traceId
75
+ : undefined;
76
+ options.presenter.error(outcome, {
77
+ json: options.argv.includes("--json"),
78
+ ...(traceId ? { traceId } : {})
79
+ });
80
+ await sendFinished(options, outcome.kind === "interrupted"
81
+ ? { outcome: "interrupted", error }
82
+ : {
83
+ outcome: "failure",
84
+ error,
85
+ errorCode: outcome.failure.code,
86
+ errorMessage: outcome.failure.message,
87
+ ...(telemetryError.httpStatus === undefined
88
+ ? {}
89
+ : { httpStatus: telemetryError.httpStatus }),
90
+ ...(telemetryError.remoteErrorCode === undefined
91
+ ? {}
92
+ : { remoteErrorCode: telemetryError.remoteErrorCode }),
93
+ ...(telemetryError.remoteErrorBody === undefined
94
+ ? {}
95
+ : { remoteErrorBody: telemetryError.remoteErrorBody })
96
+ });
97
+ return outcome.exitCode;
98
+ }
99
+ }
100
+ async function checkUpdateNotification(updateNotification, signal) {
101
+ try {
102
+ await updateNotification.check(signal);
103
+ }
104
+ catch {
105
+ // Version availability must never change the requested command outcome.
106
+ }
107
+ }
108
+ async function sendFinished(options, completion) {
109
+ const events = options.telemetry.finish(completion);
110
+ if (events.length > 0)
111
+ await options.telemetrySink.send(events);
112
+ }
@@ -0,0 +1,290 @@
1
+ import { randomBytes, randomUUID } from "node:crypto";
2
+ import { dirname } from "node:path";
3
+ import { setTimeout as delay } from "node:timers/promises";
4
+ import { fileURLToPath } from "node:url";
5
+ import { createAccessPolicies } from "../features/auth/access-policy.js";
6
+ import { createLocalCredentialStore } from "../features/auth/credential-store.js";
7
+ import { createAuthUseCases } from "../features/auth/use-cases.js";
8
+ import { createSsoService } from "../features/auth/sso-service.js";
9
+ import { createCreativeAgentAdapter } from "../features/agent/creative-agent-adapter.js";
10
+ import { createDamApiAdapter } from "../features/dam/dam-api-adapter.js";
11
+ import { createDamFileDownloader } from "../features/dam/file-downloader.js";
12
+ import { createDamOperationExecutor } from "../features/dam/operation-executor.js";
13
+ import { createDamRepositoryCatalog } from "../features/dam/repository-catalog.js";
14
+ import { createDamRegisteredUploader } from "../features/dam/registered-uploader.js";
15
+ import { createDamTransientUploader } from "../features/dam/transient-uploader.js";
16
+ import { createDamStorageUploader } from "../features/dam/storage-upload.js";
17
+ import { createDamUseCases } from "../features/dam/use-cases.js";
18
+ import { createEditorSession } from "../features/editor/session.js";
19
+ import { createEditorSessionStateStore } from "../features/editor/session-state.js";
20
+ import { createEditorUseCases } from "../features/editor/use-cases.js";
21
+ import { createObjectStorageUploader } from "../features/dam/object-storage.js";
22
+ import { createAgentUseCases } from "../features/agent/use-cases.js";
23
+ import { createMnsCatalogAdapter } from "../features/tool/mns-catalog-adapter.js";
24
+ import { createToolApiAdapter } from "../features/tool/tool-api-adapter.js";
25
+ import { createToolUseCases } from "../features/tool/use-cases.js";
26
+ import { createOrgUseCases } from "../features/org/use-cases.js";
27
+ import { createOrgService } from "../features/org/org-service.js";
28
+ import { createBrowserOpener } from "../platform/open-browser.js";
29
+ import { createSignedHttpTransport } from "../platform/signed-http-transport.js";
30
+ import { createJsonInputReader } from "../platform/json-input.js";
31
+ import { createOrganizationPrompt } from "../cli/prompt.js";
32
+ import { createPresenter } from "../cli/presenter.js";
33
+ import { createContractValidators } from "./validators.js";
34
+ import { loadBundledSkills } from "../features/skill/bundled-skills.js";
35
+ import { createUpdateService } from "../features/update/update-service.js";
36
+ import { createUpdateNotificationService } from "../features/update/update-notification.js";
37
+ import { classifyTelemetryError } from "../cli/errors.js";
38
+ import { createTelemetryInvocation } from "../telemetry/invocation.js";
39
+ import { createSlsTelemetrySink } from "../telemetry/sls-sink.js";
40
+ const productionEndpoints = {
41
+ orgApi: new URL("https://gdcli.gaoding.com/api"),
42
+ agentApi: new URL("https://gdcli.gaoding.com/api"),
43
+ mnsApi: new URL("https://gdcli.gaoding.com/api"),
44
+ toolApi: new URL("https://gdcli.gaoding.com/api"),
45
+ damApi: new URL("https://gdcli.gaoding.com/api"),
46
+ ssoApi: new URL("https://www.gaoding.com/api/sso"),
47
+ authPageOrigin: new URL("https://www.gaoding.art")
48
+ };
49
+ export function createProductionRuntime(options = {}) {
50
+ const bundledSkills = loadBundledSkills(fileURLToPath(import.meta.url));
51
+ const primarySkill = bundledSkills.find((skill) => skill.skill === "gd-cli");
52
+ if (!primarySkill)
53
+ throw new Error("Bundled gd-cli Skill is missing.");
54
+ const endpoints = options.endpoints ?? productionEndpoints;
55
+ const fetch = options.fetch ?? globalThis.fetch;
56
+ const now = options.now ?? (() => new Date());
57
+ const telemetry = createTelemetryInvocation({
58
+ cliVersion: primarySkill.version,
59
+ now: () => now().getTime(),
60
+ traceIdFactory: () => randomBytes(16).toString("hex"),
61
+ spanIdFactory: () => randomBytes(8).toString("hex"),
62
+ runtime: {
63
+ os: process.platform,
64
+ arch: process.arch,
65
+ nodeMajor: Number.parseInt(process.versions.node, 10)
66
+ },
67
+ classifyError: classifyTelemetryError
68
+ });
69
+ const telemetrySink = createSlsTelemetrySink({ fetch });
70
+ const rawIo = options.io ?? {
71
+ input: process.stdin,
72
+ stdout: process.stdout,
73
+ stderr: process.stderr,
74
+ inputTerminal: process.stdin.isTTY === true,
75
+ stderrTerminal: process.stderr.isTTY === true
76
+ };
77
+ const io = {
78
+ writeOut: (text) => { rawIo.stdout.write(text); },
79
+ writeError: (text) => { rawIo.stderr.write(text); },
80
+ inputTerminal: rawIo.inputTerminal ?? hasTerminal(rawIo.input),
81
+ stderrTerminal: rawIo.stderrTerminal ?? hasTerminal(rawIo.stderr)
82
+ };
83
+ const store = createLocalCredentialStore({
84
+ ...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
85
+ });
86
+ const orgTransport = createSignedHttpTransport({
87
+ baseUrl: endpoints.orgApi,
88
+ fetch,
89
+ now,
90
+ traceparent: () => telemetry.traceparent()
91
+ });
92
+ const agentTransport = createSignedHttpTransport({
93
+ baseUrl: endpoints.agentApi,
94
+ fetch,
95
+ now,
96
+ traceparent: () => telemetry.traceparent()
97
+ });
98
+ const mnsTransport = createSignedHttpTransport({
99
+ baseUrl: endpoints.mnsApi,
100
+ fetch,
101
+ now,
102
+ traceparent: () => telemetry.traceparent()
103
+ });
104
+ const toolTransport = createSignedHttpTransport({
105
+ baseUrl: endpoints.toolApi,
106
+ fetch,
107
+ now,
108
+ traceparent: () => telemetry.traceparent()
109
+ });
110
+ const damTransport = createSignedHttpTransport({
111
+ baseUrl: endpoints.damApi,
112
+ fetch,
113
+ now,
114
+ channelId: "32",
115
+ traceparent: () => telemetry.traceparent()
116
+ });
117
+ const sso = createSsoService({
118
+ ssoApi: endpoints.ssoApi,
119
+ fetch,
120
+ now
121
+ });
122
+ const org = createOrgUseCases({
123
+ store,
124
+ org: createOrgService({ transport: orgTransport }),
125
+ sso,
126
+ telemetry
127
+ });
128
+ const auth = createAuthUseCases({
129
+ store,
130
+ sso,
131
+ organizationBinder: org,
132
+ authPageOrigin: endpoints.authPageOrigin,
133
+ now,
134
+ telemetry,
135
+ sleep: async (milliseconds, signal) => {
136
+ await delay(milliseconds, undefined, { signal });
137
+ }
138
+ });
139
+ const storage = options.objectStorage ?? createObjectStorageUploader({ fetch, now });
140
+ const storageUpload = createDamStorageUploader({
141
+ transport: damTransport,
142
+ storage
143
+ });
144
+ const transientUploader = createDamTransientUploader({ storageUpload });
145
+ const presenter = createPresenter({
146
+ writeOut: io.writeOut,
147
+ writeError: io.writeError
148
+ });
149
+ const browser = createBrowserOpener();
150
+ const validators = createContractValidators();
151
+ const modelCatalog = createMnsCatalogAdapter({ transport: mnsTransport });
152
+ const damApi = createDamApiAdapter({ transport: damTransport });
153
+ const damRepositories = createDamRepositoryCatalog({ transport: damTransport });
154
+ const damOperations = createDamOperationExecutor({
155
+ now: () => now().getTime(),
156
+ sleep: async (milliseconds, signal) => {
157
+ await delay(milliseconds, undefined, { signal });
158
+ },
159
+ annotate: (context) => { telemetry.annotate(context); }
160
+ });
161
+ const dam = createDamUseCases({
162
+ api: damApi,
163
+ repositories: damRepositories,
164
+ storage: storageUpload,
165
+ uploader: createDamRegisteredUploader({
166
+ api: damApi,
167
+ storage: storageUpload,
168
+ warn: (message) => { presenter.warning(message); },
169
+ now,
170
+ telemetry
171
+ }),
172
+ downloader: createDamFileDownloader({ fetch }),
173
+ operations: damOperations,
174
+ sleep: async (milliseconds, signal) => {
175
+ await delay(milliseconds, undefined, { signal });
176
+ },
177
+ validate: {
178
+ repositoryList: validators.damRepositoryListOutput,
179
+ list: validators.damListOutput,
180
+ search: validators.damSearchOutput,
181
+ folderList: validators.damFolderListOutput,
182
+ tagList: validators.damTagListOutput,
183
+ download: validators.damDownloadOutput,
184
+ rename: validators.damRenameOutput,
185
+ move: validators.damMoveOutput,
186
+ copy: validators.damCopyOutput,
187
+ get: validators.damGetOutput,
188
+ upload: validators.damUploadOutput,
189
+ delete: validators.damDeleteOutput
190
+ },
191
+ telemetry
192
+ });
193
+ const agent = createAgentUseCases({
194
+ catalog: modelCatalog,
195
+ uploader: transientUploader,
196
+ completion: createCreativeAgentAdapter({
197
+ transport: agentTransport,
198
+ idFactory: randomUUID,
199
+ telemetry
200
+ }),
201
+ warn: (message) => { presenter.warning(message); },
202
+ telemetry
203
+ });
204
+ const tool = createToolUseCases({
205
+ catalog: modelCatalog,
206
+ execution: createToolApiAdapter({ transport: toolTransport, telemetry }),
207
+ uploader: transientUploader,
208
+ warn: (message) => { presenter.warning(message); },
209
+ telemetry
210
+ });
211
+ const editor = createEditorUseCases({
212
+ session: createEditorSession({
213
+ store: createEditorSessionStateStore({
214
+ ...(options.homeDirectory === undefined
215
+ ? {}
216
+ : { homeDirectory: options.homeDirectory })
217
+ }),
218
+ browser,
219
+ defaultCreateUrl: new URL("https://www.gaoding.art/editor/canvas?mode=create&type=board"),
220
+ workUrl: new URL("https://www.gaoding.art/editor/canvas"),
221
+ ...(options.homeDirectory === undefined
222
+ ? {}
223
+ : { homeDirectory: options.homeDirectory })
224
+ }),
225
+ validate: {
226
+ connect: validators.editorConnectOutput,
227
+ disconnect: validators.editorDisconnectOutput,
228
+ snapshot: validators.editorSnapshotOutput,
229
+ apply: validators.editorApplyOutput,
230
+ screenshot: validators.editorScreenshotOutput,
231
+ save: validators.editorSaveOutput
232
+ }
233
+ });
234
+ const update = {
235
+ run(signal) {
236
+ const packageRoot = dirname(dirname(primarySkill.sourceDirectory));
237
+ return createUpdateService({
238
+ currentVersion: primarySkill.version,
239
+ packageRoot,
240
+ bundledSkills,
241
+ fetch,
242
+ telemetry,
243
+ ...(process.argv[1] ? { binaryPath: process.argv[1] } : {}),
244
+ ...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
245
+ }).run(signal);
246
+ }
247
+ };
248
+ const updateNotification = createUpdateNotificationService({
249
+ currentVersion: primarySkill.version,
250
+ fetch,
251
+ now,
252
+ ...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {}),
253
+ ...(options.env ? { env: options.env } : {}),
254
+ notify: (message) => { presenter.notice(message); }
255
+ });
256
+ return {
257
+ version: primarySkill.version,
258
+ telemetry,
259
+ telemetrySink,
260
+ accessPolicies: createAccessPolicies({
261
+ store,
262
+ now,
263
+ refreshCurrentOrganization: org.refreshCurrentOrganization
264
+ }),
265
+ auth,
266
+ org,
267
+ agent,
268
+ editor,
269
+ dam,
270
+ tool,
271
+ update,
272
+ updateNotification,
273
+ jsonInput: createJsonInputReader({
274
+ cwd: process.cwd(),
275
+ stdin: rawIo.input
276
+ }),
277
+ validators,
278
+ presenter,
279
+ prompt: createOrganizationPrompt({
280
+ input: rawIo.input,
281
+ output: rawIo.stderr
282
+ }),
283
+ browser,
284
+ now,
285
+ io
286
+ };
287
+ }
288
+ function hasTerminal(value) {
289
+ return "isTTY" in value && value.isTTY === true;
290
+ }