@inkeep/agents-sdk 0.0.0-chat-to-edit-20251119071712
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.md +56 -0
- package/README.md +53 -0
- package/SUPPLEMENTAL_TERMS.md +40 -0
- package/dist/index.cjs +5070 -0
- package/dist/index.d.cts +1457 -0
- package/dist/index.d.ts +1457 -0
- package/dist/index.js +4970 -0
- package/package.json +72 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,4970 @@
|
|
|
1
|
+
import { getLogger, normalizeToolSelections, apiFetch, CredentialReferenceApiInsertSchema, MCPToolConfigSchema } from '@inkeep/agents-core';
|
|
2
|
+
export { ANTHROPIC_MODELS, GOOGLE_MODELS, OPENAI_MODELS } from '@inkeep/agents-core';
|
|
3
|
+
import { isZodSchema, convertZodToJsonSchemaWithPreview, convertZodToJsonSchema } from '@inkeep/agents-core/utils/schema-conversion';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { builtinModules } from 'module';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import * as lockfile from '@yarnpkg/lockfile';
|
|
8
|
+
import * as yaml from 'js-yaml';
|
|
9
|
+
import ts from 'typescript';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
|
|
12
|
+
var __defProp = Object.defineProperty;
|
|
13
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
14
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
15
|
+
|
|
16
|
+
// src/utils/generateIdFromName.ts
|
|
17
|
+
function generateIdFromName(name) {
|
|
18
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/artifact-component.ts
|
|
22
|
+
var logger = getLogger("artifactComponent");
|
|
23
|
+
var ArtifactComponent = class {
|
|
24
|
+
constructor(config) {
|
|
25
|
+
__publicField(this, "config");
|
|
26
|
+
__publicField(this, "baseURL");
|
|
27
|
+
__publicField(this, "tenantId");
|
|
28
|
+
__publicField(this, "projectId");
|
|
29
|
+
__publicField(this, "initialized", false);
|
|
30
|
+
__publicField(this, "id");
|
|
31
|
+
this.id = config.id || generateIdFromName(config.name);
|
|
32
|
+
let processedProps;
|
|
33
|
+
if (config.props && isZodSchema(config.props)) {
|
|
34
|
+
processedProps = convertZodToJsonSchemaWithPreview(config.props);
|
|
35
|
+
} else {
|
|
36
|
+
processedProps = config.props;
|
|
37
|
+
}
|
|
38
|
+
this.config = {
|
|
39
|
+
...config,
|
|
40
|
+
id: this.id,
|
|
41
|
+
props: processedProps
|
|
42
|
+
};
|
|
43
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
44
|
+
this.tenantId = "default";
|
|
45
|
+
this.projectId = "default";
|
|
46
|
+
logger.info(
|
|
47
|
+
{
|
|
48
|
+
artifactComponentId: this.getId(),
|
|
49
|
+
artifactComponentName: config.name
|
|
50
|
+
},
|
|
51
|
+
"ArtifactComponent constructor initialized"
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
// Set context (tenantId, projectId, and baseURL) from external source (agent, agent, CLI, etc)
|
|
55
|
+
setContext(tenantId, projectId, baseURL) {
|
|
56
|
+
this.tenantId = tenantId;
|
|
57
|
+
this.projectId = projectId;
|
|
58
|
+
if (baseURL) {
|
|
59
|
+
this.baseURL = baseURL;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Compute ID from name using same slug transformation as agents
|
|
63
|
+
getId() {
|
|
64
|
+
return this.id;
|
|
65
|
+
}
|
|
66
|
+
getName() {
|
|
67
|
+
return this.config.name;
|
|
68
|
+
}
|
|
69
|
+
getDescription() {
|
|
70
|
+
return this.config.description;
|
|
71
|
+
}
|
|
72
|
+
getProps() {
|
|
73
|
+
return this.config.props;
|
|
74
|
+
}
|
|
75
|
+
// Public method to ensure artifact component exists in backend (with upsert behavior)
|
|
76
|
+
async init() {
|
|
77
|
+
if (this.initialized) return;
|
|
78
|
+
try {
|
|
79
|
+
await this.upsertArtifactComponent();
|
|
80
|
+
logger.info(
|
|
81
|
+
{
|
|
82
|
+
artifactComponentId: this.getId()
|
|
83
|
+
},
|
|
84
|
+
"ArtifactComponent initialized successfully"
|
|
85
|
+
);
|
|
86
|
+
this.initialized = true;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
logger.error(
|
|
89
|
+
{
|
|
90
|
+
artifactComponentId: this.getId(),
|
|
91
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
92
|
+
},
|
|
93
|
+
"Failed to initialize artifact component"
|
|
94
|
+
);
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
// Private method to upsert artifact component (create or update)
|
|
99
|
+
async upsertArtifactComponent() {
|
|
100
|
+
const artifactComponentData = {
|
|
101
|
+
id: this.getId(),
|
|
102
|
+
name: this.config.name,
|
|
103
|
+
description: this.config.description,
|
|
104
|
+
props: this.config.props
|
|
105
|
+
};
|
|
106
|
+
logger.info({ artifactComponentData }, "artifactComponentData for create/update");
|
|
107
|
+
const updateResponse = await fetch(
|
|
108
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/artifact-components/${this.getId()}`,
|
|
109
|
+
{
|
|
110
|
+
method: "PUT",
|
|
111
|
+
headers: {
|
|
112
|
+
"Content-Type": "application/json"
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify(artifactComponentData)
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
logger.info(
|
|
118
|
+
{
|
|
119
|
+
status: updateResponse.status,
|
|
120
|
+
artifactComponentId: this.getId()
|
|
121
|
+
},
|
|
122
|
+
"artifact component updateResponse"
|
|
123
|
+
);
|
|
124
|
+
if (updateResponse.ok) {
|
|
125
|
+
logger.info(
|
|
126
|
+
{
|
|
127
|
+
artifactComponentId: this.getId()
|
|
128
|
+
},
|
|
129
|
+
"ArtifactComponent updated successfully"
|
|
130
|
+
);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (updateResponse.status === 404) {
|
|
134
|
+
logger.info(
|
|
135
|
+
{
|
|
136
|
+
artifactComponentId: this.getId()
|
|
137
|
+
},
|
|
138
|
+
"ArtifactComponent not found, creating new artifact component"
|
|
139
|
+
);
|
|
140
|
+
const createResponse = await fetch(
|
|
141
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/artifact-components`,
|
|
142
|
+
{
|
|
143
|
+
method: "POST",
|
|
144
|
+
headers: {
|
|
145
|
+
"Content-Type": "application/json"
|
|
146
|
+
},
|
|
147
|
+
body: JSON.stringify(artifactComponentData)
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
if (!createResponse.ok) {
|
|
151
|
+
const errorText2 = await createResponse.text().catch(() => "Unknown error");
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Failed to create artifact component: ${createResponse.status} ${createResponse.statusText} - ${errorText2}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
logger.info(
|
|
157
|
+
{
|
|
158
|
+
artifactComponentId: this.getId()
|
|
159
|
+
},
|
|
160
|
+
"ArtifactComponent created successfully"
|
|
161
|
+
);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const errorText = await updateResponse.text().catch(() => "Unknown error");
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Failed to update artifact component: ${updateResponse.status} ${updateResponse.statusText} - ${errorText}`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
var logger2 = getLogger("projectFullClient");
|
|
171
|
+
async function createFullProjectViaAPI(tenantId, apiUrl, projectData, apiKey) {
|
|
172
|
+
logger2.info(
|
|
173
|
+
{
|
|
174
|
+
tenantId,
|
|
175
|
+
projectId: projectData.id,
|
|
176
|
+
apiUrl
|
|
177
|
+
},
|
|
178
|
+
"Creating full project via API"
|
|
179
|
+
);
|
|
180
|
+
const url = `${apiUrl}/tenants/${tenantId}/project-full`;
|
|
181
|
+
const headers = {};
|
|
182
|
+
if (apiKey) {
|
|
183
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
184
|
+
}
|
|
185
|
+
let response;
|
|
186
|
+
try {
|
|
187
|
+
response = await apiFetch(url, {
|
|
188
|
+
method: "POST",
|
|
189
|
+
headers,
|
|
190
|
+
body: JSON.stringify(projectData)
|
|
191
|
+
});
|
|
192
|
+
} catch (fetchError) {
|
|
193
|
+
logger2.error(
|
|
194
|
+
{
|
|
195
|
+
error: fetchError instanceof Error ? fetchError.message : "Unknown fetch error",
|
|
196
|
+
url,
|
|
197
|
+
tenantId,
|
|
198
|
+
projectId: projectData.id
|
|
199
|
+
},
|
|
200
|
+
"Fetch request failed"
|
|
201
|
+
);
|
|
202
|
+
throw fetchError;
|
|
203
|
+
}
|
|
204
|
+
if (!response.ok) {
|
|
205
|
+
const errorText = await response.text();
|
|
206
|
+
const errorMessage = parseError(errorText) ?? `Failed to create project: ${response.status} ${response.statusText}`;
|
|
207
|
+
logger2.error(
|
|
208
|
+
{
|
|
209
|
+
status: response.status,
|
|
210
|
+
error: errorMessage
|
|
211
|
+
},
|
|
212
|
+
"Failed to create project via API"
|
|
213
|
+
);
|
|
214
|
+
throw new Error(errorMessage);
|
|
215
|
+
}
|
|
216
|
+
const result = await response.json();
|
|
217
|
+
logger2.info(
|
|
218
|
+
{
|
|
219
|
+
projectId: projectData.id
|
|
220
|
+
},
|
|
221
|
+
"Successfully created project via API"
|
|
222
|
+
);
|
|
223
|
+
return result.data;
|
|
224
|
+
}
|
|
225
|
+
async function updateFullProjectViaAPI(tenantId, apiUrl, projectId, projectData, apiKey) {
|
|
226
|
+
logger2.info(
|
|
227
|
+
{
|
|
228
|
+
tenantId,
|
|
229
|
+
projectId,
|
|
230
|
+
apiUrl
|
|
231
|
+
},
|
|
232
|
+
"Updating full project via API"
|
|
233
|
+
);
|
|
234
|
+
const url = `${apiUrl}/tenants/${tenantId}/project-full/${projectId}`;
|
|
235
|
+
const headers = {};
|
|
236
|
+
if (apiKey) {
|
|
237
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
238
|
+
}
|
|
239
|
+
let response;
|
|
240
|
+
try {
|
|
241
|
+
response = await apiFetch(url, {
|
|
242
|
+
method: "PUT",
|
|
243
|
+
headers,
|
|
244
|
+
body: JSON.stringify(projectData)
|
|
245
|
+
});
|
|
246
|
+
} catch (fetchError) {
|
|
247
|
+
logger2.error(
|
|
248
|
+
{
|
|
249
|
+
error: fetchError instanceof Error ? fetchError.message : "Unknown fetch error",
|
|
250
|
+
url,
|
|
251
|
+
tenantId,
|
|
252
|
+
projectId
|
|
253
|
+
},
|
|
254
|
+
"Fetch request failed"
|
|
255
|
+
);
|
|
256
|
+
throw fetchError;
|
|
257
|
+
}
|
|
258
|
+
if (!response.ok) {
|
|
259
|
+
const errorText = await response.text();
|
|
260
|
+
const errorMessage = parseError(errorText) ?? `Failed to update project: ${response.status} ${response.statusText}`;
|
|
261
|
+
logger2.error(
|
|
262
|
+
{
|
|
263
|
+
status: response.status,
|
|
264
|
+
error: errorMessage
|
|
265
|
+
},
|
|
266
|
+
"Failed to update project via API"
|
|
267
|
+
);
|
|
268
|
+
throw new Error(errorMessage);
|
|
269
|
+
}
|
|
270
|
+
const result = await response.json();
|
|
271
|
+
logger2.info(
|
|
272
|
+
{
|
|
273
|
+
projectId
|
|
274
|
+
},
|
|
275
|
+
"Successfully updated project via API"
|
|
276
|
+
);
|
|
277
|
+
return result.data;
|
|
278
|
+
}
|
|
279
|
+
async function getFullProjectViaAPI(tenantId, apiUrl, projectId, apiKey) {
|
|
280
|
+
logger2.info(
|
|
281
|
+
{
|
|
282
|
+
tenantId,
|
|
283
|
+
projectId,
|
|
284
|
+
apiUrl
|
|
285
|
+
},
|
|
286
|
+
"Getting full project via API"
|
|
287
|
+
);
|
|
288
|
+
const url = `${apiUrl}/tenants/${tenantId}/project-full/${projectId}`;
|
|
289
|
+
const headers = {};
|
|
290
|
+
if (apiKey) {
|
|
291
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
292
|
+
}
|
|
293
|
+
const response = await apiFetch(url, {
|
|
294
|
+
method: "GET",
|
|
295
|
+
headers
|
|
296
|
+
});
|
|
297
|
+
if (!response.ok) {
|
|
298
|
+
if (response.status === 404) {
|
|
299
|
+
logger2.info(
|
|
300
|
+
{
|
|
301
|
+
projectId
|
|
302
|
+
},
|
|
303
|
+
"Project not found"
|
|
304
|
+
);
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
const errorText = await response.text();
|
|
308
|
+
const errorMessage = parseError(errorText) ?? `Failed to get project: ${response.status} ${response.statusText}`;
|
|
309
|
+
logger2.error(
|
|
310
|
+
{
|
|
311
|
+
status: response.status,
|
|
312
|
+
error: errorMessage
|
|
313
|
+
},
|
|
314
|
+
"Failed to get project via API"
|
|
315
|
+
);
|
|
316
|
+
throw new Error(errorMessage);
|
|
317
|
+
}
|
|
318
|
+
const result = await response.json();
|
|
319
|
+
logger2.info(
|
|
320
|
+
{
|
|
321
|
+
projectId
|
|
322
|
+
},
|
|
323
|
+
"Successfully retrieved project via API"
|
|
324
|
+
);
|
|
325
|
+
return result.data;
|
|
326
|
+
}
|
|
327
|
+
async function deleteFullProjectViaAPI(tenantId, apiUrl, projectId, apiKey) {
|
|
328
|
+
logger2.info(
|
|
329
|
+
{
|
|
330
|
+
tenantId,
|
|
331
|
+
projectId,
|
|
332
|
+
apiUrl
|
|
333
|
+
},
|
|
334
|
+
"Deleting full project via API"
|
|
335
|
+
);
|
|
336
|
+
const url = `${apiUrl}/tenants/${tenantId}/project-full/${projectId}`;
|
|
337
|
+
const headers = {};
|
|
338
|
+
if (apiKey) {
|
|
339
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
340
|
+
}
|
|
341
|
+
const response = await apiFetch(url, {
|
|
342
|
+
method: "DELETE",
|
|
343
|
+
headers
|
|
344
|
+
});
|
|
345
|
+
if (!response.ok) {
|
|
346
|
+
const errorText = await response.text();
|
|
347
|
+
const errorMessage = parseError(errorText) ?? `Failed to delete project: ${response.status} ${response.statusText}`;
|
|
348
|
+
logger2.error(
|
|
349
|
+
{
|
|
350
|
+
status: response.status,
|
|
351
|
+
error: errorMessage
|
|
352
|
+
},
|
|
353
|
+
"Failed to delete project via API"
|
|
354
|
+
);
|
|
355
|
+
throw new Error(errorMessage);
|
|
356
|
+
}
|
|
357
|
+
logger2.info(
|
|
358
|
+
{
|
|
359
|
+
projectId
|
|
360
|
+
},
|
|
361
|
+
"Successfully deleted project via API"
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
function parseError(errorText) {
|
|
365
|
+
try {
|
|
366
|
+
const errorJson = JSON.parse(errorText);
|
|
367
|
+
if (errorJson.error) {
|
|
368
|
+
const { error } = errorJson;
|
|
369
|
+
return error?.message ?? error;
|
|
370
|
+
}
|
|
371
|
+
} catch {
|
|
372
|
+
if (errorText) {
|
|
373
|
+
return errorText;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// src/agentFullClient.ts
|
|
379
|
+
var logger3 = getLogger("agentFullClient");
|
|
380
|
+
async function updateFullAgentViaAPI(tenantId, projectId, apiUrl, agentId, agentData) {
|
|
381
|
+
logger3.info(
|
|
382
|
+
{
|
|
383
|
+
tenantId,
|
|
384
|
+
projectId,
|
|
385
|
+
agentId,
|
|
386
|
+
apiUrl
|
|
387
|
+
},
|
|
388
|
+
"Updating full agent via API"
|
|
389
|
+
);
|
|
390
|
+
const url = `${apiUrl}/tenants/${tenantId}/projects/${projectId}/agent/${agentId}`;
|
|
391
|
+
const response = await fetch(url, {
|
|
392
|
+
method: "PUT",
|
|
393
|
+
headers: {
|
|
394
|
+
"Content-Type": "application/json"
|
|
395
|
+
},
|
|
396
|
+
body: JSON.stringify(agentData)
|
|
397
|
+
});
|
|
398
|
+
if (!response.ok) {
|
|
399
|
+
const errorText = await response.text();
|
|
400
|
+
const errorMessage = parseError(errorText) ?? `Failed to update agent: ${response.status} ${response.statusText}`;
|
|
401
|
+
logger3.error(
|
|
402
|
+
{
|
|
403
|
+
status: response.status,
|
|
404
|
+
error: errorMessage
|
|
405
|
+
},
|
|
406
|
+
"Failed to update agent via API"
|
|
407
|
+
);
|
|
408
|
+
throw new Error(errorMessage);
|
|
409
|
+
}
|
|
410
|
+
const result = await response.json();
|
|
411
|
+
logger3.info(
|
|
412
|
+
{
|
|
413
|
+
agentId
|
|
414
|
+
},
|
|
415
|
+
"Successfully updated agent via API"
|
|
416
|
+
);
|
|
417
|
+
return result.data;
|
|
418
|
+
}
|
|
419
|
+
var logger4 = getLogger("function-tool");
|
|
420
|
+
var getFunctionToolDeps = (name, code) => {
|
|
421
|
+
const { dependencies, warnings } = buildToolManifestFromCodeTS(code);
|
|
422
|
+
if (warnings.length > 0) {
|
|
423
|
+
logger4.warn({ warnings }, `FunctionTool dependencies warnings for ${name}`);
|
|
424
|
+
}
|
|
425
|
+
return dependencies;
|
|
426
|
+
};
|
|
427
|
+
var NODE_BUILTINS = new Set(builtinModules.concat(builtinModules.map((m) => `node:${m}`)));
|
|
428
|
+
var isExternal = (spec) => !spec.startsWith(".") && !spec.startsWith("/") && !NODE_BUILTINS.has(spec);
|
|
429
|
+
var collapseSubpath = (spec) => {
|
|
430
|
+
if (spec.startsWith("@")) {
|
|
431
|
+
const [scope, name] = spec.split("/");
|
|
432
|
+
return `${scope}/${name ?? ""}`;
|
|
433
|
+
}
|
|
434
|
+
return spec.split("/")[0];
|
|
435
|
+
};
|
|
436
|
+
var readJSON = (p) => JSON.parse(fs.readFileSync(p, "utf8"));
|
|
437
|
+
var findUp = (start, file) => {
|
|
438
|
+
let dir = path.resolve(start);
|
|
439
|
+
if (fs.existsSync(dir) && fs.statSync(dir).isFile()) dir = path.dirname(dir);
|
|
440
|
+
for (; ; ) {
|
|
441
|
+
const candidate = path.join(dir, file);
|
|
442
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
443
|
+
const parent = path.dirname(dir);
|
|
444
|
+
if (parent === dir) return null;
|
|
445
|
+
dir = parent;
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
function collectDepsFromCodeTS(code) {
|
|
449
|
+
const info = ts.preProcessFile(
|
|
450
|
+
code,
|
|
451
|
+
/*readImportFiles*/
|
|
452
|
+
true,
|
|
453
|
+
/*detectJavaScriptImports*/
|
|
454
|
+
true
|
|
455
|
+
);
|
|
456
|
+
const add = /* @__PURE__ */ new Set();
|
|
457
|
+
const push = (spec) => {
|
|
458
|
+
if (isExternal(spec)) add.add(collapseSubpath(spec));
|
|
459
|
+
};
|
|
460
|
+
for (const f of info.importedFiles) {
|
|
461
|
+
const spec = f.fileName;
|
|
462
|
+
if (spec) push(spec);
|
|
463
|
+
}
|
|
464
|
+
const requireLike = /(?:require|import)\s*\(\s*(['"])([^'"]+)\1\s*\)/g;
|
|
465
|
+
let m;
|
|
466
|
+
while (m = requireLike.exec(code)) push(m[2]);
|
|
467
|
+
return add;
|
|
468
|
+
}
|
|
469
|
+
function resolveInstalledVersion(pkg, projectRoot) {
|
|
470
|
+
const pnpmLock = findUp(projectRoot, "pnpm-lock.yaml");
|
|
471
|
+
if (pnpmLock) {
|
|
472
|
+
const doc = yaml.load(fs.readFileSync(pnpmLock, "utf8"));
|
|
473
|
+
const pkgs = doc?.packages ?? {};
|
|
474
|
+
for (const key of Object.keys(pkgs)) {
|
|
475
|
+
if (key.startsWith(`${pkg}@`)) {
|
|
476
|
+
const ver = key.slice(key.indexOf("@") + 1);
|
|
477
|
+
if (ver) return { exact: String(ver) };
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const npmLock = findUp(projectRoot, "package-lock.json");
|
|
482
|
+
if (npmLock) {
|
|
483
|
+
const lock = readJSON(npmLock);
|
|
484
|
+
if (lock.packages?.[`node_modules/${pkg}`]?.version) {
|
|
485
|
+
return { exact: String(lock.packages[`node_modules/${pkg}`].version) };
|
|
486
|
+
}
|
|
487
|
+
if (lock.dependencies?.[pkg]?.version) {
|
|
488
|
+
return { exact: String(lock.dependencies[pkg].version) };
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
const yarnLock = findUp(projectRoot, "yarn.lock");
|
|
492
|
+
if (yarnLock) {
|
|
493
|
+
const parsed = lockfile.parse(fs.readFileSync(yarnLock, "utf8"));
|
|
494
|
+
if (parsed.type === "success") {
|
|
495
|
+
for (const [key, val] of Object.entries(parsed.object)) {
|
|
496
|
+
if (key === pkg || key.startsWith(`${pkg}@`)) {
|
|
497
|
+
const ver = val.version;
|
|
498
|
+
if (ver) return { exact: String(ver) };
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
const host = {
|
|
504
|
+
fileExists: fs.existsSync,
|
|
505
|
+
readFile: (p) => fs.readFileSync(p, "utf8"),
|
|
506
|
+
realpath: (p) => fs.realpathSync.native?.(p) ?? fs.realpathSync(p),
|
|
507
|
+
directoryExists: (d) => {
|
|
508
|
+
try {
|
|
509
|
+
return fs.statSync(d).isDirectory();
|
|
510
|
+
} catch {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
},
|
|
514
|
+
getCurrentDirectory: () => projectRoot,
|
|
515
|
+
getDirectories: (d) => fs.readdirSync(d, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name)
|
|
516
|
+
};
|
|
517
|
+
const res = ts.resolveModuleName(
|
|
518
|
+
`${pkg}/package.json`,
|
|
519
|
+
path.join(projectRoot, "__fake.ts"),
|
|
520
|
+
{},
|
|
521
|
+
host,
|
|
522
|
+
ts.ModuleKind.NodeNext
|
|
523
|
+
);
|
|
524
|
+
const pkgJsonPath = res?.resolvedModule?.resolvedFileName ?? // Try typical path as fallback
|
|
525
|
+
findUp(path.join(projectRoot, "node_modules", pkg), "package.json");
|
|
526
|
+
if (pkgJsonPath && fs.existsSync(pkgJsonPath)) {
|
|
527
|
+
try {
|
|
528
|
+
const version = readJSON(pkgJsonPath).version;
|
|
529
|
+
if (version) return { exact: String(version) };
|
|
530
|
+
} catch {
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
const hostPkg = findUp(projectRoot, "package.json");
|
|
534
|
+
if (hostPkg) {
|
|
535
|
+
const hostJson = readJSON(hostPkg);
|
|
536
|
+
const range = hostJson.dependencies?.[pkg] ?? hostJson.devDependencies?.[pkg] ?? hostJson.optionalDependencies?.[pkg];
|
|
537
|
+
if (range) return { range: String(range), unresolved: true };
|
|
538
|
+
}
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
function buildToolManifestFromCodeTS(code, projectRoot = process.cwd()) {
|
|
542
|
+
const deps = collectDepsFromCodeTS(code);
|
|
543
|
+
const warnings = [];
|
|
544
|
+
const dependencies = {};
|
|
545
|
+
for (const pkg of deps) {
|
|
546
|
+
try {
|
|
547
|
+
const v = resolveInstalledVersion(pkg, projectRoot);
|
|
548
|
+
if (!v) {
|
|
549
|
+
warnings.push(`Could not resolve version for "${pkg}"`);
|
|
550
|
+
continue;
|
|
551
|
+
}
|
|
552
|
+
if ("unresolved" in v) {
|
|
553
|
+
warnings.push(`Using range for "${pkg}" -> ${v.range} (no lockfile / not installed)`);
|
|
554
|
+
dependencies[pkg] = v.range;
|
|
555
|
+
} else {
|
|
556
|
+
dependencies[pkg] = v.exact;
|
|
557
|
+
}
|
|
558
|
+
} catch {
|
|
559
|
+
dependencies[pkg] = false;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return { dependencies, warnings };
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// src/function-tool.ts
|
|
566
|
+
var logger5 = getLogger("function-tool");
|
|
567
|
+
var FunctionTool = class {
|
|
568
|
+
constructor(config) {
|
|
569
|
+
__publicField(this, "config");
|
|
570
|
+
__publicField(this, "id");
|
|
571
|
+
this.config = config;
|
|
572
|
+
this.id = generateIdFromName(config.name);
|
|
573
|
+
if (!config.dependencies) {
|
|
574
|
+
const executeCode = typeof config.execute === "string" ? config.execute : config.execute.toString();
|
|
575
|
+
const deps = getFunctionToolDeps(config.name, executeCode);
|
|
576
|
+
for (const dep in deps) {
|
|
577
|
+
if (deps[dep] === false) {
|
|
578
|
+
delete deps[dep];
|
|
579
|
+
throw new Error(
|
|
580
|
+
`Dependency \x1B[1;32m${dep}\x1B[0m used in function tool \x1B[1;32m${config.name}\x1B[0m is neither installed nor in dependencies object.`
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
this.config.dependencies = deps;
|
|
585
|
+
}
|
|
586
|
+
logger5.info(
|
|
587
|
+
{
|
|
588
|
+
id: this.id,
|
|
589
|
+
name: config.name
|
|
590
|
+
},
|
|
591
|
+
"FunctionTool constructor initialized"
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
getId() {
|
|
595
|
+
return this.id;
|
|
596
|
+
}
|
|
597
|
+
getName() {
|
|
598
|
+
return this.config.name;
|
|
599
|
+
}
|
|
600
|
+
getDescription() {
|
|
601
|
+
return this.config.description;
|
|
602
|
+
}
|
|
603
|
+
getInputSchema() {
|
|
604
|
+
return this.config.inputSchema;
|
|
605
|
+
}
|
|
606
|
+
getDependencies() {
|
|
607
|
+
return this.config.dependencies || {};
|
|
608
|
+
}
|
|
609
|
+
getExecuteFunction() {
|
|
610
|
+
if (typeof this.config.execute === "string") {
|
|
611
|
+
throw new Error(
|
|
612
|
+
"Cannot get execute function from string-based function tool. Use serializeFunction() instead."
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
return this.config.execute;
|
|
616
|
+
}
|
|
617
|
+
// Serialize the function (global entity) for storage
|
|
618
|
+
serializeFunction() {
|
|
619
|
+
const executeCode = typeof this.config.execute === "string" ? this.config.execute : this.config.execute.toString();
|
|
620
|
+
return {
|
|
621
|
+
id: this.id,
|
|
622
|
+
inputSchema: this.config.inputSchema,
|
|
623
|
+
executeCode,
|
|
624
|
+
dependencies: this.config.dependencies || {}
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
// Serialize the tool (project-scoped) for storage
|
|
628
|
+
serializeTool() {
|
|
629
|
+
return {
|
|
630
|
+
id: this.id,
|
|
631
|
+
name: this.config.name,
|
|
632
|
+
description: this.config.description,
|
|
633
|
+
functionId: this.id
|
|
634
|
+
// The function ID is the same as the tool ID in this context
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
};
|
|
638
|
+
|
|
639
|
+
// src/agent.ts
|
|
640
|
+
var logger6 = getLogger("agent");
|
|
641
|
+
function resolveGetter(value) {
|
|
642
|
+
if (typeof value === "function") {
|
|
643
|
+
return value();
|
|
644
|
+
}
|
|
645
|
+
return value;
|
|
646
|
+
}
|
|
647
|
+
var Agent = class {
|
|
648
|
+
constructor(config) {
|
|
649
|
+
__publicField(this, "subAgents", []);
|
|
650
|
+
__publicField(this, "agentMap", /* @__PURE__ */ new Map());
|
|
651
|
+
__publicField(this, "defaultSubAgent");
|
|
652
|
+
__publicField(this, "baseURL");
|
|
653
|
+
__publicField(this, "tenantId");
|
|
654
|
+
__publicField(this, "projectId");
|
|
655
|
+
__publicField(this, "agentId");
|
|
656
|
+
__publicField(this, "agentName");
|
|
657
|
+
__publicField(this, "agentDescription");
|
|
658
|
+
__publicField(this, "initialized", false);
|
|
659
|
+
__publicField(this, "contextConfig");
|
|
660
|
+
// ContextConfigBuilder
|
|
661
|
+
__publicField(this, "credentials");
|
|
662
|
+
__publicField(this, "models");
|
|
663
|
+
__publicField(this, "statusUpdateSettings");
|
|
664
|
+
__publicField(this, "prompt");
|
|
665
|
+
__publicField(this, "stopWhen");
|
|
666
|
+
this.defaultSubAgent = config.defaultSubAgent;
|
|
667
|
+
this.tenantId = "default";
|
|
668
|
+
this.projectId = "default";
|
|
669
|
+
this.agentId = config.id;
|
|
670
|
+
this.agentName = config.name || this.agentId;
|
|
671
|
+
this.agentDescription = config.description;
|
|
672
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
673
|
+
this.contextConfig = config.contextConfig;
|
|
674
|
+
this.credentials = resolveGetter(config.credentials);
|
|
675
|
+
this.models = config.models;
|
|
676
|
+
this.statusUpdateSettings = config.statusUpdates;
|
|
677
|
+
this.prompt = config.prompt;
|
|
678
|
+
this.stopWhen = config.stopWhen ? {
|
|
679
|
+
transferCountIs: config.stopWhen.transferCountIs
|
|
680
|
+
} : void 0;
|
|
681
|
+
this.subAgents = resolveGetter(config.subAgents) || [];
|
|
682
|
+
this.agentMap = new Map(this.subAgents.map((agent2) => [agent2.getId(), agent2]));
|
|
683
|
+
if (this.defaultSubAgent) {
|
|
684
|
+
const isAlreadyPresent = this.subAgents.some(
|
|
685
|
+
(agent2) => agent2.getId() === this.defaultSubAgent?.getId()
|
|
686
|
+
);
|
|
687
|
+
if (!isAlreadyPresent) {
|
|
688
|
+
this.subAgents.push(this.defaultSubAgent);
|
|
689
|
+
}
|
|
690
|
+
this.agentMap.set(this.defaultSubAgent.getId(), this.defaultSubAgent);
|
|
691
|
+
}
|
|
692
|
+
if (this.models) {
|
|
693
|
+
this.propagateImmediateModelSettings();
|
|
694
|
+
}
|
|
695
|
+
logger6.info(
|
|
696
|
+
{
|
|
697
|
+
agentId: this.agentId,
|
|
698
|
+
tenantId: this.tenantId,
|
|
699
|
+
agentCount: this.subAgents.length,
|
|
700
|
+
defaultSubAgent: this.defaultSubAgent?.getName()
|
|
701
|
+
},
|
|
702
|
+
"Agent created"
|
|
703
|
+
);
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Set or update the configuration (tenantId, projectId and apiUrl)
|
|
707
|
+
* This is used by the CLI to inject configuration from inkeep.config.ts
|
|
708
|
+
*/
|
|
709
|
+
setConfig(tenantId, projectId, apiUrl) {
|
|
710
|
+
if (this.initialized) {
|
|
711
|
+
throw new Error("Cannot set config after agent has been initialized");
|
|
712
|
+
}
|
|
713
|
+
this.tenantId = tenantId;
|
|
714
|
+
this.projectId = projectId;
|
|
715
|
+
this.baseURL = apiUrl;
|
|
716
|
+
for (const subAgent2 of this.subAgents) {
|
|
717
|
+
if (subAgent2.setContext) {
|
|
718
|
+
subAgent2.setContext(tenantId, projectId, apiUrl);
|
|
719
|
+
}
|
|
720
|
+
const tools = subAgent2.getTools();
|
|
721
|
+
for (const [_, toolInstance] of Object.entries(tools)) {
|
|
722
|
+
if (toolInstance && typeof toolInstance === "object") {
|
|
723
|
+
if ("setContext" in toolInstance && typeof toolInstance.setContext === "function") {
|
|
724
|
+
toolInstance.setContext(tenantId, projectId, apiUrl);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
if (this.contextConfig?.setContext) {
|
|
730
|
+
this.contextConfig.setContext(tenantId, projectId, this.agentId, this.baseURL);
|
|
731
|
+
}
|
|
732
|
+
logger6.info(
|
|
733
|
+
{
|
|
734
|
+
agentId: this.agentId,
|
|
735
|
+
tenantId: this.tenantId,
|
|
736
|
+
projectId: this.projectId,
|
|
737
|
+
apiUrl: this.baseURL
|
|
738
|
+
},
|
|
739
|
+
"Agent configuration updated"
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Convert the Agent to FullAgentDefinition format for the new agent endpoint
|
|
744
|
+
*/
|
|
745
|
+
async toFullAgentDefinition() {
|
|
746
|
+
const subAgentsObject = {};
|
|
747
|
+
const externalAgentsObject = {};
|
|
748
|
+
const functionToolsObject = {};
|
|
749
|
+
const functionsObject = {};
|
|
750
|
+
for (const subAgent2 of this.subAgents) {
|
|
751
|
+
const transfers = subAgent2.getTransfers();
|
|
752
|
+
const delegates = subAgent2.getDelegates();
|
|
753
|
+
const tools = [];
|
|
754
|
+
const selectedToolsMapping = {};
|
|
755
|
+
const headersMapping = {};
|
|
756
|
+
const toolPoliciesMapping = {};
|
|
757
|
+
const subAgentTools = subAgent2.getTools();
|
|
758
|
+
for (const [_toolName, toolInstance] of Object.entries(subAgentTools)) {
|
|
759
|
+
const toolId = toolInstance.getId();
|
|
760
|
+
if (toolInstance.selectedTools) {
|
|
761
|
+
selectedToolsMapping[toolId] = toolInstance.selectedTools;
|
|
762
|
+
}
|
|
763
|
+
if (toolInstance.headers) {
|
|
764
|
+
headersMapping[toolId] = toolInstance.headers;
|
|
765
|
+
}
|
|
766
|
+
if (toolInstance.toolPolicies) {
|
|
767
|
+
toolPoliciesMapping[toolId] = toolInstance.toolPolicies;
|
|
768
|
+
}
|
|
769
|
+
tools.push(toolId);
|
|
770
|
+
if (toolInstance.constructor.name === "FunctionTool" && toolInstance instanceof FunctionTool) {
|
|
771
|
+
if (!functionsObject[toolId]) {
|
|
772
|
+
const functionData = toolInstance.serializeFunction();
|
|
773
|
+
functionsObject[toolId] = functionData;
|
|
774
|
+
}
|
|
775
|
+
if (!functionToolsObject[toolId]) {
|
|
776
|
+
const toolData = toolInstance.serializeTool();
|
|
777
|
+
functionToolsObject[toolId] = {
|
|
778
|
+
id: toolData.id,
|
|
779
|
+
name: toolData.name,
|
|
780
|
+
description: toolData.description,
|
|
781
|
+
functionId: toolData.functionId,
|
|
782
|
+
agentId: this.agentId
|
|
783
|
+
// Include agentId for agent-scoped function tools
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
const subAgentExternalAgents = subAgent2.getExternalAgentDelegates();
|
|
789
|
+
for (const externalAgentDelegate of subAgentExternalAgents) {
|
|
790
|
+
const externalAgent2 = externalAgentDelegate.externalAgent;
|
|
791
|
+
externalAgentsObject[externalAgent2.getId()] = {
|
|
792
|
+
id: externalAgent2.getId(),
|
|
793
|
+
name: externalAgent2.getName(),
|
|
794
|
+
description: externalAgent2.getDescription(),
|
|
795
|
+
baseUrl: externalAgent2.getBaseUrl(),
|
|
796
|
+
credentialReferenceId: externalAgent2.getCredentialReferenceId(),
|
|
797
|
+
type: "external"
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
const dataComponents = [];
|
|
801
|
+
const subAgentDataComponents = subAgent2.getDataComponents();
|
|
802
|
+
if (subAgentDataComponents) {
|
|
803
|
+
for (const dataComponent2 of subAgentDataComponents) {
|
|
804
|
+
const dataComponentId = dataComponent2.id || dataComponent2.name.toLowerCase().replace(/\s+/g, "-");
|
|
805
|
+
dataComponents.push(dataComponentId);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
const artifactComponents = [];
|
|
809
|
+
const subAgentArtifactComponents = subAgent2.getArtifactComponents();
|
|
810
|
+
if (subAgentArtifactComponents) {
|
|
811
|
+
for (const artifactComponent2 of subAgentArtifactComponents) {
|
|
812
|
+
const artifactComponentId = artifactComponent2.id || artifactComponent2.name.toLowerCase().replace(/\s+/g, "-");
|
|
813
|
+
artifactComponents.push(artifactComponentId);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
const canUse = tools.map((toolId) => ({
|
|
817
|
+
toolId,
|
|
818
|
+
toolSelection: selectedToolsMapping[toolId] || null,
|
|
819
|
+
headers: headersMapping[toolId] || null,
|
|
820
|
+
toolPolicies: toolPoliciesMapping[toolId] || null
|
|
821
|
+
}));
|
|
822
|
+
subAgentsObject[subAgent2.getId()] = {
|
|
823
|
+
id: subAgent2.getId(),
|
|
824
|
+
name: subAgent2.getName(),
|
|
825
|
+
description: subAgent2.config.description || `Agent ${subAgent2.getName()}`,
|
|
826
|
+
prompt: subAgent2.getInstructions(),
|
|
827
|
+
models: subAgent2.config.models,
|
|
828
|
+
stopWhen: subAgent2.config.stopWhen,
|
|
829
|
+
canTransferTo: transfers.map((h) => h.getId()),
|
|
830
|
+
canDelegateTo: delegates.map((d) => {
|
|
831
|
+
if (typeof d === "object" && "externalAgent" in d) {
|
|
832
|
+
return {
|
|
833
|
+
externalAgentId: d.externalAgent.getId(),
|
|
834
|
+
...d.headers && { headers: d.headers }
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
if (typeof d === "object" && "agent" in d) {
|
|
838
|
+
return {
|
|
839
|
+
agentId: d.agent.getId(),
|
|
840
|
+
...d.headers && { headers: d.headers }
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
return d.getId();
|
|
844
|
+
}),
|
|
845
|
+
canUse,
|
|
846
|
+
dataComponents: dataComponents.length > 0 ? dataComponents : void 0,
|
|
847
|
+
artifactComponents: artifactComponents.length > 0 ? artifactComponents : void 0,
|
|
848
|
+
type: "internal"
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
const processedStatusUpdates = this.statusUpdateSettings ? {
|
|
852
|
+
...this.statusUpdateSettings,
|
|
853
|
+
statusComponents: this.statusUpdateSettings.statusComponents?.map((comp) => {
|
|
854
|
+
if (comp && typeof comp.getType === "function") {
|
|
855
|
+
return {
|
|
856
|
+
type: comp.getType(),
|
|
857
|
+
description: comp.getDescription(),
|
|
858
|
+
detailsSchema: comp.getDetailsSchema()
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
if (comp && typeof comp === "object" && comp.detailsSchema && isZodSchema(comp.detailsSchema)) {
|
|
862
|
+
const jsonSchema = convertZodToJsonSchema(comp.detailsSchema);
|
|
863
|
+
return {
|
|
864
|
+
type: comp.type,
|
|
865
|
+
description: comp.description,
|
|
866
|
+
detailsSchema: {
|
|
867
|
+
type: "object",
|
|
868
|
+
properties: jsonSchema.properties || {},
|
|
869
|
+
required: jsonSchema.required || void 0
|
|
870
|
+
}
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
return comp;
|
|
874
|
+
})
|
|
875
|
+
} : void 0;
|
|
876
|
+
const agentToolsObject = {};
|
|
877
|
+
for (const subAgent2 of this.subAgents) {
|
|
878
|
+
const subAgentTools = subAgent2.getTools();
|
|
879
|
+
for (const [_toolName, toolInstance] of Object.entries(subAgentTools)) {
|
|
880
|
+
const toolId = toolInstance.getId();
|
|
881
|
+
if (toolInstance.constructor.name !== "FunctionTool") {
|
|
882
|
+
if (!agentToolsObject[toolId]) {
|
|
883
|
+
if ("config" in toolInstance && "serverUrl" in toolInstance.config) {
|
|
884
|
+
const mcpTool2 = toolInstance;
|
|
885
|
+
agentToolsObject[toolId] = {
|
|
886
|
+
id: toolId,
|
|
887
|
+
name: toolInstance.getName(),
|
|
888
|
+
description: null,
|
|
889
|
+
config: {
|
|
890
|
+
type: "mcp",
|
|
891
|
+
mcp: {
|
|
892
|
+
server: {
|
|
893
|
+
url: mcpTool2.config.serverUrl
|
|
894
|
+
},
|
|
895
|
+
transport: mcpTool2.config.transport,
|
|
896
|
+
activeTools: mcpTool2.config.activeTools
|
|
897
|
+
}
|
|
898
|
+
},
|
|
899
|
+
credentialReferenceId: null
|
|
900
|
+
};
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return {
|
|
907
|
+
id: this.agentId,
|
|
908
|
+
name: this.agentName,
|
|
909
|
+
description: this.agentDescription,
|
|
910
|
+
defaultSubAgentId: this.defaultSubAgent?.getId() || "",
|
|
911
|
+
subAgents: subAgentsObject,
|
|
912
|
+
externalAgents: externalAgentsObject,
|
|
913
|
+
contextConfig: this.contextConfig?.toObject(),
|
|
914
|
+
// Include function tools at agent level
|
|
915
|
+
...Object.keys(functionToolsObject).length > 0 && { functionTools: functionToolsObject },
|
|
916
|
+
...Object.keys(functionsObject).length > 0 && { functions: functionsObject },
|
|
917
|
+
models: this.models,
|
|
918
|
+
stopWhen: this.stopWhen,
|
|
919
|
+
statusUpdates: processedStatusUpdates,
|
|
920
|
+
prompt: this.prompt,
|
|
921
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
922
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Initialize all tools in all agents (especially IPCTools that need MCP server URLs)
|
|
927
|
+
*/
|
|
928
|
+
async initializeAllTools() {
|
|
929
|
+
logger6.info({ agentId: this.agentId }, "Initializing all tools in agent");
|
|
930
|
+
const toolInitPromises = [];
|
|
931
|
+
for (const subAgent2 of this.subAgents) {
|
|
932
|
+
const agentTools = subAgent2.getTools();
|
|
933
|
+
for (const [toolName, toolInstance] of Object.entries(agentTools)) {
|
|
934
|
+
if (toolInstance && typeof toolInstance === "object") {
|
|
935
|
+
if (typeof toolInstance.init === "function") {
|
|
936
|
+
toolInitPromises.push(
|
|
937
|
+
(async () => {
|
|
938
|
+
try {
|
|
939
|
+
const skipDbRegistration = toolInstance.constructor.name === "IPCTool" || toolInstance.constructor.name === "HostedTool" || toolInstance.constructor.name === "Tool";
|
|
940
|
+
if (typeof toolInstance.init === "function") {
|
|
941
|
+
if (skipDbRegistration) {
|
|
942
|
+
await toolInstance.init({
|
|
943
|
+
skipDatabaseRegistration: true
|
|
944
|
+
});
|
|
945
|
+
} else {
|
|
946
|
+
await toolInstance.init();
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
logger6.debug(
|
|
950
|
+
{
|
|
951
|
+
subAgentId: subAgent2.getId(),
|
|
952
|
+
toolName,
|
|
953
|
+
toolType: toolInstance.constructor.name,
|
|
954
|
+
skipDbRegistration
|
|
955
|
+
},
|
|
956
|
+
"Tool initialized successfully"
|
|
957
|
+
);
|
|
958
|
+
} catch (error) {
|
|
959
|
+
logger6.error(
|
|
960
|
+
{
|
|
961
|
+
subAgentId: subAgent2.getId(),
|
|
962
|
+
toolName,
|
|
963
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
964
|
+
},
|
|
965
|
+
"Failed to initialize tool"
|
|
966
|
+
);
|
|
967
|
+
throw error;
|
|
968
|
+
}
|
|
969
|
+
})()
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
await Promise.all(toolInitPromises);
|
|
976
|
+
logger6.info(
|
|
977
|
+
{ agentId: this.agentId, toolCount: toolInitPromises.length },
|
|
978
|
+
"All tools initialized successfully"
|
|
979
|
+
);
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Initialize the agent and all agents in the backend using the new agent endpoint
|
|
983
|
+
*/
|
|
984
|
+
async init() {
|
|
985
|
+
if (this.initialized) {
|
|
986
|
+
logger6.info({ agentId: this.agentId }, "Agent already initialized");
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
logger6.info(
|
|
990
|
+
{
|
|
991
|
+
agentId: this.agentId,
|
|
992
|
+
agentCount: this.subAgents.length
|
|
993
|
+
},
|
|
994
|
+
"Initializing agent using new agent endpoint"
|
|
995
|
+
);
|
|
996
|
+
try {
|
|
997
|
+
await this.initializeAllTools();
|
|
998
|
+
await this.applyModelInheritance();
|
|
999
|
+
const agentDefinition = await this.toFullAgentDefinition();
|
|
1000
|
+
logger6.info(
|
|
1001
|
+
{
|
|
1002
|
+
agentId: this.agentId,
|
|
1003
|
+
mode: "api-client",
|
|
1004
|
+
apiUrl: this.baseURL
|
|
1005
|
+
},
|
|
1006
|
+
"Using API client to create/update agent"
|
|
1007
|
+
);
|
|
1008
|
+
const createdAgent = await updateFullAgentViaAPI(
|
|
1009
|
+
this.tenantId,
|
|
1010
|
+
this.projectId,
|
|
1011
|
+
this.baseURL,
|
|
1012
|
+
this.agentId,
|
|
1013
|
+
agentDefinition
|
|
1014
|
+
);
|
|
1015
|
+
logger6.info(
|
|
1016
|
+
{
|
|
1017
|
+
agentId: this.agentId,
|
|
1018
|
+
agentCount: Object.keys(createdAgent.subAgents || {}).length
|
|
1019
|
+
},
|
|
1020
|
+
"Agent initialized successfully using agent endpoint"
|
|
1021
|
+
);
|
|
1022
|
+
this.initialized = true;
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
logger6.error(
|
|
1025
|
+
{
|
|
1026
|
+
agentId: this.agentId,
|
|
1027
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1028
|
+
},
|
|
1029
|
+
"Failed to initialize agent using agent endpoint"
|
|
1030
|
+
);
|
|
1031
|
+
throw error;
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Generate a response using the default agent
|
|
1036
|
+
*/
|
|
1037
|
+
async generate(input, options) {
|
|
1038
|
+
await this._init();
|
|
1039
|
+
if (!this.defaultSubAgent) {
|
|
1040
|
+
throw new Error("No default agent configured for this agent");
|
|
1041
|
+
}
|
|
1042
|
+
logger6.info(
|
|
1043
|
+
{
|
|
1044
|
+
agentId: this.agentId,
|
|
1045
|
+
defaultSubAgent: this.defaultSubAgent.getName(),
|
|
1046
|
+
conversationId: options?.conversationId
|
|
1047
|
+
},
|
|
1048
|
+
"Generating response with default agent"
|
|
1049
|
+
);
|
|
1050
|
+
const response = await this.executeWithBackend(input, options);
|
|
1051
|
+
return response;
|
|
1052
|
+
}
|
|
1053
|
+
/**
|
|
1054
|
+
* Stream a response using the default agent
|
|
1055
|
+
*/
|
|
1056
|
+
async stream(input, options) {
|
|
1057
|
+
await this._init();
|
|
1058
|
+
if (!this.defaultSubAgent) {
|
|
1059
|
+
throw new Error("No default agent configured for this agent");
|
|
1060
|
+
}
|
|
1061
|
+
logger6.info(
|
|
1062
|
+
{
|
|
1063
|
+
agentId: this.agentId,
|
|
1064
|
+
defaultSubAgent: this.defaultSubAgent.getName(),
|
|
1065
|
+
conversationId: options?.conversationId
|
|
1066
|
+
},
|
|
1067
|
+
"Streaming response with default agent"
|
|
1068
|
+
);
|
|
1069
|
+
const textStream = async function* (agent2) {
|
|
1070
|
+
const response = await agent2.executeWithBackend(input, options);
|
|
1071
|
+
const words = response.split(" ");
|
|
1072
|
+
for (const word of words) {
|
|
1073
|
+
yield `${word} `;
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
return {
|
|
1077
|
+
textStream: textStream(this)
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Alias for stream() method for consistency with naming patterns
|
|
1082
|
+
*/
|
|
1083
|
+
async generateStream(input, options) {
|
|
1084
|
+
return await this.stream(input, options);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* Run with a specific agent from the agent
|
|
1088
|
+
*/
|
|
1089
|
+
async runWith(subAgentId, input, options) {
|
|
1090
|
+
await this._init();
|
|
1091
|
+
const agent2 = this.getSubAgent(subAgentId);
|
|
1092
|
+
if (!agent2) {
|
|
1093
|
+
throw new Error(`Agent '${subAgentId}' not found in agent`);
|
|
1094
|
+
}
|
|
1095
|
+
logger6.info(
|
|
1096
|
+
{
|
|
1097
|
+
agentId: this.agentId,
|
|
1098
|
+
subAgentId,
|
|
1099
|
+
conversationId: options?.conversationId
|
|
1100
|
+
},
|
|
1101
|
+
"Running with specific agent"
|
|
1102
|
+
);
|
|
1103
|
+
const response = await this.executeWithBackend(input, options);
|
|
1104
|
+
return {
|
|
1105
|
+
finalOutput: response,
|
|
1106
|
+
agent: agent2,
|
|
1107
|
+
turnCount: 1,
|
|
1108
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
1109
|
+
metadata: {
|
|
1110
|
+
toolCalls: [],
|
|
1111
|
+
transfers: []
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Get an agent by name (unified method for all agent types)
|
|
1117
|
+
*/
|
|
1118
|
+
getSubAgent(name) {
|
|
1119
|
+
return this.agentMap.get(name);
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Add an agent to the agent
|
|
1123
|
+
*/
|
|
1124
|
+
addSubAgent(agent2) {
|
|
1125
|
+
this.subAgents.push(agent2);
|
|
1126
|
+
this.agentMap.set(agent2.getId(), agent2);
|
|
1127
|
+
if (this.models) {
|
|
1128
|
+
this.propagateModelSettingsToAgent(agent2);
|
|
1129
|
+
}
|
|
1130
|
+
logger6.info(
|
|
1131
|
+
{
|
|
1132
|
+
agentId: this.agentId,
|
|
1133
|
+
subAgentId: agent2.getId()
|
|
1134
|
+
},
|
|
1135
|
+
"SubAgent added to agent"
|
|
1136
|
+
);
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Remove an agent from the agent
|
|
1140
|
+
*/
|
|
1141
|
+
removeSubAgent(id) {
|
|
1142
|
+
const agentToRemove = this.agentMap.get(id);
|
|
1143
|
+
if (agentToRemove) {
|
|
1144
|
+
this.agentMap.delete(agentToRemove.getId());
|
|
1145
|
+
this.subAgents = this.subAgents.filter((agent2) => agent2.getId() !== agentToRemove.getId());
|
|
1146
|
+
logger6.info(
|
|
1147
|
+
{
|
|
1148
|
+
agentId: this.agentId,
|
|
1149
|
+
subAgentId: agentToRemove.getId()
|
|
1150
|
+
},
|
|
1151
|
+
"Agent removed from agent"
|
|
1152
|
+
);
|
|
1153
|
+
return true;
|
|
1154
|
+
}
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Get all agents in the agent
|
|
1159
|
+
*/
|
|
1160
|
+
getSubAgents() {
|
|
1161
|
+
return this.subAgents;
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* Get all agent ids (unified method for all agent types)
|
|
1165
|
+
*/
|
|
1166
|
+
getSubAgentIds() {
|
|
1167
|
+
return Array.from(this.agentMap.keys());
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Set the default agent
|
|
1171
|
+
*/
|
|
1172
|
+
setDefaultSubAgent(agent2) {
|
|
1173
|
+
this.defaultSubAgent = agent2;
|
|
1174
|
+
this.addSubAgent(agent2);
|
|
1175
|
+
logger6.info(
|
|
1176
|
+
{
|
|
1177
|
+
agentId: this.agentId,
|
|
1178
|
+
defaultSubAgent: agent2.getId()
|
|
1179
|
+
},
|
|
1180
|
+
"Default agent updated"
|
|
1181
|
+
);
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Get the default agent
|
|
1185
|
+
*/
|
|
1186
|
+
getDefaultSubAgent() {
|
|
1187
|
+
return this.defaultSubAgent;
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Get the agent ID
|
|
1191
|
+
*/
|
|
1192
|
+
getId() {
|
|
1193
|
+
return this.agentId;
|
|
1194
|
+
}
|
|
1195
|
+
getName() {
|
|
1196
|
+
return this.agentName;
|
|
1197
|
+
}
|
|
1198
|
+
getDescription() {
|
|
1199
|
+
return this.agentDescription;
|
|
1200
|
+
}
|
|
1201
|
+
getTenantId() {
|
|
1202
|
+
return this.tenantId;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Get the agent's model settingsuration
|
|
1206
|
+
*/
|
|
1207
|
+
getModels() {
|
|
1208
|
+
return this.models;
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Set the agent's model settingsuration
|
|
1212
|
+
*/
|
|
1213
|
+
setModels(models) {
|
|
1214
|
+
this.models = models;
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Get the agent's prompt configuration
|
|
1218
|
+
*/
|
|
1219
|
+
getPrompt() {
|
|
1220
|
+
return this.prompt;
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Get the agent's stopWhen configuration
|
|
1224
|
+
*/
|
|
1225
|
+
getStopWhen() {
|
|
1226
|
+
return this.stopWhen || { transferCountIs: 10 };
|
|
1227
|
+
}
|
|
1228
|
+
/**
|
|
1229
|
+
* Get the agent's status updates configuration
|
|
1230
|
+
*/
|
|
1231
|
+
getStatusUpdateSettings() {
|
|
1232
|
+
return this.statusUpdateSettings;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Get the summarizer model from the agent's model settings
|
|
1236
|
+
*/
|
|
1237
|
+
getSummarizerModel() {
|
|
1238
|
+
return this.models?.summarizer;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Get agent statistics
|
|
1242
|
+
*/
|
|
1243
|
+
getStats() {
|
|
1244
|
+
return {
|
|
1245
|
+
agentCount: this.subAgents.length,
|
|
1246
|
+
defaultSubAgent: this.defaultSubAgent?.getName() || null,
|
|
1247
|
+
initialized: this.initialized,
|
|
1248
|
+
agentId: this.agentId,
|
|
1249
|
+
tenantId: this.tenantId
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
with(options) {
|
|
1253
|
+
return {
|
|
1254
|
+
agent: this,
|
|
1255
|
+
headers: options.headers
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
/**
|
|
1259
|
+
* Validate the agent configuration
|
|
1260
|
+
*/
|
|
1261
|
+
validate() {
|
|
1262
|
+
const errors = [];
|
|
1263
|
+
if (this.subAgents.length === 0) {
|
|
1264
|
+
errors.push("Agent must contain at least one agent");
|
|
1265
|
+
}
|
|
1266
|
+
if (!this.defaultSubAgent) {
|
|
1267
|
+
errors.push("Agent must have a default agent");
|
|
1268
|
+
}
|
|
1269
|
+
const names = /* @__PURE__ */ new Set();
|
|
1270
|
+
for (const subAgent2 of this.subAgents) {
|
|
1271
|
+
const name = subAgent2.getName();
|
|
1272
|
+
if (names.has(name)) {
|
|
1273
|
+
errors.push(`Duplicate agent name: ${name}`);
|
|
1274
|
+
}
|
|
1275
|
+
names.add(name);
|
|
1276
|
+
}
|
|
1277
|
+
for (const subAgent2 of this.subAgents) {
|
|
1278
|
+
const transfers = subAgent2.getTransfers();
|
|
1279
|
+
for (const transferAgent of transfers) {
|
|
1280
|
+
if (!this.agentMap.has(transferAgent.getName())) {
|
|
1281
|
+
errors.push(
|
|
1282
|
+
`Agent '${subAgent2.getName()}' has transfer to '${transferAgent.getName()}' which is not in the agent`
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
const delegates = subAgent2.getDelegates();
|
|
1287
|
+
for (const delegateAgent of delegates) {
|
|
1288
|
+
if (this.isInternalAgent(delegateAgent)) {
|
|
1289
|
+
if (!this.agentMap.has(delegateAgent.getName())) {
|
|
1290
|
+
errors.push(
|
|
1291
|
+
`Agent '${subAgent2.getName()}' has delegation to '${delegateAgent.getName()}' which is not in the agent`
|
|
1292
|
+
);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return {
|
|
1298
|
+
valid: errors.length === 0,
|
|
1299
|
+
errors
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
// Private helper methods
|
|
1303
|
+
async _init() {
|
|
1304
|
+
if (!this.initialized) {
|
|
1305
|
+
await this.init();
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
/**
|
|
1309
|
+
* Type guard to check if an agent is an internal AgentInterface
|
|
1310
|
+
*/
|
|
1311
|
+
isInternalAgent(agent2) {
|
|
1312
|
+
return "getTransfers" in agent2 && typeof agent2.getTransfers === "function";
|
|
1313
|
+
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Get project-level model settingsuration defaults
|
|
1316
|
+
*/
|
|
1317
|
+
async getProjectModelDefaults() {
|
|
1318
|
+
try {
|
|
1319
|
+
const project2 = await getFullProjectViaAPI(this.tenantId, this.projectId, this.baseURL);
|
|
1320
|
+
return project2?.models;
|
|
1321
|
+
} catch (error) {
|
|
1322
|
+
logger6.warn(
|
|
1323
|
+
{
|
|
1324
|
+
tenantId: this.tenantId,
|
|
1325
|
+
projectId: this.projectId,
|
|
1326
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1327
|
+
},
|
|
1328
|
+
"Failed to get project model defaults"
|
|
1329
|
+
);
|
|
1330
|
+
return void 0;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Get project-level stopWhen configuration defaults
|
|
1335
|
+
*/
|
|
1336
|
+
async getProjectStopWhenDefaults() {
|
|
1337
|
+
try {
|
|
1338
|
+
const project2 = await getFullProjectViaAPI(this.tenantId, this.projectId, this.baseURL);
|
|
1339
|
+
return project2?.stopWhen;
|
|
1340
|
+
} catch (error) {
|
|
1341
|
+
logger6.warn(
|
|
1342
|
+
{
|
|
1343
|
+
tenantId: this.tenantId,
|
|
1344
|
+
projectId: this.projectId,
|
|
1345
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1346
|
+
},
|
|
1347
|
+
"Failed to get project stopWhen defaults"
|
|
1348
|
+
);
|
|
1349
|
+
return void 0;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
/**
|
|
1353
|
+
* Apply model inheritance hierarchy: Project -> Agent -> Agent
|
|
1354
|
+
*/
|
|
1355
|
+
async applyModelInheritance() {
|
|
1356
|
+
const projectModels = await this.getProjectModelDefaults();
|
|
1357
|
+
if (projectModels) {
|
|
1358
|
+
if (!this.models) {
|
|
1359
|
+
this.models = {};
|
|
1360
|
+
}
|
|
1361
|
+
if (!this.models.base && projectModels.base) {
|
|
1362
|
+
this.models.base = projectModels.base;
|
|
1363
|
+
}
|
|
1364
|
+
if (!this.models.structuredOutput && projectModels.structuredOutput) {
|
|
1365
|
+
this.models.structuredOutput = projectModels.structuredOutput;
|
|
1366
|
+
}
|
|
1367
|
+
if (!this.models.summarizer && projectModels.summarizer) {
|
|
1368
|
+
this.models.summarizer = projectModels.summarizer;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
await this.applyStopWhenInheritance();
|
|
1372
|
+
for (const subAgent2 of this.subAgents) {
|
|
1373
|
+
this.propagateModelSettingsToAgent(subAgent2);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* Apply stopWhen inheritance hierarchy: Project -> Agent -> Agent
|
|
1378
|
+
*/
|
|
1379
|
+
async applyStopWhenInheritance() {
|
|
1380
|
+
const projectStopWhen = await this.getProjectStopWhenDefaults();
|
|
1381
|
+
if (!this.stopWhen) {
|
|
1382
|
+
this.stopWhen = {};
|
|
1383
|
+
}
|
|
1384
|
+
if (this.stopWhen.transferCountIs === void 0 && projectStopWhen?.transferCountIs !== void 0) {
|
|
1385
|
+
this.stopWhen.transferCountIs = projectStopWhen.transferCountIs;
|
|
1386
|
+
}
|
|
1387
|
+
if (this.stopWhen.transferCountIs === void 0) {
|
|
1388
|
+
this.stopWhen.transferCountIs = 10;
|
|
1389
|
+
}
|
|
1390
|
+
if (projectStopWhen?.stepCountIs !== void 0) {
|
|
1391
|
+
for (const subAgent2 of this.subAgents) {
|
|
1392
|
+
if (!subAgent2.config.stopWhen) {
|
|
1393
|
+
subAgent2.config.stopWhen = {};
|
|
1394
|
+
}
|
|
1395
|
+
if (subAgent2.config.stopWhen.stepCountIs === void 0) {
|
|
1396
|
+
subAgent2.config.stopWhen.stepCountIs = projectStopWhen.stepCountIs;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
logger6.debug(
|
|
1401
|
+
{
|
|
1402
|
+
agentId: this.agentId,
|
|
1403
|
+
agentStopWhen: this.stopWhen,
|
|
1404
|
+
projectStopWhen
|
|
1405
|
+
},
|
|
1406
|
+
"Applied stopWhen inheritance from project to agent"
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Propagate agent-level model settings to agents (supporting partial inheritance)
|
|
1411
|
+
*/
|
|
1412
|
+
propagateModelSettingsToAgent(agent2) {
|
|
1413
|
+
if (this.models) {
|
|
1414
|
+
if (!agent2.config.models) {
|
|
1415
|
+
agent2.config.models = {};
|
|
1416
|
+
}
|
|
1417
|
+
if (!agent2.config.models.base && this.models.base) {
|
|
1418
|
+
agent2.config.models.base = this.models.base;
|
|
1419
|
+
}
|
|
1420
|
+
if (!agent2.config.models.structuredOutput && this.models.structuredOutput) {
|
|
1421
|
+
agent2.config.models.structuredOutput = this.models.structuredOutput;
|
|
1422
|
+
}
|
|
1423
|
+
if (!agent2.config.models.summarizer && this.models.summarizer) {
|
|
1424
|
+
agent2.config.models.summarizer = this.models.summarizer;
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
/**
|
|
1429
|
+
* Immediately propagate agent-level models to all agents during construction
|
|
1430
|
+
*/
|
|
1431
|
+
propagateImmediateModelSettings() {
|
|
1432
|
+
for (const subAgent2 of this.subAgents) {
|
|
1433
|
+
this.propagateModelSettingsToAgent(subAgent2);
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
/**
|
|
1437
|
+
* Execute agent using the backend system instead of local runner
|
|
1438
|
+
*/
|
|
1439
|
+
async executeWithBackend(input, options) {
|
|
1440
|
+
const normalizedMessages = this.normalizeMessages(input);
|
|
1441
|
+
const url = `${this.baseURL}/tenants/${this.tenantId}/agent/${this.agentId}/v1/chat/completions`;
|
|
1442
|
+
logger6.info({ url }, "Executing with backend");
|
|
1443
|
+
const requestBody = {
|
|
1444
|
+
model: "gpt-4o-mini",
|
|
1445
|
+
messages: normalizedMessages.map((msg) => ({
|
|
1446
|
+
role: msg.role,
|
|
1447
|
+
content: msg.content
|
|
1448
|
+
})),
|
|
1449
|
+
...options,
|
|
1450
|
+
// Include conversationId for multi-turn support
|
|
1451
|
+
...options?.conversationId && {
|
|
1452
|
+
conversationId: options.conversationId
|
|
1453
|
+
},
|
|
1454
|
+
// Include context data if available
|
|
1455
|
+
...options?.customBodyParams && { ...options.customBodyParams },
|
|
1456
|
+
stream: false
|
|
1457
|
+
// Explicitly disable streaming - must come after options to override
|
|
1458
|
+
};
|
|
1459
|
+
try {
|
|
1460
|
+
const response = await fetch(url, {
|
|
1461
|
+
method: "POST",
|
|
1462
|
+
headers: {
|
|
1463
|
+
"Content-Type": "application/json",
|
|
1464
|
+
Accept: "application/json"
|
|
1465
|
+
},
|
|
1466
|
+
body: JSON.stringify(requestBody)
|
|
1467
|
+
});
|
|
1468
|
+
if (!response.ok) {
|
|
1469
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
1470
|
+
}
|
|
1471
|
+
const responseText = await response.text();
|
|
1472
|
+
if (responseText.startsWith("data:")) {
|
|
1473
|
+
return this.parseStreamingResponse(responseText);
|
|
1474
|
+
}
|
|
1475
|
+
const data = JSON.parse(responseText);
|
|
1476
|
+
return data.result || data.choices?.[0]?.message?.content || "";
|
|
1477
|
+
} catch (error) {
|
|
1478
|
+
throw new Error(`Agent execution failed: ${error.message || "Unknown error"}`);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
/**
|
|
1482
|
+
* Parse streaming response in SSE format
|
|
1483
|
+
*/
|
|
1484
|
+
parseStreamingResponse(text) {
|
|
1485
|
+
const lines = text.split("\n");
|
|
1486
|
+
let content = "";
|
|
1487
|
+
for (const line of lines) {
|
|
1488
|
+
if (line.startsWith("data: ")) {
|
|
1489
|
+
const dataStr = line.slice(6);
|
|
1490
|
+
if (dataStr === "[DONE]") break;
|
|
1491
|
+
try {
|
|
1492
|
+
const data = JSON.parse(dataStr);
|
|
1493
|
+
const delta = data.choices?.[0]?.delta?.content;
|
|
1494
|
+
if (delta) {
|
|
1495
|
+
content += delta;
|
|
1496
|
+
}
|
|
1497
|
+
} catch (_e) {
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
return content;
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Normalize input messages to the expected format
|
|
1505
|
+
*/
|
|
1506
|
+
normalizeMessages(input) {
|
|
1507
|
+
if (typeof input === "string") {
|
|
1508
|
+
return [{ role: "user", content: input }];
|
|
1509
|
+
}
|
|
1510
|
+
if (Array.isArray(input)) {
|
|
1511
|
+
return input.map((msg) => typeof msg === "string" ? { role: "user", content: msg } : msg);
|
|
1512
|
+
}
|
|
1513
|
+
return [input];
|
|
1514
|
+
}
|
|
1515
|
+
async saveToDatabase() {
|
|
1516
|
+
try {
|
|
1517
|
+
const getUrl = `${this.baseURL}/tenants/${this.tenantId}/agents/${this.agentId}`;
|
|
1518
|
+
try {
|
|
1519
|
+
const getResponse = await fetch(getUrl, {
|
|
1520
|
+
method: "GET",
|
|
1521
|
+
headers: {
|
|
1522
|
+
"Content-Type": "application/json"
|
|
1523
|
+
}
|
|
1524
|
+
});
|
|
1525
|
+
if (getResponse.ok) {
|
|
1526
|
+
logger6.info({ agentId: this.agentId }, "Agent already exists in backend");
|
|
1527
|
+
return;
|
|
1528
|
+
}
|
|
1529
|
+
if (getResponse.status !== 404) {
|
|
1530
|
+
throw new Error(`HTTP ${getResponse.status}: ${getResponse.statusText}`);
|
|
1531
|
+
}
|
|
1532
|
+
} catch (error) {
|
|
1533
|
+
if (!error.message.includes("404")) {
|
|
1534
|
+
throw error;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
logger6.info({ agentId: this.agentId }, "Creating agent in backend");
|
|
1538
|
+
const createUrl = `${this.baseURL}/tenants/${this.tenantId}/agents`;
|
|
1539
|
+
const createResponse = await fetch(createUrl, {
|
|
1540
|
+
method: "POST",
|
|
1541
|
+
headers: {
|
|
1542
|
+
"Content-Type": "application/json"
|
|
1543
|
+
},
|
|
1544
|
+
body: JSON.stringify({
|
|
1545
|
+
id: this.agentId,
|
|
1546
|
+
name: this.agentName,
|
|
1547
|
+
defaultSubAgentId: this.defaultSubAgent?.getId() || "",
|
|
1548
|
+
contextConfigId: this.contextConfig?.getId(),
|
|
1549
|
+
models: this.models
|
|
1550
|
+
})
|
|
1551
|
+
});
|
|
1552
|
+
if (!createResponse.ok) {
|
|
1553
|
+
throw new Error(`HTTP ${createResponse.status}: ${createResponse.statusText}`);
|
|
1554
|
+
}
|
|
1555
|
+
const createData = await createResponse.json();
|
|
1556
|
+
this.agentId = createData.data.id;
|
|
1557
|
+
logger6.info({ agent: createData.data }, "Agent created in backend");
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
throw new Error(
|
|
1560
|
+
`Failed to save agent to database: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1561
|
+
);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
async saveRelations() {
|
|
1565
|
+
if (this.defaultSubAgent) {
|
|
1566
|
+
try {
|
|
1567
|
+
const updateUrl = `${this.baseURL}/tenants/${this.tenantId}/agents/${this.agentId}`;
|
|
1568
|
+
const updateResponse = await fetch(updateUrl, {
|
|
1569
|
+
method: "PUT",
|
|
1570
|
+
headers: {
|
|
1571
|
+
"Content-Type": "application/json"
|
|
1572
|
+
},
|
|
1573
|
+
body: JSON.stringify({
|
|
1574
|
+
id: this.agentId,
|
|
1575
|
+
defaultSubAgentId: this.defaultSubAgent.getId(),
|
|
1576
|
+
contextConfigId: this.contextConfig?.getId()
|
|
1577
|
+
})
|
|
1578
|
+
});
|
|
1579
|
+
if (!updateResponse.ok) {
|
|
1580
|
+
throw new Error(`HTTP ${updateResponse.status}: ${updateResponse.statusText}`);
|
|
1581
|
+
}
|
|
1582
|
+
logger6.debug(
|
|
1583
|
+
{
|
|
1584
|
+
agentId: this.agentId,
|
|
1585
|
+
defaultSubAgent: this.defaultSubAgent.getName()
|
|
1586
|
+
},
|
|
1587
|
+
"Agent relationships configured"
|
|
1588
|
+
);
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
logger6.error(
|
|
1591
|
+
{
|
|
1592
|
+
agentId: this.agentId,
|
|
1593
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1594
|
+
},
|
|
1595
|
+
"Failed to update agent relationships"
|
|
1596
|
+
);
|
|
1597
|
+
throw error;
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
async createSubAgentRelations() {
|
|
1602
|
+
const allSubAgentRelationPromises = [];
|
|
1603
|
+
for (const subAgent2 of this.subAgents) {
|
|
1604
|
+
const transfers = subAgent2.getTransfers();
|
|
1605
|
+
for (const transferAgent of transfers) {
|
|
1606
|
+
allSubAgentRelationPromises.push(
|
|
1607
|
+
this.createSubAgentRelation(subAgent2, transferAgent, "transfer")
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
const delegates = subAgent2.getSubAgentDelegates();
|
|
1611
|
+
for (const delegate of delegates) {
|
|
1612
|
+
if (this.isInternalAgent(delegate)) {
|
|
1613
|
+
allSubAgentRelationPromises.push(
|
|
1614
|
+
this.createSubAgentRelation(subAgent2, delegate, "delegate")
|
|
1615
|
+
);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
const results = await Promise.allSettled(allSubAgentRelationPromises);
|
|
1620
|
+
const errors = [];
|
|
1621
|
+
let successCount = 0;
|
|
1622
|
+
for (const result of results) {
|
|
1623
|
+
if (result.status === "fulfilled") {
|
|
1624
|
+
successCount++;
|
|
1625
|
+
} else {
|
|
1626
|
+
errors.push(result.reason);
|
|
1627
|
+
logger6.error(
|
|
1628
|
+
{
|
|
1629
|
+
error: result.reason instanceof Error ? result.reason.message : "Unknown error",
|
|
1630
|
+
agentId: this.agentId
|
|
1631
|
+
},
|
|
1632
|
+
"Failed to create agent relation"
|
|
1633
|
+
);
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
logger6.info(
|
|
1637
|
+
{
|
|
1638
|
+
agentId: this.agentId,
|
|
1639
|
+
totalRelations: allSubAgentRelationPromises.length,
|
|
1640
|
+
successCount,
|
|
1641
|
+
errorCount: errors.length
|
|
1642
|
+
},
|
|
1643
|
+
"Completed agent relation creation batch"
|
|
1644
|
+
);
|
|
1645
|
+
if (errors.length > 0 && successCount === 0) {
|
|
1646
|
+
throw new Error(`All ${errors.length} agent relation creations failed`);
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
async createSubAgentRelation(sourceAgent, targetAgent, relationType) {
|
|
1650
|
+
try {
|
|
1651
|
+
const response = await fetch(`${this.baseURL}/tenants/${this.tenantId}/agent-relations`, {
|
|
1652
|
+
method: "POST",
|
|
1653
|
+
headers: {
|
|
1654
|
+
"Content-Type": "application/json"
|
|
1655
|
+
},
|
|
1656
|
+
body: JSON.stringify({
|
|
1657
|
+
agentId: this.agentId,
|
|
1658
|
+
sourceSubAgentId: sourceAgent.getId(),
|
|
1659
|
+
targetSubAgentId: targetAgent.getId(),
|
|
1660
|
+
relationType
|
|
1661
|
+
})
|
|
1662
|
+
});
|
|
1663
|
+
if (!response.ok) {
|
|
1664
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
1665
|
+
if (response.status === 422 && errorText.includes("already exists")) {
|
|
1666
|
+
logger6.info(
|
|
1667
|
+
{
|
|
1668
|
+
sourceSubAgentId: sourceAgent.getId(),
|
|
1669
|
+
targetSubAgentId: targetAgent.getId(),
|
|
1670
|
+
agentId: this.agentId,
|
|
1671
|
+
relationType
|
|
1672
|
+
},
|
|
1673
|
+
`${relationType} relation already exists, skipping creation`
|
|
1674
|
+
);
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
throw new Error(`Failed to create subAgent relation: ${response.status} - ${errorText}`);
|
|
1678
|
+
}
|
|
1679
|
+
logger6.info(
|
|
1680
|
+
{
|
|
1681
|
+
sourceSubAgentId: sourceAgent.getId(),
|
|
1682
|
+
targetSubAgentId: targetAgent.getId(),
|
|
1683
|
+
agentId: this.agentId,
|
|
1684
|
+
relationType
|
|
1685
|
+
},
|
|
1686
|
+
`${relationType} subAgent relation created successfully`
|
|
1687
|
+
);
|
|
1688
|
+
} catch (error) {
|
|
1689
|
+
logger6.error(
|
|
1690
|
+
{
|
|
1691
|
+
sourceSubAgentId: sourceAgent.getId(),
|
|
1692
|
+
targetSubAgentId: targetAgent.getId(),
|
|
1693
|
+
agentId: this.agentId,
|
|
1694
|
+
relationType,
|
|
1695
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1696
|
+
},
|
|
1697
|
+
`Failed to create ${relationType} subAgent relation`
|
|
1698
|
+
);
|
|
1699
|
+
throw error;
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
};
|
|
1703
|
+
var logger7 = getLogger("dataComponent");
|
|
1704
|
+
var DataComponent = class {
|
|
1705
|
+
constructor(config) {
|
|
1706
|
+
__publicField(this, "config");
|
|
1707
|
+
__publicField(this, "baseURL");
|
|
1708
|
+
__publicField(this, "tenantId");
|
|
1709
|
+
__publicField(this, "projectId");
|
|
1710
|
+
__publicField(this, "initialized", false);
|
|
1711
|
+
__publicField(this, "id");
|
|
1712
|
+
this.id = config.id || generateIdFromName(config.name);
|
|
1713
|
+
let processedProps;
|
|
1714
|
+
if (config.props && isZodSchema(config.props)) {
|
|
1715
|
+
processedProps = convertZodToJsonSchema(config.props);
|
|
1716
|
+
} else {
|
|
1717
|
+
processedProps = config.props;
|
|
1718
|
+
}
|
|
1719
|
+
this.config = {
|
|
1720
|
+
...config,
|
|
1721
|
+
id: this.id,
|
|
1722
|
+
props: processedProps,
|
|
1723
|
+
render: config.render || null
|
|
1724
|
+
};
|
|
1725
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
1726
|
+
this.tenantId = "default";
|
|
1727
|
+
this.projectId = "default";
|
|
1728
|
+
logger7.info(
|
|
1729
|
+
{
|
|
1730
|
+
dataComponentId: this.getId(),
|
|
1731
|
+
dataComponentName: config.name
|
|
1732
|
+
},
|
|
1733
|
+
"DataComponent constructor initialized"
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
// Set context (tenantId, projectId, and baseURL) from external source (sub-agent, agent, CLI, etc)
|
|
1737
|
+
setContext(tenantId, projectId, baseURL) {
|
|
1738
|
+
this.tenantId = tenantId;
|
|
1739
|
+
this.projectId = projectId;
|
|
1740
|
+
if (baseURL) {
|
|
1741
|
+
this.baseURL = baseURL;
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
// Compute ID from name using same slug transformation as agents
|
|
1745
|
+
getId() {
|
|
1746
|
+
return this.id;
|
|
1747
|
+
}
|
|
1748
|
+
getName() {
|
|
1749
|
+
return this.config.name;
|
|
1750
|
+
}
|
|
1751
|
+
getDescription() {
|
|
1752
|
+
return this.config.description;
|
|
1753
|
+
}
|
|
1754
|
+
getProps() {
|
|
1755
|
+
return this.config.props;
|
|
1756
|
+
}
|
|
1757
|
+
getRender() {
|
|
1758
|
+
return this.config.render;
|
|
1759
|
+
}
|
|
1760
|
+
// Public method to ensure data component exists in backend (with upsert behavior)
|
|
1761
|
+
async init() {
|
|
1762
|
+
if (this.initialized) return;
|
|
1763
|
+
try {
|
|
1764
|
+
await this.upsertDataComponent();
|
|
1765
|
+
logger7.info(
|
|
1766
|
+
{
|
|
1767
|
+
dataComponentId: this.getId()
|
|
1768
|
+
},
|
|
1769
|
+
"DataComponent initialized successfully"
|
|
1770
|
+
);
|
|
1771
|
+
this.initialized = true;
|
|
1772
|
+
} catch (error) {
|
|
1773
|
+
logger7.error(
|
|
1774
|
+
{
|
|
1775
|
+
dataComponentId: this.getId(),
|
|
1776
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
1777
|
+
},
|
|
1778
|
+
"Failed to initialize data component"
|
|
1779
|
+
);
|
|
1780
|
+
throw error;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
// Private method to upsert data component (create or update)
|
|
1784
|
+
async upsertDataComponent() {
|
|
1785
|
+
const dataComponentData = {
|
|
1786
|
+
id: this.getId(),
|
|
1787
|
+
name: this.config.name,
|
|
1788
|
+
description: this.config.description,
|
|
1789
|
+
props: this.config.props,
|
|
1790
|
+
render: this.config.render
|
|
1791
|
+
};
|
|
1792
|
+
logger7.info({ dataComponentData }, "dataComponentData for create/update");
|
|
1793
|
+
const updateResponse = await fetch(
|
|
1794
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/data-components/${this.getId()}`,
|
|
1795
|
+
{
|
|
1796
|
+
method: "PUT",
|
|
1797
|
+
headers: {
|
|
1798
|
+
"Content-Type": "application/json"
|
|
1799
|
+
},
|
|
1800
|
+
body: JSON.stringify(dataComponentData)
|
|
1801
|
+
}
|
|
1802
|
+
);
|
|
1803
|
+
logger7.info(
|
|
1804
|
+
{
|
|
1805
|
+
status: updateResponse.status,
|
|
1806
|
+
dataComponentId: this.getId()
|
|
1807
|
+
},
|
|
1808
|
+
"data component updateResponse"
|
|
1809
|
+
);
|
|
1810
|
+
if (updateResponse.ok) {
|
|
1811
|
+
logger7.info(
|
|
1812
|
+
{
|
|
1813
|
+
dataComponentId: this.getId()
|
|
1814
|
+
},
|
|
1815
|
+
"DataComponent updated successfully"
|
|
1816
|
+
);
|
|
1817
|
+
return;
|
|
1818
|
+
}
|
|
1819
|
+
if (updateResponse.status === 404) {
|
|
1820
|
+
logger7.info(
|
|
1821
|
+
{
|
|
1822
|
+
dataComponentId: this.getId()
|
|
1823
|
+
},
|
|
1824
|
+
"DataComponent not found, creating new data component"
|
|
1825
|
+
);
|
|
1826
|
+
const createResponse = await fetch(
|
|
1827
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/data-components`,
|
|
1828
|
+
{
|
|
1829
|
+
method: "POST",
|
|
1830
|
+
headers: {
|
|
1831
|
+
"Content-Type": "application/json"
|
|
1832
|
+
},
|
|
1833
|
+
body: JSON.stringify(dataComponentData)
|
|
1834
|
+
}
|
|
1835
|
+
);
|
|
1836
|
+
if (!createResponse.ok) {
|
|
1837
|
+
const errorText2 = await createResponse.text().catch(() => "Unknown error");
|
|
1838
|
+
throw new Error(
|
|
1839
|
+
`Failed to create data component: ${createResponse.status} ${createResponse.statusText} - ${errorText2}`
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
logger7.info(
|
|
1843
|
+
{
|
|
1844
|
+
dataComponentId: this.getId()
|
|
1845
|
+
},
|
|
1846
|
+
"DataComponent created successfully"
|
|
1847
|
+
);
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
const errorText = await updateResponse.text().catch(() => "Unknown error");
|
|
1851
|
+
throw new Error(
|
|
1852
|
+
`Failed to update data component: ${updateResponse.status} ${updateResponse.statusText} - ${errorText}`
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
};
|
|
1856
|
+
var logger8 = getLogger("project");
|
|
1857
|
+
var Project = class {
|
|
1858
|
+
constructor(config) {
|
|
1859
|
+
__publicField(this, "__type", "project");
|
|
1860
|
+
__publicField(this, "projectId");
|
|
1861
|
+
__publicField(this, "projectName");
|
|
1862
|
+
__publicField(this, "projectDescription");
|
|
1863
|
+
__publicField(this, "tenantId");
|
|
1864
|
+
__publicField(this, "baseURL");
|
|
1865
|
+
__publicField(this, "apiKey");
|
|
1866
|
+
__publicField(this, "initialized", false);
|
|
1867
|
+
__publicField(this, "models");
|
|
1868
|
+
__publicField(this, "stopWhen");
|
|
1869
|
+
__publicField(this, "agents", []);
|
|
1870
|
+
__publicField(this, "agentMap", /* @__PURE__ */ new Map());
|
|
1871
|
+
__publicField(this, "credentialReferences", []);
|
|
1872
|
+
__publicField(this, "projectTools", []);
|
|
1873
|
+
__publicField(this, "projectDataComponents", []);
|
|
1874
|
+
__publicField(this, "projectArtifactComponents", []);
|
|
1875
|
+
__publicField(this, "projectExternalAgents", []);
|
|
1876
|
+
__publicField(this, "externalAgentMap", /* @__PURE__ */ new Map());
|
|
1877
|
+
this.projectId = config.id;
|
|
1878
|
+
this.projectName = config.name;
|
|
1879
|
+
this.projectDescription = config.description;
|
|
1880
|
+
this.tenantId = process.env.INKEEP_TENANT_ID || "default";
|
|
1881
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
1882
|
+
this.models = config.models;
|
|
1883
|
+
this.stopWhen = config.stopWhen;
|
|
1884
|
+
if (config.agents) {
|
|
1885
|
+
this.agents = config.agents();
|
|
1886
|
+
this.agentMap = new Map(this.agents.map((agent2) => [agent2.getId(), agent2]));
|
|
1887
|
+
for (const agent2 of this.agents) {
|
|
1888
|
+
agent2.setConfig(this.tenantId, this.projectId, this.baseURL);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
if (config.tools) {
|
|
1892
|
+
this.projectTools = config.tools();
|
|
1893
|
+
}
|
|
1894
|
+
if (config.dataComponents) {
|
|
1895
|
+
this.projectDataComponents = config.dataComponents();
|
|
1896
|
+
}
|
|
1897
|
+
if (config.artifactComponents) {
|
|
1898
|
+
this.projectArtifactComponents = config.artifactComponents();
|
|
1899
|
+
}
|
|
1900
|
+
if (config.credentialReferences) {
|
|
1901
|
+
this.credentialReferences = config.credentialReferences();
|
|
1902
|
+
}
|
|
1903
|
+
if (config.externalAgents) {
|
|
1904
|
+
this.projectExternalAgents = config.externalAgents();
|
|
1905
|
+
this.externalAgentMap = new Map(
|
|
1906
|
+
this.projectExternalAgents.map((externalAgent2) => [externalAgent2.getId(), externalAgent2])
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
logger8.info(
|
|
1910
|
+
{
|
|
1911
|
+
projectId: this.projectId,
|
|
1912
|
+
tenantId: this.tenantId,
|
|
1913
|
+
agentCount: this.agents.length
|
|
1914
|
+
},
|
|
1915
|
+
"Project created"
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
/**
|
|
1919
|
+
* Set or update the configuration (tenantId and apiUrl)
|
|
1920
|
+
* This is used by the CLI to inject configuration from inkeep.config.ts
|
|
1921
|
+
*/
|
|
1922
|
+
setConfig(tenantId, apiUrl, models, apiKey) {
|
|
1923
|
+
if (this.initialized) {
|
|
1924
|
+
throw new Error("Cannot set config after project has been initialized");
|
|
1925
|
+
}
|
|
1926
|
+
this.tenantId = tenantId;
|
|
1927
|
+
this.baseURL = apiUrl;
|
|
1928
|
+
this.apiKey = apiKey;
|
|
1929
|
+
if (models) {
|
|
1930
|
+
this.models = models;
|
|
1931
|
+
}
|
|
1932
|
+
for (const agent2 of this.agents) {
|
|
1933
|
+
agent2.setConfig(tenantId, this.projectId, apiUrl);
|
|
1934
|
+
}
|
|
1935
|
+
logger8.info(
|
|
1936
|
+
{
|
|
1937
|
+
projectId: this.projectId,
|
|
1938
|
+
tenantId: this.tenantId,
|
|
1939
|
+
apiUrl: this.baseURL,
|
|
1940
|
+
hasModels: !!this.models,
|
|
1941
|
+
hasApiKey: !!this.apiKey
|
|
1942
|
+
},
|
|
1943
|
+
"Project configuration updated"
|
|
1944
|
+
);
|
|
1945
|
+
}
|
|
1946
|
+
/**
|
|
1947
|
+
* Set credential references for the project
|
|
1948
|
+
* This is used by the CLI to inject environment-specific credentials
|
|
1949
|
+
*/
|
|
1950
|
+
setCredentials(credentials) {
|
|
1951
|
+
this.credentialReferences = Object.values(credentials);
|
|
1952
|
+
logger8.info(
|
|
1953
|
+
{
|
|
1954
|
+
projectId: this.projectId,
|
|
1955
|
+
credentialCount: this.credentialReferences?.length || 0
|
|
1956
|
+
},
|
|
1957
|
+
"Project credentials updated"
|
|
1958
|
+
);
|
|
1959
|
+
}
|
|
1960
|
+
/**
|
|
1961
|
+
* Initialize the project and create/update it in the backend using full project approach
|
|
1962
|
+
*/
|
|
1963
|
+
async init() {
|
|
1964
|
+
if (this.initialized) {
|
|
1965
|
+
logger8.info({ projectId: this.projectId }, "Project already initialized");
|
|
1966
|
+
return;
|
|
1967
|
+
}
|
|
1968
|
+
logger8.info(
|
|
1969
|
+
{
|
|
1970
|
+
projectId: this.projectId,
|
|
1971
|
+
tenantId: this.tenantId,
|
|
1972
|
+
agentCount: this.agents.length
|
|
1973
|
+
},
|
|
1974
|
+
"Initializing project using full project endpoint"
|
|
1975
|
+
);
|
|
1976
|
+
try {
|
|
1977
|
+
const projectDefinition = await this.toFullProjectDefinition();
|
|
1978
|
+
logger8.info(
|
|
1979
|
+
{
|
|
1980
|
+
projectId: this.projectId,
|
|
1981
|
+
mode: "api-client",
|
|
1982
|
+
apiUrl: this.baseURL
|
|
1983
|
+
},
|
|
1984
|
+
"Using API client to create/update full project"
|
|
1985
|
+
);
|
|
1986
|
+
const createdProject = await updateFullProjectViaAPI(
|
|
1987
|
+
this.tenantId,
|
|
1988
|
+
this.baseURL,
|
|
1989
|
+
this.projectId,
|
|
1990
|
+
projectDefinition,
|
|
1991
|
+
this.apiKey
|
|
1992
|
+
);
|
|
1993
|
+
this.initialized = true;
|
|
1994
|
+
logger8.info(
|
|
1995
|
+
{
|
|
1996
|
+
projectId: this.projectId,
|
|
1997
|
+
tenantId: this.tenantId,
|
|
1998
|
+
agentCount: Object.keys(createdProject.agent || {}).length
|
|
1999
|
+
},
|
|
2000
|
+
"Project initialized successfully using full project endpoint"
|
|
2001
|
+
);
|
|
2002
|
+
} catch (error) {
|
|
2003
|
+
logger8.error(
|
|
2004
|
+
{
|
|
2005
|
+
projectId: this.projectId,
|
|
2006
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
2007
|
+
},
|
|
2008
|
+
"Failed to initialize project using full project endpoint"
|
|
2009
|
+
);
|
|
2010
|
+
throw error;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Get the project ID
|
|
2015
|
+
*/
|
|
2016
|
+
getId() {
|
|
2017
|
+
return this.projectId;
|
|
2018
|
+
}
|
|
2019
|
+
/**
|
|
2020
|
+
* Get the project name
|
|
2021
|
+
*/
|
|
2022
|
+
getName() {
|
|
2023
|
+
return this.projectName;
|
|
2024
|
+
}
|
|
2025
|
+
/**
|
|
2026
|
+
* Get the project description
|
|
2027
|
+
*/
|
|
2028
|
+
getDescription() {
|
|
2029
|
+
return this.projectDescription;
|
|
2030
|
+
}
|
|
2031
|
+
/**
|
|
2032
|
+
* Get the tenant ID
|
|
2033
|
+
*/
|
|
2034
|
+
getTenantId() {
|
|
2035
|
+
return this.tenantId;
|
|
2036
|
+
}
|
|
2037
|
+
/**
|
|
2038
|
+
* Get the project's model configuration
|
|
2039
|
+
*/
|
|
2040
|
+
getModels() {
|
|
2041
|
+
return this.models;
|
|
2042
|
+
}
|
|
2043
|
+
/**
|
|
2044
|
+
* Set the project's model configuration
|
|
2045
|
+
*/
|
|
2046
|
+
setModels(models) {
|
|
2047
|
+
this.models = models;
|
|
2048
|
+
}
|
|
2049
|
+
/**
|
|
2050
|
+
* Get the project's stopWhen configuration
|
|
2051
|
+
*/
|
|
2052
|
+
getStopWhen() {
|
|
2053
|
+
return this.stopWhen;
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* Set the project's stopWhen configuration
|
|
2057
|
+
*/
|
|
2058
|
+
setStopWhen(stopWhen) {
|
|
2059
|
+
this.stopWhen = stopWhen;
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Get credential tracking information
|
|
2063
|
+
*/
|
|
2064
|
+
async getCredentialTracking() {
|
|
2065
|
+
const fullDef = await this.toFullProjectDefinition();
|
|
2066
|
+
const credentials = fullDef.credentialReferences || {};
|
|
2067
|
+
const usage = {};
|
|
2068
|
+
for (const [credId, credData] of Object.entries(credentials)) {
|
|
2069
|
+
if (credData.usedBy) {
|
|
2070
|
+
usage[credId] = credData.usedBy;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
return { credentials, usage };
|
|
2074
|
+
}
|
|
2075
|
+
async getFullDefinition() {
|
|
2076
|
+
return await this.toFullProjectDefinition();
|
|
2077
|
+
}
|
|
2078
|
+
/**
|
|
2079
|
+
* Get all agent in the project
|
|
2080
|
+
*/
|
|
2081
|
+
getAgents() {
|
|
2082
|
+
return this.agents;
|
|
2083
|
+
}
|
|
2084
|
+
/**
|
|
2085
|
+
* Get all external agents in the project
|
|
2086
|
+
*/
|
|
2087
|
+
getExternalAgents() {
|
|
2088
|
+
return this.projectExternalAgents;
|
|
2089
|
+
}
|
|
2090
|
+
/**
|
|
2091
|
+
* Get an external agent by ID
|
|
2092
|
+
*/
|
|
2093
|
+
getExternalAgent(id) {
|
|
2094
|
+
return this.externalAgentMap.get(id);
|
|
2095
|
+
}
|
|
2096
|
+
/**
|
|
2097
|
+
* Add an external agent to the project
|
|
2098
|
+
*/
|
|
2099
|
+
addExternalAgent(externalAgent2) {
|
|
2100
|
+
this.projectExternalAgents.push(externalAgent2);
|
|
2101
|
+
this.externalAgentMap.set(externalAgent2.getId(), externalAgent2);
|
|
2102
|
+
}
|
|
2103
|
+
/**
|
|
2104
|
+
* Remove an external agent from the project
|
|
2105
|
+
*/
|
|
2106
|
+
removeExternalAgent(id) {
|
|
2107
|
+
const externalAgentToRemove = this.externalAgentMap.get(id);
|
|
2108
|
+
if (externalAgentToRemove) {
|
|
2109
|
+
this.externalAgentMap.delete(id);
|
|
2110
|
+
this.projectExternalAgents = this.projectExternalAgents.filter(
|
|
2111
|
+
(externalAgent2) => externalAgent2.getId() !== id
|
|
2112
|
+
);
|
|
2113
|
+
logger8.info(
|
|
2114
|
+
{
|
|
2115
|
+
projectId: this.projectId,
|
|
2116
|
+
externalAgentId: id
|
|
2117
|
+
},
|
|
2118
|
+
"External agent removed from project"
|
|
2119
|
+
);
|
|
2120
|
+
return true;
|
|
2121
|
+
}
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
/**
|
|
2125
|
+
* Get an agent by ID
|
|
2126
|
+
*/
|
|
2127
|
+
getAgent(id) {
|
|
2128
|
+
return this.agentMap.get(id);
|
|
2129
|
+
}
|
|
2130
|
+
/**
|
|
2131
|
+
* Add an agent to the project
|
|
2132
|
+
*/
|
|
2133
|
+
addAgent(agent2) {
|
|
2134
|
+
this.agents.push(agent2);
|
|
2135
|
+
this.agentMap.set(agent2.getId(), agent2);
|
|
2136
|
+
agent2.setConfig(this.tenantId, this.projectId, this.baseURL);
|
|
2137
|
+
logger8.info(
|
|
2138
|
+
{
|
|
2139
|
+
projectId: this.projectId,
|
|
2140
|
+
agentId: agent2.getId()
|
|
2141
|
+
},
|
|
2142
|
+
"Agent added to project"
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
/**
|
|
2146
|
+
* Remove an agent from the project
|
|
2147
|
+
*/
|
|
2148
|
+
removeAgent(id) {
|
|
2149
|
+
const agentToRemove = this.agentMap.get(id);
|
|
2150
|
+
if (agentToRemove) {
|
|
2151
|
+
this.agentMap.delete(id);
|
|
2152
|
+
this.agents = this.agents.filter((agent2) => agent2.getId() !== id);
|
|
2153
|
+
logger8.info(
|
|
2154
|
+
{
|
|
2155
|
+
projectId: this.projectId,
|
|
2156
|
+
agentId: id
|
|
2157
|
+
},
|
|
2158
|
+
"Agent removed from project"
|
|
2159
|
+
);
|
|
2160
|
+
return true;
|
|
2161
|
+
}
|
|
2162
|
+
return false;
|
|
2163
|
+
}
|
|
2164
|
+
/**
|
|
2165
|
+
* Get project statistics
|
|
2166
|
+
*/
|
|
2167
|
+
getStats() {
|
|
2168
|
+
return {
|
|
2169
|
+
projectId: this.projectId,
|
|
2170
|
+
tenantId: this.tenantId,
|
|
2171
|
+
agentCount: this.agents.length,
|
|
2172
|
+
initialized: this.initialized
|
|
2173
|
+
};
|
|
2174
|
+
}
|
|
2175
|
+
/**
|
|
2176
|
+
* Validate the project configuration
|
|
2177
|
+
*/
|
|
2178
|
+
validate() {
|
|
2179
|
+
const errors = [];
|
|
2180
|
+
if (!this.projectId) {
|
|
2181
|
+
errors.push("Project must have an ID");
|
|
2182
|
+
}
|
|
2183
|
+
if (!this.projectName) {
|
|
2184
|
+
errors.push("Project must have a name");
|
|
2185
|
+
}
|
|
2186
|
+
const agentIds = /* @__PURE__ */ new Set();
|
|
2187
|
+
for (const agent2 of this.agents) {
|
|
2188
|
+
const id = agent2.getId();
|
|
2189
|
+
if (agentIds.has(id)) {
|
|
2190
|
+
errors.push(`Duplicate agent ID: ${id}`);
|
|
2191
|
+
}
|
|
2192
|
+
agentIds.add(id);
|
|
2193
|
+
}
|
|
2194
|
+
for (const agent2 of this.agents) {
|
|
2195
|
+
const agentValidation = agent2.validate();
|
|
2196
|
+
if (!agentValidation.valid) {
|
|
2197
|
+
errors.push(...agentValidation.errors.map((error) => `Agent '${agent2.getId()}': ${error}`));
|
|
2198
|
+
}
|
|
2199
|
+
}
|
|
2200
|
+
return {
|
|
2201
|
+
valid: errors.length === 0,
|
|
2202
|
+
errors
|
|
2203
|
+
};
|
|
2204
|
+
}
|
|
2205
|
+
/**
|
|
2206
|
+
* Convert the Project to FullProjectDefinition format
|
|
2207
|
+
*/
|
|
2208
|
+
async toFullProjectDefinition() {
|
|
2209
|
+
const agentsObject = {};
|
|
2210
|
+
const toolsObject = {};
|
|
2211
|
+
const functionToolsObject = {};
|
|
2212
|
+
const functionsObject = {};
|
|
2213
|
+
const dataComponentsObject = {};
|
|
2214
|
+
const artifactComponentsObject = {};
|
|
2215
|
+
const credentialReferencesObject = {};
|
|
2216
|
+
const externalAgentsObject = {};
|
|
2217
|
+
const credentialUsageMap = {};
|
|
2218
|
+
for (const agent2 of this.agents) {
|
|
2219
|
+
logger8.info({ agentId: agent2.getId() }, "Agent id");
|
|
2220
|
+
const agentDefinition = await agent2.toFullAgentDefinition();
|
|
2221
|
+
agentsObject[agent2.getId()] = agentDefinition;
|
|
2222
|
+
const agentCredentials = agent2.credentials;
|
|
2223
|
+
if (agentCredentials && Array.isArray(agentCredentials)) {
|
|
2224
|
+
for (const credential2 of agentCredentials) {
|
|
2225
|
+
if (credential2?.__type === "credential-ref") {
|
|
2226
|
+
continue;
|
|
2227
|
+
}
|
|
2228
|
+
if (credential2?.id) {
|
|
2229
|
+
if (!credentialReferencesObject[credential2.id]) {
|
|
2230
|
+
credentialReferencesObject[credential2.id] = {
|
|
2231
|
+
id: credential2.id,
|
|
2232
|
+
name: credential2.name,
|
|
2233
|
+
type: credential2.type,
|
|
2234
|
+
credentialStoreId: credential2.credentialStoreId,
|
|
2235
|
+
retrievalParams: credential2.retrievalParams
|
|
2236
|
+
};
|
|
2237
|
+
credentialUsageMap[credential2.id] = [];
|
|
2238
|
+
}
|
|
2239
|
+
credentialUsageMap[credential2.id].push({
|
|
2240
|
+
type: "agent",
|
|
2241
|
+
id: agent2.getId()
|
|
2242
|
+
});
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
const agentContextConfig = agent2.contextConfig;
|
|
2247
|
+
if (agentContextConfig) {
|
|
2248
|
+
const contextVariables = agentContextConfig.getContextVariables?.() || agentContextConfig.contextVariables;
|
|
2249
|
+
if (contextVariables) {
|
|
2250
|
+
for (const [key, variable] of Object.entries(contextVariables)) {
|
|
2251
|
+
if (variable?.credential) {
|
|
2252
|
+
const credential2 = variable.credential;
|
|
2253
|
+
let credId;
|
|
2254
|
+
if (credential2.__type === "credential-ref") {
|
|
2255
|
+
credId = credential2.id;
|
|
2256
|
+
if (credId && this.credentialReferences) {
|
|
2257
|
+
const resolvedCred = this.credentialReferences.find((c) => c.id === credId);
|
|
2258
|
+
if (resolvedCred && !credentialReferencesObject[credId]) {
|
|
2259
|
+
credentialReferencesObject[credId] = resolvedCred;
|
|
2260
|
+
credentialUsageMap[credId] = [];
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
} else if (credential2.id) {
|
|
2264
|
+
credId = credential2.id;
|
|
2265
|
+
if (credId && !credentialReferencesObject[credId]) {
|
|
2266
|
+
credentialReferencesObject[credId] = credential2;
|
|
2267
|
+
credentialUsageMap[credId] = [];
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
if (credId) {
|
|
2271
|
+
if (!credentialUsageMap[credId]) {
|
|
2272
|
+
credentialUsageMap[credId] = [];
|
|
2273
|
+
}
|
|
2274
|
+
credentialUsageMap[credId].push({
|
|
2275
|
+
type: "contextVariable",
|
|
2276
|
+
id: key,
|
|
2277
|
+
agentId: agent2.getId()
|
|
2278
|
+
});
|
|
2279
|
+
}
|
|
2280
|
+
} else if (variable?.credentialReferenceId) {
|
|
2281
|
+
const credId = variable.credentialReferenceId;
|
|
2282
|
+
if (!credentialUsageMap[credId]) {
|
|
2283
|
+
credentialUsageMap[credId] = [];
|
|
2284
|
+
}
|
|
2285
|
+
credentialUsageMap[credId].push({
|
|
2286
|
+
type: "contextVariable",
|
|
2287
|
+
id: key,
|
|
2288
|
+
agentId: agent2.getId()
|
|
2289
|
+
});
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
for (const subAgent2 of agent2.getSubAgents()) {
|
|
2295
|
+
const agentTools = subAgent2.getTools();
|
|
2296
|
+
for (const [, toolInstance] of Object.entries(agentTools)) {
|
|
2297
|
+
const actualTool = toolInstance;
|
|
2298
|
+
const toolId = actualTool.getId();
|
|
2299
|
+
if (actualTool.constructor.name === "FunctionTool" && actualTool instanceof FunctionTool) {
|
|
2300
|
+
if (!functionsObject[toolId]) {
|
|
2301
|
+
const functionData = actualTool.serializeFunction();
|
|
2302
|
+
functionsObject[toolId] = functionData;
|
|
2303
|
+
}
|
|
2304
|
+
if (!functionToolsObject[toolId]) {
|
|
2305
|
+
const toolData = actualTool.serializeTool();
|
|
2306
|
+
functionToolsObject[toolId] = {
|
|
2307
|
+
id: toolData.id,
|
|
2308
|
+
name: toolData.name,
|
|
2309
|
+
description: toolData.description,
|
|
2310
|
+
functionId: toolData.functionId
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
} else {
|
|
2314
|
+
if (!toolsObject[toolId]) {
|
|
2315
|
+
if ("config" in actualTool && "serverUrl" in actualTool.config) {
|
|
2316
|
+
const mcpTool2 = actualTool;
|
|
2317
|
+
const toolConfig = {
|
|
2318
|
+
type: "mcp",
|
|
2319
|
+
mcp: {
|
|
2320
|
+
server: {
|
|
2321
|
+
url: mcpTool2.config.serverUrl
|
|
2322
|
+
},
|
|
2323
|
+
transport: mcpTool2.config.transport,
|
|
2324
|
+
activeTools: mcpTool2.config.activeTools
|
|
2325
|
+
}
|
|
2326
|
+
};
|
|
2327
|
+
const toolData = {
|
|
2328
|
+
id: toolId,
|
|
2329
|
+
name: actualTool.getName(),
|
|
2330
|
+
config: toolConfig
|
|
2331
|
+
};
|
|
2332
|
+
if (mcpTool2.config?.imageUrl) {
|
|
2333
|
+
toolData.imageUrl = mcpTool2.config.imageUrl;
|
|
2334
|
+
}
|
|
2335
|
+
if (mcpTool2.config?.headers) {
|
|
2336
|
+
toolData.headers = mcpTool2.config.headers;
|
|
2337
|
+
}
|
|
2338
|
+
if ("getCredentialReferenceId" in actualTool) {
|
|
2339
|
+
const credentialId = actualTool.getCredentialReferenceId();
|
|
2340
|
+
if (credentialId) {
|
|
2341
|
+
toolData.credentialReferenceId = credentialId;
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
if ("credential" in mcpTool2.config && mcpTool2.config.credential) {
|
|
2345
|
+
const credential2 = mcpTool2.config.credential;
|
|
2346
|
+
if (credential2?.id && credential2.__type !== "credential-ref") {
|
|
2347
|
+
if (!credentialReferencesObject[credential2.id]) {
|
|
2348
|
+
credentialReferencesObject[credential2.id] = {
|
|
2349
|
+
id: credential2.id,
|
|
2350
|
+
name: credential2.name,
|
|
2351
|
+
type: credential2.type,
|
|
2352
|
+
credentialStoreId: credential2.credentialStoreId,
|
|
2353
|
+
retrievalParams: credential2.retrievalParams
|
|
2354
|
+
};
|
|
2355
|
+
credentialUsageMap[credential2.id] = [];
|
|
2356
|
+
}
|
|
2357
|
+
credentialUsageMap[credential2.id].push({
|
|
2358
|
+
type: "tool",
|
|
2359
|
+
id: toolId
|
|
2360
|
+
});
|
|
2361
|
+
}
|
|
2362
|
+
}
|
|
2363
|
+
toolsObject[toolId] = toolData;
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
}
|
|
2368
|
+
const subAgentDataComponents = subAgent2.getDataComponents?.();
|
|
2369
|
+
if (subAgentDataComponents) {
|
|
2370
|
+
for (const dataComponent2 of subAgentDataComponents) {
|
|
2371
|
+
let dataComponentId;
|
|
2372
|
+
let dataComponentName;
|
|
2373
|
+
let dataComponentDescription;
|
|
2374
|
+
let dataComponentProps;
|
|
2375
|
+
let dataComponentRender;
|
|
2376
|
+
if (dataComponent2.getId) {
|
|
2377
|
+
dataComponentId = dataComponent2.getId();
|
|
2378
|
+
dataComponentName = dataComponent2.getName();
|
|
2379
|
+
dataComponentDescription = dataComponent2.getDescription() || "";
|
|
2380
|
+
dataComponentProps = dataComponent2.getProps() || {};
|
|
2381
|
+
dataComponentRender = dataComponent2.getRender?.() || null;
|
|
2382
|
+
} else {
|
|
2383
|
+
dataComponentId = dataComponent2.id || (dataComponent2.name ? dataComponent2.name.toLowerCase().replace(/\s+/g, "-") : "");
|
|
2384
|
+
dataComponentName = dataComponent2.name || "";
|
|
2385
|
+
dataComponentDescription = dataComponent2.description || "";
|
|
2386
|
+
dataComponentProps = dataComponent2.props || {};
|
|
2387
|
+
dataComponentRender = dataComponent2.render || null;
|
|
2388
|
+
}
|
|
2389
|
+
if (!dataComponentsObject[dataComponentId] && dataComponentName) {
|
|
2390
|
+
dataComponentsObject[dataComponentId] = {
|
|
2391
|
+
id: dataComponentId,
|
|
2392
|
+
name: dataComponentName,
|
|
2393
|
+
description: dataComponentDescription,
|
|
2394
|
+
props: dataComponentProps,
|
|
2395
|
+
render: dataComponentRender
|
|
2396
|
+
};
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
const subAgentArtifactComponents = subAgent2.getArtifactComponents();
|
|
2401
|
+
if (subAgentArtifactComponents) {
|
|
2402
|
+
for (const artifactComponent2 of subAgentArtifactComponents) {
|
|
2403
|
+
let artifactComponentId;
|
|
2404
|
+
let artifactComponentName;
|
|
2405
|
+
let artifactComponentDescription;
|
|
2406
|
+
let artifactComponentProps;
|
|
2407
|
+
if ("getId" in artifactComponent2 && typeof artifactComponent2.getId === "function") {
|
|
2408
|
+
const component = artifactComponent2;
|
|
2409
|
+
artifactComponentId = component.getId();
|
|
2410
|
+
artifactComponentName = component.getName();
|
|
2411
|
+
artifactComponentDescription = component.getDescription() || "";
|
|
2412
|
+
artifactComponentProps = component.getProps() || {};
|
|
2413
|
+
} else {
|
|
2414
|
+
artifactComponentId = artifactComponent2.id || (artifactComponent2.name ? artifactComponent2.name.toLowerCase().replace(/\s+/g, "-") : "");
|
|
2415
|
+
artifactComponentName = artifactComponent2.name || "";
|
|
2416
|
+
artifactComponentDescription = artifactComponent2.description || "";
|
|
2417
|
+
artifactComponentProps = artifactComponent2.props || {};
|
|
2418
|
+
}
|
|
2419
|
+
if (!artifactComponentsObject[artifactComponentId] && artifactComponentName) {
|
|
2420
|
+
artifactComponentsObject[artifactComponentId] = {
|
|
2421
|
+
id: artifactComponentId,
|
|
2422
|
+
name: artifactComponentName,
|
|
2423
|
+
description: artifactComponentDescription,
|
|
2424
|
+
props: artifactComponentProps
|
|
2425
|
+
};
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
}
|
|
2429
|
+
const subAgentExternalAgents = subAgent2.getExternalAgentDelegates();
|
|
2430
|
+
if (subAgentExternalAgents) {
|
|
2431
|
+
for (const externalAgentDelegate of subAgentExternalAgents) {
|
|
2432
|
+
const externalAgent2 = externalAgentDelegate.externalAgent;
|
|
2433
|
+
const credential2 = externalAgent2.getCredentialReference();
|
|
2434
|
+
if (credential2) {
|
|
2435
|
+
if (!credentialReferencesObject[credential2.id]) {
|
|
2436
|
+
credentialReferencesObject[credential2.id] = {
|
|
2437
|
+
id: credential2.id,
|
|
2438
|
+
name: credential2.name,
|
|
2439
|
+
type: credential2.type,
|
|
2440
|
+
credentialStoreId: credential2.credentialStoreId,
|
|
2441
|
+
retrievalParams: credential2.retrievalParams
|
|
2442
|
+
};
|
|
2443
|
+
credentialUsageMap[credential2.id] = [];
|
|
2444
|
+
}
|
|
2445
|
+
logger8.info({ credentialId: credential2.id }, "Credential id in external agent");
|
|
2446
|
+
credentialUsageMap[credential2.id].push({
|
|
2447
|
+
type: "externalAgent",
|
|
2448
|
+
id: externalAgent2.getId()
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2451
|
+
logger8.info({ externalAgentId: externalAgent2.getId() }, "External agent id");
|
|
2452
|
+
externalAgentsObject[externalAgent2.getId()] = {
|
|
2453
|
+
id: externalAgent2.getId(),
|
|
2454
|
+
name: externalAgent2.getName(),
|
|
2455
|
+
description: externalAgent2.getDescription(),
|
|
2456
|
+
baseUrl: externalAgent2.getBaseUrl(),
|
|
2457
|
+
credentialReferenceId: externalAgent2.getCredentialReferenceId()
|
|
2458
|
+
};
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
logger8.info({ externalAgentsObject }, "External agents object");
|
|
2464
|
+
for (const tool of this.projectTools) {
|
|
2465
|
+
const toolId = tool.getId();
|
|
2466
|
+
if (!toolsObject[toolId]) {
|
|
2467
|
+
const toolConfig = {
|
|
2468
|
+
type: "mcp",
|
|
2469
|
+
mcp: {
|
|
2470
|
+
server: {
|
|
2471
|
+
url: tool.config.serverUrl
|
|
2472
|
+
},
|
|
2473
|
+
transport: tool.config.transport,
|
|
2474
|
+
activeTools: tool.config.activeTools
|
|
2475
|
+
}
|
|
2476
|
+
};
|
|
2477
|
+
const toolData = {
|
|
2478
|
+
id: toolId,
|
|
2479
|
+
name: tool.getName(),
|
|
2480
|
+
config: toolConfig
|
|
2481
|
+
};
|
|
2482
|
+
if (tool.config?.imageUrl) {
|
|
2483
|
+
toolData.imageUrl = tool.config.imageUrl;
|
|
2484
|
+
}
|
|
2485
|
+
if (tool.config?.headers) {
|
|
2486
|
+
toolData.headers = tool.config.headers;
|
|
2487
|
+
}
|
|
2488
|
+
const credentialId = tool.getCredentialReferenceId();
|
|
2489
|
+
if (credentialId) {
|
|
2490
|
+
toolData.credentialReferenceId = credentialId;
|
|
2491
|
+
}
|
|
2492
|
+
toolsObject[toolId] = toolData;
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
for (const dataComponent2 of this.projectDataComponents) {
|
|
2496
|
+
const dataComponentId = dataComponent2.getId();
|
|
2497
|
+
const dataComponentName = dataComponent2.getName();
|
|
2498
|
+
const dataComponentDescription = dataComponent2.getDescription() || "";
|
|
2499
|
+
const dataComponentProps = dataComponent2.getProps() || {};
|
|
2500
|
+
if (!dataComponentsObject[dataComponentId] && dataComponentName) {
|
|
2501
|
+
dataComponentsObject[dataComponentId] = {
|
|
2502
|
+
id: dataComponentId,
|
|
2503
|
+
name: dataComponentName,
|
|
2504
|
+
description: dataComponentDescription,
|
|
2505
|
+
props: dataComponentProps
|
|
2506
|
+
};
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
for (const artifactComponent2 of this.projectArtifactComponents) {
|
|
2510
|
+
const artifactComponentId = artifactComponent2.getId();
|
|
2511
|
+
const artifactComponentName = artifactComponent2.getName();
|
|
2512
|
+
const artifactComponentDescription = artifactComponent2.getDescription() || "";
|
|
2513
|
+
const artifactComponentProps = artifactComponent2.getProps() || {};
|
|
2514
|
+
if (!artifactComponentsObject[artifactComponentId] && artifactComponentName) {
|
|
2515
|
+
artifactComponentsObject[artifactComponentId] = {
|
|
2516
|
+
id: artifactComponentId,
|
|
2517
|
+
name: artifactComponentName,
|
|
2518
|
+
description: artifactComponentDescription,
|
|
2519
|
+
props: artifactComponentProps
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
if (this.credentialReferences && this.credentialReferences.length > 0) {
|
|
2524
|
+
for (const credential2 of this.credentialReferences) {
|
|
2525
|
+
if (credential2.id) {
|
|
2526
|
+
if (!credentialReferencesObject[credential2.id]) {
|
|
2527
|
+
credentialReferencesObject[credential2.id] = credential2;
|
|
2528
|
+
credentialUsageMap[credential2.id] = [];
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
for (const [credId, usages] of Object.entries(credentialUsageMap)) {
|
|
2534
|
+
if (credentialReferencesObject[credId]) {
|
|
2535
|
+
credentialReferencesObject[credId].usedBy = usages;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
return {
|
|
2539
|
+
id: this.projectId,
|
|
2540
|
+
name: this.projectName,
|
|
2541
|
+
description: this.projectDescription || "",
|
|
2542
|
+
models: this.models,
|
|
2543
|
+
stopWhen: this.stopWhen,
|
|
2544
|
+
agents: agentsObject,
|
|
2545
|
+
tools: toolsObject,
|
|
2546
|
+
functionTools: Object.keys(functionToolsObject).length > 0 ? functionToolsObject : void 0,
|
|
2547
|
+
functions: Object.keys(functionsObject).length > 0 ? functionsObject : void 0,
|
|
2548
|
+
dataComponents: Object.keys(dataComponentsObject).length > 0 ? dataComponentsObject : void 0,
|
|
2549
|
+
artifactComponents: Object.keys(artifactComponentsObject).length > 0 ? artifactComponentsObject : void 0,
|
|
2550
|
+
externalAgents: Object.keys(externalAgentsObject).length > 0 ? externalAgentsObject : void 0,
|
|
2551
|
+
credentialReferences: Object.keys(credentialReferencesObject).length > 0 ? credentialReferencesObject : void 0,
|
|
2552
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2553
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2554
|
+
};
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
var logger9 = getLogger("statusComponent");
|
|
2558
|
+
var StatusComponent = class {
|
|
2559
|
+
constructor(config) {
|
|
2560
|
+
__publicField(this, "config");
|
|
2561
|
+
let processedDetailsSchema;
|
|
2562
|
+
if (config.detailsSchema && isZodSchema(config.detailsSchema)) {
|
|
2563
|
+
const jsonSchema = convertZodToJsonSchema(config.detailsSchema);
|
|
2564
|
+
processedDetailsSchema = {
|
|
2565
|
+
type: "object",
|
|
2566
|
+
properties: jsonSchema.properties || {},
|
|
2567
|
+
required: jsonSchema.required || void 0
|
|
2568
|
+
};
|
|
2569
|
+
} else {
|
|
2570
|
+
processedDetailsSchema = config.detailsSchema;
|
|
2571
|
+
}
|
|
2572
|
+
this.config = {
|
|
2573
|
+
...config,
|
|
2574
|
+
detailsSchema: processedDetailsSchema
|
|
2575
|
+
};
|
|
2576
|
+
logger9.info(
|
|
2577
|
+
{
|
|
2578
|
+
statusComponentType: config.type
|
|
2579
|
+
},
|
|
2580
|
+
"StatusComponent constructor initialized"
|
|
2581
|
+
);
|
|
2582
|
+
}
|
|
2583
|
+
getType() {
|
|
2584
|
+
return this.config.type;
|
|
2585
|
+
}
|
|
2586
|
+
getDescription() {
|
|
2587
|
+
return this.config.description;
|
|
2588
|
+
}
|
|
2589
|
+
getDetailsSchema() {
|
|
2590
|
+
return this.config.detailsSchema;
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
var logger10 = getLogger("tool");
|
|
2594
|
+
var Tool = class {
|
|
2595
|
+
constructor(config) {
|
|
2596
|
+
__publicField(this, "config");
|
|
2597
|
+
__publicField(this, "baseURL");
|
|
2598
|
+
__publicField(this, "tenantId");
|
|
2599
|
+
__publicField(this, "initialized", false);
|
|
2600
|
+
__publicField(this, "projectId");
|
|
2601
|
+
this.config = config;
|
|
2602
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
2603
|
+
this.tenantId = "default";
|
|
2604
|
+
this.projectId = "default";
|
|
2605
|
+
logger10.info(
|
|
2606
|
+
{
|
|
2607
|
+
Id: this.getId(),
|
|
2608
|
+
Name: config.name
|
|
2609
|
+
},
|
|
2610
|
+
"Tool constructor initialized"
|
|
2611
|
+
);
|
|
2612
|
+
}
|
|
2613
|
+
// Set context (tenantId, projectId, and baseURL) from external source (agent, agent, CLI, etc)
|
|
2614
|
+
setContext(tenantId, projectId, baseURL) {
|
|
2615
|
+
this.tenantId = tenantId;
|
|
2616
|
+
this.projectId = projectId;
|
|
2617
|
+
if (baseURL) {
|
|
2618
|
+
this.baseURL = baseURL;
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
// Compute ID from name using same slug transformation as agents
|
|
2622
|
+
getId() {
|
|
2623
|
+
return this.config.id;
|
|
2624
|
+
}
|
|
2625
|
+
getName() {
|
|
2626
|
+
return this.config.name;
|
|
2627
|
+
}
|
|
2628
|
+
getDescription() {
|
|
2629
|
+
return this.config.description || "";
|
|
2630
|
+
}
|
|
2631
|
+
getServerUrl() {
|
|
2632
|
+
return this.config.serverUrl;
|
|
2633
|
+
}
|
|
2634
|
+
getActiveTools() {
|
|
2635
|
+
return this.config.activeTools;
|
|
2636
|
+
}
|
|
2637
|
+
getCredentialReferenceId() {
|
|
2638
|
+
return this.config.credential?.id;
|
|
2639
|
+
}
|
|
2640
|
+
// Public method to ensure tool exists in backend (with upsert behavior)
|
|
2641
|
+
async init(options) {
|
|
2642
|
+
if (this.initialized) return;
|
|
2643
|
+
try {
|
|
2644
|
+
if (!options?.skipDatabaseRegistration) {
|
|
2645
|
+
await this.upsertTool();
|
|
2646
|
+
}
|
|
2647
|
+
logger10.info(
|
|
2648
|
+
{
|
|
2649
|
+
toolId: this.getId()
|
|
2650
|
+
},
|
|
2651
|
+
"Tool initialized successfully"
|
|
2652
|
+
);
|
|
2653
|
+
this.initialized = true;
|
|
2654
|
+
} catch (error) {
|
|
2655
|
+
logger10.error(
|
|
2656
|
+
{
|
|
2657
|
+
toolId: this.getId(),
|
|
2658
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
2659
|
+
},
|
|
2660
|
+
"Failed to initialize tool"
|
|
2661
|
+
);
|
|
2662
|
+
throw error;
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
// Private method to upsert tool (create or update)
|
|
2666
|
+
async upsertTool() {
|
|
2667
|
+
const toolDataForUpdate = {
|
|
2668
|
+
id: this.getId(),
|
|
2669
|
+
name: this.config.name,
|
|
2670
|
+
credentialReferenceId: this.config.credential?.id ?? null,
|
|
2671
|
+
headers: this.config.headers ?? null,
|
|
2672
|
+
imageUrl: this.config.imageUrl,
|
|
2673
|
+
config: {
|
|
2674
|
+
type: "mcp",
|
|
2675
|
+
mcp: {
|
|
2676
|
+
server: {
|
|
2677
|
+
url: this.config.serverUrl
|
|
2678
|
+
},
|
|
2679
|
+
transport: this.config.transport,
|
|
2680
|
+
activeTools: this.config.activeTools
|
|
2681
|
+
}
|
|
2682
|
+
}
|
|
2683
|
+
};
|
|
2684
|
+
const toolDataForCreate = {
|
|
2685
|
+
...toolDataForUpdate
|
|
2686
|
+
};
|
|
2687
|
+
logger10.info({ toolDataForCreate }, "toolDataForCreate");
|
|
2688
|
+
const updateResponse = await fetch(
|
|
2689
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/tools/${this.getId()}`,
|
|
2690
|
+
{
|
|
2691
|
+
method: "PUT",
|
|
2692
|
+
headers: {
|
|
2693
|
+
"Content-Type": "application/json"
|
|
2694
|
+
},
|
|
2695
|
+
body: JSON.stringify(toolDataForUpdate)
|
|
2696
|
+
}
|
|
2697
|
+
);
|
|
2698
|
+
logger10.info({ updateResponse }, "tool updateResponse");
|
|
2699
|
+
if (updateResponse.ok) {
|
|
2700
|
+
logger10.info(
|
|
2701
|
+
{
|
|
2702
|
+
toolId: this.getId()
|
|
2703
|
+
},
|
|
2704
|
+
"Tool updated successfully"
|
|
2705
|
+
);
|
|
2706
|
+
return;
|
|
2707
|
+
}
|
|
2708
|
+
if (updateResponse.status === 404) {
|
|
2709
|
+
logger10.info(
|
|
2710
|
+
{
|
|
2711
|
+
toolId: this.getId()
|
|
2712
|
+
},
|
|
2713
|
+
"Tool not found, creating new tool"
|
|
2714
|
+
);
|
|
2715
|
+
const createResponse = await fetch(
|
|
2716
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/tools`,
|
|
2717
|
+
{
|
|
2718
|
+
method: "POST",
|
|
2719
|
+
headers: {
|
|
2720
|
+
"Content-Type": "application/json"
|
|
2721
|
+
},
|
|
2722
|
+
body: JSON.stringify(toolDataForCreate)
|
|
2723
|
+
}
|
|
2724
|
+
);
|
|
2725
|
+
if (!createResponse.ok) {
|
|
2726
|
+
throw new Error(`Failed to create tool: ${createResponse.status}`);
|
|
2727
|
+
}
|
|
2728
|
+
logger10.info(
|
|
2729
|
+
{
|
|
2730
|
+
toolId: this.getId()
|
|
2731
|
+
},
|
|
2732
|
+
"Tool created successfully"
|
|
2733
|
+
);
|
|
2734
|
+
return;
|
|
2735
|
+
}
|
|
2736
|
+
throw new Error(`Failed to update tool: ${updateResponse.status}`);
|
|
2737
|
+
}
|
|
2738
|
+
/**
|
|
2739
|
+
* Creates a new AgentMcpConfig with the given configuration.
|
|
2740
|
+
*
|
|
2741
|
+
* @param config - The configuration for the AgentMcpConfig
|
|
2742
|
+
* @returns A new AgentMcpConfig
|
|
2743
|
+
*
|
|
2744
|
+
* example:
|
|
2745
|
+
* ```typescript
|
|
2746
|
+
* const tool = new Tool({
|
|
2747
|
+
* id: 'tool-id',
|
|
2748
|
+
* name: 'Tool Name',
|
|
2749
|
+
* serverUrl: 'https://example.com/mcp',
|
|
2750
|
+
* });
|
|
2751
|
+
* const agentMcpConfig = tool.with({ selectedTools: ['tool-1', 'tool-2'], headers: { 'Authorization': 'Bearer token' } });
|
|
2752
|
+
* ```
|
|
2753
|
+
*/
|
|
2754
|
+
with(config) {
|
|
2755
|
+
const { selectedTools, toolPolicies } = normalizeToolSelections(config.selectedTools);
|
|
2756
|
+
return {
|
|
2757
|
+
server: this,
|
|
2758
|
+
selectedTools,
|
|
2759
|
+
headers: config.headers,
|
|
2760
|
+
toolPolicies
|
|
2761
|
+
};
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
|
|
2765
|
+
// src/utils/tool-normalization.ts
|
|
2766
|
+
function isAgentMcpConfig(value) {
|
|
2767
|
+
return value !== null && typeof value === "object" && "server" in value && value.server && typeof value.server === "object";
|
|
2768
|
+
}
|
|
2769
|
+
function isTool(value) {
|
|
2770
|
+
return value !== null && typeof value === "object" && "config" in value && (typeof value.getId === "function" || "id" in value);
|
|
2771
|
+
}
|
|
2772
|
+
function normalizeAgentCanUseType(value, fallbackName) {
|
|
2773
|
+
if (isAgentMcpConfig(value)) {
|
|
2774
|
+
return {
|
|
2775
|
+
tool: value.server,
|
|
2776
|
+
toolId: value.server.getId(),
|
|
2777
|
+
selectedTools: value.selectedTools,
|
|
2778
|
+
headers: value.headers,
|
|
2779
|
+
toolPolicies: value.toolPolicies,
|
|
2780
|
+
isWrapped: true
|
|
2781
|
+
};
|
|
2782
|
+
}
|
|
2783
|
+
if (isTool(value)) {
|
|
2784
|
+
const toolId = value.getId?.() || value.id || fallbackName || "unknown";
|
|
2785
|
+
return {
|
|
2786
|
+
tool: value,
|
|
2787
|
+
toolId,
|
|
2788
|
+
isWrapped: false
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
throw new Error(`Invalid AgentCanUseType: expected Tool or AgentMcpConfig, got ${typeof value}`);
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2794
|
+
// src/subAgent.ts
|
|
2795
|
+
var logger11 = getLogger("agent");
|
|
2796
|
+
function resolveGetter2(value) {
|
|
2797
|
+
if (typeof value === "function") {
|
|
2798
|
+
return value();
|
|
2799
|
+
}
|
|
2800
|
+
return value;
|
|
2801
|
+
}
|
|
2802
|
+
var SubAgent = class {
|
|
2803
|
+
constructor(config) {
|
|
2804
|
+
__publicField(this, "config");
|
|
2805
|
+
__publicField(this, "type", "internal");
|
|
2806
|
+
__publicField(this, "baseURL");
|
|
2807
|
+
__publicField(this, "tenantId");
|
|
2808
|
+
__publicField(this, "projectId");
|
|
2809
|
+
__publicField(this, "initialized", false);
|
|
2810
|
+
this.config = { ...config, type: "internal" };
|
|
2811
|
+
this.baseURL = process.env.INKEEP_API_URL || "http://localhost:3002";
|
|
2812
|
+
this.tenantId = "default";
|
|
2813
|
+
this.projectId = "default";
|
|
2814
|
+
logger11.info(
|
|
2815
|
+
{
|
|
2816
|
+
tenantId: this.tenantId,
|
|
2817
|
+
subAgentId: this.config.id,
|
|
2818
|
+
agentName: config.name
|
|
2819
|
+
},
|
|
2820
|
+
"Agent constructor initialized"
|
|
2821
|
+
);
|
|
2822
|
+
}
|
|
2823
|
+
// Set context (tenantId, projectId, and baseURL) from external source (agent, CLI, etc)
|
|
2824
|
+
setContext(tenantId, projectId, baseURL) {
|
|
2825
|
+
this.tenantId = tenantId;
|
|
2826
|
+
this.projectId = projectId;
|
|
2827
|
+
if (baseURL) {
|
|
2828
|
+
this.baseURL = baseURL;
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
// Return the configured ID
|
|
2832
|
+
getId() {
|
|
2833
|
+
return this.config.id;
|
|
2834
|
+
}
|
|
2835
|
+
// Agent introspection methods
|
|
2836
|
+
getName() {
|
|
2837
|
+
return this.config.name;
|
|
2838
|
+
}
|
|
2839
|
+
getInstructions() {
|
|
2840
|
+
return this.config.prompt;
|
|
2841
|
+
}
|
|
2842
|
+
/**
|
|
2843
|
+
* Get the agent's description (the human-readable description field)
|
|
2844
|
+
*/
|
|
2845
|
+
getDescription() {
|
|
2846
|
+
return this.config.description || "";
|
|
2847
|
+
}
|
|
2848
|
+
getTools() {
|
|
2849
|
+
const tools = resolveGetter2(this.config.canUse);
|
|
2850
|
+
if (!tools) {
|
|
2851
|
+
return {};
|
|
2852
|
+
}
|
|
2853
|
+
if (!Array.isArray(tools)) {
|
|
2854
|
+
throw new Error("tools getter must return an array");
|
|
2855
|
+
}
|
|
2856
|
+
const toolRecord = {};
|
|
2857
|
+
for (const tool of tools) {
|
|
2858
|
+
if (tool && typeof tool === "object") {
|
|
2859
|
+
let id;
|
|
2860
|
+
let toolInstance;
|
|
2861
|
+
if (isAgentMcpConfig(tool)) {
|
|
2862
|
+
id = tool.server.getId();
|
|
2863
|
+
toolInstance = tool.server;
|
|
2864
|
+
toolInstance.selectedTools = tool.selectedTools;
|
|
2865
|
+
toolInstance.headers = tool.headers;
|
|
2866
|
+
toolInstance.toolPolicies = tool.toolPolicies;
|
|
2867
|
+
} else {
|
|
2868
|
+
toolInstance = tool;
|
|
2869
|
+
id = toolInstance.getId();
|
|
2870
|
+
}
|
|
2871
|
+
if (id) {
|
|
2872
|
+
toolRecord[id] = toolInstance;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
return toolRecord;
|
|
2877
|
+
}
|
|
2878
|
+
getModels() {
|
|
2879
|
+
return this.config.models;
|
|
2880
|
+
}
|
|
2881
|
+
setModels(models) {
|
|
2882
|
+
this.config.models = models;
|
|
2883
|
+
}
|
|
2884
|
+
getTransfers() {
|
|
2885
|
+
return typeof this.config.canTransferTo === "function" ? this.config.canTransferTo() : [];
|
|
2886
|
+
}
|
|
2887
|
+
getSubAgentDelegates() {
|
|
2888
|
+
return typeof this.config.canDelegateTo === "function" ? this.config.canDelegateTo().filter((delegate) => {
|
|
2889
|
+
if (typeof delegate === "object" && "externalAgent" in delegate) {
|
|
2890
|
+
return false;
|
|
2891
|
+
}
|
|
2892
|
+
if (typeof delegate === "object" && "agent" in delegate) {
|
|
2893
|
+
return false;
|
|
2894
|
+
}
|
|
2895
|
+
if (typeof delegate === "object" && "toFullAgentDefinition" in delegate) {
|
|
2896
|
+
return false;
|
|
2897
|
+
}
|
|
2898
|
+
if (typeof delegate === "object" && "type" in delegate && delegate.type === "external") {
|
|
2899
|
+
return false;
|
|
2900
|
+
}
|
|
2901
|
+
return true;
|
|
2902
|
+
}) : [];
|
|
2903
|
+
}
|
|
2904
|
+
getExternalAgentDelegates() {
|
|
2905
|
+
if (typeof this.config.canDelegateTo !== "function") {
|
|
2906
|
+
return [];
|
|
2907
|
+
}
|
|
2908
|
+
return this.config.canDelegateTo().filter((delegate) => {
|
|
2909
|
+
if (typeof delegate === "object" && "externalAgent" in delegate) {
|
|
2910
|
+
return true;
|
|
2911
|
+
}
|
|
2912
|
+
if (typeof delegate === "object" && "type" in delegate && delegate.type === "external") {
|
|
2913
|
+
return true;
|
|
2914
|
+
}
|
|
2915
|
+
return false;
|
|
2916
|
+
}).map((delegate) => {
|
|
2917
|
+
if ("externalAgent" in delegate) {
|
|
2918
|
+
return delegate;
|
|
2919
|
+
}
|
|
2920
|
+
return {
|
|
2921
|
+
externalAgent: delegate,
|
|
2922
|
+
headers: void 0
|
|
2923
|
+
};
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
getTeamAgentDelegates() {
|
|
2927
|
+
if (typeof this.config.canDelegateTo !== "function") {
|
|
2928
|
+
return [];
|
|
2929
|
+
}
|
|
2930
|
+
return this.config.canDelegateTo().filter((delegate) => {
|
|
2931
|
+
if (typeof delegate === "object" && "agent" in delegate) {
|
|
2932
|
+
return true;
|
|
2933
|
+
}
|
|
2934
|
+
if (typeof delegate === "object" && "toFullAgentDefinition" in delegate) {
|
|
2935
|
+
return true;
|
|
2936
|
+
}
|
|
2937
|
+
return false;
|
|
2938
|
+
}).map((delegate) => {
|
|
2939
|
+
if ("agent" in delegate) {
|
|
2940
|
+
return delegate;
|
|
2941
|
+
}
|
|
2942
|
+
return {
|
|
2943
|
+
agent: delegate,
|
|
2944
|
+
headers: void 0
|
|
2945
|
+
};
|
|
2946
|
+
});
|
|
2947
|
+
}
|
|
2948
|
+
getDelegates() {
|
|
2949
|
+
return [
|
|
2950
|
+
...this.getSubAgentDelegates(),
|
|
2951
|
+
...this.getTeamAgentDelegates(),
|
|
2952
|
+
...this.getExternalAgentDelegates()
|
|
2953
|
+
];
|
|
2954
|
+
}
|
|
2955
|
+
getDataComponents() {
|
|
2956
|
+
const components = resolveGetter2(this.config.dataComponents) || [];
|
|
2957
|
+
return components.map((comp) => {
|
|
2958
|
+
if (comp && typeof comp.getId === "function") {
|
|
2959
|
+
return {
|
|
2960
|
+
id: comp.getId(),
|
|
2961
|
+
name: comp.getName(),
|
|
2962
|
+
description: comp.getDescription(),
|
|
2963
|
+
props: comp.getProps(),
|
|
2964
|
+
render: comp.getRender?.() || null
|
|
2965
|
+
};
|
|
2966
|
+
}
|
|
2967
|
+
if (comp && typeof comp === "object" && comp.props && isZodSchema(comp.props)) {
|
|
2968
|
+
return {
|
|
2969
|
+
id: comp.id,
|
|
2970
|
+
name: comp.name,
|
|
2971
|
+
description: comp.description,
|
|
2972
|
+
props: convertZodToJsonSchemaWithPreview(comp.props),
|
|
2973
|
+
render: comp.render || null
|
|
2974
|
+
};
|
|
2975
|
+
}
|
|
2976
|
+
return comp;
|
|
2977
|
+
});
|
|
2978
|
+
}
|
|
2979
|
+
getArtifactComponents() {
|
|
2980
|
+
const components = resolveGetter2(this.config.artifactComponents) || [];
|
|
2981
|
+
return components.map((comp) => {
|
|
2982
|
+
if (comp && typeof comp.getId === "function") {
|
|
2983
|
+
return {
|
|
2984
|
+
id: comp.getId(),
|
|
2985
|
+
name: comp.getName(),
|
|
2986
|
+
description: comp.getDescription(),
|
|
2987
|
+
props: comp.getProps?.() || comp.props
|
|
2988
|
+
};
|
|
2989
|
+
}
|
|
2990
|
+
if (comp && typeof comp === "object" && comp.props && isZodSchema(comp.props)) {
|
|
2991
|
+
return {
|
|
2992
|
+
id: comp.id,
|
|
2993
|
+
name: comp.name,
|
|
2994
|
+
description: comp.description,
|
|
2995
|
+
props: convertZodToJsonSchemaWithPreview(comp.props)
|
|
2996
|
+
};
|
|
2997
|
+
}
|
|
2998
|
+
return comp;
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
// adjust
|
|
3002
|
+
addTool(_name, tool) {
|
|
3003
|
+
const existingTools = this.config.canUse ? this.config.canUse() : [];
|
|
3004
|
+
this.config.canUse = () => [...existingTools, tool];
|
|
3005
|
+
}
|
|
3006
|
+
addTransfer(...agents) {
|
|
3007
|
+
if (typeof this.config.canTransferTo === "function") {
|
|
3008
|
+
const existingTransfers = this.config.canTransferTo;
|
|
3009
|
+
this.config.canTransferTo = () => [...existingTransfers(), ...agents];
|
|
3010
|
+
} else {
|
|
3011
|
+
this.config.canTransferTo = () => agents;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
addDelegate(...agents) {
|
|
3015
|
+
if (typeof this.config.canDelegateTo === "function") {
|
|
3016
|
+
const existingDelegates = this.config.canDelegateTo;
|
|
3017
|
+
this.config.canDelegateTo = () => [...existingDelegates(), ...agents];
|
|
3018
|
+
} else {
|
|
3019
|
+
this.config.canDelegateTo = () => agents;
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
// Public method to ensure agent exists in backend (with upsert behavior)
|
|
3023
|
+
async init() {
|
|
3024
|
+
if (this.initialized) return;
|
|
3025
|
+
try {
|
|
3026
|
+
await this.upsertAgent();
|
|
3027
|
+
await this.loadDataComponents();
|
|
3028
|
+
await this.loadArtifactComponents();
|
|
3029
|
+
await this.saveToolsAndRelations();
|
|
3030
|
+
await this.saveDataComponents();
|
|
3031
|
+
await this.saveArtifactComponents();
|
|
3032
|
+
logger11.info(
|
|
3033
|
+
{
|
|
3034
|
+
subAgentId: this.getId()
|
|
3035
|
+
},
|
|
3036
|
+
"Agent initialized successfully"
|
|
3037
|
+
);
|
|
3038
|
+
this.initialized = true;
|
|
3039
|
+
} catch (error) {
|
|
3040
|
+
logger11.error(
|
|
3041
|
+
{
|
|
3042
|
+
subAgentId: this.getId(),
|
|
3043
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3044
|
+
},
|
|
3045
|
+
"Failed to initialize agent"
|
|
3046
|
+
);
|
|
3047
|
+
throw error;
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
// Private method to upsert agent (create or update)
|
|
3051
|
+
async upsertAgent() {
|
|
3052
|
+
const agentData = {
|
|
3053
|
+
id: this.getId(),
|
|
3054
|
+
name: this.config.name,
|
|
3055
|
+
description: this.config.description || "",
|
|
3056
|
+
prompt: this.config.prompt,
|
|
3057
|
+
conversationHistoryConfig: this.config.conversationHistoryConfig,
|
|
3058
|
+
models: this.config.models,
|
|
3059
|
+
stopWhen: this.config.stopWhen
|
|
3060
|
+
};
|
|
3061
|
+
const updateResponse = await fetch(
|
|
3062
|
+
`${this.baseURL}/tenants/${this.tenantId}/agents/${this.getId()}`,
|
|
3063
|
+
{
|
|
3064
|
+
method: "PUT",
|
|
3065
|
+
headers: {
|
|
3066
|
+
"Content-Type": "application/json"
|
|
3067
|
+
},
|
|
3068
|
+
body: JSON.stringify(agentData)
|
|
3069
|
+
}
|
|
3070
|
+
);
|
|
3071
|
+
if (updateResponse.ok) {
|
|
3072
|
+
logger11.info(
|
|
3073
|
+
{
|
|
3074
|
+
subAgentId: this.getId()
|
|
3075
|
+
},
|
|
3076
|
+
"Agent updated successfully"
|
|
3077
|
+
);
|
|
3078
|
+
return;
|
|
3079
|
+
}
|
|
3080
|
+
if (updateResponse.status === 404) {
|
|
3081
|
+
logger11.info(
|
|
3082
|
+
{
|
|
3083
|
+
subAgentId: this.getId()
|
|
3084
|
+
},
|
|
3085
|
+
"Agent not found, creating new agent"
|
|
3086
|
+
);
|
|
3087
|
+
const createResponse = await fetch(`${this.baseURL}/tenants/${this.tenantId}/agents`, {
|
|
3088
|
+
method: "POST",
|
|
3089
|
+
headers: {
|
|
3090
|
+
"Content-Type": "application/json"
|
|
3091
|
+
},
|
|
3092
|
+
body: JSON.stringify(agentData)
|
|
3093
|
+
});
|
|
3094
|
+
if (!createResponse.ok) {
|
|
3095
|
+
const errorText2 = await createResponse.text().catch(() => "Unknown error");
|
|
3096
|
+
throw new Error(
|
|
3097
|
+
`Failed to create agent: ${createResponse.status} ${createResponse.statusText} - ${errorText2}`
|
|
3098
|
+
);
|
|
3099
|
+
}
|
|
3100
|
+
logger11.info(
|
|
3101
|
+
{
|
|
3102
|
+
subAgentId: this.getId()
|
|
3103
|
+
},
|
|
3104
|
+
"Agent created successfully"
|
|
3105
|
+
);
|
|
3106
|
+
return;
|
|
3107
|
+
}
|
|
3108
|
+
const errorText = await updateResponse.text().catch(() => "Unknown error");
|
|
3109
|
+
throw new Error(
|
|
3110
|
+
`Failed to update agent: ${updateResponse.status} ${updateResponse.statusText} - ${errorText}`
|
|
3111
|
+
);
|
|
3112
|
+
}
|
|
3113
|
+
async saveToolsAndRelations() {
|
|
3114
|
+
if (this.config.canUse) {
|
|
3115
|
+
const tools = resolveGetter2(this.config.canUse);
|
|
3116
|
+
if (tools && Array.isArray(tools)) {
|
|
3117
|
+
for (let i = 0; i < tools.length; i++) {
|
|
3118
|
+
const toolConfig = tools[i];
|
|
3119
|
+
try {
|
|
3120
|
+
const normalizedTool = normalizeAgentCanUseType(toolConfig, `tool-${i}`);
|
|
3121
|
+
await this.createTool(normalizedTool.toolId, toolConfig);
|
|
3122
|
+
} catch (error) {
|
|
3123
|
+
logger11.error(
|
|
3124
|
+
{
|
|
3125
|
+
toolId: isAgentMcpConfig(toolConfig) ? toolConfig.server.getId() : toolConfig.getId?.(),
|
|
3126
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3127
|
+
},
|
|
3128
|
+
"Tool creation failed"
|
|
3129
|
+
);
|
|
3130
|
+
throw error;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
}
|
|
3136
|
+
async saveDataComponents() {
|
|
3137
|
+
logger11.info({ dataComponents: this.config.dataComponents }, "dataComponents and config");
|
|
3138
|
+
const components = resolveGetter2(this.config.dataComponents);
|
|
3139
|
+
if (components) {
|
|
3140
|
+
for (const dataComponent2 of components) {
|
|
3141
|
+
const plainComponent = dataComponent2 && typeof dataComponent2.getId === "function" ? {
|
|
3142
|
+
id: dataComponent2.getId(),
|
|
3143
|
+
name: dataComponent2.getName(),
|
|
3144
|
+
description: dataComponent2.getDescription(),
|
|
3145
|
+
props: dataComponent2.getProps()
|
|
3146
|
+
} : dataComponent2;
|
|
3147
|
+
await this.createDataComponent(plainComponent);
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
}
|
|
3151
|
+
async saveArtifactComponents() {
|
|
3152
|
+
logger11.info(
|
|
3153
|
+
{ artifactComponents: this.config.artifactComponents },
|
|
3154
|
+
"artifactComponents and config"
|
|
3155
|
+
);
|
|
3156
|
+
const components = resolveGetter2(this.config.artifactComponents);
|
|
3157
|
+
if (components) {
|
|
3158
|
+
for (const artifactComponent2 of components) {
|
|
3159
|
+
const plainComponent = artifactComponent2 && typeof artifactComponent2.getId === "function" ? {
|
|
3160
|
+
id: artifactComponent2.getId(),
|
|
3161
|
+
name: artifactComponent2.getName(),
|
|
3162
|
+
description: artifactComponent2.getDescription(),
|
|
3163
|
+
props: artifactComponent2.getProps?.() || artifactComponent2.props
|
|
3164
|
+
} : artifactComponent2;
|
|
3165
|
+
await this.createArtifactComponent(plainComponent);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
async loadDataComponents() {
|
|
3170
|
+
try {
|
|
3171
|
+
const existingComponents = [];
|
|
3172
|
+
const dbDataComponents = existingComponents.map((component) => ({
|
|
3173
|
+
id: component.id,
|
|
3174
|
+
name: component.name,
|
|
3175
|
+
description: component.description,
|
|
3176
|
+
props: component.props,
|
|
3177
|
+
createdAt: component.createdAt,
|
|
3178
|
+
updatedAt: component.updatedAt
|
|
3179
|
+
}));
|
|
3180
|
+
const configComponents = resolveGetter2(this.config.dataComponents) || [];
|
|
3181
|
+
const normalizedConfigComponents = configComponents.map((comp) => {
|
|
3182
|
+
if (comp && typeof comp.getId === "function") {
|
|
3183
|
+
return {
|
|
3184
|
+
id: comp.getId(),
|
|
3185
|
+
name: comp.getName(),
|
|
3186
|
+
description: comp.getDescription(),
|
|
3187
|
+
props: comp.getProps()
|
|
3188
|
+
};
|
|
3189
|
+
}
|
|
3190
|
+
return comp;
|
|
3191
|
+
});
|
|
3192
|
+
const allComponents = [...dbDataComponents, ...normalizedConfigComponents];
|
|
3193
|
+
const uniqueComponents = allComponents.reduce((acc, component) => {
|
|
3194
|
+
const componentId = typeof component.getId === "function" ? component.getId() : component.id;
|
|
3195
|
+
const existingIndex = acc.findIndex((c) => {
|
|
3196
|
+
const cId = typeof c.getId === "function" ? c.getId() : c.id;
|
|
3197
|
+
return cId === componentId;
|
|
3198
|
+
});
|
|
3199
|
+
if (existingIndex >= 0) {
|
|
3200
|
+
acc[existingIndex] = component;
|
|
3201
|
+
} else {
|
|
3202
|
+
acc.push(component);
|
|
3203
|
+
}
|
|
3204
|
+
return acc;
|
|
3205
|
+
}, []);
|
|
3206
|
+
this.config.dataComponents = () => uniqueComponents;
|
|
3207
|
+
logger11.info(
|
|
3208
|
+
{
|
|
3209
|
+
subAgentId: this.getId(),
|
|
3210
|
+
dbComponentCount: dbDataComponents.length,
|
|
3211
|
+
configComponentCount: configComponents.length,
|
|
3212
|
+
totalComponentCount: uniqueComponents.length
|
|
3213
|
+
},
|
|
3214
|
+
"Loaded and merged data components"
|
|
3215
|
+
);
|
|
3216
|
+
} catch (error) {
|
|
3217
|
+
logger11.error(
|
|
3218
|
+
{
|
|
3219
|
+
subAgentId: this.getId(),
|
|
3220
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3221
|
+
},
|
|
3222
|
+
"Failed to load data components from database"
|
|
3223
|
+
);
|
|
3224
|
+
}
|
|
3225
|
+
}
|
|
3226
|
+
async loadArtifactComponents() {
|
|
3227
|
+
try {
|
|
3228
|
+
const existingComponents = [];
|
|
3229
|
+
const dbArtifactComponents = existingComponents.map((component) => ({
|
|
3230
|
+
id: component.id,
|
|
3231
|
+
name: component.name,
|
|
3232
|
+
description: component.description,
|
|
3233
|
+
props: component.props,
|
|
3234
|
+
createdAt: component.createdAt,
|
|
3235
|
+
updatedAt: component.updatedAt
|
|
3236
|
+
}));
|
|
3237
|
+
const configComponents = resolveGetter2(this.config.artifactComponents) || [];
|
|
3238
|
+
const normalizedConfigComponents = configComponents.map((comp) => {
|
|
3239
|
+
if (comp && typeof comp.getId === "function") {
|
|
3240
|
+
return {
|
|
3241
|
+
id: comp.getId(),
|
|
3242
|
+
name: comp.getName(),
|
|
3243
|
+
description: comp.getDescription(),
|
|
3244
|
+
props: comp.getProps?.() || comp.props
|
|
3245
|
+
};
|
|
3246
|
+
}
|
|
3247
|
+
return comp;
|
|
3248
|
+
});
|
|
3249
|
+
const allComponents = [...dbArtifactComponents, ...normalizedConfigComponents];
|
|
3250
|
+
const uniqueComponents = allComponents.reduce((acc, component) => {
|
|
3251
|
+
const componentId = typeof component.getId === "function" ? component.getId() : component.id;
|
|
3252
|
+
const existingIndex = acc.findIndex((c) => {
|
|
3253
|
+
const cId = typeof c.getId === "function" ? c.getId() : c.id;
|
|
3254
|
+
return cId === componentId;
|
|
3255
|
+
});
|
|
3256
|
+
if (existingIndex >= 0) {
|
|
3257
|
+
acc[existingIndex] = component;
|
|
3258
|
+
} else {
|
|
3259
|
+
acc.push(component);
|
|
3260
|
+
}
|
|
3261
|
+
return acc;
|
|
3262
|
+
}, []);
|
|
3263
|
+
this.config.artifactComponents = () => uniqueComponents;
|
|
3264
|
+
logger11.info(
|
|
3265
|
+
{
|
|
3266
|
+
subAgentId: this.getId(),
|
|
3267
|
+
dbComponentCount: dbArtifactComponents.length,
|
|
3268
|
+
configComponentCount: configComponents.length,
|
|
3269
|
+
totalComponentCount: uniqueComponents.length
|
|
3270
|
+
},
|
|
3271
|
+
"Loaded and merged artifact components"
|
|
3272
|
+
);
|
|
3273
|
+
} catch (error) {
|
|
3274
|
+
logger11.error(
|
|
3275
|
+
{
|
|
3276
|
+
subAgentId: this.getId(),
|
|
3277
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3278
|
+
},
|
|
3279
|
+
"Failed to load artifact components from database"
|
|
3280
|
+
);
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
async createFunctionTool(toolId, functionTool2) {
|
|
3284
|
+
try {
|
|
3285
|
+
const functionData = functionTool2.serializeFunction();
|
|
3286
|
+
const toolData = functionTool2.serializeTool();
|
|
3287
|
+
const functionUrl = `${this.baseURL}/tenants/${this.tenantId}/crud/projects/${this.projectId}/functions`;
|
|
3288
|
+
logger11.info(
|
|
3289
|
+
{
|
|
3290
|
+
agentId: this.getId(),
|
|
3291
|
+
toolId,
|
|
3292
|
+
functionUrl
|
|
3293
|
+
},
|
|
3294
|
+
"Attempting to create global function"
|
|
3295
|
+
);
|
|
3296
|
+
const functionResponse = await fetch(functionUrl, {
|
|
3297
|
+
method: "POST",
|
|
3298
|
+
headers: {
|
|
3299
|
+
"Content-Type": "application/json"
|
|
3300
|
+
},
|
|
3301
|
+
body: JSON.stringify({
|
|
3302
|
+
id: functionData.id,
|
|
3303
|
+
inputSchema: functionData.inputSchema,
|
|
3304
|
+
executeCode: functionData.executeCode,
|
|
3305
|
+
dependencies: functionData.dependencies
|
|
3306
|
+
})
|
|
3307
|
+
});
|
|
3308
|
+
logger11.info(
|
|
3309
|
+
{
|
|
3310
|
+
agentId: this.getId(),
|
|
3311
|
+
toolId,
|
|
3312
|
+
functionStatus: functionResponse.status,
|
|
3313
|
+
functionStatusText: functionResponse.statusText
|
|
3314
|
+
},
|
|
3315
|
+
"Function creation response received"
|
|
3316
|
+
);
|
|
3317
|
+
if (!functionResponse.ok) {
|
|
3318
|
+
const errorText = await functionResponse.text();
|
|
3319
|
+
logger11.error(
|
|
3320
|
+
{
|
|
3321
|
+
agentId: this.getId(),
|
|
3322
|
+
toolId,
|
|
3323
|
+
functionStatus: functionResponse.status,
|
|
3324
|
+
functionStatusText: functionResponse.statusText,
|
|
3325
|
+
errorText
|
|
3326
|
+
},
|
|
3327
|
+
"Function creation failed"
|
|
3328
|
+
);
|
|
3329
|
+
throw new Error(`Failed to create function: ${functionResponse.status} ${errorText}`);
|
|
3330
|
+
}
|
|
3331
|
+
const toolUrl = `${this.baseURL}/tenants/${this.tenantId}/crud/projects/${this.projectId}/tools`;
|
|
3332
|
+
logger11.info(
|
|
3333
|
+
{
|
|
3334
|
+
agentId: this.getId(),
|
|
3335
|
+
toolId,
|
|
3336
|
+
toolUrl
|
|
3337
|
+
},
|
|
3338
|
+
"Attempting to create function tool"
|
|
3339
|
+
);
|
|
3340
|
+
const toolResponse = await fetch(toolUrl, {
|
|
3341
|
+
method: "POST",
|
|
3342
|
+
headers: {
|
|
3343
|
+
"Content-Type": "application/json"
|
|
3344
|
+
},
|
|
3345
|
+
body: JSON.stringify({
|
|
3346
|
+
id: toolData.id,
|
|
3347
|
+
name: toolData.name,
|
|
3348
|
+
description: toolData.description,
|
|
3349
|
+
functionId: toolData.functionId,
|
|
3350
|
+
config: {
|
|
3351
|
+
type: "function"
|
|
3352
|
+
// No inline function details - reference via functionId only
|
|
3353
|
+
}
|
|
3354
|
+
})
|
|
3355
|
+
});
|
|
3356
|
+
logger11.info(
|
|
3357
|
+
{
|
|
3358
|
+
agentId: this.getId(),
|
|
3359
|
+
toolId,
|
|
3360
|
+
toolStatus: toolResponse.status,
|
|
3361
|
+
toolStatusText: toolResponse.statusText
|
|
3362
|
+
},
|
|
3363
|
+
"Tool creation response received"
|
|
3364
|
+
);
|
|
3365
|
+
if (!toolResponse.ok) {
|
|
3366
|
+
const errorText = await toolResponse.text();
|
|
3367
|
+
logger11.error(
|
|
3368
|
+
{
|
|
3369
|
+
agentId: this.getId(),
|
|
3370
|
+
toolId,
|
|
3371
|
+
toolStatus: toolResponse.status,
|
|
3372
|
+
toolStatusText: toolResponse.statusText,
|
|
3373
|
+
errorText
|
|
3374
|
+
},
|
|
3375
|
+
"Tool creation failed"
|
|
3376
|
+
);
|
|
3377
|
+
throw new Error(`Failed to create tool: ${toolResponse.status} ${errorText}`);
|
|
3378
|
+
}
|
|
3379
|
+
await this.createAgentToolRelation(toolData.id);
|
|
3380
|
+
logger11.info(
|
|
3381
|
+
{
|
|
3382
|
+
agentId: this.getId(),
|
|
3383
|
+
functionId: functionData.id,
|
|
3384
|
+
toolId: toolData.id
|
|
3385
|
+
},
|
|
3386
|
+
"Function and tool created successfully"
|
|
3387
|
+
);
|
|
3388
|
+
} catch (error) {
|
|
3389
|
+
logger11.error(
|
|
3390
|
+
{
|
|
3391
|
+
agentId: this.getId(),
|
|
3392
|
+
toolId,
|
|
3393
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
3394
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
3395
|
+
},
|
|
3396
|
+
"Failed to create function tool"
|
|
3397
|
+
);
|
|
3398
|
+
throw error;
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
async createTool(toolId, toolConfig) {
|
|
3402
|
+
try {
|
|
3403
|
+
if (toolConfig instanceof FunctionTool) {
|
|
3404
|
+
await this.createFunctionTool(toolId, toolConfig);
|
|
3405
|
+
return;
|
|
3406
|
+
}
|
|
3407
|
+
if (toolConfig.type === "function") {
|
|
3408
|
+
logger11.info(
|
|
3409
|
+
{
|
|
3410
|
+
subAgentId: this.getId(),
|
|
3411
|
+
toolId
|
|
3412
|
+
},
|
|
3413
|
+
"Skipping function tool creation - will be handled at runtime"
|
|
3414
|
+
);
|
|
3415
|
+
return;
|
|
3416
|
+
}
|
|
3417
|
+
let tool;
|
|
3418
|
+
let selectedTools;
|
|
3419
|
+
let headers;
|
|
3420
|
+
let toolPolicies;
|
|
3421
|
+
try {
|
|
3422
|
+
const normalizedTool = normalizeAgentCanUseType(toolConfig, toolId);
|
|
3423
|
+
tool = normalizedTool.tool;
|
|
3424
|
+
selectedTools = normalizedTool.selectedTools;
|
|
3425
|
+
headers = normalizedTool.headers;
|
|
3426
|
+
toolPolicies = normalizedTool.toolPolicies;
|
|
3427
|
+
tool.setContext(this.tenantId, this.projectId);
|
|
3428
|
+
await tool.init();
|
|
3429
|
+
} catch (_) {
|
|
3430
|
+
tool = new Tool({
|
|
3431
|
+
id: toolId,
|
|
3432
|
+
name: toolConfig.name || toolId,
|
|
3433
|
+
description: toolConfig.description || `MCP tool: ${toolId}`,
|
|
3434
|
+
serverUrl: toolConfig.config?.serverUrl || toolConfig.serverUrl || "http://localhost:3000",
|
|
3435
|
+
activeTools: toolConfig.config?.mcp?.activeTools,
|
|
3436
|
+
credential: toolConfig.credential
|
|
3437
|
+
});
|
|
3438
|
+
tool.setContext(this.tenantId, this.projectId);
|
|
3439
|
+
await tool.init();
|
|
3440
|
+
}
|
|
3441
|
+
await this.createAgentToolRelation(tool.getId(), selectedTools, headers, toolPolicies);
|
|
3442
|
+
logger11.info(
|
|
3443
|
+
{
|
|
3444
|
+
subAgentId: this.getId(),
|
|
3445
|
+
toolId: tool.getId()
|
|
3446
|
+
},
|
|
3447
|
+
"Tool created and linked to agent"
|
|
3448
|
+
);
|
|
3449
|
+
} catch (error) {
|
|
3450
|
+
logger11.error(
|
|
3451
|
+
{
|
|
3452
|
+
subAgentId: this.getId(),
|
|
3453
|
+
toolId,
|
|
3454
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3455
|
+
},
|
|
3456
|
+
"Failed to create tool"
|
|
3457
|
+
);
|
|
3458
|
+
throw error;
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
async createDataComponent(dataComponent2) {
|
|
3462
|
+
try {
|
|
3463
|
+
const dc = new DataComponent({
|
|
3464
|
+
id: dataComponent2.id,
|
|
3465
|
+
name: dataComponent2.name,
|
|
3466
|
+
description: dataComponent2.description,
|
|
3467
|
+
props: dataComponent2.props,
|
|
3468
|
+
render: dataComponent2.render
|
|
3469
|
+
});
|
|
3470
|
+
dc.setContext(this.tenantId, this.projectId);
|
|
3471
|
+
await dc.init();
|
|
3472
|
+
await this.createAgentDataComponentRelation(dc.getId());
|
|
3473
|
+
logger11.info(
|
|
3474
|
+
{
|
|
3475
|
+
subAgentId: this.getId(),
|
|
3476
|
+
dataComponentId: dc.getId()
|
|
3477
|
+
},
|
|
3478
|
+
"DataComponent created and linked to agent"
|
|
3479
|
+
);
|
|
3480
|
+
} catch (error) {
|
|
3481
|
+
logger11.error(
|
|
3482
|
+
{
|
|
3483
|
+
subAgentId: this.getId(),
|
|
3484
|
+
dataComponentName: dataComponent2.name,
|
|
3485
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3486
|
+
},
|
|
3487
|
+
"Failed to create data component"
|
|
3488
|
+
);
|
|
3489
|
+
throw error;
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
async createArtifactComponent(artifactComponent2) {
|
|
3493
|
+
try {
|
|
3494
|
+
const ac = new ArtifactComponent({
|
|
3495
|
+
id: artifactComponent2.id,
|
|
3496
|
+
name: artifactComponent2.name,
|
|
3497
|
+
description: artifactComponent2.description,
|
|
3498
|
+
props: artifactComponent2.props
|
|
3499
|
+
});
|
|
3500
|
+
ac.setContext(this.tenantId, this.projectId);
|
|
3501
|
+
await ac.init();
|
|
3502
|
+
await this.createAgentArtifactComponentRelation(ac.getId());
|
|
3503
|
+
logger11.info(
|
|
3504
|
+
{
|
|
3505
|
+
subAgentId: this.getId(),
|
|
3506
|
+
artifactComponentId: ac.getId()
|
|
3507
|
+
},
|
|
3508
|
+
"ArtifactComponent created and linked to agent"
|
|
3509
|
+
);
|
|
3510
|
+
} catch (error) {
|
|
3511
|
+
logger11.error(
|
|
3512
|
+
{
|
|
3513
|
+
subAgentId: this.getId(),
|
|
3514
|
+
artifactComponentName: artifactComponent2.name,
|
|
3515
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
3516
|
+
},
|
|
3517
|
+
"Failed to create artifact component"
|
|
3518
|
+
);
|
|
3519
|
+
throw error;
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
async createAgentDataComponentRelation(dataComponentId) {
|
|
3523
|
+
const relationResponse = await fetch(
|
|
3524
|
+
`${this.baseURL}/tenants/${this.tenantId}/agent-data-components`,
|
|
3525
|
+
{
|
|
3526
|
+
method: "POST",
|
|
3527
|
+
headers: {
|
|
3528
|
+
"Content-Type": "application/json"
|
|
3529
|
+
},
|
|
3530
|
+
body: JSON.stringify({
|
|
3531
|
+
id: `${this.getId()}-dc-${dataComponentId}`,
|
|
3532
|
+
tenantId: this.tenantId,
|
|
3533
|
+
subAgentId: this.getId(),
|
|
3534
|
+
dataComponentId
|
|
3535
|
+
})
|
|
3536
|
+
}
|
|
3537
|
+
);
|
|
3538
|
+
if (!relationResponse.ok) {
|
|
3539
|
+
throw new Error(
|
|
3540
|
+
`Failed to create agent-dataComponent relation: ${relationResponse.status} ${relationResponse.statusText}`
|
|
3541
|
+
);
|
|
3542
|
+
}
|
|
3543
|
+
logger11.info(
|
|
3544
|
+
{
|
|
3545
|
+
subAgentId: this.getId(),
|
|
3546
|
+
dataComponentId
|
|
3547
|
+
},
|
|
3548
|
+
"Created agent-dataComponent relation"
|
|
3549
|
+
);
|
|
3550
|
+
}
|
|
3551
|
+
async createAgentArtifactComponentRelation(artifactComponentId) {
|
|
3552
|
+
const relationResponse = await fetch(
|
|
3553
|
+
`${this.baseURL}/tenants/${this.tenantId}/agent-artifact-components`,
|
|
3554
|
+
{
|
|
3555
|
+
method: "POST",
|
|
3556
|
+
headers: {
|
|
3557
|
+
"Content-Type": "application/json"
|
|
3558
|
+
},
|
|
3559
|
+
body: JSON.stringify({
|
|
3560
|
+
id: crypto.randomUUID(),
|
|
3561
|
+
tenantId: this.tenantId,
|
|
3562
|
+
subAgentId: this.getId(),
|
|
3563
|
+
artifactComponentId
|
|
3564
|
+
})
|
|
3565
|
+
}
|
|
3566
|
+
);
|
|
3567
|
+
if (!relationResponse.ok) {
|
|
3568
|
+
throw new Error(
|
|
3569
|
+
`Failed to create agent-artifactComponent relation: ${relationResponse.status} ${relationResponse.statusText}`
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
logger11.info(
|
|
3573
|
+
{
|
|
3574
|
+
subAgentId: this.getId(),
|
|
3575
|
+
artifactComponentId
|
|
3576
|
+
},
|
|
3577
|
+
"Created agent-artifactComponent relation"
|
|
3578
|
+
);
|
|
3579
|
+
}
|
|
3580
|
+
async createAgentToolRelation(toolId, selectedTools, headers, toolPolicies) {
|
|
3581
|
+
const relationData = {
|
|
3582
|
+
id: `${this.getId()}-tool-${toolId}`,
|
|
3583
|
+
tenantId: this.tenantId,
|
|
3584
|
+
projectId: this.projectId,
|
|
3585
|
+
subAgentId: this.getId(),
|
|
3586
|
+
toolId
|
|
3587
|
+
};
|
|
3588
|
+
if (selectedTools !== void 0) {
|
|
3589
|
+
relationData.selectedTools = selectedTools;
|
|
3590
|
+
}
|
|
3591
|
+
if (headers !== void 0) {
|
|
3592
|
+
relationData.headers = headers;
|
|
3593
|
+
}
|
|
3594
|
+
if (toolPolicies !== void 0 && Object.keys(toolPolicies).length > 0) {
|
|
3595
|
+
relationData.toolPolicies = toolPolicies;
|
|
3596
|
+
}
|
|
3597
|
+
const relationResponse = await fetch(
|
|
3598
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/agent-tool-relations`,
|
|
3599
|
+
{
|
|
3600
|
+
method: "POST",
|
|
3601
|
+
headers: {
|
|
3602
|
+
"Content-Type": "application/json"
|
|
3603
|
+
},
|
|
3604
|
+
body: JSON.stringify(relationData)
|
|
3605
|
+
}
|
|
3606
|
+
);
|
|
3607
|
+
if (!relationResponse.ok) {
|
|
3608
|
+
const errorBody = await relationResponse.text().catch(() => "Unknown error");
|
|
3609
|
+
throw new Error(
|
|
3610
|
+
`Failed to create agent-tool relation: ${relationResponse.status} - ${errorBody}`
|
|
3611
|
+
);
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
};
|
|
3615
|
+
|
|
3616
|
+
// src/builderFunctions.ts
|
|
3617
|
+
function agent(config) {
|
|
3618
|
+
return new Agent(config);
|
|
3619
|
+
}
|
|
3620
|
+
function project(config) {
|
|
3621
|
+
return new Project(config);
|
|
3622
|
+
}
|
|
3623
|
+
function subAgent(config) {
|
|
3624
|
+
if (!config.id) {
|
|
3625
|
+
throw new Error(
|
|
3626
|
+
"Sub-Agent ID is required. Sub-Agents must have stable IDs for consistency across deployments."
|
|
3627
|
+
);
|
|
3628
|
+
}
|
|
3629
|
+
return new SubAgent(config);
|
|
3630
|
+
}
|
|
3631
|
+
function credential(config) {
|
|
3632
|
+
try {
|
|
3633
|
+
return CredentialReferenceApiInsertSchema.parse(config);
|
|
3634
|
+
} catch (error) {
|
|
3635
|
+
if (error instanceof Error) {
|
|
3636
|
+
const credId = config.id || "unknown";
|
|
3637
|
+
throw new Error(`Invalid credential '${credId}': ${error.message}`);
|
|
3638
|
+
}
|
|
3639
|
+
throw error;
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
function mcpServer(config) {
|
|
3643
|
+
if (!config.serverUrl) {
|
|
3644
|
+
throw new Error("MCP server requires a serverUrl");
|
|
3645
|
+
}
|
|
3646
|
+
const id = config.id || generateIdFromName(config.name);
|
|
3647
|
+
return new Tool({
|
|
3648
|
+
id,
|
|
3649
|
+
name: config.name,
|
|
3650
|
+
description: config.description,
|
|
3651
|
+
serverUrl: config.serverUrl,
|
|
3652
|
+
credential: config.credential,
|
|
3653
|
+
activeTools: config.activeTools,
|
|
3654
|
+
headers: config.headers,
|
|
3655
|
+
imageUrl: config.imageUrl,
|
|
3656
|
+
transport: config.transport ? { type: config.transport } : void 0
|
|
3657
|
+
});
|
|
3658
|
+
}
|
|
3659
|
+
function mcpTool(config) {
|
|
3660
|
+
const configWithId = {
|
|
3661
|
+
...config,
|
|
3662
|
+
id: config.id || generateIdFromName(config.name)
|
|
3663
|
+
};
|
|
3664
|
+
const validatedConfig = MCPToolConfigSchema.parse(configWithId);
|
|
3665
|
+
return new Tool(validatedConfig);
|
|
3666
|
+
}
|
|
3667
|
+
function artifactComponent(config) {
|
|
3668
|
+
const configWithId = {
|
|
3669
|
+
...config,
|
|
3670
|
+
id: config.id || generateIdFromName(config.name)
|
|
3671
|
+
};
|
|
3672
|
+
return new ArtifactComponent(configWithId);
|
|
3673
|
+
}
|
|
3674
|
+
function dataComponent(config) {
|
|
3675
|
+
const configWithId = {
|
|
3676
|
+
...config,
|
|
3677
|
+
id: config.id || generateIdFromName(config.name)
|
|
3678
|
+
};
|
|
3679
|
+
return new DataComponent(configWithId);
|
|
3680
|
+
}
|
|
3681
|
+
function statusComponent(config) {
|
|
3682
|
+
return new StatusComponent(config);
|
|
3683
|
+
}
|
|
3684
|
+
function agentMcp(config) {
|
|
3685
|
+
return {
|
|
3686
|
+
server: config.server,
|
|
3687
|
+
selectedTools: config.selectedTools,
|
|
3688
|
+
headers: config.headers
|
|
3689
|
+
};
|
|
3690
|
+
}
|
|
3691
|
+
function functionTool(config) {
|
|
3692
|
+
return new FunctionTool(config);
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3695
|
+
// src/utils/validateFunction.ts
|
|
3696
|
+
function validateFunction(value, name) {
|
|
3697
|
+
if (typeof value !== "function") {
|
|
3698
|
+
throw new Error(`${name} must be a function`);
|
|
3699
|
+
}
|
|
3700
|
+
}
|
|
3701
|
+
|
|
3702
|
+
// src/builders.ts
|
|
3703
|
+
var TransferConfigSchema = z.object({
|
|
3704
|
+
agent: z.instanceof(SubAgent),
|
|
3705
|
+
description: z.string().optional()
|
|
3706
|
+
});
|
|
3707
|
+
function transfer(targetAgent, description, condition) {
|
|
3708
|
+
if (condition !== void 0) {
|
|
3709
|
+
validateFunction(condition, "condition");
|
|
3710
|
+
}
|
|
3711
|
+
const config = {
|
|
3712
|
+
agent: targetAgent,
|
|
3713
|
+
description: description || `Hand off to ${targetAgent.getName()}`,
|
|
3714
|
+
condition
|
|
3715
|
+
};
|
|
3716
|
+
TransferConfigSchema.parse({
|
|
3717
|
+
agent: config.agent,
|
|
3718
|
+
description: config.description
|
|
3719
|
+
});
|
|
3720
|
+
return config;
|
|
3721
|
+
}
|
|
3722
|
+
|
|
3723
|
+
// src/credential-ref.ts
|
|
3724
|
+
function credentialRef(id) {
|
|
3725
|
+
return {
|
|
3726
|
+
__type: "credential-ref",
|
|
3727
|
+
id
|
|
3728
|
+
};
|
|
3729
|
+
}
|
|
3730
|
+
function isCredentialReference(value) {
|
|
3731
|
+
return value && typeof value === "object" && value.__type === "credential-ref";
|
|
3732
|
+
}
|
|
3733
|
+
|
|
3734
|
+
// src/environment-settings.ts
|
|
3735
|
+
function createEnvironmentSettings(environments) {
|
|
3736
|
+
return {
|
|
3737
|
+
getEnvironmentCredential: (key) => {
|
|
3738
|
+
const currentEnv = process.env.INKEEP_ENV || "development";
|
|
3739
|
+
const env = environments[currentEnv];
|
|
3740
|
+
if (!env) {
|
|
3741
|
+
throw new Error(
|
|
3742
|
+
`Environment '${currentEnv}' not found. Available: ${Object.keys(environments).join(", ")}`
|
|
3743
|
+
);
|
|
3744
|
+
}
|
|
3745
|
+
const credential2 = env.credentials?.[key];
|
|
3746
|
+
if (!credential2) {
|
|
3747
|
+
throw new Error(`Credential '${String(key)}' not found in environment '${currentEnv}'`);
|
|
3748
|
+
}
|
|
3749
|
+
return credential2;
|
|
3750
|
+
},
|
|
3751
|
+
getEnvironmentMcp: (key) => {
|
|
3752
|
+
const currentEnv = process.env.INKEEP_ENV || "development";
|
|
3753
|
+
const env = environments[currentEnv];
|
|
3754
|
+
if (!env) {
|
|
3755
|
+
throw new Error(
|
|
3756
|
+
`Environment '${currentEnv}' not found. Available: ${Object.keys(environments).join(", ")}`
|
|
3757
|
+
);
|
|
3758
|
+
}
|
|
3759
|
+
const mcpServer2 = env.mcpServers?.[key];
|
|
3760
|
+
if (!mcpServer2) {
|
|
3761
|
+
throw new Error(`MCP Server '${String(key)}' not found in environment '${currentEnv}'`);
|
|
3762
|
+
}
|
|
3763
|
+
return mcpServer2;
|
|
3764
|
+
},
|
|
3765
|
+
//Deprecated: Use getEnvironmentCredential instead
|
|
3766
|
+
getEnvironmentSetting: (key) => {
|
|
3767
|
+
const currentEnv = process.env.INKEEP_ENV || "development";
|
|
3768
|
+
const env = environments[currentEnv];
|
|
3769
|
+
if (!env) {
|
|
3770
|
+
throw new Error(
|
|
3771
|
+
`Environment '${currentEnv}' not found. Available: ${Object.keys(environments).join(", ")}`
|
|
3772
|
+
);
|
|
3773
|
+
}
|
|
3774
|
+
const credential2 = env.credentials?.[key];
|
|
3775
|
+
if (!credential2) {
|
|
3776
|
+
throw new Error(`Credential '${String(key)}' not found in environment '${currentEnv}'`);
|
|
3777
|
+
}
|
|
3778
|
+
return credential2;
|
|
3779
|
+
}
|
|
3780
|
+
};
|
|
3781
|
+
}
|
|
3782
|
+
function registerEnvironmentSettings(config) {
|
|
3783
|
+
return config;
|
|
3784
|
+
}
|
|
3785
|
+
var logger12 = getLogger("evaluationClient");
|
|
3786
|
+
function parseError2(errorText) {
|
|
3787
|
+
try {
|
|
3788
|
+
const errorJson = JSON.parse(errorText);
|
|
3789
|
+
if (errorJson.error) {
|
|
3790
|
+
const { error } = errorJson;
|
|
3791
|
+
return error?.message ?? error;
|
|
3792
|
+
}
|
|
3793
|
+
} catch {
|
|
3794
|
+
if (errorText) {
|
|
3795
|
+
return errorText;
|
|
3796
|
+
}
|
|
3797
|
+
}
|
|
3798
|
+
}
|
|
3799
|
+
function buildUrl(apiUrl, tenantId, projectId, ...pathSegments) {
|
|
3800
|
+
return `${apiUrl}/tenants/${tenantId}/projects/${projectId}/evaluations/${pathSegments.join("/")}`;
|
|
3801
|
+
}
|
|
3802
|
+
function buildHeaders(apiKey) {
|
|
3803
|
+
const headers = {
|
|
3804
|
+
"Content-Type": "application/json"
|
|
3805
|
+
};
|
|
3806
|
+
if (apiKey) {
|
|
3807
|
+
headers.Authorization = `Bearer ${apiKey}`;
|
|
3808
|
+
}
|
|
3809
|
+
return headers;
|
|
3810
|
+
}
|
|
3811
|
+
async function listDatasets(tenantId, projectId, apiUrl, apiKey) {
|
|
3812
|
+
logger12.info({ tenantId, projectId }, "Listing datasets via API");
|
|
3813
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets");
|
|
3814
|
+
try {
|
|
3815
|
+
const response = await apiFetch(url, {
|
|
3816
|
+
method: "GET",
|
|
3817
|
+
headers: buildHeaders(apiKey)
|
|
3818
|
+
});
|
|
3819
|
+
if (!response.ok) {
|
|
3820
|
+
const errorText = await response.text();
|
|
3821
|
+
const errorMessage = parseError2(errorText) ?? `Failed to list datasets: ${response.status} ${response.statusText}`;
|
|
3822
|
+
logger12.error(
|
|
3823
|
+
{ status: response.status, error: errorMessage },
|
|
3824
|
+
"Failed to list datasets via API"
|
|
3825
|
+
);
|
|
3826
|
+
throw new Error(errorMessage);
|
|
3827
|
+
}
|
|
3828
|
+
const result = await response.json();
|
|
3829
|
+
return result.data;
|
|
3830
|
+
} catch (error) {
|
|
3831
|
+
logger12.error({ error, tenantId, projectId }, "Failed to list datasets");
|
|
3832
|
+
throw error;
|
|
3833
|
+
}
|
|
3834
|
+
}
|
|
3835
|
+
async function getDataset(tenantId, projectId, datasetId, apiUrl, apiKey) {
|
|
3836
|
+
logger12.info({ tenantId, projectId, datasetId }, "Getting dataset via API");
|
|
3837
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId);
|
|
3838
|
+
try {
|
|
3839
|
+
const response = await apiFetch(url, {
|
|
3840
|
+
method: "GET",
|
|
3841
|
+
headers: buildHeaders(apiKey)
|
|
3842
|
+
});
|
|
3843
|
+
if (!response.ok) {
|
|
3844
|
+
if (response.status === 404) {
|
|
3845
|
+
logger12.info({ datasetId }, "Dataset not found");
|
|
3846
|
+
return null;
|
|
3847
|
+
}
|
|
3848
|
+
const errorText = await response.text();
|
|
3849
|
+
const errorMessage = parseError2(errorText) ?? `Failed to get dataset: ${response.status} ${response.statusText}`;
|
|
3850
|
+
logger12.error(
|
|
3851
|
+
{ status: response.status, error: errorMessage },
|
|
3852
|
+
"Failed to get dataset via API"
|
|
3853
|
+
);
|
|
3854
|
+
throw new Error(errorMessage);
|
|
3855
|
+
}
|
|
3856
|
+
const result = await response.json();
|
|
3857
|
+
return result.data;
|
|
3858
|
+
} catch (error) {
|
|
3859
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to get dataset");
|
|
3860
|
+
throw error;
|
|
3861
|
+
}
|
|
3862
|
+
}
|
|
3863
|
+
async function createDataset(tenantId, projectId, apiUrl, datasetData, apiKey) {
|
|
3864
|
+
logger12.info({ tenantId, projectId }, "Creating dataset via API");
|
|
3865
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets");
|
|
3866
|
+
try {
|
|
3867
|
+
const response = await apiFetch(url, {
|
|
3868
|
+
method: "POST",
|
|
3869
|
+
headers: buildHeaders(apiKey),
|
|
3870
|
+
body: JSON.stringify(datasetData)
|
|
3871
|
+
});
|
|
3872
|
+
if (!response.ok) {
|
|
3873
|
+
const errorText = await response.text();
|
|
3874
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create dataset: ${response.status} ${response.statusText}`;
|
|
3875
|
+
logger12.error(
|
|
3876
|
+
{ status: response.status, error: errorMessage },
|
|
3877
|
+
"Failed to create dataset via API"
|
|
3878
|
+
);
|
|
3879
|
+
throw new Error(errorMessage);
|
|
3880
|
+
}
|
|
3881
|
+
const result = await response.json();
|
|
3882
|
+
logger12.info({ tenantId, projectId }, "Successfully created dataset via API");
|
|
3883
|
+
return result.data;
|
|
3884
|
+
} catch (error) {
|
|
3885
|
+
logger12.error({ error, tenantId, projectId }, "Failed to create dataset");
|
|
3886
|
+
throw error;
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
async function updateDataset(tenantId, projectId, datasetId, apiUrl, updateData, apiKey) {
|
|
3890
|
+
logger12.info({ tenantId, projectId, datasetId }, "Updating dataset via API");
|
|
3891
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId);
|
|
3892
|
+
try {
|
|
3893
|
+
const response = await apiFetch(url, {
|
|
3894
|
+
method: "PATCH",
|
|
3895
|
+
headers: buildHeaders(apiKey),
|
|
3896
|
+
body: JSON.stringify(updateData)
|
|
3897
|
+
});
|
|
3898
|
+
if (!response.ok) {
|
|
3899
|
+
const errorText = await response.text();
|
|
3900
|
+
const errorMessage = parseError2(errorText) ?? `Failed to update dataset: ${response.status} ${response.statusText}`;
|
|
3901
|
+
logger12.error(
|
|
3902
|
+
{ status: response.status, error: errorMessage },
|
|
3903
|
+
"Failed to update dataset via API"
|
|
3904
|
+
);
|
|
3905
|
+
throw new Error(errorMessage);
|
|
3906
|
+
}
|
|
3907
|
+
const result = await response.json();
|
|
3908
|
+
logger12.info({ tenantId, projectId, datasetId }, "Successfully updated dataset via API");
|
|
3909
|
+
return result.data;
|
|
3910
|
+
} catch (error) {
|
|
3911
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to update dataset");
|
|
3912
|
+
throw error;
|
|
3913
|
+
}
|
|
3914
|
+
}
|
|
3915
|
+
async function deleteDataset(tenantId, projectId, datasetId, apiUrl, apiKey) {
|
|
3916
|
+
logger12.info({ tenantId, projectId, datasetId }, "Deleting dataset via API");
|
|
3917
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId);
|
|
3918
|
+
try {
|
|
3919
|
+
const response = await apiFetch(url, {
|
|
3920
|
+
method: "DELETE",
|
|
3921
|
+
headers: buildHeaders(apiKey)
|
|
3922
|
+
});
|
|
3923
|
+
if (!response.ok) {
|
|
3924
|
+
const errorText = await response.text();
|
|
3925
|
+
const errorMessage = parseError2(errorText) ?? `Failed to delete dataset: ${response.status} ${response.statusText}`;
|
|
3926
|
+
logger12.error(
|
|
3927
|
+
{ status: response.status, error: errorMessage },
|
|
3928
|
+
"Failed to delete dataset via API"
|
|
3929
|
+
);
|
|
3930
|
+
throw new Error(errorMessage);
|
|
3931
|
+
}
|
|
3932
|
+
logger12.info({ tenantId, projectId, datasetId }, "Successfully deleted dataset via API");
|
|
3933
|
+
} catch (error) {
|
|
3934
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to delete dataset");
|
|
3935
|
+
throw error;
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
async function listDatasetItems(tenantId, projectId, datasetId, apiUrl, apiKey) {
|
|
3939
|
+
logger12.info({ tenantId, projectId, datasetId }, "Listing dataset items via API");
|
|
3940
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items");
|
|
3941
|
+
try {
|
|
3942
|
+
const response = await apiFetch(url, {
|
|
3943
|
+
method: "GET",
|
|
3944
|
+
headers: buildHeaders(apiKey)
|
|
3945
|
+
});
|
|
3946
|
+
if (!response.ok) {
|
|
3947
|
+
const errorText = await response.text();
|
|
3948
|
+
const errorMessage = parseError2(errorText) ?? `Failed to list dataset items: ${response.status} ${response.statusText}`;
|
|
3949
|
+
logger12.error(
|
|
3950
|
+
{ status: response.status, error: errorMessage },
|
|
3951
|
+
"Failed to list dataset items via API"
|
|
3952
|
+
);
|
|
3953
|
+
throw new Error(errorMessage);
|
|
3954
|
+
}
|
|
3955
|
+
const result = await response.json();
|
|
3956
|
+
return result.data;
|
|
3957
|
+
} catch (error) {
|
|
3958
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to list dataset items");
|
|
3959
|
+
throw error;
|
|
3960
|
+
}
|
|
3961
|
+
}
|
|
3962
|
+
async function getDatasetItem(tenantId, projectId, datasetId, itemId, apiUrl, apiKey) {
|
|
3963
|
+
logger12.info({ tenantId, projectId, datasetId, itemId }, "Getting dataset item via API");
|
|
3964
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items", itemId);
|
|
3965
|
+
try {
|
|
3966
|
+
const response = await apiFetch(url, {
|
|
3967
|
+
method: "GET",
|
|
3968
|
+
headers: buildHeaders(apiKey)
|
|
3969
|
+
});
|
|
3970
|
+
if (!response.ok) {
|
|
3971
|
+
if (response.status === 404) {
|
|
3972
|
+
logger12.info({ itemId }, "Dataset item not found");
|
|
3973
|
+
return null;
|
|
3974
|
+
}
|
|
3975
|
+
const errorText = await response.text();
|
|
3976
|
+
const errorMessage = parseError2(errorText) ?? `Failed to get dataset item: ${response.status} ${response.statusText}`;
|
|
3977
|
+
logger12.error(
|
|
3978
|
+
{ status: response.status, error: errorMessage },
|
|
3979
|
+
"Failed to get dataset item via API"
|
|
3980
|
+
);
|
|
3981
|
+
throw new Error(errorMessage);
|
|
3982
|
+
}
|
|
3983
|
+
const result = await response.json();
|
|
3984
|
+
return result.data;
|
|
3985
|
+
} catch (error) {
|
|
3986
|
+
logger12.error({ error, tenantId, projectId, datasetId, itemId }, "Failed to get dataset item");
|
|
3987
|
+
throw error;
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
async function createDatasetItem(tenantId, projectId, datasetId, apiUrl, itemData, apiKey) {
|
|
3991
|
+
logger12.info({ tenantId, projectId, datasetId }, "Creating dataset item via API");
|
|
3992
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items");
|
|
3993
|
+
try {
|
|
3994
|
+
const response = await apiFetch(url, {
|
|
3995
|
+
method: "POST",
|
|
3996
|
+
headers: buildHeaders(apiKey),
|
|
3997
|
+
body: JSON.stringify(itemData)
|
|
3998
|
+
});
|
|
3999
|
+
if (!response.ok) {
|
|
4000
|
+
const errorText = await response.text();
|
|
4001
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create dataset item: ${response.status} ${response.statusText}`;
|
|
4002
|
+
logger12.error(
|
|
4003
|
+
{ status: response.status, error: errorMessage },
|
|
4004
|
+
"Failed to create dataset item via API"
|
|
4005
|
+
);
|
|
4006
|
+
throw new Error(errorMessage);
|
|
4007
|
+
}
|
|
4008
|
+
const result = await response.json();
|
|
4009
|
+
logger12.info({ tenantId, projectId, datasetId }, "Successfully created dataset item via API");
|
|
4010
|
+
return result.data;
|
|
4011
|
+
} catch (error) {
|
|
4012
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to create dataset item");
|
|
4013
|
+
throw error;
|
|
4014
|
+
}
|
|
4015
|
+
}
|
|
4016
|
+
async function createDatasetItems(tenantId, projectId, datasetId, apiUrl, itemsData, apiKey) {
|
|
4017
|
+
logger12.info(
|
|
4018
|
+
{ tenantId, projectId, datasetId, count: itemsData.length },
|
|
4019
|
+
"Creating dataset items via API"
|
|
4020
|
+
);
|
|
4021
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items", "bulk");
|
|
4022
|
+
try {
|
|
4023
|
+
const response = await apiFetch(url, {
|
|
4024
|
+
method: "POST",
|
|
4025
|
+
headers: buildHeaders(apiKey),
|
|
4026
|
+
body: JSON.stringify({ items: itemsData })
|
|
4027
|
+
});
|
|
4028
|
+
if (!response.ok) {
|
|
4029
|
+
const errorText = await response.text();
|
|
4030
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create dataset items: ${response.status} ${response.statusText}`;
|
|
4031
|
+
logger12.error(
|
|
4032
|
+
{ status: response.status, error: errorMessage },
|
|
4033
|
+
"Failed to create dataset items via API"
|
|
4034
|
+
);
|
|
4035
|
+
throw new Error(errorMessage);
|
|
4036
|
+
}
|
|
4037
|
+
const result = await response.json();
|
|
4038
|
+
logger12.info(
|
|
4039
|
+
{ tenantId, projectId, datasetId, count: result.data.length },
|
|
4040
|
+
"Successfully created dataset items via API"
|
|
4041
|
+
);
|
|
4042
|
+
return result.data;
|
|
4043
|
+
} catch (error) {
|
|
4044
|
+
logger12.error({ error, tenantId, projectId, datasetId }, "Failed to create dataset items");
|
|
4045
|
+
throw error;
|
|
4046
|
+
}
|
|
4047
|
+
}
|
|
4048
|
+
async function updateDatasetItem(tenantId, projectId, datasetId, itemId, apiUrl, updateData, apiKey) {
|
|
4049
|
+
logger12.info({ tenantId, projectId, datasetId, itemId }, "Updating dataset item via API");
|
|
4050
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items", itemId);
|
|
4051
|
+
try {
|
|
4052
|
+
const response = await apiFetch(url, {
|
|
4053
|
+
method: "PATCH",
|
|
4054
|
+
headers: buildHeaders(apiKey),
|
|
4055
|
+
body: JSON.stringify(updateData)
|
|
4056
|
+
});
|
|
4057
|
+
if (!response.ok) {
|
|
4058
|
+
const errorText = await response.text();
|
|
4059
|
+
const errorMessage = parseError2(errorText) ?? `Failed to update dataset item: ${response.status} ${response.statusText}`;
|
|
4060
|
+
logger12.error(
|
|
4061
|
+
{ status: response.status, error: errorMessage },
|
|
4062
|
+
"Failed to update dataset item via API"
|
|
4063
|
+
);
|
|
4064
|
+
throw new Error(errorMessage);
|
|
4065
|
+
}
|
|
4066
|
+
const result = await response.json();
|
|
4067
|
+
logger12.info(
|
|
4068
|
+
{ tenantId, projectId, datasetId, itemId },
|
|
4069
|
+
"Successfully updated dataset item via API"
|
|
4070
|
+
);
|
|
4071
|
+
return result.data;
|
|
4072
|
+
} catch (error) {
|
|
4073
|
+
logger12.error(
|
|
4074
|
+
{ error, tenantId, projectId, datasetId, itemId },
|
|
4075
|
+
"Failed to update dataset item"
|
|
4076
|
+
);
|
|
4077
|
+
throw error;
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
async function deleteDatasetItem(tenantId, projectId, datasetId, itemId, apiUrl, apiKey) {
|
|
4081
|
+
logger12.info({ tenantId, projectId, datasetId, itemId }, "Deleting dataset item via API");
|
|
4082
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "datasets", datasetId, "items", itemId);
|
|
4083
|
+
try {
|
|
4084
|
+
const response = await apiFetch(url, {
|
|
4085
|
+
method: "DELETE",
|
|
4086
|
+
headers: buildHeaders(apiKey)
|
|
4087
|
+
});
|
|
4088
|
+
if (!response.ok) {
|
|
4089
|
+
const errorText = await response.text();
|
|
4090
|
+
const errorMessage = parseError2(errorText) ?? `Failed to delete dataset item: ${response.status} ${response.statusText}`;
|
|
4091
|
+
logger12.error(
|
|
4092
|
+
{ status: response.status, error: errorMessage },
|
|
4093
|
+
"Failed to delete dataset item via API"
|
|
4094
|
+
);
|
|
4095
|
+
throw new Error(errorMessage);
|
|
4096
|
+
}
|
|
4097
|
+
logger12.info(
|
|
4098
|
+
{ tenantId, projectId, datasetId, itemId },
|
|
4099
|
+
"Successfully deleted dataset item via API"
|
|
4100
|
+
);
|
|
4101
|
+
} catch (error) {
|
|
4102
|
+
logger12.error(
|
|
4103
|
+
{ error, tenantId, projectId, datasetId, itemId },
|
|
4104
|
+
"Failed to delete dataset item"
|
|
4105
|
+
);
|
|
4106
|
+
throw error;
|
|
4107
|
+
}
|
|
4108
|
+
}
|
|
4109
|
+
async function listEvaluators(tenantId, projectId, apiUrl, apiKey) {
|
|
4110
|
+
logger12.info({ tenantId, projectId }, "Listing evaluators via API");
|
|
4111
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluators");
|
|
4112
|
+
try {
|
|
4113
|
+
const response = await apiFetch(url, {
|
|
4114
|
+
method: "GET",
|
|
4115
|
+
headers: buildHeaders(apiKey)
|
|
4116
|
+
});
|
|
4117
|
+
if (!response.ok) {
|
|
4118
|
+
const errorText = await response.text();
|
|
4119
|
+
const errorMessage = parseError2(errorText) ?? `Failed to list evaluators: ${response.status} ${response.statusText}`;
|
|
4120
|
+
logger12.error(
|
|
4121
|
+
{ status: response.status, error: errorMessage },
|
|
4122
|
+
"Failed to list evaluators via API"
|
|
4123
|
+
);
|
|
4124
|
+
throw new Error(errorMessage);
|
|
4125
|
+
}
|
|
4126
|
+
const result = await response.json();
|
|
4127
|
+
return result.data;
|
|
4128
|
+
} catch (error) {
|
|
4129
|
+
logger12.error({ error, tenantId, projectId }, "Failed to list evaluators");
|
|
4130
|
+
throw error;
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
async function getEvaluator(tenantId, projectId, evaluatorId, apiUrl, apiKey) {
|
|
4134
|
+
logger12.info({ tenantId, projectId, evaluatorId }, "Getting evaluator via API");
|
|
4135
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluators", evaluatorId);
|
|
4136
|
+
try {
|
|
4137
|
+
const response = await apiFetch(url, {
|
|
4138
|
+
method: "GET",
|
|
4139
|
+
headers: buildHeaders(apiKey)
|
|
4140
|
+
});
|
|
4141
|
+
if (!response.ok) {
|
|
4142
|
+
if (response.status === 404) {
|
|
4143
|
+
logger12.info({ evaluatorId }, "Evaluator not found");
|
|
4144
|
+
return null;
|
|
4145
|
+
}
|
|
4146
|
+
const errorText = await response.text();
|
|
4147
|
+
const errorMessage = parseError2(errorText) ?? `Failed to get evaluator: ${response.status} ${response.statusText}`;
|
|
4148
|
+
logger12.error(
|
|
4149
|
+
{ status: response.status, error: errorMessage },
|
|
4150
|
+
"Failed to get evaluator via API"
|
|
4151
|
+
);
|
|
4152
|
+
throw new Error(errorMessage);
|
|
4153
|
+
}
|
|
4154
|
+
const result = await response.json();
|
|
4155
|
+
return result.data;
|
|
4156
|
+
} catch (error) {
|
|
4157
|
+
logger12.error({ error, tenantId, projectId, evaluatorId }, "Failed to get evaluator");
|
|
4158
|
+
throw error;
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
async function createEvaluator(tenantId, projectId, apiUrl, evaluatorData, apiKey) {
|
|
4162
|
+
logger12.info({ tenantId, projectId }, "Creating evaluator via API");
|
|
4163
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluators");
|
|
4164
|
+
try {
|
|
4165
|
+
const response = await apiFetch(url, {
|
|
4166
|
+
method: "POST",
|
|
4167
|
+
headers: buildHeaders(apiKey),
|
|
4168
|
+
body: JSON.stringify(evaluatorData)
|
|
4169
|
+
});
|
|
4170
|
+
if (!response.ok) {
|
|
4171
|
+
const errorText = await response.text();
|
|
4172
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create evaluator: ${response.status} ${response.statusText}`;
|
|
4173
|
+
logger12.error(
|
|
4174
|
+
{ status: response.status, error: errorMessage },
|
|
4175
|
+
"Failed to create evaluator via API"
|
|
4176
|
+
);
|
|
4177
|
+
throw new Error(errorMessage);
|
|
4178
|
+
}
|
|
4179
|
+
const result = await response.json();
|
|
4180
|
+
logger12.info({ tenantId, projectId }, "Successfully created evaluator via API");
|
|
4181
|
+
return result.data;
|
|
4182
|
+
} catch (error) {
|
|
4183
|
+
logger12.error({ error, tenantId, projectId }, "Failed to create evaluator");
|
|
4184
|
+
throw error;
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
async function updateEvaluator(tenantId, projectId, evaluatorId, apiUrl, updateData, apiKey) {
|
|
4188
|
+
logger12.info({ tenantId, projectId, evaluatorId }, "Updating evaluator via API");
|
|
4189
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluators", evaluatorId);
|
|
4190
|
+
try {
|
|
4191
|
+
const response = await apiFetch(url, {
|
|
4192
|
+
method: "PATCH",
|
|
4193
|
+
headers: buildHeaders(apiKey),
|
|
4194
|
+
body: JSON.stringify(updateData)
|
|
4195
|
+
});
|
|
4196
|
+
if (!response.ok) {
|
|
4197
|
+
const errorText = await response.text();
|
|
4198
|
+
const errorMessage = parseError2(errorText) ?? `Failed to update evaluator: ${response.status} ${response.statusText}`;
|
|
4199
|
+
logger12.error(
|
|
4200
|
+
{ status: response.status, error: errorMessage },
|
|
4201
|
+
"Failed to update evaluator via API"
|
|
4202
|
+
);
|
|
4203
|
+
throw new Error(errorMessage);
|
|
4204
|
+
}
|
|
4205
|
+
const result = await response.json();
|
|
4206
|
+
logger12.info({ tenantId, projectId, evaluatorId }, "Successfully updated evaluator via API");
|
|
4207
|
+
return result.data;
|
|
4208
|
+
} catch (error) {
|
|
4209
|
+
logger12.error({ error, tenantId, projectId, evaluatorId }, "Failed to update evaluator");
|
|
4210
|
+
throw error;
|
|
4211
|
+
}
|
|
4212
|
+
}
|
|
4213
|
+
async function deleteEvaluator(tenantId, projectId, evaluatorId, apiUrl, apiKey) {
|
|
4214
|
+
logger12.info({ tenantId, projectId, evaluatorId }, "Deleting evaluator via API");
|
|
4215
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluators", evaluatorId);
|
|
4216
|
+
try {
|
|
4217
|
+
const response = await apiFetch(url, {
|
|
4218
|
+
method: "DELETE",
|
|
4219
|
+
headers: buildHeaders(apiKey)
|
|
4220
|
+
});
|
|
4221
|
+
if (!response.ok) {
|
|
4222
|
+
const errorText = await response.text();
|
|
4223
|
+
const errorMessage = parseError2(errorText) ?? `Failed to delete evaluator: ${response.status} ${response.statusText}`;
|
|
4224
|
+
logger12.error(
|
|
4225
|
+
{ status: response.status, error: errorMessage },
|
|
4226
|
+
"Failed to delete evaluator via API"
|
|
4227
|
+
);
|
|
4228
|
+
throw new Error(errorMessage);
|
|
4229
|
+
}
|
|
4230
|
+
logger12.info({ tenantId, projectId, evaluatorId }, "Successfully deleted evaluator via API");
|
|
4231
|
+
} catch (error) {
|
|
4232
|
+
logger12.error({ error, tenantId, projectId, evaluatorId }, "Failed to delete evaluator");
|
|
4233
|
+
throw error;
|
|
4234
|
+
}
|
|
4235
|
+
}
|
|
4236
|
+
async function listEvaluationSuiteConfigs(tenantId, projectId, apiUrl, apiKey) {
|
|
4237
|
+
logger12.info({ tenantId, projectId }, "Listing evaluation suite configs via API");
|
|
4238
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-suite-configs");
|
|
4239
|
+
try {
|
|
4240
|
+
const response = await apiFetch(url, {
|
|
4241
|
+
method: "GET",
|
|
4242
|
+
headers: buildHeaders(apiKey)
|
|
4243
|
+
});
|
|
4244
|
+
if (!response.ok) {
|
|
4245
|
+
const errorText = await response.text();
|
|
4246
|
+
const errorMessage = parseError2(errorText) ?? `Failed to list evaluation suite configs: ${response.status} ${response.statusText}`;
|
|
4247
|
+
logger12.error(
|
|
4248
|
+
{ status: response.status, error: errorMessage },
|
|
4249
|
+
"Failed to list evaluation suite configs via API"
|
|
4250
|
+
);
|
|
4251
|
+
throw new Error(errorMessage);
|
|
4252
|
+
}
|
|
4253
|
+
const result = await response.json();
|
|
4254
|
+
return result.data;
|
|
4255
|
+
} catch (error) {
|
|
4256
|
+
logger12.error({ error, tenantId, projectId }, "Failed to list evaluation suite configs");
|
|
4257
|
+
throw error;
|
|
4258
|
+
}
|
|
4259
|
+
}
|
|
4260
|
+
async function getEvaluationSuiteConfig(tenantId, projectId, configId, apiUrl, apiKey) {
|
|
4261
|
+
logger12.info({ tenantId, projectId, configId }, "Getting evaluation suite config via API");
|
|
4262
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-suite-configs", configId);
|
|
4263
|
+
try {
|
|
4264
|
+
const response = await apiFetch(url, {
|
|
4265
|
+
method: "GET",
|
|
4266
|
+
headers: buildHeaders(apiKey)
|
|
4267
|
+
});
|
|
4268
|
+
if (!response.ok) {
|
|
4269
|
+
if (response.status === 404) {
|
|
4270
|
+
logger12.info({ configId }, "Evaluation suite config not found");
|
|
4271
|
+
return null;
|
|
4272
|
+
}
|
|
4273
|
+
const errorText = await response.text();
|
|
4274
|
+
const errorMessage = parseError2(errorText) ?? `Failed to get evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4275
|
+
logger12.error(
|
|
4276
|
+
{ status: response.status, error: errorMessage },
|
|
4277
|
+
"Failed to get evaluation suite config via API"
|
|
4278
|
+
);
|
|
4279
|
+
throw new Error(errorMessage);
|
|
4280
|
+
}
|
|
4281
|
+
const result = await response.json();
|
|
4282
|
+
return result.data;
|
|
4283
|
+
} catch (error) {
|
|
4284
|
+
logger12.error({ error, tenantId, projectId, configId }, "Failed to get evaluation suite config");
|
|
4285
|
+
throw error;
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
async function createEvaluationSuiteConfig(tenantId, projectId, apiUrl, configData, apiKey) {
|
|
4289
|
+
logger12.info({ tenantId, projectId }, "Creating evaluation suite config via API");
|
|
4290
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-suite-configs");
|
|
4291
|
+
try {
|
|
4292
|
+
const response = await apiFetch(url, {
|
|
4293
|
+
method: "POST",
|
|
4294
|
+
headers: buildHeaders(apiKey),
|
|
4295
|
+
body: JSON.stringify(configData)
|
|
4296
|
+
});
|
|
4297
|
+
if (!response.ok) {
|
|
4298
|
+
const errorText = await response.text();
|
|
4299
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4300
|
+
logger12.error(
|
|
4301
|
+
{ status: response.status, error: errorMessage },
|
|
4302
|
+
"Failed to create evaluation suite config via API"
|
|
4303
|
+
);
|
|
4304
|
+
throw new Error(errorMessage);
|
|
4305
|
+
}
|
|
4306
|
+
const result = await response.json();
|
|
4307
|
+
logger12.info({ tenantId, projectId }, "Successfully created evaluation suite config via API");
|
|
4308
|
+
return result.data;
|
|
4309
|
+
} catch (error) {
|
|
4310
|
+
logger12.error({ error, tenantId, projectId }, "Failed to create evaluation suite config");
|
|
4311
|
+
throw error;
|
|
4312
|
+
}
|
|
4313
|
+
}
|
|
4314
|
+
async function updateEvaluationSuiteConfig(tenantId, projectId, configId, apiUrl, updateData, apiKey) {
|
|
4315
|
+
logger12.info({ tenantId, projectId, configId }, "Updating evaluation suite config via API");
|
|
4316
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-suite-configs", configId);
|
|
4317
|
+
try {
|
|
4318
|
+
const response = await apiFetch(url, {
|
|
4319
|
+
method: "PATCH",
|
|
4320
|
+
headers: buildHeaders(apiKey),
|
|
4321
|
+
body: JSON.stringify(updateData)
|
|
4322
|
+
});
|
|
4323
|
+
if (!response.ok) {
|
|
4324
|
+
const errorText = await response.text();
|
|
4325
|
+
const errorMessage = parseError2(errorText) ?? `Failed to update evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4326
|
+
logger12.error(
|
|
4327
|
+
{ status: response.status, error: errorMessage },
|
|
4328
|
+
"Failed to update evaluation suite config via API"
|
|
4329
|
+
);
|
|
4330
|
+
throw new Error(errorMessage);
|
|
4331
|
+
}
|
|
4332
|
+
const result = await response.json();
|
|
4333
|
+
logger12.info(
|
|
4334
|
+
{ tenantId, projectId, configId },
|
|
4335
|
+
"Successfully updated evaluation suite config via API"
|
|
4336
|
+
);
|
|
4337
|
+
return result.data;
|
|
4338
|
+
} catch (error) {
|
|
4339
|
+
logger12.error(
|
|
4340
|
+
{ error, tenantId, projectId, configId },
|
|
4341
|
+
"Failed to update evaluation suite config"
|
|
4342
|
+
);
|
|
4343
|
+
throw error;
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
async function deleteEvaluationSuiteConfig(tenantId, projectId, configId, apiUrl, apiKey) {
|
|
4347
|
+
logger12.info({ tenantId, projectId, configId }, "Deleting evaluation suite config via API");
|
|
4348
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-suite-configs", configId);
|
|
4349
|
+
try {
|
|
4350
|
+
const response = await apiFetch(url, {
|
|
4351
|
+
method: "DELETE",
|
|
4352
|
+
headers: buildHeaders(apiKey)
|
|
4353
|
+
});
|
|
4354
|
+
if (!response.ok) {
|
|
4355
|
+
const errorText = await response.text();
|
|
4356
|
+
const errorMessage = parseError2(errorText) ?? `Failed to delete evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4357
|
+
logger12.error(
|
|
4358
|
+
{ status: response.status, error: errorMessage },
|
|
4359
|
+
"Failed to delete evaluation suite config via API"
|
|
4360
|
+
);
|
|
4361
|
+
throw new Error(errorMessage);
|
|
4362
|
+
}
|
|
4363
|
+
logger12.info(
|
|
4364
|
+
{ tenantId, projectId, configId },
|
|
4365
|
+
"Successfully deleted evaluation suite config via API"
|
|
4366
|
+
);
|
|
4367
|
+
} catch (error) {
|
|
4368
|
+
logger12.error(
|
|
4369
|
+
{ error, tenantId, projectId, configId },
|
|
4370
|
+
"Failed to delete evaluation suite config"
|
|
4371
|
+
);
|
|
4372
|
+
throw error;
|
|
4373
|
+
}
|
|
4374
|
+
}
|
|
4375
|
+
async function listEvaluationSuiteConfigEvaluators(tenantId, projectId, configId, apiUrl, apiKey) {
|
|
4376
|
+
logger12.info(
|
|
4377
|
+
{ tenantId, projectId, configId },
|
|
4378
|
+
"Listing evaluators for evaluation suite config via API"
|
|
4379
|
+
);
|
|
4380
|
+
const url = buildUrl(
|
|
4381
|
+
apiUrl,
|
|
4382
|
+
tenantId,
|
|
4383
|
+
projectId,
|
|
4384
|
+
"evaluation-suite-configs",
|
|
4385
|
+
configId,
|
|
4386
|
+
"evaluators"
|
|
4387
|
+
);
|
|
4388
|
+
try {
|
|
4389
|
+
const response = await apiFetch(url, {
|
|
4390
|
+
method: "GET",
|
|
4391
|
+
headers: buildHeaders(apiKey)
|
|
4392
|
+
});
|
|
4393
|
+
if (!response.ok) {
|
|
4394
|
+
const errorText = await response.text();
|
|
4395
|
+
const errorMessage = parseError2(errorText) ?? `Failed to list evaluators for evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4396
|
+
logger12.error(
|
|
4397
|
+
{ status: response.status, error: errorMessage },
|
|
4398
|
+
"Failed to list evaluators for evaluation suite config via API"
|
|
4399
|
+
);
|
|
4400
|
+
throw new Error(errorMessage);
|
|
4401
|
+
}
|
|
4402
|
+
const result = await response.json();
|
|
4403
|
+
return result.data;
|
|
4404
|
+
} catch (error) {
|
|
4405
|
+
logger12.error(
|
|
4406
|
+
{ error, tenantId, projectId, configId },
|
|
4407
|
+
"Failed to list evaluators for evaluation suite config"
|
|
4408
|
+
);
|
|
4409
|
+
throw error;
|
|
4410
|
+
}
|
|
4411
|
+
}
|
|
4412
|
+
async function addEvaluatorToSuiteConfig(tenantId, projectId, configId, evaluatorId, apiUrl, apiKey) {
|
|
4413
|
+
logger12.info(
|
|
4414
|
+
{ tenantId, projectId, configId, evaluatorId },
|
|
4415
|
+
"Adding evaluator to evaluation suite config via API"
|
|
4416
|
+
);
|
|
4417
|
+
const url = buildUrl(
|
|
4418
|
+
apiUrl,
|
|
4419
|
+
tenantId,
|
|
4420
|
+
projectId,
|
|
4421
|
+
"evaluation-suite-configs",
|
|
4422
|
+
configId,
|
|
4423
|
+
"evaluators",
|
|
4424
|
+
evaluatorId
|
|
4425
|
+
);
|
|
4426
|
+
try {
|
|
4427
|
+
const response = await apiFetch(url, {
|
|
4428
|
+
method: "POST",
|
|
4429
|
+
headers: buildHeaders(apiKey)
|
|
4430
|
+
});
|
|
4431
|
+
if (!response.ok) {
|
|
4432
|
+
const errorText = await response.text();
|
|
4433
|
+
const errorMessage = parseError2(errorText) ?? `Failed to add evaluator to evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4434
|
+
logger12.error(
|
|
4435
|
+
{ status: response.status, error: errorMessage },
|
|
4436
|
+
"Failed to add evaluator to evaluation suite config via API"
|
|
4437
|
+
);
|
|
4438
|
+
throw new Error(errorMessage);
|
|
4439
|
+
}
|
|
4440
|
+
const result = await response.json();
|
|
4441
|
+
logger12.info(
|
|
4442
|
+
{ tenantId, projectId, configId, evaluatorId },
|
|
4443
|
+
"Successfully added evaluator to evaluation suite config via API"
|
|
4444
|
+
);
|
|
4445
|
+
return result.data;
|
|
4446
|
+
} catch (error) {
|
|
4447
|
+
logger12.error(
|
|
4448
|
+
{ error, tenantId, projectId, configId, evaluatorId },
|
|
4449
|
+
"Failed to add evaluator to evaluation suite config"
|
|
4450
|
+
);
|
|
4451
|
+
throw error;
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
async function removeEvaluatorFromSuiteConfig(tenantId, projectId, configId, evaluatorId, apiUrl, apiKey) {
|
|
4455
|
+
logger12.info(
|
|
4456
|
+
{ tenantId, projectId, configId, evaluatorId },
|
|
4457
|
+
"Removing evaluator from evaluation suite config via API"
|
|
4458
|
+
);
|
|
4459
|
+
const url = buildUrl(
|
|
4460
|
+
apiUrl,
|
|
4461
|
+
tenantId,
|
|
4462
|
+
projectId,
|
|
4463
|
+
"evaluation-suite-configs",
|
|
4464
|
+
configId,
|
|
4465
|
+
"evaluators",
|
|
4466
|
+
evaluatorId
|
|
4467
|
+
);
|
|
4468
|
+
try {
|
|
4469
|
+
const response = await apiFetch(url, {
|
|
4470
|
+
method: "DELETE",
|
|
4471
|
+
headers: buildHeaders(apiKey)
|
|
4472
|
+
});
|
|
4473
|
+
if (!response.ok) {
|
|
4474
|
+
const errorText = await response.text();
|
|
4475
|
+
const errorMessage = parseError2(errorText) ?? `Failed to remove evaluator from evaluation suite config: ${response.status} ${response.statusText}`;
|
|
4476
|
+
logger12.error(
|
|
4477
|
+
{ status: response.status, error: errorMessage },
|
|
4478
|
+
"Failed to remove evaluator from evaluation suite config via API"
|
|
4479
|
+
);
|
|
4480
|
+
throw new Error(errorMessage);
|
|
4481
|
+
}
|
|
4482
|
+
logger12.info(
|
|
4483
|
+
{ tenantId, projectId, configId, evaluatorId },
|
|
4484
|
+
"Successfully removed evaluator from evaluation suite config via API"
|
|
4485
|
+
);
|
|
4486
|
+
} catch (error) {
|
|
4487
|
+
logger12.error(
|
|
4488
|
+
{ error, tenantId, projectId, configId, evaluatorId },
|
|
4489
|
+
"Failed to remove evaluator from evaluation suite config"
|
|
4490
|
+
);
|
|
4491
|
+
throw error;
|
|
4492
|
+
}
|
|
4493
|
+
}
|
|
4494
|
+
async function getEvaluationResult(tenantId, projectId, resultId, apiUrl, apiKey) {
|
|
4495
|
+
logger12.info({ tenantId, projectId, resultId }, "Getting evaluation result via API");
|
|
4496
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-results", resultId);
|
|
4497
|
+
try {
|
|
4498
|
+
const response = await apiFetch(url, {
|
|
4499
|
+
method: "GET",
|
|
4500
|
+
headers: buildHeaders(apiKey)
|
|
4501
|
+
});
|
|
4502
|
+
if (!response.ok) {
|
|
4503
|
+
if (response.status === 404) {
|
|
4504
|
+
logger12.info({ resultId }, "Evaluation result not found");
|
|
4505
|
+
return null;
|
|
4506
|
+
}
|
|
4507
|
+
const errorText = await response.text();
|
|
4508
|
+
const errorMessage = parseError2(errorText) ?? `Failed to get evaluation result: ${response.status} ${response.statusText}`;
|
|
4509
|
+
logger12.error(
|
|
4510
|
+
{ status: response.status, error: errorMessage },
|
|
4511
|
+
"Failed to get evaluation result via API"
|
|
4512
|
+
);
|
|
4513
|
+
throw new Error(errorMessage);
|
|
4514
|
+
}
|
|
4515
|
+
const result = await response.json();
|
|
4516
|
+
return result.data;
|
|
4517
|
+
} catch (error) {
|
|
4518
|
+
logger12.error({ error, tenantId, projectId, resultId }, "Failed to get evaluation result");
|
|
4519
|
+
throw error;
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
async function createEvaluationResult(tenantId, projectId, apiUrl, resultData, apiKey) {
|
|
4523
|
+
logger12.info({ tenantId, projectId }, "Creating evaluation result via API");
|
|
4524
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-results");
|
|
4525
|
+
try {
|
|
4526
|
+
const response = await apiFetch(url, {
|
|
4527
|
+
method: "POST",
|
|
4528
|
+
headers: buildHeaders(apiKey),
|
|
4529
|
+
body: JSON.stringify(resultData)
|
|
4530
|
+
});
|
|
4531
|
+
if (!response.ok) {
|
|
4532
|
+
const errorText = await response.text();
|
|
4533
|
+
const errorMessage = parseError2(errorText) ?? `Failed to create evaluation result: ${response.status} ${response.statusText}`;
|
|
4534
|
+
logger12.error(
|
|
4535
|
+
{ status: response.status, error: errorMessage },
|
|
4536
|
+
"Failed to create evaluation result via API"
|
|
4537
|
+
);
|
|
4538
|
+
throw new Error(errorMessage);
|
|
4539
|
+
}
|
|
4540
|
+
const result = await response.json();
|
|
4541
|
+
logger12.info({ tenantId, projectId }, "Successfully created evaluation result via API");
|
|
4542
|
+
return result.data;
|
|
4543
|
+
} catch (error) {
|
|
4544
|
+
logger12.error({ error, tenantId, projectId }, "Failed to create evaluation result");
|
|
4545
|
+
throw error;
|
|
4546
|
+
}
|
|
4547
|
+
}
|
|
4548
|
+
async function updateEvaluationResult(tenantId, projectId, resultId, apiUrl, updateData, apiKey) {
|
|
4549
|
+
logger12.info({ tenantId, projectId, resultId }, "Updating evaluation result via API");
|
|
4550
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-results", resultId);
|
|
4551
|
+
try {
|
|
4552
|
+
const response = await apiFetch(url, {
|
|
4553
|
+
method: "PATCH",
|
|
4554
|
+
headers: buildHeaders(apiKey),
|
|
4555
|
+
body: JSON.stringify(updateData)
|
|
4556
|
+
});
|
|
4557
|
+
if (!response.ok) {
|
|
4558
|
+
const errorText = await response.text();
|
|
4559
|
+
const errorMessage = parseError2(errorText) ?? `Failed to update evaluation result: ${response.status} ${response.statusText}`;
|
|
4560
|
+
logger12.error(
|
|
4561
|
+
{ status: response.status, error: errorMessage },
|
|
4562
|
+
"Failed to update evaluation result via API"
|
|
4563
|
+
);
|
|
4564
|
+
throw new Error(errorMessage);
|
|
4565
|
+
}
|
|
4566
|
+
const result = await response.json();
|
|
4567
|
+
logger12.info(
|
|
4568
|
+
{ tenantId, projectId, resultId },
|
|
4569
|
+
"Successfully updated evaluation result via API"
|
|
4570
|
+
);
|
|
4571
|
+
return result.data;
|
|
4572
|
+
} catch (error) {
|
|
4573
|
+
logger12.error({ error, tenantId, projectId, resultId }, "Failed to update evaluation result");
|
|
4574
|
+
throw error;
|
|
4575
|
+
}
|
|
4576
|
+
}
|
|
4577
|
+
async function deleteEvaluationResult(tenantId, projectId, resultId, apiUrl, apiKey) {
|
|
4578
|
+
logger12.info({ tenantId, projectId, resultId }, "Deleting evaluation result via API");
|
|
4579
|
+
const url = buildUrl(apiUrl, tenantId, projectId, "evaluation-results", resultId);
|
|
4580
|
+
try {
|
|
4581
|
+
const response = await apiFetch(url, {
|
|
4582
|
+
method: "DELETE",
|
|
4583
|
+
headers: buildHeaders(apiKey)
|
|
4584
|
+
});
|
|
4585
|
+
if (!response.ok) {
|
|
4586
|
+
const errorText = await response.text();
|
|
4587
|
+
const errorMessage = parseError2(errorText) ?? `Failed to delete evaluation result: ${response.status} ${response.statusText}`;
|
|
4588
|
+
logger12.error(
|
|
4589
|
+
{ status: response.status, error: errorMessage },
|
|
4590
|
+
"Failed to delete evaluation result via API"
|
|
4591
|
+
);
|
|
4592
|
+
throw new Error(errorMessage);
|
|
4593
|
+
}
|
|
4594
|
+
logger12.info(
|
|
4595
|
+
{ tenantId, projectId, resultId },
|
|
4596
|
+
"Successfully deleted evaluation result via API"
|
|
4597
|
+
);
|
|
4598
|
+
} catch (error) {
|
|
4599
|
+
logger12.error({ error, tenantId, projectId, resultId }, "Failed to delete evaluation result");
|
|
4600
|
+
throw error;
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4603
|
+
var logger13 = getLogger("external-agent-builder");
|
|
4604
|
+
var ExternalAgent = class {
|
|
4605
|
+
constructor(config) {
|
|
4606
|
+
__publicField(this, "config");
|
|
4607
|
+
__publicField(this, "type", "external");
|
|
4608
|
+
__publicField(this, "initialized", false);
|
|
4609
|
+
__publicField(this, "tenantId");
|
|
4610
|
+
__publicField(this, "projectId");
|
|
4611
|
+
__publicField(this, "baseURL");
|
|
4612
|
+
this.config = { ...config, type: "external" };
|
|
4613
|
+
this.tenantId = "default";
|
|
4614
|
+
this.projectId = "default";
|
|
4615
|
+
this.baseURL = this.config.baseUrl;
|
|
4616
|
+
logger13.debug(
|
|
4617
|
+
{
|
|
4618
|
+
externalAgentName: this.config.name,
|
|
4619
|
+
baseUrl: this.config.baseUrl,
|
|
4620
|
+
tenantId: this.tenantId
|
|
4621
|
+
},
|
|
4622
|
+
"External Agent constructor initialized"
|
|
4623
|
+
);
|
|
4624
|
+
}
|
|
4625
|
+
/**
|
|
4626
|
+
* Initialize the external agent by upserting it in the database
|
|
4627
|
+
*/
|
|
4628
|
+
async init() {
|
|
4629
|
+
if (this.initialized) return;
|
|
4630
|
+
try {
|
|
4631
|
+
await this.upsertExternalAgent();
|
|
4632
|
+
logger13.info(
|
|
4633
|
+
{
|
|
4634
|
+
externalSubAgentId: this.getId()
|
|
4635
|
+
},
|
|
4636
|
+
"External agent initialized successfully"
|
|
4637
|
+
);
|
|
4638
|
+
this.initialized = true;
|
|
4639
|
+
} catch (error) {
|
|
4640
|
+
logger13.error(
|
|
4641
|
+
{
|
|
4642
|
+
externalSubAgentId: this.getId(),
|
|
4643
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
4644
|
+
},
|
|
4645
|
+
"Failed to initialize external agent"
|
|
4646
|
+
);
|
|
4647
|
+
throw error;
|
|
4648
|
+
}
|
|
4649
|
+
}
|
|
4650
|
+
// Set context (tenantId and baseURL) from external source (agent, CLI, etc)
|
|
4651
|
+
setContext(tenantId, projectId) {
|
|
4652
|
+
this.tenantId = tenantId;
|
|
4653
|
+
this.projectId = projectId;
|
|
4654
|
+
}
|
|
4655
|
+
// Compute ID from name using a simple slug transformation
|
|
4656
|
+
getId() {
|
|
4657
|
+
return this.config.id;
|
|
4658
|
+
}
|
|
4659
|
+
with(options) {
|
|
4660
|
+
return {
|
|
4661
|
+
externalAgent: this,
|
|
4662
|
+
headers: options.headers
|
|
4663
|
+
};
|
|
4664
|
+
}
|
|
4665
|
+
// Private method to upsert external agent (create or update)
|
|
4666
|
+
async upsertExternalAgent() {
|
|
4667
|
+
const externalAgentData = {
|
|
4668
|
+
id: this.getId(),
|
|
4669
|
+
name: this.config.name,
|
|
4670
|
+
description: this.config.description,
|
|
4671
|
+
baseUrl: this.config.baseUrl,
|
|
4672
|
+
credentialReferenceId: this.config.credentialReference?.id || void 0
|
|
4673
|
+
};
|
|
4674
|
+
const updateResponse = await fetch(
|
|
4675
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/external-agents/${this.getId()}`,
|
|
4676
|
+
{
|
|
4677
|
+
method: "PUT",
|
|
4678
|
+
headers: {
|
|
4679
|
+
"Content-Type": "application/json"
|
|
4680
|
+
},
|
|
4681
|
+
body: JSON.stringify(externalAgentData)
|
|
4682
|
+
}
|
|
4683
|
+
);
|
|
4684
|
+
if (updateResponse.ok) {
|
|
4685
|
+
logger13.info(
|
|
4686
|
+
{
|
|
4687
|
+
externalSubAgentId: this.getId()
|
|
4688
|
+
},
|
|
4689
|
+
"External agent updated successfully"
|
|
4690
|
+
);
|
|
4691
|
+
return;
|
|
4692
|
+
}
|
|
4693
|
+
if (updateResponse.status === 404) {
|
|
4694
|
+
logger13.info(
|
|
4695
|
+
{
|
|
4696
|
+
externalSubAgentId: this.getId()
|
|
4697
|
+
},
|
|
4698
|
+
"External agent not found, creating new external agent"
|
|
4699
|
+
);
|
|
4700
|
+
const createResponse = await fetch(
|
|
4701
|
+
`${this.baseURL}/tenants/${this.tenantId}/projects/${this.projectId}/external-agents`,
|
|
4702
|
+
{
|
|
4703
|
+
method: "POST",
|
|
4704
|
+
headers: {
|
|
4705
|
+
"Content-Type": "application/json"
|
|
4706
|
+
},
|
|
4707
|
+
body: JSON.stringify(externalAgentData)
|
|
4708
|
+
}
|
|
4709
|
+
);
|
|
4710
|
+
if (!createResponse.ok) {
|
|
4711
|
+
const errorText2 = await createResponse.text().catch(() => "Unknown error");
|
|
4712
|
+
throw new Error(
|
|
4713
|
+
`Failed to create external agent: ${createResponse.status} ${createResponse.statusText} - ${errorText2}`
|
|
4714
|
+
);
|
|
4715
|
+
}
|
|
4716
|
+
logger13.info(
|
|
4717
|
+
{
|
|
4718
|
+
externalSubAgentId: this.getId()
|
|
4719
|
+
},
|
|
4720
|
+
"External agent created successfully"
|
|
4721
|
+
);
|
|
4722
|
+
return;
|
|
4723
|
+
}
|
|
4724
|
+
const errorText = await updateResponse.text().catch(() => "Unknown error");
|
|
4725
|
+
throw new Error(
|
|
4726
|
+
`Failed to update external agent: ${updateResponse.status} ${updateResponse.statusText} - ${errorText}`
|
|
4727
|
+
);
|
|
4728
|
+
}
|
|
4729
|
+
/**
|
|
4730
|
+
* Get the external agent configuration
|
|
4731
|
+
*/
|
|
4732
|
+
getConfig() {
|
|
4733
|
+
return { ...this.config };
|
|
4734
|
+
}
|
|
4735
|
+
/**
|
|
4736
|
+
* Get the external agent name
|
|
4737
|
+
*/
|
|
4738
|
+
getName() {
|
|
4739
|
+
return this.config.name;
|
|
4740
|
+
}
|
|
4741
|
+
/**
|
|
4742
|
+
* Get the external agent base URL
|
|
4743
|
+
*/
|
|
4744
|
+
getBaseUrl() {
|
|
4745
|
+
return this.config.baseUrl;
|
|
4746
|
+
}
|
|
4747
|
+
/**
|
|
4748
|
+
* Get the tenant ID
|
|
4749
|
+
*/
|
|
4750
|
+
getTenantId() {
|
|
4751
|
+
return this.tenantId;
|
|
4752
|
+
}
|
|
4753
|
+
getDescription() {
|
|
4754
|
+
return this.config.description || "";
|
|
4755
|
+
}
|
|
4756
|
+
getCredentialReferenceId() {
|
|
4757
|
+
return this.config.credentialReference?.id || void 0;
|
|
4758
|
+
}
|
|
4759
|
+
getCredentialReference() {
|
|
4760
|
+
return this.config.credentialReference || void 0;
|
|
4761
|
+
}
|
|
4762
|
+
};
|
|
4763
|
+
function externalAgent(config) {
|
|
4764
|
+
return new ExternalAgent(config);
|
|
4765
|
+
}
|
|
4766
|
+
function externalAgents(configs) {
|
|
4767
|
+
const builders = {};
|
|
4768
|
+
for (const [name, config] of Object.entries(configs)) {
|
|
4769
|
+
builders[name] = externalAgent(config);
|
|
4770
|
+
}
|
|
4771
|
+
return builders;
|
|
4772
|
+
}
|
|
4773
|
+
|
|
4774
|
+
// src/types.ts
|
|
4775
|
+
var AgentError = class extends Error {
|
|
4776
|
+
constructor(message, code, details) {
|
|
4777
|
+
super(message);
|
|
4778
|
+
this.code = code;
|
|
4779
|
+
this.details = details;
|
|
4780
|
+
this.name = "AgentError";
|
|
4781
|
+
}
|
|
4782
|
+
};
|
|
4783
|
+
var MaxTurnsExceededError = class extends AgentError {
|
|
4784
|
+
constructor(maxTurns) {
|
|
4785
|
+
super(`Maximum turns (${maxTurns}) exceeded`);
|
|
4786
|
+
this.code = "MAX_TURNS_EXCEEDED";
|
|
4787
|
+
}
|
|
4788
|
+
};
|
|
4789
|
+
|
|
4790
|
+
// src/runner.ts
|
|
4791
|
+
var logger14 = getLogger("runner");
|
|
4792
|
+
var Runner = class _Runner {
|
|
4793
|
+
/**
|
|
4794
|
+
* Run an agent until completion, handling transfers and tool calls
|
|
4795
|
+
* Similar to OpenAI's Runner.run() pattern
|
|
4796
|
+
* NOTE: This now requires an agent instead of an agent
|
|
4797
|
+
*/
|
|
4798
|
+
static async run(agent2, messages, options) {
|
|
4799
|
+
const maxTurns = options?.maxTurns || 10;
|
|
4800
|
+
let turnCount = 0;
|
|
4801
|
+
const messageHistory = _Runner.normalizeToMessageHistory(messages);
|
|
4802
|
+
const allToolCalls = [];
|
|
4803
|
+
logger14.info(
|
|
4804
|
+
{
|
|
4805
|
+
agentId: agent2.getId(),
|
|
4806
|
+
defaultSubAgent: agent2.getDefaultSubAgent()?.getName(),
|
|
4807
|
+
maxTurns,
|
|
4808
|
+
initialMessageCount: messageHistory.length
|
|
4809
|
+
},
|
|
4810
|
+
"Starting agent run"
|
|
4811
|
+
);
|
|
4812
|
+
while (turnCount < maxTurns) {
|
|
4813
|
+
logger14.debug(
|
|
4814
|
+
{
|
|
4815
|
+
agentId: agent2.getId(),
|
|
4816
|
+
turnCount,
|
|
4817
|
+
messageHistoryLength: messageHistory.length
|
|
4818
|
+
},
|
|
4819
|
+
"Starting turn"
|
|
4820
|
+
);
|
|
4821
|
+
const response = await agent2.generate(messageHistory, options);
|
|
4822
|
+
turnCount++;
|
|
4823
|
+
logger14.info(
|
|
4824
|
+
{
|
|
4825
|
+
agentId: agent2.getId(),
|
|
4826
|
+
turnCount,
|
|
4827
|
+
responseLength: response.length
|
|
4828
|
+
},
|
|
4829
|
+
"Agent generation completed"
|
|
4830
|
+
);
|
|
4831
|
+
return {
|
|
4832
|
+
finalOutput: response,
|
|
4833
|
+
agent: agent2.getDefaultSubAgent() || {},
|
|
4834
|
+
turnCount,
|
|
4835
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
4836
|
+
metadata: {
|
|
4837
|
+
toolCalls: allToolCalls,
|
|
4838
|
+
transfers: []
|
|
4839
|
+
// Agent handles transfers internally
|
|
4840
|
+
}
|
|
4841
|
+
};
|
|
4842
|
+
}
|
|
4843
|
+
logger14.error(
|
|
4844
|
+
{
|
|
4845
|
+
agentId: agent2.getId(),
|
|
4846
|
+
maxTurns,
|
|
4847
|
+
finalTurnCount: turnCount
|
|
4848
|
+
},
|
|
4849
|
+
"Maximum turns exceeded"
|
|
4850
|
+
);
|
|
4851
|
+
throw new MaxTurnsExceededError(maxTurns);
|
|
4852
|
+
}
|
|
4853
|
+
/**
|
|
4854
|
+
* Stream an agent's response
|
|
4855
|
+
*/
|
|
4856
|
+
static async stream(agent2, messages, options) {
|
|
4857
|
+
logger14.info(
|
|
4858
|
+
{
|
|
4859
|
+
agentId: agent2.getId(),
|
|
4860
|
+
defaultSubAgent: agent2.getDefaultSubAgent()?.getName()
|
|
4861
|
+
},
|
|
4862
|
+
"Starting agent stream"
|
|
4863
|
+
);
|
|
4864
|
+
return agent2.stream(messages, options);
|
|
4865
|
+
}
|
|
4866
|
+
/**
|
|
4867
|
+
* Execute multiple agent in parallel and return the first successful result
|
|
4868
|
+
*/
|
|
4869
|
+
static async raceAgents(agent2, messages, options) {
|
|
4870
|
+
if (agent2.length === 0) {
|
|
4871
|
+
throw new Error("No agent provided for race");
|
|
4872
|
+
}
|
|
4873
|
+
logger14.info(
|
|
4874
|
+
{
|
|
4875
|
+
agentCount: agent2.length,
|
|
4876
|
+
agentIds: agent2.map((g) => g.getId())
|
|
4877
|
+
},
|
|
4878
|
+
"Starting agent race"
|
|
4879
|
+
);
|
|
4880
|
+
const promises = agent2.map(async (agent3, index) => {
|
|
4881
|
+
try {
|
|
4882
|
+
const result2 = await _Runner.run(agent3, messages, options);
|
|
4883
|
+
return { ...result2, raceIndex: index };
|
|
4884
|
+
} catch (error) {
|
|
4885
|
+
logger14.error(
|
|
4886
|
+
{
|
|
4887
|
+
agentId: agent3.getId(),
|
|
4888
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
4889
|
+
},
|
|
4890
|
+
"Agent failed in race"
|
|
4891
|
+
);
|
|
4892
|
+
throw error;
|
|
4893
|
+
}
|
|
4894
|
+
});
|
|
4895
|
+
const result = await Promise.race(promises);
|
|
4896
|
+
logger14.info(
|
|
4897
|
+
{
|
|
4898
|
+
winningAgentId: result.agentId || "unknown",
|
|
4899
|
+
raceIndex: result.raceIndex
|
|
4900
|
+
},
|
|
4901
|
+
"Agent race completed"
|
|
4902
|
+
);
|
|
4903
|
+
return result;
|
|
4904
|
+
}
|
|
4905
|
+
// Private helper methods
|
|
4906
|
+
static normalizeToMessageHistory(messages) {
|
|
4907
|
+
if (typeof messages === "string") {
|
|
4908
|
+
return [{ role: "user", content: messages }];
|
|
4909
|
+
}
|
|
4910
|
+
if (Array.isArray(messages)) {
|
|
4911
|
+
return messages.map(
|
|
4912
|
+
(msg) => typeof msg === "string" ? { role: "user", content: msg } : msg
|
|
4913
|
+
);
|
|
4914
|
+
}
|
|
4915
|
+
return [messages];
|
|
4916
|
+
}
|
|
4917
|
+
/**
|
|
4918
|
+
* Validate agent configuration before running
|
|
4919
|
+
*/
|
|
4920
|
+
static validateAgent(agent2) {
|
|
4921
|
+
const errors = [];
|
|
4922
|
+
if (!agent2.getId()) {
|
|
4923
|
+
errors.push("Agent ID is required");
|
|
4924
|
+
}
|
|
4925
|
+
const defaultSubAgent = agent2.getDefaultSubAgent();
|
|
4926
|
+
if (!defaultSubAgent) {
|
|
4927
|
+
errors.push("Default agent is required");
|
|
4928
|
+
} else {
|
|
4929
|
+
if (!defaultSubAgent.getName()) {
|
|
4930
|
+
errors.push("Default agent name is required");
|
|
4931
|
+
}
|
|
4932
|
+
if (!defaultSubAgent.getInstructions()) {
|
|
4933
|
+
errors.push("Default agent instructions are required");
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
const subAgents = agent2.getSubAgents();
|
|
4937
|
+
if (subAgents.length === 0) {
|
|
4938
|
+
errors.push("Agent must contain at least one subagent");
|
|
4939
|
+
}
|
|
4940
|
+
for (const subAgent2 of subAgents) {
|
|
4941
|
+
if (!subAgent2.getName()) {
|
|
4942
|
+
errors.push(`Agent missing name`);
|
|
4943
|
+
}
|
|
4944
|
+
}
|
|
4945
|
+
return {
|
|
4946
|
+
valid: errors.length === 0,
|
|
4947
|
+
errors
|
|
4948
|
+
};
|
|
4949
|
+
}
|
|
4950
|
+
/**
|
|
4951
|
+
* Get execution statistics for an agent
|
|
4952
|
+
*/
|
|
4953
|
+
static async getExecutionStats(agent2, messages, options) {
|
|
4954
|
+
const subAgents = agent2.getSubAgents();
|
|
4955
|
+
const defaultSubAgent = agent2.getDefaultSubAgent();
|
|
4956
|
+
const messageCount = Array.isArray(messages) ? messages.length : 1;
|
|
4957
|
+
return {
|
|
4958
|
+
estimatedTurns: Math.min(Math.max(messageCount, 1), options?.maxTurns || 10),
|
|
4959
|
+
estimatedTokens: messageCount * 100,
|
|
4960
|
+
// Rough estimate
|
|
4961
|
+
subAgentCount: subAgents.length,
|
|
4962
|
+
defaultSubAgent: defaultSubAgent?.getName()
|
|
4963
|
+
};
|
|
4964
|
+
}
|
|
4965
|
+
};
|
|
4966
|
+
var run = Runner.run.bind(Runner);
|
|
4967
|
+
var stream = Runner.stream.bind(Runner);
|
|
4968
|
+
var raceAgents = Runner.raceAgents.bind(Runner);
|
|
4969
|
+
|
|
4970
|
+
export { ArtifactComponent, DataComponent, ExternalAgent, FunctionTool, Project, Runner, StatusComponent, SubAgent, Tool, addEvaluatorToSuiteConfig, agent, agentMcp, artifactComponent, createDataset, createDatasetItem, createDatasetItems, createEnvironmentSettings, createEvaluationResult, createEvaluationSuiteConfig, createEvaluator, createFullProjectViaAPI, credential, credentialRef, dataComponent, deleteDataset, deleteDatasetItem, deleteEvaluationResult, deleteEvaluationSuiteConfig, deleteEvaluator, deleteFullProjectViaAPI, externalAgent, externalAgents, functionTool, getDataset, getDatasetItem, getEvaluationResult, getEvaluationSuiteConfig, getEvaluator, getFullProjectViaAPI, isCredentialReference, listDatasetItems, listDatasets, listEvaluationSuiteConfigEvaluators, listEvaluationSuiteConfigs, listEvaluators, mcpServer, mcpTool, project, raceAgents, registerEnvironmentSettings, removeEvaluatorFromSuiteConfig, run, statusComponent, stream, subAgent, transfer, updateDataset, updateDatasetItem, updateEvaluationResult, updateEvaluationSuiteConfig, updateEvaluator, updateFullProjectViaAPI };
|