@axiom-lattice/gateway 2.1.38 → 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 +10 -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
package/dist/index.mjs
CHANGED
|
@@ -14,12 +14,20 @@ import { Command } from "@langchain/langgraph";
|
|
|
14
14
|
import { v4 } from "uuid";
|
|
15
15
|
import {
|
|
16
16
|
getAgentClient,
|
|
17
|
-
|
|
17
|
+
agentLatticeManager,
|
|
18
18
|
InMemoryChunkBuffer,
|
|
19
19
|
registerChunkBuffer,
|
|
20
20
|
getChunkBuffer,
|
|
21
21
|
hasChunkBuffer
|
|
22
22
|
} from "@axiom-lattice/core";
|
|
23
|
+
async function checkAgentExists(tenant_id, assistant_id) {
|
|
24
|
+
try {
|
|
25
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
26
|
+
return agentLattice !== void 0;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
23
31
|
function getOrCreateChunkBuffer() {
|
|
24
32
|
if (!hasChunkBuffer("default")) {
|
|
25
33
|
const buffer = new InMemoryChunkBuffer({
|
|
@@ -43,7 +51,7 @@ async function agent_invoke({
|
|
|
43
51
|
run_id,
|
|
44
52
|
custom_run_config
|
|
45
53
|
}) {
|
|
46
|
-
const agentLattice =
|
|
54
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
47
55
|
const runnable_agent = agentLattice?.client;
|
|
48
56
|
const { message, ...rest } = input;
|
|
49
57
|
const humanMessage = new HumanMessage(message || "");
|
|
@@ -53,6 +61,7 @@ async function agent_invoke({
|
|
|
53
61
|
}
|
|
54
62
|
const runConfig = {
|
|
55
63
|
...agentLattice?.config?.runConfig || {},
|
|
64
|
+
tenantId: tenant_id,
|
|
56
65
|
workspaceId: workspace_id,
|
|
57
66
|
projectId: project_id,
|
|
58
67
|
...custom_run_config || {},
|
|
@@ -95,8 +104,8 @@ async function agent_stream({
|
|
|
95
104
|
run_id,
|
|
96
105
|
custom_run_config
|
|
97
106
|
}) {
|
|
98
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
99
|
-
const agentLattice =
|
|
107
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
108
|
+
const agentLattice = agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
100
109
|
const { message, ...rest } = input;
|
|
101
110
|
let messages = [];
|
|
102
111
|
if (!command) {
|
|
@@ -106,6 +115,7 @@ async function agent_stream({
|
|
|
106
115
|
const chunkBuffer = getOrCreateChunkBuffer();
|
|
107
116
|
const runConfig = {
|
|
108
117
|
...agentLattice?.config?.runConfig || {},
|
|
118
|
+
tenantId: tenant_id,
|
|
109
119
|
workspaceId: workspace_id,
|
|
110
120
|
projectId: project_id,
|
|
111
121
|
...custom_run_config || {},
|
|
@@ -184,10 +194,11 @@ async function agent_stream({
|
|
|
184
194
|
}
|
|
185
195
|
}
|
|
186
196
|
async function agent_state({
|
|
197
|
+
assistant_id,
|
|
187
198
|
thread_id,
|
|
188
|
-
|
|
199
|
+
tenant_id
|
|
189
200
|
}) {
|
|
190
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
201
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
191
202
|
if (!runnable_agent) {
|
|
192
203
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
193
204
|
}
|
|
@@ -201,7 +212,7 @@ async function agent_messages({
|
|
|
201
212
|
tenant_id,
|
|
202
213
|
assistant_id
|
|
203
214
|
}) {
|
|
204
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
215
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
205
216
|
if (!runnable_agent) {
|
|
206
217
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
207
218
|
}
|
|
@@ -222,8 +233,8 @@ async function agent_messages({
|
|
|
222
233
|
const new_messages = messagesArray;
|
|
223
234
|
return new_messages;
|
|
224
235
|
}
|
|
225
|
-
async function draw_graph(assistant_id) {
|
|
226
|
-
const runnable_agent = getAgentClient(assistant_id);
|
|
236
|
+
async function draw_graph(assistant_id, tenant_id) {
|
|
237
|
+
const runnable_agent = await getAgentClient(tenant_id, assistant_id);
|
|
227
238
|
if (!runnable_agent) {
|
|
228
239
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
229
240
|
}
|
|
@@ -260,10 +271,19 @@ async function resume_stream({
|
|
|
260
271
|
// src/controllers/assistant.ts
|
|
261
272
|
import { getStoreLattice } from "@axiom-lattice/core";
|
|
262
273
|
import { randomUUID } from "crypto";
|
|
263
|
-
import {
|
|
274
|
+
import { agentLatticeManager as agentLatticeManager2, eventBus } from "@axiom-lattice/core";
|
|
275
|
+
function getTenantId(request) {
|
|
276
|
+
const userTenantId = request.user?.tenantId;
|
|
277
|
+
if (userTenantId) {
|
|
278
|
+
return userTenantId;
|
|
279
|
+
}
|
|
280
|
+
return request.headers["x-tenant-id"] || "default";
|
|
281
|
+
}
|
|
264
282
|
function convertAgentConfigToAssistant(config) {
|
|
265
283
|
return {
|
|
266
284
|
id: config.key,
|
|
285
|
+
tenantId: "default",
|
|
286
|
+
// Code-configured agents belong to default tenant
|
|
267
287
|
name: config.name,
|
|
268
288
|
description: config.description,
|
|
269
289
|
graphDefinition: config,
|
|
@@ -275,13 +295,14 @@ function convertAgentConfigToAssistant(config) {
|
|
|
275
295
|
};
|
|
276
296
|
}
|
|
277
297
|
async function getAssistantList(request, reply) {
|
|
278
|
-
const
|
|
298
|
+
const tenantId = getTenantId(request);
|
|
299
|
+
const agentConfigs = await agentLatticeManager2.getAllAgentConfigsByTenant(tenantId);
|
|
279
300
|
const codeConfiguredAssistants = agentConfigs.map(
|
|
280
301
|
convertAgentConfigToAssistant
|
|
281
302
|
);
|
|
282
303
|
const storeLattice = getStoreLattice("default", "assistant");
|
|
283
304
|
const assistantStore = storeLattice.store;
|
|
284
|
-
const storedAssistants = await assistantStore.getAllAssistants();
|
|
305
|
+
const storedAssistants = await assistantStore.getAllAssistants(tenantId);
|
|
285
306
|
const assistantMap = /* @__PURE__ */ new Map();
|
|
286
307
|
codeConfiguredAssistants.forEach((assistant) => {
|
|
287
308
|
assistantMap.set(assistant.id, assistant);
|
|
@@ -301,12 +322,12 @@ async function getAssistantList(request, reply) {
|
|
|
301
322
|
}
|
|
302
323
|
async function getAssistant(request, reply) {
|
|
303
324
|
const { id } = request.params;
|
|
325
|
+
const tenantId = getTenantId(request);
|
|
304
326
|
const storeLattice = getStoreLattice("default", "assistant");
|
|
305
327
|
const assistantStore = storeLattice.store;
|
|
306
|
-
let assistant = await assistantStore.getAssistantById(id);
|
|
328
|
+
let assistant = await assistantStore.getAssistantById(tenantId, id);
|
|
307
329
|
if (!assistant) {
|
|
308
|
-
const
|
|
309
|
-
const agentConfig = agentConfigs.find((config) => config.key === id);
|
|
330
|
+
const agentConfig = await agentLatticeManager2.getAgentConfigWithTenant(tenantId, id);
|
|
310
331
|
if (agentConfig) {
|
|
311
332
|
assistant = convertAgentConfigToAssistant(agentConfig);
|
|
312
333
|
}
|
|
@@ -323,20 +344,20 @@ async function getAssistant(request, reply) {
|
|
|
323
344
|
data: assistant
|
|
324
345
|
};
|
|
325
346
|
}
|
|
326
|
-
async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
347
|
+
async function upsertAssistant(tenantId, id, data, reply, requireFields = false) {
|
|
327
348
|
const storeLattice = getStoreLattice("default", "assistant");
|
|
328
349
|
const assistantStore = storeLattice.store;
|
|
329
|
-
const exists = await assistantStore.hasAssistant(id);
|
|
350
|
+
const exists = await assistantStore.hasAssistant(tenantId, id);
|
|
330
351
|
let assistant;
|
|
331
352
|
if (exists) {
|
|
332
|
-
assistant = await assistantStore.updateAssistant(id, data);
|
|
353
|
+
assistant = await assistantStore.updateAssistant(tenantId, id, data);
|
|
333
354
|
if (!assistant) {
|
|
334
355
|
return reply.status(500).send({
|
|
335
356
|
success: false,
|
|
336
357
|
message: "Failed to update assistant"
|
|
337
358
|
});
|
|
338
359
|
}
|
|
339
|
-
eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name });
|
|
360
|
+
eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name, tenantId });
|
|
340
361
|
return {
|
|
341
362
|
success: true,
|
|
342
363
|
message: "Updated assistant",
|
|
@@ -352,8 +373,8 @@ async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
|
352
373
|
});
|
|
353
374
|
}
|
|
354
375
|
}
|
|
355
|
-
assistant = await assistantStore.createAssistant(id, data);
|
|
356
|
-
eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name });
|
|
376
|
+
assistant = await assistantStore.createAssistant(tenantId, id, data);
|
|
377
|
+
eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name, tenantId });
|
|
357
378
|
return reply.status(201).send({
|
|
358
379
|
success: true,
|
|
359
380
|
message: "Created assistant",
|
|
@@ -361,6 +382,7 @@ async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
|
361
382
|
});
|
|
362
383
|
}
|
|
363
384
|
async function createAssistant(request, reply) {
|
|
385
|
+
const tenantId = getTenantId(request);
|
|
364
386
|
const data = request.body;
|
|
365
387
|
if (!data.name || !data.graphDefinition) {
|
|
366
388
|
return reply.status(400).send({
|
|
@@ -369,49 +391,51 @@ async function createAssistant(request, reply) {
|
|
|
369
391
|
});
|
|
370
392
|
}
|
|
371
393
|
const id = data.id ?? randomUUID();
|
|
372
|
-
return upsertAssistant(id, data, reply, true);
|
|
394
|
+
return upsertAssistant(tenantId, id, data, reply, true);
|
|
373
395
|
}
|
|
374
396
|
async function updateAssistant(request, reply) {
|
|
397
|
+
const tenantId = getTenantId(request);
|
|
375
398
|
const { id } = request.params;
|
|
376
399
|
const updates = request.body;
|
|
377
|
-
return upsertAssistant(id, updates, reply, false);
|
|
400
|
+
return upsertAssistant(tenantId, id, updates, reply, false);
|
|
378
401
|
}
|
|
379
402
|
async function deleteAssistant(request, reply) {
|
|
403
|
+
const tenantId = getTenantId(request);
|
|
380
404
|
const { id } = request.params;
|
|
381
405
|
const storeLattice = getStoreLattice("default", "assistant");
|
|
382
406
|
const assistantStore = storeLattice.store;
|
|
383
|
-
const
|
|
384
|
-
const isCodeConfigured =
|
|
407
|
+
const agentConfig = await agentLatticeManager2.getAgentConfigWithTenant(tenantId, id);
|
|
408
|
+
const isCodeConfigured = !!agentConfig;
|
|
385
409
|
if (isCodeConfigured) {
|
|
386
|
-
const exists2 = await assistantStore.hasAssistant(id);
|
|
410
|
+
const exists2 = await assistantStore.hasAssistant(tenantId, id);
|
|
387
411
|
if (!exists2) {
|
|
388
412
|
return reply.status(404).send({
|
|
389
413
|
success: false,
|
|
390
414
|
message: "Assistant not found (code-configured assistants cannot be deleted from code, only from store)"
|
|
391
415
|
});
|
|
392
416
|
}
|
|
393
|
-
await assistantStore.deleteAssistant(id);
|
|
394
|
-
eventBus.publish("assistant:deleted", { id });
|
|
417
|
+
await assistantStore.deleteAssistant(tenantId, id);
|
|
418
|
+
eventBus.publish("assistant:deleted", { id, tenantId });
|
|
395
419
|
return {
|
|
396
420
|
success: true,
|
|
397
421
|
message: "Deleted assistant from store (code-configured registration remains)"
|
|
398
422
|
};
|
|
399
423
|
}
|
|
400
|
-
const exists = await assistantStore.hasAssistant(id);
|
|
424
|
+
const exists = await assistantStore.hasAssistant(tenantId, id);
|
|
401
425
|
if (!exists) {
|
|
402
426
|
return reply.status(404).send({
|
|
403
427
|
success: false,
|
|
404
428
|
message: "Assistant not found"
|
|
405
429
|
});
|
|
406
430
|
}
|
|
407
|
-
const deleted = await assistantStore.deleteAssistant(id);
|
|
431
|
+
const deleted = await assistantStore.deleteAssistant(tenantId, id);
|
|
408
432
|
if (!deleted) {
|
|
409
433
|
return reply.status(500).send({
|
|
410
434
|
success: false,
|
|
411
435
|
message: "Failed to delete assistant"
|
|
412
436
|
});
|
|
413
437
|
}
|
|
414
|
-
eventBus.publish("assistant:deleted", { id });
|
|
438
|
+
eventBus.publish("assistant:deleted", { id, tenantId });
|
|
415
439
|
return {
|
|
416
440
|
success: true,
|
|
417
441
|
message: "Successfully deleted assistant"
|
|
@@ -420,7 +444,8 @@ async function deleteAssistant(request, reply) {
|
|
|
420
444
|
var getAgentGraph = async (request, reply) => {
|
|
421
445
|
try {
|
|
422
446
|
const { assistantId } = request.params;
|
|
423
|
-
const
|
|
447
|
+
const tenant_id = getTenantId(request);
|
|
448
|
+
const imageData = await draw_graph(assistantId, tenant_id);
|
|
424
449
|
reply.header("Content-Type", "application/json").send({
|
|
425
450
|
image: imageData
|
|
426
451
|
});
|
|
@@ -457,6 +482,14 @@ var createRun = async (request, reply) => {
|
|
|
457
482
|
return;
|
|
458
483
|
}
|
|
459
484
|
if (streaming) {
|
|
485
|
+
const agentExists = await checkAgentExists(tenant_id, assistant_id);
|
|
486
|
+
if (!agentExists) {
|
|
487
|
+
reply.status(404).send({
|
|
488
|
+
success: false,
|
|
489
|
+
error: `Agent ${assistant_id} not found for tenant ${tenant_id}`
|
|
490
|
+
});
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
460
493
|
const stream = await agent_stream({
|
|
461
494
|
assistant_id,
|
|
462
495
|
input,
|
|
@@ -476,13 +509,27 @@ var createRun = async (request, reply) => {
|
|
|
476
509
|
"Access-Control-Allow-Origin": "*"
|
|
477
510
|
});
|
|
478
511
|
try {
|
|
512
|
+
let chunkCount = 0;
|
|
479
513
|
for await (const chunk of stream) {
|
|
480
|
-
|
|
514
|
+
chunkCount++;
|
|
515
|
+
const success = reply.raw.write(`data: ${JSON.stringify(chunk)}
|
|
481
516
|
|
|
482
517
|
`);
|
|
518
|
+
if (!success) {
|
|
519
|
+
await new Promise((resolve) => reply.raw.once("drain", resolve));
|
|
520
|
+
}
|
|
483
521
|
}
|
|
484
522
|
} catch (error) {
|
|
485
|
-
|
|
523
|
+
const errorEvent = {
|
|
524
|
+
type: "error",
|
|
525
|
+
data: {
|
|
526
|
+
id: v42(),
|
|
527
|
+
content: error.message || "Stream processing error"
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
reply.raw.write(`data: ${JSON.stringify(errorEvent)}
|
|
531
|
+
|
|
532
|
+
`);
|
|
486
533
|
} finally {
|
|
487
534
|
reply.raw.end();
|
|
488
535
|
}
|
|
@@ -537,7 +584,16 @@ var resumeStream = async (request, reply) => {
|
|
|
537
584
|
`);
|
|
538
585
|
}
|
|
539
586
|
} catch (error) {
|
|
540
|
-
|
|
587
|
+
const errorEvent = {
|
|
588
|
+
type: "error",
|
|
589
|
+
data: {
|
|
590
|
+
id: v42(),
|
|
591
|
+
content: error.message || "Resume stream processing error"
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
reply.raw.write(`data: ${JSON.stringify(errorEvent)}
|
|
595
|
+
|
|
596
|
+
`);
|
|
541
597
|
} finally {
|
|
542
598
|
reply.raw.end();
|
|
543
599
|
}
|
|
@@ -648,9 +704,11 @@ var getAgentState = async (request, reply) => {
|
|
|
648
704
|
});
|
|
649
705
|
return;
|
|
650
706
|
}
|
|
707
|
+
const tenant_id = request.headers["x-tenant-id"];
|
|
651
708
|
const result = await agent_state({
|
|
652
709
|
assistant_id: assistantId,
|
|
653
|
-
thread_id
|
|
710
|
+
thread_id,
|
|
711
|
+
tenant_id
|
|
654
712
|
});
|
|
655
713
|
if (!result) {
|
|
656
714
|
reply.status(500).send(result);
|
|
@@ -750,11 +808,19 @@ var triggerAgentTask = async (request, reply) => {
|
|
|
750
808
|
// src/controllers/threads.ts
|
|
751
809
|
import { getStoreLattice as getStoreLattice2 } from "@axiom-lattice/core";
|
|
752
810
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
811
|
+
function getTenantId2(request) {
|
|
812
|
+
const userTenantId = request.user?.tenantId;
|
|
813
|
+
if (userTenantId) {
|
|
814
|
+
return userTenantId;
|
|
815
|
+
}
|
|
816
|
+
return request.headers["x-tenant-id"] || "default";
|
|
817
|
+
}
|
|
753
818
|
async function getThreadList(request, reply) {
|
|
819
|
+
const tenantId = getTenantId2(request);
|
|
754
820
|
const { assistantId } = request.params;
|
|
755
821
|
const storeLattice = getStoreLattice2("default", "thread");
|
|
756
822
|
const threadStore = storeLattice.store;
|
|
757
|
-
const threads = await threadStore.getThreadsByAssistantId(assistantId);
|
|
823
|
+
const threads = await threadStore.getThreadsByAssistantId(tenantId, assistantId);
|
|
758
824
|
return {
|
|
759
825
|
success: true,
|
|
760
826
|
message: "Successfully retrieved thread list",
|
|
@@ -765,10 +831,11 @@ async function getThreadList(request, reply) {
|
|
|
765
831
|
};
|
|
766
832
|
}
|
|
767
833
|
async function getThread(request, reply) {
|
|
768
|
-
const
|
|
834
|
+
const tenantId = getTenantId2(request);
|
|
835
|
+
const { threadId } = request.params;
|
|
769
836
|
const storeLattice = getStoreLattice2("default", "thread");
|
|
770
837
|
const threadStore = storeLattice.store;
|
|
771
|
-
const thread = await threadStore.getThreadById(
|
|
838
|
+
const thread = await threadStore.getThreadById(tenantId, threadId);
|
|
772
839
|
if (!thread) {
|
|
773
840
|
return reply.status(404).send({
|
|
774
841
|
success: false,
|
|
@@ -782,12 +849,13 @@ async function getThread(request, reply) {
|
|
|
782
849
|
};
|
|
783
850
|
}
|
|
784
851
|
async function createThread(request, reply) {
|
|
852
|
+
const tenantId = getTenantId2(request);
|
|
785
853
|
const { assistantId } = request.params;
|
|
786
854
|
const data = request.body;
|
|
787
855
|
const threadId = randomUUID2();
|
|
788
856
|
const storeLattice = getStoreLattice2("default", "thread");
|
|
789
857
|
const threadStore = storeLattice.store;
|
|
790
|
-
const newThread = await threadStore.createThread(assistantId, threadId, data);
|
|
858
|
+
const newThread = await threadStore.createThread(tenantId, assistantId, threadId, data);
|
|
791
859
|
return reply.status(201).send({
|
|
792
860
|
success: true,
|
|
793
861
|
message: "Successfully created thread",
|
|
@@ -795,11 +863,12 @@ async function createThread(request, reply) {
|
|
|
795
863
|
});
|
|
796
864
|
}
|
|
797
865
|
async function updateThread(request, reply) {
|
|
798
|
-
const
|
|
866
|
+
const tenantId = getTenantId2(request);
|
|
867
|
+
const { threadId } = request.params;
|
|
799
868
|
const updates = request.body;
|
|
800
869
|
const storeLattice = getStoreLattice2("default", "thread");
|
|
801
870
|
const threadStore = storeLattice.store;
|
|
802
|
-
const exists = await threadStore.hasThread(
|
|
871
|
+
const exists = await threadStore.hasThread(tenantId, threadId);
|
|
803
872
|
if (!exists) {
|
|
804
873
|
return reply.status(404).send({
|
|
805
874
|
success: false,
|
|
@@ -807,7 +876,7 @@ async function updateThread(request, reply) {
|
|
|
807
876
|
});
|
|
808
877
|
}
|
|
809
878
|
const updatedThread = await threadStore.updateThread(
|
|
810
|
-
|
|
879
|
+
tenantId,
|
|
811
880
|
threadId,
|
|
812
881
|
updates
|
|
813
882
|
);
|
|
@@ -824,17 +893,18 @@ async function updateThread(request, reply) {
|
|
|
824
893
|
};
|
|
825
894
|
}
|
|
826
895
|
async function deleteThread(request, reply) {
|
|
827
|
-
const
|
|
896
|
+
const tenantId = getTenantId2(request);
|
|
897
|
+
const { threadId } = request.params;
|
|
828
898
|
const storeLattice = getStoreLattice2("default", "thread");
|
|
829
899
|
const threadStore = storeLattice.store;
|
|
830
|
-
const exists = await threadStore.hasThread(
|
|
900
|
+
const exists = await threadStore.hasThread(tenantId, threadId);
|
|
831
901
|
if (!exists) {
|
|
832
902
|
return reply.status(404).send({
|
|
833
903
|
success: false,
|
|
834
904
|
message: "Thread not found"
|
|
835
905
|
});
|
|
836
906
|
}
|
|
837
|
-
const deleted = await threadStore.deleteThread(
|
|
907
|
+
const deleted = await threadStore.deleteThread(tenantId, threadId);
|
|
838
908
|
if (!deleted) {
|
|
839
909
|
return reply.status(500).send({
|
|
840
910
|
success: false,
|
|
@@ -849,6 +919,13 @@ async function deleteThread(request, reply) {
|
|
|
849
919
|
|
|
850
920
|
// src/controllers/schedules.ts
|
|
851
921
|
import { scheduleLatticeManager } from "@axiom-lattice/core";
|
|
922
|
+
function getTenantId3(request) {
|
|
923
|
+
const userTenantId = request.user?.tenantId;
|
|
924
|
+
if (userTenantId) {
|
|
925
|
+
return userTenantId;
|
|
926
|
+
}
|
|
927
|
+
return request.headers["x-tenant-id"] || "default";
|
|
928
|
+
}
|
|
852
929
|
function getScheduleLattice() {
|
|
853
930
|
const keys = scheduleLatticeManager.getLatticeKeys();
|
|
854
931
|
if (keys.length === 0) {
|
|
@@ -885,7 +962,9 @@ async function getThreadSchedules(request, reply) {
|
|
|
885
962
|
}
|
|
886
963
|
};
|
|
887
964
|
}
|
|
965
|
+
const tenantId = getTenantId3(request);
|
|
888
966
|
const filters = {
|
|
967
|
+
tenantId,
|
|
889
968
|
threadId,
|
|
890
969
|
assistantId
|
|
891
970
|
};
|
|
@@ -900,6 +979,7 @@ async function getThreadSchedules(request, reply) {
|
|
|
900
979
|
}
|
|
901
980
|
const tasks = await storage.getAllTasks(filters);
|
|
902
981
|
const total = await storage.countTasks({
|
|
982
|
+
tenantId,
|
|
903
983
|
threadId,
|
|
904
984
|
assistantId,
|
|
905
985
|
status
|
|
@@ -1362,6 +1442,13 @@ async function getHealth(request, reply) {
|
|
|
1362
1442
|
// src/controllers/skills.ts
|
|
1363
1443
|
import { getStoreLattice as getStoreLattice3 } from "@axiom-lattice/core";
|
|
1364
1444
|
import { validateSkillName } from "@axiom-lattice/core";
|
|
1445
|
+
function getTenantId4(request) {
|
|
1446
|
+
const userTenantId = request.user?.tenantId;
|
|
1447
|
+
if (userTenantId) {
|
|
1448
|
+
return userTenantId;
|
|
1449
|
+
}
|
|
1450
|
+
return request.headers["x-tenant-id"] || "default";
|
|
1451
|
+
}
|
|
1365
1452
|
function serializeSkill(skill) {
|
|
1366
1453
|
const serialized = {
|
|
1367
1454
|
id: skill.id,
|
|
@@ -1384,9 +1471,10 @@ function serializeSkill(skill) {
|
|
|
1384
1471
|
}
|
|
1385
1472
|
async function getSkillList(request, reply) {
|
|
1386
1473
|
try {
|
|
1474
|
+
const tenantId = getTenantId4(request);
|
|
1387
1475
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1388
1476
|
const skillStore = storeLattice.store;
|
|
1389
|
-
const skills = await skillStore.getAllSkills();
|
|
1477
|
+
const skills = await skillStore.getAllSkills(tenantId);
|
|
1390
1478
|
const serializedSkills = skills.map(serializeSkill);
|
|
1391
1479
|
return {
|
|
1392
1480
|
success: true,
|
|
@@ -1409,10 +1497,11 @@ async function getSkillList(request, reply) {
|
|
|
1409
1497
|
}
|
|
1410
1498
|
async function getSkill(request, reply) {
|
|
1411
1499
|
try {
|
|
1500
|
+
const tenantId = getTenantId4(request);
|
|
1412
1501
|
const { id } = request.params;
|
|
1413
1502
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1414
1503
|
const skillStore = storeLattice.store;
|
|
1415
|
-
const skill = await skillStore.getSkillById(id);
|
|
1504
|
+
const skill = await skillStore.getSkillById(tenantId, id);
|
|
1416
1505
|
if (!skill) {
|
|
1417
1506
|
return reply.status(404).send({
|
|
1418
1507
|
success: false,
|
|
@@ -1461,16 +1550,17 @@ async function createSkill(request, reply) {
|
|
|
1461
1550
|
message: `id "${id}" must equal name "${data.name}" (name is used for path addressing)`
|
|
1462
1551
|
});
|
|
1463
1552
|
}
|
|
1553
|
+
const tenantId = getTenantId4(request);
|
|
1464
1554
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1465
1555
|
const skillStore = storeLattice.store;
|
|
1466
|
-
const exists = await skillStore.hasSkill(id);
|
|
1556
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1467
1557
|
if (exists) {
|
|
1468
1558
|
return reply.status(409).send({
|
|
1469
1559
|
success: false,
|
|
1470
1560
|
message: `Skill with id "${id}" already exists`
|
|
1471
1561
|
});
|
|
1472
1562
|
}
|
|
1473
|
-
const newSkill = await skillStore.createSkill(id, data);
|
|
1563
|
+
const newSkill = await skillStore.createSkill(tenantId, id, data);
|
|
1474
1564
|
return reply.status(201).send({
|
|
1475
1565
|
success: true,
|
|
1476
1566
|
message: "Successfully created skill",
|
|
@@ -1497,16 +1587,17 @@ async function updateSkill(request, reply) {
|
|
|
1497
1587
|
});
|
|
1498
1588
|
}
|
|
1499
1589
|
}
|
|
1590
|
+
const tenantId = getTenantId4(request);
|
|
1500
1591
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1501
1592
|
const skillStore = storeLattice.store;
|
|
1502
|
-
const exists = await skillStore.hasSkill(id);
|
|
1593
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1503
1594
|
if (!exists) {
|
|
1504
1595
|
return reply.status(404).send({
|
|
1505
1596
|
success: false,
|
|
1506
1597
|
message: "Skill not found"
|
|
1507
1598
|
});
|
|
1508
1599
|
}
|
|
1509
|
-
const updatedSkill = await skillStore.updateSkill(id, updates);
|
|
1600
|
+
const updatedSkill = await skillStore.updateSkill(tenantId, id, updates);
|
|
1510
1601
|
if (!updatedSkill) {
|
|
1511
1602
|
return reply.status(500).send({
|
|
1512
1603
|
success: false,
|
|
@@ -1528,16 +1619,17 @@ async function updateSkill(request, reply) {
|
|
|
1528
1619
|
async function deleteSkill(request, reply) {
|
|
1529
1620
|
try {
|
|
1530
1621
|
const { id } = request.params;
|
|
1622
|
+
const tenantId = getTenantId4(request);
|
|
1531
1623
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1532
1624
|
const skillStore = storeLattice.store;
|
|
1533
|
-
const exists = await skillStore.hasSkill(id);
|
|
1625
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1534
1626
|
if (!exists) {
|
|
1535
1627
|
return reply.status(404).send({
|
|
1536
1628
|
success: false,
|
|
1537
1629
|
message: "Skill not found"
|
|
1538
1630
|
});
|
|
1539
1631
|
}
|
|
1540
|
-
const deleted = await skillStore.deleteSkill(id);
|
|
1632
|
+
const deleted = await skillStore.deleteSkill(tenantId, id);
|
|
1541
1633
|
if (!deleted) {
|
|
1542
1634
|
return reply.status(500).send({
|
|
1543
1635
|
success: false,
|
|
@@ -1568,9 +1660,10 @@ async function searchSkillsByMetadata(request, reply) {
|
|
|
1568
1660
|
}
|
|
1569
1661
|
});
|
|
1570
1662
|
}
|
|
1663
|
+
const tenantId = getTenantId4(request);
|
|
1571
1664
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1572
1665
|
const skillStore = storeLattice.store;
|
|
1573
|
-
const skills = await skillStore.searchByMetadata(key, value);
|
|
1666
|
+
const skills = await skillStore.searchByMetadata(tenantId, key, value);
|
|
1574
1667
|
const serializedSkills = skills.map(serializeSkill);
|
|
1575
1668
|
return {
|
|
1576
1669
|
success: true,
|
|
@@ -1604,9 +1697,10 @@ async function filterSkillsByCompatibility(request, reply) {
|
|
|
1604
1697
|
}
|
|
1605
1698
|
});
|
|
1606
1699
|
}
|
|
1700
|
+
const tenantId = getTenantId4(request);
|
|
1607
1701
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1608
1702
|
const skillStore = storeLattice.store;
|
|
1609
|
-
const skills = await skillStore.filterByCompatibility(compatibility);
|
|
1703
|
+
const skills = await skillStore.filterByCompatibility(tenantId, compatibility);
|
|
1610
1704
|
const serializedSkills = skills.map(serializeSkill);
|
|
1611
1705
|
return {
|
|
1612
1706
|
success: true,
|
|
@@ -1640,9 +1734,10 @@ async function filterSkillsByLicense(request, reply) {
|
|
|
1640
1734
|
}
|
|
1641
1735
|
});
|
|
1642
1736
|
}
|
|
1737
|
+
const tenantId = getTenantId4(request);
|
|
1643
1738
|
const storeLattice = getStoreLattice3("default", "skill");
|
|
1644
1739
|
const skillStore = storeLattice.store;
|
|
1645
|
-
const skills = await skillStore.filterByLicense(license);
|
|
1740
|
+
const skills = await skillStore.filterByLicense(tenantId, license);
|
|
1646
1741
|
const serializedSkills = skills.map(serializeSkill);
|
|
1647
1742
|
return {
|
|
1648
1743
|
success: true,
|
|
@@ -1665,7 +1760,7 @@ async function filterSkillsByLicense(request, reply) {
|
|
|
1665
1760
|
}
|
|
1666
1761
|
|
|
1667
1762
|
// src/controllers/tools.ts
|
|
1668
|
-
import {
|
|
1763
|
+
import { toolLatticeManager } from "@axiom-lattice/core";
|
|
1669
1764
|
function serializeSchema(schema) {
|
|
1670
1765
|
if (!schema) {
|
|
1671
1766
|
return void 0;
|
|
@@ -2021,7 +2116,7 @@ var getHealthSchema = {
|
|
|
2021
2116
|
import { Readable } from "stream";
|
|
2022
2117
|
|
|
2023
2118
|
// src/services/sandbox_service.ts
|
|
2024
|
-
import {
|
|
2119
|
+
import { agentLatticeManager as agentLatticeManager3, getSandBoxManager, normalizeSandboxName } from "@axiom-lattice/core";
|
|
2025
2120
|
var ERROR_HTML = `<!DOCTYPE html>
|
|
2026
2121
|
<html lang="zh-CN">
|
|
2027
2122
|
<head>
|
|
@@ -2132,17 +2227,17 @@ var ERROR_HTML = `<!DOCTYPE html>
|
|
|
2132
2227
|
</body>
|
|
2133
2228
|
</html>`;
|
|
2134
2229
|
var SandboxService = class {
|
|
2135
|
-
getFilesystemIsolatedLevel(assistantId) {
|
|
2136
|
-
const
|
|
2137
|
-
if (!
|
|
2230
|
+
getFilesystemIsolatedLevel(tenantId, assistantId) {
|
|
2231
|
+
const agentLattice = agentLatticeManager3.getAgentLatticeWithTenant(tenantId, assistantId);
|
|
2232
|
+
if (!agentLattice) {
|
|
2138
2233
|
return null;
|
|
2139
2234
|
}
|
|
2140
|
-
const agentLattice = getAgentLattice2(assistantId);
|
|
2141
2235
|
const filesystemConfig = agentLattice?.config?.middleware?.find((m) => m.type === "filesystem");
|
|
2142
2236
|
if (!filesystemConfig) {
|
|
2143
2237
|
return null;
|
|
2144
2238
|
}
|
|
2145
|
-
|
|
2239
|
+
const config = filesystemConfig.config;
|
|
2240
|
+
return config?.isolatedLevel || null;
|
|
2146
2241
|
}
|
|
2147
2242
|
computeSandboxName(assistantId, threadId, isolatedLevel) {
|
|
2148
2243
|
let sandboxName;
|
|
@@ -2161,7 +2256,7 @@ var SandboxService = class {
|
|
|
2161
2256
|
return normalizeSandboxName(sandboxName);
|
|
2162
2257
|
}
|
|
2163
2258
|
getTargetUrl(sandboxName) {
|
|
2164
|
-
const sandboxManager = getSandBoxManager(
|
|
2259
|
+
const sandboxManager = getSandBoxManager();
|
|
2165
2260
|
return `${sandboxManager.getBaseURL()}/sandbox/${sandboxName}`;
|
|
2166
2261
|
}
|
|
2167
2262
|
async getVncHtml(sandboxName) {
|
|
@@ -2238,7 +2333,8 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2238
2333
|
async (request, reply) => {
|
|
2239
2334
|
console.log("[Sandbox Upload] Route matched:", request.url);
|
|
2240
2335
|
const { assistantId, threadId } = request.params;
|
|
2241
|
-
const
|
|
2336
|
+
const tenantId = request.headers["x-tenant-id"] || "default";
|
|
2337
|
+
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(tenantId, assistantId);
|
|
2242
2338
|
if (!isolatedLevel) {
|
|
2243
2339
|
return reply.status(500).send({ error: "Assistant sandbox config not found" });
|
|
2244
2340
|
}
|
|
@@ -2247,7 +2343,7 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2247
2343
|
threadId,
|
|
2248
2344
|
isolatedLevel
|
|
2249
2345
|
);
|
|
2250
|
-
const sandboxManager = getSandBoxManager2(
|
|
2346
|
+
const sandboxManager = getSandBoxManager2();
|
|
2251
2347
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2252
2348
|
try {
|
|
2253
2349
|
const data = await request.file();
|
|
@@ -2281,10 +2377,11 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2281
2377
|
async (request, reply) => {
|
|
2282
2378
|
const { assistantId, threadId } = request.params;
|
|
2283
2379
|
const { path: filePath } = request.query;
|
|
2380
|
+
const tenantId = request.headers["x-tenant-id"] || "default";
|
|
2284
2381
|
if (!filePath || typeof filePath !== "string") {
|
|
2285
2382
|
return reply.status(400).send({ error: "Query parameter 'path' is required" });
|
|
2286
2383
|
}
|
|
2287
|
-
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(assistantId);
|
|
2384
|
+
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(tenantId, assistantId);
|
|
2288
2385
|
if (!isolatedLevel) {
|
|
2289
2386
|
return reply.status(500).send({ error: "Assistant filesystem isolated level not found" });
|
|
2290
2387
|
}
|
|
@@ -2293,7 +2390,7 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2293
2390
|
threadId,
|
|
2294
2391
|
isolatedLevel
|
|
2295
2392
|
);
|
|
2296
|
-
const sandboxManager = getSandBoxManager2(
|
|
2393
|
+
const sandboxManager = getSandBoxManager2();
|
|
2297
2394
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2298
2395
|
try {
|
|
2299
2396
|
const resolvedPath = filePath.startsWith("/home/gem") ? filePath : `/home/gem/${filePath.replace(/^\//, "")}`;
|
|
@@ -2349,16 +2446,24 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2349
2446
|
import * as fs from "fs/promises";
|
|
2350
2447
|
import * as path from "path";
|
|
2351
2448
|
import { Readable as Readable2 } from "stream";
|
|
2352
|
-
import { getStoreLattice as
|
|
2449
|
+
import { getStoreLattice as getStoreLattice4 } from "@axiom-lattice/core";
|
|
2353
2450
|
import { SandboxFilesystem, FilesystemBackend } from "@axiom-lattice/core";
|
|
2354
2451
|
import { getSandBoxManager as getSandBoxManager3 } from "@axiom-lattice/core";
|
|
2355
2452
|
import { v4 as uuidv4 } from "uuid";
|
|
2356
2453
|
var WorkspaceController = class {
|
|
2357
2454
|
constructor() {
|
|
2358
|
-
this.workspaceStore =
|
|
2359
|
-
this.projectStore =
|
|
2455
|
+
this.workspaceStore = getStoreLattice4("default", "workspace").store;
|
|
2456
|
+
this.projectStore = getStoreLattice4("default", "project").store;
|
|
2360
2457
|
}
|
|
2361
2458
|
getTenantId(request) {
|
|
2459
|
+
const userTenantId = request.user?.tenantId;
|
|
2460
|
+
if (userTenantId) {
|
|
2461
|
+
return userTenantId;
|
|
2462
|
+
}
|
|
2463
|
+
const queryTenantId = request.query?.tenantId;
|
|
2464
|
+
if (queryTenantId) {
|
|
2465
|
+
return String(queryTenantId);
|
|
2466
|
+
}
|
|
2362
2467
|
return request.headers["x-tenant-id"] || "default";
|
|
2363
2468
|
}
|
|
2364
2469
|
// ==================== Workspace CRUD ====================
|
|
@@ -2472,8 +2577,7 @@ var WorkspaceController = class {
|
|
|
2472
2577
|
return { success: true };
|
|
2473
2578
|
}
|
|
2474
2579
|
// ==================== File Operations ====================
|
|
2475
|
-
async getBackend(workspaceId, projectId) {
|
|
2476
|
-
const tenantId = "default";
|
|
2580
|
+
async getBackend(tenantId, workspaceId, projectId) {
|
|
2477
2581
|
const workspace = await this.workspaceStore.getWorkspaceById(
|
|
2478
2582
|
tenantId,
|
|
2479
2583
|
workspaceId
|
|
@@ -2482,18 +2586,24 @@ var WorkspaceController = class {
|
|
|
2482
2586
|
throw new Error("Workspace not found");
|
|
2483
2587
|
}
|
|
2484
2588
|
if (workspace.storageType === "sandbox") {
|
|
2485
|
-
const sandboxManager = getSandBoxManager3(
|
|
2589
|
+
const sandboxManager = getSandBoxManager3();
|
|
2486
2590
|
const sandboxName = "global";
|
|
2487
2591
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2488
|
-
return {
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2592
|
+
return {
|
|
2593
|
+
backend: new SandboxFilesystem({
|
|
2594
|
+
sandboxInstance: sandbox,
|
|
2595
|
+
workingDirectory: `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`
|
|
2596
|
+
}),
|
|
2597
|
+
workspace
|
|
2598
|
+
};
|
|
2492
2599
|
} else {
|
|
2493
|
-
return {
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2600
|
+
return {
|
|
2601
|
+
backend: new FilesystemBackend({
|
|
2602
|
+
rootDir: `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`,
|
|
2603
|
+
virtualMode: true
|
|
2604
|
+
}),
|
|
2605
|
+
workspace
|
|
2606
|
+
};
|
|
2497
2607
|
}
|
|
2498
2608
|
}
|
|
2499
2609
|
getFilenameFromPath(filePath) {
|
|
@@ -2523,18 +2633,19 @@ var WorkspaceController = class {
|
|
|
2523
2633
|
return mimeTypes[ext] || "application/octet-stream";
|
|
2524
2634
|
}
|
|
2525
2635
|
async downloadFile(request, reply) {
|
|
2636
|
+
const tenantId = this.getTenantId(request);
|
|
2526
2637
|
const { workspaceId, projectId } = request.params;
|
|
2527
2638
|
const filePath = request.query.path;
|
|
2528
2639
|
if (!filePath) {
|
|
2529
2640
|
return reply.status(400).send({ success: false, error: "Path is required" });
|
|
2530
2641
|
}
|
|
2531
2642
|
try {
|
|
2532
|
-
const { workspace } = await this.getBackend(workspaceId, projectId);
|
|
2643
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2533
2644
|
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
2534
2645
|
if (workspace.storageType === "sandbox") {
|
|
2535
|
-
const sandboxManager = getSandBoxManager3(
|
|
2646
|
+
const sandboxManager = getSandBoxManager3();
|
|
2536
2647
|
const sandbox = await sandboxManager.createSandbox("global");
|
|
2537
|
-
const realPath = path.join("/home/gem/workspaces", workspaceId, projectId, resolvedPath);
|
|
2648
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
2538
2649
|
const filename2 = this.getFilenameFromPath(resolvedPath);
|
|
2539
2650
|
const inferredContentType = this.getMimeType(filename2);
|
|
2540
2651
|
const downloadResult = await sandbox.file.downloadFile({
|
|
@@ -2551,13 +2662,13 @@ var WorkspaceController = class {
|
|
|
2551
2662
|
const webStream = body.stream();
|
|
2552
2663
|
const nodeStream = Readable2.fromWeb(webStream);
|
|
2553
2664
|
const contentType2 = body.contentType ?? inferredContentType;
|
|
2554
|
-
const contentDisposition2 = body.contentDisposition ?? `
|
|
2665
|
+
const contentDisposition2 = body.contentDisposition ?? `attachment; filename*=UTF-8''${encodeURIComponent(filename2)}`;
|
|
2555
2666
|
return reply.status(200).type(contentType2).header("Content-Disposition", contentDisposition2).send(nodeStream);
|
|
2556
2667
|
}
|
|
2557
2668
|
const bodyUnknown = downloadResult.body;
|
|
2558
2669
|
let buf;
|
|
2559
2670
|
let contentType = inferredContentType;
|
|
2560
|
-
let contentDisposition = `
|
|
2671
|
+
let contentDisposition = `attachment; filename*=UTF-8''${encodeURIComponent(filename2)}`;
|
|
2561
2672
|
if (bodyUnknown instanceof ArrayBuffer) {
|
|
2562
2673
|
buf = Buffer.from(bodyUnknown);
|
|
2563
2674
|
} else if (bodyUnknown instanceof Buffer) {
|
|
@@ -2575,28 +2686,96 @@ var WorkspaceController = class {
|
|
|
2575
2686
|
}
|
|
2576
2687
|
return reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(buf);
|
|
2577
2688
|
}
|
|
2578
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2689
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2579
2690
|
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
2580
2691
|
const filename = this.getFilenameFromPath(resolvedPath);
|
|
2581
2692
|
const mimeType = this.getMimeType(filename);
|
|
2582
2693
|
const buffer = Buffer.from(content, "utf-8");
|
|
2583
|
-
return reply.status(200).type(mimeType).header("Content-Disposition", `
|
|
2694
|
+
return reply.status(200).type(mimeType).header("Content-Disposition", `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`).send(buffer);
|
|
2584
2695
|
} catch (error) {
|
|
2585
2696
|
const message = error instanceof Error ? error.message : String(error);
|
|
2586
2697
|
return reply.status(502).send({ success: false, error: `Download proxy error: ${message}` });
|
|
2587
2698
|
}
|
|
2588
2699
|
}
|
|
2700
|
+
/**
|
|
2701
|
+
* View a file inline in the browser (not download).
|
|
2702
|
+
* Returns file content with inline Content-Disposition for preview.
|
|
2703
|
+
*/
|
|
2704
|
+
async viewFile(request, reply) {
|
|
2705
|
+
const tenantId = this.getTenantId(request);
|
|
2706
|
+
const { workspaceId, projectId } = request.params;
|
|
2707
|
+
const filePath = request.query.path;
|
|
2708
|
+
if (!filePath) {
|
|
2709
|
+
return reply.status(400).send({ success: false, error: "Path is required" });
|
|
2710
|
+
}
|
|
2711
|
+
try {
|
|
2712
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2713
|
+
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
2714
|
+
if (workspace.storageType === "sandbox") {
|
|
2715
|
+
const sandboxManager = getSandBoxManager3();
|
|
2716
|
+
const sandbox = await sandboxManager.createSandbox("global");
|
|
2717
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
2718
|
+
const filename2 = this.getFilenameFromPath(resolvedPath);
|
|
2719
|
+
const inferredContentType = this.getMimeType(filename2);
|
|
2720
|
+
const downloadResult = await sandbox.file.downloadFile({
|
|
2721
|
+
path: realPath
|
|
2722
|
+
});
|
|
2723
|
+
if (!downloadResult.ok) {
|
|
2724
|
+
return reply.status(502).send({
|
|
2725
|
+
success: false,
|
|
2726
|
+
error: `View error: ${JSON.stringify(downloadResult.error)}`
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2729
|
+
const body = downloadResult.body;
|
|
2730
|
+
if (typeof body?.stream === "function") {
|
|
2731
|
+
const webStream = body.stream();
|
|
2732
|
+
const nodeStream = Readable2.fromWeb(webStream);
|
|
2733
|
+
const contentType2 = body.contentType ?? inferredContentType;
|
|
2734
|
+
return reply.status(200).type(contentType2).header("Content-Disposition", "inline").send(nodeStream);
|
|
2735
|
+
}
|
|
2736
|
+
const bodyUnknown = downloadResult.body;
|
|
2737
|
+
let buf;
|
|
2738
|
+
let contentType = inferredContentType;
|
|
2739
|
+
if (bodyUnknown instanceof ArrayBuffer) {
|
|
2740
|
+
buf = Buffer.from(bodyUnknown);
|
|
2741
|
+
} else if (bodyUnknown instanceof Buffer) {
|
|
2742
|
+
buf = bodyUnknown;
|
|
2743
|
+
} else if (bodyUnknown && typeof bodyUnknown.arrayBuffer === "function") {
|
|
2744
|
+
const res = bodyUnknown;
|
|
2745
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
2746
|
+
if (res.headers?.get("content-type")) contentType = res.headers.get("content-type");
|
|
2747
|
+
} else if (bodyUnknown && typeof bodyUnknown.blob === "function") {
|
|
2748
|
+
const blob = await bodyUnknown.blob();
|
|
2749
|
+
buf = Buffer.from(await blob.arrayBuffer());
|
|
2750
|
+
} else {
|
|
2751
|
+
return reply.status(502).send({ success: false, error: "Unexpected view response format" });
|
|
2752
|
+
}
|
|
2753
|
+
return reply.status(200).type(contentType).header("Content-Disposition", "inline").send(buf);
|
|
2754
|
+
}
|
|
2755
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2756
|
+
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
2757
|
+
const filename = this.getFilenameFromPath(resolvedPath);
|
|
2758
|
+
const mimeType = this.getMimeType(filename);
|
|
2759
|
+
const buffer = Buffer.from(content, "utf-8");
|
|
2760
|
+
return reply.status(200).type(mimeType).header("Content-Disposition", "inline").send(buffer);
|
|
2761
|
+
} catch (error) {
|
|
2762
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2763
|
+
return reply.status(502).send({ success: false, error: `View proxy error: ${message}` });
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2589
2766
|
async listPath(request) {
|
|
2767
|
+
const tenantId = this.getTenantId(request);
|
|
2590
2768
|
const { workspaceId, projectId } = request.params;
|
|
2591
2769
|
const path2 = request.query.path || "/";
|
|
2592
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2770
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2593
2771
|
const files = await backend.lsInfo(path2);
|
|
2594
2772
|
return { success: true, data: files };
|
|
2595
2773
|
}
|
|
2596
2774
|
async readFile(request) {
|
|
2775
|
+
const tenantId = this.getTenantId(request);
|
|
2597
2776
|
const { workspaceId, projectId } = request.params;
|
|
2598
2777
|
const { path: path2, offset = 0, limit = 1e3 } = request.query;
|
|
2599
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2778
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2600
2779
|
const content = await backend.read(path2, Number(offset), Number(limit));
|
|
2601
2780
|
return { success: true, data: { content, offset, limit } };
|
|
2602
2781
|
}
|
|
@@ -2633,10 +2812,10 @@ var WorkspaceController = class {
|
|
|
2633
2812
|
return reply.status(400).send({ success: false, error: "Invalid path parameter" });
|
|
2634
2813
|
}
|
|
2635
2814
|
if (workspace.storageType === "sandbox") {
|
|
2636
|
-
const sandboxManager = getSandBoxManager3(
|
|
2815
|
+
const sandboxManager = getSandBoxManager3();
|
|
2637
2816
|
const sandboxName = "global";
|
|
2638
2817
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2639
|
-
const baseDir = path.join("/home/gem/workspaces", workspaceId, projectId);
|
|
2818
|
+
const baseDir = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId);
|
|
2640
2819
|
const realPath = pathValue ? path.join(baseDir, pathValue, filename) : path.join(baseDir, filename);
|
|
2641
2820
|
const uploadResult = await sandbox.file.uploadFile({
|
|
2642
2821
|
file: buffer,
|
|
@@ -2648,7 +2827,7 @@ var WorkspaceController = class {
|
|
|
2648
2827
|
error: `Upload error: ${JSON.stringify(uploadResult.error)}`
|
|
2649
2828
|
});
|
|
2650
2829
|
}
|
|
2651
|
-
const relativePath = uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/workspaces", workspaceId, projectId), "") || (pathValue ? `/${pathValue}/${filename}` : `/${filename}`);
|
|
2830
|
+
const relativePath = uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId), "") || (pathValue ? `/${pathValue}/${filename}` : `/${filename}`);
|
|
2652
2831
|
const result2 = {
|
|
2653
2832
|
path: relativePath,
|
|
2654
2833
|
name: filename,
|
|
@@ -2658,7 +2837,7 @@ var WorkspaceController = class {
|
|
|
2658
2837
|
};
|
|
2659
2838
|
return reply.status(200).send({ success: true, data: result2 });
|
|
2660
2839
|
}
|
|
2661
|
-
const rootDir = `/lattice_store/workspaces/${workspaceId}/${projectId}`;
|
|
2840
|
+
const rootDir = `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
2662
2841
|
const targetDir = pathValue ? path.join(rootDir, pathValue) : rootDir;
|
|
2663
2842
|
const targetPath = path.join(targetDir, filename);
|
|
2664
2843
|
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
@@ -2732,21 +2911,29 @@ function registerWorkspaceRoutes(app2) {
|
|
|
2732
2911
|
"/api/workspaces/:workspaceId/projects/:projectId/downloadfile",
|
|
2733
2912
|
controller.downloadFile.bind(controller)
|
|
2734
2913
|
);
|
|
2914
|
+
app2.get(
|
|
2915
|
+
"/api/workspaces/:workspaceId/projects/:projectId/viewfile",
|
|
2916
|
+
controller.viewFile.bind(controller)
|
|
2917
|
+
);
|
|
2735
2918
|
}
|
|
2736
2919
|
|
|
2737
2920
|
// src/controllers/database-configs.ts
|
|
2738
2921
|
import {
|
|
2739
|
-
getStoreLattice as
|
|
2922
|
+
getStoreLattice as getStoreLattice5,
|
|
2740
2923
|
sqlDatabaseManager
|
|
2741
2924
|
} from "@axiom-lattice/core";
|
|
2742
2925
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2743
|
-
function
|
|
2926
|
+
function getTenantId5(request) {
|
|
2927
|
+
const userTenantId = request.user?.tenantId;
|
|
2928
|
+
if (userTenantId) {
|
|
2929
|
+
return userTenantId;
|
|
2930
|
+
}
|
|
2744
2931
|
return request.headers["x-tenant-id"] || "default";
|
|
2745
2932
|
}
|
|
2746
2933
|
async function getDatabaseConfigList(request, reply) {
|
|
2747
|
-
const tenantId =
|
|
2934
|
+
const tenantId = getTenantId5(request);
|
|
2748
2935
|
try {
|
|
2749
|
-
const storeLattice =
|
|
2936
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2750
2937
|
const store = storeLattice.store;
|
|
2751
2938
|
const configs = await store.getAllConfigs(tenantId);
|
|
2752
2939
|
console.log("Backend: getAllConfigs returned:", configs);
|
|
@@ -2774,10 +2961,10 @@ async function getDatabaseConfigList(request, reply) {
|
|
|
2774
2961
|
}
|
|
2775
2962
|
}
|
|
2776
2963
|
async function getDatabaseConfig(request, reply) {
|
|
2777
|
-
const tenantId =
|
|
2964
|
+
const tenantId = getTenantId5(request);
|
|
2778
2965
|
const { key } = request.params;
|
|
2779
2966
|
try {
|
|
2780
|
-
const storeLattice =
|
|
2967
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2781
2968
|
const store = storeLattice.store;
|
|
2782
2969
|
const config = await store.getConfigByKey(tenantId, key);
|
|
2783
2970
|
if (!config) {
|
|
@@ -2800,10 +2987,10 @@ async function getDatabaseConfig(request, reply) {
|
|
|
2800
2987
|
}
|
|
2801
2988
|
}
|
|
2802
2989
|
async function createDatabaseConfig(request, reply) {
|
|
2803
|
-
const tenantId =
|
|
2990
|
+
const tenantId = getTenantId5(request);
|
|
2804
2991
|
const body = request.body;
|
|
2805
2992
|
try {
|
|
2806
|
-
const storeLattice =
|
|
2993
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2807
2994
|
const store = storeLattice.store;
|
|
2808
2995
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
2809
2996
|
if (existing) {
|
|
@@ -2816,7 +3003,7 @@ async function createDatabaseConfig(request, reply) {
|
|
|
2816
3003
|
const id = body.id || randomUUID3();
|
|
2817
3004
|
const config = await store.createConfig(tenantId, id, body);
|
|
2818
3005
|
try {
|
|
2819
|
-
sqlDatabaseManager.registerDatabase(config.key, config.config);
|
|
3006
|
+
sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
|
|
2820
3007
|
} catch (error) {
|
|
2821
3008
|
console.warn("Failed to auto-register database:", error);
|
|
2822
3009
|
}
|
|
@@ -2835,11 +3022,11 @@ async function createDatabaseConfig(request, reply) {
|
|
|
2835
3022
|
}
|
|
2836
3023
|
}
|
|
2837
3024
|
async function updateDatabaseConfig(request, reply) {
|
|
2838
|
-
const tenantId =
|
|
3025
|
+
const tenantId = getTenantId5(request);
|
|
2839
3026
|
const { key } = request.params;
|
|
2840
3027
|
const updates = request.body;
|
|
2841
3028
|
try {
|
|
2842
|
-
const storeLattice =
|
|
3029
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2843
3030
|
const store = storeLattice.store;
|
|
2844
3031
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
2845
3032
|
if (!existing) {
|
|
@@ -2858,7 +3045,7 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
2858
3045
|
}
|
|
2859
3046
|
if (updates.config) {
|
|
2860
3047
|
try {
|
|
2861
|
-
sqlDatabaseManager.registerDatabase(updated.key, updated.config);
|
|
3048
|
+
sqlDatabaseManager.registerDatabase(tenantId, updated.key, updated.config);
|
|
2862
3049
|
} catch (error) {
|
|
2863
3050
|
console.warn("Failed to re-register database:", error);
|
|
2864
3051
|
}
|
|
@@ -2877,10 +3064,10 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
2877
3064
|
}
|
|
2878
3065
|
}
|
|
2879
3066
|
async function deleteDatabaseConfig(request, reply) {
|
|
2880
|
-
const tenantId =
|
|
3067
|
+
const tenantId = getTenantId5(request);
|
|
2881
3068
|
const { keyOrId } = request.params;
|
|
2882
3069
|
try {
|
|
2883
|
-
const storeLattice =
|
|
3070
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2884
3071
|
const store = storeLattice.store;
|
|
2885
3072
|
console.log("Delete request - keyOrId:", keyOrId);
|
|
2886
3073
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
@@ -2907,8 +3094,8 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
2907
3094
|
};
|
|
2908
3095
|
}
|
|
2909
3096
|
try {
|
|
2910
|
-
if (sqlDatabaseManager.hasDatabase(configKey)) {
|
|
2911
|
-
await sqlDatabaseManager.removeDatabase(configKey);
|
|
3097
|
+
if (sqlDatabaseManager.hasDatabase(tenantId, configKey)) {
|
|
3098
|
+
await sqlDatabaseManager.removeDatabase(tenantId, configKey);
|
|
2912
3099
|
}
|
|
2913
3100
|
} catch (error) {
|
|
2914
3101
|
console.warn("Failed to remove from SqlDatabaseManager:", error);
|
|
@@ -2926,10 +3113,10 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
2926
3113
|
}
|
|
2927
3114
|
}
|
|
2928
3115
|
async function testDatabaseConnection(request, reply) {
|
|
2929
|
-
const tenantId =
|
|
3116
|
+
const tenantId = getTenantId5(request);
|
|
2930
3117
|
const { key } = request.params;
|
|
2931
3118
|
try {
|
|
2932
|
-
const storeLattice =
|
|
3119
|
+
const storeLattice = getStoreLattice5("default", "database");
|
|
2933
3120
|
const store = storeLattice.store;
|
|
2934
3121
|
const config = await store.getConfigByKey(tenantId, key);
|
|
2935
3122
|
if (!config) {
|
|
@@ -2940,16 +3127,16 @@ async function testDatabaseConnection(request, reply) {
|
|
|
2940
3127
|
};
|
|
2941
3128
|
}
|
|
2942
3129
|
const testKey = `__test_${key}_${Date.now()}`;
|
|
2943
|
-
sqlDatabaseManager.registerDatabase(testKey, config.config);
|
|
3130
|
+
sqlDatabaseManager.registerDatabase(tenantId, testKey, config.config);
|
|
2944
3131
|
const startTime = Date.now();
|
|
2945
|
-
const db = sqlDatabaseManager.getDatabase(testKey);
|
|
3132
|
+
const db = sqlDatabaseManager.getDatabase(tenantId, testKey);
|
|
2946
3133
|
try {
|
|
2947
3134
|
await db.connect();
|
|
2948
3135
|
await db.listTables();
|
|
2949
3136
|
const latency = Date.now() - startTime;
|
|
2950
3137
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2951
3138
|
await db.disconnect();
|
|
2952
|
-
await sqlDatabaseManager.removeDatabase(testKey);
|
|
3139
|
+
await sqlDatabaseManager.removeDatabase(tenantId, testKey);
|
|
2953
3140
|
return {
|
|
2954
3141
|
success: true,
|
|
2955
3142
|
message: "Connection test successful",
|
|
@@ -2961,7 +3148,7 @@ async function testDatabaseConnection(request, reply) {
|
|
|
2961
3148
|
} catch (error) {
|
|
2962
3149
|
try {
|
|
2963
3150
|
await db.disconnect();
|
|
2964
|
-
await sqlDatabaseManager.removeDatabase(testKey);
|
|
3151
|
+
await sqlDatabaseManager.removeDatabase(tenantId, testKey);
|
|
2965
3152
|
} catch {
|
|
2966
3153
|
}
|
|
2967
3154
|
return {
|
|
@@ -3014,18 +3201,22 @@ function registerDatabaseConfigRoutes(app2) {
|
|
|
3014
3201
|
|
|
3015
3202
|
// src/controllers/metrics-configs.ts
|
|
3016
3203
|
import {
|
|
3017
|
-
getStoreLattice as
|
|
3204
|
+
getStoreLattice as getStoreLattice6,
|
|
3018
3205
|
metricsServerManager,
|
|
3019
3206
|
SemanticMetricsClient
|
|
3020
3207
|
} from "@axiom-lattice/core";
|
|
3021
3208
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
3022
|
-
function
|
|
3209
|
+
function getTenantId6(request) {
|
|
3210
|
+
const userTenantId = request.user?.tenantId;
|
|
3211
|
+
if (userTenantId) {
|
|
3212
|
+
return userTenantId;
|
|
3213
|
+
}
|
|
3023
3214
|
return request.headers["x-tenant-id"] || "default";
|
|
3024
3215
|
}
|
|
3025
3216
|
async function getMetricsServerConfigList(request, reply) {
|
|
3026
|
-
const tenantId =
|
|
3217
|
+
const tenantId = getTenantId6(request);
|
|
3027
3218
|
try {
|
|
3028
|
-
const storeLattice =
|
|
3219
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3029
3220
|
const store = storeLattice.store;
|
|
3030
3221
|
const configs = await store.getAllConfigs(tenantId);
|
|
3031
3222
|
return {
|
|
@@ -3049,10 +3240,10 @@ async function getMetricsServerConfigList(request, reply) {
|
|
|
3049
3240
|
}
|
|
3050
3241
|
}
|
|
3051
3242
|
async function getMetricsServerConfig(request, reply) {
|
|
3052
|
-
const tenantId =
|
|
3243
|
+
const tenantId = getTenantId6(request);
|
|
3053
3244
|
const { key } = request.params;
|
|
3054
3245
|
try {
|
|
3055
|
-
const storeLattice =
|
|
3246
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3056
3247
|
const store = storeLattice.store;
|
|
3057
3248
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3058
3249
|
if (!config) {
|
|
@@ -3075,10 +3266,10 @@ async function getMetricsServerConfig(request, reply) {
|
|
|
3075
3266
|
}
|
|
3076
3267
|
}
|
|
3077
3268
|
async function createMetricsServerConfig(request, reply) {
|
|
3078
|
-
const tenantId =
|
|
3269
|
+
const tenantId = getTenantId6(request);
|
|
3079
3270
|
const body = request.body;
|
|
3080
3271
|
try {
|
|
3081
|
-
const storeLattice =
|
|
3272
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3082
3273
|
const store = storeLattice.store;
|
|
3083
3274
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
3084
3275
|
if (existing) {
|
|
@@ -3107,7 +3298,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3107
3298
|
};
|
|
3108
3299
|
const config = await store.createConfig(tenantId, id, configData);
|
|
3109
3300
|
try {
|
|
3110
|
-
metricsServerManager.registerServer(config.key, config.config);
|
|
3301
|
+
metricsServerManager.registerServer(tenantId, config.key, config.config);
|
|
3111
3302
|
} catch (error) {
|
|
3112
3303
|
console.warn("Failed to auto-register metrics server:", error);
|
|
3113
3304
|
}
|
|
@@ -3126,11 +3317,11 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3126
3317
|
}
|
|
3127
3318
|
}
|
|
3128
3319
|
async function updateMetricsServerConfig(request, reply) {
|
|
3129
|
-
const tenantId =
|
|
3320
|
+
const tenantId = getTenantId6(request);
|
|
3130
3321
|
const { key } = request.params;
|
|
3131
3322
|
const updates = request.body;
|
|
3132
3323
|
try {
|
|
3133
|
-
const storeLattice =
|
|
3324
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3134
3325
|
const store = storeLattice.store;
|
|
3135
3326
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
3136
3327
|
if (!existing) {
|
|
@@ -3158,7 +3349,7 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3158
3349
|
}
|
|
3159
3350
|
if (updates.config) {
|
|
3160
3351
|
try {
|
|
3161
|
-
metricsServerManager.registerServer(updated.key, updated.config);
|
|
3352
|
+
metricsServerManager.registerServer(tenantId, updated.key, updated.config);
|
|
3162
3353
|
} catch (error) {
|
|
3163
3354
|
console.warn("Failed to re-register metrics server:", error);
|
|
3164
3355
|
}
|
|
@@ -3177,10 +3368,10 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3177
3368
|
}
|
|
3178
3369
|
}
|
|
3179
3370
|
async function deleteMetricsServerConfig(request, reply) {
|
|
3180
|
-
const tenantId =
|
|
3371
|
+
const tenantId = getTenantId6(request);
|
|
3181
3372
|
const { keyOrId } = request.params;
|
|
3182
3373
|
try {
|
|
3183
|
-
const storeLattice =
|
|
3374
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3184
3375
|
const store = storeLattice.store;
|
|
3185
3376
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
3186
3377
|
let configKey = keyOrId;
|
|
@@ -3205,8 +3396,8 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3205
3396
|
};
|
|
3206
3397
|
}
|
|
3207
3398
|
try {
|
|
3208
|
-
if (metricsServerManager.hasServer(configKey)) {
|
|
3209
|
-
metricsServerManager.removeServer(configKey);
|
|
3399
|
+
if (metricsServerManager.hasServer(tenantId, configKey)) {
|
|
3400
|
+
metricsServerManager.removeServer(tenantId, configKey);
|
|
3210
3401
|
}
|
|
3211
3402
|
} catch (error) {
|
|
3212
3403
|
console.warn("Failed to remove from MetricsServerManager:", error);
|
|
@@ -3224,10 +3415,10 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3224
3415
|
}
|
|
3225
3416
|
}
|
|
3226
3417
|
async function testMetricsServerConnection(request, reply) {
|
|
3227
|
-
const tenantId =
|
|
3418
|
+
const tenantId = getTenantId6(request);
|
|
3228
3419
|
const { key } = request.params;
|
|
3229
3420
|
try {
|
|
3230
|
-
const storeLattice =
|
|
3421
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3231
3422
|
const store = storeLattice.store;
|
|
3232
3423
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3233
3424
|
if (!config) {
|
|
@@ -3238,11 +3429,11 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3238
3429
|
};
|
|
3239
3430
|
}
|
|
3240
3431
|
const testKey = `__test_${key}_${Date.now()}`;
|
|
3241
|
-
metricsServerManager.registerServer(testKey, config.config);
|
|
3432
|
+
metricsServerManager.registerServer(tenantId, testKey, config.config);
|
|
3242
3433
|
try {
|
|
3243
|
-
const client = metricsServerManager.getClient(testKey);
|
|
3434
|
+
const client = metricsServerManager.getClient(tenantId, testKey);
|
|
3244
3435
|
const result = await client.testConnection();
|
|
3245
|
-
metricsServerManager.removeServer(testKey);
|
|
3436
|
+
metricsServerManager.removeServer(tenantId, testKey);
|
|
3246
3437
|
return {
|
|
3247
3438
|
success: true,
|
|
3248
3439
|
message: result.connected ? "Connection test successful" : "Connection test failed",
|
|
@@ -3250,7 +3441,7 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3250
3441
|
};
|
|
3251
3442
|
} catch (error) {
|
|
3252
3443
|
try {
|
|
3253
|
-
metricsServerManager.removeServer(testKey);
|
|
3444
|
+
metricsServerManager.removeServer(tenantId, testKey);
|
|
3254
3445
|
} catch {
|
|
3255
3446
|
}
|
|
3256
3447
|
return {
|
|
@@ -3275,10 +3466,10 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3275
3466
|
}
|
|
3276
3467
|
}
|
|
3277
3468
|
async function listAvailableMetrics(request, reply) {
|
|
3278
|
-
const tenantId =
|
|
3469
|
+
const tenantId = getTenantId6(request);
|
|
3279
3470
|
const { key } = request.params;
|
|
3280
3471
|
try {
|
|
3281
|
-
const storeLattice =
|
|
3472
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3282
3473
|
const store = storeLattice.store;
|
|
3283
3474
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3284
3475
|
if (!config) {
|
|
@@ -3288,10 +3479,10 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3288
3479
|
message: "Metrics server configuration not found"
|
|
3289
3480
|
};
|
|
3290
3481
|
}
|
|
3291
|
-
if (!metricsServerManager.hasServer(key)) {
|
|
3292
|
-
metricsServerManager.registerServer(key, config.config);
|
|
3482
|
+
if (!metricsServerManager.hasServer(tenantId, key)) {
|
|
3483
|
+
metricsServerManager.registerServer(tenantId, key, config.config);
|
|
3293
3484
|
}
|
|
3294
|
-
const client = metricsServerManager.getClient(key);
|
|
3485
|
+
const client = metricsServerManager.getClient(tenantId, key);
|
|
3295
3486
|
const metrics = await client.listMetrics();
|
|
3296
3487
|
return {
|
|
3297
3488
|
success: true,
|
|
@@ -3313,11 +3504,11 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3313
3504
|
}
|
|
3314
3505
|
}
|
|
3315
3506
|
async function queryMetricsData(request, reply) {
|
|
3316
|
-
const tenantId =
|
|
3507
|
+
const tenantId = getTenantId6(request);
|
|
3317
3508
|
const { key } = request.params;
|
|
3318
3509
|
const { metricName, startTime, endTime, step, labels } = request.body;
|
|
3319
3510
|
try {
|
|
3320
|
-
const storeLattice =
|
|
3511
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3321
3512
|
const store = storeLattice.store;
|
|
3322
3513
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3323
3514
|
if (!config) {
|
|
@@ -3334,10 +3525,10 @@ async function queryMetricsData(request, reply) {
|
|
|
3334
3525
|
message: "metricName is required"
|
|
3335
3526
|
};
|
|
3336
3527
|
}
|
|
3337
|
-
if (!metricsServerManager.hasServer(key)) {
|
|
3338
|
-
metricsServerManager.registerServer(key, config.config);
|
|
3528
|
+
if (!metricsServerManager.hasServer(tenantId, key)) {
|
|
3529
|
+
metricsServerManager.registerServer(tenantId, key, config.config);
|
|
3339
3530
|
}
|
|
3340
|
-
const client = metricsServerManager.getClient(key);
|
|
3531
|
+
const client = metricsServerManager.getClient(tenantId, key);
|
|
3341
3532
|
const result = await client.queryMetricData(metricName, {
|
|
3342
3533
|
startTime,
|
|
3343
3534
|
endTime,
|
|
@@ -3361,10 +3552,10 @@ async function queryMetricsData(request, reply) {
|
|
|
3361
3552
|
}
|
|
3362
3553
|
}
|
|
3363
3554
|
async function getDataSources(request, reply) {
|
|
3364
|
-
const tenantId =
|
|
3555
|
+
const tenantId = getTenantId6(request);
|
|
3365
3556
|
const { key } = request.params;
|
|
3366
3557
|
try {
|
|
3367
|
-
const storeLattice =
|
|
3558
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3368
3559
|
const store = storeLattice.store;
|
|
3369
3560
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3370
3561
|
if (!config) {
|
|
@@ -3402,10 +3593,10 @@ async function getDataSources(request, reply) {
|
|
|
3402
3593
|
}
|
|
3403
3594
|
}
|
|
3404
3595
|
async function getDatasourceMetrics(request, reply) {
|
|
3405
|
-
const tenantId =
|
|
3596
|
+
const tenantId = getTenantId6(request);
|
|
3406
3597
|
const { key, datasourceId } = request.params;
|
|
3407
3598
|
try {
|
|
3408
|
-
const storeLattice =
|
|
3599
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3409
3600
|
const store = storeLattice.store;
|
|
3410
3601
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3411
3602
|
if (!config) {
|
|
@@ -3439,11 +3630,11 @@ async function getDatasourceMetrics(request, reply) {
|
|
|
3439
3630
|
}
|
|
3440
3631
|
}
|
|
3441
3632
|
async function querySemanticMetrics(request, reply) {
|
|
3442
|
-
const tenantId =
|
|
3633
|
+
const tenantId = getTenantId6(request);
|
|
3443
3634
|
const { key } = request.params;
|
|
3444
3635
|
const body = request.body;
|
|
3445
3636
|
try {
|
|
3446
|
-
const storeLattice =
|
|
3637
|
+
const storeLattice = getStoreLattice6("default", "metrics");
|
|
3447
3638
|
const store = storeLattice.store;
|
|
3448
3639
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3449
3640
|
if (!config) {
|
|
@@ -3470,14 +3661,32 @@ async function querySemanticMetrics(request, reply) {
|
|
|
3470
3661
|
const semanticConfig = config.config;
|
|
3471
3662
|
const client = new SemanticMetricsClient(semanticConfig);
|
|
3472
3663
|
const result = await client.semanticQuery(body);
|
|
3664
|
+
const allDataPoints = [];
|
|
3665
|
+
const metricNames = [];
|
|
3666
|
+
for (const metricResult of result.results) {
|
|
3667
|
+
metricNames.push(metricResult.metricName);
|
|
3668
|
+
for (const row of metricResult.rows) {
|
|
3669
|
+
allDataPoints.push({
|
|
3670
|
+
timestamp: row.timestamp ? new Date(row.timestamp).getTime() : void 0,
|
|
3671
|
+
value: typeof row.value === "number" ? row.value : 0,
|
|
3672
|
+
metricName: metricResult.metricName,
|
|
3673
|
+
labels: Object.fromEntries(
|
|
3674
|
+
Object.entries(row).filter(([k]) => k !== "value" && k !== "timestamp").map(([k, v]) => [k, String(v)])
|
|
3675
|
+
)
|
|
3676
|
+
});
|
|
3677
|
+
}
|
|
3678
|
+
}
|
|
3473
3679
|
return {
|
|
3474
3680
|
success: true,
|
|
3475
3681
|
message: "Semantic query executed successfully",
|
|
3476
3682
|
data: {
|
|
3477
3683
|
datasourceId: result.datasourceId,
|
|
3478
|
-
metrics:
|
|
3479
|
-
dataPoints:
|
|
3480
|
-
metadata:
|
|
3684
|
+
metrics: metricNames,
|
|
3685
|
+
dataPoints: allDataPoints,
|
|
3686
|
+
metadata: {
|
|
3687
|
+
rowCount: allDataPoints.length,
|
|
3688
|
+
queryTimeMs: result.totalExecutionTimeMs
|
|
3689
|
+
}
|
|
3481
3690
|
}
|
|
3482
3691
|
};
|
|
3483
3692
|
} catch (error) {
|
|
@@ -3575,18 +3784,22 @@ function registerMetricsServerConfigRoutes(app2) {
|
|
|
3575
3784
|
|
|
3576
3785
|
// src/controllers/mcp-configs.ts
|
|
3577
3786
|
import {
|
|
3578
|
-
getStoreLattice as
|
|
3787
|
+
getStoreLattice as getStoreLattice7,
|
|
3579
3788
|
mcpManager,
|
|
3580
3789
|
toolLatticeManager as toolLatticeManager2
|
|
3581
3790
|
} from "@axiom-lattice/core";
|
|
3582
3791
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
3583
|
-
function
|
|
3792
|
+
function getTenantId7(request) {
|
|
3793
|
+
const userTenantId = request.user?.tenantId;
|
|
3794
|
+
if (userTenantId) {
|
|
3795
|
+
return userTenantId;
|
|
3796
|
+
}
|
|
3584
3797
|
return request.headers["x-tenant-id"] || "default";
|
|
3585
3798
|
}
|
|
3586
3799
|
async function getMcpServerConfigList(request, reply) {
|
|
3587
|
-
const tenantId =
|
|
3800
|
+
const tenantId = getTenantId7(request);
|
|
3588
3801
|
try {
|
|
3589
|
-
const storeLattice =
|
|
3802
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3590
3803
|
const store = storeLattice.store;
|
|
3591
3804
|
const configs = await store.getAllConfigs(tenantId);
|
|
3592
3805
|
return {
|
|
@@ -3610,10 +3823,10 @@ async function getMcpServerConfigList(request, reply) {
|
|
|
3610
3823
|
}
|
|
3611
3824
|
}
|
|
3612
3825
|
async function getMcpServerConfig(request, reply) {
|
|
3613
|
-
const tenantId =
|
|
3826
|
+
const tenantId = getTenantId7(request);
|
|
3614
3827
|
const { key } = request.params;
|
|
3615
3828
|
try {
|
|
3616
|
-
const storeLattice =
|
|
3829
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3617
3830
|
const store = storeLattice.store;
|
|
3618
3831
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3619
3832
|
if (!config) {
|
|
@@ -3636,10 +3849,10 @@ async function getMcpServerConfig(request, reply) {
|
|
|
3636
3849
|
}
|
|
3637
3850
|
}
|
|
3638
3851
|
async function createMcpServerConfig(request, reply) {
|
|
3639
|
-
const tenantId =
|
|
3852
|
+
const tenantId = getTenantId7(request);
|
|
3640
3853
|
const body = request.body;
|
|
3641
3854
|
try {
|
|
3642
|
-
const storeLattice =
|
|
3855
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3643
3856
|
const store = storeLattice.store;
|
|
3644
3857
|
const existing = await store.getConfigByKey(tenantId, body.key);
|
|
3645
3858
|
if (existing) {
|
|
@@ -3675,11 +3888,11 @@ async function createMcpServerConfig(request, reply) {
|
|
|
3675
3888
|
}
|
|
3676
3889
|
}
|
|
3677
3890
|
async function updateMcpServerConfig(request, reply) {
|
|
3678
|
-
const tenantId =
|
|
3891
|
+
const tenantId = getTenantId7(request);
|
|
3679
3892
|
const { key } = request.params;
|
|
3680
3893
|
const updates = request.body;
|
|
3681
3894
|
try {
|
|
3682
|
-
const storeLattice =
|
|
3895
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3683
3896
|
const store = storeLattice.store;
|
|
3684
3897
|
const existing = await store.getConfigByKey(tenantId, key);
|
|
3685
3898
|
if (!existing) {
|
|
@@ -3725,10 +3938,10 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
3725
3938
|
}
|
|
3726
3939
|
}
|
|
3727
3940
|
async function deleteMcpServerConfig(request, reply) {
|
|
3728
|
-
const tenantId =
|
|
3941
|
+
const tenantId = getTenantId7(request);
|
|
3729
3942
|
const { keyOrId } = request.params;
|
|
3730
3943
|
try {
|
|
3731
|
-
const storeLattice =
|
|
3944
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3732
3945
|
const store = storeLattice.store;
|
|
3733
3946
|
let config = await store.getConfigByKey(tenantId, keyOrId);
|
|
3734
3947
|
let configKey = keyOrId;
|
|
@@ -3772,10 +3985,10 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
3772
3985
|
}
|
|
3773
3986
|
}
|
|
3774
3987
|
async function testMcpServerConnection(request, reply) {
|
|
3775
|
-
const tenantId =
|
|
3988
|
+
const tenantId = getTenantId7(request);
|
|
3776
3989
|
const { key } = request.params;
|
|
3777
3990
|
try {
|
|
3778
|
-
const storeLattice =
|
|
3991
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3779
3992
|
const store = storeLattice.store;
|
|
3780
3993
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3781
3994
|
if (!config) {
|
|
@@ -3825,10 +4038,10 @@ async function testMcpServerConnection(request, reply) {
|
|
|
3825
4038
|
}
|
|
3826
4039
|
}
|
|
3827
4040
|
async function listMcpServerTools(request, reply) {
|
|
3828
|
-
const tenantId =
|
|
4041
|
+
const tenantId = getTenantId7(request);
|
|
3829
4042
|
const { key } = request.params;
|
|
3830
4043
|
try {
|
|
3831
|
-
const storeLattice =
|
|
4044
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3832
4045
|
const store = storeLattice.store;
|
|
3833
4046
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3834
4047
|
if (!config) {
|
|
@@ -3858,10 +4071,10 @@ async function listMcpServerTools(request, reply) {
|
|
|
3858
4071
|
}
|
|
3859
4072
|
}
|
|
3860
4073
|
async function connectMcpServer(request, reply) {
|
|
3861
|
-
const tenantId =
|
|
4074
|
+
const tenantId = getTenantId7(request);
|
|
3862
4075
|
const { key } = request.params;
|
|
3863
4076
|
try {
|
|
3864
|
-
const storeLattice =
|
|
4077
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3865
4078
|
const store = storeLattice.store;
|
|
3866
4079
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3867
4080
|
if (!config) {
|
|
@@ -3882,7 +4095,7 @@ async function connectMcpServer(request, reply) {
|
|
|
3882
4095
|
};
|
|
3883
4096
|
} catch (error) {
|
|
3884
4097
|
console.error("Failed to connect MCP server:", error);
|
|
3885
|
-
const storeLattice =
|
|
4098
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3886
4099
|
const store = storeLattice.store;
|
|
3887
4100
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3888
4101
|
if (config) {
|
|
@@ -3895,10 +4108,10 @@ async function connectMcpServer(request, reply) {
|
|
|
3895
4108
|
}
|
|
3896
4109
|
}
|
|
3897
4110
|
async function disconnectMcpServer(request, reply) {
|
|
3898
|
-
const tenantId =
|
|
4111
|
+
const tenantId = getTenantId7(request);
|
|
3899
4112
|
const { key } = request.params;
|
|
3900
4113
|
try {
|
|
3901
|
-
const storeLattice =
|
|
4114
|
+
const storeLattice = getStoreLattice7("default", "mcp");
|
|
3902
4115
|
const store = storeLattice.store;
|
|
3903
4116
|
const config = await store.getConfigByKey(tenantId, key);
|
|
3904
4117
|
if (!config) {
|
|
@@ -4003,11 +4216,11 @@ function registerMcpServerConfigRoutes(app2) {
|
|
|
4003
4216
|
}
|
|
4004
4217
|
|
|
4005
4218
|
// src/controllers/users.ts
|
|
4006
|
-
import { getStoreLattice as
|
|
4219
|
+
import { getStoreLattice as getStoreLattice8 } from "@axiom-lattice/core";
|
|
4007
4220
|
import { v4 as uuidv42 } from "uuid";
|
|
4008
4221
|
var UsersController = class {
|
|
4009
4222
|
constructor() {
|
|
4010
|
-
this.userStore =
|
|
4223
|
+
this.userStore = getStoreLattice8("default", "user").store;
|
|
4011
4224
|
}
|
|
4012
4225
|
async listUsers(request, reply) {
|
|
4013
4226
|
const { email } = request.query;
|
|
@@ -4085,11 +4298,11 @@ function registerUserRoutes(app2) {
|
|
|
4085
4298
|
}
|
|
4086
4299
|
|
|
4087
4300
|
// src/controllers/tenants.ts
|
|
4088
|
-
import { getStoreLattice as
|
|
4301
|
+
import { getStoreLattice as getStoreLattice9 } from "@axiom-lattice/core";
|
|
4089
4302
|
import { v4 as uuidv43 } from "uuid";
|
|
4090
4303
|
var TenantsController = class {
|
|
4091
4304
|
constructor() {
|
|
4092
|
-
this.tenantStore =
|
|
4305
|
+
this.tenantStore = getStoreLattice9("default", "tenant").store;
|
|
4093
4306
|
}
|
|
4094
4307
|
// ==================== Tenant CRUD ====================
|
|
4095
4308
|
async listTenants(request, reply) {
|
|
@@ -4153,7 +4366,7 @@ function registerTenantRoutes(app2) {
|
|
|
4153
4366
|
}
|
|
4154
4367
|
|
|
4155
4368
|
// src/controllers/auth.ts
|
|
4156
|
-
import { getStoreLattice as
|
|
4369
|
+
import { getStoreLattice as getStoreLattice10 } from "@axiom-lattice/core";
|
|
4157
4370
|
import { v4 as uuidv44 } from "uuid";
|
|
4158
4371
|
var defaultAuthConfig = {
|
|
4159
4372
|
autoApproveUsers: true,
|
|
@@ -4162,9 +4375,9 @@ var defaultAuthConfig = {
|
|
|
4162
4375
|
};
|
|
4163
4376
|
var AuthController = class {
|
|
4164
4377
|
constructor(config = {}) {
|
|
4165
|
-
this.userStore =
|
|
4166
|
-
this.tenantStore =
|
|
4167
|
-
this.userTenantLinkStore =
|
|
4378
|
+
this.userStore = getStoreLattice10("default", "user").store;
|
|
4379
|
+
this.tenantStore = getStoreLattice10("default", "tenant").store;
|
|
4380
|
+
this.userTenantLinkStore = getStoreLattice10("default", "userTenantLink").store;
|
|
4168
4381
|
this.config = { ...defaultAuthConfig, ...config };
|
|
4169
4382
|
}
|
|
4170
4383
|
async register(request, reply) {
|
|
@@ -4738,7 +4951,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
4738
4951
|
reader.releaseLock();
|
|
4739
4952
|
}
|
|
4740
4953
|
if (callback_event) {
|
|
4741
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
4954
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
4742
4955
|
eventBus2.publish(callback_event, {
|
|
4743
4956
|
success: true,
|
|
4744
4957
|
state,
|
|
@@ -4752,7 +4965,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
4752
4965
|
} else {
|
|
4753
4966
|
await response.text();
|
|
4754
4967
|
if (callback_event) {
|
|
4755
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
4968
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
4756
4969
|
eventBus2.publish(callback_event, {
|
|
4757
4970
|
success: true,
|
|
4758
4971
|
state,
|
|
@@ -4960,7 +5173,8 @@ var AgentTaskConsumer = _AgentTaskConsumer;
|
|
|
4960
5173
|
import {
|
|
4961
5174
|
registerLoggerLattice,
|
|
4962
5175
|
getLoggerLattice,
|
|
4963
|
-
loggerLatticeManager
|
|
5176
|
+
loggerLatticeManager,
|
|
5177
|
+
sandboxLatticeManager as sandboxLatticeManager2
|
|
4964
5178
|
} from "@axiom-lattice/core";
|
|
4965
5179
|
import {
|
|
4966
5180
|
LoggerType
|
|
@@ -5072,6 +5286,13 @@ var start = async (config) => {
|
|
|
5072
5286
|
logger = loggerLattice.client;
|
|
5073
5287
|
}
|
|
5074
5288
|
app.decorate("loggerLattice", loggerLattice);
|
|
5289
|
+
if (!sandboxLatticeManager2.hasLattice("default")) {
|
|
5290
|
+
const sandboxBaseURL = process.env.SANDBOX_BASE_URL || "http://localhost:8080";
|
|
5291
|
+
sandboxLatticeManager2.registerLattice("default", {
|
|
5292
|
+
baseURL: sandboxBaseURL
|
|
5293
|
+
});
|
|
5294
|
+
logger.info(`Registered sandbox manager with baseURL: ${sandboxBaseURL}`);
|
|
5295
|
+
}
|
|
5075
5296
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
5076
5297
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
5077
5298
|
logger.info(`Lattice Gateway is running on port: ${target_port}`);
|