@axiom-lattice/gateway 3.0.6 → 3.0.8

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.js CHANGED
@@ -2722,6 +2722,125 @@ var getAgentGraph = async (request, reply) => {
2722
2722
  });
2723
2723
  }
2724
2724
  };
2725
+ var STATS_CACHE_TTL_MS = 5 * 60 * 1e3;
2726
+ var statsCache = /* @__PURE__ */ new Map();
2727
+ async function getAssistantStats(request, reply) {
2728
+ const tenantId = getTenantId(request);
2729
+ const cached = statsCache.get(tenantId);
2730
+ if (cached && cached.expiresAt > Date.now()) {
2731
+ return {
2732
+ success: true,
2733
+ message: "Ok (cached)",
2734
+ data: cached.data,
2735
+ cache: {
2736
+ expiresAt: new Date(cached.expiresAt).toISOString(),
2737
+ remainingMs: cached.expiresAt - Date.now(),
2738
+ cached: true
2739
+ }
2740
+ };
2741
+ }
2742
+ try {
2743
+ const agentConfigs = await import_core2.agentLatticeManager.getAllAgentConfigsByTenant(tenantId);
2744
+ const codeConfiguredAssistants = agentConfigs.map(convertAgentConfigToAssistant);
2745
+ const storeLattice = (0, import_core.getStoreLattice)("default", "assistant");
2746
+ const assistantStore = storeLattice.store;
2747
+ const storedAssistants = await assistantStore.getAllAssistants(tenantId);
2748
+ const assistantMap = /* @__PURE__ */ new Map();
2749
+ codeConfiguredAssistants.forEach((a) => assistantMap.set(a.id, a));
2750
+ storedAssistants.forEach((a) => assistantMap.set(a.id, a));
2751
+ const userId = getUserId(request);
2752
+ const assistants = Array.from(assistantMap.values()).filter((a) => {
2753
+ if (!a.ownerUserId) return true;
2754
+ return a.ownerUserId === userId;
2755
+ });
2756
+ const threadStore = (0, import_core.getStoreLattice)("default", "thread").store;
2757
+ const evalStore = (0, import_core.getStoreLattice)("default", "eval").store;
2758
+ const now = Date.now();
2759
+ const ms7d = 7 * 864e5;
2760
+ const ms30d = 30 * 864e5;
2761
+ const records = await Promise.all(
2762
+ assistants.map(async (assistant) => {
2763
+ let threadCount = 0;
2764
+ let last7d = 0;
2765
+ let last30d = 0;
2766
+ let lastActive = null;
2767
+ const daily7d = new Array(7).fill(0);
2768
+ const daily30d = new Array(30).fill(0);
2769
+ try {
2770
+ const threads = await threadStore.getThreadsByAssistantId(tenantId, assistant.id);
2771
+ threadCount = threads.length;
2772
+ for (const t of threads) {
2773
+ const created = new Date(t.createdAt).getTime();
2774
+ if (created >= now - ms7d) last7d++;
2775
+ if (created >= now - ms30d) last30d++;
2776
+ const idx7 = Math.floor((now - created) / 864e5);
2777
+ if (idx7 >= 0 && idx7 < 7) daily7d[6 - idx7]++;
2778
+ const idx30 = Math.floor((now - created) / 864e5);
2779
+ if (idx30 >= 0 && idx30 < 30) daily30d[29 - idx30]++;
2780
+ const updated = new Date(t.updatedAt).getTime();
2781
+ if (lastActive === null || updated > lastActive.getTime()) {
2782
+ lastActive = new Date(t.updatedAt);
2783
+ }
2784
+ }
2785
+ } catch {
2786
+ }
2787
+ let evalScore = null;
2788
+ let evalPassRate = null;
2789
+ let evalRuns = 0;
2790
+ let evalTrend = [];
2791
+ try {
2792
+ const projects = await evalStore.getProjectsByTenant(tenantId);
2793
+ const project = projects.find((p) => p.name === `eval-${assistant.id}`);
2794
+ if (project) {
2795
+ const runs = await evalStore.getRunsByTenant(tenantId, { projectId: project.id });
2796
+ evalRuns = runs.length;
2797
+ const sorted = [...runs].sort(
2798
+ (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
2799
+ );
2800
+ evalTrend = sorted.map((r) => typeof r.avgScore === "number" ? r.avgScore : null).filter((v) => v !== null);
2801
+ const latest = sorted[sorted.length - 1];
2802
+ if (latest) {
2803
+ evalScore = typeof latest.avgScore === "number" ? latest.avgScore : null;
2804
+ if (latest.totalCases > 0) {
2805
+ evalPassRate = Math.round(latest.passedCases / latest.totalCases * 100);
2806
+ }
2807
+ }
2808
+ }
2809
+ } catch {
2810
+ }
2811
+ return {
2812
+ id: assistant.id,
2813
+ threadCount,
2814
+ last7d,
2815
+ last30d,
2816
+ lastActive: lastActive ? lastActive.toISOString() : null,
2817
+ daily7d,
2818
+ daily30d,
2819
+ evalScore,
2820
+ evalPassRate,
2821
+ evalRuns,
2822
+ evalTrend: evalTrend.slice(-8)
2823
+ };
2824
+ })
2825
+ );
2826
+ const payload = { records };
2827
+ const expiresAt = Date.now() + STATS_CACHE_TTL_MS;
2828
+ statsCache.set(tenantId, { data: payload, expiresAt });
2829
+ return {
2830
+ success: true,
2831
+ message: "Ok",
2832
+ data: payload,
2833
+ cache: {
2834
+ expiresAt: new Date(expiresAt).toISOString(),
2835
+ remainingMs: STATS_CACHE_TTL_MS,
2836
+ cached: false
2837
+ }
2838
+ };
2839
+ } catch (err) {
2840
+ const message = err instanceof Error ? err.message : "Failed to get assistant stats";
2841
+ return reply.status(500).send({ success: false, message });
2842
+ }
2843
+ }
2725
2844
 
2726
2845
  // src/controllers/run.ts
2727
2846
  var import_uuid = require("uuid");
@@ -5390,6 +5509,7 @@ async function listTasks(request, reply) {
5390
5509
  priority: query.priority,
5391
5510
  ...query.ownerId && { ownerId: query.ownerId },
5392
5511
  ...query.ownerType && { ownerType: query.ownerType },
5512
+ ...query.parentId && { parentId: query.parentId },
5393
5513
  metadata: query.metadata ? JSON.parse(query.metadata) : void 0,
5394
5514
  projectId: query.projectId,
5395
5515
  limit: query.limit ? parseInt(query.limit) : void 0,
@@ -8222,7 +8342,7 @@ var EvalRunner = class {
8222
8342
  getEventEmitter() {
8223
8343
  return this.eventEmitter;
8224
8344
  }
8225
- async startRun(tenantId, projectId, suiteIds, caseIds, runConfig) {
8345
+ async startRun(tenantId, projectId, suiteIds, caseIds, runConfig, taskId) {
8226
8346
  const store2 = this.getEvalStore();
8227
8347
  const project = await store2.getProjectById(tenantId, projectId);
8228
8348
  if (!project) throw new Error("Project not found");
@@ -8310,7 +8430,8 @@ var EvalRunner = class {
8310
8430
  concurrency,
8311
8431
  holdout: isHoldout,
8312
8432
  envWorkspaceId: workspaceId || void 0,
8313
- envProjectId: projectIdFromConfig || void 0
8433
+ envProjectId: projectIdFromConfig || void 0,
8434
+ taskId
8314
8435
  });
8315
8436
  const projectConfig = {
8316
8437
  projectName: project.name,
@@ -8417,7 +8538,7 @@ var EvalRunner = class {
8417
8538
  this.runs.delete(runId);
8418
8539
  }
8419
8540
  })();
8420
- this.runs.set(runId, { runId, projectId, tenantId, abortController, promise: runPromise });
8541
+ this.runs.set(runId, { runId, projectId, tenantId, abortController, promise: runPromise, taskId });
8421
8542
  runPromise.catch(() => {
8422
8543
  });
8423
8544
  return runId;
@@ -8488,7 +8609,9 @@ async function createProject(request, reply) {
8488
8609
  },
8489
8610
  targetServerConfig: {
8490
8611
  base_url: serverCfg.base_url || "",
8491
- api_key: serverCfg.api_key || ""
8612
+ api_key: serverCfg.api_key || "",
8613
+ // Project↔agent association pointer (see manage_eval create_project).
8614
+ ...serverCfg.targetAgentId ? { targetAgentId: serverCfg.targetAgentId } : {}
8492
8615
  },
8493
8616
  concurrency: data.concurrency ?? 1,
8494
8617
  reportConfig: data.reportConfig
@@ -8797,7 +8920,7 @@ function registerEvalRoutes(app2) {
8797
8920
  workspaceId: body?.runConfig?.workspaceId ?? bodyWs,
8798
8921
  projectId: body?.runConfig?.projectId ?? bodyPj
8799
8922
  };
8800
- const runId = await evalRunner.startRun(tenantId, pid, body?.suiteIds, body?.caseIds, runConfig);
8923
+ const runId = await evalRunner.startRun(tenantId, pid, body?.suiteIds, body?.caseIds, runConfig, body?.taskId);
8801
8924
  reply.status(202).send({ success: true, message: "Run started", data: { run_id: runId } });
8802
8925
  } catch (err) {
8803
8926
  const msg = err.message;
@@ -10801,6 +10924,7 @@ var registerLatticeRoutes = (app2, channelDeps) => {
10801
10924
  clearMemory
10802
10925
  );
10803
10926
  app2.get("/api/assistants", getAssistantList);
10927
+ app2.get("/api/assistants/stats", getAssistantStats);
10804
10928
  app2.get("/api/assistants/:id", getAssistant);
10805
10929
  app2.post("/api/assistants", createAssistant);
10806
10930
  app2.put("/api/assistants/:id", updateAssistant);