gaoding-cli 1.0.0-alpha.12 → 1.0.0-alpha.14
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 +3 -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 +3 -1
- package/dist/src/bootstrap/create-cli.js +36 -3
- package/dist/src/bootstrap/create-runtime.js +32 -7
- 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 +19 -1
- package/dist/src/cli/model-commands.js +41 -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/sso-service.js +17 -2
- package/dist/src/features/auth/use-cases.js +82 -52
- 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 +35 -33
- package/dist/src/features/tool/use-cases.js +68 -36
- package/dist/src/features/update/update-service.js +28 -22
- package/dist/src/platform/json-input.js +3 -0
- package/dist/src/platform/remote-protocol.js +6 -0
- package/dist/src/telemetry/invocation.js +128 -0
- package/dist/src/telemetry/sls-sink.js +31 -0
- package/package.json +1 -1
- package/skills/gd-cli/references/creation.md +4 -2
- package/skills/gd-cli/references/errors.md +3 -1
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { RemoteRequestError } from "../../platform/signed-http-transport.js";
|
|
2
2
|
import { projectDamAssetDetail, projectDamAssetSummary } from "./asset-projection.js";
|
|
3
|
+
export class DamAssetNotFoundError extends Error {
|
|
4
|
+
constructor() {
|
|
5
|
+
super("DAM 素材不存在。");
|
|
6
|
+
this.name = "DamAssetNotFoundError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
3
9
|
const contentFormats = {
|
|
4
10
|
image: ["gdpic", "gdimage"],
|
|
5
11
|
video: ["gdvideo"],
|
|
@@ -152,10 +158,19 @@ export function createDamApiAdapter(dependencies) {
|
|
|
152
158
|
return searchResult(response, input);
|
|
153
159
|
},
|
|
154
160
|
async getAsset(input) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
let response;
|
|
162
|
+
try {
|
|
163
|
+
response = await dependencies.transport.getJson({
|
|
164
|
+
path: `/dam/asset/${encodeURIComponent(input.assetId)}`,
|
|
165
|
+
...requestContext(input)
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (error instanceof RemoteRequestError && error.status === 404) {
|
|
170
|
+
throw new DamAssetNotFoundError();
|
|
171
|
+
}
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
159
174
|
const asset = projectDamAssetDetail(response, input.assetId);
|
|
160
175
|
if (asset === undefined)
|
|
161
176
|
throw new RemoteRequestError();
|
|
@@ -66,6 +66,8 @@ const defaultPutOss = async (input) => {
|
|
|
66
66
|
accessKeyId: input.token.accessKeyId,
|
|
67
67
|
accessKeySecret: input.token.accessKeySecret,
|
|
68
68
|
stsToken: input.token.securityToken,
|
|
69
|
+
// DAM issues one-shot credentials without a refresh endpoint.
|
|
70
|
+
refreshSTSTokenInterval: Number.MAX_SAFE_INTEGER,
|
|
69
71
|
endpoint: input.endpoint,
|
|
70
72
|
region: input.token.region,
|
|
71
73
|
bucket: input.token.bucketName,
|
|
@@ -114,24 +114,45 @@ export function createDamRegisteredUploader(dependencies) {
|
|
|
114
114
|
return {
|
|
115
115
|
async upload(input) {
|
|
116
116
|
try {
|
|
117
|
+
const stage = (name, run) => (dependencies.telemetry.stage(name, async () => {
|
|
118
|
+
try {
|
|
119
|
+
return await run();
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
if (input.signal.aborted)
|
|
123
|
+
throw input.signal.reason;
|
|
124
|
+
if (error instanceof RemoteRequestError)
|
|
125
|
+
throw error;
|
|
126
|
+
throw new RemoteRequestError();
|
|
127
|
+
}
|
|
128
|
+
}));
|
|
117
129
|
input.signal.throwIfAborted();
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
const prepared = await stage("prepare", async () => {
|
|
131
|
+
const [digest, metadata] = await Promise.all([
|
|
132
|
+
hashes(input.file.filePath, input.signal),
|
|
133
|
+
localMetadata(input.file, input.signal)
|
|
134
|
+
]);
|
|
135
|
+
input.signal.throwIfAborted();
|
|
136
|
+
const contentId = await dependencies.api.createAssetId({
|
|
137
|
+
access: input.access,
|
|
138
|
+
signal: input.signal
|
|
139
|
+
});
|
|
140
|
+
const format = input.file.format.toLowerCase();
|
|
141
|
+
return {
|
|
142
|
+
digest,
|
|
143
|
+
metadata,
|
|
144
|
+
contentId,
|
|
145
|
+
format,
|
|
146
|
+
damFormat: storageFormat(format),
|
|
147
|
+
title: input.input.title ?? filenameTitle(input.file.filename),
|
|
148
|
+
folderId: input.input.folderId ?? "0"
|
|
149
|
+
};
|
|
126
150
|
});
|
|
127
|
-
const
|
|
151
|
+
const { digest, metadata, contentId, format, damFormat, title, folderId } = prepared;
|
|
152
|
+
const stored = await stage("upload", () => dependencies.storage.upload({
|
|
128
153
|
file: input.file,
|
|
129
154
|
contentId
|
|
130
|
-
}, input.access, input.signal);
|
|
131
|
-
const format = input.file.format.toLowerCase();
|
|
132
|
-
const damFormat = storageFormat(format);
|
|
133
|
-
const title = input.input.title ?? filenameTitle(input.file.filename);
|
|
134
|
-
const folderId = input.input.folderId ?? "0";
|
|
155
|
+
}, input.access, input.signal));
|
|
135
156
|
const preview = input.file.mediaType.startsWith("image/")
|
|
136
157
|
? {
|
|
137
158
|
url: stored.url,
|
|
@@ -182,35 +203,37 @@ export function createDamRegisteredUploader(dependencies) {
|
|
|
182
203
|
});
|
|
183
204
|
if (fallback === undefined)
|
|
184
205
|
throw new RemoteRequestError();
|
|
185
|
-
let latest = await dependencies.api.createMaterial({
|
|
206
|
+
let latest = await stage("persist", () => dependencies.api.createMaterial({
|
|
186
207
|
body,
|
|
187
208
|
fallback,
|
|
188
209
|
access: input.access,
|
|
189
210
|
signal: input.signal
|
|
190
|
-
});
|
|
211
|
+
}));
|
|
191
212
|
if (input.input.waitAnalysis !== true || terminalAnalysisStatus(latest.analysis_status)) {
|
|
192
213
|
return latest;
|
|
193
214
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
return stage("wait", async () => {
|
|
216
|
+
const deadline = now().getTime() + 180_000;
|
|
217
|
+
while (true) {
|
|
218
|
+
input.signal.throwIfAborted();
|
|
219
|
+
const current = await dependencies.api.getBatchStatus({
|
|
220
|
+
assetId: latest.asset_id,
|
|
221
|
+
fallback: latest,
|
|
222
|
+
access: input.access,
|
|
223
|
+
signal: input.signal
|
|
224
|
+
});
|
|
225
|
+
if (current !== null)
|
|
226
|
+
latest = current;
|
|
227
|
+
if (terminalAnalysisStatus(latest.analysis_status))
|
|
228
|
+
return latest;
|
|
229
|
+
const remaining = deadline - now().getTime();
|
|
230
|
+
if (remaining <= 0) {
|
|
231
|
+
dependencies.warn("素材分析仍在处理中,已返回当前结果。");
|
|
232
|
+
return latest;
|
|
233
|
+
}
|
|
234
|
+
await sleep(Math.min(3000, remaining), input.signal);
|
|
211
235
|
}
|
|
212
|
-
|
|
213
|
-
}
|
|
236
|
+
});
|
|
214
237
|
}
|
|
215
238
|
catch (error) {
|
|
216
239
|
if (input.signal.aborted)
|
|
@@ -62,57 +62,63 @@ export function createDamUseCases(dependencies) {
|
|
|
62
62
|
async list({ input, access, signal }) {
|
|
63
63
|
signal.throwIfAborted();
|
|
64
64
|
assertPageSize(input.pageSize);
|
|
65
|
-
const repositories = await resolveRepositories(input, access, signal);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
const repositories = await dependencies.telemetry.stage("repository", () => (resolveRepositories(input, access, signal)));
|
|
66
|
+
return dependencies.telemetry.stage("request", async () => {
|
|
67
|
+
const result = await dependencies.api.search({
|
|
68
|
+
...searchRequest(input, "", repositories.map((repository) => repository.id)),
|
|
69
|
+
access,
|
|
70
|
+
signal
|
|
71
|
+
});
|
|
72
|
+
signal.throwIfAborted();
|
|
73
|
+
validate.list(result);
|
|
74
|
+
return result;
|
|
70
75
|
});
|
|
71
|
-
signal.throwIfAborted();
|
|
72
|
-
validate.list(result);
|
|
73
|
-
return result;
|
|
74
76
|
},
|
|
75
77
|
async search({ input, access, signal }) {
|
|
76
78
|
signal.throwIfAborted();
|
|
77
79
|
if (!nonblank(input.query))
|
|
78
80
|
invalid();
|
|
79
81
|
assertPageSize(input.pageSize);
|
|
80
|
-
const repositories = await resolveRepositories(input, access, signal);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
const repositories = await dependencies.telemetry.stage("repository", () => (resolveRepositories(input, access, signal)));
|
|
83
|
+
return dependencies.telemetry.stage("request", async () => {
|
|
84
|
+
const result = await dependencies.api.search({
|
|
85
|
+
...searchRequest(input, input.query, repositories.map((repository) => repository.id)),
|
|
86
|
+
access,
|
|
87
|
+
signal
|
|
88
|
+
});
|
|
89
|
+
signal.throwIfAborted();
|
|
90
|
+
validate.search(result);
|
|
91
|
+
return result;
|
|
85
92
|
});
|
|
86
|
-
signal.throwIfAborted();
|
|
87
|
-
validate.search(result);
|
|
88
|
-
return result;
|
|
89
93
|
},
|
|
90
94
|
async get({ input, access, signal }) {
|
|
91
95
|
signal.throwIfAborted();
|
|
92
96
|
assertAssetId(input.asset_id);
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
+
return dependencies.telemetry.stage("request", async () => {
|
|
98
|
+
const result = await dependencies.api.getAsset({
|
|
99
|
+
assetId: input.asset_id,
|
|
100
|
+
access,
|
|
101
|
+
signal
|
|
102
|
+
});
|
|
103
|
+
signal.throwIfAborted();
|
|
104
|
+
validate.get(result);
|
|
105
|
+
return result;
|
|
97
106
|
});
|
|
98
|
-
signal.throwIfAborted();
|
|
99
|
-
validate.get(result);
|
|
100
|
-
return result;
|
|
101
107
|
},
|
|
102
108
|
async upload({ input, access, signal }) {
|
|
103
109
|
signal.throwIfAborted();
|
|
104
110
|
if (!nonblank(input.file))
|
|
105
111
|
invalid();
|
|
106
|
-
const file = await dependencies.storage.inspect({
|
|
112
|
+
const file = await dependencies.telemetry.stage("inspect", () => (dependencies.storage.inspect({
|
|
107
113
|
url: pathToFileURL(resolve(process.cwd(), input.file)).href,
|
|
108
114
|
...(input.allowSensitivePath === undefined
|
|
109
115
|
? {}
|
|
110
116
|
: { allowSensitivePath: input.allowSensitivePath })
|
|
111
|
-
}, signal);
|
|
117
|
+
}, signal)));
|
|
112
118
|
signal.throwIfAborted();
|
|
113
|
-
const [repository] = await resolveRepositories({
|
|
119
|
+
const [repository] = await dependencies.telemetry.stage("repository", () => (resolveRepositories({
|
|
114
120
|
...(input.repositoryId === undefined ? {} : { repositoryId: input.repositoryId })
|
|
115
|
-
}, access, signal);
|
|
121
|
+
}, access, signal)));
|
|
116
122
|
if (repository === undefined)
|
|
117
123
|
throw new RemoteRequestError();
|
|
118
124
|
const result = await dependencies.uploader.upload({
|
|
@@ -129,9 +135,9 @@ export function createDamUseCases(dependencies) {
|
|
|
129
135
|
async delete({ input, access, signal }) {
|
|
130
136
|
signal.throwIfAborted();
|
|
131
137
|
assertAssetId(input.asset_id);
|
|
132
|
-
const [repository] = await resolveRepositories({
|
|
138
|
+
const [repository] = await dependencies.telemetry.stage("repository", () => (resolveRepositories({
|
|
133
139
|
...(input.repositoryId === undefined ? {} : { repositoryId: input.repositoryId })
|
|
134
|
-
}, access, signal);
|
|
140
|
+
}, access, signal)));
|
|
135
141
|
if (repository === undefined)
|
|
136
142
|
throw new RemoteRequestError();
|
|
137
143
|
const request = {
|
|
@@ -140,10 +146,11 @@ export function createDamUseCases(dependencies) {
|
|
|
140
146
|
access,
|
|
141
147
|
signal
|
|
142
148
|
};
|
|
143
|
-
await dependencies.api.recycle(request);
|
|
149
|
+
await dependencies.telemetry.stage("recycle", () => dependencies.api.recycle(request));
|
|
144
150
|
signal.throwIfAborted();
|
|
145
|
-
if (input.permanent === true)
|
|
146
|
-
await dependencies.api.deleteRecycled(request);
|
|
151
|
+
if (input.permanent === true) {
|
|
152
|
+
await dependencies.telemetry.stage("delete", () => dependencies.api.deleteRecycled(request));
|
|
153
|
+
}
|
|
147
154
|
signal.throwIfAborted();
|
|
148
155
|
validate.delete(null);
|
|
149
156
|
}
|
|
@@ -38,7 +38,11 @@ export function createOrgUseCases(dependencies) {
|
|
|
38
38
|
}
|
|
39
39
|
return {
|
|
40
40
|
async list(input) {
|
|
41
|
-
|
|
41
|
+
dependencies.telemetry.annotate({
|
|
42
|
+
account_id: input.state.account?.id,
|
|
43
|
+
organization_id: input.state.organization?.id
|
|
44
|
+
});
|
|
45
|
+
const records = await dependencies.telemetry.stage("list", () => dependencies.org.list(input.state.credential, input.signal));
|
|
42
46
|
return {
|
|
43
47
|
orgs: records.map((record) => ({
|
|
44
48
|
id: record.id,
|
|
@@ -53,7 +57,13 @@ export function createOrgUseCases(dependencies) {
|
|
|
53
57
|
};
|
|
54
58
|
},
|
|
55
59
|
async current() {
|
|
56
|
-
const state = await dependencies.store.read();
|
|
60
|
+
const state = await dependencies.telemetry.stage("state", () => dependencies.store.read());
|
|
61
|
+
if (state) {
|
|
62
|
+
dependencies.telemetry.annotate({
|
|
63
|
+
account_id: state.account?.id,
|
|
64
|
+
organization_id: state.organization?.id
|
|
65
|
+
});
|
|
66
|
+
}
|
|
57
67
|
return {
|
|
58
68
|
organization: state?.organization
|
|
59
69
|
? { id: state.organization.id, name: state.organization.name }
|
|
@@ -65,15 +75,21 @@ export function createOrgUseCases(dependencies) {
|
|
|
65
75
|
},
|
|
66
76
|
async switchOrganization(input) {
|
|
67
77
|
input.signal.throwIfAborted();
|
|
68
|
-
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
dependencies.telemetry.annotate({ account_id: input.state.account?.id });
|
|
79
|
+
const records = await dependencies.telemetry.stage("list", () => dependencies.org.list(input.state.credential, input.signal));
|
|
80
|
+
const { record, selectedId } = await dependencies.telemetry.stage("select", async () => {
|
|
81
|
+
const selectedId = input.organizationId === undefined
|
|
82
|
+
? await selectOrganization(records, input.select)
|
|
83
|
+
: requiredSelection(input.organizationId);
|
|
84
|
+
const record = records.find((candidate) => candidate.id === selectedId);
|
|
85
|
+
if (!record)
|
|
86
|
+
throw new OrganizationInvalidError();
|
|
87
|
+
return { record, selectedId };
|
|
88
|
+
});
|
|
89
|
+
dependencies.telemetry.annotate({ parameters: { organizationId: selectedId } });
|
|
90
|
+
const organization = await dependencies.telemetry.stage("bind", () => bind(input.state.credential, record, input.signal));
|
|
91
|
+
await dependencies.telemetry.stage("state", () => dependencies.store.write({ ...input.state, organization }));
|
|
92
|
+
dependencies.telemetry.annotate({ organization_id: organization.id });
|
|
77
93
|
return record;
|
|
78
94
|
},
|
|
79
95
|
async bindAuthorizedOrganization(input) {
|
|
@@ -56,10 +56,14 @@ export function projectModelList(catalog, tool) {
|
|
|
56
56
|
.map(summary)
|
|
57
57
|
};
|
|
58
58
|
}
|
|
59
|
-
export function
|
|
59
|
+
export function findModel(catalog, model) {
|
|
60
60
|
const found = catalog.models.find((candidate) => candidate.model === model);
|
|
61
61
|
if (found === undefined)
|
|
62
62
|
throw new ToolInputError();
|
|
63
|
+
return found;
|
|
64
|
+
}
|
|
65
|
+
export function projectModelDetail(catalog, model) {
|
|
66
|
+
const found = findModel(catalog, model);
|
|
63
67
|
return {
|
|
64
68
|
...summary(found),
|
|
65
69
|
...(found.usageDescription === undefined
|
|
@@ -72,8 +76,8 @@ export function projectModelDetail(catalog, model) {
|
|
|
72
76
|
};
|
|
73
77
|
}
|
|
74
78
|
export function findToolModel(catalog, tool, model) {
|
|
75
|
-
const found = catalog
|
|
76
|
-
if (found
|
|
79
|
+
const found = findModel(catalog, model);
|
|
80
|
+
if (found.tool !== tool)
|
|
77
81
|
throw new ToolInputError();
|
|
78
82
|
return found;
|
|
79
83
|
}
|
|
@@ -11,6 +11,8 @@ function parameterSchema(parameter) {
|
|
|
11
11
|
if (parameter.type === "uri[]") {
|
|
12
12
|
return { type: "array", items: { type: "string", format: "uri" }, ...common };
|
|
13
13
|
}
|
|
14
|
+
if (parameter.type === "number")
|
|
15
|
+
return { type: "number", ...common };
|
|
14
16
|
return {
|
|
15
17
|
type: "string",
|
|
16
18
|
...(parameter.options === undefined
|
|
@@ -67,29 +69,37 @@ export function buildToolArgumentsSchema(catalog, tool) {
|
|
|
67
69
|
additionalProperties: false
|
|
68
70
|
};
|
|
69
71
|
}
|
|
70
|
-
|
|
71
|
-
const addFormats = addFormatsImport;
|
|
72
|
-
addFormats(ajv);
|
|
73
|
-
function validator(model) {
|
|
72
|
+
export function buildModelArgumentsSchema(model) {
|
|
74
73
|
const properties = {
|
|
75
|
-
model: {
|
|
74
|
+
model: {
|
|
75
|
+
type: "string",
|
|
76
|
+
const: model.model,
|
|
77
|
+
description: "要调用的模型机器标识。"
|
|
78
|
+
}
|
|
76
79
|
};
|
|
77
80
|
for (const parameter of model.parameters) {
|
|
78
81
|
properties[parameter.name] = parameterSchema(parameter);
|
|
79
82
|
}
|
|
80
|
-
return
|
|
83
|
+
return {
|
|
81
84
|
type: "object",
|
|
82
85
|
properties,
|
|
83
86
|
required: [
|
|
84
87
|
"model",
|
|
85
|
-
...model.parameters
|
|
88
|
+
...model.parameters
|
|
89
|
+
.filter((parameter) => parameter.required)
|
|
90
|
+
.map((parameter) => parameter.name)
|
|
86
91
|
],
|
|
87
92
|
additionalProperties: false
|
|
88
|
-
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const ajv = new Ajv2020({ allErrors: true, strict: true });
|
|
96
|
+
const addFormats = addFormatsImport;
|
|
97
|
+
addFormats(ajv);
|
|
98
|
+
function validator(model) {
|
|
99
|
+
return ajv.compile(buildModelArgumentsSchema(model));
|
|
89
100
|
}
|
|
90
101
|
export function assertModelArguments(model, value) {
|
|
91
102
|
if (typeof value !== "object" || value === null
|
|
92
|
-
|| value.model !== model.model
|
|
93
103
|
|| !validator(model)(value)) {
|
|
94
104
|
throw new ToolInputError();
|
|
95
105
|
}
|
|
@@ -18,6 +18,7 @@ const toolOrder = {
|
|
|
18
18
|
};
|
|
19
19
|
const multiUriKeys = new Set([
|
|
20
20
|
"image_urls",
|
|
21
|
+
"reference_images",
|
|
21
22
|
"file_urls",
|
|
22
23
|
"video_urls",
|
|
23
24
|
"audio_urls"
|
|
@@ -98,9 +99,11 @@ function parameter(value) {
|
|
|
98
99
|
? "uri[]"
|
|
99
100
|
: name === "start_frame" || name === "end_frame" || sourceType === "IMAGE"
|
|
100
101
|
? "uri"
|
|
101
|
-
: sourceType === "
|
|
102
|
-
? "
|
|
103
|
-
:
|
|
102
|
+
: sourceType === "NUMBER"
|
|
103
|
+
? "number"
|
|
104
|
+
: sourceType === "TEXT" || sourceType === "INPUT" || sourceType === "SELECT"
|
|
105
|
+
? "string"
|
|
106
|
+
: undefined;
|
|
104
107
|
if (type === undefined)
|
|
105
108
|
throw new Error("unsupported parameter");
|
|
106
109
|
let options;
|
|
@@ -120,7 +123,7 @@ function parameter(value) {
|
|
|
120
123
|
if (options.length === 0)
|
|
121
124
|
throw new Error("empty options");
|
|
122
125
|
}
|
|
123
|
-
const description = text(field.
|
|
126
|
+
const description = text(field.description) ?? text(field.label);
|
|
124
127
|
const defaultValue = field.default_value;
|
|
125
128
|
const hasDefault = defaultValue !== undefined
|
|
126
129
|
&& defaultValue !== null
|
|
@@ -138,7 +138,7 @@ export function createToolApiAdapter(dependencies) {
|
|
|
138
138
|
async execute({ invocation, access, signal }) {
|
|
139
139
|
signal.throwIfAborted();
|
|
140
140
|
const managedContentId = contentId(createContentId());
|
|
141
|
-
const intent = parseIntent(await safePost(dependencies.transport, {
|
|
141
|
+
const intent = await dependencies.telemetry.stage("intent", async () => parseIntent(await safePost(dependencies.transport, {
|
|
142
142
|
path: "/ai-agent/v1/tool-intent",
|
|
143
143
|
body: {
|
|
144
144
|
prompt: invocation.prompt,
|
|
@@ -148,9 +148,9 @@ export function createToolApiAdapter(dependencies) {
|
|
|
148
148
|
credential: access.credential,
|
|
149
149
|
organizationId: access.organizationId,
|
|
150
150
|
signal
|
|
151
|
-
}));
|
|
151
|
+
})));
|
|
152
152
|
signal.throwIfAborted();
|
|
153
|
-
const taskId = submittedTask(await safePost(dependencies.transport, {
|
|
153
|
+
const taskId = await dependencies.telemetry.stage("submit", async () => submittedTask(await safePost(dependencies.transport, {
|
|
154
154
|
path: "/gdesign/tool/v1/dify/call_async",
|
|
155
155
|
body: {
|
|
156
156
|
jsonrpc: "2.0",
|
|
@@ -164,37 +164,39 @@ export function createToolApiAdapter(dependencies) {
|
|
|
164
164
|
credential: access.credential,
|
|
165
165
|
organizationId: access.organizationId,
|
|
166
166
|
signal
|
|
167
|
-
}));
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
167
|
+
})));
|
|
168
|
+
return dependencies.telemetry.stage("wait", async () => {
|
|
169
|
+
let transientFailures = 0;
|
|
170
|
+
while (true) {
|
|
171
|
+
signal.throwIfAborted();
|
|
172
|
+
let response;
|
|
173
|
+
try {
|
|
174
|
+
response = await safePost(dependencies.transport, {
|
|
175
|
+
path: "/gdesign/tool/v1/dify/process/batch",
|
|
176
|
+
body: { task_ids: [taskId] },
|
|
177
|
+
credential: access.credential,
|
|
178
|
+
organizationId: access.organizationId,
|
|
179
|
+
signal
|
|
180
|
+
});
|
|
181
|
+
transientFailures = 0;
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (signal.aborted)
|
|
185
|
+
throw signal.reason;
|
|
186
|
+
if (!(error instanceof RemoteRequestError) || !error.transient)
|
|
187
|
+
throw error;
|
|
188
|
+
transientFailures += 1;
|
|
189
|
+
if (transientFailures > 3)
|
|
190
|
+
throw error;
|
|
191
|
+
await sleep(transientFailures * 1_000, signal);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const result = pollResult(response, taskId);
|
|
195
|
+
if (result !== undefined)
|
|
196
|
+
return result;
|
|
197
|
+
await sleep(2_000, signal);
|
|
192
198
|
}
|
|
193
|
-
|
|
194
|
-
if (result !== undefined)
|
|
195
|
-
return result;
|
|
196
|
-
await sleep(2_000, signal);
|
|
197
|
-
}
|
|
199
|
+
});
|
|
198
200
|
}
|
|
199
201
|
};
|
|
200
202
|
}
|