@axiom-lattice/gateway 2.1.37 → 2.1.39
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +19 -0
- package/dist/index.js +365 -145
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +412 -191
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/__tests__/agent_service.test.ts +238 -0
- package/src/__tests__/workspace.test.ts +253 -0
- package/src/controllers/assistant.ts +48 -25
- package/src/controllers/database-configs.ts +17 -9
- package/src/controllers/mcp-configs.ts +9 -1
- package/src/controllers/memory.ts +3 -0
- package/src/controllers/metrics-configs.ts +81 -19
- package/src/controllers/models.ts +39 -0
- package/src/controllers/run.ts +36 -6
- package/src/controllers/sandbox.ts +6 -4
- package/src/controllers/schedules.ts +20 -0
- package/src/controllers/skills.ts +34 -11
- package/src/controllers/threads.ts +32 -12
- package/src/controllers/tools.ts +2 -273
- package/src/controllers/workspace.ts +153 -25
- package/src/index.ts +10 -0
- package/src/services/agent_service.ts +29 -10
- package/src/services/agent_task_consumer.ts +2 -2
- package/src/services/sandbox_service.ts +10 -9
|
@@ -52,6 +52,19 @@ export class WorkspaceController {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
private getTenantId(request: FastifyRequest): string {
|
|
55
|
+
// First try to get from authenticated user context
|
|
56
|
+
const userTenantId = (request as any).user?.tenantId;
|
|
57
|
+
if (userTenantId) {
|
|
58
|
+
return userTenantId;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Try to get from query parameters (for direct URL access like file downloads)
|
|
62
|
+
const queryTenantId = (request.query as any)?.tenantId;
|
|
63
|
+
if (queryTenantId) {
|
|
64
|
+
return String(queryTenantId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Fallback to request headers for backward compatibility
|
|
55
68
|
return (request.headers["x-tenant-id"] as string) || "default";
|
|
56
69
|
}
|
|
57
70
|
|
|
@@ -239,8 +252,7 @@ export class WorkspaceController {
|
|
|
239
252
|
|
|
240
253
|
// ==================== File Operations ====================
|
|
241
254
|
|
|
242
|
-
private async getBackend(workspaceId: string, projectId: string) {
|
|
243
|
-
const tenantId = "default";
|
|
255
|
+
private async getBackend(tenantId: string, workspaceId: string, projectId: string) {
|
|
244
256
|
const workspace = await this.workspaceStore.getWorkspaceById(
|
|
245
257
|
tenantId,
|
|
246
258
|
workspaceId
|
|
@@ -251,18 +263,22 @@ export class WorkspaceController {
|
|
|
251
263
|
}
|
|
252
264
|
|
|
253
265
|
if (workspace.storageType === "sandbox") {
|
|
254
|
-
const sandboxManager = getSandBoxManager(
|
|
266
|
+
const sandboxManager = getSandBoxManager();
|
|
255
267
|
const sandboxName = "global";
|
|
256
268
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
257
|
-
return {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
269
|
+
return {
|
|
270
|
+
backend: new SandboxFilesystem({
|
|
271
|
+
sandboxInstance: sandbox,
|
|
272
|
+
workingDirectory: `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`,
|
|
273
|
+
}), workspace
|
|
274
|
+
};
|
|
261
275
|
} else {
|
|
262
|
-
return {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
return {
|
|
277
|
+
backend: new FilesystemBackend({
|
|
278
|
+
rootDir: `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`,
|
|
279
|
+
virtualMode: true,
|
|
280
|
+
}), workspace
|
|
281
|
+
};
|
|
266
282
|
}
|
|
267
283
|
}
|
|
268
284
|
|
|
@@ -301,6 +317,7 @@ export class WorkspaceController {
|
|
|
301
317
|
}>,
|
|
302
318
|
reply: FastifyReply
|
|
303
319
|
) {
|
|
320
|
+
const tenantId = this.getTenantId(request);
|
|
304
321
|
const { workspaceId, projectId } = request.params;
|
|
305
322
|
const filePath = request.query.path;
|
|
306
323
|
|
|
@@ -309,13 +326,13 @@ export class WorkspaceController {
|
|
|
309
326
|
}
|
|
310
327
|
|
|
311
328
|
try {
|
|
312
|
-
const { workspace } = await this.getBackend(workspaceId, projectId);
|
|
329
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
313
330
|
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
314
331
|
|
|
315
332
|
if (workspace.storageType === "sandbox") {
|
|
316
|
-
const sandboxManager = getSandBoxManager(
|
|
333
|
+
const sandboxManager = getSandBoxManager();
|
|
317
334
|
const sandbox = await sandboxManager.createSandbox("global");
|
|
318
|
-
const realPath = path.join("/home/gem/workspaces", workspaceId, projectId, resolvedPath);
|
|
335
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
319
336
|
const filename = this.getFilenameFromPath(resolvedPath);
|
|
320
337
|
const inferredContentType = this.getMimeType(filename);
|
|
321
338
|
|
|
@@ -341,14 +358,14 @@ export class WorkspaceController {
|
|
|
341
358
|
const nodeStream = Readable.fromWeb(webStream);
|
|
342
359
|
const contentType = body.contentType ?? inferredContentType;
|
|
343
360
|
const contentDisposition =
|
|
344
|
-
body.contentDisposition ?? `
|
|
361
|
+
body.contentDisposition ?? `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
345
362
|
return reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(nodeStream);
|
|
346
363
|
}
|
|
347
364
|
|
|
348
365
|
const bodyUnknown = downloadResult.body as unknown;
|
|
349
366
|
let buf: Buffer;
|
|
350
367
|
let contentType = inferredContentType;
|
|
351
|
-
let contentDisposition = `
|
|
368
|
+
let contentDisposition = `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`;
|
|
352
369
|
|
|
353
370
|
if (bodyUnknown instanceof ArrayBuffer) {
|
|
354
371
|
buf = Buffer.from(bodyUnknown);
|
|
@@ -372,7 +389,7 @@ export class WorkspaceController {
|
|
|
372
389
|
return reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(buf);
|
|
373
390
|
}
|
|
374
391
|
|
|
375
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
392
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
376
393
|
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
377
394
|
const filename = this.getFilenameFromPath(resolvedPath);
|
|
378
395
|
const mimeType = this.getMimeType(filename);
|
|
@@ -381,7 +398,7 @@ export class WorkspaceController {
|
|
|
381
398
|
return reply
|
|
382
399
|
.status(200)
|
|
383
400
|
.type(mimeType)
|
|
384
|
-
.header("Content-Disposition", `
|
|
401
|
+
.header("Content-Disposition", `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`)
|
|
385
402
|
.send(buffer);
|
|
386
403
|
} catch (error: unknown) {
|
|
387
404
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -389,16 +406,122 @@ export class WorkspaceController {
|
|
|
389
406
|
}
|
|
390
407
|
}
|
|
391
408
|
|
|
409
|
+
/**
|
|
410
|
+
* View a file inline in the browser (not download).
|
|
411
|
+
* Returns file content with inline Content-Disposition for preview.
|
|
412
|
+
*/
|
|
413
|
+
async viewFile(
|
|
414
|
+
request: FastifyRequest<{
|
|
415
|
+
Params: ProjectParams;
|
|
416
|
+
Querystring: { path: string };
|
|
417
|
+
}>,
|
|
418
|
+
reply: FastifyReply
|
|
419
|
+
) {
|
|
420
|
+
const tenantId = this.getTenantId(request);
|
|
421
|
+
const { workspaceId, projectId } = request.params;
|
|
422
|
+
const filePath = request.query.path;
|
|
423
|
+
|
|
424
|
+
if (!filePath) {
|
|
425
|
+
return reply.status(400).send({ success: false, error: "Path is required" });
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
430
|
+
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
431
|
+
|
|
432
|
+
if (workspace.storageType === "sandbox") {
|
|
433
|
+
const sandboxManager = getSandBoxManager();
|
|
434
|
+
const sandbox = await sandboxManager.createSandbox("global");
|
|
435
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
436
|
+
const filename = this.getFilenameFromPath(resolvedPath);
|
|
437
|
+
const inferredContentType = this.getMimeType(filename);
|
|
438
|
+
|
|
439
|
+
const downloadResult = await sandbox.file.downloadFile({
|
|
440
|
+
path: realPath,
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
if (!downloadResult.ok) {
|
|
444
|
+
return reply.status(502).send({
|
|
445
|
+
success: false,
|
|
446
|
+
error: `View error: ${JSON.stringify(downloadResult.error)}`,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const body = downloadResult.body as unknown as {
|
|
451
|
+
stream?: () => ReadableStream<Uint8Array>;
|
|
452
|
+
contentType?: string;
|
|
453
|
+
contentDisposition?: string;
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
if (typeof body?.stream === "function") {
|
|
457
|
+
const webStream = body.stream();
|
|
458
|
+
const nodeStream = Readable.fromWeb(webStream);
|
|
459
|
+
const contentType = body.contentType ?? inferredContentType;
|
|
460
|
+
// inline for viewing, not attachment for download
|
|
461
|
+
return reply
|
|
462
|
+
.status(200)
|
|
463
|
+
.type(contentType)
|
|
464
|
+
.header("Content-Disposition", "inline")
|
|
465
|
+
.send(nodeStream);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const bodyUnknown = downloadResult.body as unknown;
|
|
469
|
+
let buf: Buffer;
|
|
470
|
+
let contentType = inferredContentType;
|
|
471
|
+
|
|
472
|
+
if (bodyUnknown instanceof ArrayBuffer) {
|
|
473
|
+
buf = Buffer.from(bodyUnknown);
|
|
474
|
+
} else if (bodyUnknown instanceof Buffer) {
|
|
475
|
+
buf = bodyUnknown;
|
|
476
|
+
} else if (
|
|
477
|
+
bodyUnknown &&
|
|
478
|
+
typeof (bodyUnknown as { arrayBuffer?: () => Promise<ArrayBuffer> }).arrayBuffer === "function"
|
|
479
|
+
) {
|
|
480
|
+
const res = bodyUnknown as { arrayBuffer: () => Promise<ArrayBuffer>; headers?: Headers };
|
|
481
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
482
|
+
if (res.headers?.get("content-type")) contentType = res.headers.get("content-type")!;
|
|
483
|
+
} else if (bodyUnknown && typeof (bodyUnknown as { blob?: () => Promise<Blob> }).blob === "function") {
|
|
484
|
+
const blob = await (bodyUnknown as { blob: () => Promise<Blob> }).blob();
|
|
485
|
+
buf = Buffer.from(await blob.arrayBuffer());
|
|
486
|
+
} else {
|
|
487
|
+
return reply.status(502).send({ success: false, error: "Unexpected view response format" });
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
return reply
|
|
491
|
+
.status(200)
|
|
492
|
+
.type(contentType)
|
|
493
|
+
.header("Content-Disposition", "inline")
|
|
494
|
+
.send(buf);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
498
|
+
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
499
|
+
const filename = this.getFilenameFromPath(resolvedPath);
|
|
500
|
+
const mimeType = this.getMimeType(filename);
|
|
501
|
+
const buffer = Buffer.from(content, "utf-8");
|
|
502
|
+
|
|
503
|
+
return reply
|
|
504
|
+
.status(200)
|
|
505
|
+
.type(mimeType)
|
|
506
|
+
.header("Content-Disposition", "inline")
|
|
507
|
+
.send(buffer);
|
|
508
|
+
} catch (error: unknown) {
|
|
509
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
510
|
+
return reply.status(502).send({ success: false, error: `View proxy error: ${message}` });
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
392
514
|
async listPath(
|
|
393
515
|
request: FastifyRequest<{
|
|
394
516
|
Params: ProjectParams;
|
|
395
517
|
Querystring: ListPathQuery;
|
|
396
518
|
}>
|
|
397
519
|
) {
|
|
520
|
+
const tenantId = this.getTenantId(request);
|
|
398
521
|
const { workspaceId, projectId } = request.params;
|
|
399
522
|
const path = (request.query.path as string) || "/";
|
|
400
523
|
|
|
401
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
524
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
402
525
|
const files = await backend.lsInfo(path);
|
|
403
526
|
|
|
404
527
|
return { success: true, data: files };
|
|
@@ -410,10 +533,11 @@ export class WorkspaceController {
|
|
|
410
533
|
Querystring: ReadFileQuery;
|
|
411
534
|
}>
|
|
412
535
|
) {
|
|
536
|
+
const tenantId = this.getTenantId(request);
|
|
413
537
|
const { workspaceId, projectId } = request.params;
|
|
414
538
|
const { path, offset = 0, limit = 1000 } = request.query;
|
|
415
539
|
|
|
416
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
540
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
417
541
|
const content = await backend.read(path, Number(offset), Number(limit));
|
|
418
542
|
|
|
419
543
|
return { success: true, data: { content, offset, limit } };
|
|
@@ -475,11 +599,11 @@ export class WorkspaceController {
|
|
|
475
599
|
}
|
|
476
600
|
|
|
477
601
|
if (workspace.storageType === "sandbox") {
|
|
478
|
-
const sandboxManager = getSandBoxManager(
|
|
602
|
+
const sandboxManager = getSandBoxManager();
|
|
479
603
|
const sandboxName = "global";
|
|
480
604
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
481
605
|
|
|
482
|
-
const baseDir = path.join("/home/gem/workspaces", workspaceId, projectId);
|
|
606
|
+
const baseDir = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId);
|
|
483
607
|
const realPath = pathValue
|
|
484
608
|
? path.join(baseDir, pathValue, filename)
|
|
485
609
|
: path.join(baseDir, filename);
|
|
@@ -497,7 +621,7 @@ export class WorkspaceController {
|
|
|
497
621
|
}
|
|
498
622
|
|
|
499
623
|
const relativePath =
|
|
500
|
-
uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/workspaces", workspaceId, projectId), "") ||
|
|
624
|
+
uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId), "") ||
|
|
501
625
|
(pathValue ? `/${pathValue}/${filename}` : `/${filename}`);
|
|
502
626
|
|
|
503
627
|
const result = {
|
|
@@ -511,8 +635,8 @@ export class WorkspaceController {
|
|
|
511
635
|
return reply.status(200).send({ success: true, data: result });
|
|
512
636
|
}
|
|
513
637
|
|
|
514
|
-
// Filesystem storage: write under /lattice_store/workspaces/{workspaceId}/{projectId} and expose as virtual path "/<filename>"
|
|
515
|
-
const rootDir = `/lattice_store/workspaces/${workspaceId}/${projectId}`;
|
|
638
|
+
// Filesystem storage: write under /lattice_store/tenants/{tenantId}/workspaces/{workspaceId}/{projectId} and expose as virtual path "/<filename>"
|
|
639
|
+
const rootDir = `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
516
640
|
const targetDir = pathValue ? path.join(rootDir, pathValue) : rootDir;
|
|
517
641
|
const targetPath = path.join(targetDir, filename);
|
|
518
642
|
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
@@ -595,4 +719,8 @@ export function registerWorkspaceRoutes(app: FastifyInstance) {
|
|
|
595
719
|
"/api/workspaces/:workspaceId/projects/:projectId/downloadfile",
|
|
596
720
|
controller.downloadFile.bind(controller)
|
|
597
721
|
);
|
|
722
|
+
app.get(
|
|
723
|
+
"/api/workspaces/:workspaceId/projects/:projectId/viewfile",
|
|
724
|
+
controller.viewFile.bind(controller)
|
|
725
|
+
);
|
|
598
726
|
}
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
registerLoggerLattice,
|
|
15
15
|
getLoggerLattice,
|
|
16
16
|
loggerLatticeManager,
|
|
17
|
+
sandboxLatticeManager,
|
|
17
18
|
} from "@axiom-lattice/core";
|
|
18
19
|
import {
|
|
19
20
|
LoggerType,
|
|
@@ -196,6 +197,15 @@ const start = async (config?: LatticeGatewayConfig) => {
|
|
|
196
197
|
// Access via: request.server.loggerLattice or app.loggerLattice
|
|
197
198
|
app.decorate("loggerLattice", loggerLattice);
|
|
198
199
|
|
|
200
|
+
// Register sandbox manager if not already registered
|
|
201
|
+
if (!sandboxLatticeManager.hasLattice("default")) {
|
|
202
|
+
const sandboxBaseURL = process.env.SANDBOX_BASE_URL || "http://localhost:8080";
|
|
203
|
+
sandboxLatticeManager.registerLattice("default", {
|
|
204
|
+
baseURL: sandboxBaseURL,
|
|
205
|
+
});
|
|
206
|
+
logger.info(`Registered sandbox manager with baseURL: ${sandboxBaseURL}`);
|
|
207
|
+
}
|
|
208
|
+
|
|
199
209
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
200
210
|
|
|
201
211
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
@@ -11,13 +11,28 @@ import { Command, CommandParams } from "@langchain/langgraph";
|
|
|
11
11
|
import { v4 } from "uuid";
|
|
12
12
|
import {
|
|
13
13
|
getAgentClient,
|
|
14
|
-
|
|
14
|
+
agentLatticeManager,
|
|
15
15
|
InMemoryChunkBuffer,
|
|
16
16
|
registerChunkBuffer,
|
|
17
17
|
getChunkBuffer,
|
|
18
18
|
hasChunkBuffer,
|
|
19
19
|
} from "@axiom-lattice/core";
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Check if an agent exists for the given tenant and assistant ID
|
|
23
|
+
*/
|
|
24
|
+
export async function checkAgentExists(
|
|
25
|
+
tenant_id: string,
|
|
26
|
+
assistant_id: string
|
|
27
|
+
): Promise<boolean> {
|
|
28
|
+
try {
|
|
29
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
30
|
+
return agentLattice !== undefined;
|
|
31
|
+
} catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
21
36
|
/**
|
|
22
37
|
* Get or create the global ChunkBuffer instance
|
|
23
38
|
*/
|
|
@@ -53,7 +68,7 @@ export async function agent_invoke({
|
|
|
53
68
|
command?: CommandParams<any>;
|
|
54
69
|
custom_run_config?: Record<string, any>;
|
|
55
70
|
}) {
|
|
56
|
-
const agentLattice =
|
|
71
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
57
72
|
const runnable_agent = agentLattice?.client;
|
|
58
73
|
|
|
59
74
|
const { message, ...rest } = input;
|
|
@@ -66,6 +81,7 @@ export async function agent_invoke({
|
|
|
66
81
|
// Get runConfig from agent config and merge with custom_run_config
|
|
67
82
|
const runConfig = {
|
|
68
83
|
...agentLattice?.config?.runConfig || {},
|
|
84
|
+
tenantId: tenant_id,
|
|
69
85
|
workspaceId: workspace_id,
|
|
70
86
|
projectId: project_id,
|
|
71
87
|
...custom_run_config || {},
|
|
@@ -124,8 +140,8 @@ export async function agent_stream({
|
|
|
124
140
|
run_id?: string;
|
|
125
141
|
custom_run_config?: Record<string, any>;
|
|
126
142
|
}) {
|
|
127
|
-
const runnable_agent = getAgentClient(assistant_id)
|
|
128
|
-
const agentLattice =
|
|
143
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
144
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
129
145
|
const { message, ...rest } = input;
|
|
130
146
|
let messages: BaseMessage[] = [];
|
|
131
147
|
if (!command) {
|
|
@@ -139,6 +155,7 @@ export async function agent_stream({
|
|
|
139
155
|
// Get runConfig from agent config and merge with custom_run_config
|
|
140
156
|
const runConfig = {
|
|
141
157
|
...agentLattice?.config?.runConfig || {},
|
|
158
|
+
tenantId: tenant_id,
|
|
142
159
|
workspaceId: workspace_id,
|
|
143
160
|
projectId: project_id,
|
|
144
161
|
...custom_run_config || {},
|
|
@@ -150,7 +167,7 @@ export async function agent_stream({
|
|
|
150
167
|
if (!runnable_agent) {
|
|
151
168
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
152
169
|
}
|
|
153
|
-
const agentStream = await runnable_agent.stream(
|
|
170
|
+
const agentStream = await (runnable_agent as any).stream(
|
|
154
171
|
command
|
|
155
172
|
? new Command(command)
|
|
156
173
|
: {
|
|
@@ -235,13 +252,15 @@ export async function agent_stream({
|
|
|
235
252
|
}
|
|
236
253
|
|
|
237
254
|
export async function agent_state({
|
|
238
|
-
thread_id,
|
|
239
255
|
assistant_id,
|
|
256
|
+
thread_id,
|
|
257
|
+
tenant_id,
|
|
240
258
|
}: {
|
|
241
259
|
assistant_id: string;
|
|
242
260
|
thread_id: string;
|
|
261
|
+
tenant_id: string;
|
|
243
262
|
}) {
|
|
244
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
263
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
245
264
|
if (!runnable_agent) {
|
|
246
265
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
247
266
|
}
|
|
@@ -260,7 +279,7 @@ export async function agent_messages({
|
|
|
260
279
|
thread_id: string;
|
|
261
280
|
tenant_id: string;
|
|
262
281
|
}) {
|
|
263
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
282
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
264
283
|
if (!runnable_agent) {
|
|
265
284
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
266
285
|
}
|
|
@@ -298,8 +317,8 @@ export async function agent_messages({
|
|
|
298
317
|
return new_messages;
|
|
299
318
|
}
|
|
300
319
|
|
|
301
|
-
export async function draw_graph(assistant_id: string) {
|
|
302
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
320
|
+
export async function draw_graph(assistant_id: string, tenant_id: string) {
|
|
321
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
303
322
|
if (!runnable_agent) {
|
|
304
323
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
305
324
|
}
|
|
@@ -120,7 +120,7 @@ const handleAgentTask = async (
|
|
|
120
120
|
|
|
121
121
|
// Stream has ended successfully
|
|
122
122
|
if (callback_event) {
|
|
123
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
123
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
124
124
|
eventBus.publish(callback_event, {
|
|
125
125
|
success: true,
|
|
126
126
|
state: state,
|
|
@@ -137,7 +137,7 @@ const handleAgentTask = async (
|
|
|
137
137
|
await response.text(); // Consume the response
|
|
138
138
|
|
|
139
139
|
if (callback_event) {
|
|
140
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
140
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
141
141
|
eventBus.publish(callback_event, {
|
|
142
142
|
success: true,
|
|
143
143
|
state,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { agentLatticeManager, getSandBoxManager, normalizeSandboxName, sandboxLatticeManager } from "@axiom-lattice/core";
|
|
2
|
+
import { SandboxMiddlewareConfig } from "@axiom-lattice/protocols";
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
const ERROR_HTML = `<!DOCTYPE html>
|
|
@@ -114,19 +114,20 @@ const ERROR_HTML = `<!DOCTYPE html>
|
|
|
114
114
|
|
|
115
115
|
export class SandboxService {
|
|
116
116
|
|
|
117
|
-
getFilesystemIsolatedLevel(assistantId: string): "agent" | "thread" | "global" | null {
|
|
118
|
-
const
|
|
119
|
-
if (!
|
|
117
|
+
getFilesystemIsolatedLevel(tenantId: string, assistantId: string): "agent" | "thread" | "global" | null {
|
|
118
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenantId, assistantId);
|
|
119
|
+
if (!agentLattice) {
|
|
120
120
|
return null;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
const
|
|
124
|
-
const filesystemConfig = agentLattice?.config?.middleware?.find(m => m.type === "filesystem");
|
|
123
|
+
const filesystemConfig = agentLattice?.config?.middleware?.find((m: any) => m.type === "filesystem");
|
|
125
124
|
if (!filesystemConfig) {
|
|
126
125
|
return null;
|
|
127
126
|
}
|
|
128
127
|
|
|
129
|
-
|
|
128
|
+
// Type guard for SandboxMiddlewareConfig which has isolatedLevel
|
|
129
|
+
const config = filesystemConfig.config as SandboxMiddlewareConfig;
|
|
130
|
+
return config?.isolatedLevel || null;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
computeSandboxName(
|
|
@@ -153,7 +154,7 @@ export class SandboxService {
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
getTargetUrl(sandboxName: string): string {
|
|
156
|
-
const sandboxManager = getSandBoxManager(
|
|
157
|
+
const sandboxManager = getSandBoxManager()
|
|
157
158
|
return `${sandboxManager.getBaseURL()}/sandbox/${sandboxName}`;
|
|
158
159
|
}
|
|
159
160
|
|