@axiom-lattice/gateway 2.1.111 → 2.1.113

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.
Files changed (32) hide show
  1. package/.turbo/turbo-build.log +13 -13
  2. package/CHANGELOG.md +20 -0
  3. package/dist/index.js +2118 -319
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +1948 -145
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +5 -6
  8. package/src/controllers/__tests__/workflow-tracking.test.ts +113 -0
  9. package/src/controllers/connections.ts +7 -0
  10. package/src/controllers/eval.ts +44 -4
  11. package/src/controllers/export-import.ts +166 -0
  12. package/src/controllers/run.ts +30 -4
  13. package/src/controllers/workflow-tracking.ts +105 -11
  14. package/src/export_registrations/a2a-api-key.registration.ts +89 -0
  15. package/src/export_registrations/agent.registration.ts +80 -0
  16. package/src/export_registrations/binding.registration.ts +106 -0
  17. package/src/export_registrations/channel-installation.registration.ts +88 -0
  18. package/src/export_registrations/collection.registration.ts +85 -0
  19. package/src/export_registrations/connection.registration.ts +97 -0
  20. package/src/export_registrations/database-config.registration.ts +94 -0
  21. package/src/export_registrations/eval.registration.ts +334 -0
  22. package/src/export_registrations/index.ts +31 -0
  23. package/src/export_registrations/mcp-config.registration.ts +97 -0
  24. package/src/export_registrations/menu.registration.ts +91 -0
  25. package/src/export_registrations/metrics-config.registration.ts +94 -0
  26. package/src/export_registrations/skill.registration.ts +88 -0
  27. package/src/export_registrations/task.registration.ts +99 -0
  28. package/src/index.ts +18 -8
  29. package/src/routes/index.ts +42 -1
  30. package/src/services/ExportImportService.ts +296 -0
  31. package/src/services/__tests__/ExportImportService.test.ts +130 -0
  32. package/src/services/eval-runner.ts +63 -55
package/dist/index.mjs CHANGED
@@ -281,6 +281,20 @@ var createRun = async (request, reply) => {
281
281
  project_id,
282
282
  custom_run_config: mergedConfig
283
283
  });
