gaoding-cli 1.0.0-alpha.15 → 1.0.0-alpha.16

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.
@@ -47,6 +47,21 @@ function parseIntent(value) {
47
47
  arguments: parseRecord(nonBlank(value.arguments))
48
48
  };
49
49
  }
50
+ function isEmptyOptionalMedia(value) {
51
+ return value === undefined
52
+ || value === null
53
+ || value === ""
54
+ || (Array.isArray(value) && value.length === 0)
55
+ || (typeof value === "string" && value.trim() === "[]");
56
+ }
57
+ function withoutEmptyOptionalMedia(value, optionalMediaParameters) {
58
+ const normalized = { ...value };
59
+ for (const name of optionalMediaParameters) {
60
+ if (isEmptyOptionalMedia(normalized[name]))
61
+ delete normalized[name];
62
+ }
63
+ return normalized;
64
+ }
50
65
  function submittedTask(value) {
51
66
  if (!isRecord(value) || !isRecord(value.result))
52
67
  return protocolFailure(value);
@@ -143,6 +158,17 @@ function optionalInnerDifyTaskId(value) {
143
158
  return undefined;
144
159
  }
145
160
  }
161
+ function isJsonRpcError(value) {
162
+ if (value.jsonrpc !== "2.0"
163
+ || Object.prototype.hasOwnProperty.call(value, "result")
164
+ || !isRecord(value.error)) {
165
+ return false;
166
+ }
167
+ return typeof value.error.code === "number"
168
+ && Number.isInteger(value.error.code)
169
+ && typeof value.error.message === "string"
170
+ && value.error.message.trim() !== "";
171
+ }
146
172
  function pollResult(value, taskId) {
147
173
  if (!Array.isArray(value))
148
174
  return protocolFailure(value);
@@ -175,6 +201,11 @@ function pollResult(value, taskId) {
175
201
  && (typeof difyTaskId !== "string" || difyTaskId.trim() === "")) {
176
202
  return protocolFailure(inner);
177
203
  }
204
+ if (Object.prototype.hasOwnProperty.call(inner, "error")) {
205
+ return isJsonRpcError(inner)
206
+ ? failedPoll(new ToolTaskFailedError(remoteErrorEvidence(inner)), difyTaskId)
207
+ : failedPoll(new RemoteProtocolError(remoteErrorEvidence(inner)), difyTaskId);
208
+ }
178
209
  if (!isRecord(inner.result)) {
179
210
  return failedPoll(new RemoteProtocolError(remoteErrorEvidence(inner)), difyTaskId);
180
211
  }
@@ -240,17 +271,25 @@ export function createToolApiAdapter(dependencies) {
240
271
  async execute({ invocation, access, signal }) {
241
272
  signal.throwIfAborted();
242
273
  const managedContentId = contentId(createContentId());
243
- const intent = await dependencies.telemetry.stage("intent", async () => parseIntent(await safePost(dependencies.transport, {
244
- path: "/ai-agent/v1/tool-intent",
245
- body: {
246
- prompt: invocation.prompt,
247
- scene_code: invocation.model,
248
- parameters: invocation.parameters
249
- },
250
- credential: access.credential,
251
- organizationId: access.organizationId,
252
- signal
253
- })));
274
+ const resolved = invocation.kind === "direct"
275
+ ? { name: invocation.name, arguments: invocation.arguments }
276
+ : await dependencies.telemetry.stage("intent", async () => {
277
+ const intent = parseIntent(await safePost(dependencies.transport, {
278
+ path: "/ai-agent/v1/tool-intent",
279
+ body: {
280
+ prompt: invocation.prompt,
281
+ scene_code: invocation.model,
282
+ parameters: invocation.parameters
283
+ },
284
+ credential: access.credential,
285
+ organizationId: access.organizationId,
286
+ signal
287
+ }));
288
+ return {
289
+ ...intent,
290
+ arguments: withoutEmptyOptionalMedia(intent.arguments, invocation.optionalMediaParameters)
291
+ };
292
+ });
254
293
  signal.throwIfAborted();
255
294
  const taskId = await dependencies.telemetry.stage("submit", async () => {
256
295
  dependencies.telemetry.annotate({ content_id: managedContentId });
@@ -261,8 +300,8 @@ export function createToolApiAdapter(dependencies) {
261
300
  id: 0,
262
301
  method: "tools/call",
263
302
  params: {
264
- name: intent.name,
265
- arguments: { ...intent.arguments, content_id: managedContentId }
303
+ name: resolved.name,
304
+ arguments: { ...resolved.arguments, content_id: managedContentId }
266
305
  }
267
306
  },
268
307
  credential: access.credential,
@@ -86,6 +86,7 @@ export function createToolUseCases(dependencies) {
86
86
  });
87
87
  const prompt = [];
88
88
  const requestParameters = {};
89
+ const directArguments = {};
89
90
  const prepare = async () => {
90
91
  for (const parameter of model.parameters) {
91
92
  signal.throwIfAborted();
@@ -95,14 +96,17 @@ export function createToolUseCases(dependencies) {
95
96
  if (parameter.type === "string") {
96
97
  if (parameter.name === "prompt") {
97
98
  prompt.push({ type: "text", content: value });
99
+ directArguments[parameter.name] = value;
98
100
  }
99
101
  else {
100
102
  requestParameters[parameter.name] = value;
103
+ directArguments[parameter.name] = value;
101
104
  }
102
105
  continue;
103
106
  }
104
107
  if (parameter.type === "number") {
105
108
  requestParameters[parameter.name] = value;
109
+ directArguments[parameter.name] = value;
106
110
  continue;
107
111
  }
108
112
  const values = parameter.type === "uri[]" ? value : [value];
@@ -138,8 +142,26 @@ export function createToolUseCases(dependencies) {
138
142
  await prepare();
139
143
  }
140
144
  signal.throwIfAborted();
145
+ const requiresIntent = prompt.some((item) => item.type === "media")
146
+ || Object.values(requestParameters).some((value) => value === "");
147
+ const invocation = requiresIntent
148
+ ? {
149
+ kind: "intent",
150
+ model: model.model,
151
+ prompt,
152
+ parameters: requestParameters,
153
+ optionalMediaParameters: model.parameters
154
+ .filter((parameter) => ((parameter.type === "uri" || parameter.type === "uri[]")
155
+ && !parameter.required))
156
+ .map((parameter) => parameter.name)
157
+ }
158
+ : {
159
+ kind: "direct",
160
+ name: model.model,
161
+ arguments: directArguments
162
+ };
141
163
  const content = await dependencies.execution.execute({
142
- invocation: { model: model.model, prompt, parameters: requestParameters },
164
+ invocation,
143
165
  access,
144
166
  signal
145
167
  });
@@ -3,7 +3,7 @@ const maximumLength = 8_192;
3
3
  const truncationMarker = "[TRUNCATED]";
4
4
  export function remoteErrorEvidence(value) {
5
5
  const normalized = parseJson(value);
6
- const remoteCode = topLevelCode(normalized);
6
+ const remoteCode = topLevelCode(normalized) ?? jsonRpcErrorCode(normalized);
7
7
  const sanitized = sanitize(normalized);
8
8
  if (sanitized === undefined) {
9
9
  return remoteCode === undefined ? {} : { remoteCode };
@@ -31,7 +31,21 @@ function topLevelCode(value) {
31
31
  return undefined;
32
32
  if (!Object.prototype.hasOwnProperty.call(value, "code"))
33
33
  return undefined;
34
- const code = value.code;
34
+ return normalizeCode(value.code);
35
+ }
36
+ function jsonRpcErrorCode(value) {
37
+ if (value === null || typeof value !== "object" || Array.isArray(value))
38
+ return undefined;
39
+ const record = value;
40
+ if (record.jsonrpc !== "2.0"
41
+ || record.error === null
42
+ || typeof record.error !== "object"
43
+ || Array.isArray(record.error)) {
44
+ return undefined;
45
+ }
46
+ return normalizeCode(record.error.code);
47
+ }
48
+ function normalizeCode(code) {
35
49
  if (typeof code === "string")
36
50
  return redactRemoteText(code);
37
51
  return typeof code === "number" ? String(code) : undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gaoding-cli",
3
- "version": "1.0.0-alpha.15",
3
+ "version": "1.0.0-alpha.16",
4
4
  "description": "Gaoding command-line interface for agents and people.",
5
5
  "type": "module",
6
6
  "license": "MIT",