gaoding-cli 1.0.0-alpha.10
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/LICENSE +21 -0
- package/README.md +38 -0
- package/contracts/operations/agent.send/input.schema.json +354 -0
- package/contracts/operations/agent.send/output.schema.json +271 -0
- package/contracts/operations/auth.status/input.schema.json +7 -0
- package/contracts/operations/auth.status/output.schema.json +132 -0
- package/contracts/operations/dam.delete/input.schema.json +23 -0
- package/contracts/operations/dam.delete/output.schema.json +6 -0
- package/contracts/operations/dam.get/input.schema.json +16 -0
- package/contracts/operations/dam.get/output.schema.json +46 -0
- package/contracts/operations/dam.list/input.schema.json +44 -0
- package/contracts/operations/dam.list/output.schema.json +71 -0
- package/contracts/operations/dam.search/input.schema.json +46 -0
- package/contracts/operations/dam.search/output.schema.json +71 -0
- package/contracts/operations/dam.upload/input.schema.json +31 -0
- package/contracts/operations/dam.upload/output.schema.json +46 -0
- package/contracts/operations/editor.apply/input.schema.json +134 -0
- package/contracts/operations/editor.apply/output.schema.json +15 -0
- package/contracts/operations/editor.connect/input.schema.json +15 -0
- package/contracts/operations/editor.connect/output.schema.json +17 -0
- package/contracts/operations/editor.disconnect/input.schema.json +8 -0
- package/contracts/operations/editor.disconnect/output.schema.json +14 -0
- package/contracts/operations/editor.save/input.schema.json +8 -0
- package/contracts/operations/editor.save/output.schema.json +23 -0
- package/contracts/operations/editor.screenshot/input.schema.json +8 -0
- package/contracts/operations/editor.screenshot/output.schema.json +16 -0
- package/contracts/operations/editor.snapshot/input.schema.json +8 -0
- package/contracts/operations/editor.snapshot/output.schema.json +113 -0
- package/contracts/operations/model.get/input.schema.json +18 -0
- package/contracts/operations/model.get/output.schema.json +190 -0
- package/contracts/operations/model.list/input.schema.json +15 -0
- package/contracts/operations/model.list/output.schema.json +111 -0
- package/contracts/operations/org.current/input.schema.json +7 -0
- package/contracts/operations/org.current/output.schema.json +49 -0
- package/contracts/operations/org.list/input.schema.json +7 -0
- package/contracts/operations/org.list/output.schema.json +71 -0
- package/contracts/operations/tool.call/input.schema.json +35 -0
- package/contracts/operations/tool.call/output.schema.json +129 -0
- package/contracts/operations/tool.list/input.schema.json +7 -0
- package/contracts/operations/tool.list/output.schema.json +45 -0
- package/dist/bin/gd-cli.js +38 -0
- package/dist/bin/postinstall.js +42 -0
- package/dist/src/bootstrap/create-cli.js +55 -0
- package/dist/src/bootstrap/create-runtime.js +222 -0
- package/dist/src/bootstrap/validators.js +118 -0
- package/dist/src/cli/action-binding.js +63 -0
- package/dist/src/cli/agent-commands.js +39 -0
- package/dist/src/cli/auth-commands.js +47 -0
- package/dist/src/cli/dam-commands.js +207 -0
- package/dist/src/cli/editor-commands.js +73 -0
- package/dist/src/cli/errors.js +90 -0
- package/dist/src/cli/model-commands.js +47 -0
- package/dist/src/cli/org-commands.js +52 -0
- package/dist/src/cli/presenter.js +80 -0
- package/dist/src/cli/prompt.js +30 -0
- package/dist/src/cli/tool-commands.js +65 -0
- package/dist/src/cli/update-command.js +12 -0
- package/dist/src/contracts/schema.js +4 -0
- package/dist/src/features/agent/creative-agent-adapter.js +31 -0
- package/dist/src/features/agent/creative-protocol.js +324 -0
- package/dist/src/features/agent/creative-stream.js +127 -0
- package/dist/src/features/agent/use-cases.js +113 -0
- package/dist/src/features/auth/access-policy.js +101 -0
- package/dist/src/features/auth/credential-store.js +62 -0
- package/dist/src/features/auth/sso-service.js +179 -0
- package/dist/src/features/auth/state.js +129 -0
- package/dist/src/features/auth/use-cases.js +106 -0
- package/dist/src/features/dam/asset-projection.js +270 -0
- package/dist/src/features/dam/dam-api-adapter.js +206 -0
- package/dist/src/features/dam/object-storage.js +191 -0
- package/dist/src/features/dam/registered-uploader.js +224 -0
- package/dist/src/features/dam/storage-upload.js +141 -0
- package/dist/src/features/dam/transient-uploader.js +17 -0
- package/dist/src/features/dam/use-cases.js +151 -0
- package/dist/src/features/editor/bridge-client.js +96 -0
- package/dist/src/features/editor/bridge-process.js +222 -0
- package/dist/src/features/editor/bridge-server.js +311 -0
- package/dist/src/features/editor/protocol.js +1 -0
- package/dist/src/features/editor/session-state.js +78 -0
- package/dist/src/features/editor/session.js +193 -0
- package/dist/src/features/editor/use-cases.js +61 -0
- package/dist/src/features/org/org-service.js +76 -0
- package/dist/src/features/org/use-cases.js +140 -0
- package/dist/src/features/skill/bundled-skills.js +55 -0
- package/dist/src/features/skill/installer.js +265 -0
- package/dist/src/features/tool/catalog.js +79 -0
- package/dist/src/features/tool/dynamic-schema.js +96 -0
- package/dist/src/features/tool/mns-catalog-adapter.js +262 -0
- package/dist/src/features/tool/tool-api-adapter.js +200 -0
- package/dist/src/features/tool/use-cases.js +126 -0
- package/dist/src/features/update/update-service.js +194 -0
- package/dist/src/platform/json-input.js +64 -0
- package/dist/src/platform/local-json-file.js +59 -0
- package/dist/src/platform/open-browser.js +8 -0
- package/dist/src/platform/redact.js +80 -0
- package/dist/src/platform/safe-upload-file.js +146 -0
- package/dist/src/platform/signature.js +19 -0
- package/dist/src/platform/signed-http-transport.js +109 -0
- package/dist/src/platform/url-safety.js +100 -0
- package/package.json +56 -0
- package/skills/gd-cli/SKILL.md +15 -0
- package/skills/gd-cli/references/auth-org.md +9 -0
- package/skills/gd-cli/references/creation.md +38 -0
- package/skills/gd-cli/references/dam.md +20 -0
- package/skills/gd-cli/references/editor.md +12 -0
- package/skills/gd-cli/references/errors.md +10 -0
- package/skills/gd-cli/references/update.md +11 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { 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 { createDamRegisteredUploader } from "../features/dam/registered-uploader.js";
|
|
12
|
+
import { createDamTransientUploader } from "../features/dam/transient-uploader.js";
|
|
13
|
+
import { createDamStorageUploader } from "../features/dam/storage-upload.js";
|
|
14
|
+
import { createDamUseCases } from "../features/dam/use-cases.js";
|
|
15
|
+
import { createEditorSession } from "../features/editor/session.js";
|
|
16
|
+
import { createEditorSessionStateStore } from "../features/editor/session-state.js";
|
|
17
|
+
import { createEditorUseCases } from "../features/editor/use-cases.js";
|
|
18
|
+
import { createObjectStorageUploader } from "../features/dam/object-storage.js";
|
|
19
|
+
import { createAgentUseCases } from "../features/agent/use-cases.js";
|
|
20
|
+
import { createMnsCatalogAdapter } from "../features/tool/mns-catalog-adapter.js";
|
|
21
|
+
import { createToolApiAdapter } from "../features/tool/tool-api-adapter.js";
|
|
22
|
+
import { createToolUseCases } from "../features/tool/use-cases.js";
|
|
23
|
+
import { createOrgUseCases } from "../features/org/use-cases.js";
|
|
24
|
+
import { createOrgService } from "../features/org/org-service.js";
|
|
25
|
+
import { createBrowserOpener } from "../platform/open-browser.js";
|
|
26
|
+
import { createSignedHttpTransport } from "../platform/signed-http-transport.js";
|
|
27
|
+
import { createJsonInputReader } from "../platform/json-input.js";
|
|
28
|
+
import { createOrganizationPrompt } from "../cli/prompt.js";
|
|
29
|
+
import { createPresenter } from "../cli/presenter.js";
|
|
30
|
+
import { createContractValidators } from "./validators.js";
|
|
31
|
+
import { loadBundledSkills } from "../features/skill/bundled-skills.js";
|
|
32
|
+
import { createUpdateService } from "../features/update/update-service.js";
|
|
33
|
+
const productionEndpoints = {
|
|
34
|
+
orgApi: new URL("https://gdcli.gaoding.com/api"),
|
|
35
|
+
agentApi: new URL("https://gdcli.gaoding.com/api"),
|
|
36
|
+
mnsApi: new URL("https://gdcli.gaoding.com/api"),
|
|
37
|
+
toolApi: new URL("https://gdcli.gaoding.com/api"),
|
|
38
|
+
damApi: new URL("https://gdcli.gaoding.com/api"),
|
|
39
|
+
ssoApi: new URL("https://www.gaoding.com/api/sso"),
|
|
40
|
+
authPageOrigin: new URL("https://www.gaoding.com")
|
|
41
|
+
};
|
|
42
|
+
export function createProductionRuntime(options = {}) {
|
|
43
|
+
const bundledSkills = loadBundledSkills(fileURLToPath(import.meta.url));
|
|
44
|
+
const primarySkill = bundledSkills.find((skill) => skill.skill === "gd-cli");
|
|
45
|
+
if (!primarySkill)
|
|
46
|
+
throw new Error("Bundled gd-cli Skill is missing.");
|
|
47
|
+
const endpoints = options.endpoints ?? productionEndpoints;
|
|
48
|
+
const fetch = options.fetch ?? globalThis.fetch;
|
|
49
|
+
const now = options.now ?? (() => new Date());
|
|
50
|
+
const rawIo = options.io ?? {
|
|
51
|
+
input: process.stdin,
|
|
52
|
+
stdout: process.stdout,
|
|
53
|
+
stderr: process.stderr,
|
|
54
|
+
inputTerminal: process.stdin.isTTY === true,
|
|
55
|
+
stderrTerminal: process.stderr.isTTY === true
|
|
56
|
+
};
|
|
57
|
+
const io = {
|
|
58
|
+
writeOut: (text) => { rawIo.stdout.write(text); },
|
|
59
|
+
writeError: (text) => { rawIo.stderr.write(text); },
|
|
60
|
+
inputTerminal: rawIo.inputTerminal ?? hasTerminal(rawIo.input),
|
|
61
|
+
stderrTerminal: rawIo.stderrTerminal ?? hasTerminal(rawIo.stderr)
|
|
62
|
+
};
|
|
63
|
+
const store = createLocalCredentialStore({
|
|
64
|
+
...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
|
|
65
|
+
});
|
|
66
|
+
const orgTransport = createSignedHttpTransport({
|
|
67
|
+
baseUrl: endpoints.orgApi,
|
|
68
|
+
fetch,
|
|
69
|
+
now
|
|
70
|
+
});
|
|
71
|
+
const agentTransport = createSignedHttpTransport({
|
|
72
|
+
baseUrl: endpoints.agentApi,
|
|
73
|
+
fetch,
|
|
74
|
+
now
|
|
75
|
+
});
|
|
76
|
+
const mnsTransport = createSignedHttpTransport({
|
|
77
|
+
baseUrl: endpoints.mnsApi,
|
|
78
|
+
fetch,
|
|
79
|
+
now
|
|
80
|
+
});
|
|
81
|
+
const toolTransport = createSignedHttpTransport({
|
|
82
|
+
baseUrl: endpoints.toolApi,
|
|
83
|
+
fetch,
|
|
84
|
+
now
|
|
85
|
+
});
|
|
86
|
+
const damTransport = createSignedHttpTransport({
|
|
87
|
+
baseUrl: endpoints.damApi,
|
|
88
|
+
fetch,
|
|
89
|
+
now,
|
|
90
|
+
channelId: "32"
|
|
91
|
+
});
|
|
92
|
+
const sso = createSsoService({
|
|
93
|
+
ssoApi: endpoints.ssoApi,
|
|
94
|
+
fetch,
|
|
95
|
+
now
|
|
96
|
+
});
|
|
97
|
+
const org = createOrgUseCases({
|
|
98
|
+
store,
|
|
99
|
+
org: createOrgService({ transport: orgTransport }),
|
|
100
|
+
sso
|
|
101
|
+
});
|
|
102
|
+
const auth = createAuthUseCases({
|
|
103
|
+
store,
|
|
104
|
+
sso,
|
|
105
|
+
organizationBinder: org,
|
|
106
|
+
authPageOrigin: endpoints.authPageOrigin,
|
|
107
|
+
now,
|
|
108
|
+
sleep: async (milliseconds, signal) => {
|
|
109
|
+
await delay(milliseconds, undefined, { signal });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
const storage = options.objectStorage ?? createObjectStorageUploader({ fetch, now });
|
|
113
|
+
const storageUpload = createDamStorageUploader({
|
|
114
|
+
transport: damTransport,
|
|
115
|
+
storage
|
|
116
|
+
});
|
|
117
|
+
const transientUploader = createDamTransientUploader({ storageUpload });
|
|
118
|
+
const presenter = createPresenter({
|
|
119
|
+
writeOut: io.writeOut,
|
|
120
|
+
writeError: io.writeError
|
|
121
|
+
});
|
|
122
|
+
const browser = createBrowserOpener();
|
|
123
|
+
const validators = createContractValidators();
|
|
124
|
+
const damApi = createDamApiAdapter({ transport: damTransport });
|
|
125
|
+
const dam = createDamUseCases({
|
|
126
|
+
api: damApi,
|
|
127
|
+
storage: storageUpload,
|
|
128
|
+
uploader: createDamRegisteredUploader({
|
|
129
|
+
api: damApi,
|
|
130
|
+
storage: storageUpload,
|
|
131
|
+
warn: (message) => { presenter.warning(message); },
|
|
132
|
+
now
|
|
133
|
+
}),
|
|
134
|
+
validate: {
|
|
135
|
+
list: validators.damListOutput,
|
|
136
|
+
search: validators.damSearchOutput,
|
|
137
|
+
get: validators.damGetOutput,
|
|
138
|
+
upload: validators.damUploadOutput,
|
|
139
|
+
delete: validators.damDeleteOutput
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
const agent = createAgentUseCases({
|
|
143
|
+
uploader: transientUploader,
|
|
144
|
+
completion: createCreativeAgentAdapter({
|
|
145
|
+
transport: agentTransport,
|
|
146
|
+
idFactory: randomUUID
|
|
147
|
+
})
|
|
148
|
+
});
|
|
149
|
+
const tool = createToolUseCases({
|
|
150
|
+
catalog: createMnsCatalogAdapter({ transport: mnsTransport }),
|
|
151
|
+
execution: createToolApiAdapter({ transport: toolTransport }),
|
|
152
|
+
uploader: transientUploader,
|
|
153
|
+
warn: (message) => { presenter.warning(message); }
|
|
154
|
+
});
|
|
155
|
+
const editor = createEditorUseCases({
|
|
156
|
+
session: createEditorSession({
|
|
157
|
+
store: createEditorSessionStateStore({
|
|
158
|
+
...(options.homeDirectory === undefined
|
|
159
|
+
? {}
|
|
160
|
+
: { homeDirectory: options.homeDirectory })
|
|
161
|
+
}),
|
|
162
|
+
browser,
|
|
163
|
+
defaultCreateUrl: new URL("https://www.gaoding.art/editor/canvas?mode=create&type=board"),
|
|
164
|
+
workUrl: new URL("https://www.gaoding.art/editor/canvas"),
|
|
165
|
+
...(options.homeDirectory === undefined
|
|
166
|
+
? {}
|
|
167
|
+
: { homeDirectory: options.homeDirectory })
|
|
168
|
+
}),
|
|
169
|
+
validate: {
|
|
170
|
+
connect: validators.editorConnectOutput,
|
|
171
|
+
disconnect: validators.editorDisconnectOutput,
|
|
172
|
+
snapshot: validators.editorSnapshotOutput,
|
|
173
|
+
apply: validators.editorApplyOutput,
|
|
174
|
+
screenshot: validators.editorScreenshotOutput,
|
|
175
|
+
save: validators.editorSaveOutput
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
const update = {
|
|
179
|
+
run(signal) {
|
|
180
|
+
const packageRoot = dirname(dirname(primarySkill.sourceDirectory));
|
|
181
|
+
return createUpdateService({
|
|
182
|
+
currentVersion: primarySkill.version,
|
|
183
|
+
packageRoot,
|
|
184
|
+
bundledSkills,
|
|
185
|
+
fetch,
|
|
186
|
+
...(process.argv[1] ? { binaryPath: process.argv[1] } : {}),
|
|
187
|
+
...(options.homeDirectory ? { homeDirectory: options.homeDirectory } : {})
|
|
188
|
+
}).run(signal);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
version: primarySkill.version,
|
|
193
|
+
accessPolicies: createAccessPolicies({
|
|
194
|
+
store,
|
|
195
|
+
now,
|
|
196
|
+
refreshCurrentOrganization: org.refreshCurrentOrganization
|
|
197
|
+
}),
|
|
198
|
+
auth,
|
|
199
|
+
org,
|
|
200
|
+
agent,
|
|
201
|
+
editor,
|
|
202
|
+
dam,
|
|
203
|
+
tool,
|
|
204
|
+
update,
|
|
205
|
+
jsonInput: createJsonInputReader({
|
|
206
|
+
cwd: process.cwd(),
|
|
207
|
+
stdin: rawIo.input
|
|
208
|
+
}),
|
|
209
|
+
validators,
|
|
210
|
+
presenter,
|
|
211
|
+
prompt: createOrganizationPrompt({
|
|
212
|
+
input: rawIo.input,
|
|
213
|
+
output: rawIo.stderr
|
|
214
|
+
}),
|
|
215
|
+
browser,
|
|
216
|
+
now,
|
|
217
|
+
io
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function hasTerminal(value) {
|
|
221
|
+
return "isTTY" in value && value.isTTY === true;
|
|
222
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
2
|
+
import addFormatsImport, {} from "ajv-formats";
|
|
3
|
+
import { contractSchema } from "../contracts/schema.js";
|
|
4
|
+
const agentSendInputSchema = contractSchema("agent.send", "input");
|
|
5
|
+
const agentSendOutputSchema = contractSchema("agent.send", "output");
|
|
6
|
+
const authStatusSchema = contractSchema("auth.status", "output");
|
|
7
|
+
const damDeleteInputSchema = contractSchema("dam.delete", "input");
|
|
8
|
+
const damDeleteOutputSchema = contractSchema("dam.delete", "output");
|
|
9
|
+
const damGetInputSchema = contractSchema("dam.get", "input");
|
|
10
|
+
const damGetOutputSchema = contractSchema("dam.get", "output");
|
|
11
|
+
const damListInputSchema = contractSchema("dam.list", "input");
|
|
12
|
+
const damListOutputSchema = contractSchema("dam.list", "output");
|
|
13
|
+
const damSearchInputSchema = contractSchema("dam.search", "input");
|
|
14
|
+
const damSearchOutputSchema = contractSchema("dam.search", "output");
|
|
15
|
+
const damUploadInputSchema = contractSchema("dam.upload", "input");
|
|
16
|
+
const damUploadOutputSchema = contractSchema("dam.upload", "output");
|
|
17
|
+
const editorApplyInputSchema = contractSchema("editor.apply", "input");
|
|
18
|
+
const editorApplyOutputSchema = contractSchema("editor.apply", "output");
|
|
19
|
+
const editorConnectInputSchema = contractSchema("editor.connect", "input");
|
|
20
|
+
const editorConnectOutputSchema = contractSchema("editor.connect", "output");
|
|
21
|
+
const editorDisconnectOutputSchema = contractSchema("editor.disconnect", "output");
|
|
22
|
+
const editorSaveOutputSchema = contractSchema("editor.save", "output");
|
|
23
|
+
const editorScreenshotOutputSchema = contractSchema("editor.screenshot", "output");
|
|
24
|
+
const editorSnapshotOutputSchema = contractSchema("editor.snapshot", "output");
|
|
25
|
+
const orgCurrentSchema = contractSchema("org.current", "output");
|
|
26
|
+
const orgListSchema = contractSchema("org.list", "output");
|
|
27
|
+
const modelGetInputSchema = contractSchema("model.get", "input");
|
|
28
|
+
const modelGetOutputSchema = contractSchema("model.get", "output");
|
|
29
|
+
const modelListInputSchema = contractSchema("model.list", "input");
|
|
30
|
+
const modelListOutputSchema = contractSchema("model.list", "output");
|
|
31
|
+
const toolCallInputSchema = contractSchema("tool.call", "input");
|
|
32
|
+
const toolCallOutputSchema = contractSchema("tool.call", "output");
|
|
33
|
+
const toolListOutputSchema = contractSchema("tool.list", "output");
|
|
34
|
+
export class InputContractError extends Error {
|
|
35
|
+
constructor() {
|
|
36
|
+
super("输入不符合命令契约。");
|
|
37
|
+
this.name = "InputContractError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export class OutputContractError extends Error {
|
|
41
|
+
constructor() {
|
|
42
|
+
super("命令结果不符合公开契约。");
|
|
43
|
+
this.name = "OutputContractError";
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function createContractValidators() {
|
|
47
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
48
|
+
const addFormats = addFormatsImport;
|
|
49
|
+
addFormats(ajv);
|
|
50
|
+
const agentSendInput = ajv.compile(agentSendInputSchema);
|
|
51
|
+
const agentSendOutput = ajv.compile(agentSendOutputSchema);
|
|
52
|
+
const authStatus = ajv.compile(authStatusSchema);
|
|
53
|
+
const damListInput = ajv.compile(damListInputSchema);
|
|
54
|
+
const damListOutput = ajv.compile(damListOutputSchema);
|
|
55
|
+
const damSearchInput = ajv.compile(damSearchInputSchema);
|
|
56
|
+
const damSearchOutput = ajv.compile(damSearchOutputSchema);
|
|
57
|
+
const damGetInput = ajv.compile(damGetInputSchema);
|
|
58
|
+
const damGetOutput = ajv.compile(damGetOutputSchema);
|
|
59
|
+
const damUploadInput = ajv.compile(damUploadInputSchema);
|
|
60
|
+
const damUploadOutput = ajv.compile(damUploadOutputSchema);
|
|
61
|
+
const damDeleteInput = ajv.compile(damDeleteInputSchema);
|
|
62
|
+
const damDeleteOutput = ajv.compile(damDeleteOutputSchema);
|
|
63
|
+
const editorConnectInput = ajv.compile(editorConnectInputSchema);
|
|
64
|
+
const editorConnectOutput = ajv.compile(editorConnectOutputSchema);
|
|
65
|
+
const editorDisconnectOutput = ajv.compile(editorDisconnectOutputSchema);
|
|
66
|
+
const editorSnapshotOutput = ajv.compile(editorSnapshotOutputSchema);
|
|
67
|
+
const editorApplyInput = ajv.compile(editorApplyInputSchema);
|
|
68
|
+
const editorApplyOutput = ajv.compile(editorApplyOutputSchema);
|
|
69
|
+
const editorScreenshotOutput = ajv.compile(editorScreenshotOutputSchema);
|
|
70
|
+
const editorSaveOutput = ajv.compile(editorSaveOutputSchema);
|
|
71
|
+
const orgList = ajv.compile(orgListSchema);
|
|
72
|
+
const orgCurrent = ajv.compile(orgCurrentSchema);
|
|
73
|
+
const toolListOutput = ajv.compile(toolListOutputSchema);
|
|
74
|
+
const modelListInput = ajv.compile(modelListInputSchema);
|
|
75
|
+
const modelListOutput = ajv.compile(modelListOutputSchema);
|
|
76
|
+
const modelGetInput = ajv.compile(modelGetInputSchema);
|
|
77
|
+
const modelGetOutput = ajv.compile(modelGetOutputSchema);
|
|
78
|
+
const toolCallInput = ajv.compile(toolCallInputSchema);
|
|
79
|
+
const toolCallOutput = ajv.compile(toolCallOutputSchema);
|
|
80
|
+
return {
|
|
81
|
+
agentSendInput: assertion(agentSendInput, InputContractError),
|
|
82
|
+
agentSendOutput: assertion(agentSendOutput, OutputContractError),
|
|
83
|
+
authStatus: assertion(authStatus, OutputContractError),
|
|
84
|
+
damListInput: assertion(damListInput, InputContractError),
|
|
85
|
+
damListOutput: assertion(damListOutput, OutputContractError),
|
|
86
|
+
damSearchInput: assertion(damSearchInput, InputContractError),
|
|
87
|
+
damSearchOutput: assertion(damSearchOutput, OutputContractError),
|
|
88
|
+
damGetInput: assertion(damGetInput, InputContractError),
|
|
89
|
+
damGetOutput: assertion(damGetOutput, OutputContractError),
|
|
90
|
+
damUploadInput: assertion(damUploadInput, InputContractError),
|
|
91
|
+
damUploadOutput: assertion(damUploadOutput, OutputContractError),
|
|
92
|
+
damDeleteInput: assertion(damDeleteInput, InputContractError),
|
|
93
|
+
damDeleteOutput: assertion(damDeleteOutput, OutputContractError),
|
|
94
|
+
editorConnectInput: assertion(editorConnectInput, InputContractError),
|
|
95
|
+
editorConnectOutput: assertion(editorConnectOutput, OutputContractError),
|
|
96
|
+
editorDisconnectOutput: assertion(editorDisconnectOutput, OutputContractError),
|
|
97
|
+
editorSnapshotOutput: assertion(editorSnapshotOutput, OutputContractError),
|
|
98
|
+
editorApplyInput: assertion(editorApplyInput, InputContractError),
|
|
99
|
+
editorApplyOutput: assertion(editorApplyOutput, OutputContractError),
|
|
100
|
+
editorScreenshotOutput: assertion(editorScreenshotOutput, OutputContractError),
|
|
101
|
+
editorSaveOutput: assertion(editorSaveOutput, OutputContractError),
|
|
102
|
+
orgList: assertion(orgList, OutputContractError),
|
|
103
|
+
orgCurrent: assertion(orgCurrent, OutputContractError),
|
|
104
|
+
toolListOutput: assertion(toolListOutput, OutputContractError),
|
|
105
|
+
modelListInput: assertion(modelListInput, InputContractError),
|
|
106
|
+
modelListOutput: assertion(modelListOutput, OutputContractError),
|
|
107
|
+
modelGetInput: assertion(modelGetInput, InputContractError),
|
|
108
|
+
modelGetOutput: assertion(modelGetOutput, OutputContractError),
|
|
109
|
+
toolCallInput: assertion(toolCallInput, InputContractError),
|
|
110
|
+
toolCallOutput: assertion(toolCallOutput, OutputContractError)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function assertion(validate, ErrorType) {
|
|
114
|
+
return (value) => {
|
|
115
|
+
if (!validate(value))
|
|
116
|
+
throw new ErrorType();
|
|
117
|
+
};
|
|
118
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const environments = new WeakMap();
|
|
2
|
+
const boundPolicies = new WeakMap();
|
|
3
|
+
export function configureActionEnvironment(program, environment) {
|
|
4
|
+
environments.set(program, environment);
|
|
5
|
+
}
|
|
6
|
+
export function bindAction(command, policy, handler) {
|
|
7
|
+
if (boundPolicies.has(command))
|
|
8
|
+
throw new Error(`Action already bound: ${commandPath(command)}`);
|
|
9
|
+
boundPolicies.set(command, policy);
|
|
10
|
+
command.action(async () => {
|
|
11
|
+
const environment = environments.get(rootCommand(command));
|
|
12
|
+
if (!environment)
|
|
13
|
+
throw new Error("CLI action environment is missing.");
|
|
14
|
+
const context = await environment.policies[policy].authorize(environment.signal);
|
|
15
|
+
if (context.policy !== policy)
|
|
16
|
+
throw new Error("Access policy returned the wrong context.");
|
|
17
|
+
await handler(context, environment.signal);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
export function bindPreparedAction(command, policy, prepare, run) {
|
|
21
|
+
if (boundPolicies.has(command))
|
|
22
|
+
throw new Error(`Action already bound: ${commandPath(command)}`);
|
|
23
|
+
boundPolicies.set(command, policy);
|
|
24
|
+
command.action(async () => {
|
|
25
|
+
const environment = environments.get(rootCommand(command));
|
|
26
|
+
if (!environment)
|
|
27
|
+
throw new Error("CLI action environment is missing.");
|
|
28
|
+
const prepared = await prepare(environment.signal);
|
|
29
|
+
if (prepared.handled)
|
|
30
|
+
return;
|
|
31
|
+
const context = await environment.policies[policy].authorize(environment.signal);
|
|
32
|
+
if (context.policy !== policy)
|
|
33
|
+
throw new Error("Access policy returned the wrong context.");
|
|
34
|
+
await run(context, prepared.input, environment.signal);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
export function assertAllLeafCommandsBound(program) {
|
|
38
|
+
for (const command of leafCommands(program)) {
|
|
39
|
+
if (!boundPolicies.has(command)) {
|
|
40
|
+
throw new Error(`Leaf command is missing an access policy: ${commandPath(command)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function leafCommands(command) {
|
|
45
|
+
if (command.commands.length === 0)
|
|
46
|
+
return [command];
|
|
47
|
+
return command.commands.flatMap(leafCommands);
|
|
48
|
+
}
|
|
49
|
+
function rootCommand(command) {
|
|
50
|
+
let current = command;
|
|
51
|
+
while (current.parent)
|
|
52
|
+
current = current.parent;
|
|
53
|
+
return current;
|
|
54
|
+
}
|
|
55
|
+
function commandPath(command) {
|
|
56
|
+
const names = [];
|
|
57
|
+
let current = command;
|
|
58
|
+
while (current) {
|
|
59
|
+
names.unshift(current.name());
|
|
60
|
+
current = current.parent;
|
|
61
|
+
}
|
|
62
|
+
return names.join(" ");
|
|
63
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { contractSchema } from "../contracts/schema.js";
|
|
2
|
+
import { bindPreparedAction } from "./action-binding.js";
|
|
3
|
+
import { CliUsageError } from "./errors.js";
|
|
4
|
+
const agentSendInputSchema = contractSchema("agent.send", "input");
|
|
5
|
+
export function registerAgentCommands(program, runtime) {
|
|
6
|
+
const agent = program.command("agent")
|
|
7
|
+
.description("稿定 Agent")
|
|
8
|
+
.helpCommand(false);
|
|
9
|
+
const send = agent.command("send")
|
|
10
|
+
.description("发送结构化创作消息")
|
|
11
|
+
.option("--schema", "输出输入 Schema")
|
|
12
|
+
.option("--input <file|->", "从文件或标准输入读取 JSON")
|
|
13
|
+
.allowExcessArguments(false);
|
|
14
|
+
bindPreparedAction(send, "organization", async (signal) => {
|
|
15
|
+
signal.throwIfAborted();
|
|
16
|
+
const options = send.opts();
|
|
17
|
+
const modes = Number(options.schema === true) + Number(options.input !== undefined);
|
|
18
|
+
if (modes !== 1)
|
|
19
|
+
throw new CliUsageError();
|
|
20
|
+
if (options.schema === true) {
|
|
21
|
+
runtime.io.writeOut(`${JSON.stringify(agentSendInputSchema)}\n`);
|
|
22
|
+
return { handled: true };
|
|
23
|
+
}
|
|
24
|
+
const input = await runtime.jsonInput.read(options.input, signal);
|
|
25
|
+
runtime.validators.agentSendInput(input);
|
|
26
|
+
return { handled: false, input };
|
|
27
|
+
}, async (context, input, signal) => {
|
|
28
|
+
const result = await runtime.agent.send({
|
|
29
|
+
input,
|
|
30
|
+
access: {
|
|
31
|
+
credential: context.state.credential,
|
|
32
|
+
organizationId: context.state.organization.id
|
|
33
|
+
},
|
|
34
|
+
signal
|
|
35
|
+
});
|
|
36
|
+
runtime.validators.agentSendOutput(result);
|
|
37
|
+
runtime.io.writeOut(`${JSON.stringify(result)}\n`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { bindAction } from "./action-binding.js";
|
|
2
|
+
import { authStatusView } from "./presenter.js";
|
|
3
|
+
export function registerAuthCommands(program, runtime) {
|
|
4
|
+
const auth = program.command("auth")
|
|
5
|
+
.description("登录与本机凭证")
|
|
6
|
+
.helpCommand(false);
|
|
7
|
+
const login = leaf(auth.command("login"))
|
|
8
|
+
.description("登录稿定")
|
|
9
|
+
.option("--no-browser", "不自动打开浏览器");
|
|
10
|
+
bindAction(login, "none", async (_context, signal) => {
|
|
11
|
+
const result = await runtime.auth.login({
|
|
12
|
+
noBrowser: login.opts().browser === false,
|
|
13
|
+
signal,
|
|
14
|
+
interaction: {
|
|
15
|
+
showAuthorization: (url) => runtime.presenter.authorization({
|
|
16
|
+
url,
|
|
17
|
+
terminal: runtime.io.stderrTerminal
|
|
18
|
+
}),
|
|
19
|
+
openBrowser: (url) => runtime.browser.open(url),
|
|
20
|
+
warn: (message) => runtime.presenter.warning(message)
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
runtime.presenter.success(result.status === "already_logged_in" ? "已登录。" : "登录成功。");
|
|
24
|
+
if (result.status === "already_logged_in" && !result.organizationSelected) {
|
|
25
|
+
runtime.presenter.warning("尚未选择组织,请执行 gd-cli org switch。");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const status = leaf(auth.command("status"))
|
|
29
|
+
.description("查看登录状态")
|
|
30
|
+
.option("--json", "输出 JSON");
|
|
31
|
+
bindAction(status, "none", async () => {
|
|
32
|
+
const result = await runtime.auth.status({ now: runtime.now() });
|
|
33
|
+
runtime.validators.authStatus(result);
|
|
34
|
+
runtime.presenter.result(result, {
|
|
35
|
+
json: status.opts().json === true,
|
|
36
|
+
view: authStatusView
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
const logout = leaf(auth.command("logout")).description("退出登录");
|
|
40
|
+
bindAction(logout, "none", async () => {
|
|
41
|
+
await runtime.auth.logout();
|
|
42
|
+
runtime.presenter.success("已退出登录。");
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function leaf(command) {
|
|
46
|
+
return command.allowExcessArguments(false);
|
|
47
|
+
}
|