284
+ if (background) {
285
+ const messageInput = message_id ? { ...input, id: message_id } : input;
286
+ const result = await agent.addMessage({
287
+ input: messageInput,
288
+ command,
289
+ custom_run_config: mergedConfig
290
+ }, mode);
291
+ reply.status(202).send({
292
+ success: true,
293
+ messageId: result.messageId,
294
+ queued: true
295
+ });
296
+ return;
297
+ }
284
298
  if (streaming) {
285
299
  reply.hijack();
286
300
  reply.raw.writeHead(200, {
@@ -366,8 +380,13 @@ var resumeStream = async (request, reply) => {
366
380
  workspace_id,
367
381
  project_id
368
382
  });
369
- const stream = agent.chunkStream(message_id, [MessageChunkTypes.THREAD_IDLE]);
383
+ const stream = agent.chunkStream(message_id, []);
384
+ let closed = false;
385
+ request.raw.on("close", () => {
386
+ closed = true;
387
+ });
370
388
  for await (const chunk of stream) {
389
+ if (closed || reply.raw.destroyed) break;
371
390
  reply.raw.write(`data: ${JSON.stringify(chunk)}
372
391
 
373
392
  `);
@@ -2227,7 +2246,7 @@ async function executeSqlQuery(client, body, reply) {
2227
2246
  }
2228
2247
 
2229
2248
  // src/controllers/workflow-tracking.ts
2230
- import { getStoreLattice as getStoreLattice4, agentInstanceManager as agentInstanceManager4, ThreadStatus as ThreadStatus2 } from "@axiom-lattice/core";
2249
+ import { getStoreLattice as getStoreLattice4, agentInstanceManager as agentInstanceManager4, ThreadStatus as ThreadStatus2, abortWorkflowRun as signalAbort } from "@axiom-lattice/core";
2231
2250
  import { MessageChunkTypes as MessageChunkTypes2 } from "@axiom-lattice/protocols";
2232
2251
  function getTenantId7(request) {
2233
2252
  const userTenantId = request.user?.tenantId;
@@ -2366,6 +2385,8 @@ async function getAllWorkflowRuns(request, reply) {
2366
2385
  });
2367
2386
  }
2368
2387
  }
2388
+ var INBOX_DEFAULT_PAGE_SIZE = 20;
2389
+ var INBOX_MAX_PAGE_SIZE = 100;
2369
2390
  async function getInboxItems(request, reply) {
2370
2391
  const tenantId = getTenantId7(request);
2371
2392
  try {
@@ -2383,10 +2404,30 @@ async function getInboxItems(request, reply) {
2383
2404
  }
2384
2405
  } catch {
2385
2406
  }
2386
- const runs = await store.getWorkflowRunsByTenantId(tenantId);
2387
- const pendingRuns = runs.filter((r) => r.status === "interrupted");
2407
+ const { page: pageParam, pageSize: pageSizeParam } = request.query;
2408
+ const paged = pageParam !== void 0 || pageSizeParam !== void 0;
2409
+ const page = Math.max(1, parseInt(pageParam ?? "", 10) || 1);
2410
+ const pageSize = Math.min(INBOX_MAX_PAGE_SIZE, Math.max(1, parseInt(pageSizeParam ?? "", 10) || INBOX_DEFAULT_PAGE_SIZE));
2411
+ let pendingRuns;
2412
+ let total;
2413
+ if (paged) {
2414
+ const result = await store.queryWorkflowRuns(tenantId, {
2415
+ status: "interrupted",
2416
+ limit: pageSize,
2417
+ offset: (page - 1) * pageSize
2418
+ });
2419
+ pendingRuns = result.records;
2420
+ total = result.total;
2421
+ } else {
2422
+ const result = await store.queryWorkflowRuns(tenantId, { status: "interrupted" });
2423
+ pendingRuns = result.records;
2424
+ }
2388
2425
  if (pendingRuns.length === 0) {
2389
- return { success: true, message: "No pending workflows", data: { records: [] } };
2426
+ return {
2427
+ success: true,
2428
+ message: "No pending workflows",
2429
+ data: paged ? { records: [], total, page, pageSize } : { records: [] }
2430
+ };
2390
2431
  }
2391
2432
  const checkPromises = pendingRuns.map(async (r) => {
2392
2433
  try {
@@ -2443,13 +2484,10 @@ async function getInboxItems(request, reply) {
2443
2484
  });
2444
2485
  const results = await Promise.all(checkPromises);
2445
2486
  const inboxItems = results.flat();
2446
- inboxItems.sort(
2447
- (a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime()
2448
- );
2449
2487
  return {
2450
2488
  success: true,
2451
2489
  message: "Successfully retrieved inbox items",
2452
- data: { records: inboxItems }
2490
+ data: paged ? { records: inboxItems, total, page, pageSize } : { records: inboxItems }
2453
2491
  };
2454
2492
  } catch (error) {
2455
2493
  request.log.error(error, "Failed to get inbox items");
@@ -2682,6 +2720,54 @@ async function replyInboxTask(request, reply) {
2682
2720
  });
2683
2721
  }
2684
2722
  }
2723
+ async function abortWorkflowRun(request, reply) {
2724
+ try {
2725
+ const { runId } = request.params;
2726
+ const tenantId = getTenantId7(request);
2727
+ const store = getTrackingStore();
2728
+ if (!store) {
2729
+ return reply.status(404).send({
2730
+ success: false,
2731
+ message: "No workflow tracking store configured"
2732
+ });
2733
+ }
2734
+ const run = await store.getWorkflowRun(runId);
2735
+ if (!run) {
2736
+ return reply.status(404).send({
2737
+ success: false,
2738
+ message: "Workflow run not found"
2739
+ });
2740
+ }
2741
+ await store.updateWorkflowRun(runId, {
2742
+ status: "cancelled",
2743
+ errorMessage: "Aborted by user",
2744
+ completedAt: /* @__PURE__ */ new Date()
2745
+ }).catch(() => {
2746
+ });
2747
+ const workspace_id = request.headers["x-workspace-id"];
2748
+ const project_id = request.headers["x-project-id"];
2749
+ const agent = agentInstanceManager4.getAgent({
2750
+ assistant_id: run.assistantId,
2751
+ thread_id: run.threadId,
2752
+ tenant_id: tenantId,
2753
+ workspace_id,
2754
+ project_id
2755
+ });
2756
+ await agent.abort();
2757
+ signalAbort(runId);
2758
+ return reply.status(200).send({
2759
+ success: true,
2760
+ message: "Workflow aborted",
2761
+ data: { runId, assistantId: run.assistantId, threadId: run.threadId }
2762
+ });
2763
+ } catch (error) {
2764
+ request.log.error(error, "Failed to abort workflow run");
2765
+ return reply.status(500).send({
2766
+ success: false,
2767
+ message: `Abort failed: ${error.message}`
2768
+ });
2769
+ }
2770
+ }
2685
2771
 
2686
2772
  // src/controllers/personal-assistant.ts
2687
2773
  import { getStoreLattice as getStoreLattice5, PersonalAssistantConfig } from "@axiom-lattice/core";
@@ -2945,6 +3031,334 @@ async function completeTask(request, reply) {
2945
3031
  }
2946
3032
  }
2947
3033
 
3034
+ // src/services/ExportImportService.ts
3035
+ import { ExportableEntityRegistry, DependencyResolver, IdRemapper } from "@axiom-lattice/core";
3036
+ import { randomUUID as randomUUID4 } from "crypto";
3037
+ var exportJobs = /* @__PURE__ */ new Map();
3038
+ var JOB_TTL_MS = 60 * 60 * 1e3;
3039
+ function cleanExpiredJobs() {
3040
+ const now = Date.now();
3041
+ for (const [id, entry] of exportJobs) {
3042
+ if (now - entry.createdAt > JOB_TTL_MS) {
3043
+ exportJobs.delete(id);
3044
+ }
3045
+ }
3046
+ }
3047
+ var ExportImportService = class {
3048
+ constructor() {
3049
+ this.registry = ExportableEntityRegistry.getInstance();
3050
+ }
3051
+ /**
3052
+ * Preview an export: check which types would be auto-included, which dependencies are missing.
3053
+ */
3054
+ async exportPreview(tenantId, selectedTypes) {
3055
+ const allDefs = this.registry.getAll();
3056
+ const expanded = DependencyResolver.expandCascade(allDefs, selectedTypes);
3057
+ const cascadeAdditions = expanded.filter((t) => !selectedTypes.includes(t));
3058
+ const deps = DependencyResolver.computeDependencies(allDefs, expanded);
3059
+ const registeredTypes = new Set(allDefs.map((d) => d.entityType));
3060
+ const missingDependencies = deps.missing.filter((t) => registeredTypes.has(t));
3061
+ return { missingDependencies, cascadeAdditions };
3062
+ }
3063
+ /**
3064
+ * Generate a full ExportBundle for the given tenant and entity types.
3065
+ * Stores the bundle in-memory and returns a jobId for download.
3066
+ */
3067
+ async export(tenantId, entityTypes, entityIds) {
3068
+ const allDefs = this.registry.getAll();
3069
+ const expanded = DependencyResolver.expandCascade(allDefs, entityTypes);
3070
+ const finalTypes = [.../* @__PURE__ */ new Set([...expanded, ...entityTypes])];
3071
+ const dependencyOrder = DependencyResolver.resolveOrder(
3072
+ finalTypes.map((t) => this.registry.get(t))
3073
+ );
3074
+ const entities = {};
3075
+ let exportCounter = 0;
3076
+ for (const type of dependencyOrder) {
3077
+ const def = this.registry.get(type);
3078
+ let raw = await def.listForExport(tenantId);
3079
+ if (entityIds && entityIds[type] && entityIds[type].length > 0) {
3080
+ const idSet = new Set(entityIds[type]);
3081
+ raw = raw.filter((e) => idSet.has(e.data.id));
3082
+ }
3083
+ entities[type] = raw.map((e) => ({
3084
+ ...e,
3085
+ _exportId: `exp-${type}-${String(++exportCounter).padStart(3, "0")}`,
3086
+ data: this.sanitizeEntityData(e.data)
3087
+ }));
3088
+ }
3089
+ const rawIdToExportId = /* @__PURE__ */ new Map();
3090
+ for (const [, entityList] of Object.entries(entities)) {
3091
+ for (const entity of entityList) {
3092
+ const rawId = entity.data.id;
3093
+ if (rawId) {
3094
+ rawIdToExportId.set(rawId, entity._exportId);
3095
+ }
3096
+ }
3097
+ }
3098
+ for (const [type, entityList] of Object.entries(entities)) {
3099
+ const def = this.registry.get(type);
3100
+ const refFields = def.referenceFields || {};
3101
+ for (const entity of entityList) {
3102
+ for (const [fieldName, refEntityType] of Object.entries(refFields)) {
3103
+ const rawValue = entity.data[fieldName];
3104
+ if (typeof rawValue === "string" && rawValue) {
3105
+ const exportId = rawIdToExportId.get(rawValue);
3106
+ if (exportId) {
3107
+ entity.data[fieldName] = `@${refEntityType}/${exportId}`;
3108
+ }
3109
+ }
3110
+ }
3111
+ }
3112
+ }
3113
+ const bundle = {
3114
+ version: 1,
3115
+ exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
3116
+ sourceTenantId: tenantId,
3117
+ entities,
3118
+ dependencyOrder,
3119
+ _warning: "This file contains plaintext secrets (passwords, API keys, tokens). Store it securely and delete after import."
3120
+ };
3121
+ const jobId = randomUUID4();
3122
+ exportJobs.set(jobId, { bundle, tenantId, createdAt: Date.now() });
3123
+ return { jobId, bundle };
3124
+ }
3125
+ /**
3126
+ * Retrieve a previously generated export bundle by jobId with tenant validation.
3127
+ */
3128
+ getExportJob(jobId, tenantId) {
3129
+ cleanExpiredJobs();
3130
+ const entry = exportJobs.get(jobId);
3131
+ if (!entry || entry.tenantId !== tenantId) return void 0;
3132
+ return entry.bundle;
3133
+ }
3134
+ /**
3135
+ * Preview import: validate bundle and detect conflicts.
3136
+ */
3137
+ async previewImport(tenantId, bundle) {
3138
+ this.validateBundle(bundle);
3139
+ const allConflicts = [];
3140
+ const allInsertions = [];
3141
+ const allErrors = [];
3142
+ for (const [entityType, entities] of Object.entries(bundle.entities)) {
3143
+ if (entities.length === 0) continue;
3144
+ try {
3145
+ const def = this.registry.get(entityType);
3146
+ const result = await def.previewImport(tenantId, entities);
3147
+ allConflicts.push(...result.conflicts);
3148
+ allInsertions.push(...result.insertions);
3149
+ allErrors.push(...result.errors);
3150
+ } catch (err) {
3151
+ for (const entity of entities) {
3152
+ allErrors.push({
3153
+ _exportId: entity._exportId,
3154
+ entityType,
3155
+ error: `Preview failed: ${err.message}`
3156
+ });
3157
+ }
3158
+ }
3159
+ }
3160
+ return { conflicts: allConflicts, insertions: allInsertions, errors: allErrors };
3161
+ }
3162
+ /**
3163
+ * Apply import: create entities in dependency order with ID remapping.
3164
+ */
3165
+ async applyImport(tenantId, bundle, resolutions) {
3166
+ this.validateBundle(bundle);
3167
+ const results = [];
3168
+ const idMap = {};
3169
+ const skillIdRemap = {};
3170
+ for (const entityType of bundle.dependencyOrder) {
3171
+ const entities = bundle.entities[entityType];
3172
+ if (!entities || entities.length === 0) continue;
3173
+ const def = this.registry.get(entityType);
3174
+ const remapper = new IdRemapper(idMap);
3175
+ for (const entity of entities) {
3176
+ const resolution = resolutions[entity._exportId];
3177
+ if (resolution?.action === "skip") {
3178
+ results.push({ _exportId: entity._exportId, entityType, status: "skipped" });
3179
+ continue;
3180
+ }
3181
+ try {
3182
+ const remappedData = remapper.remapReferences(entity.data);
3183
+ if (entityType === "agent" && Object.keys(skillIdRemap).length > 0) {
3184
+ const skillRemapper = new IdRemapper({});
3185
+ remappedData.graphDefinition = skillRemapper.remapSkillIds(
3186
+ remappedData.graphDefinition || {},
3187
+ skillIdRemap
3188
+ );
3189
+ }
3190
+ if (resolution?.action === "rename" && resolution.newId) {
3191
+ remappedData.id = resolution.newId;
3192
+ }
3193
+ const entityWithRemappedData = { ...entity, data: remappedData };
3194
+ const { newId } = await def.applyImport(
3195
+ tenantId,
3196
+ entityWithRemappedData,
3197
+ resolution ?? { _exportId: entity._exportId, action: "overwrite" }
3198
+ );
3199
+ if (newId) {
3200
+ idMap[entity._exportId] = newId;
3201
+ if (entityType === "skill" && newId) {
3202
+ const oldSkillId = remappedData.id;
3203
+ if (oldSkillId !== newId) {
3204
+ skillIdRemap[oldSkillId] = newId;
3205
+ }
3206
+ }
3207
+ results.push({
3208
+ _exportId: entity._exportId,
3209
+ entityType,
3210
+ status: resolution?.action === "overwrite" ? "updated" : "created",
3211
+ newId
3212
+ });
3213
+ }
3214
+ } catch (err) {
3215
+ results.push({
3216
+ _exportId: entity._exportId,
3217
+ entityType,
3218
+ status: "failed",
3219
+ error: err.message
3220
+ });
3221
+ }
3222
+ }
3223
+ }
3224
+ return { results, idMap };
3225
+ }
3226
+ /**
3227
+ * List all registered exportable types (for frontend).
3228
+ */
3229
+ listExportableTypes() {
3230
+ return this.registry.listTypes();
3231
+ }
3232
+ validateBundle(bundle) {
3233
+ if (bundle.version !== 1) {
3234
+ throw new Error(`Unsupported bundle version: ${bundle.version}. Expected: 1`);
3235
+ }
3236
+ if (!bundle.entities || typeof bundle.entities !== "object") {
3237
+ throw new Error("Invalid bundle: missing entities");
3238
+ }
3239
+ if (!Array.isArray(bundle.dependencyOrder)) {
3240
+ throw new Error("Invalid bundle: missing dependencyOrder");
3241
+ }
3242
+ }
3243
+ sanitizeEntityData(data) {
3244
+ const sanitized = { ...data };
3245
+ delete sanitized.tenantId;
3246
+ delete sanitized.createdAt;
3247
+ delete sanitized.updatedAt;
3248
+ return sanitized;
3249
+ }
3250
+ };
3251
+
3252
+ // src/controllers/export-import.ts
3253
+ import { ExportableEntityRegistry as ExportableEntityRegistry2 } from "@axiom-lattice/core";
3254
+ var service = new ExportImportService();
3255
+ function getTenantId10(request) {
3256
+ return request.user?.tenantId || request.headers["x-tenant-id"] || "default";
3257
+ }
3258
+ async function getExportableTypes(_request, reply) {
3259
+ const types = service.listExportableTypes();
3260
+ return reply.send({ success: true, data: types });
3261
+ }
3262
+ async function exportConfig(request, reply) {
3263
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3264
+ const { entityTypes, entityIds } = request.body;
3265
+ if (!Array.isArray(entityTypes) || entityTypes.length === 0) {
3266
+ return reply.status(400).send({ success: false, message: "entityTypes must be a non-empty array" });
3267
+ }
3268
+ const preview = await service.exportPreview(tenantId, entityTypes);
3269
+ if (preview.missingDependencies.length > 0 || preview.cascadeAdditions.length > 0) {
3270
+ return reply.send({
3271
+ success: true,
3272
+ data: {
3273
+ needsConfirmation: true,
3274
+ missingDependencies: preview.missingDependencies,
3275
+ cascadeAdditions: preview.cascadeAdditions
3276
+ }
3277
+ });
3278
+ }
3279
+ const { jobId, bundle } = await service.export(tenantId, entityTypes, entityIds);
3280
+ return reply.send({
3281
+ success: true,
3282
+ data: {
3283
+ jobId,
3284
+ summary: Object.fromEntries(
3285
+ Object.entries(bundle.entities).map(([type, entities]) => [type, entities.length])
3286
+ )
3287
+ }
3288
+ });
3289
+ }
3290
+ async function exportConfigConfirm(request, reply) {
3291
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3292
+ const { entityTypes, entityIds } = request.body;
3293
+ const { jobId, bundle } = await service.export(tenantId, entityTypes, entityIds);
3294
+ return reply.send({
3295
+ success: true,
3296
+ data: {
3297
+ jobId,
3298
+ summary: Object.fromEntries(
3299
+ Object.entries(bundle.entities).map(([type, entities]) => [type, entities.length])
3300
+ )
3301
+ }
3302
+ });
3303
+ }
3304
+ async function previewEntities(request, reply) {
3305
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3306
+ const { entityTypes } = request.body;
3307
+ try {
3308
+ const registry = ExportableEntityRegistry2.getInstance();
3309
+ const result = {};
3310
+ for (const type of entityTypes) {
3311
+ const def = registry.get(type);
3312
+ const entities = await def.listForExport(tenantId);
3313
+ result[type] = entities.map((e) => ({
3314
+ id: e.data.id,
3315
+ name: e.data.name || e.data.id,
3316
+ description: e.data.description
3317
+ }));
3318
+ }
3319
+ return reply.send({ success: true, data: result });
3320
+ } catch (err) {
3321
+ return reply.status(400).send({ success: false, message: err.message });
3322
+ }
3323
+ }
3324
+ async function downloadExport(request, reply) {
3325
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3326
+ const bundle = service.getExportJob(request.params.jobId, tenantId);
3327
+ if (!bundle) {
3328
+ return reply.status(404).send({ success: false, message: "Export job not found or expired" });
3329
+ }
3330
+ return reply.header("Content-Type", "application/json").header("Content-Disposition", `attachment; filename="tenant-export-${bundle.sourceTenantId}.json"`).send({ success: true, data: bundle });
3331
+ }
3332
+ async function importPreview(request, reply) {
3333
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3334
+ const { bundle } = request.body;
3335
+ if (!bundle) {
3336
+ return reply.status(400).send({ success: false, message: "No bundle provided in request body" });
3337
+ }
3338
+ try {
3339
+ const preview = await service.previewImport(tenantId, bundle);
3340
+ return reply.send({ success: true, data: preview });
3341
+ } catch (err) {
3342
+ return reply.status(400).send({
3343
+ success: false,
3344
+ message: `Invalid export file: ${err.message}`
3345
+ });
3346
+ }
3347
+ }
3348
+ async function importApply(request, reply) {
3349
+ const tenantId = getTenantId10(request) || request.params.tenantId;
3350
+ try {
3351
+ const { bundle, resolutions } = request.body;
3352
+ const result = await service.applyImport(tenantId, bundle, resolutions);
3353
+ return reply.send({ success: true, data: result });
3354
+ } catch (err) {
3355
+ return reply.status(400).send({
3356
+ success: false,
3357
+ message: `Import failed: ${err.message}`
3358
+ });
3359
+ }
3360
+ }
3361
+
2948
3362
  // src/controllers/middleware-types.ts
2949
3363
  import { PluginRegistry } from "@axiom-lattice/core";
2950
3364
  function middlewareTypesRoutes(fastify2) {
@@ -4147,8 +4561,8 @@ import {
4147
4561
  getStoreLattice as getStoreLattice8,
4148
4562
  sqlDatabaseManager
4149
4563
  } from "@axiom-lattice/core";
4150
- import { randomUUID as randomUUID4 } from "crypto";
4151
- function getTenantId10(request) {
4564
+ import { randomUUID as randomUUID5 } from "crypto";
4565
+ function getTenantId11(request) {
4152
4566
  const userTenantId = request.user?.tenantId;
4153
4567
  if (userTenantId) {
4154
4568
  return userTenantId;
@@ -4156,7 +4570,7 @@ function getTenantId10(request) {
4156
4570
  return request.headers["x-tenant-id"] || "default";
4157
4571
  }
4158
4572
  async function getDatabaseConfigList(request, reply) {
4159
- const tenantId = getTenantId10(request);
4573
+ const tenantId = getTenantId11(request);
4160
4574
  try {
4161
4575
  const storeLattice = getStoreLattice8("default", "database");
4162
4576
  const store = storeLattice.store;
@@ -4186,7 +4600,7 @@ async function getDatabaseConfigList(request, reply) {
4186
4600
  }
4187
4601
  }
4188
4602
  async function getDatabaseConfig(request, reply) {
4189
- const tenantId = getTenantId10(request);
4603
+ const tenantId = getTenantId11(request);
4190
4604
  const { key } = request.params;
4191
4605
  try {
4192
4606
  const storeLattice = getStoreLattice8("default", "database");
@@ -4212,7 +4626,7 @@ async function getDatabaseConfig(request, reply) {
4212
4626
  }
4213
4627
  }
4214
4628
  async function createDatabaseConfig(request, reply) {
4215
- const tenantId = getTenantId10(request);
4629
+ const tenantId = getTenantId11(request);
4216
4630
  const body = request.body;
4217
4631
  try {
4218
4632
  const storeLattice = getStoreLattice8("default", "database");
@@ -4225,7 +4639,7 @@ async function createDatabaseConfig(request, reply) {
4225
4639
  message: "Database configuration with this key already exists"
4226
4640
  };
4227
4641
  }
4228
- const id = body.id || randomUUID4();
4642
+ const id = body.id || randomUUID5();
4229
4643
  const config = await store.createConfig(tenantId, id, body);
4230
4644
  try {
4231
4645
  sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
@@ -4247,7 +4661,7 @@ async function createDatabaseConfig(request, reply) {
4247
4661
  }
4248
4662
  }
4249
4663
  async function updateDatabaseConfig(request, reply) {
4250
- const tenantId = getTenantId10(request);
4664
+ const tenantId = getTenantId11(request);
4251
4665
  const { key } = request.params;
4252
4666
  const updates = request.body;
4253
4667
  try {
@@ -4289,7 +4703,7 @@ async function updateDatabaseConfig(request, reply) {
4289
4703
  }
4290
4704
  }
4291
4705
  async function deleteDatabaseConfig(request, reply) {
4292
- const tenantId = getTenantId10(request);
4706
+ const tenantId = getTenantId11(request);
4293
4707
  const { keyOrId } = request.params;
4294
4708
  try {
4295
4709
  const storeLattice = getStoreLattice8("default", "database");
@@ -4338,7 +4752,7 @@ async function deleteDatabaseConfig(request, reply) {
4338
4752
  }
4339
4753
  }
4340
4754
  async function testDatabaseConnection(request, reply) {
4341
- const tenantId = getTenantId10(request);
4755
+ const tenantId = getTenantId11(request);
4342
4756
  const { key } = request.params;
4343
4757
  try {
4344
4758
  const storeLattice = getStoreLattice8("default", "database");
@@ -4430,8 +4844,8 @@ import {
4430
4844
  metricsServerManager as metricsServerManager2,
4431
4845
  SemanticMetricsClient as SemanticMetricsClient2
4432
4846
  } from "@axiom-lattice/core";
4433
- import { randomUUID as randomUUID5 } from "crypto";
4434
- function getTenantId11(request) {
4847
+ import { randomUUID as randomUUID6 } from "crypto";
4848
+ function getTenantId12(request) {
4435
4849
  const userTenantId = request.user?.tenantId;
4436
4850
  if (userTenantId) {
4437
4851
  return userTenantId;
@@ -4439,7 +4853,7 @@ function getTenantId11(request) {
4439
4853
  return request.headers["x-tenant-id"] || "default";
4440
4854
  }
4441
4855
  async function getMetricsServerConfigList(request, reply) {
4442
- const tenantId = getTenantId11(request);
4856
+ const tenantId = getTenantId12(request);
4443
4857
  try {
4444
4858
  const storeLattice = getStoreLattice9("default", "metrics");
4445
4859
  const store = storeLattice.store;
@@ -4465,7 +4879,7 @@ async function getMetricsServerConfigList(request, reply) {
4465
4879
  }
4466
4880
  }
4467
4881
  async function getMetricsServerConfig(request, reply) {
4468
- const tenantId = getTenantId11(request);
4882
+ const tenantId = getTenantId12(request);
4469
4883
  const { key } = request.params;
4470
4884
  try {
4471
4885
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4491,7 +4905,7 @@ async function getMetricsServerConfig(request, reply) {
4491
4905
  }
4492
4906
  }
4493
4907
  async function createMetricsServerConfig(request, reply) {
4494
- const tenantId = getTenantId11(request);
4908
+ const tenantId = getTenantId12(request);
4495
4909
  const body = request.body;
4496
4910
  try {
4497
4911
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4511,7 +4925,7 @@ async function createMetricsServerConfig(request, reply) {
4511
4925
  message: "selectedDataSources is required for semantic metrics servers"
4512
4926
  };
4513
4927
  }
4514
- const id = body.id || randomUUID5();
4928
+ const id = body.id || randomUUID6();
4515
4929
  const configData = {
4516
4930
  key: body.key,
4517
4931
  name: body.name,
@@ -4542,7 +4956,7 @@ async function createMetricsServerConfig(request, reply) {
4542
4956
  }
4543
4957
  }
4544
4958
  async function updateMetricsServerConfig(request, reply) {
4545
- const tenantId = getTenantId11(request);
4959
+ const tenantId = getTenantId12(request);
4546
4960
  const { key } = request.params;
4547
4961
  const updates = request.body;
4548
4962
  try {
@@ -4593,7 +5007,7 @@ async function updateMetricsServerConfig(request, reply) {
4593
5007
  }
4594
5008
  }
4595
5009
  async function deleteMetricsServerConfig(request, reply) {
4596
- const tenantId = getTenantId11(request);
5010
+ const tenantId = getTenantId12(request);
4597
5011
  const { keyOrId } = request.params;
4598
5012
  try {
4599
5013
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4640,7 +5054,7 @@ async function deleteMetricsServerConfig(request, reply) {
4640
5054
  }
4641
5055
  }
4642
5056
  async function testMetricsServerConnection(request, reply) {
4643
- const tenantId = getTenantId11(request);
5057
+ const tenantId = getTenantId12(request);
4644
5058
  const { key } = request.params;
4645
5059
  try {
4646
5060
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4691,7 +5105,7 @@ async function testMetricsServerConnection(request, reply) {
4691
5105
  }
4692
5106
  }
4693
5107
  async function listAvailableMetrics(request, reply) {
4694
- const tenantId = getTenantId11(request);
5108
+ const tenantId = getTenantId12(request);
4695
5109
  const { key } = request.params;
4696
5110
  try {
4697
5111
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4729,7 +5143,7 @@ async function listAvailableMetrics(request, reply) {
4729
5143
  }
4730
5144
  }
4731
5145
  async function queryMetricsData(request, reply) {
4732
- const tenantId = getTenantId11(request);
5146
+ const tenantId = getTenantId12(request);
4733
5147
  const { key } = request.params;
4734
5148
  const { metricName, startTime, endTime, step, labels } = request.body;
4735
5149
  try {
@@ -4777,7 +5191,7 @@ async function queryMetricsData(request, reply) {
4777
5191
  }
4778
5192
  }
4779
5193
  async function getDataSources(request, reply) {
4780
- const tenantId = getTenantId11(request);
5194
+ const tenantId = getTenantId12(request);
4781
5195
  const { key } = request.params;
4782
5196
  try {
4783
5197
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4818,7 +5232,7 @@ async function getDataSources(request, reply) {
4818
5232
  }
4819
5233
  }
4820
5234
  async function getDatasourceMetrics(request, reply) {
4821
- const tenantId = getTenantId11(request);
5235
+ const tenantId = getTenantId12(request);
4822
5236
  const { key, datasourceId } = request.params;
4823
5237
  try {
4824
5238
  const storeLattice = getStoreLattice9("default", "metrics");
@@ -4855,7 +5269,7 @@ async function getDatasourceMetrics(request, reply) {
4855
5269
  }
4856
5270
  }
4857
5271
  async function querySemanticMetrics(request, reply) {
4858
- const tenantId = getTenantId11(request);
5272
+ const tenantId = getTenantId12(request);
4859
5273
  const { key } = request.params;
4860
5274
  const body = request.body;
4861
5275
  try {
@@ -5026,6 +5440,10 @@ var testOrDiscoverBody = z.object({
5026
5440
  config: z.record(z.unknown()).optional()
5027
5441
  });
5028
5442
  function getTenant(request) {
5443
+ const userTenantId = request.user?.tenantId;
5444
+ if (userTenantId) {
5445
+ return userTenantId;
5446
+ }
5029
5447
  return request.headers["x-tenant-id"] || "default";
5030
5448
  }
5031
5449
  function maskSecrets(config) {
@@ -5171,8 +5589,11 @@ import { v4 as uuidv44 } from "uuid";
5171
5589
 
5172
5590
  // src/services/eval-runner.ts
5173
5591
  import { EventEmitter } from "events";
5174
- import { getStoreLattice as getStoreLattice10, modelLatticeManager as modelLatticeManager2 } from "@axiom-lattice/core";
5175
- import { LatticeEvalProject } from "@axiom-lattice/agent-eval";
5592
+ import {
5593
+ getStoreLattice as getStoreLattice10,
5594
+ modelLatticeManager as modelLatticeManager2,
5595
+ LatticeEvalProject
5596
+ } from "@axiom-lattice/core";
5176
5597
  import { v4 as uuidv43 } from "uuid";
5177
5598
  function mapLogs(logs) {
5178
5599
  return logs.map((l) => ({
@@ -5194,6 +5615,11 @@ var EvalRunner = class {
5194
5615
  const store = this.getEvalStore();
5195
5616
  const project = await store.getProjectById(tenantId, projectId);
5196
5617
  if (!project) throw new Error("Project not found");
5618
+ for (const ctx of this.runs.values()) {
5619
+ if (ctx.projectId === projectId) {
5620
+ throw new Error("A run is already in progress for this project");
5621
+ }
5622
+ }
5197
5623
  const existingRuns = await store.getRunsByTenant(tenantId, { projectId, status: "running" });
5198
5624
  if (existingRuns.length > 0) {
5199
5625
  throw new Error("A run is already in progress for this project");
@@ -5210,7 +5636,7 @@ var EvalRunner = class {
5210
5636
  caseId: c.id,
5211
5637
  input: { message: c.inputMessage, files: c.inputFiles },
5212
5638
  steps: c.steps,
5213
- output: { type: c.outputType },
5639
+ output: { type: "message_content" },
5214
5640
  eval: {
5215
5641
  content_assertion: c.contentAssertion,
5216
5642
  eval_rubrics: c.rubrics?.map((r) => ({
@@ -5222,35 +5648,32 @@ var EvalRunner = class {
5222
5648
  }))
5223
5649
  });
5224
5650
  }
5225
- const runId = uuidv43();
5226
- const concurrency = project.concurrency || 3;
5227
- await store.createRun(tenantId, projectId, runId, { totalCases, concurrency });
5228
- const judgeCfg = project.judgeModelConfig;
5229
- const hasModelKey = Boolean(judgeCfg.modelKey);
5230
- const hasApiKey = Boolean(judgeCfg.apiKeyEnvName || judgeCfg.apiKey);
5231
- const hasCredentials = hasApiKey;
5232
- let judgeModelConfig = {};
5233
- if (hasModelKey) {
5234
- judgeModelConfig = { modelKey: judgeCfg.modelKey };
5235
- } else if (!hasCredentials) {
5236
- const firstModel = modelLatticeManager2.getAllLattices()[0];
5237
- if (firstModel) {
5238
- judgeModelConfig = { modelKey: firstModel.key };
5239
- } else {
5240
- judgeModelConfig = { model: judgeCfg };
5651
+ const judgeCfg = project.judgeModelConfig ?? {};
5652
+ const judgeModelKey = judgeCfg.modelKey || "";
5653
+ let resolvedJudgeModelKey;
5654
+ if (judgeModelKey) {
5655
+ if (!modelLatticeManager2.hasLattice(judgeModelKey)) {
5656
+ throw new Error(`Judge model "${judgeModelKey}" is not registered`);
5241
5657
  }
5658
+ resolvedJudgeModelKey = judgeModelKey;
5242
5659
  } else {
5243
- judgeModelConfig = { model: judgeCfg };
5660
+ const firstModel = modelLatticeManager2.getAllLattices()[0];
5661
+ if (!firstModel) {
5662
+ throw new Error("No model registered \u2014 cannot run eval without a judge model");
5663
+ }
5664
+ resolvedJudgeModelKey = firstModel.key;
5665
+ console.warn(`[eval-runner] Project "${project.name}" has no judge modelKey \u2014 falling back to first registered model "${firstModel.key}"`);
5244
5666
  }
5667
+ const runId = uuidv43();
5668
+ const concurrency = Math.max(1, Math.floor(project.concurrency) || 3);
5669
+ await store.createRun(tenantId, projectId, runId, { totalCases, concurrency });
5245
5670
  const projectConfig = {
5246
5671
  projectName: project.name,
5247
5672
  version: project.version,
5248
5673
  description: project.description,
5249
5674
  suites: evalSuites,
5250
- judge_agent_config: judgeModelConfig,
5675
+ judge_agent_config: { modelKey: resolvedJudgeModelKey },
5251
5676
  lattice_server_config: {
5252
- base_url: project.targetServerConfig.base_url || "",
5253
- api_key: project.targetServerConfig.api_key || "",
5254
5677
  tenant_id: tenantId
5255
5678
  },
5256
5679
  concurrency
@@ -5295,33 +5718,37 @@ var EvalRunner = class {
5295
5718
  const runPromise = (async () => {
5296
5719
  try {
5297
5720
  const evalProject = new LatticeEvalProject(projectConfig, onCaseComplete);
5298
- const { report } = await evalProject.runAllSuitesBatch(concurrency);
5299
- const completedCount = stats.passed + stats.failed;
5300
- await store.updateRunStatus(tenantId, runId, {
5301
- status: "completed",
5302
- completedAt: /* @__PURE__ */ new Date(),
5303
- passedCases: stats.passed,
5304
- failedCases: stats.failed,
5305
- avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0
5306
- });
5307
- this.eventEmitter.emit(`run:${runId}`, {
5308
- type: "completed",
5309
- runId,
5310
- data: { passed: stats.passed, failed: stats.failed, avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0 }
5311
- });
5721
+ const { report } = await evalProject.runAllSuitesBatch(concurrency, abortController.signal);
5722
+ if (!abortController.signal.aborted) {
5723
+ const completedCount = stats.passed + stats.failed;
5724
+ await store.updateRunStatus(tenantId, runId, {
5725
+ status: "completed",
5726
+ completedAt: /* @__PURE__ */ new Date(),
5727
+ passedCases: stats.passed,
5728
+ failedCases: stats.failed,
5729
+ avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0
5730
+ });
5731
+ this.eventEmitter.emit(`run:${runId}`, {
5732
+ type: "completed",
5733
+ runId,
5734
+ data: { passed: stats.passed, failed: stats.failed, avgScore: completedCount > 0 ? stats.totalScore / completedCount : 0 }
5735
+ });
5736
+ }
5312
5737
  return { report };
5313
5738
  } catch (err) {
5314
5739
  const errorMsg = err.message;
5315
- await store.updateRunStatus(tenantId, runId, {
5316
- status: "failed",
5317
- error: errorMsg,
5318
- completedAt: /* @__PURE__ */ new Date()
5319
- });
5320
- this.eventEmitter.emit(`run:${runId}`, {
5321
- type: "error",
5322
- runId,
5323
- data: { message: errorMsg }
5324
- });
5740
+ if (!abortController.signal.aborted) {
5741
+ await store.updateRunStatus(tenantId, runId, {
5742
+ status: "failed",
5743
+ error: errorMsg,
5744
+ completedAt: /* @__PURE__ */ new Date()
5745
+ });
5746
+ this.eventEmitter.emit(`run:${runId}`, {
5747
+ type: "error",
5748
+ runId,
5749
+ data: { message: errorMsg }
5750
+ });
5751
+ }
5325
5752
  throw err;
5326
5753
  } finally {
5327
5754
  this.runs.delete(runId);
@@ -5350,7 +5777,7 @@ var EvalRunner = class {
5350
5777
  var evalRunner = new EvalRunner();
5351
5778
 
5352
5779
  // src/controllers/eval.ts
5353
- function getTenantId12(request) {
5780
+ function getTenantId13(request) {
5354
5781
  const userTenantId = request.user?.tenantId;
5355
5782
  if (userTenantId) {
5356
5783
  return userTenantId;
@@ -5362,16 +5789,31 @@ function getEvalStore() {
5362
5789
  }
5363
5790
  async function createProject(request, reply) {
5364
5791
  try {
5365
- const tenantId = getTenantId12(request);
5792
+ const tenantId = getTenantId13(request);
5366
5793
  const store = getEvalStore();
5367
5794
  const id = uuidv44();
5368
5795
  const data = request.body;
5796
+ const serverCfg = data.targetServerConfig || {};
5797
+ const judgeCfg = data.judgeModelConfig || {};
5798
+ const modelKey = judgeCfg.modelKey || "";
5799
+ if (modelKey) {
5800
+ const { modelLatticeManager: modelLatticeManager3 } = await import("@axiom-lattice/core");
5801
+ if (!modelLatticeManager3.hasLattice(modelKey)) {
5802
+ return reply.status(400).send({ success: false, message: `Judge model "${modelKey}" is not registered` });
5803
+ }
5804
+ }
5369
5805
  const project = await store.createProject(tenantId, id, {
5370
5806
  name: data.name,
5371
5807
  description: data.description,
5372
5808
  version: data.version,
5373
- judgeModelConfig: data.judgeModelConfig ?? {},
5374
- targetServerConfig: data.targetServerConfig ?? {},
5809
+ judgeModelConfig: {
5810
+ modelKey,
5811
+ displayName: judgeCfg.displayName || ""
5812
+ },
5813
+ targetServerConfig: {
5814
+ base_url: serverCfg.base_url || "",
5815
+ api_key: serverCfg.api_key || ""
5816
+ },
5375
5817
  concurrency: data.concurrency ?? 1,
5376
5818
  reportConfig: data.reportConfig
5377
5819
  });
@@ -5387,7 +5829,7 @@ async function createProject(request, reply) {
5387
5829
  }
5388
5830
  async function listProjects(request, reply) {
5389
5831
  try {
5390
- const tenantId = getTenantId12(request);
5832
+ const tenantId = getTenantId13(request);
5391
5833
  const store = getEvalStore();
5392
5834
  let projects = await store.getProjectsByTenant(tenantId);
5393
5835
  if (projects.length === 0) {
@@ -5395,7 +5837,7 @@ async function listProjects(request, reply) {
5395
5837
  const { modelLatticeManager: modelLatticeManager3 } = await import("@axiom-lattice/core");
5396
5838
  const models = modelLatticeManager3.getAllLattices();
5397
5839
  const first = models[0];
5398
- const judgeModel = first ? { modelKey: first.key } : { provider: "openai", model: "gpt-4" };
5840
+ const judgeModel = first ? { modelKey: first.key } : {};
5399
5841
  const host = request.hostname || "localhost";
5400
5842
  const baseUrl = `http://${host}:${process.env.PORT || 4001}`;
5401
5843
  await store.createProject(tenantId, uuidv44(), {
@@ -5421,7 +5863,7 @@ async function listProjects(request, reply) {
5421
5863
  }
5422
5864
  async function getProject(request, reply) {
5423
5865
  try {
5424
- const tenantId = getTenantId12(request);
5866
+ const tenantId = getTenantId13(request);
5425
5867
  const store = getEvalStore();
5426
5868
  const { pid } = request.params;
5427
5869
  const project = await store.getProjectById(tenantId, pid);
@@ -5441,14 +5883,37 @@ async function getProject(request, reply) {
5441
5883
  }
5442
5884
  async function updateProject(request, reply) {
5443
5885
  try {
5444
- const tenantId = getTenantId12(request);
5886
+ const tenantId = getTenantId13(request);
5445
5887
  const store = getEvalStore();
5446
5888
  const { pid } = request.params;
5447
5889
  const existing = await store.getProjectById(tenantId, pid);
5448
5890
  if (!existing) {
5449
5891
  return reply.status(404).send({ success: false, message: "Project not found" });
5450
5892
  }
5451
- const updated = await store.updateProject(tenantId, pid, request.body);
5893
+ const body = request.body;
5894
+ const updateData = { ...body };
5895
+ const serverCfg = body.targetServerConfig || {};
5896
+ if (body.targetServerConfig !== void 0) {
5897
+ updateData.targetServerConfig = {
5898
+ base_url: serverCfg.base_url || "",
5899
+ api_key: serverCfg.api_key || ""
5900
+ };
5901
+ }
5902
+ if (body.judgeModelConfig !== void 0) {
5903
+ const judgeCfg = body.judgeModelConfig || {};
5904
+ const modelKey = judgeCfg.modelKey || "";
5905
+ if (modelKey) {
5906
+ const { modelLatticeManager: modelLatticeManager3 } = await import("@axiom-lattice/core");
5907
+ if (!modelLatticeManager3.hasLattice(modelKey)) {
5908
+ return reply.status(400).send({ success: false, message: `Judge model "${modelKey}" is not registered` });
5909
+ }
5910
+ }
5911
+ updateData.judgeModelConfig = {
5912
+ modelKey,
5913
+ displayName: judgeCfg.displayName || ""
5914
+ };
5915
+ }
5916
+ const updated = await store.updateProject(tenantId, pid, updateData);
5452
5917
  return {
5453
5918
  success: true,
5454
5919
  message: "Successfully updated project",
@@ -5461,7 +5926,7 @@ async function updateProject(request, reply) {
5461
5926
  }
5462
5927
  async function deleteProject(request, reply) {
5463
5928
  try {
5464
- const tenantId = getTenantId12(request);
5929
+ const tenantId = getTenantId13(request);
5465
5930
  const store = getEvalStore();
5466
5931
  const { pid } = request.params;
5467
5932
  const existing = await store.getProjectById(tenantId, pid);
@@ -5480,7 +5945,7 @@ async function deleteProject(request, reply) {
5480
5945
  }
5481
5946
  async function createSuite(request, reply) {
5482
5947
  try {
5483
- const tenantId = getTenantId12(request);
5948
+ const tenantId = getTenantId13(request);
5484
5949
  const store = getEvalStore();
5485
5950
  const { pid } = request.params;
5486
5951
  const project = await store.getProjectById(tenantId, pid);
@@ -5502,7 +5967,7 @@ async function createSuite(request, reply) {
5502
5967
  }
5503
5968
  async function updateSuite(request, reply) {
5504
5969
  try {
5505
- const tenantId = getTenantId12(request);
5970
+ const tenantId = getTenantId13(request);
5506
5971
  const store = getEvalStore();
5507
5972
  const { sid } = request.params;
5508
5973
  const existing = await store.getSuiteById(tenantId, sid);
@@ -5522,7 +5987,7 @@ async function updateSuite(request, reply) {
5522
5987
  }
5523
5988
  async function deleteSuite(request, reply) {
5524
5989
  try {
5525
- const tenantId = getTenantId12(request);
5990
+ const tenantId = getTenantId13(request);
5526
5991
  const store = getEvalStore();
5527
5992
  const { sid } = request.params;
5528
5993
  const existing = await store.getSuiteById(tenantId, sid);
@@ -5541,7 +6006,7 @@ async function deleteSuite(request, reply) {
5541
6006
  }
5542
6007
  async function createCase(request, reply) {
5543
6008
  try {
5544
- const tenantId = getTenantId12(request);
6009
+ const tenantId = getTenantId13(request);
5545
6010
  const store = getEvalStore();
5546
6011
  const { sid } = request.params;
5547
6012
  const suite = await store.getSuiteById(tenantId, sid);
@@ -5570,7 +6035,7 @@ async function createCase(request, reply) {
5570
6035
  }
5571
6036
  async function listCasesForSuite(request, reply) {
5572
6037
  try {
5573
- const tenantId = getTenantId12(request);
6038
+ const tenantId = getTenantId13(request);
5574
6039
  const store = getEvalStore();
5575
6040
  const { sid } = request.params;
5576
6041
  const cases = await store.getCasesBySuite(tenantId, sid);
@@ -5586,7 +6051,7 @@ async function listCasesForSuite(request, reply) {
5586
6051
  }
5587
6052
  async function updateCase(request, reply) {
5588
6053
  try {
5589
- const tenantId = getTenantId12(request);
6054
+ const tenantId = getTenantId13(request);
5590
6055
  const store = getEvalStore();
5591
6056
  const { cid } = request.params;
5592
6057
  const existing = await store.getCaseById(tenantId, cid);
@@ -5606,7 +6071,7 @@ async function updateCase(request, reply) {
5606
6071
  }
5607
6072
  async function deleteCase(request, reply) {
5608
6073
  try {
5609
- const tenantId = getTenantId12(request);
6074
+ const tenantId = getTenantId13(request);
5610
6075
  const store = getEvalStore();
5611
6076
  const { cid } = request.params;
5612
6077
  const existing = await store.getCaseById(tenantId, cid);
@@ -5638,7 +6103,7 @@ function registerEvalRoutes(app2) {
5638
6103
  app2.delete("/api/eval/projects/:pid/suites/:sid/cases/:cid", deleteCase);
5639
6104
  app2.post("/api/eval/projects/:pid/runs", async (request, reply) => {
5640
6105
  try {
5641
- const tenantId = getTenantId12(request);
6106
+ const tenantId = getTenantId13(request);
5642
6107
  const { pid } = request.params;
5643
6108
  const runId = await evalRunner.startRun(tenantId, pid);
5644
6109
  reply.status(202).send({ success: true, message: "Run started", data: { run_id: runId } });
@@ -5650,7 +6115,7 @@ function registerEvalRoutes(app2) {
5650
6115
  });
5651
6116
  app2.get("/api/eval/runs", async (request, reply) => {
5652
6117
  try {
5653
- const tenantId = getTenantId12(request);
6118
+ const tenantId = getTenantId13(request);
5654
6119
  const query = request.query;
5655
6120
  const runs = await getEvalStore().getRunsByTenant(tenantId, { projectId: query.project_id, status: query.status });
5656
6121
  reply.send({ success: true, message: "Ok", data: { records: runs, total: runs.length } });
@@ -5660,7 +6125,7 @@ function registerEvalRoutes(app2) {
5660
6125
  });
5661
6126
  app2.get("/api/eval/runs/:rid", async (request, reply) => {
5662
6127
  try {
5663
- const tenantId = getTenantId12(request);
6128
+ const tenantId = getTenantId13(request);
5664
6129
  const { rid } = request.params;
5665
6130
  const run = await getEvalStore().getRunById(tenantId, rid);
5666
6131
  if (!run) return reply.status(404).send({ success: false, message: "Run not found" });
@@ -5682,7 +6147,7 @@ function registerEvalRoutes(app2) {
5682
6147
  const emitter = evalRunner.getEventEmitter();
5683
6148
  const eventKey = `run:${rid}`;
5684
6149
  if (!evalRunner.isRunning(rid)) {
5685
- const tenantId = getTenantId12(request);
6150
+ const tenantId = getTenantId13(request);
5686
6151
  const run = await getEvalStore().getRunById(tenantId, rid);
5687
6152
  if (run) {
5688
6153
  const eventType = run.status === "completed" ? "completed" : "error";
@@ -5721,7 +6186,7 @@ data: ${JSON.stringify(event.data)}
5721
6186
  });
5722
6187
  app2.delete("/api/eval/runs/:rid", async (request, reply) => {
5723
6188
  try {
5724
- const tenantId = getTenantId12(request);
6189
+ const tenantId = getTenantId13(request);
5725
6190
  const { rid } = request.params;
5726
6191
  const deleted = await getEvalStore().deleteRun(tenantId, rid);
5727
6192
  if (!deleted) return reply.status(404).send({ success: false, message: "Run not found" });
@@ -5732,7 +6197,7 @@ data: ${JSON.stringify(event.data)}
5732
6197
  });
5733
6198
  app2.get("/api/eval/reports/projects/:pid", async (request, reply) => {
5734
6199
  try {
5735
- const tenantId = getTenantId12(request);
6200
+ const tenantId = getTenantId13(request);
5736
6201
  const { pid } = request.params;
5737
6202
  const report = await getEvalStore().getProjectReport(tenantId, pid);
5738
6203
  if (!report) return reply.status(404).send({ success: false, message: "Project not found" });
@@ -6610,14 +7075,14 @@ function registerChannelRoutes(app2, dependencies) {
6610
7075
  }
6611
7076
 
6612
7077
  // src/controllers/channel-installations.ts
6613
- import { randomUUID as randomUUID6 } from "crypto";
7078
+ import { randomUUID as randomUUID7 } from "crypto";
6614
7079
  var _adapterRegistry;
6615
7080
  var _router;
6616
7081
  function setChannelControllerDeps(deps) {
6617
7082
  _adapterRegistry = deps.adapterRegistry;
6618
7083
  _router = deps.router;
6619
7084
  }
6620
- function getTenantId13(request) {
7085
+ function getTenantId14(request) {
6621
7086
  const userTenantId = request.user?.tenantId;
6622
7087
  if (userTenantId) {
6623
7088
  return userTenantId;
@@ -6625,8 +7090,8 @@ function getTenantId13(request) {
6625
7090
  return request.headers["x-tenant-id"] || "default";
6626
7091
  }
6627
7092
  async function getInstallationStore() {
6628
- const { getStoreLattice: getStoreLattice17 } = await import("@axiom-lattice/core");
6629
- const store = getStoreLattice17("default", "channelInstallation").store;
7093
+ const { getStoreLattice: getStoreLattice30 } = await import("@axiom-lattice/core");
7094
+ const store = getStoreLattice30("default", "channelInstallation").store;
6630
7095
  if (store) return store;
6631
7096
  const { PostgreSQLChannelInstallationStore } = await import("@axiom-lattice/pg-stores");
6632
7097
  const databaseUrl = process.env.DATABASE_URL;
@@ -6638,7 +7103,7 @@ async function getInstallationStore() {
6638
7103
  });
6639
7104
  }
6640
7105
  async function getChannelInstallationList(request, reply) {
6641
- const tenantId = getTenantId13(request);
7106
+ const tenantId = getTenantId14(request);
6642
7107
  const { channel } = request.query;
6643
7108
  try {
6644
7109
  const store = await getInstallationStore();
@@ -6664,7 +7129,7 @@ async function getChannelInstallationList(request, reply) {
6664
7129
  }
6665
7130
  }
6666
7131
  async function getChannelInstallation(request, reply) {
6667
- const tenantId = getTenantId13(request);
7132
+ const tenantId = getTenantId14(request);
6668
7133
  const { installationId } = request.params;
6669
7134
  try {
6670
7135
  const store = await getInstallationStore();
@@ -6697,7 +7162,7 @@ async function getChannelInstallation(request, reply) {
6697
7162
  }
6698
7163
  }
6699
7164
  async function createChannelInstallation(request, reply) {
6700
- const tenantId = getTenantId13(request);
7165
+ const tenantId = getTenantId14(request);
6701
7166
  const body = request.body;
6702
7167
  try {
6703
7168
  if (!body.channel) {
@@ -6732,7 +7197,7 @@ async function createChannelInstallation(request, reply) {
6732
7197
  }
6733
7198
  }
6734
7199
  const store = await getInstallationStore();
6735
- const installationId = body.id || randomUUID6();
7200
+ const installationId = body.id || randomUUID7();
6736
7201
  const installation = await store.createInstallation(
6737
7202
  tenantId,
6738
7203
  installationId,
@@ -6770,7 +7235,7 @@ async function createChannelInstallation(request, reply) {
6770
7235
  }
6771
7236
  }
6772
7237
  async function updateChannelInstallation(request, reply) {
6773
- const tenantId = getTenantId13(request);
7238
+ const tenantId = getTenantId14(request);
6774
7239
  const { installationId } = request.params;
6775
7240
  const body = request.body;
6776
7241
  try {
@@ -6824,7 +7289,7 @@ async function updateChannelInstallation(request, reply) {
6824
7289
  }
6825
7290
  }
6826
7291
  async function deleteChannelInstallation(request, reply) {
6827
- const tenantId = getTenantId13(request);
7292
+ const tenantId = getTenantId14(request);
6828
7293
  const { installationId } = request.params;
6829
7294
  try {
6830
7295
  const store = await getInstallationStore();
@@ -6885,13 +7350,13 @@ function registerChannelInstallationRoutes(app2) {
6885
7350
 
6886
7351
  // src/controllers/channel-bindings.ts
6887
7352
  import { getBindingRegistry } from "@axiom-lattice/core";
6888
- function getTenantId14(request) {
7353
+ function getTenantId15(request) {
6889
7354
  const userTenantId = request.user?.tenantId;
6890
7355
  if (userTenantId) return userTenantId;
6891
7356
  return request.headers["x-tenant-id"] || "default";
6892
7357
  }
6893
7358
  async function getBindingList(request, _reply) {
6894
- const tenantId = getTenantId14(request);
7359
+ const tenantId = getTenantId15(request);
6895
7360
  const { channel, agentId, channelInstallationId, limit, offset } = request.query;
6896
7361
  try {
6897
7362
  const registry = getBindingRegistry();
@@ -6903,7 +7368,7 @@ async function getBindingList(request, _reply) {
6903
7368
  }
6904
7369
  }
6905
7370
  async function getBinding(request, reply) {
6906
- const tenantId = getTenantId14(request);
7371
+ const tenantId = getTenantId15(request);
6907
7372
  try {
6908
7373
  const registry = getBindingRegistry();
6909
7374
  const bindings = await registry.list({ tenantId });
@@ -6919,7 +7384,7 @@ async function getBinding(request, reply) {
6919
7384
  }
6920
7385
  }
6921
7386
  async function createBinding(request, reply) {
6922
- const tenantId = getTenantId14(request);
7387
+ const tenantId = getTenantId15(request);
6923
7388
  try {
6924
7389
  const registry = getBindingRegistry();
6925
7390
  const binding = await registry.create({ ...request.body, tenantId });
@@ -6933,7 +7398,7 @@ async function createBinding(request, reply) {
6933
7398
  }
6934
7399
  async function updateBinding(request, reply) {
6935
7400
  try {
6936
- const tenantId = getTenantId14(request);
7401
+ const tenantId = getTenantId15(request);
6937
7402
  const registry = getBindingRegistry();
6938
7403
  const bindings = await registry.list({ tenantId });
6939
7404
  const existing = bindings.find((b) => b.id === request.params.id);
@@ -6951,7 +7416,7 @@ async function updateBinding(request, reply) {
6951
7416
  }
6952
7417
  async function deleteBinding(request, reply) {
6953
7418
  try {
6954
- const tenantId = getTenantId14(request);
7419
+ const tenantId = getTenantId15(request);
6955
7420
  const registry = getBindingRegistry();
6956
7421
  const bindings = await registry.list({ tenantId });
6957
7422
  const existing = bindings.find((b) => b.id === request.params.id);
@@ -6968,7 +7433,7 @@ async function deleteBinding(request, reply) {
6968
7433
  }
6969
7434
  }
6970
7435
  async function resolveBinding(request, _reply) {
6971
- const tenantId = getTenantId14(request);
7436
+ const tenantId = getTenantId15(request);
6972
7437
  const { channel, senderId, channelInstallationId } = request.query;
6973
7438
  try {
6974
7439
  const registry = getBindingRegistry();
@@ -6995,7 +7460,7 @@ function registerChannelBindingRoutes(app2) {
6995
7460
 
6996
7461
  // src/controllers/menu-items.ts
6997
7462
  import { getMenuRegistry } from "@axiom-lattice/core";
6998
- function getTenantId15(request) {
7463
+ function getTenantId16(request) {
6999
7464
  const userTenantId = request.user?.tenantId;
7000
7465
  if (userTenantId) return userTenantId;
7001
7466
  return request.headers["x-tenant-id"] || "default";
@@ -7004,7 +7469,7 @@ function errorMessage(err) {
7004
7469
  return err instanceof Error ? err.message : "Unexpected error";
7005
7470
  }
7006
7471
  async function getMenuItemList(request, _reply) {
7007
- const tenantId = getTenantId15(request);
7472
+ const tenantId = getTenantId16(request);
7008
7473
  try {
7009
7474
  const registry = getMenuRegistry();
7010
7475
  const items = await registry.list({ tenantId, menuTarget: request.query.menuTarget });
@@ -7016,7 +7481,7 @@ async function getMenuItemList(request, _reply) {
7016
7481
  }
7017
7482
  }
7018
7483
  async function getMenuItem(request, reply) {
7019
- const tenantId = getTenantId15(request);
7484
+ const tenantId = getTenantId16(request);
7020
7485
  try {
7021
7486
  const registry = getMenuRegistry();
7022
7487
  const item = await registry.getById(request.params.id);
@@ -7033,7 +7498,7 @@ async function getMenuItem(request, reply) {
7033
7498
  }
7034
7499
  }
7035
7500
  async function createMenuItem(request, reply) {
7036
- const tenantId = getTenantId15(request);
7501
+ const tenantId = getTenantId16(request);
7037
7502
  try {
7038
7503
  const registry = getMenuRegistry();
7039
7504
  const item = await registry.create({ ...request.body, tenantId });
@@ -7048,7 +7513,7 @@ async function createMenuItem(request, reply) {
7048
7513
  }
7049
7514
  async function updateMenuItem(request, reply) {
7050
7515
  try {
7051
- const tenantId = getTenantId15(request);
7516
+ const tenantId = getTenantId16(request);
7052
7517
  const registry = getMenuRegistry();
7053
7518
  const existing = await registry.getById(request.params.id);
7054
7519
  if (!existing || existing.tenantId !== tenantId) {
@@ -7066,7 +7531,7 @@ async function updateMenuItem(request, reply) {
7066
7531
  }
7067
7532
  async function deleteMenuItem(request, reply) {
7068
7533
  try {
7069
- const tenantId = getTenantId15(request);
7534
+ const tenantId = getTenantId16(request);
7070
7535
  const registry = getMenuRegistry();
7071
7536
  const existing = await registry.getById(request.params.id);
7072
7537
  if (!existing || existing.tenantId !== tenantId) {
@@ -7499,12 +7964,38 @@ var registerLatticeRoutes = (app2, channelDeps) => {
7499
7964
  app2.delete("/api/workflows/runs/:runId", deleteWorkflowRun);
7500
7965
  app2.get("/api/workflows/runs/:runId/steps", getRunSteps);
7501
7966
  app2.get("/api/workflows/runs/:runId/tasks", getRunTasks);
7967
+ app2.post("/api/workflows/runs/:runId/abort", abortWorkflowRun);
7502
7968
  app2.post("/api/workflows/inbox/reply", replyInboxTask);
7503
7969
  app2.delete(
7504
7970
  "/api/assistants/:assistant_id/threads/:thread_id/pending-messages/:message_id",
7505
7971
  removePendingMessageHandler
7506
7972
  );
7507
- };
7973
+ app2.get("/api/tenants/exportable-types", getExportableTypes);
7974
+ app2.post(
7975
+ "/api/tenants/:tenantId/export",
7976
+ exportConfig
7977
+ );
7978
+ app2.post(
7979
+ "/api/tenants/:tenantId/export/confirm",
7980
+ exportConfigConfirm
7981
+ );
7982
+ app2.post(
7983
+ "/api/tenants/:tenantId/export/entities",
7984
+ previewEntities
7985
+ );
7986
+ app2.get(
7987
+ "/api/tenants/:tenantId/export/:jobId/download",
7988
+ downloadExport
7989
+ );
7990
+ app2.post(
7991
+ "/api/tenants/:tenantId/import/preview",
7992
+ importPreview
7993
+ );
7994
+ app2.post(
7995
+ "/api/tenants/:tenantId/import/apply",
7996
+ importApply
7997
+ );
7998
+ };
7508
7999
 
7509
8000
  // src/routes/resource-routes.ts
7510
8001
  function registerResourceRoutes(app2, controller) {
@@ -7532,12 +8023,1320 @@ function registerResourceRoutes(app2, controller) {
7532
8023
  app2.delete("/api/resources/share/:token", controller.revokeShare.bind(controller));
7533
8024
  }
7534
8025
 
8026
+ // src/export_registrations/index.ts
8027
+ import { ExportableEntityRegistry as ExportableEntityRegistry3 } from "@axiom-lattice/core";
8028
+
8029
+ // src/export_registrations/skill.registration.ts
8030
+ import { getStoreLattice as getStoreLattice15 } from "@axiom-lattice/core";
8031
+ function getStore2() {
8032
+ return getStoreLattice15("default", "skill").store;
8033
+ }
8034
+ var skillRegistration = {
8035
+ entityType: "skill",
8036
+ label: "Skill(\u6280\u80FD)",
8037
+ category: "core",
8038
+ dependsOn: [],
8039
+ cascadeParents: [],
8040
+ async listForExport(tenantId) {
8041
+ const store = getStore2();
8042
+ const skills = await store.getAllSkills(tenantId);
8043
+ return skills.map((s) => ({
8044
+ _exportId: "",
8045
+ data: {
8046
+ id: s.id,
8047
+ name: s.name,
8048
+ description: s.description,
8049
+ license: s.license,
8050
+ compatibility: s.compatibility,
8051
+ metadata: s.metadata,
8052
+ content: s.content,
8053
+ subSkills: s.subSkills
8054
+ }
8055
+ }));
8056
+ },
8057
+ async previewImport(tenantId, entities) {
8058
+ const store = getStore2();
8059
+ const existing = await store.getAllSkills(tenantId);
8060
+ const existingIds = new Set(existing.map((s) => s.id));
8061
+ const conflicts = [];
8062
+ const insertions = [];
8063
+ for (const entity of entities) {
8064
+ const id = entity.data.id;
8065
+ if (existingIds.has(id)) {
8066
+ conflicts.push({
8067
+ _exportId: entity._exportId,
8068
+ entityType: "skill",
8069
+ conflictType: "id_exists",
8070
+ existingId: id,
8071
+ existingName: entity.data.name || id
8072
+ });
8073
+ } else {
8074
+ insertions.push({
8075
+ _exportId: entity._exportId,
8076
+ entityType: "skill",
8077
+ name: entity.data.name || id
8078
+ });
8079
+ }
8080
+ }
8081
+ return { conflicts, insertions, errors: [] };
8082
+ },
8083
+ async applyImport(tenantId, entity, resolution) {
8084
+ const store = getStore2();
8085
+ const data = entity.data;
8086
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8087
+ if (resolution.action === "overwrite") {
8088
+ try {
8089
+ await store.deleteSkill(tenantId, id);
8090
+ } catch {
8091
+ }
8092
+ }
8093
+ await store.createSkill(tenantId, id, {
8094
+ name: data.name,
8095
+ description: data.description,
8096
+ license: data.license,
8097
+ compatibility: data.compatibility,
8098
+ metadata: data.metadata,
8099
+ content: data.content,
8100
+ subSkills: data.subSkills
8101
+ });
8102
+ return { newId: id };
8103
+ }
8104
+ };
8105
+
8106
+ // src/export_registrations/agent.registration.ts
8107
+ import { getStoreLattice as getStoreLattice16 } from "@axiom-lattice/core";
8108
+ function getStore3() {
8109
+ return getStoreLattice16("default", "assistant").store;
8110
+ }
8111
+ var agentRegistration = {
8112
+ entityType: "agent",
8113
+ label: "Agent(\u667A\u80FD\u4F53)",
8114
+ category: "core",
8115
+ dependsOn: ["skill"],
8116
+ cascadeParents: [],
8117
+ async listForExport(tenantId) {
8118
+ const store = getStore3();
8119
+ const agents = await store.getAllAssistants(tenantId);
8120
+ return agents.map((a) => ({
8121
+ _exportId: "",
8122
+ data: {
8123
+ id: a.id,
8124
+ name: a.name,
8125
+ description: a.description,
8126
+ graphDefinition: a.graphDefinition
8127
+ }
8128
+ }));
8129
+ },
8130
+ async previewImport(tenantId, entities) {
8131
+ const store = getStore3();
8132
+ const existing = await store.getAllAssistants(tenantId);
8133
+ const existingIds = new Set(existing.map((a) => a.id));
8134
+ const conflicts = [];
8135
+ const insertions = [];
8136
+ for (const entity of entities) {
8137
+ const id = entity.data.id;
8138
+ if (existingIds.has(id)) {
8139
+ conflicts.push({
8140
+ _exportId: entity._exportId,
8141
+ entityType: "agent",
8142
+ conflictType: "id_exists",
8143
+ existingId: id,
8144
+ existingName: entity.data.name || id
8145
+ });
8146
+ } else {
8147
+ insertions.push({
8148
+ _exportId: entity._exportId,
8149
+ entityType: "agent",
8150
+ name: entity.data.name || id
8151
+ });
8152
+ }
8153
+ }
8154
+ return { conflicts, insertions, errors: [] };
8155
+ },
8156
+ async applyImport(tenantId, entity, resolution) {
8157
+ const store = getStore3();
8158
+ const data = entity.data;
8159
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8160
+ if (resolution.action === "overwrite") {
8161
+ try {
8162
+ await store.deleteAssistant(tenantId, id);
8163
+ } catch {
8164
+ }
8165
+ }
8166
+ await store.createAssistant(tenantId, id, {
8167
+ name: data.name,
8168
+ description: data.description || "",
8169
+ graphDefinition: data.graphDefinition
8170
+ });
8171
+ return { newId: id };
8172
+ }
8173
+ };
8174
+
8175
+ // src/export_registrations/binding.registration.ts
8176
+ import { getStoreLattice as getStoreLattice17 } from "@axiom-lattice/core";
8177
+ function getStore4() {
8178
+ return getStoreLattice17("default", "channelBinding").store;
8179
+ }
8180
+ var bindingRegistration = {
8181
+ entityType: "binding",
8182
+ label: "Binding(\u6E20\u9053\u7ED1\u5B9A)",
8183
+ category: "core",
8184
+ dependsOn: ["agent", "channel_installation"],
8185
+ cascadeParents: [],
8186
+ referenceFields: { agentId: "agent", channelInstallationId: "channel_installation" },
8187
+ async listForExport(tenantId) {
8188
+ const store = getStore4();
8189
+ const bindings = await store.list({ tenantId, limit: 1e4, offset: 0 });
8190
+ return bindings.map((b) => ({
8191
+ _exportId: "",
8192
+ data: {
8193
+ channel: b.channel,
8194
+ channelInstallationId: b.channelInstallationId,
8195
+ senderId: b.senderId,
8196
+ agentId: b.agentId,
8197
+ threadId: b.threadId,
8198
+ workspaceId: b.workspaceId,
8199
+ projectId: b.projectId,
8200
+ threadMode: b.threadMode,
8201
+ senderDisplayName: b.senderDisplayName,
8202
+ senderMetadata: b.senderMetadata,
8203
+ enabled: b.enabled
8204
+ }
8205
+ }));
8206
+ },
8207
+ async previewImport(tenantId, entities) {
8208
+ const store = getStore4();
8209
+ const existing = await store.list({ tenantId, limit: 1e4, offset: 0 });
8210
+ const existingKeys = new Set(
8211
+ existing.map((b) => `${b.channel}:${b.channelInstallationId}:${b.senderId}`)
8212
+ );
8213
+ const conflicts = [];
8214
+ const insertions = [];
8215
+ for (const entity of entities) {
8216
+ const d = entity.data;
8217
+ const key = `${d.channel}:${d.channelInstallationId}:${d.senderId}`;
8218
+ if (existingKeys.has(key)) {
8219
+ conflicts.push({
8220
+ _exportId: entity._exportId,
8221
+ entityType: "binding",
8222
+ conflictType: "unique_constraint",
8223
+ existingName: `${d.channel}:${d.senderId}`,
8224
+ field: "channel+channelInstallationId+senderId"
8225
+ });
8226
+ } else {
8227
+ insertions.push({
8228
+ _exportId: entity._exportId,
8229
+ entityType: "binding",
8230
+ name: `${d.channel}:${d.senderId}`
8231
+ });
8232
+ }
8233
+ }
8234
+ return { conflicts, insertions, errors: [] };
8235
+ },
8236
+ async applyImport(tenantId, entity, resolution) {
8237
+ if (resolution.action === "skip") return {};
8238
+ const store = getStore4();
8239
+ const d = entity.data;
8240
+ if (resolution.action === "overwrite") {
8241
+ const existing = await store.list({ tenantId, limit: 1e4, offset: 0 });
8242
+ const match = existing.find(
8243
+ (b) => b.channel === d.channel && b.channelInstallationId === d.channelInstallationId && b.senderId === d.senderId
8244
+ );
8245
+ if (match) {
8246
+ await store.delete(match.id);
8247
+ }
8248
+ }
8249
+ await store.create({
8250
+ channel: d.channel,
8251
+ channelInstallationId: d.channelInstallationId,
8252
+ tenantId,
8253
+ senderId: d.senderId,
8254
+ agentId: d.agentId,
8255
+ threadMode: d.threadMode || "fixed",
8256
+ senderDisplayName: d.senderDisplayName,
8257
+ senderMetadata: d.senderMetadata,
8258
+ workspaceId: d.workspaceId,
8259
+ projectId: d.projectId
8260
+ });
8261
+ return { newId: void 0 };
8262
+ }
8263
+ };
8264
+
8265
+ // src/export_registrations/database-config.registration.ts
8266
+ import { getStoreLattice as getStoreLattice18 } from "@axiom-lattice/core";
8267
+ function getStore5() {
8268
+ return getStoreLattice18("default", "database").store;
8269
+ }
8270
+ var databaseConfigRegistration = {
8271
+ entityType: "database_config",
8272
+ label: "Database Config(\u6570\u636E\u5E93\u914D\u7F6E)",
8273
+ category: "core",
8274
+ dependsOn: [],
8275
+ cascadeParents: [],
8276
+ async listForExport(tenantId) {
8277
+ const store = getStore5();
8278
+ const configs = await store.getAllConfigs(tenantId);
8279
+ return configs.map((c) => ({
8280
+ _exportId: "",
8281
+ data: {
8282
+ id: c.id,
8283
+ key: c.key,
8284
+ name: c.name,
8285
+ description: c.description,
8286
+ config: c.config
8287
+ }
8288
+ }));
8289
+ },
8290
+ async previewImport(tenantId, entities) {
8291
+ const store = getStore5();
8292
+ const existing = await store.getAllConfigs(tenantId);
8293
+ const existingIds = new Set(existing.map((c) => c.id));
8294
+ const existingKeys = new Set(existing.map((c) => c.key));
8295
+ const conflicts = [];
8296
+ const insertions = [];
8297
+ for (const entity of entities) {
8298
+ const d = entity.data;
8299
+ const id = d.id;
8300
+ const key = d.key;
8301
+ if (existingIds.has(id)) {
8302
+ conflicts.push({
8303
+ _exportId: entity._exportId,
8304
+ entityType: "database_config",
8305
+ conflictType: "id_exists",
8306
+ existingId: id,
8307
+ existingName: d.name || key
8308
+ });
8309
+ } else if (key && existingKeys.has(key)) {
8310
+ conflicts.push({
8311
+ _exportId: entity._exportId,
8312
+ entityType: "database_config",
8313
+ conflictType: "unique_constraint",
8314
+ existingName: d.name || key,
8315
+ field: "key"
8316
+ });
8317
+ } else {
8318
+ insertions.push({
8319
+ _exportId: entity._exportId,
8320
+ entityType: "database_config",
8321
+ name: d.name || key
8322
+ });
8323
+ }
8324
+ }
8325
+ return { conflicts, insertions, errors: [] };
8326
+ },
8327
+ async applyImport(tenantId, entity, resolution) {
8328
+ const store = getStore5();
8329
+ const data = entity.data;
8330
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8331
+ if (resolution.action === "overwrite") {
8332
+ try {
8333
+ await store.deleteConfig(tenantId, id);
8334
+ } catch {
8335
+ }
8336
+ }
8337
+ await store.createConfig(tenantId, id, {
8338
+ key: data.key,
8339
+ name: data.name,
8340
+ description: data.description,
8341
+ config: data.config
8342
+ });
8343
+ return { newId: id };
8344
+ }
8345
+ };
8346
+
8347
+ // src/export_registrations/metrics-config.registration.ts
8348
+ import { getStoreLattice as getStoreLattice19 } from "@axiom-lattice/core";
8349
+ function getStore6() {
8350
+ return getStoreLattice19("default", "metrics").store;
8351
+ }
8352
+ var metricsConfigRegistration = {
8353
+ entityType: "metrics_config",
8354
+ label: "Metrics Config(\u6307\u6807\u914D\u7F6E)",
8355
+ category: "core",
8356
+ dependsOn: [],
8357
+ cascadeParents: [],
8358
+ async listForExport(tenantId) {
8359
+ const store = getStore6();
8360
+ const configs = await store.getAllConfigs(tenantId);
8361
+ return configs.map((c) => ({
8362
+ _exportId: "",
8363
+ data: {
8364
+ id: c.id,
8365
+ key: c.key,
8366
+ name: c.name,
8367
+ description: c.description,
8368
+ config: c.config
8369
+ }
8370
+ }));
8371
+ },
8372
+ async previewImport(tenantId, entities) {
8373
+ const store = getStore6();
8374
+ const existing = await store.getAllConfigs(tenantId);
8375
+ const existingIds = new Set(existing.map((c) => c.id));
8376
+ const existingKeys = new Set(existing.map((c) => c.key));
8377
+ const conflicts = [];
8378
+ const insertions = [];
8379
+ for (const entity of entities) {
8380
+ const d = entity.data;
8381
+ const id = d.id;
8382
+ const key = d.key;
8383
+ if (existingIds.has(id)) {
8384
+ conflicts.push({
8385
+ _exportId: entity._exportId,
8386
+ entityType: "metrics_config",
8387
+ conflictType: "id_exists",
8388
+ existingId: id,
8389
+ existingName: d.name || key
8390
+ });
8391
+ } else if (key && existingKeys.has(key)) {
8392
+ conflicts.push({
8393
+ _exportId: entity._exportId,
8394
+ entityType: "metrics_config",
8395
+ conflictType: "unique_constraint",
8396
+ existingName: d.name || key,
8397
+ field: "key"
8398
+ });
8399
+ } else {
8400
+ insertions.push({
8401
+ _exportId: entity._exportId,
8402
+ entityType: "metrics_config",
8403
+ name: d.name || key
8404
+ });
8405
+ }
8406
+ }
8407
+ return { conflicts, insertions, errors: [] };
8408
+ },
8409
+ async applyImport(tenantId, entity, resolution) {
8410
+ const store = getStore6();
8411
+ const data = entity.data;
8412
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8413
+ if (resolution.action === "overwrite") {
8414
+ try {
8415
+ await store.deleteConfig(tenantId, id);
8416
+ } catch {
8417
+ }
8418
+ }
8419
+ await store.createConfig(tenantId, id, {
8420
+ key: data.key,
8421
+ name: data.name,
8422
+ description: data.description,
8423
+ config: data.config
8424
+ });
8425
+ return { newId: id };
8426
+ }
8427
+ };
8428
+
8429
+ // src/export_registrations/mcp-config.registration.ts
8430
+ import { getStoreLattice as getStoreLattice20 } from "@axiom-lattice/core";
8431
+ function getStore7() {
8432
+ return getStoreLattice20("default", "mcp").store;
8433
+ }
8434
+ var mcpConfigRegistration = {
8435
+ entityType: "mcp_config",
8436
+ label: "MCP Config(MCP\u914D\u7F6E)",
8437
+ category: "core",
8438
+ dependsOn: [],
8439
+ cascadeParents: [],
8440
+ async listForExport(tenantId) {
8441
+ const store = getStore7();
8442
+ const configs = await store.getAllConfigs(tenantId);
8443
+ return configs.map((c) => ({
8444
+ _exportId: "",
8445
+ data: {
8446
+ id: c.id,
8447
+ key: c.key,
8448
+ name: c.name,
8449
+ description: c.description,
8450
+ config: c.config,
8451
+ selectedTools: c.selectedTools,
8452
+ status: c.status
8453
+ }
8454
+ }));
8455
+ },
8456
+ async previewImport(tenantId, entities) {
8457
+ const store = getStore7();
8458
+ const existing = await store.getAllConfigs(tenantId);
8459
+ const existingIds = new Set(existing.map((c) => c.id));
8460
+ const existingKeys = new Set(existing.map((c) => c.key));
8461
+ const conflicts = [];
8462
+ const insertions = [];
8463
+ for (const entity of entities) {
8464
+ const d = entity.data;
8465
+ const id = d.id;
8466
+ const key = d.key;
8467
+ if (existingIds.has(id)) {
8468
+ conflicts.push({
8469
+ _exportId: entity._exportId,
8470
+ entityType: "mcp_config",
8471
+ conflictType: "id_exists",
8472
+ existingId: id,
8473
+ existingName: d.name || key
8474
+ });
8475
+ } else if (key && existingKeys.has(key)) {
8476
+ conflicts.push({
8477
+ _exportId: entity._exportId,
8478
+ entityType: "mcp_config",
8479
+ conflictType: "unique_constraint",
8480
+ existingName: d.name || key,
8481
+ field: "key"
8482
+ });
8483
+ } else {
8484
+ insertions.push({
8485
+ _exportId: entity._exportId,
8486
+ entityType: "mcp_config",
8487
+ name: d.name || key
8488
+ });
8489
+ }
8490
+ }
8491
+ return { conflicts, insertions, errors: [] };
8492
+ },
8493
+ async applyImport(tenantId, entity, resolution) {
8494
+ const store = getStore7();
8495
+ const data = entity.data;
8496
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8497
+ if (resolution.action === "overwrite") {
8498
+ try {
8499
+ await store.deleteConfig(tenantId, id);
8500
+ } catch {
8501
+ }
8502
+ }
8503
+ await store.createConfig(tenantId, id, {
8504
+ key: data.key,
8505
+ name: data.name,
8506
+ description: data.description,
8507
+ config: data.config,
8508
+ selectedTools: data.selectedTools
8509
+ });
8510
+ return { newId: id };
8511
+ }
8512
+ };
8513
+
8514
+ // src/export_registrations/connection.registration.ts
8515
+ import { getStoreLattice as getStoreLattice21 } from "@axiom-lattice/core";
8516
+ function getStore8() {
8517
+ return getStoreLattice21("default", "connection").store;
8518
+ }
8519
+ async function listAllConnections(tenantId) {
8520
+ const store = getStore8();
8521
+ if (typeof store.listByTenant !== "function") {
8522
+ throw new Error("ConnectionStore.listByTenant is not implemented. SQL bypass removed \u2014 upgrade your store adapter.");
8523
+ }
8524
+ return store.listByTenant(tenantId);
8525
+ }
8526
+ var connectionRegistration = {
8527
+ entityType: "connection",
8528
+ label: "Connection(\u8FDE\u63A5)",
8529
+ category: "core",
8530
+ dependsOn: [],
8531
+ cascadeParents: [],
8532
+ async listForExport(tenantId) {
8533
+ const connections2 = await listAllConnections(tenantId);
8534
+ return connections2.map((c) => ({
8535
+ _exportId: "",
8536
+ data: {
8537
+ id: c.id,
8538
+ type: c.type,
8539
+ key: c.key,
8540
+ name: c.name,
8541
+ description: c.description,
8542
+ config: c.config
8543
+ }
8544
+ }));
8545
+ },
8546
+ async previewImport(tenantId, entities) {
8547
+ const existing = await listAllConnections(tenantId);
8548
+ const existingCompositeKeys = new Set(
8549
+ existing.map((c) => `${c.type}:${c.key}`)
8550
+ );
8551
+ const conflicts = [];
8552
+ const insertions = [];
8553
+ for (const entity of entities) {
8554
+ const d = entity.data;
8555
+ const compositeKey = `${d.type}:${d.key}`;
8556
+ if (existingCompositeKeys.has(compositeKey)) {
8557
+ conflicts.push({
8558
+ _exportId: entity._exportId,
8559
+ entityType: "connection",
8560
+ conflictType: "unique_constraint",
8561
+ existingName: `${d.type}:${d.key}`,
8562
+ field: "type+key"
8563
+ });
8564
+ } else {
8565
+ insertions.push({
8566
+ _exportId: entity._exportId,
8567
+ entityType: "connection",
8568
+ name: `${d.type}:${d.key}`
8569
+ });
8570
+ }
8571
+ }
8572
+ return { conflicts, insertions, errors: [] };
8573
+ },
8574
+ async applyImport(tenantId, entity, resolution) {
8575
+ if (resolution.action === "skip") return {};
8576
+ const store = getStore8();
8577
+ const d = entity.data;
8578
+ const type = d.type;
8579
+ const key = d.key;
8580
+ if (resolution.action === "overwrite") {
8581
+ try {
8582
+ await store.delete(tenantId, type, key);
8583
+ } catch {
8584
+ }
8585
+ }
8586
+ await store.create({
8587
+ tenantId,
8588
+ type,
8589
+ key,
8590
+ name: d.name,
8591
+ description: d.description,
8592
+ config: d.config
8593
+ });
8594
+ return { newId: void 0 };
8595
+ }
8596
+ };
8597
+
8598
+ // src/export_registrations/collection.registration.ts
8599
+ import { getStoreLattice as getStoreLattice22 } from "@axiom-lattice/core";
8600
+ function getStore9() {
8601
+ return getStoreLattice22("default", "collection").store;
8602
+ }
8603
+ var collectionRegistration = {
8604
+ entityType: "collection",
8605
+ label: "Collection(\u77E5\u8BC6\u5E93)",
8606
+ category: "core",
8607
+ dependsOn: [],
8608
+ cascadeParents: [],
8609
+ async listForExport(tenantId) {
8610
+ const store = getStore9();
8611
+ const collections = await store.getAllCollections(tenantId);
8612
+ return collections.map((c) => ({
8613
+ _exportId: "",
8614
+ data: {
8615
+ id: c.id,
8616
+ name: c.name,
8617
+ label: c.label,
8618
+ embeddingKey: c.embeddingKey,
8619
+ schema: c.schema
8620
+ }
8621
+ }));
8622
+ },
8623
+ async previewImport(tenantId, entities) {
8624
+ const store = getStore9();
8625
+ const existing = await store.getAllCollections(tenantId);
8626
+ const existingNames = new Set(existing.map((c) => c.name));
8627
+ const conflicts = [];
8628
+ const insertions = [];
8629
+ for (const entity of entities) {
8630
+ const d = entity.data;
8631
+ const name = d.name;
8632
+ if (existingNames.has(name)) {
8633
+ conflicts.push({
8634
+ _exportId: entity._exportId,
8635
+ entityType: "collection",
8636
+ conflictType: "unique_constraint",
8637
+ existingName: name,
8638
+ field: "name"
8639
+ });
8640
+ } else {
8641
+ insertions.push({
8642
+ _exportId: entity._exportId,
8643
+ entityType: "collection",
8644
+ name
8645
+ });
8646
+ }
8647
+ }
8648
+ return { conflicts, insertions, errors: [] };
8649
+ },
8650
+ async applyImport(tenantId, entity, resolution) {
8651
+ if (resolution.action === "skip") return {};
8652
+ const store = getStore9();
8653
+ const d = entity.data;
8654
+ const name = d.name;
8655
+ if (resolution.action === "overwrite") {
8656
+ try {
8657
+ await store.deleteCollection(tenantId, name);
8658
+ } catch {
8659
+ }
8660
+ }
8661
+ await store.createCollection(tenantId, {
8662
+ name,
8663
+ label: d.label,
8664
+ embeddingKey: d.embeddingKey,
8665
+ schema: d.schema
8666
+ });
8667
+ return { newId: void 0 };
8668
+ }
8669
+ };
8670
+
8671
+ // src/export_registrations/channel-installation.registration.ts
8672
+ import { getStoreLattice as getStoreLattice23 } from "@axiom-lattice/core";
8673
+ function getStore10() {
8674
+ return getStoreLattice23("default", "channelInstallation").store;
8675
+ }
8676
+ var channelInstallationRegistration = {
8677
+ entityType: "channel_installation",
8678
+ label: "Channel Installation(\u6E20\u9053\u5B89\u88C5)",
8679
+ category: "core",
8680
+ dependsOn: ["agent"],
8681
+ cascadeParents: [],
8682
+ referenceFields: { fallbackAgentId: "agent" },
8683
+ async listForExport(tenantId) {
8684
+ const store = getStore10();
8685
+ const installations = await store.getInstallationsByTenant(tenantId);
8686
+ return installations.map((i) => ({
8687
+ _exportId: "",
8688
+ data: {
8689
+ id: i.id,
8690
+ channel: i.channel,
8691
+ name: i.name,
8692
+ config: i.config,
8693
+ enabled: i.enabled,
8694
+ fallbackAgentId: i.fallbackAgentId,
8695
+ rejectWhenNoBinding: i.rejectWhenNoBinding
8696
+ }
8697
+ }));
8698
+ },
8699
+ async previewImport(tenantId, entities) {
8700
+ const store = getStore10();
8701
+ const existing = await store.getInstallationsByTenant(tenantId);
8702
+ const existingIds = new Set(existing.map((i) => i.id));
8703
+ const conflicts = [];
8704
+ const insertions = [];
8705
+ for (const entity of entities) {
8706
+ const d = entity.data;
8707
+ const id = d.id;
8708
+ if (existingIds.has(id)) {
8709
+ conflicts.push({
8710
+ _exportId: entity._exportId,
8711
+ entityType: "channel_installation",
8712
+ conflictType: "id_exists",
8713
+ existingId: id,
8714
+ existingName: d.name || id
8715
+ });
8716
+ } else {
8717
+ insertions.push({
8718
+ _exportId: entity._exportId,
8719
+ entityType: "channel_installation",
8720
+ name: d.name || id
8721
+ });
8722
+ }
8723
+ }
8724
+ return { conflicts, insertions, errors: [] };
8725
+ },
8726
+ async applyImport(tenantId, entity, resolution) {
8727
+ const store = getStore10();
8728
+ const data = entity.data;
8729
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8730
+ if (resolution.action === "overwrite") {
8731
+ try {
8732
+ await store.deleteInstallation(tenantId, id);
8733
+ } catch {
8734
+ }
8735
+ }
8736
+ await store.createInstallation(tenantId, id, {
8737
+ channel: data.channel,
8738
+ name: data.name,
8739
+ config: data.config,
8740
+ enabled: data.enabled,
8741
+ fallbackAgentId: data.fallbackAgentId,
8742
+ rejectWhenNoBinding: data.rejectWhenNoBinding
8743
+ });
8744
+ return { newId: id };
8745
+ }
8746
+ };
8747
+
8748
+ // src/export_registrations/menu.registration.ts
8749
+ import { getStoreLattice as getStoreLattice24 } from "@axiom-lattice/core";
8750
+ function getStore11() {
8751
+ return getStoreLattice24("default", "menu").store;
8752
+ }
8753
+ var menuRegistration = {
8754
+ entityType: "menu",
8755
+ label: "Menu(\u83DC\u5355)",
8756
+ category: "core",
8757
+ dependsOn: ["agent"],
8758
+ cascadeParents: [],
8759
+ async listForExport(tenantId) {
8760
+ const store = getStore11();
8761
+ const menus = await store.list({ tenantId });
8762
+ return menus.map((m) => ({
8763
+ _exportId: "",
8764
+ data: {
8765
+ id: m.id,
8766
+ menuTarget: m.menuTarget,
8767
+ group: m.group,
8768
+ name: m.name,
8769
+ icon: m.icon,
8770
+ sortOrder: m.sortOrder,
8771
+ contentType: m.contentType,
8772
+ contentConfig: m.contentConfig,
8773
+ enabled: m.enabled
8774
+ }
8775
+ }));
8776
+ },
8777
+ async previewImport(tenantId, entities) {
8778
+ const store = getStore11();
8779
+ const existing = await store.list({ tenantId });
8780
+ const existingIds = new Set(existing.map((m) => m.id));
8781
+ const conflicts = [];
8782
+ const insertions = [];
8783
+ for (const entity of entities) {
8784
+ const d = entity.data;
8785
+ const id = d.id;
8786
+ if (existingIds.has(id)) {
8787
+ conflicts.push({
8788
+ _exportId: entity._exportId,
8789
+ entityType: "menu",
8790
+ conflictType: "id_exists",
8791
+ existingId: id,
8792
+ existingName: d.name || id
8793
+ });
8794
+ } else {
8795
+ insertions.push({
8796
+ _exportId: entity._exportId,
8797
+ entityType: "menu",
8798
+ name: d.name || id
8799
+ });
8800
+ }
8801
+ }
8802
+ return { conflicts, insertions, errors: [] };
8803
+ },
8804
+ async applyImport(tenantId, entity, resolution) {
8805
+ const store = getStore11();
8806
+ const d = entity.data;
8807
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : d.id;
8808
+ if (resolution.action === "overwrite") {
8809
+ try {
8810
+ await store.delete(id);
8811
+ } catch {
8812
+ }
8813
+ }
8814
+ await store.create({
8815
+ tenantId,
8816
+ menuTarget: d.menuTarget,
8817
+ group: d.group,
8818
+ name: d.name,
8819
+ icon: d.icon,
8820
+ sortOrder: d.sortOrder,
8821
+ contentType: d.contentType,
8822
+ contentConfig: d.contentConfig
8823
+ });
8824
+ return { newId: void 0 };
8825
+ }
8826
+ };
8827
+
8828
+ // src/export_registrations/task.registration.ts
8829
+ import { getStoreLattice as getStoreLattice25 } from "@axiom-lattice/core";
8830
+ function getStore12() {
8831
+ return getStoreLattice25("default", "task").store;
8832
+ }
8833
+ var taskRegistration = {
8834
+ entityType: "task",
8835
+ label: "Task(\u4EFB\u52A1)",
8836
+ category: "core",
8837
+ dependsOn: ["agent"],
8838
+ cascadeParents: [],
8839
+ referenceFields: { ownerId: "agent", parentId: "task" },
8840
+ async listForExport(tenantId) {
8841
+ const store = getStore12();
8842
+ const tasks = await store.list({ tenantId, limit: 1e4, offset: 0 });
8843
+ return tasks.map((t) => ({
8844
+ _exportId: "",
8845
+ data: {
8846
+ id: t.id,
8847
+ title: t.title,
8848
+ description: t.description,
8849
+ status: t.status,
8850
+ priority: t.priority,
8851
+ dueDate: t.dueDate,
8852
+ ownerType: t.ownerType,
8853
+ ownerId: t.ownerId,
8854
+ metadata: t.metadata,
8855
+ parentId: t.parentId,
8856
+ sourceId: t.sourceId,
8857
+ context: t.context
8858
+ }
8859
+ }));
8860
+ },
8861
+ async previewImport(tenantId, entities) {
8862
+ const store = getStore12();
8863
+ const existing = await store.list({ tenantId, limit: 1e4, offset: 0 });
8864
+ const existingIds = new Set(existing.map((t) => t.id));
8865
+ const conflicts = [];
8866
+ const insertions = [];
8867
+ for (const entity of entities) {
8868
+ const d = entity.data;
8869
+ const id = d.id;
8870
+ if (existingIds.has(id)) {
8871
+ conflicts.push({
8872
+ _exportId: entity._exportId,
8873
+ entityType: "task",
8874
+ conflictType: "id_exists",
8875
+ existingId: id,
8876
+ existingName: d.title || id
8877
+ });
8878
+ } else {
8879
+ insertions.push({
8880
+ _exportId: entity._exportId,
8881
+ entityType: "task",
8882
+ name: d.title || id
8883
+ });
8884
+ }
8885
+ }
8886
+ return { conflicts, insertions, errors: [] };
8887
+ },
8888
+ async applyImport(tenantId, entity, resolution) {
8889
+ const store = getStore12();
8890
+ const data = entity.data;
8891
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : data.id;
8892
+ if (resolution.action === "overwrite") {
8893
+ try {
8894
+ await store.delete(tenantId, id);
8895
+ } catch {
8896
+ }
8897
+ }
8898
+ await store.create({
8899
+ tenantId,
8900
+ ownerType: data.ownerType || "user",
8901
+ ownerId: data.ownerId || "",
8902
+ title: data.title,
8903
+ description: data.description,
8904
+ status: data.status,
8905
+ priority: data.priority,
8906
+ dueDate: data.dueDate,
8907
+ metadata: data.metadata,
8908
+ parentId: data.parentId,
8909
+ sourceId: data.sourceId,
8910
+ context: data.context
8911
+ });
8912
+ return { newId: id };
8913
+ }
8914
+ };
8915
+
8916
+ // src/export_registrations/a2a-api-key.registration.ts
8917
+ import { getStoreLattice as getStoreLattice26 } from "@axiom-lattice/core";
8918
+ function getStore13() {
8919
+ return getStoreLattice26("default", "a2aApiKey").store;
8920
+ }
8921
+ var a2aApiKeyRegistration = {
8922
+ entityType: "a2a_api_key",
8923
+ label: "A2A API Key(API\u5BC6\u94A5)",
8924
+ category: "core",
8925
+ dependsOn: [],
8926
+ cascadeParents: [],
8927
+ async listForExport(tenantId) {
8928
+ const store = getStore13();
8929
+ const keys = await store.list({ tenantId, limit: 1e4, offset: 0 });
8930
+ return keys.map((k) => ({
8931
+ _exportId: "",
8932
+ data: {
8933
+ id: k.id,
8934
+ tenantId: k.tenantId,
8935
+ projectId: k.projectId,
8936
+ workspaceId: k.workspaceId,
8937
+ label: k.label,
8938
+ enabled: k.enabled
8939
+ }
8940
+ }));
8941
+ },
8942
+ async previewImport(tenantId, entities) {
8943
+ const store = getStore13();
8944
+ const existing = await store.list({ tenantId, limit: 1e4, offset: 0 });
8945
+ const existingIds = new Set(existing.map((k) => k.id));
8946
+ const conflicts = [];
8947
+ const insertions = [];
8948
+ for (const entity of entities) {
8949
+ const d = entity.data;
8950
+ const id = d.id;
8951
+ if (existingIds.has(id)) {
8952
+ conflicts.push({
8953
+ _exportId: entity._exportId,
8954
+ entityType: "a2a_api_key",
8955
+ conflictType: "id_exists",
8956
+ existingId: id,
8957
+ existingName: d.label || id
8958
+ });
8959
+ } else {
8960
+ insertions.push({
8961
+ _exportId: entity._exportId,
8962
+ entityType: "a2a_api_key",
8963
+ name: d.label || id
8964
+ });
8965
+ }
8966
+ }
8967
+ return { conflicts, insertions, errors: [] };
8968
+ },
8969
+ async applyImport(tenantId, entity, resolution) {
8970
+ if (resolution.action === "skip") return {};
8971
+ const store = getStore13();
8972
+ const d = entity.data;
8973
+ if (resolution.action === "overwrite") {
8974
+ try {
8975
+ await store.delete(d.id);
8976
+ } catch {
8977
+ }
8978
+ }
8979
+ await store.create({
8980
+ tenantId,
8981
+ projectId: d.projectId,
8982
+ workspaceId: d.workspaceId,
8983
+ label: d.label
8984
+ });
8985
+ return { newId: void 0 };
8986
+ }
8987
+ };
8988
+
8989
+ // src/export_registrations/eval.registration.ts
8990
+ import { getStoreLattice as getStoreLattice27 } from "@axiom-lattice/core";
8991
+ function getStore14() {
8992
+ return getStoreLattice27("default", "eval").store;
8993
+ }
8994
+ var evalRegistration = {
8995
+ entityType: "eval",
8996
+ label: "Eval(\u8BC4\u4F30)",
8997
+ category: "core",
8998
+ dependsOn: [],
8999
+ cascadeParents: [],
9000
+ referenceFields: { suiteId: "eval_suite", projectId: "eval_project", runId: "eval_run", caseId: "eval_case" },
9001
+ async listForExport(tenantId) {
9002
+ const store = getStore14();
9003
+ const projects = await store.getProjectsByTenant(tenantId);
9004
+ const entities = [];
9005
+ for (const project of projects) {
9006
+ entities.push({
9007
+ _exportId: "",
9008
+ data: {
9009
+ _subType: "eval_project",
9010
+ id: project.id,
9011
+ name: project.name,
9012
+ description: project.description,
9013
+ version: project.version,
9014
+ judgeModelConfig: project.judgeModelConfig,
9015
+ targetServerConfig: project.targetServerConfig,
9016
+ concurrency: project.concurrency,
9017
+ reportConfig: project.reportConfig
9018
+ }
9019
+ });
9020
+ const suites = await store.getSuitesByProject(tenantId, project.id);
9021
+ for (const suite of suites) {
9022
+ entities.push({
9023
+ _exportId: "",
9024
+ data: {
9025
+ _subType: "eval_suite",
9026
+ id: suite.id,
9027
+ projectId: suite.projectId,
9028
+ name: suite.name
9029
+ }
9030
+ });
9031
+ const cases = await store.getCasesBySuite(tenantId, suite.id);
9032
+ for (const c of cases) {
9033
+ entities.push({
9034
+ _exportId: "",
9035
+ data: {
9036
+ _subType: "eval_case",
9037
+ id: c.id,
9038
+ suiteId: c.suiteId,
9039
+ inputMessage: c.inputMessage,
9040
+ inputFiles: c.inputFiles,
9041
+ steps: c.steps,
9042
+ outputType: c.outputType,
9043
+ contentAssertion: c.contentAssertion,
9044
+ rubrics: c.rubrics
9045
+ }
9046
+ });
9047
+ }
9048
+ }
9049
+ const runs = await store.getRunsByTenant(tenantId, { projectId: project.id });
9050
+ for (const run of runs) {
9051
+ entities.push({
9052
+ _exportId: "",
9053
+ data: {
9054
+ _subType: "eval_run",
9055
+ id: run.id,
9056
+ projectId: run.projectId,
9057
+ status: run.status,
9058
+ concurrency: run.concurrency,
9059
+ totalCases: run.totalCases,
9060
+ passedCases: run.passedCases,
9061
+ failedCases: run.failedCases,
9062
+ avgScore: run.avgScore,
9063
+ error: run.error
9064
+ }
9065
+ });
9066
+ const results = await store.getResultsByRun(tenantId, run.id);
9067
+ for (const result of results) {
9068
+ entities.push({
9069
+ _exportId: "",
9070
+ data: {
9071
+ _subType: "eval_run_result",
9072
+ id: result.id,
9073
+ runId: result.runId,
9074
+ suiteName: result.suiteName,
9075
+ caseId: result.caseId,
9076
+ pass: result.pass,
9077
+ score: result.score,
9078
+ summary: result.summary,
9079
+ dimensionResults: result.dimensionResults,
9080
+ durationMs: result.durationMs,
9081
+ messages: result.messages,
9082
+ logs: result.logs,
9083
+ error: result.error
9084
+ }
9085
+ });
9086
+ }
9087
+ }
9088
+ }
9089
+ return entities;
9090
+ },
9091
+ async previewImport(tenantId, entities) {
9092
+ const store = getStore14();
9093
+ const existingProjects = await store.getProjectsByTenant(tenantId);
9094
+ const existingProjectIds = new Set(existingProjects.map((p) => p.id));
9095
+ const existingProjectNames = new Set(existingProjects.map((p) => p.name));
9096
+ const existingSuites = /* @__PURE__ */ new Map();
9097
+ const existingSuiteIds = /* @__PURE__ */ new Set();
9098
+ const existingCaseIds = /* @__PURE__ */ new Set();
9099
+ const existingRunIds = /* @__PURE__ */ new Set();
9100
+ const existingResultIds = /* @__PURE__ */ new Set();
9101
+ for (const project of existingProjects) {
9102
+ const suites = await store.getSuitesByProject(tenantId, project.id);
9103
+ existingSuites.set(project.id, new Set(suites.map((s) => `${s.projectId}:${s.name}`)));
9104
+ for (const s of suites) {
9105
+ existingSuiteIds.add(s.id);
9106
+ try {
9107
+ const cases = await store.getCasesBySuite(tenantId, s.id);
9108
+ for (const c of cases) existingCaseIds.add(c.id);
9109
+ } catch {
9110
+ }
9111
+ }
9112
+ }
9113
+ for (const project of existingProjects) {
9114
+ const runs = await store.getRunsByTenant(tenantId, { projectId: project.id });
9115
+ for (const run of runs) {
9116
+ existingRunIds.add(run.id);
9117
+ try {
9118
+ const results = await store.getResultsByRun(tenantId, run.id);
9119
+ for (const r of results) existingResultIds.add(r.id);
9120
+ } catch {
9121
+ }
9122
+ }
9123
+ }
9124
+ const conflicts = [];
9125
+ const insertions = [];
9126
+ for (const entity of entities) {
9127
+ const d = entity.data;
9128
+ const subType = d._subType;
9129
+ const id = d.id;
9130
+ switch (subType) {
9131
+ case "eval_project": {
9132
+ const name = d.name;
9133
+ if (existingProjectIds.has(id)) {
9134
+ conflicts.push({
9135
+ _exportId: entity._exportId,
9136
+ entityType: "eval_project",
9137
+ conflictType: "id_exists",
9138
+ existingId: id,
9139
+ existingName: name
9140
+ });
9141
+ } else if (name && existingProjectNames.has(name)) {
9142
+ conflicts.push({
9143
+ _exportId: entity._exportId,
9144
+ entityType: "eval_project",
9145
+ conflictType: "unique_constraint",
9146
+ existingName: name,
9147
+ field: "name"
9148
+ });
9149
+ } else {
9150
+ insertions.push({ _exportId: entity._exportId, entityType: "eval_project", name });
9151
+ }
9152
+ break;
9153
+ }
9154
+ case "eval_suite": {
9155
+ const projectId = d.projectId;
9156
+ const name = d.name;
9157
+ const suiteKey = `${projectId}:${name}`;
9158
+ const projectSuites = existingSuites.get(projectId);
9159
+ if (existingSuiteIds.has(id)) {
9160
+ conflicts.push({
9161
+ _exportId: entity._exportId,
9162
+ entityType: "eval_suite",
9163
+ conflictType: "id_exists",
9164
+ existingId: id,
9165
+ existingName: name
9166
+ });
9167
+ } else if (projectSuites?.has(suiteKey)) {
9168
+ conflicts.push({
9169
+ _exportId: entity._exportId,
9170
+ entityType: "eval_suite",
9171
+ conflictType: "unique_constraint",
9172
+ existingName: name,
9173
+ field: "projectId+name"
9174
+ });
9175
+ } else {
9176
+ insertions.push({ _exportId: entity._exportId, entityType: "eval_suite", name });
9177
+ }
9178
+ break;
9179
+ }
9180
+ case "eval_case": {
9181
+ if (existingCaseIds.has(id)) {
9182
+ conflicts.push({
9183
+ _exportId: entity._exportId,
9184
+ entityType: "eval_case",
9185
+ conflictType: "id_exists",
9186
+ existingId: id
9187
+ });
9188
+ } else {
9189
+ insertions.push({ _exportId: entity._exportId, entityType: "eval_case", name: id });
9190
+ }
9191
+ break;
9192
+ }
9193
+ case "eval_run": {
9194
+ if (existingRunIds.has(id)) {
9195
+ conflicts.push({
9196
+ _exportId: entity._exportId,
9197
+ entityType: "eval_run",
9198
+ conflictType: "id_exists",
9199
+ existingId: id
9200
+ });
9201
+ } else {
9202
+ insertions.push({ _exportId: entity._exportId, entityType: "eval_run", name: id });
9203
+ }
9204
+ break;
9205
+ }
9206
+ case "eval_run_result": {
9207
+ if (existingResultIds.has(id)) {
9208
+ conflicts.push({
9209
+ _exportId: entity._exportId,
9210
+ entityType: "eval_run_result",
9211
+ conflictType: "id_exists",
9212
+ existingId: id
9213
+ });
9214
+ } else {
9215
+ insertions.push({ _exportId: entity._exportId, entityType: "eval_run_result", name: id });
9216
+ }
9217
+ break;
9218
+ }
9219
+ }
9220
+ }
9221
+ return { conflicts, insertions, errors: [] };
9222
+ },
9223
+ async applyImport(tenantId, entity, resolution) {
9224
+ if (resolution.action === "skip") return {};
9225
+ const store = getStore14();
9226
+ const d = entity.data;
9227
+ const subType = d._subType;
9228
+ const id = resolution.action === "rename" && resolution.newId ? resolution.newId : d.id;
9229
+ switch (subType) {
9230
+ case "eval_project": {
9231
+ if (resolution.action === "overwrite") {
9232
+ try {
9233
+ await store.deleteProject(tenantId, id);
9234
+ } catch {
9235
+ }
9236
+ }
9237
+ await store.createProject(tenantId, id, {
9238
+ name: d.name,
9239
+ description: d.description,
9240
+ version: d.version,
9241
+ judgeModelConfig: d.judgeModelConfig,
9242
+ targetServerConfig: d.targetServerConfig,
9243
+ concurrency: d.concurrency,
9244
+ reportConfig: d.reportConfig
9245
+ });
9246
+ break;
9247
+ }
9248
+ case "eval_suite": {
9249
+ if (resolution.action === "overwrite") {
9250
+ try {
9251
+ await store.deleteSuite(tenantId, id);
9252
+ } catch {
9253
+ }
9254
+ }
9255
+ await store.createSuite(tenantId, d.projectId, id, {
9256
+ name: d.name
9257
+ });
9258
+ break;
9259
+ }
9260
+ case "eval_case": {
9261
+ if (resolution.action === "overwrite") {
9262
+ try {
9263
+ await store.deleteCase(tenantId, id);
9264
+ } catch {
9265
+ }
9266
+ }
9267
+ await store.createCase(tenantId, d.suiteId, id, {
9268
+ inputMessage: d.inputMessage,
9269
+ inputFiles: d.inputFiles,
9270
+ steps: d.steps,
9271
+ outputType: d.outputType,
9272
+ contentAssertion: d.contentAssertion,
9273
+ rubrics: d.rubrics
9274
+ });
9275
+ break;
9276
+ }
9277
+ case "eval_run": {
9278
+ if (resolution.action === "overwrite") {
9279
+ try {
9280
+ await store.deleteRun(tenantId, id);
9281
+ } catch {
9282
+ }
9283
+ }
9284
+ await store.createRun(tenantId, d.projectId, id, {
9285
+ totalCases: d.totalCases,
9286
+ concurrency: d.concurrency
9287
+ });
9288
+ break;
9289
+ }
9290
+ case "eval_run_result": {
9291
+ if (resolution.action === "overwrite") {
9292
+ try {
9293
+ await store.deleteRunResult(tenantId, entity.data.id);
9294
+ } catch {
9295
+ }
9296
+ }
9297
+ await store.createRunResult(tenantId, d.runId, id, {
9298
+ suiteName: d.suiteName,
9299
+ caseId: d.caseId,
9300
+ pass: d.pass,
9301
+ score: d.score,
9302
+ summary: d.summary,
9303
+ dimensionResults: d.dimensionResults,
9304
+ durationMs: d.durationMs,
9305
+ messages: d.messages,
9306
+ logs: d.logs,
9307
+ error: d.error
9308
+ });
9309
+ break;
9310
+ }
9311
+ }
9312
+ return { newId: id };
9313
+ }
9314
+ };
9315
+
9316
+ // src/export_registrations/index.ts
9317
+ function registerAllBuiltinEntities() {
9318
+ const registry = ExportableEntityRegistry3.getInstance();
9319
+ registry.register(skillRegistration);
9320
+ registry.register(agentRegistration);
9321
+ registry.register(bindingRegistration);
9322
+ registry.register(databaseConfigRegistration);
9323
+ registry.register(metricsConfigRegistration);
9324
+ registry.register(mcpConfigRegistration);
9325
+ registry.register(connectionRegistration);
9326
+ registry.register(collectionRegistration);
9327
+ registry.register(channelInstallationRegistration);
9328
+ registry.register(menuRegistration);
9329
+ registry.register(taskRegistration);
9330
+ registry.register(a2aApiKeyRegistration);
9331
+ registry.register(evalRegistration);
9332
+ }
9333
+
7535
9334
  // src/router/MessageRouter.ts
7536
9335
  import {
7537
- getStoreLattice as getStoreLattice15,
9336
+ getStoreLattice as getStoreLattice28,
7538
9337
  agentInstanceManager as agentInstanceManager6
7539
9338
  } from "@axiom-lattice/core";
7540
- import { randomUUID as randomUUID7 } from "crypto";
9339
+ import { randomUUID as randomUUID8 } from "crypto";
7541
9340
  var BindingNotFoundError = class extends Error {
7542
9341
  constructor(message) {
7543
9342
  super(message);
@@ -7697,7 +9496,7 @@ var MessageRouter = class {
7697
9496
  channel: message.channel,
7698
9497
  adapterChannel: adapter.channel
7699
9498
  }, "Thread resolved by adapter strategy");
7700
- const threadStore = getStoreLattice15("default", "thread").store;
9499
+ const threadStore = getStoreLattice28("default", "thread").store;
7701
9500
  try {
7702
9501
  await threadStore.createThread(
7703
9502
  tenantId,
@@ -7734,8 +9533,8 @@ var MessageRouter = class {
7734
9533
  }
7735
9534
  }
7736
9535
  if (!threadId) {
7737
- const threadStore = getStoreLattice15("default", "thread").store;
7738
- const newThreadId = randomUUID7();
9536
+ const threadStore = getStoreLattice28("default", "thread").store;
9537
+ const newThreadId = randomUUID8();
7739
9538
  console.log({
7740
9539
  event: "dispatch:thread:create",
7741
9540
  agentId,
@@ -8018,7 +9817,7 @@ function createAuditLoggerMiddleware() {
8018
9817
  }
8019
9818
 
8020
9819
  // src/index.ts
8021
- import { setBindingRegistry, setMenuRegistry } from "@axiom-lattice/core";
9820
+ import { setBindingRegistry, setMenuRegistry, setEvalRunService } from "@axiom-lattice/core";
8022
9821
 
8023
9822
  // src/swagger.ts
8024
9823
  import swagger from "@fastify/swagger";
@@ -8340,7 +10139,7 @@ import {
8340
10139
  getLoggerLattice,
8341
10140
  loggerLatticeManager,
8342
10141
  sandboxLatticeManager as sandboxLatticeManager2,
8343
- getStoreLattice as getStoreLattice16,
10142
+ getStoreLattice as getStoreLattice29,
8344
10143
  agentInstanceManager as agentInstanceManager8,
8345
10144
  createSandboxProvider,
8346
10145
  TokenCache,
@@ -8493,7 +10292,7 @@ function getConfiguredSandboxProvider() {
8493
10292
  }
8494
10293
  async function restoreMcpConnections() {
8495
10294
  try {
8496
- const storeLattice = getStoreLattice16("default", "mcp");
10295
+ const storeLattice = getStoreLattice29("default", "mcp");
8497
10296
  const store = storeLattice.store;
8498
10297
  if (!store) {
8499
10298
  logger4.info("MCP store not configured, skipping connection restoration");
@@ -8545,9 +10344,9 @@ var start = async (config) => {
8545
10344
  const { wechatChannelAdapter } = await import("./WechatChannelAdapter-WSDKR4OA.mjs");
8546
10345
  adapterRegistry.register(wechatChannelAdapter);
8547
10346
  try {
8548
- const { getStoreLattice: getStore2 } = await import("@axiom-lattice/core");
8549
- const bindingStore = getStore2("default", "channelBinding").store;
8550
- const installationStore = getStore2("default", "channelInstallation").store;
10347
+ const { getStoreLattice: getStore15 } = await import("@axiom-lattice/core");
10348
+ const bindingStore = getStore15("default", "channelBinding").store;
10349
+ const installationStore = getStore15("default", "channelInstallation").store;
8551
10350
  setBindingRegistry(bindingStore);
8552
10351
  const router = new MessageRouter({
8553
10352
  middlewares: [
@@ -8561,7 +10360,7 @@ var start = async (config) => {
8561
10360
  });
8562
10361
  channelDeps = { router, installationStore };
8563
10362
  try {
8564
- const a2aKeyStore = getStore2("default", "a2aApiKey").store;
10363
+ const a2aKeyStore = getStore15("default", "a2aApiKey").store;
8565
10364
  const a2a = await import("./a2a-ERG5RMUW.mjs");
8566
10365
  a2a.setA2AKeyStore(a2aKeyStore);
8567
10366
  await a2a.refreshStoreKeyMap();
@@ -8573,12 +10372,14 @@ var start = async (config) => {
8573
10372
  error: err instanceof Error ? err.message : String(err)
8574
10373
  });
8575
10374
  }
10375
+ setEvalRunService(evalRunner);
8576
10376
  try {
8577
- const menuStore = getStoreLattice16("default", "menu").store;
10377
+ const menuStore = getStoreLattice29("default", "menu").store;
8578
10378
  setMenuRegistry(menuStore);
8579
10379
  logger4.info("Menu registry initialized");
8580
10380
  } catch {
8581
10381
  }
10382
+ registerAllBuiltinEntities();
8582
10383
  if (channelDeps?.router) {
8583
10384
  setChannelControllerDeps({ adapterRegistry, router: channelDeps.router });
8584
10385
  }
@@ -8589,7 +10390,7 @@ var start = async (config) => {
8589
10390
  }
8590
10391
  try {
8591
10392
  const { ResourceController } = await import("./resources-VA7LSDKN.mjs");
8592
- const sharedResourceStore = getStoreLattice16("default", "sharedResource").store;
10393
+ const sharedResourceStore = getStoreLattice29("default", "sharedResource").store;
8593
10394
  const cache = new TokenCache();
8594
10395
  const resourceController = new ResourceController({
8595
10396
  store: sharedResourceStore,
@@ -8633,11 +10434,13 @@ var start = async (config) => {
8633
10434
  agentTaskConsumer.startPollingQueue();
8634
10435
  }
8635
10436
  }
8636
- agentInstanceManager8.restore().then((stats) => {
8637
- logger4.info(`Agent recovery complete: ${stats.restored} threads restored, ${stats.errors} errors`);
8638
- }).catch((error) => {
8639
- logger4.error("Agent recovery failed", { error });
8640
- });
10437
+ if (process.env.AXIOM_RESTORE_PENDING_ON_STARTUP === "true") {
10438
+ agentInstanceManager8.restore().then((stats) => {
10439
+ logger4.info(`Agent recovery complete: ${stats.restored} threads restored, ${stats.errors} errors`);
10440
+ }).catch((error) => {
10441
+ logger4.error("Agent recovery failed", { error });
10442
+ });
10443
+ }
8641
10444
  restoreMcpConnections().catch((error) => {
8642
10445
  logger4.error("MCP connection restoration failed", { error });
8643
10446
  });