@jskit-ai/assistant 0.1.4
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/package.descriptor.mjs +284 -0
- package/package.json +31 -0
- package/src/client/components/AssistantClientElement.vue +1316 -0
- package/src/client/components/AssistantConsoleSettingsClientElement.vue +71 -0
- package/src/client/components/AssistantSettingsFormCard.vue +76 -0
- package/src/client/components/AssistantWorkspaceClientElement.vue +15 -0
- package/src/client/components/AssistantWorkspaceSettingsClientElement.vue +73 -0
- package/src/client/composables/useAssistantWorkspaceRuntime.js +789 -0
- package/src/client/index.js +12 -0
- package/src/client/lib/assistantApi.js +137 -0
- package/src/client/lib/assistantHttpClient.js +10 -0
- package/src/client/lib/markdownRenderer.js +31 -0
- package/src/client/providers/AssistantWebClientProvider.js +25 -0
- package/src/server/AssistantServiceProvider.js +179 -0
- package/src/server/actionIds.js +11 -0
- package/src/server/actions.js +191 -0
- package/src/server/diTokens.js +19 -0
- package/src/server/lib/aiClient.js +43 -0
- package/src/server/lib/ndjson.js +47 -0
- package/src/server/lib/providers/anthropicClient.js +375 -0
- package/src/server/lib/providers/common.js +158 -0
- package/src/server/lib/providers/deepSeekClient.js +22 -0
- package/src/server/lib/providers/openAiClient.js +13 -0
- package/src/server/lib/providers/openAiCompatibleClient.js +69 -0
- package/src/server/lib/resolveWorkspaceSlug.js +24 -0
- package/src/server/lib/serviceToolCatalog.js +459 -0
- package/src/server/registerRoutes.js +384 -0
- package/src/server/repositories/assistantSettingsRepository.js +100 -0
- package/src/server/repositories/conversationsRepository.js +244 -0
- package/src/server/repositories/messagesRepository.js +154 -0
- package/src/server/repositories/repositoryPersistenceUtils.js +63 -0
- package/src/server/services/assistantSettingsService.js +153 -0
- package/src/server/services/chatService.js +987 -0
- package/src/server/services/transcriptService.js +334 -0
- package/src/shared/assistantPaths.js +50 -0
- package/src/shared/assistantResource.js +323 -0
- package/src/shared/assistantSettingsResource.js +214 -0
- package/src/shared/index.js +39 -0
- package/src/shared/queryKeys.js +69 -0
- package/src/shared/settingsEvents.js +7 -0
- package/src/shared/streamEvents.js +31 -0
- package/src/shared/support/positiveInteger.js +9 -0
- package/templates/migrations/assistant_settings_initial.cjs +39 -0
- package/templates/migrations/assistant_transcripts_initial.cjs +51 -0
- package/templates/src/pages/admin/workspace/assistant/index.vue +7 -0
- package/test/aiConfigValidation.test.js +15 -0
- package/test/assistantApiSurfaceHeader.test.js +64 -0
- package/test/assistantResource.test.js +53 -0
- package/test/assistantSettingsResource.test.js +48 -0
- package/test/assistantSettingsService.test.js +133 -0
- package/test/chatService.test.js +841 -0
- package/test/descriptorSurfaceOption.test.js +35 -0
- package/test/queryKeys.test.js +41 -0
- package/test/resolveWorkspaceSlug.test.js +83 -0
- package/test/routeInputContracts.test.js +287 -0
- package/test/serviceToolCatalog.test.js +1235 -0
- package/test/transcriptService.test.js +175 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import { requireAuth } from "@jskit-ai/kernel/server/runtime";
|
|
2
|
+
import { resolveActionContributors } from "@jskit-ai/kernel/server/actions";
|
|
3
|
+
import { normalizeActionDefinition } from "@jskit-ai/kernel/shared/actions";
|
|
4
|
+
import { normalizeText } from "@jskit-ai/kernel/shared/support/normalize";
|
|
5
|
+
import { resolveWorkspaceSlug } from "./resolveWorkspaceSlug.js";
|
|
6
|
+
|
|
7
|
+
const AUTOMATION_CHANNEL = "automation";
|
|
8
|
+
|
|
9
|
+
function normalizeAssistantExtension(value) {
|
|
10
|
+
const source = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
11
|
+
return Object.freeze({
|
|
12
|
+
description: normalizeText(source.description)
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function normalizeAssistantActionExtension(action = {}) {
|
|
17
|
+
const source = action && typeof action === "object" && !Array.isArray(action) ? action : {};
|
|
18
|
+
const actionId = normalizeText(source.id);
|
|
19
|
+
|
|
20
|
+
if (Object.prototype.hasOwnProperty.call(source, "assistantTool")) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`Action definition \"${actionId || "<unknown>"}\" assistantTool is not supported. Use extensions.assistant instead.`
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const extensions = source.extensions && typeof source.extensions === "object" && !Array.isArray(source.extensions)
|
|
27
|
+
? source.extensions
|
|
28
|
+
: {};
|
|
29
|
+
return normalizeAssistantExtension(extensions.assistant);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function normalizeBarredEntry(value) {
|
|
33
|
+
return normalizeText(value).toLowerCase();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function normalizeBarredActionSet(value) {
|
|
37
|
+
const source = Array.isArray(value) ? value : [value];
|
|
38
|
+
const exact = new Set();
|
|
39
|
+
const prefixes = [];
|
|
40
|
+
|
|
41
|
+
for (const entry of source) {
|
|
42
|
+
const normalized = normalizeBarredEntry(entry);
|
|
43
|
+
if (!normalized) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (normalized.endsWith(".*")) {
|
|
48
|
+
const prefix = normalized.slice(0, -1);
|
|
49
|
+
if (prefix) {
|
|
50
|
+
prefixes.push(prefix);
|
|
51
|
+
}
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
exact.add(normalized);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return Object.freeze({
|
|
59
|
+
exact,
|
|
60
|
+
prefixes: Object.freeze(prefixes)
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function isActionBarred(barredRules, actionId) {
|
|
65
|
+
const normalizedActionId = normalizeText(actionId).toLowerCase();
|
|
66
|
+
if (!normalizedActionId) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (barredRules.exact.has(normalizedActionId)) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return barredRules.prefixes.some((prefix) => normalizedActionId.startsWith(prefix));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function sanitizeToolName(value) {
|
|
78
|
+
const normalized = String(value || "")
|
|
79
|
+
.trim()
|
|
80
|
+
.toLowerCase()
|
|
81
|
+
.replace(/[^a-z0-9_]+/g, "_")
|
|
82
|
+
.replace(/_+/g, "_")
|
|
83
|
+
.replace(/^_+|_+$/g, "");
|
|
84
|
+
|
|
85
|
+
if (!normalized) {
|
|
86
|
+
return "tool";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return normalized;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function resolveUniqueToolName(baseName, used) {
|
|
93
|
+
const normalizedBase = sanitizeToolName(baseName) || "tool";
|
|
94
|
+
let candidate = normalizedBase.slice(0, 64);
|
|
95
|
+
let suffix = 1;
|
|
96
|
+
|
|
97
|
+
while (used.has(candidate)) {
|
|
98
|
+
const suffixText = `_${suffix}`;
|
|
99
|
+
const baseBudget = Math.max(1, 64 - suffixText.length);
|
|
100
|
+
candidate = `${normalizedBase.slice(0, baseBudget)}${suffixText}`;
|
|
101
|
+
suffix += 1;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
used.add(candidate);
|
|
105
|
+
return candidate;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function parseToolPayload(argumentsText) {
|
|
109
|
+
const source = String(argumentsText || "").trim();
|
|
110
|
+
if (!source) {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const parsed = JSON.parse(source);
|
|
116
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
117
|
+
return {};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (Array.isArray(parsed.args) || Object.hasOwn(parsed, "options")) {
|
|
121
|
+
const args = Array.isArray(parsed.args) ? parsed.args : [];
|
|
122
|
+
const options = parsed.options && typeof parsed.options === "object" && !Array.isArray(parsed.options)
|
|
123
|
+
? parsed.options
|
|
124
|
+
: {};
|
|
125
|
+
|
|
126
|
+
if (args.length === 1 && args[0] && typeof args[0] === "object" && !Array.isArray(args[0])) {
|
|
127
|
+
return {
|
|
128
|
+
...args[0],
|
|
129
|
+
...options
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
args,
|
|
135
|
+
...options
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return parsed;
|
|
140
|
+
} catch {
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function canInvokeMethod(permission, context) {
|
|
146
|
+
const permissionSpec = normalizePermissionSpec(permission);
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
requireAuth(
|
|
150
|
+
{
|
|
151
|
+
context
|
|
152
|
+
},
|
|
153
|
+
permissionSpec
|
|
154
|
+
);
|
|
155
|
+
return true;
|
|
156
|
+
} catch {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function normalizePermissionSpec(permission) {
|
|
162
|
+
const source = permission && typeof permission === "object" && !Array.isArray(permission)
|
|
163
|
+
? permission
|
|
164
|
+
: {};
|
|
165
|
+
const requireMode = normalizeText(source.require || "none").toLowerCase();
|
|
166
|
+
const permissions = Array.isArray(source.permissions) ? source.permissions : [];
|
|
167
|
+
|
|
168
|
+
return Object.freeze({
|
|
169
|
+
require: requireMode || "none",
|
|
170
|
+
permissions,
|
|
171
|
+
message: normalizeText(source.message),
|
|
172
|
+
code: normalizeText(source.code)
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function stripWorkspaceSlugFromSchema(schema, context = {}) {
|
|
177
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) {
|
|
178
|
+
return schema;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const workspaceSlug = resolveWorkspaceSlug(context);
|
|
182
|
+
if (!workspaceSlug) {
|
|
183
|
+
return schema;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if (schema.type !== "object" || !schema.properties || typeof schema.properties !== "object") {
|
|
187
|
+
return schema;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (!Object.hasOwn(schema.properties, "workspaceSlug")) {
|
|
191
|
+
return schema;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const properties = { ...schema.properties };
|
|
195
|
+
delete properties.workspaceSlug;
|
|
196
|
+
|
|
197
|
+
const requiredSource = Array.isArray(schema.required) ? schema.required : [];
|
|
198
|
+
const required = requiredSource.filter((entry) => entry !== "workspaceSlug");
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
...schema,
|
|
202
|
+
properties,
|
|
203
|
+
...(Array.isArray(schema.required) ? { required } : {})
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function hasAutomationChannel(action = {}) {
|
|
208
|
+
const channels = Array.isArray(action.channels) ? action.channels : [];
|
|
209
|
+
return channels.some((channel) => normalizeText(channel).toLowerCase() === AUTOMATION_CHANNEL);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function resolveActionBackedToolEntries(scope) {
|
|
213
|
+
if (!scope || typeof scope.has !== "function" || typeof scope.make !== "function") {
|
|
214
|
+
return new Map();
|
|
215
|
+
}
|
|
216
|
+
if (typeof scope.resolveTag !== "function") {
|
|
217
|
+
return new Map();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const entriesByActionId = new Map();
|
|
221
|
+
const contributors = resolveActionContributors(scope);
|
|
222
|
+
|
|
223
|
+
for (const contributor of contributors) {
|
|
224
|
+
const actions = Array.isArray(contributor?.actions) ? contributor.actions : [];
|
|
225
|
+
for (const action of actions) {
|
|
226
|
+
if (!action || typeof action !== "object") {
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (!hasAutomationChannel(action)) {
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const actionId = normalizeText(action.id);
|
|
234
|
+
if (!actionId) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
let normalizedAction = null;
|
|
239
|
+
let assistantExtension = null;
|
|
240
|
+
try {
|
|
241
|
+
assistantExtension = normalizeAssistantActionExtension(action);
|
|
242
|
+
normalizedAction = normalizeActionDefinition(action, {
|
|
243
|
+
contributorDomain: action.domain
|
|
244
|
+
});
|
|
245
|
+
} catch {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const inputSchema = normalizedAction.inputValidator?.schema || null;
|
|
250
|
+
const outputSchema = normalizedAction.outputValidator?.schema || null;
|
|
251
|
+
if (!inputSchema || !outputSchema) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const actionVersion = Number(normalizedAction.version) || 1;
|
|
256
|
+
const actionKey = actionId.toLowerCase();
|
|
257
|
+
const nextEntry = Object.freeze({
|
|
258
|
+
actionId,
|
|
259
|
+
actionVersion,
|
|
260
|
+
toolBaseName: actionId,
|
|
261
|
+
description: assistantExtension.description || `Run ${actionId}.`,
|
|
262
|
+
inputSchema,
|
|
263
|
+
outputSchema,
|
|
264
|
+
permission: normalizePermissionSpec(normalizedAction.permission)
|
|
265
|
+
});
|
|
266
|
+
const existing = entriesByActionId.get(actionKey);
|
|
267
|
+
if (!existing || actionVersion >= Number(existing.actionVersion || 0)) {
|
|
268
|
+
entriesByActionId.set(actionKey, nextEntry);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return entriesByActionId;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function resolveActionToolEntries(
|
|
277
|
+
scope,
|
|
278
|
+
{ barredActionIds = [], skipActionPrefixes = [] } = {}
|
|
279
|
+
) {
|
|
280
|
+
const actionBackedEntries = resolveActionBackedToolEntries(scope);
|
|
281
|
+
const barredRules = normalizeBarredActionSet(barredActionIds);
|
|
282
|
+
const usedToolNames = new Set();
|
|
283
|
+
const entries = [];
|
|
284
|
+
|
|
285
|
+
for (const actionEntry of actionBackedEntries.values()) {
|
|
286
|
+
const actionId = normalizeText(actionEntry?.actionId);
|
|
287
|
+
if (!actionId) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const normalizedActionId = actionId.toLowerCase();
|
|
292
|
+
const skipByPrefix = skipActionPrefixes.some((prefix) => normalizedActionId.startsWith(prefix));
|
|
293
|
+
if (skipByPrefix) {
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (isActionBarred(barredRules, actionId)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
const toolName = resolveUniqueToolName(actionEntry.toolBaseName, usedToolNames);
|
|
302
|
+
entries.push(
|
|
303
|
+
Object.freeze({
|
|
304
|
+
descriptor: Object.freeze({
|
|
305
|
+
name: toolName,
|
|
306
|
+
actionId,
|
|
307
|
+
actionVersion: Number(actionEntry.actionVersion) || null,
|
|
308
|
+
description: normalizeText(actionEntry.description) || `Run ${actionId}.`,
|
|
309
|
+
parameters: actionEntry.inputSchema,
|
|
310
|
+
outputSchema: actionEntry.outputSchema
|
|
311
|
+
}),
|
|
312
|
+
permission: actionEntry.permission
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return Object.freeze(entries.sort((left, right) => left.descriptor.name.localeCompare(right.descriptor.name)));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function createServiceToolCatalog(
|
|
321
|
+
scope,
|
|
322
|
+
{ barredActionIds = [], skipActionPrefixes = [] } = {}
|
|
323
|
+
) {
|
|
324
|
+
if (!scope || typeof scope.make !== "function") {
|
|
325
|
+
throw new Error("createServiceToolCatalog requires container scope.make().");
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const normalizedSkipPrefixes = (Array.isArray(skipActionPrefixes) ? skipActionPrefixes : [skipActionPrefixes])
|
|
329
|
+
.map((entry) => normalizeText(entry).toLowerCase())
|
|
330
|
+
.filter(Boolean);
|
|
331
|
+
let methodEntries = null;
|
|
332
|
+
|
|
333
|
+
function resolveOrCreateMethodEntries() {
|
|
334
|
+
if (methodEntries) {
|
|
335
|
+
return methodEntries;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
methodEntries = resolveActionToolEntries(scope, {
|
|
339
|
+
barredActionIds,
|
|
340
|
+
skipActionPrefixes: normalizedSkipPrefixes
|
|
341
|
+
});
|
|
342
|
+
return methodEntries;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function resolveToolSet(context = {}) {
|
|
346
|
+
const tools = [];
|
|
347
|
+
const byName = new Map();
|
|
348
|
+
for (const entry of resolveOrCreateMethodEntries()) {
|
|
349
|
+
if (!canInvokeMethod(entry.permission, context)) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const descriptor = Object.freeze({
|
|
354
|
+
...entry.descriptor,
|
|
355
|
+
parameters: stripWorkspaceSlugFromSchema(entry.descriptor.parameters, context)
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
tools.push(descriptor);
|
|
359
|
+
byName.set(descriptor.name, descriptor);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return Object.freeze({
|
|
363
|
+
tools: Object.freeze(tools),
|
|
364
|
+
byName
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function toOpenAiToolSchema(tool) {
|
|
369
|
+
return {
|
|
370
|
+
type: "function",
|
|
371
|
+
function: {
|
|
372
|
+
name: tool.name,
|
|
373
|
+
description: tool.description,
|
|
374
|
+
parameters: tool.parameters
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
async function executeToolCall({ toolName = "", argumentsText = "", context = {}, toolSet = null } = {}) {
|
|
380
|
+
const normalizedToolName = normalizeText(toolName);
|
|
381
|
+
const resolvedToolSet = toolSet && typeof toolSet === "object" ? toolSet : resolveToolSet(context);
|
|
382
|
+
const descriptor = normalizedToolName ? resolvedToolSet.byName.get(normalizedToolName) : null;
|
|
383
|
+
|
|
384
|
+
if (!descriptor) {
|
|
385
|
+
return {
|
|
386
|
+
ok: false,
|
|
387
|
+
error: {
|
|
388
|
+
code: "assistant_tool_unknown",
|
|
389
|
+
message: "Unknown tool."
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (!scope.has("actionExecutor")) {
|
|
395
|
+
return {
|
|
396
|
+
ok: false,
|
|
397
|
+
error: {
|
|
398
|
+
code: "assistant_tool_unavailable",
|
|
399
|
+
message: "Tool executor is unavailable.",
|
|
400
|
+
status: 500
|
|
401
|
+
}
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
const actionExecutor = scope.make("actionExecutor");
|
|
405
|
+
if (!actionExecutor || typeof actionExecutor.execute !== "function") {
|
|
406
|
+
return {
|
|
407
|
+
ok: false,
|
|
408
|
+
error: {
|
|
409
|
+
code: "assistant_tool_unavailable",
|
|
410
|
+
message: "Tool executor is unavailable.",
|
|
411
|
+
status: 500
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
try {
|
|
417
|
+
const actionInput = parseToolPayload(argumentsText);
|
|
418
|
+
if (actionInput && typeof actionInput === "object" && !Array.isArray(actionInput)) {
|
|
419
|
+
const workspaceSlug = resolveWorkspaceSlug(context, actionInput);
|
|
420
|
+
if (workspaceSlug && !Object.hasOwn(actionInput, "workspaceSlug")) {
|
|
421
|
+
actionInput.workspaceSlug = workspaceSlug;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const executionContext = {
|
|
425
|
+
...context,
|
|
426
|
+
channel: AUTOMATION_CHANNEL
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const result = await actionExecutor.execute({
|
|
430
|
+
actionId: descriptor.actionId,
|
|
431
|
+
version: descriptor.actionVersion || null,
|
|
432
|
+
input: actionInput,
|
|
433
|
+
context: executionContext
|
|
434
|
+
});
|
|
435
|
+
return {
|
|
436
|
+
ok: true,
|
|
437
|
+
result
|
|
438
|
+
};
|
|
439
|
+
} catch (error) {
|
|
440
|
+
const status = Number(error?.status || error?.statusCode || 500);
|
|
441
|
+
return {
|
|
442
|
+
ok: false,
|
|
443
|
+
error: {
|
|
444
|
+
code: String(error?.code || "assistant_tool_failed").trim() || "assistant_tool_failed",
|
|
445
|
+
message: status >= 500 ? "Tool call failed." : String(error?.message || "Tool call failed."),
|
|
446
|
+
status: Number.isInteger(status) ? status : 500
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
return Object.freeze({
|
|
453
|
+
resolveToolSet,
|
|
454
|
+
toOpenAiToolSchema,
|
|
455
|
+
executeToolCall
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export { createServiceToolCatalog };
|