@axiom-lattice/gateway 2.1.73 → 2.1.75

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
@@ -1747,6 +1747,7 @@ async function getDefinitionsFromAssistants(tenantId) {
1747
1747
  results.push({
1748
1748
  assistantId: a.id,
1749
1749
  assistantName: a.name,
1750
+ description: a.description,
1750
1751
  topologyEdges: mw.config.edges,
1751
1752
  totalEdges: mw.config.edges.length
1752
1753
  });
@@ -4592,12 +4593,590 @@ function registerMcpServerConfigRoutes(app2) {
4592
4593
  app2.post("/api/mcp-servers/test-tools", testMcpServerTools);
4593
4594
  }
4594
4595
 
4595
- // src/controllers/users.ts
4596
- import { getStoreLattice as getStoreLattice9 } from "@axiom-lattice/core";
4596
+ // src/controllers/eval.ts
4597
+ import { getStoreLattice as getStoreLattice10 } from "@axiom-lattice/core";
4598
+ import { v4 as uuidv43 } from "uuid";
4599
+
4600
+ // src/services/eval-runner.ts
4601
+ import { EventEmitter } from "events";
4602
+ import { getStoreLattice as getStoreLattice9, modelLatticeManager as modelLatticeManager2 } from "@axiom-lattice/core";
4603
+ import { LatticeEvalProject } from "@axiom-lattice/agent-eval";
4597
4604
  import { v4 as uuidv42 } from "uuid";
4605
+ function mapLogs(logs) {
4606
+ return logs.map((l) => ({
4607
+ timestamp: l.ts,
4608
+ level: l.level,
4609
+ message: l.message,
4610
+ data: l.data
4611
+ }));
4612
+ }
4613
+ var EvalRunner = class {
4614
+ constructor() {
4615
+ this.runs = /* @__PURE__ */ new Map();
4616
+ this.eventEmitter = new EventEmitter();
4617
+ }
4618
+ getEventEmitter() {
4619
+ return this.eventEmitter;
4620
+ }
4621
+ async startRun(tenantId, projectId) {
4622
+ const store = this.getEvalStore();
4623
+ const project = await store.getProjectById(tenantId, projectId);
4624
+ if (!project) throw new Error("Project not found");
4625
+ const existingRuns = await store.getRunsByTenant(tenantId, { projectId, status: "running" });
4626
+ if (existingRuns.length > 0) {
4627
+ throw new Error("A run is already in progress for this project");
4628
+ }
4629
+ const suites = await store.getSuitesByProject(tenantId, projectId);
4630
+ const evalSuites = [];
4631
+ let totalCases = 0;
4632
+ for (const suite of suites) {
4633
+ const cases = await store.getCasesBySuite(tenantId, suite.id);
4634
+ totalCases += cases.length;
4635
+ evalSuites.push({
4636
+ suiteName: suite.name,
4637
+ cases: cases.map((c) => ({
4638
+ caseId: c.id,
4639
+ input: { message: c.inputMessage, files: c.inputFiles },
4640
+ steps: c.steps,
4641
+ output: { type: c.outputType },
4642
+ eval: {
4643
+ content_assertion: c.contentAssertion,
4644
+ eval_rubrics: c.rubrics?.map((r) => ({
4645
+ dimension: r.name,
4646
+ weight: r.weight,
4647
+ description: r.description
4648
+ }))
4649
+ }
4650
+ }))
4651
+ });
4652
+ }
4653
+ const runId = uuidv42();
4654
+ const concurrency = project.concurrency || 3;
4655
+ await store.createRun(tenantId, projectId, runId, { totalCases, concurrency });
4656
+ const judgeCfg = project.judgeModelConfig;
4657
+ const hasModelKey = Boolean(judgeCfg.modelKey);
4658
+ const hasApiKey = Boolean(judgeCfg.apiKeyEnvName || judgeCfg.apiKey);
4659
+ const hasCredentials = hasApiKey;
4660
+ let judgeModelConfig = {};
4661
+ if (hasModelKey) {
4662
+ judgeModelConfig = { modelKey: judgeCfg.modelKey };
4663
+ } else if (!hasCredentials) {
4664
+ const firstModel = modelLatticeManager2.getAllLattices()[0];
4665
+ if (firstModel) {
4666
+ judgeModelConfig = { modelKey: firstModel.key };
4667
+ } else {
4668
+ judgeModelConfig = { model: judgeCfg };
4669
+ }
4670
+ } else {
4671
+ judgeModelConfig = { model: judgeCfg };
4672
+ }
4673
+ const projectConfig = {
4674
+ projectName: project.name,
4675
+ version: project.version,
4676
+ description: project.description,
4677
+ suites: evalSuites,
4678
+ judge_agent_config: judgeModelConfig,
4679
+ lattice_server_config: {
4680
+ base_url: project.targetServerConfig.base_url || "",
4681
+ api_key: project.targetServerConfig.api_key || "",
4682
+ tenant_id: tenantId
4683
+ },
4684
+ concurrency
4685
+ };
4686
+ const abortController = new AbortController();
4687
+ const stats = { passed: 0, failed: 0, totalScore: 0 };
4688
+ const onCaseComplete = async (result, suiteName) => {
4689
+ const passed = result.result?.pass ?? false;
4690
+ const score = result.result?.final_score ?? 0;
4691
+ if (passed) stats.passed++;
4692
+ else stats.failed++;
4693
+ stats.totalScore += score;
4694
+ const completedCount = stats.passed + stats.failed;
4695
+ await store.createRunResult(tenantId, runId, uuidv42(), {
4696
+ suiteName,
4697
+ caseId: result.caseId,
4698
+ pass: passed,
4699
+ score,
4700
+ summary: result.result?.summary,
4701
+ dimensionResults: result.result?.dimension_results?.map((d) => ({
4702
+ name: d.name,
4703
+ score: d.score,
4704
+ reason: d.reason
4705
+ })),
4706
+ durationMs: result.duration_ms,
4707
+ messages: result.messages,
4708
+ logs: mapLogs(result.logs),
4709
+ error: result.error
4710
+ });
4711
+ const avgScore = completedCount > 0 ? stats.totalScore / completedCount : 0;
4712
+ await store.updateRunStatus(tenantId, runId, {
4713
+ passedCases: stats.passed,
4714
+ failedCases: stats.failed,
4715
+ avgScore
4716
+ });
4717
+ this.eventEmitter.emit(`run:${runId}`, {
4718
+ type: "progress",
4719
+ runId,
4720
+ data: { suiteName, caseId: result.caseId, pass: passed, score, completed: completedCount, total: totalCases }
4721
+ });
4722
+ };
4723
+ const runPromise = (async () => {
4724
+ try {
4725
+ const evalProject = new LatticeEvalProject(projectConfig, onCaseComplete);
4726
+ const { report } = await evalProject.runAllSuitesBatch(concurrency);
4727
+ const completedCount = stats.passed + stats.failed;
4728
+ await store.updateRunStatus(tenantId, runId, {
4729
+ status: "completed",
4730
+ completedAt: /* @__PURE__ */ new Date(),
4731
+ passedCases: stats.passed,
4732
+ failedCases: stats.failed,
4733
+ avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0
4734
+ });
4735
+ this.eventEmitter.emit(`run:${runId}`, {
4736
+ type: "completed",
4737
+ runId,
4738
+ data: { passed: stats.passed, failed: stats.failed, avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0 }
4739
+ });
4740
+ return { report };
4741
+ } catch (err) {
4742
+ const errorMsg = err.message;
4743
+ await store.updateRunStatus(tenantId, runId, {
4744
+ status: "failed",
4745
+ error: errorMsg,
4746
+ completedAt: /* @__PURE__ */ new Date()
4747
+ });
4748
+ this.eventEmitter.emit(`run:${runId}`, {
4749
+ type: "error",
4750
+ runId,
4751
+ data: { message: errorMsg }
4752
+ });
4753
+ throw err;
4754
+ } finally {
4755
+ this.runs.delete(runId);
4756
+ }
4757
+ })();
4758
+ this.runs.set(runId, { runId, projectId, tenantId, abortController, promise: runPromise });
4759
+ runPromise.catch(() => {
4760
+ });
4761
+ return runId;
4762
+ }
4763
+ async abortRun(runId) {
4764
+ const ctx = this.runs.get(runId);
4765
+ if (!ctx) return false;
4766
+ ctx.abortController.abort();
4767
+ const store = this.getEvalStore();
4768
+ await store.updateRunStatus(ctx.tenantId, runId, { status: "aborted", completedAt: /* @__PURE__ */ new Date() });
4769
+ return true;
4770
+ }
4771
+ isRunning(runId) {
4772
+ return this.runs.has(runId);
4773
+ }
4774
+ getEvalStore() {
4775
+ return getStoreLattice9("default", "eval").store;
4776
+ }
4777
+ };
4778
+ var evalRunner = new EvalRunner();
4779
+
4780
+ // src/controllers/eval.ts
4781
+ function getTenantId10(request) {
4782
+ const userTenantId = request.user?.tenantId;
4783
+ if (userTenantId) {
4784
+ return userTenantId;
4785
+ }
4786
+ return request.headers["x-tenant-id"] || "default";
4787
+ }
4788
+ function getEvalStore() {
4789
+ return getStoreLattice10("default", "eval").store;
4790
+ }
4791
+ async function createProject(request, reply) {
4792
+ try {
4793
+ const tenantId = getTenantId10(request);
4794
+ const store = getEvalStore();
4795
+ const id = uuidv43();
4796
+ const data = request.body;
4797
+ const project = await store.createProject(tenantId, id, {
4798
+ name: data.name,
4799
+ description: data.description,
4800
+ version: data.version,
4801
+ judgeModelConfig: data.judgeModelConfig ?? {},
4802
+ targetServerConfig: data.targetServerConfig ?? {},
4803
+ concurrency: data.concurrency ?? 1,
4804
+ reportConfig: data.reportConfig
4805
+ });
4806
+ return reply.status(201).send({
4807
+ success: true,
4808
+ message: "Successfully created project",
4809
+ data: project
4810
+ });
4811
+ } catch (err) {
4812
+ const message = err instanceof Error ? err.message : "Failed to create project";
4813
+ return reply.status(500).send({ success: false, message });
4814
+ }
4815
+ }
4816
+ async function listProjects(request, reply) {
4817
+ try {
4818
+ const tenantId = getTenantId10(request);
4819
+ const store = getEvalStore();
4820
+ let projects = await store.getProjectsByTenant(tenantId);
4821
+ if (projects.length === 0) {
4822
+ try {
4823
+ const { modelLatticeManager: modelLatticeManager3 } = await import("@axiom-lattice/core");
4824
+ const models = modelLatticeManager3.getAllLattices();
4825
+ const first = models[0];
4826
+ const judgeModel = first ? { modelKey: first.key } : { provider: "openai", model: "gpt-4" };
4827
+ const host = request.hostname || "localhost";
4828
+ const baseUrl = `http://${host}:${process.env.PORT || 4001}`;
4829
+ await store.createProject(tenantId, uuidv43(), {
4830
+ name: "Default",
4831
+ description: "Built-in project for testing eval against this server",
4832
+ judgeModelConfig: judgeModel,
4833
+ targetServerConfig: { base_url: baseUrl, api_key: "" },
4834
+ concurrency: 3
4835
+ });
4836
+ projects = await store.getProjectsByTenant(tenantId);
4837
+ } catch {
4838
+ }
4839
+ }
4840
+ return {
4841
+ success: true,
4842
+ message: "Ok",
4843
+ data: { records: projects, total: projects.length }
4844
+ };
4845
+ } catch (err) {
4846
+ const message = err instanceof Error ? err.message : "Failed to list projects";
4847
+ return reply.status(500).send({ success: false, message });
4848
+ }
4849
+ }
4850
+ async function getProject(request, reply) {
4851
+ try {
4852
+ const tenantId = getTenantId10(request);
4853
+ const store = getEvalStore();
4854
+ const { pid } = request.params;
4855
+ const project = await store.getProjectById(tenantId, pid);
4856
+ if (!project) {
4857
+ return reply.status(404).send({ success: false, message: "Project not found" });
4858
+ }
4859
+ const suites = await store.getSuitesByProject(tenantId, pid);
4860
+ return {
4861
+ success: true,
4862
+ message: "Ok",
4863
+ data: { project, suites }
4864
+ };
4865
+ } catch (err) {
4866
+ const message = err instanceof Error ? err.message : "Failed to get project";
4867
+ return reply.status(500).send({ success: false, message });
4868
+ }
4869
+ }
4870
+ async function updateProject(request, reply) {
4871
+ try {
4872
+ const tenantId = getTenantId10(request);
4873
+ const store = getEvalStore();
4874
+ const { pid } = request.params;
4875
+ const existing = await store.getProjectById(tenantId, pid);
4876
+ if (!existing) {
4877
+ return reply.status(404).send({ success: false, message: "Project not found" });
4878
+ }
4879
+ const updated = await store.updateProject(tenantId, pid, request.body);
4880
+ return {
4881
+ success: true,
4882
+ message: "Successfully updated project",
4883
+ data: updated
4884
+ };
4885
+ } catch (err) {
4886
+ const message = err instanceof Error ? err.message : "Failed to update project";
4887
+ return reply.status(500).send({ success: false, message });
4888
+ }
4889
+ }
4890
+ async function deleteProject(request, reply) {
4891
+ try {
4892
+ const tenantId = getTenantId10(request);
4893
+ const store = getEvalStore();
4894
+ const { pid } = request.params;
4895
+ const existing = await store.getProjectById(tenantId, pid);
4896
+ if (!existing) {
4897
+ return reply.status(404).send({ success: false, message: "Project not found" });
4898
+ }
4899
+ const deleted = await store.deleteProject(tenantId, pid);
4900
+ if (!deleted) {
4901
+ return reply.status(500).send({ success: false, message: "Failed to delete project" });
4902
+ }
4903
+ return { success: true, message: "Successfully deleted project" };
4904
+ } catch (err) {
4905
+ const message = err instanceof Error ? err.message : "Failed to delete project";
4906
+ return reply.status(500).send({ success: false, message });
4907
+ }
4908
+ }
4909
+ async function createSuite(request, reply) {
4910
+ try {
4911
+ const tenantId = getTenantId10(request);
4912
+ const store = getEvalStore();
4913
+ const { pid } = request.params;
4914
+ const project = await store.getProjectById(tenantId, pid);
4915
+ if (!project) {
4916
+ return reply.status(404).send({ success: false, message: "Project not found" });
4917
+ }
4918
+ const id = uuidv43();
4919
+ const data = request.body;
4920
+ const suite = await store.createSuite(tenantId, pid, id, { name: data.name });
4921
+ return reply.status(201).send({
4922
+ success: true,
4923
+ message: "Successfully created suite",
4924
+ data: suite
4925
+ });
4926
+ } catch (err) {
4927
+ const message = err instanceof Error ? err.message : "Failed to create suite";
4928
+ return reply.status(500).send({ success: false, message });
4929
+ }
4930
+ }
4931
+ async function updateSuite(request, reply) {
4932
+ try {
4933
+ const tenantId = getTenantId10(request);
4934
+ const store = getEvalStore();
4935
+ const { sid } = request.params;
4936
+ const existing = await store.getSuiteById(tenantId, sid);
4937
+ if (!existing) {
4938
+ return reply.status(404).send({ success: false, message: "Suite not found" });
4939
+ }
4940
+ const updated = await store.updateSuite(tenantId, sid, request.body);
4941
+ return {
4942
+ success: true,
4943
+ message: "Successfully updated suite",
4944
+ data: updated
4945
+ };
4946
+ } catch (err) {
4947
+ const message = err instanceof Error ? err.message : "Failed to update suite";
4948
+ return reply.status(500).send({ success: false, message });
4949
+ }
4950
+ }
4951
+ async function deleteSuite(request, reply) {
4952
+ try {
4953
+ const tenantId = getTenantId10(request);
4954
+ const store = getEvalStore();
4955
+ const { sid } = request.params;
4956
+ const existing = await store.getSuiteById(tenantId, sid);
4957
+ if (!existing) {
4958
+ return reply.status(404).send({ success: false, message: "Suite not found" });
4959
+ }
4960
+ const deleted = await store.deleteSuite(tenantId, sid);
4961
+ if (!deleted) {
4962
+ return reply.status(500).send({ success: false, message: "Failed to delete suite" });
4963
+ }
4964
+ return { success: true, message: "Successfully deleted suite" };
4965
+ } catch (err) {
4966
+ const message = err instanceof Error ? err.message : "Failed to delete suite";
4967
+ return reply.status(500).send({ success: false, message });
4968
+ }
4969
+ }
4970
+ async function createCase(request, reply) {
4971
+ try {
4972
+ const tenantId = getTenantId10(request);
4973
+ const store = getEvalStore();
4974
+ const { sid } = request.params;
4975
+ const suite = await store.getSuiteById(tenantId, sid);
4976
+ if (!suite) {
4977
+ return reply.status(404).send({ success: false, message: "Suite not found" });
4978
+ }
4979
+ const id = uuidv43();
4980
+ const data = request.body;
4981
+ const created = await store.createCase(tenantId, sid, id, {
4982
+ inputMessage: data.inputMessage,
4983
+ inputFiles: data.inputFiles,
4984
+ steps: data.steps ?? [],
4985
+ outputType: data.outputType ?? "message_content",
4986
+ contentAssertion: data.contentAssertion ?? "",
4987
+ rubrics: data.rubrics
4988
+ });
4989
+ return reply.status(201).send({
4990
+ success: true,
4991
+ message: "Successfully created case",
4992
+ data: created
4993
+ });
4994
+ } catch (err) {
4995
+ const message = err instanceof Error ? err.message : "Failed to create case";
4996
+ return reply.status(500).send({ success: false, message });
4997
+ }
4998
+ }
4999
+ async function listCasesForSuite(request, reply) {
5000
+ try {
5001
+ const tenantId = getTenantId10(request);
5002
+ const store = getEvalStore();
5003
+ const { sid } = request.params;
5004
+ const cases = await store.getCasesBySuite(tenantId, sid);
5005
+ return {
5006
+ success: true,
5007
+ message: "Ok",
5008
+ data: { records: cases, total: cases.length }
5009
+ };
5010
+ } catch (err) {
5011
+ const message = err instanceof Error ? err.message : "Failed to list cases";
5012
+ return reply.status(500).send({ success: false, message });
5013
+ }
5014
+ }
5015
+ async function updateCase(request, reply) {
5016
+ try {
5017
+ const tenantId = getTenantId10(request);
5018
+ const store = getEvalStore();
5019
+ const { cid } = request.params;
5020
+ const existing = await store.getCaseById(tenantId, cid);
5021
+ if (!existing) {
5022
+ return reply.status(404).send({ success: false, message: "Case not found" });
5023
+ }
5024
+ const updated = await store.updateCase(tenantId, cid, request.body);
5025
+ return {
5026
+ success: true,
5027
+ message: "Successfully updated case",
5028
+ data: updated
5029
+ };
5030
+ } catch (err) {
5031
+ const message = err instanceof Error ? err.message : "Failed to update case";
5032
+ return reply.status(500).send({ success: false, message });
5033
+ }
5034
+ }
5035
+ async function deleteCase(request, reply) {
5036
+ try {
5037
+ const tenantId = getTenantId10(request);
5038
+ const store = getEvalStore();
5039
+ const { cid } = request.params;
5040
+ const existing = await store.getCaseById(tenantId, cid);
5041
+ if (!existing) {
5042
+ return reply.status(404).send({ success: false, message: "Case not found" });
5043
+ }
5044
+ const deleted = await store.deleteCase(tenantId, cid);
5045
+ if (!deleted) {
5046
+ return reply.status(500).send({ success: false, message: "Failed to delete case" });
5047
+ }
5048
+ return { success: true, message: "Successfully deleted case" };
5049
+ } catch (err) {
5050
+ const message = err instanceof Error ? err.message : "Failed to delete case";
5051
+ return reply.status(500).send({ success: false, message });
5052
+ }
5053
+ }
5054
+ function registerEvalRoutes(app2) {
5055
+ app2.post("/api/eval/projects", createProject);
5056
+ app2.get("/api/eval/projects", listProjects);
5057
+ app2.get("/api/eval/projects/:pid", getProject);
5058
+ app2.put("/api/eval/projects/:pid", updateProject);
5059
+ app2.delete("/api/eval/projects/:pid", deleteProject);
5060
+ app2.post("/api/eval/projects/:pid/suites", createSuite);
5061
+ app2.put("/api/eval/projects/:pid/suites/:sid", updateSuite);
5062
+ app2.delete("/api/eval/projects/:pid/suites/:sid", deleteSuite);
5063
+ app2.post("/api/eval/projects/:pid/suites/:sid/cases", createCase);
5064
+ app2.get("/api/eval/projects/:pid/suites/:sid/cases", listCasesForSuite);
5065
+ app2.put("/api/eval/projects/:pid/suites/:sid/cases/:cid", updateCase);
5066
+ app2.delete("/api/eval/projects/:pid/suites/:sid/cases/:cid", deleteCase);
5067
+ app2.post("/api/eval/projects/:pid/runs", async (request, reply) => {
5068
+ try {
5069
+ const tenantId = getTenantId10(request);
5070
+ const { pid } = request.params;
5071
+ const runId = await evalRunner.startRun(tenantId, pid);
5072
+ reply.status(202).send({ success: true, message: "Run started", data: { run_id: runId } });
5073
+ } catch (err) {
5074
+ const msg = err.message;
5075
+ const code = msg === "Project not found" ? 404 : msg.includes("already in progress") ? 409 : 500;
5076
+ reply.status(code).send({ success: false, message: msg });
5077
+ }
5078
+ });
5079
+ app2.get("/api/eval/runs", async (request, reply) => {
5080
+ try {
5081
+ const tenantId = getTenantId10(request);
5082
+ const query = request.query;
5083
+ const runs = await getEvalStore().getRunsByTenant(tenantId, { projectId: query.project_id, status: query.status });
5084
+ reply.send({ success: true, message: "Ok", data: { records: runs, total: runs.length } });
5085
+ } catch (err) {
5086
+ reply.status(500).send({ success: false, message: err.message });
5087
+ }
5088
+ });
5089
+ app2.get("/api/eval/runs/:rid", async (request, reply) => {
5090
+ try {
5091
+ const tenantId = getTenantId10(request);
5092
+ const { rid } = request.params;
5093
+ const run = await getEvalStore().getRunById(tenantId, rid);
5094
+ if (!run) return reply.status(404).send({ success: false, message: "Run not found" });
5095
+ const results = await getEvalStore().getResultsByRun(tenantId, rid);
5096
+ reply.send({ success: true, message: "Ok", data: { ...run, results } });
5097
+ } catch (err) {
5098
+ reply.status(500).send({ success: false, message: err.message });
5099
+ }
5100
+ });
5101
+ app2.get("/api/eval/runs/:rid/stream", async (request, reply) => {
5102
+ reply.hijack();
5103
+ reply.raw.writeHead(200, {
5104
+ "Content-Type": "text/event-stream",
5105
+ "Cache-Control": "no-cache",
5106
+ Connection: "keep-alive",
5107
+ "Access-Control-Allow-Origin": "*"
5108
+ });
5109
+ const { rid } = request.params;
5110
+ const emitter = evalRunner.getEventEmitter();
5111
+ const eventKey = `run:${rid}`;
5112
+ if (!evalRunner.isRunning(rid)) {
5113
+ const tenantId = getTenantId10(request);
5114
+ const run = await getEvalStore().getRunById(tenantId, rid);
5115
+ if (run) {
5116
+ const eventType = run.status === "completed" ? "completed" : "error";
5117
+ reply.raw.write(`event: ${eventType}
5118
+ data: ${JSON.stringify({ passed: run.passedCases, failed: run.failedCases, avgScore: run.avgScore })}
5119
+
5120
+ `);
5121
+ }
5122
+ reply.raw.end();
5123
+ return;
5124
+ }
5125
+ const handler = (event) => {
5126
+ reply.raw.write(`event: ${event.type}
5127
+ data: ${JSON.stringify(event.data)}
5128
+
5129
+ `);
5130
+ if (event.type === "completed" || event.type === "error") {
5131
+ emitter.off(eventKey, handler);
5132
+ reply.raw.end();
5133
+ }
5134
+ };
5135
+ emitter.on(eventKey, handler);
5136
+ request.raw.on("close", () => {
5137
+ emitter.off(eventKey, handler);
5138
+ });
5139
+ });
5140
+ app2.post("/api/eval/runs/:rid/abort", async (request, reply) => {
5141
+ try {
5142
+ const { rid } = request.params;
5143
+ const aborted = await evalRunner.abortRun(rid);
5144
+ if (!aborted) return reply.status(404).send({ success: false, message: "Run not found or not running" });
5145
+ reply.send({ success: true, message: "Run aborted" });
5146
+ } catch (err) {
5147
+ reply.status(500).send({ success: false, message: err.message });
5148
+ }
5149
+ });
5150
+ app2.delete("/api/eval/runs/:rid", async (request, reply) => {
5151
+ try {
5152
+ const tenantId = getTenantId10(request);
5153
+ const { rid } = request.params;
5154
+ const deleted = await getEvalStore().deleteRun(tenantId, rid);
5155
+ if (!deleted) return reply.status(404).send({ success: false, message: "Run not found" });
5156
+ reply.send({ success: true, message: "Run deleted" });
5157
+ } catch (err) {
5158
+ reply.status(500).send({ success: false, message: err.message });
5159
+ }
5160
+ });
5161
+ app2.get("/api/eval/reports/projects/:pid", async (request, reply) => {
5162
+ try {
5163
+ const tenantId = getTenantId10(request);
5164
+ const { pid } = request.params;
5165
+ const report = await getEvalStore().getProjectReport(tenantId, pid);
5166
+ if (!report) return reply.status(404).send({ success: false, message: "Project not found" });
5167
+ reply.send({ success: true, message: "Ok", data: report });
5168
+ } catch (err) {
5169
+ reply.status(500).send({ success: false, message: err.message });
5170
+ }
5171
+ });
5172
+ }
5173
+
5174
+ // src/controllers/users.ts
5175
+ import { getStoreLattice as getStoreLattice11 } from "@axiom-lattice/core";
5176
+ import { v4 as uuidv44 } from "uuid";
4598
5177
  var UsersController = class {
4599
5178
  constructor() {
4600
- this.userStore = getStoreLattice9("default", "user").store;
5179
+ this.userStore = getStoreLattice11("default", "user").store;
4601
5180
  }
4602
5181
  async listUsers(request, reply) {
4603
5182
  const { email } = request.query;
@@ -4610,7 +5189,7 @@ var UsersController = class {
4610
5189
  }
4611
5190
  async createUser(request, reply) {
4612
5191
  const data = request.body;
4613
- const id = uuidv42();
5192
+ const id = uuidv44();
4614
5193
  const existingUser = await this.userStore.getUserByEmail(data.email);
4615
5194
  if (existingUser) {
4616
5195
  return reply.status(409).send({
@@ -4675,11 +5254,11 @@ function registerUserRoutes(app2) {
4675
5254
  }
4676
5255
 
4677
5256
  // src/controllers/tenants.ts
4678
- import { getStoreLattice as getStoreLattice10 } from "@axiom-lattice/core";
4679
- import { v4 as uuidv43 } from "uuid";
5257
+ import { getStoreLattice as getStoreLattice12 } from "@axiom-lattice/core";
5258
+ import { v4 as uuidv45 } from "uuid";
4680
5259
  var TenantsController = class {
4681
5260
  constructor() {
4682
- this.tenantStore = getStoreLattice10("default", "tenant").store;
5261
+ this.tenantStore = getStoreLattice12("default", "tenant").store;
4683
5262
  }
4684
5263
  // ==================== Tenant CRUD ====================
4685
5264
  async listTenants(request, reply) {
@@ -4688,7 +5267,7 @@ var TenantsController = class {
4688
5267
  }
4689
5268
  async createTenant(request, reply) {
4690
5269
  const data = request.body;
4691
- const id = uuidv43();
5270
+ const id = uuidv45();
4692
5271
  const tenant = await this.tenantStore.createTenant(id, data);
4693
5272
  return reply.status(201).send({ success: true, data: tenant });
4694
5273
  }
@@ -4743,8 +5322,8 @@ function registerTenantRoutes(app2) {
4743
5322
  }
4744
5323
 
4745
5324
  // src/controllers/auth.ts
4746
- import { getStoreLattice as getStoreLattice11 } from "@axiom-lattice/core";
4747
- import { v4 as uuidv44 } from "uuid";
5325
+ import { getStoreLattice as getStoreLattice13 } from "@axiom-lattice/core";
5326
+ import { v4 as uuidv46 } from "uuid";
4748
5327
  var defaultAuthConfig = {
4749
5328
  autoApproveUsers: true,
4750
5329
  allowTenantRegistration: true,
@@ -4752,9 +5331,9 @@ var defaultAuthConfig = {
4752
5331
  };
4753
5332
  var AuthController = class {
4754
5333
  constructor(config = {}) {
4755
- this.userStore = getStoreLattice11("default", "user").store;
4756
- this.tenantStore = getStoreLattice11("default", "tenant").store;
4757
- this.userTenantLinkStore = getStoreLattice11("default", "userTenantLink").store;
5334
+ this.userStore = getStoreLattice13("default", "user").store;
5335
+ this.tenantStore = getStoreLattice13("default", "tenant").store;
5336
+ this.userTenantLinkStore = getStoreLattice13("default", "userTenantLink").store;
4758
5337
  this.config = { ...defaultAuthConfig, ...config };
4759
5338
  }
4760
5339
  async register(request, reply) {
@@ -4767,7 +5346,7 @@ var AuthController = class {
4767
5346
  error: "User with this email already exists"
4768
5347
  });
4769
5348
  }
4770
- const userId = uuidv44();
5349
+ const userId = uuidv46();
4771
5350
  const userStatus = this.config.autoApproveUsers ? "active" : "pending";
4772
5351
  const userData = {
4773
5352
  email,
@@ -5122,7 +5701,7 @@ function registerAuthRoutes(app2, config) {
5122
5701
  }
5123
5702
 
5124
5703
  // src/channels/lark/routes.ts
5125
- import { getStoreLattice as getStoreLattice12 } from "@axiom-lattice/core";
5704
+ import { getStoreLattice as getStoreLattice14 } from "@axiom-lattice/core";
5126
5705
  import {
5127
5706
  ChannelIdentityMappingStore,
5128
5707
  PostgreSQLChannelInstallationStore
@@ -5498,7 +6077,7 @@ function createDefaultLarkDependencies() {
5498
6077
  const installationStore = new PostgreSQLChannelInstallationStore({
5499
6078
  poolConfig: getDatabaseUrl()
5500
6079
  });
5501
- const threadStore = getStoreLattice12("default", "thread").store;
6080
+ const threadStore = getStoreLattice14("default", "thread").store;
5502
6081
  const mappingStore = new ChannelIdentityMappingStore({
5503
6082
  poolConfig: getDatabaseUrl()
5504
6083
  });
@@ -5579,7 +6158,7 @@ function registerChannelRoutes(app2, dependencies = {}) {
5579
6158
 
5580
6159
  // src/controllers/channel-installations.ts
5581
6160
  import { randomUUID as randomUUID7 } from "crypto";
5582
- function getTenantId10(request) {
6161
+ function getTenantId11(request) {
5583
6162
  const userTenantId = request.user?.tenantId;
5584
6163
  if (userTenantId) {
5585
6164
  return userTenantId;
@@ -5597,7 +6176,7 @@ async function getInstallationStore() {
5597
6176
  });
5598
6177
  }
5599
6178
  async function getChannelInstallationList(request, reply) {
5600
- const tenantId = getTenantId10(request);
6179
+ const tenantId = getTenantId11(request);
5601
6180
  const { channel } = request.query;
5602
6181
  try {
5603
6182
  const store = await getInstallationStore();
@@ -5623,7 +6202,7 @@ async function getChannelInstallationList(request, reply) {
5623
6202
  }
5624
6203
  }
5625
6204
  async function getChannelInstallation(request, reply) {
5626
- const tenantId = getTenantId10(request);
6205
+ const tenantId = getTenantId11(request);
5627
6206
  const { installationId } = request.params;
5628
6207
  try {
5629
6208
  const store = await getInstallationStore();
@@ -5656,7 +6235,7 @@ async function getChannelInstallation(request, reply) {
5656
6235
  }
5657
6236
  }
5658
6237
  async function createChannelInstallation(request, reply) {
5659
- const tenantId = getTenantId10(request);
6238
+ const tenantId = getTenantId11(request);
5660
6239
  const body = request.body;
5661
6240
  try {
5662
6241
  if (!body.channel) {
@@ -5719,7 +6298,7 @@ async function createChannelInstallation(request, reply) {
5719
6298
  }
5720
6299
  }
5721
6300
  async function updateChannelInstallation(request, reply) {
5722
- const tenantId = getTenantId10(request);
6301
+ const tenantId = getTenantId11(request);
5723
6302
  const { installationId } = request.params;
5724
6303
  const body = request.body;
5725
6304
  try {
@@ -5765,7 +6344,7 @@ async function updateChannelInstallation(request, reply) {
5765
6344
  }
5766
6345
  }
5767
6346
  async function deleteChannelInstallation(request, reply) {
5768
- const tenantId = getTenantId10(request);
6347
+ const tenantId = getTenantId11(request);
5769
6348
  const { installationId } = request.params;
5770
6349
  try {
5771
6350
  const store = await getInstallationStore();
@@ -5934,6 +6513,7 @@ var registerLatticeRoutes = (app2) => {
5934
6513
  filterSkillsByLicense
5935
6514
  );
5936
6515
  registerSandboxProxyRoutes(app2);
6516
+ registerEvalRoutes(app2);
5937
6517
  registerWorkspaceRoutes(app2);
5938
6518
  registerDatabaseConfigRoutes(app2);
5939
6519
  registerMetricsServerConfigRoutes(app2);
@@ -6308,7 +6888,7 @@ import {
6308
6888
  loggerLatticeManager,
6309
6889
  sandboxLatticeManager as sandboxLatticeManager2,
6310
6890
  sqlDatabaseManager as sqlDatabaseManager2,
6311
- getStoreLattice as getStoreLattice13,
6891
+ getStoreLattice as getStoreLattice15,
6312
6892
  agentInstanceManager as agentInstanceManager8,
6313
6893
  createSandboxProvider
6314
6894
  } from "@axiom-lattice/core";
@@ -6464,7 +7044,7 @@ var start = async (config) => {
6464
7044
  app.decorate("loggerLattice", loggerLattice);
6465
7045
  registerLatticeRoutes(app);
6466
7046
  try {
6467
- const storeLattice = getStoreLattice13("default", "database");
7047
+ const storeLattice = getStoreLattice15("default", "database");
6468
7048
  const store = storeLattice.store;
6469
7049
  sqlDatabaseManager2.setConfigStore(store);
6470
7050
  logger.info("Database config store set for SqlDatabaseManager");