gaoding-cli 1.0.0-alpha.13 → 1.0.0-alpha.15
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.
- package/README.md +2 -2
- package/contracts/operations/agent.send/input.schema.json +4 -0
- package/contracts/operations/model.get/output.schema.json +1 -0
- package/dist/bin/gd-cli.js +37 -16
- package/dist/src/bootstrap/create-cli.js +43 -4
- package/dist/src/bootstrap/create-runtime.js +44 -13
- package/dist/src/cli/action-binding.js +43 -9
- package/dist/src/cli/agent-commands.js +13 -3
- package/dist/src/cli/auth-commands.js +21 -13
- package/dist/src/cli/dam-commands.js +35 -20
- package/dist/src/cli/errors.js +34 -1
- package/dist/src/cli/model-commands.js +25 -11
- package/dist/src/cli/org-commands.js +18 -12
- package/dist/src/cli/presenter.js +11 -1
- package/dist/src/cli/tool-commands.js +19 -7
- package/dist/src/cli/update-command.js +6 -4
- package/dist/src/features/agent/creative-agent-adapter.js +19 -14
- package/dist/src/features/agent/creative-protocol.js +7 -3
- package/dist/src/features/agent/use-cases.js +63 -54
- package/dist/src/features/auth/use-cases.js +82 -65
- package/dist/src/features/dam/asset-projection.js +22 -14
- package/dist/src/features/dam/dam-api-adapter.js +19 -4
- package/dist/src/features/dam/object-storage.js +2 -0
- package/dist/src/features/dam/registered-uploader.js +58 -35
- package/dist/src/features/dam/use-cases.js +39 -32
- package/dist/src/features/org/use-cases.js +27 -11
- package/dist/src/features/tool/catalog.js +7 -3
- package/dist/src/features/tool/dynamic-schema.js +19 -9
- package/dist/src/features/tool/mns-catalog-adapter.js +7 -4
- package/dist/src/features/tool/tool-api-adapter.js +186 -73
- package/dist/src/features/tool/use-cases.js +63 -34
- package/dist/src/features/update/update-service.js +28 -22
- package/dist/src/platform/json-input.js +3 -0
- package/dist/src/platform/remote-error-evidence.js +66 -0
- package/dist/src/platform/remote-protocol.js +10 -0
- package/dist/src/platform/signed-http-transport.js +31 -5
- package/dist/src/telemetry/invocation.js +156 -0
- package/dist/src/telemetry/sls-sink.js +31 -0
- package/package.json +1 -1
- package/skills/gd-cli/references/creation.md +15 -4
- package/skills/gd-cli/references/errors.md +3 -1
package/README.md
CHANGED
|
@@ -28,10 +28,10 @@ gd-cli org switch --org <org-id>
|
|
|
28
28
|
gd-cli agent send --schema
|
|
29
29
|
gd-cli tool list
|
|
30
30
|
gd-cli model list --tool <tool>
|
|
31
|
-
gd-cli
|
|
31
|
+
gd-cli model get <model>
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
选定 Model 后,以 `model get` 返回的 `parameters` 与 `usageDescription` 构造实际输入;`tool call --schema` 只给出整个 Tool 的参数并集。运行 `gd-cli --help` 查看当前命令;运行任一命令的 `--help` 查看参数。`gd-cli update` 固定检查 npm `latest`,支持更新 npm、pnpm 全局安装并同步 Agent Skill。
|
|
35
35
|
|
|
36
36
|
## License
|
|
37
37
|
|
package/dist/bin/gd-cli.js
CHANGED
|
@@ -1,38 +1,59 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { createCli, executeCli } from "../src/bootstrap/create-cli.js";
|
|
3
|
-
import { createProductionRuntime } from "../src/bootstrap/create-runtime.js";
|
|
4
|
-
import { mapCliError } from "../src/cli/errors.js";
|
|
5
|
-
import { redact } from "../src/platform/redact.js";
|
|
6
2
|
const controller = new AbortController();
|
|
7
3
|
const interrupt = () => controller.abort(new Error("SIGINT"));
|
|
8
4
|
process.once("SIGINT", interrupt);
|
|
9
5
|
let runtime;
|
|
6
|
+
let mapCliError;
|
|
7
|
+
let redact;
|
|
10
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;
|
|
11
21
|
runtime = createProductionRuntime();
|
|
12
22
|
const program = createCli(runtime, { signal: controller.signal });
|
|
13
23
|
process.exitCode = await executeCli({
|
|
14
24
|
program,
|
|
15
25
|
argv: process.argv.slice(2),
|
|
16
26
|
presenter: runtime.presenter,
|
|
17
|
-
signal: controller.signal
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
telemetry: runtime.telemetry,
|
|
29
|
+
telemetrySink: runtime.telemetrySink
|
|
18
30
|
});
|
|
19
31
|
}
|
|
20
32
|
catch (error) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
process.stderr.write("已取消。\n");
|
|
27
|
-
}
|
|
28
|
-
else if (process.argv.includes("--json")) {
|
|
29
|
-
process.stderr.write(`${JSON.stringify({ error: outcome.failure })}\n`);
|
|
33
|
+
// Dynamic module loading can fail before the error mapper is available.
|
|
34
|
+
// Keep that rare startup failure bounded and avoid an unhandled rejection.
|
|
35
|
+
if (mapCliError === undefined || redact === undefined) {
|
|
36
|
+
process.stderr.write("INTERNAL_ERROR: CLI 启动失败。\n");
|
|
37
|
+
process.exitCode = 1;
|
|
30
38
|
}
|
|
31
39
|
else {
|
|
32
|
-
|
|
40
|
+
const outcome = redact(mapCliError(error, { aborted: controller.signal.aborted }));
|
|
41
|
+
if (runtime) {
|
|
42
|
+
runtime.presenter.error(outcome, { json: process.argv.includes("--json") });
|
|
43
|
+
}
|
|
44
|
+
else if (outcome.kind === "interrupted") {
|
|
45
|
+
process.stderr.write("已取消。\n");
|
|
46
|
+
}
|
|
47
|
+
else if (process.argv.includes("--json")) {
|
|
48
|
+
process.stderr.write(`${JSON.stringify({ error: outcome.failure })}\n`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
process.stderr.write(`${outcome.failure.code}: ${outcome.failure.message}\n`);
|
|
52
|
+
}
|
|
53
|
+
process.exitCode = outcome.exitCode;
|
|
33
54
|
}
|
|
34
|
-
process.exitCode = outcome.exitCode;
|
|
35
55
|
}
|
|
36
56
|
finally {
|
|
37
57
|
process.removeListener("SIGINT", interrupt);
|
|
38
58
|
}
|
|
59
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
1
|
+
import { Command, CommanderError } from "commander";
|
|
2
2
|
import { assertAllLeafCommandsBound, configureActionEnvironment } from "../cli/action-binding.js";
|
|
3
3
|
import { registerAgentCommands } from "../cli/agent-commands.js";
|
|
4
4
|
import { registerAuthCommands } from "../cli/auth-commands.js";
|
|
5
|
-
import { isHelpOutcome, mapCliError } from "../cli/errors.js";
|
|
5
|
+
import { classifyTelemetryError, isHelpOutcome, mapCliError } from "../cli/errors.js";
|
|
6
6
|
import { registerOrgCommands } from "../cli/org-commands.js";
|
|
7
7
|
import { registerToolCommands } from "../cli/tool-commands.js";
|
|
8
8
|
import { registerModelCommands } from "../cli/model-commands.js";
|
|
@@ -27,7 +27,8 @@ export function createCli(runtime, options) {
|
|
|
27
27
|
});
|
|
28
28
|
configureActionEnvironment(program, {
|
|
29
29
|
policies: runtime.accessPolicies,
|
|
30
|
-
signal: options.signal
|
|
30
|
+
signal: options.signal,
|
|
31
|
+
telemetry: runtime.telemetry
|
|
31
32
|
});
|
|
32
33
|
registerAuthCommands(program, runtime);
|
|
33
34
|
registerOrgCommands(program, runtime);
|
|
@@ -43,13 +44,51 @@ export function createCli(runtime, options) {
|
|
|
43
44
|
export async function executeCli(options) {
|
|
44
45
|
try {
|
|
45
46
|
await options.program.parseAsync(options.argv, { from: "user" });
|
|
47
|
+
await sendFinished(options, { outcome: "success" });
|
|
46
48
|
return 0;
|
|
47
49
|
}
|
|
48
50
|
catch (error) {
|
|
49
51
|
if (isHelpOutcome(error))
|
|
50
52
|
return 0;
|
|
53
|
+
if (options.telemetry.selected && error instanceof CommanderError) {
|
|
54
|
+
try {
|
|
55
|
+
await options.telemetry.stage("input", () => { throw error; });
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// The original Commander error is mapped and presented below.
|
|
59
|
+
}
|
|
60
|
+
}
|
|
51
61
|
const outcome = redact(mapCliError(error, { aborted: options.signal.aborted }));
|
|
52
|
-
|
|
62
|
+
const telemetryError = classifyTelemetryError(error);
|
|
63
|
+
const traceId = options.telemetry.selected
|
|
64
|
+
? options.telemetry.traceId
|
|
65
|
+
: undefined;
|
|
66
|
+
options.presenter.error(outcome, {
|
|
67
|
+
json: options.argv.includes("--json"),
|
|
68
|
+
...(traceId ? { traceId } : {})
|
|
69
|
+
});
|
|
70
|
+
await sendFinished(options, outcome.kind === "interrupted"
|
|
71
|
+
? { outcome: "interrupted", error }
|
|
72
|
+
: {
|
|
73
|
+
outcome: "failure",
|
|
74
|
+
error,
|
|
75
|
+
errorCode: outcome.failure.code,
|
|
76
|
+
errorMessage: outcome.failure.message,
|
|
77
|
+
...(telemetryError.httpStatus === undefined
|
|
78
|
+
? {}
|
|
79
|
+
: { httpStatus: telemetryError.httpStatus }),
|
|
80
|
+
...(telemetryError.remoteErrorCode === undefined
|
|
81
|
+
? {}
|
|
82
|
+
: { remoteErrorCode: telemetryError.remoteErrorCode }),
|
|
83
|
+
...(telemetryError.remoteErrorBody === undefined
|
|
84
|
+
? {}
|
|
85
|
+
: { remoteErrorBody: telemetryError.remoteErrorBody })
|
|
86
|
+
});
|
|
53
87
|
return outcome.exitCode;
|
|
54
88
|
}
|
|
55
89
|
}
|
|
90
|
+
async function sendFinished(options, completion) {
|
|
91
|
+
const events = options.telemetry.finish(completion);
|
|
92
|
+
if (events.length > 0)
|
|
93
|
+
await options.telemetrySink.send(events);
|
|
94
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
1
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { setTimeout as delay } from "node:timers/promises";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -30,6 +30,9 @@ import { createPresenter } from "../cli/presenter.js";
|
|
|
30
30
|
import { createContractValidators } from "./validators.js";
|
|
31
31
|
import { loadBundledSkills } from "../features/skill/bundled-skills.js";
|
|
32
32
|
import { createUpdateService } from "../features/update/update-service.js";
|
|
33
|
+
import { classifyTelemetryError } from "../cli/errors.js";
|
|
34
|
+
import { createTelemetryInvocation } from "../telemetry/invocation.js";
|
|
35
|
+
import { createSlsTelemetrySink } from "../telemetry/sls-sink.js";
|
|
33
36
|
const productionEndpoints = {
|
|
34
37
|
orgApi: new URL("https://gdcli.gaoding.com/api"),
|
|
35
38
|
agentApi: new URL("https://gdcli.gaoding.com/api"),
|
|
@@ -47,6 +50,19 @@ export function createProductionRuntime(options = {}) {
|
|
|
47
50
|
const endpoints = options.endpoints ?? productionEndpoints;
|
|
48
51
|
const fetch = options.fetch ?? globalThis.fetch;
|
|
49
52
|
const now = options.now ?? (() => new Date());
|
|
53
|
+
const telemetry = createTelemetryInvocation({
|
|
54
|
+
cliVersion: primarySkill.version,
|
|
55
|
+
now: () => now().getTime(),
|
|
56
|
+
traceIdFactory: () => randomBytes(16).toString("hex"),
|
|
57
|
+
spanIdFactory: () => randomBytes(8).toString("hex"),
|
|
58
|
+
runtime: {
|
|
59
|
+
os: process.platform,
|
|
60
|
+
arch: process.arch,
|
|
61
|
+
nodeMajor: Number.parseInt(process.versions.node, 10)
|
|
62
|
+
},
|
|
63
|
+
classifyError: classifyTelemetryError
|
|
64
|
+
});
|
|
65
|
+
const telemetrySink = createSlsTelemetrySink({ fetch });
|
|
50
66
|
const rawIo = options.io ?? {
|
|
51
67
|
input: process.stdin,
|
|
52
68
|
stdout: process.stdout,
|
|
@@ -66,28 +82,33 @@ export function createProductionRuntime(options = {}) {
|
|
|
66
82
|
const orgTransport = createSignedHttpTransport({
|
|
67
83
|
baseUrl: endpoints.orgApi,
|
|
68
84
|
fetch,
|
|
69
|
-
now
|
|
85
|
+
now,
|
|
86
|
+
traceparent: () => telemetry.traceparent()
|
|
70
87
|
});
|
|
71
88
|
const agentTransport = createSignedHttpTransport({
|
|
72
89
|
baseUrl: endpoints.agentApi,
|
|
73
90
|
fetch,
|
|
74
|
-
now
|
|
91
|
+
now,
|
|
92
|
+
traceparent: () => telemetry.traceparent()
|
|
75
93
|
});
|
|
76
94
|
const mnsTransport = createSignedHttpTransport({
|
|
77
95
|
baseUrl: endpoints.mnsApi,
|
|
78
96
|
fetch,
|
|
79
|
-
now
|
|
97
|
+
now,
|
|
98
|
+
traceparent: () => telemetry.traceparent()
|
|
80
99
|
});
|
|
81
100
|
const toolTransport = createSignedHttpTransport({
|
|
82
101
|
baseUrl: endpoints.toolApi,
|
|
83
102
|
fetch,
|
|
84
|
-
now
|
|
103
|
+
now,
|
|
104
|
+
traceparent: () => telemetry.traceparent()
|
|
85
105
|
});
|
|
86
106
|
const damTransport = createSignedHttpTransport({
|
|
87
107
|
baseUrl: endpoints.damApi,
|
|
88
108
|
fetch,
|
|
89
109
|
now,
|
|
90
|
-
channelId: "32"
|
|
110
|
+
channelId: "32",
|
|
111
|
+
traceparent: () => telemetry.traceparent()
|
|
91
112
|
});
|
|
92
113
|
const sso = createSsoService({
|
|
93
114
|
ssoApi: endpoints.ssoApi,
|
|
@@ -97,7 +118,8 @@ export function createProductionRuntime(options = {}) {
|
|
|
97
118
|
const org = createOrgUseCases({
|
|
98
119
|
store,
|
|
99
120
|
org: createOrgService({ transport: orgTransport }),
|
|
100
|
-
sso
|
|
121
|
+
sso,
|
|
122
|
+
telemetry
|
|
101
123
|
});
|
|
102
124
|
const auth = createAuthUseCases({
|
|
103
125
|
store,
|
|
@@ -105,6 +127,7 @@ export function createProductionRuntime(options = {}) {
|
|
|
105
127
|
organizationBinder: org,
|
|
106
128
|
authPageOrigin: endpoints.authPageOrigin,
|
|
107
129
|
now,
|
|
130
|
+
telemetry,
|
|
108
131
|
sleep: async (milliseconds, signal) => {
|
|
109
132
|
await delay(milliseconds, undefined, { signal });
|
|
110
133
|
}
|
|
@@ -129,7 +152,8 @@ export function createProductionRuntime(options = {}) {
|
|
|
129
152
|
api: damApi,
|
|
130
153
|
storage: storageUpload,
|
|
131
154
|
warn: (message) => { presenter.warning(message); },
|
|
132
|
-
now
|
|
155
|
+
now,
|
|
156
|
+
telemetry
|
|
133
157
|
}),
|
|
134
158
|
validate: {
|
|
135
159
|
list: validators.damListOutput,
|
|
@@ -137,20 +161,24 @@ export function createProductionRuntime(options = {}) {
|
|
|
137
161
|
get: validators.damGetOutput,
|
|
138
162
|
upload: validators.damUploadOutput,
|
|
139
163
|
delete: validators.damDeleteOutput
|
|
140
|
-
}
|
|
164
|
+
},
|
|
165
|
+
telemetry
|
|
141
166
|
});
|
|
142
167
|
const agent = createAgentUseCases({
|
|
143
168
|
uploader: transientUploader,
|
|
144
169
|
completion: createCreativeAgentAdapter({
|
|
145
170
|
transport: agentTransport,
|
|
146
|
-
idFactory: randomUUID
|
|
147
|
-
|
|
171
|
+
idFactory: randomUUID,
|
|
172
|
+
telemetry
|
|
173
|
+
}),
|
|
174
|
+
telemetry
|
|
148
175
|
});
|
|
149
176
|
const tool = createToolUseCases({
|
|
150
177
|
catalog: createMnsCatalogAdapter({ transport: mnsTransport }),
|
|
151
|
-
execution: createToolApiAdapter({ transport: toolTransport }),
|
|
178
|
+
execution: createToolApiAdapter({ transport: toolTransport, telemetry }),
|
|
152
179
|
uploader: transientUploader,
|
|
153
|
-
warn: (message) => { presenter.warning(message); }
|
|
180
|
+
warn: (message) => { presenter.warning(message); },
|
|
181
|
+
telemetry
|
|
154
182
|
});
|
|
155
183
|
const editor = createEditorUseCases({
|
|
156
184
|
session: createEditorSession({
|
|
@@ -183,6 +211,7 @@ export function createProductionRuntime(options = {}) {
|
|
|
183
211
|
packageRoot,
|
|
184
212
|
bundledSkills,
|
|
185
213
|
fetch,
|
|
214
|
+
telemetry,
|
|
186
215
|
...(process.argv[1] ? { binaryPath: process.argv[1] } : {}),
|
|
187
216
|
...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
|
|
188
217
|
}).run(signal);
|
|
@@ -190,6 +219,8 @@ export function createProductionRuntime(options = {}) {
|
|
|
190
219
|
};
|
|
191
220
|
return {
|
|
192
221
|
version: primarySkill.version,
|
|
222
|
+
telemetry,
|
|
223
|
+
telemetrySink,
|
|
193
224
|
accessPolicies: createAccessPolicies({
|
|
194
225
|
store,
|
|
195
226
|
now,
|
|
@@ -3,34 +3,46 @@ const boundPolicies = new WeakMap();
|
|
|
3
3
|
export function configureActionEnvironment(program, environment) {
|
|
4
4
|
environments.set(program, environment);
|
|
5
5
|
}
|
|
6
|
-
export function bindAction(command, policy, handler) {
|
|
6
|
+
export function bindAction(command, policy, handler, telemetry) {
|
|
7
7
|
if (boundPolicies.has(command))
|
|
8
8
|
throw new Error(`Action already bound: ${commandPath(command)}`);
|
|
9
9
|
boundPolicies.set(command, policy);
|
|
10
|
+
bindTelemetrySelection(command, telemetry);
|
|
10
11
|
command.action(async () => {
|
|
11
12
|
const environment = environments.get(rootCommand(command));
|
|
12
13
|
if (!environment)
|
|
13
14
|
throw new Error("CLI action environment is missing.");
|
|
14
|
-
const context = await environment.
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const context = await environment.telemetry.stage("access", async () => {
|
|
16
|
+
const authorized = await environment.policies[policy].authorize(environment.signal);
|
|
17
|
+
if (authorized.policy !== policy) {
|
|
18
|
+
throw new Error("Access policy returned the wrong context.");
|
|
19
|
+
}
|
|
20
|
+
return authorized;
|
|
21
|
+
});
|
|
22
|
+
annotateAccessContext(environment.telemetry, context);
|
|
17
23
|
await handler(context, environment.signal);
|
|
18
24
|
});
|
|
19
25
|
}
|
|
20
|
-
export function bindPreparedAction(command, policy, prepare, run) {
|
|
26
|
+
export function bindPreparedAction(command, policy, prepare, run, telemetry) {
|
|
21
27
|
if (boundPolicies.has(command))
|
|
22
28
|
throw new Error(`Action already bound: ${commandPath(command)}`);
|
|
23
29
|
boundPolicies.set(command, policy);
|
|
30
|
+
bindTelemetrySelection(command, telemetry);
|
|
24
31
|
command.action(async () => {
|
|
25
32
|
const environment = environments.get(rootCommand(command));
|
|
26
33
|
if (!environment)
|
|
27
34
|
throw new Error("CLI action environment is missing.");
|
|
28
|
-
const prepared = await prepare(environment.signal);
|
|
35
|
+
const prepared = await environment.telemetry.stage("input", () => prepare(environment.signal));
|
|
29
36
|
if (prepared.handled)
|
|
30
37
|
return;
|
|
31
|
-
const context = await environment.
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
const context = await environment.telemetry.stage("access", async () => {
|
|
39
|
+
const authorized = await environment.policies[policy].authorize(environment.signal);
|
|
40
|
+
if (authorized.policy !== policy) {
|
|
41
|
+
throw new Error("Access policy returned the wrong context.");
|
|
42
|
+
}
|
|
43
|
+
return authorized;
|
|
44
|
+
});
|
|
45
|
+
annotateAccessContext(environment.telemetry, context);
|
|
34
46
|
await run(context, prepared.input, environment.signal);
|
|
35
47
|
});
|
|
36
48
|
}
|
|
@@ -52,6 +64,28 @@ function rootCommand(command) {
|
|
|
52
64
|
current = current.parent;
|
|
53
65
|
return current;
|
|
54
66
|
}
|
|
67
|
+
function bindTelemetrySelection(command, definition) {
|
|
68
|
+
if (!definition)
|
|
69
|
+
return;
|
|
70
|
+
if (!command.parent)
|
|
71
|
+
throw new Error(`Telemetry command has no parent: ${command.name()}`);
|
|
72
|
+
command.parent.hook("preSubcommand", (parent, selected) => {
|
|
73
|
+
if (selected !== command)
|
|
74
|
+
return;
|
|
75
|
+
const environment = environments.get(rootCommand(parent));
|
|
76
|
+
if (!environment)
|
|
77
|
+
throw new Error("CLI action environment is missing.");
|
|
78
|
+
environment.telemetry.select(definition);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function annotateAccessContext(telemetry, context) {
|
|
82
|
+
if (context.policy === "none")
|
|
83
|
+
return;
|
|
84
|
+
telemetry.annotate({
|
|
85
|
+
account_id: context.state.account?.id,
|
|
86
|
+
organization_id: context.state.organization?.id
|
|
87
|
+
});
|
|
88
|
+
}
|
|
55
89
|
function commandPath(command) {
|
|
56
90
|
const names = [];
|
|
57
91
|
let current = command;
|
|
@@ -18,11 +18,14 @@ export function registerAgentCommands(program, runtime) {
|
|
|
18
18
|
if (modes !== 1)
|
|
19
19
|
throw new CliUsageError();
|
|
20
20
|
if (options.schema === true) {
|
|
21
|
-
runtime.
|
|
21
|
+
await runtime.telemetry.stage("output", async () => {
|
|
22
|
+
runtime.io.writeOut(`${JSON.stringify(agentSendInputSchema)}\n`);
|
|
23
|
+
});
|
|
22
24
|
return { handled: true };
|
|
23
25
|
}
|
|
24
26
|
const input = await runtime.jsonInput.read(options.input, signal);
|
|
25
27
|
runtime.validators.agentSendInput(input);
|
|
28
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
26
29
|
return { handled: false, input };
|
|
27
30
|
}, async (context, input, signal) => {
|
|
28
31
|
const result = await runtime.agent.send({
|
|
@@ -33,7 +36,14 @@ export function registerAgentCommands(program, runtime) {
|
|
|
33
36
|
},
|
|
34
37
|
signal
|
|
35
38
|
});
|
|
36
|
-
runtime.
|
|
37
|
-
|
|
39
|
+
await runtime.telemetry.stage("output", async () => {
|
|
40
|
+
runtime.validators.agentSendOutput(result);
|
|
41
|
+
runtime.io.writeOut(`${JSON.stringify(result)}\n`);
|
|
42
|
+
});
|
|
43
|
+
}, {
|
|
44
|
+
operation: "agent.send",
|
|
45
|
+
mode: () => send.opts().schema === true
|
|
46
|
+
? "schema"
|
|
47
|
+
: "execute"
|
|
38
48
|
});
|
|
39
49
|
}
|
|
@@ -8,8 +8,10 @@ export function registerAuthCommands(program, runtime) {
|
|
|
8
8
|
.description("登录稿定")
|
|
9
9
|
.option("--no-browser", "不自动打开浏览器");
|
|
10
10
|
bindAction(login, "none", async (_context, signal) => {
|
|
11
|
+
const noBrowser = login.opts().browser === false;
|
|
12
|
+
runtime.telemetry.annotate({ parameters: { noBrowser } });
|
|
11
13
|
const result = await runtime.auth.login({
|
|
12
|
-
noBrowser
|
|
14
|
+
noBrowser,
|
|
13
15
|
signal,
|
|
14
16
|
interaction: {
|
|
15
17
|
showAuthorization: (url) => runtime.presenter.authorization({
|
|
@@ -20,27 +22,33 @@ export function registerAuthCommands(program, runtime) {
|
|
|
20
22
|
warn: (message) => runtime.presenter.warning(message)
|
|
21
23
|
}
|
|
22
24
|
});
|
|
23
|
-
runtime.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
await runtime.telemetry.stage("output", async () => {
|
|
26
|
+
runtime.presenter.success(result.status === "already_logged_in" ? "已登录。" : "登录成功。");
|
|
27
|
+
if (result.status === "already_logged_in" && !result.organizationSelected) {
|
|
28
|
+
runtime.presenter.warning("尚未选择组织,请执行 gd-cli org switch。");
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}, { operation: "auth.login" });
|
|
28
32
|
const status = leaf(auth.command("status"))
|
|
29
33
|
.description("查看登录状态")
|
|
30
34
|
.option("--json", "输出 JSON");
|
|
31
35
|
bindAction(status, "none", async () => {
|
|
32
36
|
const result = await runtime.auth.status({ now: runtime.now() });
|
|
33
|
-
runtime.
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
await runtime.telemetry.stage("output", async () => {
|
|
38
|
+
runtime.validators.authStatus(result);
|
|
39
|
+
runtime.presenter.result(result, {
|
|
40
|
+
json: status.opts().json === true,
|
|
41
|
+
view: authStatusView
|
|
42
|
+
});
|
|
37
43
|
});
|
|
38
|
-
});
|
|
44
|
+
}, { operation: "auth.status" });
|
|
39
45
|
const logout = leaf(auth.command("logout")).description("退出登录");
|
|
40
46
|
bindAction(logout, "none", async () => {
|
|
41
47
|
await runtime.auth.logout();
|
|
42
|
-
runtime.
|
|
43
|
-
|
|
48
|
+
await runtime.telemetry.stage("output", async () => {
|
|
49
|
+
runtime.presenter.success("已退出登录。");
|
|
50
|
+
});
|
|
51
|
+
}, { operation: "auth.logout" });
|
|
44
52
|
}
|
|
45
53
|
function leaf(command) {
|
|
46
54
|
return command.allowExcessArguments(false);
|
|
@@ -10,6 +10,7 @@ export function registerDamCommands(program, runtime) {
|
|
|
10
10
|
signal.throwIfAborted();
|
|
11
11
|
const input = browseInput(list);
|
|
12
12
|
runtime.validators.damListInput(input);
|
|
13
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
13
14
|
return { handled: false, input };
|
|
14
15
|
}, async (context, input, signal) => {
|
|
15
16
|
const result = await runtime.dam.list({
|
|
@@ -17,11 +18,13 @@ export function registerDamCommands(program, runtime) {
|
|
|
17
18
|
access: organizationAccess(context.state),
|
|
18
19
|
signal
|
|
19
20
|
});
|
|
20
|
-
runtime.
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
await runtime.telemetry.stage("output", async () => {
|
|
22
|
+
runtime.presenter.result(result, {
|
|
23
|
+
json: list.opts().json === true,
|
|
24
|
+
view: assetListView
|
|
25
|
+
});
|
|
23
26
|
});
|
|
24
|
-
});
|
|
27
|
+
}, { operation: "dam.list" });
|
|
25
28
|
const search = browseCommand(leaf(dam.command("search")))
|
|
26
29
|
.description("按关键词搜索素材")
|
|
27
30
|
.argument("<query>", "搜索关键词");
|
|
@@ -32,6 +35,7 @@ export function registerDamCommands(program, runtime) {
|
|
|
32
35
|
...browseInput(search)
|
|
33
36
|
};
|
|
34
37
|
runtime.validators.damSearchInput(input);
|
|
38
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
35
39
|
return { handled: false, input };
|
|
36
40
|
}, async (context, input, signal) => {
|
|
37
41
|
const result = await runtime.dam.search({
|
|
@@ -39,11 +43,13 @@ export function registerDamCommands(program, runtime) {
|
|
|
39
43
|
access: organizationAccess(context.state),
|
|
40
44
|
signal
|
|
41
45
|
});
|
|
42
|
-
runtime.
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
await runtime.telemetry.stage("output", async () => {
|
|
47
|
+
runtime.presenter.result(result, {
|
|
48
|
+
json: search.opts().json === true,
|
|
49
|
+
view: assetListView
|
|
50
|
+
});
|
|
45
51
|
});
|
|
46
|
-
});
|
|
52
|
+
}, { operation: "dam.search" });
|
|
47
53
|
const get = leaf(dam.command("get"))
|
|
48
54
|
.description("查看素材完整信息")
|
|
49
55
|
.argument("<asset>", "素材 ID")
|
|
@@ -52,6 +58,7 @@ export function registerDamCommands(program, runtime) {
|
|
|
52
58
|
signal.throwIfAborted();
|
|
53
59
|
const input = { asset_id: position(get, 0) };
|
|
54
60
|
runtime.validators.damGetInput(input);
|
|
61
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
55
62
|
return { handled: false, input };
|
|
56
63
|
}, async (context, input, signal) => {
|
|
57
64
|
const result = await runtime.dam.get({
|
|
@@ -59,11 +66,13 @@ export function registerDamCommands(program, runtime) {
|
|
|
59
66
|
access: organizationAccess(context.state),
|
|
60
67
|
signal
|
|
61
68
|
});
|
|
62
|
-
runtime.
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
await runtime.telemetry.stage("output", async () => {
|
|
70
|
+
runtime.presenter.result(result, {
|
|
71
|
+
json: get.opts().json === true,
|
|
72
|
+
view: assetDetailView
|
|
73
|
+
});
|
|
65
74
|
});
|
|
66
|
-
});
|
|
75
|
+
}, { operation: "dam.get" });
|
|
67
76
|
const upload = leaf(dam.command("upload"))
|
|
68
77
|
.description("上传本地文件并创建素材")
|
|
69
78
|
.argument("<file>", "本地文件路径")
|
|
@@ -87,6 +96,7 @@ export function registerDamCommands(program, runtime) {
|
|
|
87
96
|
...(options.waitAnalysis === true ? { waitAnalysis: true } : {})
|
|
88
97
|
};
|
|
89
98
|
runtime.validators.damUploadInput(input);
|
|
99
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
90
100
|
return { handled: false, input };
|
|
91
101
|
}, async (context, input, signal) => {
|
|
92
102
|
const result = await runtime.dam.upload({
|
|
@@ -94,11 +104,13 @@ export function registerDamCommands(program, runtime) {
|
|
|
94
104
|
access: organizationAccess(context.state),
|
|
95
105
|
signal
|
|
96
106
|
});
|
|
97
|
-
runtime.
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
await runtime.telemetry.stage("output", async () => {
|
|
108
|
+
runtime.presenter.result(result, {
|
|
109
|
+
json: upload.opts().json === true,
|
|
110
|
+
view: assetDetailView
|
|
111
|
+
});
|
|
100
112
|
});
|
|
101
|
-
});
|
|
113
|
+
}, { operation: "dam.upload" });
|
|
102
114
|
const deleteCommand = leaf(dam.command("delete"))
|
|
103
115
|
.description("删除素材")
|
|
104
116
|
.argument("<asset>", "素材 ID")
|
|
@@ -113,6 +125,7 @@ export function registerDamCommands(program, runtime) {
|
|
|
113
125
|
...(options.permanent === true ? { permanent: true } : {})
|
|
114
126
|
};
|
|
115
127
|
runtime.validators.damDeleteInput(input);
|
|
128
|
+
runtime.telemetry.annotate({ parameters: { ...input } });
|
|
116
129
|
return { handled: false, input };
|
|
117
130
|
}, async (context, input, signal) => {
|
|
118
131
|
await runtime.dam.delete({
|
|
@@ -120,10 +133,12 @@ export function registerDamCommands(program, runtime) {
|
|
|
120
133
|
access: organizationAccess(context.state),
|
|
121
134
|
signal
|
|
122
135
|
});
|
|
123
|
-
runtime.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
await runtime.telemetry.stage("output", async () => {
|
|
137
|
+
runtime.presenter.success(input.permanent === true
|
|
138
|
+
? "素材已永久删除。"
|
|
139
|
+
: "素材已移入回收站。");
|
|
140
|
+
});
|
|
141
|
+
}, { operation: "dam.delete" });
|
|
127
142
|
}
|
|
128
143
|
function leaf(command) {
|
|
129
144
|
return command.allowExcessArguments(false);
|