@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/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
- getAgentLattice,
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 = getAgentLattice(assistant_id);
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 = getAgentLattice(assistant_id);
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
- assistant_id
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 { getAllAgentConfigs, eventBus } from "@axiom-lattice/core";
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 agentConfigs = await getAllAgentConfigs();
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 agentConfigs = await getAllAgentConfigs();
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 agentConfigs = await getAllAgentConfigs();
384
- const isCodeConfigured = agentConfigs.some((config) => config.key === id);
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 imageData = await draw_graph(assistantId);
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
- reply.raw.write(`data: ${JSON.stringify(chunk)}
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
- console.error("Stream processing error:", error);
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
- console.error("Resume stream processing error:", error);
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 { assistantId, threadId } = request.params;
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(assistantId, threadId);
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 { assistantId, threadId } = request.params;
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(assistantId, threadId);
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
- assistantId,
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 { assistantId, threadId } = request.params;
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(assistantId, threadId);
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(assistantId, threadId);
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 { getStoreLattice as getStoreLattice4, toolLatticeManager } from "@axiom-lattice/core";
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 { getAgentConfig, getAgentLattice as getAgentLattice2, getSandBoxManager, normalizeSandboxName } from "@axiom-lattice/core";
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 agentConfig = getAgentConfig(assistantId);
2137
- if (!agentConfig) {
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
- return filesystemConfig.config?.isolatedLevel || null;
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("default");
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 isolatedLevel = sandboxService.getFilesystemIsolatedLevel(assistantId);
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("default");
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("default");
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 getStoreLattice5 } from "@axiom-lattice/core";
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 = getStoreLattice5("default", "workspace").store;
2359
- this.projectStore = getStoreLattice5("default", "project").store;
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("default");
2589
+ const sandboxManager = getSandBoxManager3();
2486
2590
  const sandboxName = "global";
2487
2591
  const sandbox = await sandboxManager.createSandbox(sandboxName);
2488
- return { backend: new SandboxFilesystem({
2489
- sandboxInstance: sandbox,
2490
- workingDirectory: `/workspaces/${workspaceId}/${projectId}`
2491
- }), workspace };
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 { backend: new FilesystemBackend({
2494
- rootDir: `/lattice_store/workspaces/${workspaceId}/${projectId}`,
2495
- virtualMode: true
2496
- }), workspace };
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("default");
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 ?? `inline; filename*=UTF-8''${encodeURIComponent(filename2)}`;
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 = `inline; filename*=UTF-8''${encodeURIComponent(filename2)}`;
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", `inline; filename*=UTF-8''${encodeURIComponent(filename)}`).send(buffer);
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("default");
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 getStoreLattice6,
2922
+ getStoreLattice as getStoreLattice5,
2740
2923
  sqlDatabaseManager
2741
2924
  } from "@axiom-lattice/core";
2742
2925
  import { randomUUID as randomUUID3 } from "crypto";
2743
- function getTenantId(request) {
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 = getTenantId(request);
2934
+ const tenantId = getTenantId5(request);
2748
2935
  try {
2749
- const storeLattice = getStoreLattice6("default", "database");
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 = getTenantId(request);
2964
+ const tenantId = getTenantId5(request);
2778
2965
  const { key } = request.params;
2779
2966
  try {
2780
- const storeLattice = getStoreLattice6("default", "database");
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 = getTenantId(request);
2990
+ const tenantId = getTenantId5(request);
2804
2991
  const body = request.body;
2805
2992
  try {
2806
- const storeLattice = getStoreLattice6("default", "database");
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 = getTenantId(request);
3025
+ const tenantId = getTenantId5(request);
2839
3026
  const { key } = request.params;
2840
3027
  const updates = request.body;
2841
3028
  try {
2842
- const storeLattice = getStoreLattice6("default", "database");
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 = getTenantId(request);
3067
+ const tenantId = getTenantId5(request);
2881
3068
  const { keyOrId } = request.params;
2882
3069
  try {
2883
- const storeLattice = getStoreLattice6("default", "database");
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 = getTenantId(request);
3116
+ const tenantId = getTenantId5(request);
2930
3117
  const { key } = request.params;
2931
3118
  try {
2932
- const storeLattice = getStoreLattice6("default", "database");
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 getStoreLattice7,
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 getTenantId2(request) {
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 = getTenantId2(request);
3217
+ const tenantId = getTenantId6(request);
3027
3218
  try {
3028
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3243
+ const tenantId = getTenantId6(request);
3053
3244
  const { key } = request.params;
3054
3245
  try {
3055
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3269
+ const tenantId = getTenantId6(request);
3079
3270
  const body = request.body;
3080
3271
  try {
3081
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3320
+ const tenantId = getTenantId6(request);
3130
3321
  const { key } = request.params;
3131
3322
  const updates = request.body;
3132
3323
  try {
3133
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3371
+ const tenantId = getTenantId6(request);
3181
3372
  const { keyOrId } = request.params;
3182
3373
  try {
3183
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3418
+ const tenantId = getTenantId6(request);
3228
3419
  const { key } = request.params;
3229
3420
  try {
3230
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3469
+ const tenantId = getTenantId6(request);
3279
3470
  const { key } = request.params;
3280
3471
  try {
3281
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
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 = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3555
+ const tenantId = getTenantId6(request);
3365
3556
  const { key } = request.params;
3366
3557
  try {
3367
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3596
+ const tenantId = getTenantId6(request);
3406
3597
  const { key, datasourceId } = request.params;
3407
3598
  try {
3408
- const storeLattice = getStoreLattice7("default", "metrics");
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 = getTenantId2(request);
3633
+ const tenantId = getTenantId6(request);
3443
3634
  const { key } = request.params;
3444
3635
  const body = request.body;
3445
3636
  try {
3446
- const storeLattice = getStoreLattice7("default", "metrics");
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: result.metrics,
3479
- dataPoints: result.dataPoints,
3480
- metadata: result.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 getStoreLattice8,
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 getTenantId3(request) {
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 = getTenantId3(request);
3800
+ const tenantId = getTenantId7(request);
3588
3801
  try {
3589
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
3826
+ const tenantId = getTenantId7(request);
3614
3827
  const { key } = request.params;
3615
3828
  try {
3616
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
3852
+ const tenantId = getTenantId7(request);
3640
3853
  const body = request.body;
3641
3854
  try {
3642
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
3891
+ const tenantId = getTenantId7(request);
3679
3892
  const { key } = request.params;
3680
3893
  const updates = request.body;
3681
3894
  try {
3682
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
3941
+ const tenantId = getTenantId7(request);
3729
3942
  const { keyOrId } = request.params;
3730
3943
  try {
3731
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
3988
+ const tenantId = getTenantId7(request);
3776
3989
  const { key } = request.params;
3777
3990
  try {
3778
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
4041
+ const tenantId = getTenantId7(request);
3829
4042
  const { key } = request.params;
3830
4043
  try {
3831
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
4074
+ const tenantId = getTenantId7(request);
3862
4075
  const { key } = request.params;
3863
4076
  try {
3864
- const storeLattice = getStoreLattice8("default", "mcp");
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 = getStoreLattice8("default", "mcp");
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 = getTenantId3(request);
4111
+ const tenantId = getTenantId7(request);
3899
4112
  const { key } = request.params;
3900
4113
  try {
3901
- const storeLattice = getStoreLattice8("default", "mcp");
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 getStoreLattice9 } from "@axiom-lattice/core";
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 = getStoreLattice9("default", "user").store;
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 getStoreLattice10 } from "@axiom-lattice/core";
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 = getStoreLattice10("default", "tenant").store;
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 getStoreLattice11 } from "@axiom-lattice/core";
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 = getStoreLattice11("default", "user").store;
4166
- this.tenantStore = getStoreLattice11("default", "tenant").store;
4167
- this.userTenantLinkStore = getStoreLattice11("default", "userTenantLink").store;
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}`);