@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
package/dist/index.js
CHANGED
|
@@ -44,6 +44,14 @@ var import_messages = require("@langchain/core/messages");
|
|
|
44
44
|
var import_langgraph = require("@langchain/langgraph");
|
|
45
45
|
var import_uuid = require("uuid");
|
|
46
46
|
var import_core = require("@axiom-lattice/core");
|
|
47
|
+
async function checkAgentExists(tenant_id, assistant_id) {
|
|
48
|
+
try {
|
|
49
|
+
const agentLattice = import_core.agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
50
|
+
return agentLattice !== void 0;
|
|
51
|
+
} catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
47
55
|
function getOrCreateChunkBuffer() {
|
|
48
56
|
if (!(0, import_core.hasChunkBuffer)("default")) {
|
|
49
57
|
const buffer = new import_core.InMemoryChunkBuffer({
|
|
@@ -67,7 +75,7 @@ async function agent_invoke({
|
|
|
67
75
|
run_id,
|
|
68
76
|
custom_run_config
|
|
69
77
|
}) {
|
|
70
|
-
const agentLattice = (
|
|
78
|
+
const agentLattice = import_core.agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
71
79
|
const runnable_agent = agentLattice?.client;
|
|
72
80
|
const { message, ...rest } = input;
|
|
73
81
|
const humanMessage = new import_messages.HumanMessage(message || "");
|
|
@@ -77,6 +85,7 @@ async function agent_invoke({
|
|
|
77
85
|
}
|
|
78
86
|
const runConfig = {
|
|
79
87
|
...agentLattice?.config?.runConfig || {},
|
|
88
|
+
tenantId: tenant_id,
|
|
80
89
|
workspaceId: workspace_id,
|
|
81
90
|
projectId: project_id,
|
|
82
91
|
...custom_run_config || {},
|
|
@@ -119,8 +128,8 @@ async function agent_stream({
|
|
|
119
128
|
run_id,
|
|
120
129
|
custom_run_config
|
|
121
130
|
}) {
|
|
122
|
-
const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
|
|
123
|
-
const agentLattice = (
|
|
131
|
+
const runnable_agent = await (0, import_core.getAgentClient)(tenant_id, assistant_id);
|
|
132
|
+
const agentLattice = import_core.agentLatticeManager.getAgentLatticeWithTenant(tenant_id, assistant_id);
|
|
124
133
|
const { message, ...rest } = input;
|
|
125
134
|
let messages = [];
|
|
126
135
|
if (!command) {
|
|
@@ -130,6 +139,7 @@ async function agent_stream({
|
|
|
130
139
|
const chunkBuffer = getOrCreateChunkBuffer();
|
|
131
140
|
const runConfig = {
|
|
132
141
|
...agentLattice?.config?.runConfig || {},
|
|
142
|
+
tenantId: tenant_id,
|
|
133
143
|
workspaceId: workspace_id,
|
|
134
144
|
projectId: project_id,
|
|
135
145
|
...custom_run_config || {},
|
|
@@ -208,10 +218,11 @@ async function agent_stream({
|
|
|
208
218
|
}
|
|
209
219
|
}
|
|
210
220
|
async function agent_state({
|
|
221
|
+
assistant_id,
|
|
211
222
|
thread_id,
|
|
212
|
-
|
|
223
|
+
tenant_id
|
|
213
224
|
}) {
|
|
214
|
-
const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
|
|
225
|
+
const runnable_agent = await (0, import_core.getAgentClient)(tenant_id, assistant_id);
|
|
215
226
|
if (!runnable_agent) {
|
|
216
227
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
217
228
|
}
|
|
@@ -225,7 +236,7 @@ async function agent_messages({
|
|
|
225
236
|
tenant_id,
|
|
226
237
|
assistant_id
|
|
227
238
|
}) {
|
|
228
|
-
const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
|
|
239
|
+
const runnable_agent = await (0, import_core.getAgentClient)(tenant_id, assistant_id);
|
|
229
240
|
if (!runnable_agent) {
|
|
230
241
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
231
242
|
}
|
|
@@ -246,8 +257,8 @@ async function agent_messages({
|
|
|
246
257
|
const new_messages = messagesArray;
|
|
247
258
|
return new_messages;
|
|
248
259
|
}
|
|
249
|
-
async function draw_graph(assistant_id) {
|
|
250
|
-
const runnable_agent = (0, import_core.getAgentClient)(assistant_id);
|
|
260
|
+
async function draw_graph(assistant_id, tenant_id) {
|
|
261
|
+
const runnable_agent = await (0, import_core.getAgentClient)(tenant_id, assistant_id);
|
|
251
262
|
if (!runnable_agent) {
|
|
252
263
|
throw new Error(`Agent ${assistant_id} not found`);
|
|
253
264
|
}
|
|
@@ -285,9 +296,18 @@ async function resume_stream({
|
|
|
285
296
|
var import_core2 = require("@axiom-lattice/core");
|
|
286
297
|
var import_crypto = require("crypto");
|
|
287
298
|
var import_core3 = require("@axiom-lattice/core");
|
|
299
|
+
function getTenantId(request) {
|
|
300
|
+
const userTenantId = request.user?.tenantId;
|
|
301
|
+
if (userTenantId) {
|
|
302
|
+
return userTenantId;
|
|
303
|
+
}
|
|
304
|
+
return request.headers["x-tenant-id"] || "default";
|
|
305
|
+
}
|
|
288
306
|
function convertAgentConfigToAssistant(config) {
|
|
289
307
|
return {
|
|
290
308
|
id: config.key,
|
|
309
|
+
tenantId: "default",
|
|
310
|
+
// Code-configured agents belong to default tenant
|
|
291
311
|
name: config.name,
|
|
292
312
|
description: config.description,
|
|
293
313
|
graphDefinition: config,
|
|
@@ -299,13 +319,14 @@ function convertAgentConfigToAssistant(config) {
|
|
|
299
319
|
};
|
|
300
320
|
}
|
|
301
321
|
async function getAssistantList(request, reply) {
|
|
302
|
-
const
|
|
322
|
+
const tenantId = getTenantId(request);
|
|
323
|
+
const agentConfigs = await import_core3.agentLatticeManager.getAllAgentConfigsByTenant(tenantId);
|
|
303
324
|
const codeConfiguredAssistants = agentConfigs.map(
|
|
304
325
|
convertAgentConfigToAssistant
|
|
305
326
|
);
|
|
306
327
|
const storeLattice = (0, import_core2.getStoreLattice)("default", "assistant");
|
|
307
328
|
const assistantStore = storeLattice.store;
|
|
308
|
-
const storedAssistants = await assistantStore.getAllAssistants();
|
|
329
|
+
const storedAssistants = await assistantStore.getAllAssistants(tenantId);
|
|
309
330
|
const assistantMap = /* @__PURE__ */ new Map();
|
|
310
331
|
codeConfiguredAssistants.forEach((assistant) => {
|
|
311
332
|
assistantMap.set(assistant.id, assistant);
|
|
@@ -325,12 +346,12 @@ async function getAssistantList(request, reply) {
|
|
|
325
346
|
}
|
|
326
347
|
async function getAssistant(request, reply) {
|
|
327
348
|
const { id } = request.params;
|
|
349
|
+
const tenantId = getTenantId(request);
|
|
328
350
|
const storeLattice = (0, import_core2.getStoreLattice)("default", "assistant");
|
|
329
351
|
const assistantStore = storeLattice.store;
|
|
330
|
-
let assistant = await assistantStore.getAssistantById(id);
|
|
352
|
+
let assistant = await assistantStore.getAssistantById(tenantId, id);
|
|
331
353
|
if (!assistant) {
|
|
332
|
-
const
|
|
333
|
-
const agentConfig = agentConfigs.find((config) => config.key === id);
|
|
354
|
+
const agentConfig = await import_core3.agentLatticeManager.getAgentConfigWithTenant(tenantId, id);
|
|
334
355
|
if (agentConfig) {
|
|
335
356
|
assistant = convertAgentConfigToAssistant(agentConfig);
|
|
336
357
|
}
|
|
@@ -347,20 +368,20 @@ async function getAssistant(request, reply) {
|
|
|
347
368
|
data: assistant
|
|
348
369
|
};
|
|
349
370
|
}
|
|
350
|
-
async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
371
|
+
async function upsertAssistant(tenantId, id, data, reply, requireFields = false) {
|
|
351
372
|
const storeLattice = (0, import_core2.getStoreLattice)("default", "assistant");
|
|
352
373
|
const assistantStore = storeLattice.store;
|
|
353
|
-
const exists = await assistantStore.hasAssistant(id);
|
|
374
|
+
const exists = await assistantStore.hasAssistant(tenantId, id);
|
|
354
375
|
let assistant;
|
|
355
376
|
if (exists) {
|
|
356
|
-
assistant = await assistantStore.updateAssistant(id, data);
|
|
377
|
+
assistant = await assistantStore.updateAssistant(tenantId, id, data);
|
|
357
378
|
if (!assistant) {
|
|
358
379
|
return reply.status(500).send({
|
|
359
380
|
success: false,
|
|
360
381
|
message: "Failed to update assistant"
|
|
361
382
|
});
|
|
362
383
|
}
|
|
363
|
-
import_core3.eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name });
|
|
384
|
+
import_core3.eventBus.publish("assistant:updated", { id: assistant.id, name: assistant.name, tenantId });
|
|
364
385
|
return {
|
|
365
386
|
success: true,
|
|
366
387
|
message: "Updated assistant",
|
|
@@ -376,8 +397,8 @@ async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
|
376
397
|
});
|
|
377
398
|
}
|
|
378
399
|
}
|
|
379
|
-
assistant = await assistantStore.createAssistant(id, data);
|
|
380
|
-
import_core3.eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name });
|
|
400
|
+
assistant = await assistantStore.createAssistant(tenantId, id, data);
|
|
401
|
+
import_core3.eventBus.publish("assistant:created", { id: assistant.id, name: assistant.name, tenantId });
|
|
381
402
|
return reply.status(201).send({
|
|
382
403
|
success: true,
|
|
383
404
|
message: "Created assistant",
|
|
@@ -385,6 +406,7 @@ async function upsertAssistant(id, data, reply, requireFields = false) {
|
|
|
385
406
|
});
|
|
386
407
|
}
|
|
387
408
|
async function createAssistant(request, reply) {
|
|
409
|
+
const tenantId = getTenantId(request);
|
|
388
410
|
const data = request.body;
|
|
389
411
|
if (!data.name || !data.graphDefinition) {
|
|
390
412
|
return reply.status(400).send({
|
|
@@ -393,49 +415,51 @@ async function createAssistant(request, reply) {
|
|
|
393
415
|
});
|
|
394
416
|
}
|
|
395
417
|
const id = data.id ?? (0, import_crypto.randomUUID)();
|
|
396
|
-
return upsertAssistant(id, data, reply, true);
|
|
418
|
+
return upsertAssistant(tenantId, id, data, reply, true);
|
|
397
419
|
}
|
|
398
420
|
async function updateAssistant(request, reply) {
|
|
421
|
+
const tenantId = getTenantId(request);
|
|
399
422
|
const { id } = request.params;
|
|
400
423
|
const updates = request.body;
|
|
401
|
-
return upsertAssistant(id, updates, reply, false);
|
|
424
|
+
return upsertAssistant(tenantId, id, updates, reply, false);
|
|
402
425
|
}
|
|
403
426
|
async function deleteAssistant(request, reply) {
|
|
427
|
+
const tenantId = getTenantId(request);
|
|
404
428
|
const { id } = request.params;
|
|
405
429
|
const storeLattice = (0, import_core2.getStoreLattice)("default", "assistant");
|
|
406
430
|
const assistantStore = storeLattice.store;
|
|
407
|
-
const
|
|
408
|
-
const isCodeConfigured =
|
|
431
|
+
const agentConfig = await import_core3.agentLatticeManager.getAgentConfigWithTenant(tenantId, id);
|
|
432
|
+
const isCodeConfigured = !!agentConfig;
|
|
409
433
|
if (isCodeConfigured) {
|
|
410
|
-
const exists2 = await assistantStore.hasAssistant(id);
|
|
434
|
+
const exists2 = await assistantStore.hasAssistant(tenantId, id);
|
|
411
435
|
if (!exists2) {
|
|
412
436
|
return reply.status(404).send({
|
|
413
437
|
success: false,
|
|
414
438
|
message: "Assistant not found (code-configured assistants cannot be deleted from code, only from store)"
|
|
415
439
|
});
|
|
416
440
|
}
|
|
417
|
-
await assistantStore.deleteAssistant(id);
|
|
418
|
-
import_core3.eventBus.publish("assistant:deleted", { id });
|
|
441
|
+
await assistantStore.deleteAssistant(tenantId, id);
|
|
442
|
+
import_core3.eventBus.publish("assistant:deleted", { id, tenantId });
|
|
419
443
|
return {
|
|
420
444
|
success: true,
|
|
421
445
|
message: "Deleted assistant from store (code-configured registration remains)"
|
|
422
446
|
};
|
|
423
447
|
}
|
|
424
|
-
const exists = await assistantStore.hasAssistant(id);
|
|
448
|
+
const exists = await assistantStore.hasAssistant(tenantId, id);
|
|
425
449
|
if (!exists) {
|
|
426
450
|
return reply.status(404).send({
|
|
427
451
|
success: false,
|
|
428
452
|
message: "Assistant not found"
|
|
429
453
|
});
|
|
430
454
|
}
|
|
431
|
-
const deleted = await assistantStore.deleteAssistant(id);
|
|
455
|
+
const deleted = await assistantStore.deleteAssistant(tenantId, id);
|
|
432
456
|
if (!deleted) {
|
|
433
457
|
return reply.status(500).send({
|
|
434
458
|
success: false,
|
|
435
459
|
message: "Failed to delete assistant"
|
|
436
460
|
});
|
|
437
461
|
}
|
|
438
|
-
import_core3.eventBus.publish("assistant:deleted", { id });
|
|
462
|
+
import_core3.eventBus.publish("assistant:deleted", { id, tenantId });
|
|
439
463
|
return {
|
|
440
464
|
success: true,
|
|
441
465
|
message: "Successfully deleted assistant"
|
|
@@ -444,7 +468,8 @@ async function deleteAssistant(request, reply) {
|
|
|
444
468
|
var getAgentGraph = async (request, reply) => {
|
|
445
469
|
try {
|
|
446
470
|
const { assistantId } = request.params;
|
|
447
|
-
const
|
|
471
|
+
const tenant_id = getTenantId(request);
|
|
472
|
+
const imageData = await draw_graph(assistantId, tenant_id);
|
|
448
473
|
reply.header("Content-Type", "application/json").send({
|
|
449
474
|
image: imageData
|
|
450
475
|
});
|
|
@@ -481,6 +506,14 @@ var createRun = async (request, reply) => {
|
|
|
481
506
|
return;
|
|
482
507
|
}
|
|
483
508
|
if (streaming) {
|
|
509
|
+
const agentExists = await checkAgentExists(tenant_id, assistant_id);
|
|
510
|
+
if (!agentExists) {
|
|
511
|
+
reply.status(404).send({
|
|
512
|
+
success: false,
|
|
513
|
+
error: `Agent ${assistant_id} not found for tenant ${tenant_id}`
|
|
514
|
+
});
|
|
515
|
+
return;
|
|
516
|
+
}
|
|
484
517
|
const stream = await agent_stream({
|
|
485
518
|
assistant_id,
|
|
486
519
|
input,
|
|
@@ -500,13 +533,27 @@ var createRun = async (request, reply) => {
|
|
|
500
533
|
"Access-Control-Allow-Origin": "*"
|
|
501
534
|
});
|
|
502
535
|
try {
|
|
536
|
+
let chunkCount = 0;
|
|
503
537
|
for await (const chunk of stream) {
|
|
504
|
-
|
|
538
|
+
chunkCount++;
|
|
539
|
+
const success = reply.raw.write(`data: ${JSON.stringify(chunk)}
|
|
505
540
|
|
|
506
541
|
`);
|
|
542
|
+
if (!success) {
|
|
543
|
+
await new Promise((resolve) => reply.raw.once("drain", resolve));
|
|
544
|
+
}
|
|
507
545
|
}
|
|
508
546
|
} catch (error) {
|
|
509
|
-
|
|
547
|
+
const errorEvent = {
|
|
548
|
+
type: "error",
|
|
549
|
+
data: {
|
|
550
|
+
id: (0, import_uuid2.v4)(),
|
|
551
|
+
content: error.message || "Stream processing error"
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
reply.raw.write(`data: ${JSON.stringify(errorEvent)}
|
|
555
|
+
|
|
556
|
+
`);
|
|
510
557
|
} finally {
|
|
511
558
|
reply.raw.end();
|
|
512
559
|
}
|
|
@@ -561,7 +608,16 @@ var resumeStream = async (request, reply) => {
|
|
|
561
608
|
`);
|
|
562
609
|
}
|
|
563
610
|
} catch (error) {
|
|
564
|
-
|
|
611
|
+
const errorEvent = {
|
|
612
|
+
type: "error",
|
|
613
|
+
data: {
|
|
614
|
+
id: (0, import_uuid2.v4)(),
|
|
615
|
+
content: error.message || "Resume stream processing error"
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
reply.raw.write(`data: ${JSON.stringify(errorEvent)}
|
|
619
|
+
|
|
620
|
+
`);
|
|
565
621
|
} finally {
|
|
566
622
|
reply.raw.end();
|
|
567
623
|
}
|
|
@@ -672,9 +728,11 @@ var getAgentState = async (request, reply) => {
|
|
|
672
728
|
});
|
|
673
729
|
return;
|
|
674
730
|
}
|
|
731
|
+
const tenant_id = request.headers["x-tenant-id"];
|
|
675
732
|
const result = await agent_state({
|
|
676
733
|
assistant_id: assistantId,
|
|
677
|
-
thread_id
|
|
734
|
+
thread_id,
|
|
735
|
+
tenant_id
|
|
678
736
|
});
|
|
679
737
|
if (!result) {
|
|
680
738
|
reply.status(500).send(result);
|
|
@@ -774,11 +832,19 @@ var triggerAgentTask = async (request, reply) => {
|
|
|
774
832
|
// src/controllers/threads.ts
|
|
775
833
|
var import_core5 = require("@axiom-lattice/core");
|
|
776
834
|
var import_crypto2 = require("crypto");
|
|
835
|
+
function getTenantId2(request) {
|
|
836
|
+
const userTenantId = request.user?.tenantId;
|
|
837
|
+
if (userTenantId) {
|
|
838
|
+
return userTenantId;
|
|
839
|
+
}
|
|
840
|
+
return request.headers["x-tenant-id"] || "default";
|
|
841
|
+
}
|
|
777
842
|
async function getThreadList(request, reply) {
|
|
843
|
+
const tenantId = getTenantId2(request);
|
|
778
844
|
const { assistantId } = request.params;
|
|
779
845
|
const storeLattice = (0, import_core5.getStoreLattice)("default", "thread");
|
|
780
846
|
const threadStore = storeLattice.store;
|
|
781
|
-
const threads = await threadStore.getThreadsByAssistantId(assistantId);
|
|
847
|
+
const threads = await threadStore.getThreadsByAssistantId(tenantId, assistantId);
|
|
782
848
|
return {
|
|
783
849
|
success: true,
|
|
784
850
|
message: "Successfully retrieved thread list",
|
|
@@ -789,10 +855,11 @@ async function getThreadList(request, reply) {
|
|
|
789
855
|
};
|
|
790
856
|
}
|
|
791
857
|
async function getThread(request, reply) {
|
|
792
|
-
const
|
|
858
|
+
const tenantId = getTenantId2(request);
|
|
859
|
+
const { threadId } = request.params;
|
|
793
860
|
const storeLattice = (0, import_core5.getStoreLattice)("default", "thread");
|
|
794
861
|
const threadStore = storeLattice.store;
|
|
795
|
-
const thread = await threadStore.getThreadById(
|
|
862
|
+
const thread = await threadStore.getThreadById(tenantId, threadId);
|
|
796
863
|
if (!thread) {
|
|
797
864
|
return reply.status(404).send({
|
|
798
865
|
success: false,
|
|
@@ -806,12 +873,13 @@ async function getThread(request, reply) {
|
|
|
806
873
|
};
|
|
807
874
|
}
|
|
808
875
|
async function createThread(request, reply) {
|
|
876
|
+
const tenantId = getTenantId2(request);
|
|
809
877
|
const { assistantId } = request.params;
|
|
810
878
|
const data = request.body;
|
|
811
879
|
const threadId = (0, import_crypto2.randomUUID)();
|
|
812
880
|
const storeLattice = (0, import_core5.getStoreLattice)("default", "thread");
|
|
813
881
|
const threadStore = storeLattice.store;
|
|
814
|
-
const newThread = await threadStore.createThread(assistantId, threadId, data);
|
|
882
|
+
const newThread = await threadStore.createThread(tenantId, assistantId, threadId, data);
|
|
815
883
|
return reply.status(201).send({
|
|
816
884
|
success: true,
|
|
817
885
|
message: "Successfully created thread",
|
|
@@ -819,11 +887,12 @@ async function createThread(request, reply) {
|
|
|
819
887
|
});
|
|
820
888
|
}
|
|
821
889
|
async function updateThread(request, reply) {
|
|
822
|
-
const
|
|
890
|
+
const tenantId = getTenantId2(request);
|
|
891
|
+
const { threadId } = request.params;
|
|
823
892
|
const updates = request.body;
|
|
824
893
|
const storeLattice = (0, import_core5.getStoreLattice)("default", "thread");
|
|
825
894
|
const threadStore = storeLattice.store;
|
|
826
|
-
const exists = await threadStore.hasThread(
|
|
895
|
+
const exists = await threadStore.hasThread(tenantId, threadId);
|
|
827
896
|
if (!exists) {
|
|
828
897
|
return reply.status(404).send({
|
|
829
898
|
success: false,
|
|
@@ -831,7 +900,7 @@ async function updateThread(request, reply) {
|
|
|
831
900
|
});
|
|
832
901
|
}
|
|
833
902
|
const updatedThread = await threadStore.updateThread(
|
|
834
|
-
|
|
903
|
+
tenantId,
|
|
835
904
|
threadId,
|
|
836
905
|
updates
|
|
837
906
|
);
|
|
@@ -848,17 +917,18 @@ async function updateThread(request, reply) {
|
|
|
848
917
|
};
|
|
849
918
|
}
|
|
850
919
|
async function deleteThread(request, reply) {
|
|
851
|
-
const
|
|
920
|
+
const tenantId = getTenantId2(request);
|
|
921
|
+
const { threadId } = request.params;
|
|
852
922
|
const storeLattice = (0, import_core5.getStoreLattice)("default", "thread");
|
|
853
923
|
const threadStore = storeLattice.store;
|
|
854
|
-
const exists = await threadStore.hasThread(
|
|
924
|
+
const exists = await threadStore.hasThread(tenantId, threadId);
|
|
855
925
|
if (!exists) {
|
|
856
926
|
return reply.status(404).send({
|
|
857
927
|
success: false,
|
|
858
928
|
message: "Thread not found"
|
|
859
929
|
});
|
|
860
930
|
}
|
|
861
|
-
const deleted = await threadStore.deleteThread(
|
|
931
|
+
const deleted = await threadStore.deleteThread(tenantId, threadId);
|
|
862
932
|
if (!deleted) {
|
|
863
933
|
return reply.status(500).send({
|
|
864
934
|
success: false,
|
|
@@ -873,6 +943,13 @@ async function deleteThread(request, reply) {
|
|
|
873
943
|
|
|
874
944
|
// src/controllers/schedules.ts
|
|
875
945
|
var import_core6 = require("@axiom-lattice/core");
|
|
946
|
+
function getTenantId3(request) {
|
|
947
|
+
const userTenantId = request.user?.tenantId;
|
|
948
|
+
if (userTenantId) {
|
|
949
|
+
return userTenantId;
|
|
950
|
+
}
|
|
951
|
+
return request.headers["x-tenant-id"] || "default";
|
|
952
|
+
}
|
|
876
953
|
function getScheduleLattice() {
|
|
877
954
|
const keys = import_core6.scheduleLatticeManager.getLatticeKeys();
|
|
878
955
|
if (keys.length === 0) {
|
|
@@ -909,7 +986,9 @@ async function getThreadSchedules(request, reply) {
|
|
|
909
986
|
}
|
|
910
987
|
};
|
|
911
988
|
}
|
|
989
|
+
const tenantId = getTenantId3(request);
|
|
912
990
|
const filters = {
|
|
991
|
+
tenantId,
|
|
913
992
|
threadId,
|
|
914
993
|
assistantId
|
|
915
994
|
};
|
|
@@ -924,6 +1003,7 @@ async function getThreadSchedules(request, reply) {
|
|
|
924
1003
|
}
|
|
925
1004
|
const tasks = await storage.getAllTasks(filters);
|
|
926
1005
|
const total = await storage.countTasks({
|
|
1006
|
+
tenantId,
|
|
927
1007
|
threadId,
|
|
928
1008
|
assistantId,
|
|
929
1009
|
status
|
|
@@ -1382,6 +1462,13 @@ async function getHealth(request, reply) {
|
|
|
1382
1462
|
// src/controllers/skills.ts
|
|
1383
1463
|
var import_core9 = require("@axiom-lattice/core");
|
|
1384
1464
|
var import_core10 = require("@axiom-lattice/core");
|
|
1465
|
+
function getTenantId4(request) {
|
|
1466
|
+
const userTenantId = request.user?.tenantId;
|
|
1467
|
+
if (userTenantId) {
|
|
1468
|
+
return userTenantId;
|
|
1469
|
+
}
|
|
1470
|
+
return request.headers["x-tenant-id"] || "default";
|
|
1471
|
+
}
|
|
1385
1472
|
function serializeSkill(skill) {
|
|
1386
1473
|
const serialized = {
|
|
1387
1474
|
id: skill.id,
|
|
@@ -1404,9 +1491,10 @@ function serializeSkill(skill) {
|
|
|
1404
1491
|
}
|
|
1405
1492
|
async function getSkillList(request, reply) {
|
|
1406
1493
|
try {
|
|
1494
|
+
const tenantId = getTenantId4(request);
|
|
1407
1495
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1408
1496
|
const skillStore = storeLattice.store;
|
|
1409
|
-
const skills = await skillStore.getAllSkills();
|
|
1497
|
+
const skills = await skillStore.getAllSkills(tenantId);
|
|
1410
1498
|
const serializedSkills = skills.map(serializeSkill);
|
|
1411
1499
|
return {
|
|
1412
1500
|
success: true,
|
|
@@ -1429,10 +1517,11 @@ async function getSkillList(request, reply) {
|
|
|
1429
1517
|
}
|
|
1430
1518
|
async function getSkill(request, reply) {
|
|
1431
1519
|
try {
|
|
1520
|
+
const tenantId = getTenantId4(request);
|
|
1432
1521
|
const { id } = request.params;
|
|
1433
1522
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1434
1523
|
const skillStore = storeLattice.store;
|
|
1435
|
-
const skill = await skillStore.getSkillById(id);
|
|
1524
|
+
const skill = await skillStore.getSkillById(tenantId, id);
|
|
1436
1525
|
if (!skill) {
|
|
1437
1526
|
return reply.status(404).send({
|
|
1438
1527
|
success: false,
|
|
@@ -1481,16 +1570,17 @@ async function createSkill(request, reply) {
|
|
|
1481
1570
|
message: `id "${id}" must equal name "${data.name}" (name is used for path addressing)`
|
|
1482
1571
|
});
|
|
1483
1572
|
}
|
|
1573
|
+
const tenantId = getTenantId4(request);
|
|
1484
1574
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1485
1575
|
const skillStore = storeLattice.store;
|
|
1486
|
-
const exists = await skillStore.hasSkill(id);
|
|
1576
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1487
1577
|
if (exists) {
|
|
1488
1578
|
return reply.status(409).send({
|
|
1489
1579
|
success: false,
|
|
1490
1580
|
message: `Skill with id "${id}" already exists`
|
|
1491
1581
|
});
|
|
1492
1582
|
}
|
|
1493
|
-
const newSkill = await skillStore.createSkill(id, data);
|
|
1583
|
+
const newSkill = await skillStore.createSkill(tenantId, id, data);
|
|
1494
1584
|
return reply.status(201).send({
|
|
1495
1585
|
success: true,
|
|
1496
1586
|
message: "Successfully created skill",
|
|
@@ -1517,16 +1607,17 @@ async function updateSkill(request, reply) {
|
|
|
1517
1607
|
});
|
|
1518
1608
|
}
|
|
1519
1609
|
}
|
|
1610
|
+
const tenantId = getTenantId4(request);
|
|
1520
1611
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1521
1612
|
const skillStore = storeLattice.store;
|
|
1522
|
-
const exists = await skillStore.hasSkill(id);
|
|
1613
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1523
1614
|
if (!exists) {
|
|
1524
1615
|
return reply.status(404).send({
|
|
1525
1616
|
success: false,
|
|
1526
1617
|
message: "Skill not found"
|
|
1527
1618
|
});
|
|
1528
1619
|
}
|
|
1529
|
-
const updatedSkill = await skillStore.updateSkill(id, updates);
|
|
1620
|
+
const updatedSkill = await skillStore.updateSkill(tenantId, id, updates);
|
|
1530
1621
|
if (!updatedSkill) {
|
|
1531
1622
|
return reply.status(500).send({
|
|
1532
1623
|
success: false,
|
|
@@ -1548,16 +1639,17 @@ async function updateSkill(request, reply) {
|
|
|
1548
1639
|
async function deleteSkill(request, reply) {
|
|
1549
1640
|
try {
|
|
1550
1641
|
const { id } = request.params;
|
|
1642
|
+
const tenantId = getTenantId4(request);
|
|
1551
1643
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1552
1644
|
const skillStore = storeLattice.store;
|
|
1553
|
-
const exists = await skillStore.hasSkill(id);
|
|
1645
|
+
const exists = await skillStore.hasSkill(tenantId, id);
|
|
1554
1646
|
if (!exists) {
|
|
1555
1647
|
return reply.status(404).send({
|
|
1556
1648
|
success: false,
|
|
1557
1649
|
message: "Skill not found"
|
|
1558
1650
|
});
|
|
1559
1651
|
}
|
|
1560
|
-
const deleted = await skillStore.deleteSkill(id);
|
|
1652
|
+
const deleted = await skillStore.deleteSkill(tenantId, id);
|
|
1561
1653
|
if (!deleted) {
|
|
1562
1654
|
return reply.status(500).send({
|
|
1563
1655
|
success: false,
|
|
@@ -1588,9 +1680,10 @@ async function searchSkillsByMetadata(request, reply) {
|
|
|
1588
1680
|
}
|
|
1589
1681
|
});
|
|
1590
1682
|
}
|
|
1683
|
+
const tenantId = getTenantId4(request);
|
|
1591
1684
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1592
1685
|
const skillStore = storeLattice.store;
|
|
1593
|
-
const skills = await skillStore.searchByMetadata(key, value);
|
|
1686
|
+
const skills = await skillStore.searchByMetadata(tenantId, key, value);
|
|
1594
1687
|
const serializedSkills = skills.map(serializeSkill);
|
|
1595
1688
|
return {
|
|
1596
1689
|
success: true,
|
|
@@ -1624,9 +1717,10 @@ async function filterSkillsByCompatibility(request, reply) {
|
|
|
1624
1717
|
}
|
|
1625
1718
|
});
|
|
1626
1719
|
}
|
|
1720
|
+
const tenantId = getTenantId4(request);
|
|
1627
1721
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1628
1722
|
const skillStore = storeLattice.store;
|
|
1629
|
-
const skills = await skillStore.filterByCompatibility(compatibility);
|
|
1723
|
+
const skills = await skillStore.filterByCompatibility(tenantId, compatibility);
|
|
1630
1724
|
const serializedSkills = skills.map(serializeSkill);
|
|
1631
1725
|
return {
|
|
1632
1726
|
success: true,
|
|
@@ -1660,9 +1754,10 @@ async function filterSkillsByLicense(request, reply) {
|
|
|
1660
1754
|
}
|
|
1661
1755
|
});
|
|
1662
1756
|
}
|
|
1757
|
+
const tenantId = getTenantId4(request);
|
|
1663
1758
|
const storeLattice = (0, import_core9.getStoreLattice)("default", "skill");
|
|
1664
1759
|
const skillStore = storeLattice.store;
|
|
1665
|
-
const skills = await skillStore.filterByLicense(license);
|
|
1760
|
+
const skills = await skillStore.filterByLicense(tenantId, license);
|
|
1666
1761
|
const serializedSkills = skills.map(serializeSkill);
|
|
1667
1762
|
return {
|
|
1668
1763
|
success: true,
|
|
@@ -2152,17 +2247,17 @@ var ERROR_HTML = `<!DOCTYPE html>
|
|
|
2152
2247
|
</body>
|
|
2153
2248
|
</html>`;
|
|
2154
2249
|
var SandboxService = class {
|
|
2155
|
-
getFilesystemIsolatedLevel(assistantId) {
|
|
2156
|
-
const
|
|
2157
|
-
if (!
|
|
2250
|
+
getFilesystemIsolatedLevel(tenantId, assistantId) {
|
|
2251
|
+
const agentLattice = import_core12.agentLatticeManager.getAgentLatticeWithTenant(tenantId, assistantId);
|
|
2252
|
+
if (!agentLattice) {
|
|
2158
2253
|
return null;
|
|
2159
2254
|
}
|
|
2160
|
-
const agentLattice = (0, import_core12.getAgentLattice)(assistantId);
|
|
2161
2255
|
const filesystemConfig = agentLattice?.config?.middleware?.find((m) => m.type === "filesystem");
|
|
2162
2256
|
if (!filesystemConfig) {
|
|
2163
2257
|
return null;
|
|
2164
2258
|
}
|
|
2165
|
-
|
|
2259
|
+
const config = filesystemConfig.config;
|
|
2260
|
+
return config?.isolatedLevel || null;
|
|
2166
2261
|
}
|
|
2167
2262
|
computeSandboxName(assistantId, threadId, isolatedLevel) {
|
|
2168
2263
|
let sandboxName;
|
|
@@ -2181,7 +2276,7 @@ var SandboxService = class {
|
|
|
2181
2276
|
return (0, import_core12.normalizeSandboxName)(sandboxName);
|
|
2182
2277
|
}
|
|
2183
2278
|
getTargetUrl(sandboxName) {
|
|
2184
|
-
const sandboxManager = (0, import_core12.getSandBoxManager)(
|
|
2279
|
+
const sandboxManager = (0, import_core12.getSandBoxManager)();
|
|
2185
2280
|
return `${sandboxManager.getBaseURL()}/sandbox/${sandboxName}`;
|
|
2186
2281
|
}
|
|
2187
2282
|
async getVncHtml(sandboxName) {
|
|
@@ -2258,7 +2353,8 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2258
2353
|
async (request, reply) => {
|
|
2259
2354
|
console.log("[Sandbox Upload] Route matched:", request.url);
|
|
2260
2355
|
const { assistantId, threadId } = request.params;
|
|
2261
|
-
const
|
|
2356
|
+
const tenantId = request.headers["x-tenant-id"] || "default";
|
|
2357
|
+
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(tenantId, assistantId);
|
|
2262
2358
|
if (!isolatedLevel) {
|
|
2263
2359
|
return reply.status(500).send({ error: "Assistant sandbox config not found" });
|
|
2264
2360
|
}
|
|
@@ -2267,7 +2363,7 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2267
2363
|
threadId,
|
|
2268
2364
|
isolatedLevel
|
|
2269
2365
|
);
|
|
2270
|
-
const sandboxManager = (0, import_core13.getSandBoxManager)(
|
|
2366
|
+
const sandboxManager = (0, import_core13.getSandBoxManager)();
|
|
2271
2367
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2272
2368
|
try {
|
|
2273
2369
|
const data = await request.file();
|
|
@@ -2301,10 +2397,11 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2301
2397
|
async (request, reply) => {
|
|
2302
2398
|
const { assistantId, threadId } = request.params;
|
|
2303
2399
|
const { path: filePath } = request.query;
|
|
2400
|
+
const tenantId = request.headers["x-tenant-id"] || "default";
|
|
2304
2401
|
if (!filePath || typeof filePath !== "string") {
|
|
2305
2402
|
return reply.status(400).send({ error: "Query parameter 'path' is required" });
|
|
2306
2403
|
}
|
|
2307
|
-
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(assistantId);
|
|
2404
|
+
const isolatedLevel = sandboxService.getFilesystemIsolatedLevel(tenantId, assistantId);
|
|
2308
2405
|
if (!isolatedLevel) {
|
|
2309
2406
|
return reply.status(500).send({ error: "Assistant filesystem isolated level not found" });
|
|
2310
2407
|
}
|
|
@@ -2313,7 +2410,7 @@ function registerSandboxProxyRoutes(app2) {
|
|
|
2313
2410
|
threadId,
|
|
2314
2411
|
isolatedLevel
|
|
2315
2412
|
);
|
|
2316
|
-
const sandboxManager = (0, import_core13.getSandBoxManager)(
|
|
2413
|
+
const sandboxManager = (0, import_core13.getSandBoxManager)();
|
|
2317
2414
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2318
2415
|
try {
|
|
2319
2416
|
const resolvedPath = filePath.startsWith("/home/gem") ? filePath : `/home/gem/${filePath.replace(/^\//, "")}`;
|
|
@@ -2379,6 +2476,14 @@ var WorkspaceController = class {
|
|
|
2379
2476
|
this.projectStore = (0, import_core14.getStoreLattice)("default", "project").store;
|
|
2380
2477
|
}
|
|
2381
2478
|
getTenantId(request) {
|
|
2479
|
+
const userTenantId = request.user?.tenantId;
|
|
2480
|
+
if (userTenantId) {
|
|
2481
|
+
return userTenantId;
|
|
2482
|
+
}
|
|
2483
|
+
const queryTenantId = request.query?.tenantId;
|
|
2484
|
+
if (queryTenantId) {
|
|
2485
|
+
return String(queryTenantId);
|
|
2486
|
+
}
|
|
2382
2487
|
return request.headers["x-tenant-id"] || "default";
|
|
2383
2488
|
}
|
|
2384
2489
|
// ==================== Workspace CRUD ====================
|
|
@@ -2492,8 +2597,7 @@ var WorkspaceController = class {
|
|
|
2492
2597
|
return { success: true };
|
|
2493
2598
|
}
|
|
2494
2599
|
// ==================== File Operations ====================
|
|
2495
|
-
async getBackend(workspaceId, projectId) {
|
|
2496
|
-
const tenantId = "default";
|
|
2600
|
+
async getBackend(tenantId, workspaceId, projectId) {
|
|
2497
2601
|
const workspace = await this.workspaceStore.getWorkspaceById(
|
|
2498
2602
|
tenantId,
|
|
2499
2603
|
workspaceId
|
|
@@ -2502,18 +2606,24 @@ var WorkspaceController = class {
|
|
|
2502
2606
|
throw new Error("Workspace not found");
|
|
2503
2607
|
}
|
|
2504
2608
|
if (workspace.storageType === "sandbox") {
|
|
2505
|
-
const sandboxManager = (0, import_core16.getSandBoxManager)(
|
|
2609
|
+
const sandboxManager = (0, import_core16.getSandBoxManager)();
|
|
2506
2610
|
const sandboxName = "global";
|
|
2507
2611
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2508
|
-
return {
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2612
|
+
return {
|
|
2613
|
+
backend: new import_core15.SandboxFilesystem({
|
|
2614
|
+
sandboxInstance: sandbox,
|
|
2615
|
+
workingDirectory: `/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`
|
|
2616
|
+
}),
|
|
2617
|
+
workspace
|
|
2618
|
+
};
|
|
2512
2619
|
} else {
|
|
2513
|
-
return {
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2620
|
+
return {
|
|
2621
|
+
backend: new import_core15.FilesystemBackend({
|
|
2622
|
+
rootDir: `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`,
|
|
2623
|
+
virtualMode: true
|
|
2624
|
+
}),
|
|
2625
|
+
workspace
|
|
2626
|
+
};
|
|
2517
2627
|
}
|
|
2518
2628
|
}
|
|
2519
2629
|
getFilenameFromPath(filePath) {
|
|
@@ -2543,18 +2653,19 @@ var WorkspaceController = class {
|
|
|
2543
2653
|
return mimeTypes[ext] || "application/octet-stream";
|
|
2544
2654
|
}
|
|
2545
2655
|
async downloadFile(request, reply) {
|
|
2656
|
+
const tenantId = this.getTenantId(request);
|
|
2546
2657
|
const { workspaceId, projectId } = request.params;
|
|
2547
2658
|
const filePath = request.query.path;
|
|
2548
2659
|
if (!filePath) {
|
|
2549
2660
|
return reply.status(400).send({ success: false, error: "Path is required" });
|
|
2550
2661
|
}
|
|
2551
2662
|
try {
|
|
2552
|
-
const { workspace } = await this.getBackend(workspaceId, projectId);
|
|
2663
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2553
2664
|
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
2554
2665
|
if (workspace.storageType === "sandbox") {
|
|
2555
|
-
const sandboxManager = (0, import_core16.getSandBoxManager)(
|
|
2666
|
+
const sandboxManager = (0, import_core16.getSandBoxManager)();
|
|
2556
2667
|
const sandbox = await sandboxManager.createSandbox("global");
|
|
2557
|
-
const realPath = path.join("/home/gem/workspaces", workspaceId, projectId, resolvedPath);
|
|
2668
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
2558
2669
|
const filename2 = this.getFilenameFromPath(resolvedPath);
|
|
2559
2670
|
const inferredContentType = this.getMimeType(filename2);
|
|
2560
2671
|
const downloadResult = await sandbox.file.downloadFile({
|
|
@@ -2571,13 +2682,13 @@ var WorkspaceController = class {
|
|
|
2571
2682
|
const webStream = body.stream();
|
|
2572
2683
|
const nodeStream = import_stream2.Readable.fromWeb(webStream);
|
|
2573
2684
|
const contentType2 = body.contentType ?? inferredContentType;
|
|
2574
|
-
const contentDisposition2 = body.contentDisposition ?? `
|
|
2685
|
+
const contentDisposition2 = body.contentDisposition ?? `attachment; filename*=UTF-8''${encodeURIComponent(filename2)}`;
|
|
2575
2686
|
return reply.status(200).type(contentType2).header("Content-Disposition", contentDisposition2).send(nodeStream);
|
|
2576
2687
|
}
|
|
2577
2688
|
const bodyUnknown = downloadResult.body;
|
|
2578
2689
|
let buf;
|
|
2579
2690
|
let contentType = inferredContentType;
|
|
2580
|
-
let contentDisposition = `
|
|
2691
|
+
let contentDisposition = `attachment; filename*=UTF-8''${encodeURIComponent(filename2)}`;
|
|
2581
2692
|
if (bodyUnknown instanceof ArrayBuffer) {
|
|
2582
2693
|
buf = Buffer.from(bodyUnknown);
|
|
2583
2694
|
} else if (bodyUnknown instanceof Buffer) {
|
|
@@ -2595,28 +2706,96 @@ var WorkspaceController = class {
|
|
|
2595
2706
|
}
|
|
2596
2707
|
return reply.status(200).type(contentType).header("Content-Disposition", contentDisposition).send(buf);
|
|
2597
2708
|
}
|
|
2598
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2709
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2599
2710
|
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
2600
2711
|
const filename = this.getFilenameFromPath(resolvedPath);
|
|
2601
2712
|
const mimeType = this.getMimeType(filename);
|
|
2602
2713
|
const buffer = Buffer.from(content, "utf-8");
|
|
2603
|
-
return reply.status(200).type(mimeType).header("Content-Disposition", `
|
|
2714
|
+
return reply.status(200).type(mimeType).header("Content-Disposition", `attachment; filename*=UTF-8''${encodeURIComponent(filename)}`).send(buffer);
|
|
2604
2715
|
} catch (error) {
|
|
2605
2716
|
const message = error instanceof Error ? error.message : String(error);
|
|
2606
2717
|
return reply.status(502).send({ success: false, error: `Download proxy error: ${message}` });
|
|
2607
2718
|
}
|
|
2608
2719
|
}
|
|
2720
|
+
/**
|
|
2721
|
+
* View a file inline in the browser (not download).
|
|
2722
|
+
* Returns file content with inline Content-Disposition for preview.
|
|
2723
|
+
*/
|
|
2724
|
+
async viewFile(request, reply) {
|
|
2725
|
+
const tenantId = this.getTenantId(request);
|
|
2726
|
+
const { workspaceId, projectId } = request.params;
|
|
2727
|
+
const filePath = request.query.path;
|
|
2728
|
+
if (!filePath) {
|
|
2729
|
+
return reply.status(400).send({ success: false, error: "Path is required" });
|
|
2730
|
+
}
|
|
2731
|
+
try {
|
|
2732
|
+
const { workspace } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2733
|
+
const resolvedPath = filePath.startsWith("/") ? filePath : `/${filePath}`;
|
|
2734
|
+
if (workspace.storageType === "sandbox") {
|
|
2735
|
+
const sandboxManager = (0, import_core16.getSandBoxManager)();
|
|
2736
|
+
const sandbox = await sandboxManager.createSandbox("global");
|
|
2737
|
+
const realPath = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId, resolvedPath);
|
|
2738
|
+
const filename2 = this.getFilenameFromPath(resolvedPath);
|
|
2739
|
+
const inferredContentType = this.getMimeType(filename2);
|
|
2740
|
+
const downloadResult = await sandbox.file.downloadFile({
|
|
2741
|
+
path: realPath
|
|
2742
|
+
});
|
|
2743
|
+
if (!downloadResult.ok) {
|
|
2744
|
+
return reply.status(502).send({
|
|
2745
|
+
success: false,
|
|
2746
|
+
error: `View error: ${JSON.stringify(downloadResult.error)}`
|
|
2747
|
+
});
|
|
2748
|
+
}
|
|
2749
|
+
const body = downloadResult.body;
|
|
2750
|
+
if (typeof body?.stream === "function") {
|
|
2751
|
+
const webStream = body.stream();
|
|
2752
|
+
const nodeStream = import_stream2.Readable.fromWeb(webStream);
|
|
2753
|
+
const contentType2 = body.contentType ?? inferredContentType;
|
|
2754
|
+
return reply.status(200).type(contentType2).header("Content-Disposition", "inline").send(nodeStream);
|
|
2755
|
+
}
|
|
2756
|
+
const bodyUnknown = downloadResult.body;
|
|
2757
|
+
let buf;
|
|
2758
|
+
let contentType = inferredContentType;
|
|
2759
|
+
if (bodyUnknown instanceof ArrayBuffer) {
|
|
2760
|
+
buf = Buffer.from(bodyUnknown);
|
|
2761
|
+
} else if (bodyUnknown instanceof Buffer) {
|
|
2762
|
+
buf = bodyUnknown;
|
|
2763
|
+
} else if (bodyUnknown && typeof bodyUnknown.arrayBuffer === "function") {
|
|
2764
|
+
const res = bodyUnknown;
|
|
2765
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
2766
|
+
if (res.headers?.get("content-type")) contentType = res.headers.get("content-type");
|
|
2767
|
+
} else if (bodyUnknown && typeof bodyUnknown.blob === "function") {
|
|
2768
|
+
const blob = await bodyUnknown.blob();
|
|
2769
|
+
buf = Buffer.from(await blob.arrayBuffer());
|
|
2770
|
+
} else {
|
|
2771
|
+
return reply.status(502).send({ success: false, error: "Unexpected view response format" });
|
|
2772
|
+
}
|
|
2773
|
+
return reply.status(200).type(contentType).header("Content-Disposition", "inline").send(buf);
|
|
2774
|
+
}
|
|
2775
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2776
|
+
const content = await backend.read(resolvedPath, 0, Infinity);
|
|
2777
|
+
const filename = this.getFilenameFromPath(resolvedPath);
|
|
2778
|
+
const mimeType = this.getMimeType(filename);
|
|
2779
|
+
const buffer = Buffer.from(content, "utf-8");
|
|
2780
|
+
return reply.status(200).type(mimeType).header("Content-Disposition", "inline").send(buffer);
|
|
2781
|
+
} catch (error) {
|
|
2782
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2783
|
+
return reply.status(502).send({ success: false, error: `View proxy error: ${message}` });
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2609
2786
|
async listPath(request) {
|
|
2787
|
+
const tenantId = this.getTenantId(request);
|
|
2610
2788
|
const { workspaceId, projectId } = request.params;
|
|
2611
2789
|
const path2 = request.query.path || "/";
|
|
2612
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2790
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2613
2791
|
const files = await backend.lsInfo(path2);
|
|
2614
2792
|
return { success: true, data: files };
|
|
2615
2793
|
}
|
|
2616
2794
|
async readFile(request) {
|
|
2795
|
+
const tenantId = this.getTenantId(request);
|
|
2617
2796
|
const { workspaceId, projectId } = request.params;
|
|
2618
2797
|
const { path: path2, offset = 0, limit = 1e3 } = request.query;
|
|
2619
|
-
const { backend } = await this.getBackend(workspaceId, projectId);
|
|
2798
|
+
const { backend } = await this.getBackend(tenantId, workspaceId, projectId);
|
|
2620
2799
|
const content = await backend.read(path2, Number(offset), Number(limit));
|
|
2621
2800
|
return { success: true, data: { content, offset, limit } };
|
|
2622
2801
|
}
|
|
@@ -2653,10 +2832,10 @@ var WorkspaceController = class {
|
|
|
2653
2832
|
return reply.status(400).send({ success: false, error: "Invalid path parameter" });
|
|
2654
2833
|
}
|
|
2655
2834
|
if (workspace.storageType === "sandbox") {
|
|
2656
|
-
const sandboxManager = (0, import_core16.getSandBoxManager)(
|
|
2835
|
+
const sandboxManager = (0, import_core16.getSandBoxManager)();
|
|
2657
2836
|
const sandboxName = "global";
|
|
2658
2837
|
const sandbox = await sandboxManager.createSandbox(sandboxName);
|
|
2659
|
-
const baseDir = path.join("/home/gem/workspaces", workspaceId, projectId);
|
|
2838
|
+
const baseDir = path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId);
|
|
2660
2839
|
const realPath = pathValue ? path.join(baseDir, pathValue, filename) : path.join(baseDir, filename);
|
|
2661
2840
|
const uploadResult = await sandbox.file.uploadFile({
|
|
2662
2841
|
file: buffer,
|
|
@@ -2668,7 +2847,7 @@ var WorkspaceController = class {
|
|
|
2668
2847
|
error: `Upload error: ${JSON.stringify(uploadResult.error)}`
|
|
2669
2848
|
});
|
|
2670
2849
|
}
|
|
2671
|
-
const relativePath = uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/workspaces", workspaceId, projectId), "") || (pathValue ? `/${pathValue}/${filename}` : `/${filename}`);
|
|
2850
|
+
const relativePath = uploadResult.body?.data?.file_path?.replace(path.join("/home/gem/tenants", tenantId, "workspaces", workspaceId, projectId), "") || (pathValue ? `/${pathValue}/${filename}` : `/${filename}`);
|
|
2672
2851
|
const result2 = {
|
|
2673
2852
|
path: relativePath,
|
|
2674
2853
|
name: filename,
|
|
@@ -2678,7 +2857,7 @@ var WorkspaceController = class {
|
|
|
2678
2857
|
};
|
|
2679
2858
|
return reply.status(200).send({ success: true, data: result2 });
|
|
2680
2859
|
}
|
|
2681
|
-
const rootDir = `/lattice_store/workspaces/${workspaceId}/${projectId}`;
|
|
2860
|
+
const rootDir = `/lattice_store/tenants/${tenantId}/workspaces/${workspaceId}/${projectId}`;
|
|
2682
2861
|
const targetDir = pathValue ? path.join(rootDir, pathValue) : rootDir;
|
|
2683
2862
|
const targetPath = path.join(targetDir, filename);
|
|
2684
2863
|
await fs.mkdir(path.dirname(targetPath), { recursive: true });
|
|
@@ -2752,16 +2931,24 @@ function registerWorkspaceRoutes(app2) {
|
|
|
2752
2931
|
"/api/workspaces/:workspaceId/projects/:projectId/downloadfile",
|
|
2753
2932
|
controller.downloadFile.bind(controller)
|
|
2754
2933
|
);
|
|
2934
|
+
app2.get(
|
|
2935
|
+
"/api/workspaces/:workspaceId/projects/:projectId/viewfile",
|
|
2936
|
+
controller.viewFile.bind(controller)
|
|
2937
|
+
);
|
|
2755
2938
|
}
|
|
2756
2939
|
|
|
2757
2940
|
// src/controllers/database-configs.ts
|
|
2758
2941
|
var import_core17 = require("@axiom-lattice/core");
|
|
2759
2942
|
var import_crypto3 = require("crypto");
|
|
2760
|
-
function
|
|
2943
|
+
function getTenantId5(request) {
|
|
2944
|
+
const userTenantId = request.user?.tenantId;
|
|
2945
|
+
if (userTenantId) {
|
|
2946
|
+
return userTenantId;
|
|
2947
|
+
}
|
|
2761
2948
|
return request.headers["x-tenant-id"] || "default";
|
|
2762
2949
|
}
|
|
2763
2950
|
async function getDatabaseConfigList(request, reply) {
|
|
2764
|
-
const tenantId =
|
|
2951
|
+
const tenantId = getTenantId5(request);
|
|
2765
2952
|
try {
|
|
2766
2953
|
const storeLattice = (0, import_core17.getStoreLattice)("default", "database");
|
|
2767
2954
|
const store = storeLattice.store;
|
|
@@ -2791,7 +2978,7 @@ async function getDatabaseConfigList(request, reply) {
|
|
|
2791
2978
|
}
|
|
2792
2979
|
}
|
|
2793
2980
|
async function getDatabaseConfig(request, reply) {
|
|
2794
|
-
const tenantId =
|
|
2981
|
+
const tenantId = getTenantId5(request);
|
|
2795
2982
|
const { key } = request.params;
|
|
2796
2983
|
try {
|
|
2797
2984
|
const storeLattice = (0, import_core17.getStoreLattice)("default", "database");
|
|
@@ -2817,7 +3004,7 @@ async function getDatabaseConfig(request, reply) {
|
|
|
2817
3004
|
}
|
|
2818
3005
|
}
|
|
2819
3006
|
async function createDatabaseConfig(request, reply) {
|
|
2820
|
-
const tenantId =
|
|
3007
|
+
const tenantId = getTenantId5(request);
|
|
2821
3008
|
const body = request.body;
|
|
2822
3009
|
try {
|
|
2823
3010
|
const storeLattice = (0, import_core17.getStoreLattice)("default", "database");
|
|
@@ -2833,7 +3020,7 @@ async function createDatabaseConfig(request, reply) {
|
|
|
2833
3020
|
const id = body.id || (0, import_crypto3.randomUUID)();
|
|
2834
3021
|
const config = await store.createConfig(tenantId, id, body);
|
|
2835
3022
|
try {
|
|
2836
|
-
import_core17.sqlDatabaseManager.registerDatabase(config.key, config.config);
|
|
3023
|
+
import_core17.sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
|
|
2837
3024
|
} catch (error) {
|
|
2838
3025
|
console.warn("Failed to auto-register database:", error);
|
|
2839
3026
|
}
|
|
@@ -2852,7 +3039,7 @@ async function createDatabaseConfig(request, reply) {
|
|
|
2852
3039
|
}
|
|
2853
3040
|
}
|
|
2854
3041
|
async function updateDatabaseConfig(request, reply) {
|
|
2855
|
-
const tenantId =
|
|
3042
|
+
const tenantId = getTenantId5(request);
|
|
2856
3043
|
const { key } = request.params;
|
|
2857
3044
|
const updates = request.body;
|
|
2858
3045
|
try {
|
|
@@ -2875,7 +3062,7 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
2875
3062
|
}
|
|
2876
3063
|
if (updates.config) {
|
|
2877
3064
|
try {
|
|
2878
|
-
import_core17.sqlDatabaseManager.registerDatabase(updated.key, updated.config);
|
|
3065
|
+
import_core17.sqlDatabaseManager.registerDatabase(tenantId, updated.key, updated.config);
|
|
2879
3066
|
} catch (error) {
|
|
2880
3067
|
console.warn("Failed to re-register database:", error);
|
|
2881
3068
|
}
|
|
@@ -2894,7 +3081,7 @@ async function updateDatabaseConfig(request, reply) {
|
|
|
2894
3081
|
}
|
|
2895
3082
|
}
|
|
2896
3083
|
async function deleteDatabaseConfig(request, reply) {
|
|
2897
|
-
const tenantId =
|
|
3084
|
+
const tenantId = getTenantId5(request);
|
|
2898
3085
|
const { keyOrId } = request.params;
|
|
2899
3086
|
try {
|
|
2900
3087
|
const storeLattice = (0, import_core17.getStoreLattice)("default", "database");
|
|
@@ -2924,8 +3111,8 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
2924
3111
|
};
|
|
2925
3112
|
}
|
|
2926
3113
|
try {
|
|
2927
|
-
if (import_core17.sqlDatabaseManager.hasDatabase(configKey)) {
|
|
2928
|
-
await import_core17.sqlDatabaseManager.removeDatabase(configKey);
|
|
3114
|
+
if (import_core17.sqlDatabaseManager.hasDatabase(tenantId, configKey)) {
|
|
3115
|
+
await import_core17.sqlDatabaseManager.removeDatabase(tenantId, configKey);
|
|
2929
3116
|
}
|
|
2930
3117
|
} catch (error) {
|
|
2931
3118
|
console.warn("Failed to remove from SqlDatabaseManager:", error);
|
|
@@ -2943,7 +3130,7 @@ async function deleteDatabaseConfig(request, reply) {
|
|
|
2943
3130
|
}
|
|
2944
3131
|
}
|
|
2945
3132
|
async function testDatabaseConnection(request, reply) {
|
|
2946
|
-
const tenantId =
|
|
3133
|
+
const tenantId = getTenantId5(request);
|
|
2947
3134
|
const { key } = request.params;
|
|
2948
3135
|
try {
|
|
2949
3136
|
const storeLattice = (0, import_core17.getStoreLattice)("default", "database");
|
|
@@ -2957,16 +3144,16 @@ async function testDatabaseConnection(request, reply) {
|
|
|
2957
3144
|
};
|
|
2958
3145
|
}
|
|
2959
3146
|
const testKey = `__test_${key}_${Date.now()}`;
|
|
2960
|
-
import_core17.sqlDatabaseManager.registerDatabase(testKey, config.config);
|
|
3147
|
+
import_core17.sqlDatabaseManager.registerDatabase(tenantId, testKey, config.config);
|
|
2961
3148
|
const startTime = Date.now();
|
|
2962
|
-
const db = import_core17.sqlDatabaseManager.getDatabase(testKey);
|
|
3149
|
+
const db = import_core17.sqlDatabaseManager.getDatabase(tenantId, testKey);
|
|
2963
3150
|
try {
|
|
2964
3151
|
await db.connect();
|
|
2965
3152
|
await db.listTables();
|
|
2966
3153
|
const latency = Date.now() - startTime;
|
|
2967
3154
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
2968
3155
|
await db.disconnect();
|
|
2969
|
-
await import_core17.sqlDatabaseManager.removeDatabase(testKey);
|
|
3156
|
+
await import_core17.sqlDatabaseManager.removeDatabase(tenantId, testKey);
|
|
2970
3157
|
return {
|
|
2971
3158
|
success: true,
|
|
2972
3159
|
message: "Connection test successful",
|
|
@@ -2978,7 +3165,7 @@ async function testDatabaseConnection(request, reply) {
|
|
|
2978
3165
|
} catch (error) {
|
|
2979
3166
|
try {
|
|
2980
3167
|
await db.disconnect();
|
|
2981
|
-
await import_core17.sqlDatabaseManager.removeDatabase(testKey);
|
|
3168
|
+
await import_core17.sqlDatabaseManager.removeDatabase(tenantId, testKey);
|
|
2982
3169
|
} catch {
|
|
2983
3170
|
}
|
|
2984
3171
|
return {
|
|
@@ -3032,11 +3219,15 @@ function registerDatabaseConfigRoutes(app2) {
|
|
|
3032
3219
|
// src/controllers/metrics-configs.ts
|
|
3033
3220
|
var import_core18 = require("@axiom-lattice/core");
|
|
3034
3221
|
var import_crypto4 = require("crypto");
|
|
3035
|
-
function
|
|
3222
|
+
function getTenantId6(request) {
|
|
3223
|
+
const userTenantId = request.user?.tenantId;
|
|
3224
|
+
if (userTenantId) {
|
|
3225
|
+
return userTenantId;
|
|
3226
|
+
}
|
|
3036
3227
|
return request.headers["x-tenant-id"] || "default";
|
|
3037
3228
|
}
|
|
3038
3229
|
async function getMetricsServerConfigList(request, reply) {
|
|
3039
|
-
const tenantId =
|
|
3230
|
+
const tenantId = getTenantId6(request);
|
|
3040
3231
|
try {
|
|
3041
3232
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
3042
3233
|
const store = storeLattice.store;
|
|
@@ -3062,7 +3253,7 @@ async function getMetricsServerConfigList(request, reply) {
|
|
|
3062
3253
|
}
|
|
3063
3254
|
}
|
|
3064
3255
|
async function getMetricsServerConfig(request, reply) {
|
|
3065
|
-
const tenantId =
|
|
3256
|
+
const tenantId = getTenantId6(request);
|
|
3066
3257
|
const { key } = request.params;
|
|
3067
3258
|
try {
|
|
3068
3259
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3088,7 +3279,7 @@ async function getMetricsServerConfig(request, reply) {
|
|
|
3088
3279
|
}
|
|
3089
3280
|
}
|
|
3090
3281
|
async function createMetricsServerConfig(request, reply) {
|
|
3091
|
-
const tenantId =
|
|
3282
|
+
const tenantId = getTenantId6(request);
|
|
3092
3283
|
const body = request.body;
|
|
3093
3284
|
try {
|
|
3094
3285
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3120,7 +3311,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3120
3311
|
};
|
|
3121
3312
|
const config = await store.createConfig(tenantId, id, configData);
|
|
3122
3313
|
try {
|
|
3123
|
-
import_core18.metricsServerManager.registerServer(config.key, config.config);
|
|
3314
|
+
import_core18.metricsServerManager.registerServer(tenantId, config.key, config.config);
|
|
3124
3315
|
} catch (error) {
|
|
3125
3316
|
console.warn("Failed to auto-register metrics server:", error);
|
|
3126
3317
|
}
|
|
@@ -3139,7 +3330,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
3139
3330
|
}
|
|
3140
3331
|
}
|
|
3141
3332
|
async function updateMetricsServerConfig(request, reply) {
|
|
3142
|
-
const tenantId =
|
|
3333
|
+
const tenantId = getTenantId6(request);
|
|
3143
3334
|
const { key } = request.params;
|
|
3144
3335
|
const updates = request.body;
|
|
3145
3336
|
try {
|
|
@@ -3171,7 +3362,7 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3171
3362
|
}
|
|
3172
3363
|
if (updates.config) {
|
|
3173
3364
|
try {
|
|
3174
|
-
import_core18.metricsServerManager.registerServer(updated.key, updated.config);
|
|
3365
|
+
import_core18.metricsServerManager.registerServer(tenantId, updated.key, updated.config);
|
|
3175
3366
|
} catch (error) {
|
|
3176
3367
|
console.warn("Failed to re-register metrics server:", error);
|
|
3177
3368
|
}
|
|
@@ -3190,7 +3381,7 @@ async function updateMetricsServerConfig(request, reply) {
|
|
|
3190
3381
|
}
|
|
3191
3382
|
}
|
|
3192
3383
|
async function deleteMetricsServerConfig(request, reply) {
|
|
3193
|
-
const tenantId =
|
|
3384
|
+
const tenantId = getTenantId6(request);
|
|
3194
3385
|
const { keyOrId } = request.params;
|
|
3195
3386
|
try {
|
|
3196
3387
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3218,8 +3409,8 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3218
3409
|
};
|
|
3219
3410
|
}
|
|
3220
3411
|
try {
|
|
3221
|
-
if (import_core18.metricsServerManager.hasServer(configKey)) {
|
|
3222
|
-
import_core18.metricsServerManager.removeServer(configKey);
|
|
3412
|
+
if (import_core18.metricsServerManager.hasServer(tenantId, configKey)) {
|
|
3413
|
+
import_core18.metricsServerManager.removeServer(tenantId, configKey);
|
|
3223
3414
|
}
|
|
3224
3415
|
} catch (error) {
|
|
3225
3416
|
console.warn("Failed to remove from MetricsServerManager:", error);
|
|
@@ -3237,7 +3428,7 @@ async function deleteMetricsServerConfig(request, reply) {
|
|
|
3237
3428
|
}
|
|
3238
3429
|
}
|
|
3239
3430
|
async function testMetricsServerConnection(request, reply) {
|
|
3240
|
-
const tenantId =
|
|
3431
|
+
const tenantId = getTenantId6(request);
|
|
3241
3432
|
const { key } = request.params;
|
|
3242
3433
|
try {
|
|
3243
3434
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3251,11 +3442,11 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3251
3442
|
};
|
|
3252
3443
|
}
|
|
3253
3444
|
const testKey = `__test_${key}_${Date.now()}`;
|
|
3254
|
-
import_core18.metricsServerManager.registerServer(testKey, config.config);
|
|
3445
|
+
import_core18.metricsServerManager.registerServer(tenantId, testKey, config.config);
|
|
3255
3446
|
try {
|
|
3256
|
-
const client = import_core18.metricsServerManager.getClient(testKey);
|
|
3447
|
+
const client = import_core18.metricsServerManager.getClient(tenantId, testKey);
|
|
3257
3448
|
const result = await client.testConnection();
|
|
3258
|
-
import_core18.metricsServerManager.removeServer(testKey);
|
|
3449
|
+
import_core18.metricsServerManager.removeServer(tenantId, testKey);
|
|
3259
3450
|
return {
|
|
3260
3451
|
success: true,
|
|
3261
3452
|
message: result.connected ? "Connection test successful" : "Connection test failed",
|
|
@@ -3263,7 +3454,7 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3263
3454
|
};
|
|
3264
3455
|
} catch (error) {
|
|
3265
3456
|
try {
|
|
3266
|
-
import_core18.metricsServerManager.removeServer(testKey);
|
|
3457
|
+
import_core18.metricsServerManager.removeServer(tenantId, testKey);
|
|
3267
3458
|
} catch {
|
|
3268
3459
|
}
|
|
3269
3460
|
return {
|
|
@@ -3288,7 +3479,7 @@ async function testMetricsServerConnection(request, reply) {
|
|
|
3288
3479
|
}
|
|
3289
3480
|
}
|
|
3290
3481
|
async function listAvailableMetrics(request, reply) {
|
|
3291
|
-
const tenantId =
|
|
3482
|
+
const tenantId = getTenantId6(request);
|
|
3292
3483
|
const { key } = request.params;
|
|
3293
3484
|
try {
|
|
3294
3485
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3301,10 +3492,10 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3301
3492
|
message: "Metrics server configuration not found"
|
|
3302
3493
|
};
|
|
3303
3494
|
}
|
|
3304
|
-
if (!import_core18.metricsServerManager.hasServer(key)) {
|
|
3305
|
-
import_core18.metricsServerManager.registerServer(key, config.config);
|
|
3495
|
+
if (!import_core18.metricsServerManager.hasServer(tenantId, key)) {
|
|
3496
|
+
import_core18.metricsServerManager.registerServer(tenantId, key, config.config);
|
|
3306
3497
|
}
|
|
3307
|
-
const client = import_core18.metricsServerManager.getClient(key);
|
|
3498
|
+
const client = import_core18.metricsServerManager.getClient(tenantId, key);
|
|
3308
3499
|
const metrics = await client.listMetrics();
|
|
3309
3500
|
return {
|
|
3310
3501
|
success: true,
|
|
@@ -3326,7 +3517,7 @@ async function listAvailableMetrics(request, reply) {
|
|
|
3326
3517
|
}
|
|
3327
3518
|
}
|
|
3328
3519
|
async function queryMetricsData(request, reply) {
|
|
3329
|
-
const tenantId =
|
|
3520
|
+
const tenantId = getTenantId6(request);
|
|
3330
3521
|
const { key } = request.params;
|
|
3331
3522
|
const { metricName, startTime, endTime, step, labels } = request.body;
|
|
3332
3523
|
try {
|
|
@@ -3347,10 +3538,10 @@ async function queryMetricsData(request, reply) {
|
|
|
3347
3538
|
message: "metricName is required"
|
|
3348
3539
|
};
|
|
3349
3540
|
}
|
|
3350
|
-
if (!import_core18.metricsServerManager.hasServer(key)) {
|
|
3351
|
-
import_core18.metricsServerManager.registerServer(key, config.config);
|
|
3541
|
+
if (!import_core18.metricsServerManager.hasServer(tenantId, key)) {
|
|
3542
|
+
import_core18.metricsServerManager.registerServer(tenantId, key, config.config);
|
|
3352
3543
|
}
|
|
3353
|
-
const client = import_core18.metricsServerManager.getClient(key);
|
|
3544
|
+
const client = import_core18.metricsServerManager.getClient(tenantId, key);
|
|
3354
3545
|
const result = await client.queryMetricData(metricName, {
|
|
3355
3546
|
startTime,
|
|
3356
3547
|
endTime,
|
|
@@ -3374,7 +3565,7 @@ async function queryMetricsData(request, reply) {
|
|
|
3374
3565
|
}
|
|
3375
3566
|
}
|
|
3376
3567
|
async function getDataSources(request, reply) {
|
|
3377
|
-
const tenantId =
|
|
3568
|
+
const tenantId = getTenantId6(request);
|
|
3378
3569
|
const { key } = request.params;
|
|
3379
3570
|
try {
|
|
3380
3571
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3415,7 +3606,7 @@ async function getDataSources(request, reply) {
|
|
|
3415
3606
|
}
|
|
3416
3607
|
}
|
|
3417
3608
|
async function getDatasourceMetrics(request, reply) {
|
|
3418
|
-
const tenantId =
|
|
3609
|
+
const tenantId = getTenantId6(request);
|
|
3419
3610
|
const { key, datasourceId } = request.params;
|
|
3420
3611
|
try {
|
|
3421
3612
|
const storeLattice = (0, import_core18.getStoreLattice)("default", "metrics");
|
|
@@ -3452,7 +3643,7 @@ async function getDatasourceMetrics(request, reply) {
|
|
|
3452
3643
|
}
|
|
3453
3644
|
}
|
|
3454
3645
|
async function querySemanticMetrics(request, reply) {
|
|
3455
|
-
const tenantId =
|
|
3646
|
+
const tenantId = getTenantId6(request);
|
|
3456
3647
|
const { key } = request.params;
|
|
3457
3648
|
const body = request.body;
|
|
3458
3649
|
try {
|
|
@@ -3483,14 +3674,32 @@ async function querySemanticMetrics(request, reply) {
|
|
|
3483
3674
|
const semanticConfig = config.config;
|
|
3484
3675
|
const client = new import_core18.SemanticMetricsClient(semanticConfig);
|
|
3485
3676
|
const result = await client.semanticQuery(body);
|
|
3677
|
+
const allDataPoints = [];
|
|
3678
|
+
const metricNames = [];
|
|
3679
|
+
for (const metricResult of result.results) {
|
|
3680
|
+
metricNames.push(metricResult.metricName);
|
|
3681
|
+
for (const row of metricResult.rows) {
|
|
3682
|
+
allDataPoints.push({
|
|
3683
|
+
timestamp: row.timestamp ? new Date(row.timestamp).getTime() : void 0,
|
|
3684
|
+
value: typeof row.value === "number" ? row.value : 0,
|
|
3685
|
+
metricName: metricResult.metricName,
|
|
3686
|
+
labels: Object.fromEntries(
|
|
3687
|
+
Object.entries(row).filter(([k]) => k !== "value" && k !== "timestamp").map(([k, v]) => [k, String(v)])
|
|
3688
|
+
)
|
|
3689
|
+
});
|
|
3690
|
+
}
|
|
3691
|
+
}
|
|
3486
3692
|
return {
|
|
3487
3693
|
success: true,
|
|
3488
3694
|
message: "Semantic query executed successfully",
|
|
3489
3695
|
data: {
|
|
3490
3696
|
datasourceId: result.datasourceId,
|
|
3491
|
-
metrics:
|
|
3492
|
-
dataPoints:
|
|
3493
|
-
metadata:
|
|
3697
|
+
metrics: metricNames,
|
|
3698
|
+
dataPoints: allDataPoints,
|
|
3699
|
+
metadata: {
|
|
3700
|
+
rowCount: allDataPoints.length,
|
|
3701
|
+
queryTimeMs: result.totalExecutionTimeMs
|
|
3702
|
+
}
|
|
3494
3703
|
}
|
|
3495
3704
|
};
|
|
3496
3705
|
} catch (error) {
|
|
@@ -3589,11 +3798,15 @@ function registerMetricsServerConfigRoutes(app2) {
|
|
|
3589
3798
|
// src/controllers/mcp-configs.ts
|
|
3590
3799
|
var import_core19 = require("@axiom-lattice/core");
|
|
3591
3800
|
var import_crypto5 = require("crypto");
|
|
3592
|
-
function
|
|
3801
|
+
function getTenantId7(request) {
|
|
3802
|
+
const userTenantId = request.user?.tenantId;
|
|
3803
|
+
if (userTenantId) {
|
|
3804
|
+
return userTenantId;
|
|
3805
|
+
}
|
|
3593
3806
|
return request.headers["x-tenant-id"] || "default";
|
|
3594
3807
|
}
|
|
3595
3808
|
async function getMcpServerConfigList(request, reply) {
|
|
3596
|
-
const tenantId =
|
|
3809
|
+
const tenantId = getTenantId7(request);
|
|
3597
3810
|
try {
|
|
3598
3811
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
3599
3812
|
const store = storeLattice.store;
|
|
@@ -3619,7 +3832,7 @@ async function getMcpServerConfigList(request, reply) {
|
|
|
3619
3832
|
}
|
|
3620
3833
|
}
|
|
3621
3834
|
async function getMcpServerConfig(request, reply) {
|
|
3622
|
-
const tenantId =
|
|
3835
|
+
const tenantId = getTenantId7(request);
|
|
3623
3836
|
const { key } = request.params;
|
|
3624
3837
|
try {
|
|
3625
3838
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3645,7 +3858,7 @@ async function getMcpServerConfig(request, reply) {
|
|
|
3645
3858
|
}
|
|
3646
3859
|
}
|
|
3647
3860
|
async function createMcpServerConfig(request, reply) {
|
|
3648
|
-
const tenantId =
|
|
3861
|
+
const tenantId = getTenantId7(request);
|
|
3649
3862
|
const body = request.body;
|
|
3650
3863
|
try {
|
|
3651
3864
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3684,7 +3897,7 @@ async function createMcpServerConfig(request, reply) {
|
|
|
3684
3897
|
}
|
|
3685
3898
|
}
|
|
3686
3899
|
async function updateMcpServerConfig(request, reply) {
|
|
3687
|
-
const tenantId =
|
|
3900
|
+
const tenantId = getTenantId7(request);
|
|
3688
3901
|
const { key } = request.params;
|
|
3689
3902
|
const updates = request.body;
|
|
3690
3903
|
try {
|
|
@@ -3734,7 +3947,7 @@ async function updateMcpServerConfig(request, reply) {
|
|
|
3734
3947
|
}
|
|
3735
3948
|
}
|
|
3736
3949
|
async function deleteMcpServerConfig(request, reply) {
|
|
3737
|
-
const tenantId =
|
|
3950
|
+
const tenantId = getTenantId7(request);
|
|
3738
3951
|
const { keyOrId } = request.params;
|
|
3739
3952
|
try {
|
|
3740
3953
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3781,7 +3994,7 @@ async function deleteMcpServerConfig(request, reply) {
|
|
|
3781
3994
|
}
|
|
3782
3995
|
}
|
|
3783
3996
|
async function testMcpServerConnection(request, reply) {
|
|
3784
|
-
const tenantId =
|
|
3997
|
+
const tenantId = getTenantId7(request);
|
|
3785
3998
|
const { key } = request.params;
|
|
3786
3999
|
try {
|
|
3787
4000
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3834,7 +4047,7 @@ async function testMcpServerConnection(request, reply) {
|
|
|
3834
4047
|
}
|
|
3835
4048
|
}
|
|
3836
4049
|
async function listMcpServerTools(request, reply) {
|
|
3837
|
-
const tenantId =
|
|
4050
|
+
const tenantId = getTenantId7(request);
|
|
3838
4051
|
const { key } = request.params;
|
|
3839
4052
|
try {
|
|
3840
4053
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3867,7 +4080,7 @@ async function listMcpServerTools(request, reply) {
|
|
|
3867
4080
|
}
|
|
3868
4081
|
}
|
|
3869
4082
|
async function connectMcpServer(request, reply) {
|
|
3870
|
-
const tenantId =
|
|
4083
|
+
const tenantId = getTenantId7(request);
|
|
3871
4084
|
const { key } = request.params;
|
|
3872
4085
|
try {
|
|
3873
4086
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -3904,7 +4117,7 @@ async function connectMcpServer(request, reply) {
|
|
|
3904
4117
|
}
|
|
3905
4118
|
}
|
|
3906
4119
|
async function disconnectMcpServer(request, reply) {
|
|
3907
|
-
const tenantId =
|
|
4120
|
+
const tenantId = getTenantId7(request);
|
|
3908
4121
|
const { key } = request.params;
|
|
3909
4122
|
try {
|
|
3910
4123
|
const storeLattice = (0, import_core19.getStoreLattice)("default", "mcp");
|
|
@@ -4747,7 +4960,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
4747
4960
|
reader.releaseLock();
|
|
4748
4961
|
}
|
|
4749
4962
|
if (callback_event) {
|
|
4750
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
4963
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
4751
4964
|
import_core23.eventBus.publish(callback_event, {
|
|
4752
4965
|
success: true,
|
|
4753
4966
|
state,
|
|
@@ -4761,7 +4974,7 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
|
|
|
4761
4974
|
} else {
|
|
4762
4975
|
await response.text();
|
|
4763
4976
|
if (callback_event) {
|
|
4764
|
-
const state = await agent_state({ assistant_id, thread_id });
|
|
4977
|
+
const state = await agent_state({ assistant_id, thread_id, tenant_id });
|
|
4765
4978
|
import_core23.eventBus.publish(callback_event, {
|
|
4766
4979
|
success: true,
|
|
4767
4980
|
state,
|
|
@@ -5075,6 +5288,13 @@ var start = async (config) => {
|
|
|
5075
5288
|
logger = loggerLattice.client;
|
|
5076
5289
|
}
|
|
5077
5290
|
app.decorate("loggerLattice", loggerLattice);
|
|
5291
|
+
if (!import_core24.sandboxLatticeManager.hasLattice("default")) {
|
|
5292
|
+
const sandboxBaseURL = process.env.SANDBOX_BASE_URL || "http://localhost:8080";
|
|
5293
|
+
import_core24.sandboxLatticeManager.registerLattice("default", {
|
|
5294
|
+
baseURL: sandboxBaseURL
|
|
5295
|
+
});
|
|
5296
|
+
logger.info(`Registered sandbox manager with baseURL: ${sandboxBaseURL}`);
|
|
5297
|
+
}
|
|
5078
5298
|
const target_port = config?.port || Number(process.env.PORT) || 4001;
|
|
5079
5299
|
await app.listen({ port: target_port, host: "0.0.0.0" });
|
|
5080
5300
|
logger.info(`Lattice Gateway is running on port: ${target_port}`);
|