@axiom-lattice/gateway 4.1.0 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1040,18 +1040,18 @@ function extractText(msg) {
1040
1040
  }
1041
1041
  return null;
1042
1042
  }
1043
- var import_zod6, logger4, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections2, seenClientIds, wechatChannelAdapter;
1043
+ var import_zod8, logger5, wechatConfigSchema, MAX_RECONNECT_DELAY_MS, BASE_RECONNECT_DELAY_MS, HEARTBEAT_INTERVAL_MS, MSG_TYPE_USER, MSG_ITEM_TEXT, activeConnections2, seenClientIds, wechatChannelAdapter;
1044
1044
  var init_WechatChannelAdapter = __esm({
1045
1045
  "src/channels/wechat/WechatChannelAdapter.ts"() {
1046
1046
  "use strict";
1047
- import_zod6 = require("zod");
1047
+ import_zod8 = require("zod");
1048
1048
  init_wechat_client();
1049
1049
  init_context_store();
1050
1050
  init_Logger();
1051
- logger4 = new Logger({ serviceName: "lattice/gateway/wechat" });
1052
- wechatConfigSchema = import_zod6.z.object({
1053
- botToken: import_zod6.z.string(),
1054
- uin: import_zod6.z.string().optional()
1051
+ logger5 = new Logger({ serviceName: "lattice/gateway/wechat" });
1052
+ wechatConfigSchema = import_zod8.z.object({
1053
+ botToken: import_zod8.z.string(),
1054
+ uin: import_zod8.z.string().optional()
1055
1055
  });
1056
1056
  MAX_RECONNECT_DELAY_MS = 3e4;
1057
1057
  BASE_RECONNECT_DELAY_MS = 1e3;
@@ -1099,7 +1099,7 @@ var init_WechatChannelAdapter = __esm({
1099
1099
  const senderId = replyTarget.rawTarget.senderId;
1100
1100
  const contextToken = getContextToken(installation.id, senderId);
1101
1101
  if (!contextToken) {
1102
- logger4.warn("WeChat context token expired, cannot send reply", {
1102
+ logger5.warn("WeChat context token expired, cannot send reply", {
1103
1103
  installationId: installation.id,
1104
1104
  senderId
1105
1105
  });
@@ -1117,14 +1117,14 @@ var init_WechatChannelAdapter = __esm({
1117
1117
  async connect(installation, deps) {
1118
1118
  const { id: installationId, tenantId, config } = installation;
1119
1119
  if (!config.botToken) {
1120
- logger4.warn("WeChat installation missing botToken, skipping", { installationId });
1120
+ logger5.warn("WeChat installation missing botToken, skipping", { installationId });
1121
1121
  return;
1122
1122
  }
1123
1123
  if (activeConnections2.has(installationId)) {
1124
- logger4.warn("WeChat polling already running for installation, skipping", { installationId });
1124
+ logger5.warn("WeChat polling already running for installation, skipping", { installationId });
1125
1125
  return;
1126
1126
  }
1127
- logger4.info("WeChat polling starting", { installationId, tenantId });
1127
+ logger5.info("WeChat polling starting", { installationId, tenantId });
1128
1128
  const abortController = new AbortController();
1129
1129
  const heartbeatTimer = setInterval(() => {
1130
1130
  const state2 = activeConnections2.get(installationId);
@@ -1134,7 +1134,7 @@ var init_WechatChannelAdapter = __esm({
1134
1134
  }
1135
1135
  const elapsed = Date.now() - state2.lastActivity;
1136
1136
  if (elapsed > HEARTBEAT_INTERVAL_MS * 2) {
1137
- logger4.error("WeChat polling heartbeat lost \u2014 no activity", {
1137
+ logger5.error("WeChat polling heartbeat lost \u2014 no activity", {
1138
1138
  installationId,
1139
1139
  elapsedMs: elapsed
1140
1140
  });
@@ -1153,7 +1153,7 @@ var init_WechatChannelAdapter = __esm({
1153
1153
  let reconnectDelay = BASE_RECONNECT_DELAY_MS;
1154
1154
  const scheduleNextPoll = () => {
1155
1155
  poll().catch((err) => {
1156
- logger4.error("WeChat poll iteration crashed", {
1156
+ logger5.error("WeChat poll iteration crashed", {
1157
1157
  installationId,
1158
1158
  error: err instanceof Error ? err.message : String(err)
1159
1159
  });
@@ -1166,7 +1166,7 @@ var init_WechatChannelAdapter = __esm({
1166
1166
  const poll = async () => {
1167
1167
  const currentState = activeConnections2.get(installationId);
1168
1168
  if (!currentState || currentState.abortController.signal.aborted) {
1169
- logger4.info("WeChat polling aborted", { installationId });
1169
+ logger5.info("WeChat polling aborted", { installationId });
1170
1170
  return;
1171
1171
  }
1172
1172
  try {
@@ -1179,7 +1179,7 @@ var init_WechatChannelAdapter = __esm({
1179
1179
  reconnectDelay = BASE_RECONNECT_DELAY_MS;
1180
1180
  currentState.lastActivity = Date.now();
1181
1181
  if (result.msgs.length > 0) {
1182
- logger4.info("WeChat poll received messages", {
1182
+ logger5.info("WeChat poll received messages", {
1183
1183
  installationId,
1184
1184
  count: result.msgs.length
1185
1185
  });
@@ -1196,7 +1196,7 @@ var init_WechatChannelAdapter = __esm({
1196
1196
  if (inbound && router) {
1197
1197
  const dispatchResult = await router.dispatch(inbound);
1198
1198
  if (!dispatchResult.success) {
1199
- logger4.warn("WeChat dispatch failed", {
1199
+ logger5.warn("WeChat dispatch failed", {
1200
1200
  installationId,
1201
1201
  error: dispatchResult.error?.message
1202
1202
  });
@@ -1205,10 +1205,10 @@ var init_WechatChannelAdapter = __esm({
1205
1205
  }
1206
1206
  } catch (err) {
1207
1207
  if (err instanceof Error && err.name === "AbortError") {
1208
- logger4.info("WeChat poll aborted by signal", { installationId });
1208
+ logger5.info("WeChat poll aborted by signal", { installationId });
1209
1209
  return;
1210
1210
  }
1211
- logger4.error("WeChat poll error", {
1211
+ logger5.error("WeChat poll error", {
1212
1212
  installationId,
1213
1213
  error: err instanceof Error ? err.message : String(err)
1214
1214
  });
@@ -1218,19 +1218,19 @@ var init_WechatChannelAdapter = __esm({
1218
1218
  scheduleNextPoll();
1219
1219
  };
1220
1220
  scheduleNextPoll();
1221
- logger4.info("WeChat polling started", { installationId });
1221
+ logger5.info("WeChat polling started", { installationId });
1222
1222
  },
1223
1223
  async disconnect(installationId) {
1224
1224
  const state = activeConnections2.get(installationId);
1225
1225
  if (!state) {
1226
- logger4.warn("WeChat polling not running, nothing to disconnect", { installationId });
1226
+ logger5.warn("WeChat polling not running, nothing to disconnect", { installationId });
1227
1227
  return;
1228
1228
  }
1229
- logger4.info("WeChat polling disconnecting", { installationId });
1229
+ logger5.info("WeChat polling disconnecting", { installationId });
1230
1230
  state.abortController.abort();
1231
1231
  clearInterval(state.heartbeatTimer);
1232
1232
  activeConnections2.delete(installationId);
1233
- logger4.info("WeChat polling disconnected", { installationId });
1233
+ logger5.info("WeChat polling disconnected", { installationId });
1234
1234
  }
1235
1235
  };
1236
1236
  }
@@ -1895,12 +1895,12 @@ function agentMessage(text) {
1895
1895
  parts: [{ kind: "text", text }]
1896
1896
  };
1897
1897
  }
1898
- var import_uuid10, import_core55, import_protocols8, _AxiomAgentExecutor, AxiomAgentExecutor;
1898
+ var import_uuid10, import_core56, import_protocols8, _AxiomAgentExecutor, AxiomAgentExecutor;
1899
1899
  var init_AxiomAgentExecutor = __esm({
1900
1900
  "src/services/a2a/AxiomAgentExecutor.ts"() {
1901
1901
  "use strict";
1902
1902
  import_uuid10 = require("uuid");
1903
- import_core55 = require("@axiom-lattice/core");
1903
+ import_core56 = require("@axiom-lattice/core");
1904
1904
  import_protocols8 = require("@axiom-lattice/protocols");
1905
1905
  init_a2aFileRefs();
1906
1906
  init_task_file_refs();
@@ -1987,7 +1987,7 @@ var init_AxiomAgentExecutor = __esm({
1987
1987
  await this.taskStore.save(initialTask);
1988
1988
  bus.publish(initialTask);
1989
1989
  try {
1990
- const agent = import_core55.agentInstanceManager.getAgent({
1990
+ const agent = import_core56.agentInstanceManager.getAgent({
1991
1991
  assistant_id: this.scope.assistantId,
1992
1992
  thread_id: threadId,
1993
1993
  tenant_id: this.scope.tenantId,
@@ -2137,7 +2137,7 @@ ${formatFileRefsSection(inputFiles)}` : text;
2137
2137
  const threadId = task ? asString2(task.metadata?.threadId) : void 0;
2138
2138
  if (threadId) {
2139
2139
  try {
2140
- const agent = import_core55.agentInstanceManager.getAgent({
2140
+ const agent = import_core56.agentInstanceManager.getAgent({
2141
2141
  assistant_id: this.scope.assistantId,
2142
2142
  thread_id: threadId,
2143
2143
  tenant_id: this.scope.tenantId,
@@ -2499,13 +2499,13 @@ function isAsyncGenerator(value) {
2499
2499
  }
2500
2500
  function registerA2AStandardRoutes(app2, deps) {
2501
2501
  const authService = deps.authService;
2502
- const getTaskStore = deps.getTaskStoreLattice ?? (() => (0, import_core56.getStoreLattice)("default", "task").store);
2503
- const getTaskWorkItemStore2 = deps.getTaskWorkItemStore ?? (() => (0, import_core56.getStoreLattice)("default", "taskWorkItem").store);
2504
- const getAssistantStore3 = deps.getAssistantStore ?? (() => (0, import_core56.getStoreLattice)("default", "assistant").store);
2505
- const getProjectStore2 = deps.getProjectStore ?? (() => (0, import_core56.getStoreLattice)("default", "project").store);
2502
+ const getTaskStore = deps.getTaskStoreLattice ?? (() => (0, import_core57.getStoreLattice)("default", "task").store);
2503
+ const getTaskWorkItemStore2 = deps.getTaskWorkItemStore ?? (() => (0, import_core57.getStoreLattice)("default", "taskWorkItem").store);
2504
+ const getAssistantStore3 = deps.getAssistantStore ?? (() => (0, import_core57.getStoreLattice)("default", "assistant").store);
2505
+ const getProjectStore2 = deps.getProjectStore ?? (() => (0, import_core57.getStoreLattice)("default", "project").store);
2506
2506
  const getTenantStore = deps.getTenantStore ?? (() => {
2507
2507
  try {
2508
- return (0, import_core56.getStoreLattice)("default", "tenant").store;
2508
+ return (0, import_core57.getStoreLattice)("default", "tenant").store;
2509
2509
  } catch {
2510
2510
  return void 0;
2511
2511
  }
@@ -2520,10 +2520,10 @@ function registerA2AStandardRoutes(app2, deps) {
2520
2520
  const tenantStore = getTenantStore();
2521
2521
  if (!tenantStore) return null;
2522
2522
  const tenants = await tenantStore.getAllTenants();
2523
- for (const tenant of tenants) {
2524
- if (tenant.id === tenantId) continue;
2523
+ for (const tenant2 of tenants) {
2524
+ if (tenant2.id === tenantId) continue;
2525
2525
  const found = await getAssistantStore3().getAssistantById(
2526
- tenant.id,
2526
+ tenant2.id,
2527
2527
  assistantId
2528
2528
  );
2529
2529
  if (found) return found;
@@ -2597,7 +2597,7 @@ function registerA2AStandardRoutes(app2, deps) {
2597
2597
  const taskStore = new A2ATaskStoreAdapter({
2598
2598
  taskStore: internalTaskStore,
2599
2599
  workItemStore,
2600
- lifecycle: (0, import_core56.createTaskLifecycleService)({
2600
+ lifecycle: (0, import_core57.createTaskLifecycleService)({
2601
2601
  taskStore: internalTaskStore,
2602
2602
  workItemStore
2603
2603
  }),
@@ -2716,7 +2716,7 @@ data: ${JSON.stringify(errorResponse)}
2716
2716
  const taskStore = new A2ATaskStoreAdapter({
2717
2717
  taskStore: internalTaskStore,
2718
2718
  workItemStore,
2719
- lifecycle: (0, import_core56.createTaskLifecycleService)({
2719
+ lifecycle: (0, import_core57.createTaskLifecycleService)({
2720
2720
  taskStore: internalTaskStore,
2721
2721
  workItemStore
2722
2722
  }),
@@ -2761,13 +2761,13 @@ data: ${JSON.stringify(data)}
2761
2761
  }
2762
2762
  );
2763
2763
  }
2764
- var import_uuid11, import_server2, import_core56, SSE_HEADERS;
2764
+ var import_uuid11, import_server2, import_core57, SSE_HEADERS;
2765
2765
  var init_a2a_standard = __esm({
2766
2766
  "src/routes/a2a-standard.ts"() {
2767
2767
  "use strict";
2768
2768
  import_uuid11 = require("uuid");
2769
2769
  import_server2 = require("@a2a-js/sdk/server");
2770
- import_core56 = require("@axiom-lattice/core");
2770
+ import_core57 = require("@axiom-lattice/core");
2771
2771
  init_A2AAuthService();
2772
2772
  init_A2AAgentCardBuilder();
2773
2773
  init_A2ATaskStoreAdapter();
@@ -2941,12 +2941,12 @@ var resources_exports = {};
2941
2941
  __export(resources_exports, {
2942
2942
  ResourceController: () => ResourceController
2943
2943
  });
2944
- var import_bcryptjs, import_core57, ResourceController;
2944
+ var import_bcryptjs, import_core58, ResourceController;
2945
2945
  var init_resources = __esm({
2946
2946
  "src/controllers/resources.ts"() {
2947
2947
  "use strict";
2948
2948
  import_bcryptjs = __toESM(require("bcryptjs"));
2949
- import_core57 = require("@axiom-lattice/core");
2949
+ import_core58 = require("@axiom-lattice/core");
2950
2950
  init_mime();
2951
2951
  ResourceController = class {
2952
2952
  constructor(deps) {
@@ -2961,14 +2961,14 @@ var init_resources = __esm({
2961
2961
  if (!workspaceId || !projectId) {
2962
2962
  return reply.status(400).send({ error: "x-workspace-id and x-project-id headers required" });
2963
2963
  }
2964
- const payload = (0, import_core57.createSharePayload)(
2964
+ const payload = (0, import_core58.createSharePayload)(
2965
2965
  tenantId,
2966
2966
  workspaceId,
2967
2967
  projectId,
2968
2968
  userId,
2969
2969
  body
2970
2970
  );
2971
- const token = (0, import_core57.generateToken)();
2971
+ const token = (0, import_core58.generateToken)();
2972
2972
  try {
2973
2973
  await this.deps.store.create({ ...payload, token });
2974
2974
  this.deps.logger.info(
@@ -3120,7 +3120,7 @@ var init_resources = __esm({
3120
3120
  resourcePath: subPath
3121
3121
  }, subPath, ext, request, reply);
3122
3122
  }
3123
- const volume = (0, import_core57.buildNamedVolumeName)("p", "project", tenantId, workspaceId, projectId);
3123
+ const volume = (0, import_core58.buildNamedVolumeName)("p", "project", tenantId, workspaceId, projectId);
3124
3124
  return this._resolveAndServe(
3125
3125
  volume,
3126
3126
  subPath,
@@ -4395,7 +4395,7 @@ var recoverRun = async (request, reply) => {
4395
4395
  const { assistantId, threadId } = request.params;
4396
4396
  const tenant_id = request.headers["x-tenant-id"];
4397
4397
  const workspace_id = request.headers["x-workspace-id"] || "default";
4398
- const project_id = request.headers["x-project-id"] || "default";
4398
+ const project_id = request.headers["x-project-id"];
4399
4399
  const agent = import_core3.agentInstanceManager.getAgent({
4400
4400
  assistant_id: assistantId,
4401
4401
  thread_id: threadId,
@@ -4403,8 +4403,7 @@ var recoverRun = async (request, reply) => {
4403
4403
  workspace_id,
4404
4404
  project_id
4405
4405
  });
4406
- await agent.resumeTask();
4407
- const status = await agent.getRunStatus();
4406
+ const { status } = await agent.resumeTask();
4408
4407
  reply.status(200).send({
4409
4408
  success: true,
4410
4409
  threadId,
@@ -5291,6 +5290,7 @@ async function getHealth(request, reply) {
5291
5290
 
5292
5291
  // src/services/skill_service.ts
5293
5292
  var import_core10 = require("@axiom-lattice/core");
5293
+ var PLUGIN_SKILL_SOURCE = "builtin-plugin";
5294
5294
  function getTenantId4(request) {
5295
5295
  return request.user?.tenantId || request.headers["x-tenant-id"] || "default";
5296
5296
  }
@@ -5306,28 +5306,63 @@ function buildContext(request) {
5306
5306
  projectId: getProjectId(request)
5307
5307
  };
5308
5308
  }
5309
+ function pluginSkillToSkill(item, tenantId, content) {
5310
+ return {
5311
+ id: item.id,
5312
+ tenantId,
5313
+ name: item.name,
5314
+ description: item.description,
5315
+ version: item.version,
5316
+ pluginType: item.pluginType,
5317
+ resourcePaths: item.resourcePaths,
5318
+ source: PLUGIN_SKILL_SOURCE,
5319
+ readOnly: true,
5320
+ content,
5321
+ createdAt: /* @__PURE__ */ new Date(0),
5322
+ updatedAt: /* @__PURE__ */ new Date(0)
5323
+ };
5324
+ }
5309
5325
  var SkillService = class {
5310
5326
  constructor() {
5311
5327
  this.store = new import_core10.SandboxSkillStore();
5312
5328
  }
5313
5329
  async getAllSkills(request) {
5314
5330
  const tenantId = getTenantId4(request);
5315
- return this.store.getAllSkills(tenantId, buildContext(request));
5331
+ const storeSkills = await this.store.getAllSkills(tenantId, buildContext(request));
5332
+ const merged = /* @__PURE__ */ new Map();
5333
+ for (const skill of storeSkills) {
5334
+ merged.set(skill.id, skill);
5335
+ }
5336
+ for (const item of import_core10.PluginRegistry.listSkills()) {
5337
+ merged.set(item.id, pluginSkillToSkill(item, tenantId));
5338
+ }
5339
+ return Array.from(merged.values());
5316
5340
  }
5317
5341
  async getSkillById(request, id) {
5318
5342
  const tenantId = getTenantId4(request);
5343
+ const plugin = import_core10.PluginRegistry.getSkill(id);
5344
+ if (plugin) {
5345
+ const { definition } = plugin;
5346
+ const item = import_core10.PluginRegistry.listSkills().find((entry) => entry.id === id);
5347
+ if (item) {
5348
+ return pluginSkillToSkill(item, tenantId, definition.content);
5349
+ }
5350
+ }
5319
5351
  return this.store.getSkillById(tenantId, id, buildContext(request));
5320
5352
  }
5321
5353
  async createSkill(request, id, data) {
5322
5354
  const tenantId = getTenantId4(request);
5355
+ this.assertNotPluginSkill(id, "created");
5323
5356
  return this.store.createSkill(tenantId, id, data, buildContext(request));
5324
5357
  }
5325
5358
  async updateSkill(request, id, updates) {
5326
5359
  const tenantId = getTenantId4(request);
5360
+ this.assertNotPluginSkill(id, "modified");
5327
5361
  return this.store.updateSkill(tenantId, id, updates, buildContext(request));
5328
5362
  }
5329
5363
  async deleteSkill(request, id) {
5330
5364
  const tenantId = getTenantId4(request);
5365
+ this.assertNotPluginSkill(id, "deleted");
5331
5366
  return this.store.deleteSkill(tenantId, id, buildContext(request));
5332
5367
  }
5333
5368
  async searchByMetadata(request, key, value) {
@@ -5342,6 +5377,16 @@ var SkillService = class {
5342
5377
  const tenantId = getTenantId4(request);
5343
5378
  return this.store.filterByLicense(tenantId, license, buildContext(request));
5344
5379
  }
5380
+ /**
5381
+ * Guard against mutating a registered plugin skill.
5382
+ * Message style mirrors SandboxSkillStore built-in errors so the controller's
5383
+ * existing "built-in skill" -> 403 mapping applies.
5384
+ */
5385
+ assertNotPluginSkill(id, action) {
5386
+ if (import_core10.PluginRegistry.getSkill(id)) {
5387
+ throw new Error(`Skill "${id}" is a built-in skill and cannot be ${action}`);
5388
+ }
5389
+ }
5345
5390
  };
5346
5391
 
5347
5392
  // src/controllers/skills.ts
@@ -5356,6 +5401,11 @@ function serializeSkill(skill) {
5356
5401
  metadata: skill.metadata || {},
5357
5402
  content: skill.content,
5358
5403
  subSkills: skill.subSkills,
5404
+ source: skill.source,
5405
+ pluginType: skill.pluginType,
5406
+ version: skill.version,
5407
+ resources: skill.resourcePaths,
5408
+ readOnly: skill.readOnly,
5359
5409
  createdAt: skill.createdAt instanceof Date ? skill.createdAt.toISOString() : (/* @__PURE__ */ new Date()).toISOString(),
5360
5410
  updatedAt: skill.updatedAt instanceof Date ? skill.updatedAt.toISOString() : (/* @__PURE__ */ new Date()).toISOString()
5361
5411
  };
@@ -8480,6 +8530,10 @@ function createZip(entries) {
8480
8530
  end.writeUInt32LE(offset, 16);
8481
8531
  return Buffer.concat([...localParts, centralDirectory, end]);
8482
8532
  }
8533
+ var CAPABILITY_BUNDLE_CONFIG_MESSAGE = "Use /api/projects/:projectId/capability-bundles to update capability bundle IDs";
8534
+ function writesCapabilityBundleIds(config) {
8535
+ return config !== void 0 && Object.prototype.hasOwnProperty.call(config, "capabilityBundleIds");
8536
+ }
8483
8537
  var WorkspaceController = class {
8484
8538
  constructor() {
8485
8539
  this.workspaceStore = (0, import_core24.getStoreLattice)("default", "workspace").store;
@@ -8587,6 +8641,13 @@ var WorkspaceController = class {
8587
8641
  const tenantId = this.getTenantId(request);
8588
8642
  const { workspaceId } = request.params;
8589
8643
  const data = request.body;
8644
+ if (writesCapabilityBundleIds(data.config)) {
8645
+ return reply.status(400).send({
8646
+ success: false,
8647
+ code: "INVALID_BUNDLE_CONFIG",
8648
+ message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
8649
+ });
8650
+ }
8590
8651
  const id = (0, import_uuid3.v4)();
8591
8652
  const project = await this.projectStore.createProject(
8592
8653
  tenantId,
@@ -8609,6 +8670,13 @@ var WorkspaceController = class {
8609
8670
  const tenantId = this.getTenantId(request);
8610
8671
  const { projectId } = request.params;
8611
8672
  const updates = request.body;
8673
+ if (writesCapabilityBundleIds(updates.config)) {
8674
+ return reply.status(400).send({
8675
+ success: false,
8676
+ code: "INVALID_BUNDLE_CONFIG",
8677
+ message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
8678
+ });
8679
+ }
8612
8680
  const project = await this.projectStore.updateProject(
8613
8681
  tenantId,
8614
8682
  projectId,
@@ -8766,6 +8834,40 @@ var WorkspaceController = class {
8766
8834
  if (!project || project.workspaceId !== workspaceId) {
8767
8835
  throw new FolderDownloadError(404, "PROJECT_NOT_FOUND", "Project not found");
8768
8836
  }
8837
+ if (storedWorkspace.storageType === "sandbox") {
8838
+ const sandboxManager = (0, import_core26.getSandBoxManager)();
8839
+ const volumeConfig = {
8840
+ assistant_id: assistantId || "",
8841
+ thread_id: "",
8842
+ tenantId,
8843
+ workspaceId,
8844
+ projectId
8845
+ };
8846
+ const sandbox = await sandboxManager.getSandboxFromConfig(volumeConfig);
8847
+ if (!sandbox.packDirectory || !sandbox.file.deleteFile) {
8848
+ throw new FolderDownloadError(502, "BACKEND_UNSUPPORTED", "Backend does not support folder archive cleanup");
8849
+ }
8850
+ let packed;
8851
+ try {
8852
+ packed = await sandbox.packDirectory(folderPath);
8853
+ if (packed.size === void 0) {
8854
+ throw new FolderDownloadError(502, "BACKEND_UNSUPPORTED", "Backend does not report packed archive size");
8855
+ }
8856
+ if (!Number.isFinite(packed.size) || packed.size < 0 || packed.size > MAX_ZIP_TOTAL_SIZE) {
8857
+ throw new FolderDownloadError(400, "SIZE_LIMIT", "Packed folder exceeds download size limits");
8858
+ }
8859
+ const buffer = await sandbox.file.downloadFile({ file: packed.path });
8860
+ return reply.status(200).type("application/zip").header("Content-Disposition", `attachment; filename*=UTF-8''${encodeURIComponent(packed.filename)}`).send(buffer);
8861
+ } finally {
8862
+ if (packed) {
8863
+ try {
8864
+ await sandbox.file.deleteFile(packed.path);
8865
+ } catch (cleanupError) {
8866
+ console.warn("Failed to clean up packed sandbox folder archive", cleanupError);
8867
+ }
8868
+ }
8869
+ }
8870
+ }
8769
8871
  const { backend, workspace } = await this.getBackend(
8770
8872
  tenantId,
8771
8873
  workspaceId,
@@ -8773,7 +8875,7 @@ var WorkspaceController = class {
8773
8875
  assistantId,
8774
8876
  folderPath
8775
8877
  );
8776
- if (!backend.lsInfo || workspace.storageType === "sandbox" && !backend.readBinary) {
8878
+ if (!backend.lsInfo) {
8777
8879
  throw new FolderDownloadError(502, "BACKEND_UNSUPPORTED", "Backend does not support folder downloads");
8778
8880
  }
8779
8881
  let listEntries2;
@@ -11304,31 +11406,31 @@ var TenantsController = class {
11304
11406
  async createTenant(request, reply) {
11305
11407
  const data = request.body;
11306
11408
  const id = (0, import_uuid7.v4)();
11307
- const tenant = await this.tenantStore.createTenant(id, data);
11308
- return reply.status(201).send({ success: true, data: tenant });
11409
+ const tenant2 = await this.tenantStore.createTenant(id, data);
11410
+ return reply.status(201).send({ success: true, data: tenant2 });
11309
11411
  }
11310
11412
  async getTenant(request, reply) {
11311
11413
  const { tenantId } = request.params;
11312
- const tenant = await this.tenantStore.getTenantById(tenantId);
11313
- if (!tenant) {
11414
+ const tenant2 = await this.tenantStore.getTenantById(tenantId);
11415
+ if (!tenant2) {
11314
11416
  return reply.status(404).send({
11315
11417
  success: false,
11316
11418
  error: "Tenant not found"
11317
11419
  });
11318
11420
  }
11319
- return { success: true, data: tenant };
11421
+ return { success: true, data: tenant2 };
11320
11422
  }
11321
11423
  async updateTenant(request, reply) {
11322
11424
  const { tenantId } = request.params;
11323
11425
  const updates = request.body;
11324
- const tenant = await this.tenantStore.updateTenant(tenantId, updates);
11325
- if (!tenant) {
11426
+ const tenant2 = await this.tenantStore.updateTenant(tenantId, updates);
11427
+ if (!tenant2) {
11326
11428
  return reply.status(404).send({
11327
11429
  success: false,
11328
11430
  error: "Tenant not found"
11329
11431
  });
11330
11432
  }
11331
- return { success: true, data: tenant };
11433
+ return { success: true, data: tenant2 };
11332
11434
  }
11333
11435
  async deleteTenant(request, reply) {
11334
11436
  const { tenantId } = request.params;
@@ -11481,10 +11583,10 @@ var AuthController = class {
11481
11583
  const links = await this.userTenantLinkStore.getTenantsByUser(userId);
11482
11584
  const tenantsWithDetails = await Promise.all(
11483
11585
  links.map(async (link) => {
11484
- const tenant = await this.tenantStore.getTenantById(link.tenantId);
11586
+ const tenant2 = await this.tenantStore.getTenantById(link.tenantId);
11485
11587
  return {
11486
11588
  ...link,
11487
- tenant: tenant || null
11589
+ tenant: tenant2 || null
11488
11590
  };
11489
11591
  })
11490
11592
  );
@@ -11517,8 +11619,8 @@ var AuthController = class {
11517
11619
  error: "You do not have access to this tenant"
11518
11620
  });
11519
11621
  }
11520
- const tenant = await this.tenantStore.getTenantById(tenantId);
11521
- if (!tenant) {
11622
+ const tenant2 = await this.tenantStore.getTenantById(tenantId);
11623
+ if (!tenant2) {
11522
11624
  return reply.status(404).send({
11523
11625
  success: false,
11524
11626
  error: "Tenant not found"
@@ -11542,7 +11644,7 @@ var AuthController = class {
11542
11644
  return {
11543
11645
  success: true,
11544
11646
  data: {
11545
- tenant,
11647
+ tenant: tenant2,
11546
11648
  token,
11547
11649
  personalAssistant
11548
11650
  }
@@ -11612,8 +11714,8 @@ var AuthController = class {
11612
11714
  error: "User not found"
11613
11715
  });
11614
11716
  }
11615
- const tenant = await this.tenantStore.getTenantById(tenantId);
11616
- if (!tenant) {
11717
+ const tenant2 = await this.tenantStore.getTenantById(tenantId);
11718
+ if (!tenant2) {
11617
11719
  return reply.status(404).send({
11618
11720
  success: false,
11619
11721
  error: "Tenant not found"
@@ -13458,7 +13560,7 @@ function registerTaskRoutes(app2) {
13458
13560
  }
13459
13561
 
13460
13562
  // src/routes/index.ts
13461
- var import_core41 = require("@axiom-lattice/core");
13563
+ var import_core42 = require("@axiom-lattice/core");
13462
13564
 
13463
13565
  // src/services/agent-web-app/AgentWebAppService.ts
13464
13566
  function createConfiguredAgentResolver(registry) {
@@ -14417,42 +14519,399 @@ function isAttachmentPayload(value) {
14417
14519
 
14418
14520
  // src/routes/index.ts
14419
14521
  init_workspace_file_service();
14522
+
14523
+ // src/controllers/capability-bundles.ts
14524
+ var import_zod7 = require("zod");
14525
+
14526
+ // src/services/capability/CapabilityBundleService.ts
14527
+ var import_zod6 = require("zod");
14528
+ var import_core41 = require("@axiom-lattice/core");
14529
+ var CapabilityBundleServiceError = class extends Error {
14530
+ constructor(code, message, statusCode) {
14531
+ super(message);
14532
+ this.code = code;
14533
+ this.statusCode = statusCode;
14534
+ this.name = "CapabilityBundleServiceError";
14535
+ }
14536
+ };
14537
+ var uuid = import_zod6.z.string().uuid();
14538
+ function ownRecord(value) {
14539
+ if (value === void 0 || value === null) return {};
14540
+ if (typeof value !== "object" || Array.isArray(value)) throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "Project config must be an object", 409);
14541
+ const result = {};
14542
+ for (const [key, entry] of Object.entries(value)) {
14543
+ if (key !== "__proto__" && key !== "constructor" && key !== "prototype") result[key] = entry;
14544
+ }
14545
+ return result;
14546
+ }
14547
+ function isDuplicate(error) {
14548
+ return error instanceof Error && /already exists|unique|duplicate/i.test(error.message);
14549
+ }
14550
+ function rejectStableKey(input) {
14551
+ if (input !== null && typeof input === "object" && !Array.isArray(input) && Object.prototype.hasOwnProperty.call(input, "key")) {
14552
+ throw new CapabilityBundleServiceError("INVALID_INPUT", "Capability bundle key is generated and cannot be supplied or changed", 400);
14553
+ }
14554
+ }
14555
+ function slugify(name) {
14556
+ const slug = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
14557
+ return slug || "runtime-profile";
14558
+ }
14559
+ function projectBundleIds(config) {
14560
+ const record = ownRecord(config);
14561
+ if (!Object.prototype.hasOwnProperty.call(record, "capabilityBundleIds")) return [];
14562
+ const value = record.capabilityBundleIds;
14563
+ if (!Array.isArray(value) || value.some((id) => typeof id !== "string" || !uuid.safeParse(id).success) || new Set(value).size !== value.length) {
14564
+ throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "Project capabilityBundleIds must be a unique array of UUIDs", 409);
14565
+ }
14566
+ return [...value];
14567
+ }
14568
+ function issue(error) {
14569
+ if (error instanceof import_core41.CapabilityBundleMergeError || error instanceof import_core41.CapabilityBundleValidationError) return { code: error instanceof import_core41.CapabilityBundleValidationError && error.code === "CAPABILITY_BUNDLE_INVALID_CONFIG" ? "INVALID_BUNDLE_CONFIG" : error.code, message: error.message, bundleId: error instanceof import_core41.CapabilityBundleMergeError ? error.bundleId : void 0, capabilityType: error.capabilityType, fieldPath: error.fieldPath };
14570
+ return { code: "CAPABILITY_BUNDLE_CONFIGURATION_ERROR", message: error instanceof Error ? error.message : "Invalid capability bundle configuration" };
14571
+ }
14572
+ var CapabilityBundleService = class {
14573
+ constructor(deps) {
14574
+ this.deps = deps;
14575
+ }
14576
+ async list(tenantId) {
14577
+ const values = await this.deps.bundleStore.listByTenant(tenantId);
14578
+ const bundles = [];
14579
+ const errors = [];
14580
+ for (const value of values) {
14581
+ try {
14582
+ (0, import_core41.validateCapabilityBundleInput)(value);
14583
+ bundles.push(value);
14584
+ } catch {
14585
+ errors.push({ bundleId: value.id, code: "INVALID_BUNDLE_CONFIG", message: "Capability bundle record is invalid" });
14586
+ }
14587
+ }
14588
+ return { bundles, errors };
14589
+ }
14590
+ async get(tenantId, id) {
14591
+ const value = await this.deps.bundleStore.getById(tenantId, id);
14592
+ if (!value) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
14593
+ try {
14594
+ (0, import_core41.validateCapabilityBundleInput)(value);
14595
+ } catch {
14596
+ throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "Capability bundle record is invalid", 422);
14597
+ }
14598
+ return value;
14599
+ }
14600
+ async create(tenantId, input) {
14601
+ rejectStableKey(input);
14602
+ (0, import_core41.validateCapabilityBundleInput)(input);
14603
+ const value = input;
14604
+ const name = value.name.trim();
14605
+ const base = slugify(name);
14606
+ for (let attempt = 0; attempt < 5; attempt += 1) {
14607
+ const existing = await this.deps.bundleStore.listByTenant(tenantId) ?? [];
14608
+ const keys = new Set(existing.map((bundle) => bundle.key));
14609
+ let key = base;
14610
+ let suffix = 2;
14611
+ while (keys.has(key)) key = `${base}-${suffix++}`;
14612
+ const normalized = { ...value, key, name };
14613
+ (0, import_core41.validateCapabilityBundleInput)(normalized);
14614
+ try {
14615
+ const result = await this.deps.bundleStore.create(tenantId, normalized);
14616
+ (0, import_core41.validateCapabilityBundleInput)(result);
14617
+ return result;
14618
+ } catch (error) {
14619
+ if (!isDuplicate(error)) throw error;
14620
+ if (attempt === 4) throw new CapabilityBundleServiceError("DUPLICATE_BUNDLE_KEY", "Capability bundle key already exists", 409);
14621
+ }
14622
+ }
14623
+ throw new CapabilityBundleServiceError("DUPLICATE_BUNDLE_KEY", "Capability bundle key already exists", 409);
14624
+ }
14625
+ async update(tenantId, id, input) {
14626
+ rejectStableKey(input);
14627
+ (0, import_core41.validateCapabilityBundleInput)(input, { partial: true });
14628
+ if (!input || typeof input !== "object" || Array.isArray(input) || typeof input.expectedUpdatedAt !== "string" || !input.expectedUpdatedAt.trim()) throw new CapabilityBundleServiceError("INVALID_BUNDLE_CONFIG", "expectedUpdatedAt is required for capability bundle updates", 400);
14629
+ const value = input;
14630
+ const normalized = { ...value, ...value.name === void 0 ? {} : { name: value.name.trim() }, ...Object.prototype.hasOwnProperty.call(value, "description") ? { description: value.description?.trim() || void 0 } : {} };
14631
+ (0, import_core41.validateCapabilityBundleInput)(normalized, { partial: true });
14632
+ try {
14633
+ const result = await this.deps.bundleStore.update(tenantId, id, normalized);
14634
+ if (!result) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
14635
+ if ("status" in result && result.status === "conflict") throw new CapabilityBundleServiceError("BUNDLE_CONFLICT", "Capability bundle changed after it was loaded; reload before saving", 409);
14636
+ (0, import_core41.validateCapabilityBundleInput)(result);
14637
+ return result;
14638
+ } catch (error) {
14639
+ if (error instanceof CapabilityBundleServiceError) throw error;
14640
+ if (isDuplicate(error)) throw new CapabilityBundleServiceError("DUPLICATE_BUNDLE_KEY", "Capability bundle key already exists", 409);
14641
+ throw error;
14642
+ }
14643
+ }
14644
+ async remove(tenantId, id) {
14645
+ const result = await this.deps.bundleStore.deleteIfUnreferenced(tenantId, id);
14646
+ if (result === "not_found") throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
14647
+ if (result === "in_use") throw new CapabilityBundleServiceError("BUNDLE_IN_USE", "Capability bundle is in use", 409);
14648
+ }
14649
+ async getProjectBundles(tenantId, projectId) {
14650
+ const project = await this.deps.projectStore.getProjectById(tenantId, projectId);
14651
+ if (!project) throw new CapabilityBundleServiceError("PROJECT_NOT_FOUND", "Project not found", 404);
14652
+ const ids = projectBundleIds(project.config);
14653
+ const stored = await this.deps.bundleStore.getManyByIds(tenantId, ids) ?? [];
14654
+ return this.compose(project, ids, stored);
14655
+ }
14656
+ async previewProject(tenantId, projectId) {
14657
+ const project = await this.deps.projectStore.getProjectById(tenantId, projectId);
14658
+ if (!project) throw new CapabilityBundleServiceError("PROJECT_NOT_FOUND", "Project not found", 404);
14659
+ let ids;
14660
+ try {
14661
+ ids = projectBundleIds(project.config);
14662
+ } catch (error) {
14663
+ return { bundleIds: [], capabilities: [], overrides: [], sources: [], warnings: [], errors: [{ code: "INVALID_BUNDLE_CONFIG", message: error instanceof Error ? error.message : "Invalid project capability configuration" }], revision: "" };
14664
+ }
14665
+ const stored = await this.deps.bundleStore.getManyByIds(tenantId, ids) ?? [];
14666
+ const byId = new Map(stored.map((value) => [value.id, value]));
14667
+ const missing = ids.filter((id) => !byId.has(id));
14668
+ if (missing.length > 0) return { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: missing.map((id) => ({ code: "BUNDLE_NOT_FOUND", message: `Persisted capability bundle '${id}' is missing`, bundleId: id })), revision: "" };
14669
+ try {
14670
+ const ordered = ids.map((id) => byId.get(id));
14671
+ ordered.forEach((bundle) => (0, import_core41.validateCapabilityBundleInput)(bundle));
14672
+ return (0, import_core41.mergeCapabilityBundles)(ordered);
14673
+ } catch (error) {
14674
+ return { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: [issue(error)], revision: "" };
14675
+ }
14676
+ }
14677
+ async project(tenantId, projectId, ids, persist, expectedRevisions) {
14678
+ const current = await this.deps.projectStore.getProjectById(tenantId, projectId);
14679
+ if (!current) throw new CapabilityBundleServiceError("PROJECT_NOT_FOUND", "Project not found", 404);
14680
+ if (new Set(ids).size !== ids.length) throw new CapabilityBundleServiceError("DUPLICATE_PROJECT_BUNDLE", "Duplicate capability bundle ID", 400);
14681
+ if (persist) this.assertExpectedRevisions(ids, expectedRevisions);
14682
+ const ordered = await this.loadOrderedBundles(tenantId, ids);
14683
+ let resultProject = current;
14684
+ if (persist) {
14685
+ projectBundleIds(current.config);
14686
+ const update = await this.deps.projectStore.updateCapabilityBundleIds(tenantId, projectId, ids, expectedRevisions);
14687
+ if (update.status === "project_not_found") throw new CapabilityBundleServiceError("PROJECT_NOT_FOUND", "Project not found", 404);
14688
+ if (update.status === "bundle_not_found") throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
14689
+ if (update.status === "bundle_conflict") throw new CapabilityBundleServiceError("BUNDLE_CONFLICT", "Capability bundle changed after preview; preview the current bundle contents before saving", 409);
14690
+ resultProject = update.project;
14691
+ }
14692
+ return this.compose(resultProject, ids, ordered);
14693
+ }
14694
+ assertExpectedRevisions(ids, revisions) {
14695
+ if (!revisions || Object.keys(revisions).length !== ids.length || ids.some((id) => typeof revisions[id] !== "string" || !revisions[id].trim()) || Object.keys(revisions).some((id) => !ids.includes(id))) {
14696
+ throw new CapabilityBundleServiceError("BUNDLE_CONFLICT", "Expected revisions must exactly match the selected capability bundles", 409);
14697
+ }
14698
+ }
14699
+ async loadOrderedBundles(tenantId, ids) {
14700
+ const stored = await this.deps.bundleStore.getManyByIds(tenantId, ids) ?? [];
14701
+ const byId = new Map(stored.map((value) => [value.id, value]));
14702
+ return ids.map((id) => {
14703
+ const value = byId.get(id);
14704
+ if (!value) throw new CapabilityBundleServiceError("BUNDLE_NOT_FOUND", "Capability bundle not found", 404);
14705
+ (0, import_core41.validateCapabilityBundleInput)(value);
14706
+ return value;
14707
+ });
14708
+ }
14709
+ compose(project, ids, bundles) {
14710
+ const valid = [];
14711
+ const errors = [];
14712
+ const byId = new Map(bundles.map((bundle) => [bundle.id, bundle]));
14713
+ for (const id of ids) {
14714
+ const bundle = byId.get(id);
14715
+ if (!bundle) {
14716
+ errors.push({ code: "BUNDLE_NOT_FOUND", message: `Persisted capability bundle '${id}' is missing`, bundleId: id });
14717
+ continue;
14718
+ }
14719
+ try {
14720
+ (0, import_core41.validateCapabilityBundleInput)(bundle);
14721
+ valid.push(bundle);
14722
+ } catch (error) {
14723
+ errors.push({ ...issue(error), bundleId: id });
14724
+ }
14725
+ }
14726
+ let preview;
14727
+ try {
14728
+ preview = (0, import_core41.mergeCapabilityBundles)(valid);
14729
+ } catch (error) {
14730
+ preview = { bundleIds: ids, capabilities: [], overrides: [], sources: [], warnings: [], errors: [issue(error)], revision: "" };
14731
+ }
14732
+ preview = { ...preview, bundleIds: ids, errors: [...errors, ...preview.errors] };
14733
+ return { project, persistedBundleIds: ids, bundles: valid, preview };
14734
+ }
14735
+ };
14736
+
14737
+ // src/controllers/capability-bundles.ts
14738
+ init_Logger();
14739
+ var logger3 = new Logger({ serviceName: "lattice/gateway/capability-bundles" });
14740
+ var capability = import_zod7.z.unknown();
14741
+ var createSchema = import_zod7.z.object({ name: import_zod7.z.string(), description: import_zod7.z.string().optional(), capabilities: import_zod7.z.array(capability) }).strict();
14742
+ var updateSchema = createSchema.partial().extend({ expectedUpdatedAt: import_zod7.z.string().optional() });
14743
+ var bundleIdSchema = import_zod7.z.string().uuid();
14744
+ var bundleParamsSchema = import_zod7.z.object({ bundleId: bundleIdSchema });
14745
+ var projectSchema = import_zod7.z.object({ bundleIds: import_zod7.z.array(bundleIdSchema), expectedRevisions: import_zod7.z.record(import_zod7.z.string()).optional() }).strict();
14746
+ function tenant(request, authRequired2) {
14747
+ const authenticated = request.user?.tenantId;
14748
+ const header = request.headers["x-tenant-id"];
14749
+ const requested = Array.isArray(header) ? header[0] : header;
14750
+ if (authenticated) {
14751
+ if (requested && requested !== authenticated) throw new CapabilityBundleServiceError("INVALID_INPUT", "Forbidden", 403);
14752
+ return authenticated;
14753
+ }
14754
+ if (authRequired2) throw new CapabilityBundleServiceError("INVALID_INPUT", "Unauthorized", 401);
14755
+ return requested || "default";
14756
+ }
14757
+ function sendError(reply, error) {
14758
+ if (error instanceof CapabilityBundleServiceError) return reply.status(error.statusCode).send({ success: false, code: error.code, message: error.message });
14759
+ if (error instanceof Error && error.name === "CapabilityBundleValidationError") {
14760
+ const validationError = error;
14761
+ const code = validationError.code === "CAPABILITY_BUNDLE_INELIGIBLE_CAPABILITY" ? "BUNDLE_PLUGIN_NOT_ELIGIBLE" : validationError.code === "CAPABILITY_BUNDLE_CREDENTIALS_FORBIDDEN" || validationError.code === "CAPABILITY_BUNDLE_INVALID_CONFIG" ? "INVALID_BUNDLE_CONFIG" : validationError.code;
14762
+ return reply.status(400).send({ success: false, code, message: error.message, capabilityType: validationError.capabilityType, fieldPath: validationError.fieldPath });
14763
+ }
14764
+ logger3.error("Capability bundle controller error", { error: error instanceof Error ? error : new Error(String(error)) });
14765
+ return reply.status(500).send({ success: false, code: "INTERNAL_ERROR", message: "Internal server error" });
14766
+ }
14767
+ var CapabilityBundleController = class {
14768
+ constructor(deps, options = {}) {
14769
+ this.service = new CapabilityBundleService(deps);
14770
+ this.authRequired = options.authRequired ?? true;
14771
+ }
14772
+ async listBundles(request, reply) {
14773
+ try {
14774
+ const result = await this.service.list(tenant(request, this.authRequired));
14775
+ return reply.send({ success: true, data: result.bundles, errors: result.errors });
14776
+ } catch (error) {
14777
+ return sendError(reply, error);
14778
+ }
14779
+ }
14780
+ async getBundle(request, reply) {
14781
+ try {
14782
+ const tenantId = tenant(request, this.authRequired);
14783
+ const parsed = bundleParamsSchema.safeParse(request.params);
14784
+ if (!parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid capability bundle ID" });
14785
+ return reply.send({ success: true, data: await this.service.get(tenantId, parsed.data.bundleId) });
14786
+ } catch (error) {
14787
+ return sendError(reply, error);
14788
+ }
14789
+ }
14790
+ async createBundle(request, reply) {
14791
+ try {
14792
+ const tenantId = tenant(request, this.authRequired);
14793
+ const parsed = createSchema.safeParse(request.body);
14794
+ if (!parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid capability bundle body" });
14795
+ return reply.status(201).send({ success: true, data: await this.service.create(tenantId, parsed.data) });
14796
+ } catch (error) {
14797
+ return sendError(reply, error);
14798
+ }
14799
+ }
14800
+ async updateBundle(request, reply) {
14801
+ try {
14802
+ const tenantId = tenant(request, this.authRequired);
14803
+ const params = bundleParamsSchema.safeParse(request.params);
14804
+ const parsed = updateSchema.safeParse(request.body);
14805
+ if (!params.success || !parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid capability bundle request" });
14806
+ return reply.send({ success: true, data: await this.service.update(tenantId, params.data.bundleId, parsed.data) });
14807
+ } catch (error) {
14808
+ return sendError(reply, error);
14809
+ }
14810
+ }
14811
+ async deleteBundle(request, reply) {
14812
+ try {
14813
+ const tenantId = tenant(request, this.authRequired);
14814
+ const parsed = bundleParamsSchema.safeParse(request.params);
14815
+ if (!parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid capability bundle ID" });
14816
+ await this.service.remove(tenantId, parsed.data.bundleId);
14817
+ return reply.send({ success: true, data: null });
14818
+ } catch (error) {
14819
+ return sendError(reply, error);
14820
+ }
14821
+ }
14822
+ async updateProjectBundles(request, reply) {
14823
+ try {
14824
+ const tenantId = tenant(request, this.authRequired);
14825
+ const parsed = projectSchema.safeParse(request.body);
14826
+ if (!parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid project capability bundle body" });
14827
+ const result = await this.service.project(tenantId, request.params.projectId, parsed.data.bundleIds, true, parsed.data.expectedRevisions);
14828
+ return reply.send({ success: true, data: { project: result.project, persistedBundleIds: result.persistedBundleIds, bundles: result.bundles, preview: result.preview } });
14829
+ } catch (error) {
14830
+ return sendError(reply, error);
14831
+ }
14832
+ }
14833
+ async getProjectBundles(request, reply) {
14834
+ try {
14835
+ const result = await this.service.getProjectBundles(tenant(request, this.authRequired), request.params.projectId);
14836
+ if (result.preview.errors.some((issue2) => issue2.code === "CAPABILITY_BUNDLE_CREDENTIALS_FORBIDDEN")) return reply.status(400).send({ success: false, code: "INVALID_BUNDLE_CONFIG", message: "Capability bundle record is invalid" });
14837
+ return reply.send({ success: true, data: { project: result.project, persistedBundleIds: result.persistedBundleIds, bundles: result.bundles, preview: result.preview } });
14838
+ } catch (error) {
14839
+ return sendError(reply, error);
14840
+ }
14841
+ }
14842
+ async getProjectPreview(request, reply) {
14843
+ try {
14844
+ const preview = await this.service.previewProject(tenant(request, this.authRequired), request.params.projectId);
14845
+ return reply.send({ success: true, data: preview });
14846
+ } catch (error) {
14847
+ return sendError(reply, error);
14848
+ }
14849
+ }
14850
+ async postProjectPreview(request, reply) {
14851
+ try {
14852
+ const tenantId = tenant(request, this.authRequired);
14853
+ const parsed = projectSchema.safeParse(request.body);
14854
+ if (!parsed.success) return reply.status(400).send({ success: false, code: "INVALID_INPUT", message: "Invalid project capability bundle body" });
14855
+ const result = await this.service.project(tenantId, request.params.projectId, parsed.data.bundleIds, false);
14856
+ return reply.send({ success: true, data: result.preview });
14857
+ } catch (error) {
14858
+ return sendError(reply, error);
14859
+ }
14860
+ }
14861
+ };
14862
+ function registerCapabilityBundleRoutes(app2, controller) {
14863
+ app2.get("/api/capability-bundles", controller.listBundles.bind(controller));
14864
+ app2.post("/api/capability-bundles", controller.createBundle.bind(controller));
14865
+ app2.get("/api/capability-bundles/:bundleId", controller.getBundle.bind(controller));
14866
+ app2.put("/api/capability-bundles/:bundleId", controller.updateBundle.bind(controller));
14867
+ app2.delete("/api/capability-bundles/:bundleId", controller.deleteBundle.bind(controller));
14868
+ app2.get("/api/projects/:projectId/capability-bundles", controller.getProjectBundles.bind(controller));
14869
+ app2.put("/api/projects/:projectId/capability-bundles", controller.updateProjectBundles.bind(controller));
14870
+ app2.get("/api/projects/:projectId/capability-preview", controller.getProjectPreview.bind(controller));
14871
+ app2.post("/api/projects/:projectId/capability-preview", controller.postProjectPreview.bind(controller));
14872
+ }
14873
+
14874
+ // src/routes/index.ts
14420
14875
  var registerLatticeRoutes = (app2, channelDeps) => {
14421
- const webAppStore = (0, import_core41.getStoreLattice)("default", "agentWebApp").store;
14422
- const assistantStore = (0, import_core41.getStoreLattice)("default", "assistant").store;
14423
- const projectStore = (0, import_core41.getStoreLattice)("default", "project").store;
14876
+ const webAppStore = (0, import_core42.getStoreLattice)("default", "agentWebApp").store;
14877
+ const assistantStore = (0, import_core42.getStoreLattice)("default", "assistant").store;
14878
+ const projectStore = (0, import_core42.getStoreLattice)("default", "project").store;
14879
+ registerCapabilityBundleRoutes(app2, new CapabilityBundleController({
14880
+ bundleStore: (0, import_core42.getStoreLattice)("default", "capabilityBundle").store,
14881
+ projectStore
14882
+ }, { authRequired: process.env.AUTH_REQUIRED === "true" }));
14424
14883
  registerAgentWebAppRoutes(app2, {
14425
14884
  service: new AgentWebAppService({
14426
14885
  webAppStore,
14427
14886
  assistantStore,
14428
14887
  projectStore,
14429
- modelRegistry: { has: (key) => import_core41.modelLatticeManager.hasLattice(key) },
14888
+ modelRegistry: { has: (key) => import_core42.modelLatticeManager.hasLattice(key) },
14430
14889
  configuredAgentResolver: createConfiguredAgentResolver({
14431
- hydrate: (tenantId) => import_core41.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId),
14432
- has: (tenantId, assistantId) => import_core41.agentLatticeManager.hasAgentLatticeWithTenant(tenantId, assistantId)
14890
+ hydrate: (tenantId) => import_core42.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId),
14891
+ has: (tenantId, assistantId) => import_core42.agentLatticeManager.hasAgentLatticeWithTenant(tenantId, assistantId)
14433
14892
  })
14434
14893
  })
14435
14894
  });
14436
14895
  registerAgentWebAppRuntimeRoutes(app2, {
14437
14896
  service: new AgentWebAppRuntimeService({
14438
14897
  webAppStore,
14439
- threadStore: (0, import_core41.getStoreLattice)("default", "thread").store,
14898
+ threadStore: (0, import_core42.getStoreLattice)("default", "thread").store,
14440
14899
  projectStore,
14441
14900
  assistantResolver: {
14442
14901
  resolve: async (tenantId, assistantId) => {
14443
14902
  const stored = await assistantStore.getAssistantById(tenantId, assistantId);
14444
14903
  if (stored) return stored;
14445
- await import_core41.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId);
14446
- const config = import_core41.agentLatticeManager.getAgentConfigWithTenant(tenantId, assistantId);
14904
+ await import_core42.agentLatticeManager.initializeStoredAssistantsForTenant(tenantId);
14905
+ const config = import_core42.agentLatticeManager.getAgentConfigWithTenant(tenantId, assistantId);
14447
14906
  return config ? { id: assistantId, name: config.name, description: config.description } : null;
14448
14907
  }
14449
14908
  },
14450
14909
  modelRegistry: {
14451
- has: (key) => import_core41.modelLatticeManager.hasLattice(key),
14910
+ has: (key) => import_core42.modelLatticeManager.hasLattice(key),
14452
14911
  label: (key) => key
14453
14912
  },
14454
14913
  messageReader: {
14455
- getCurrentMessages: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core41.agentInstanceManager.getAgent({
14914
+ getCurrentMessages: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core42.agentInstanceManager.getAgent({
14456
14915
  tenant_id: tenantId,
14457
14916
  assistant_id: assistantId,
14458
14917
  thread_id: threadId,
@@ -14461,7 +14920,7 @@ var registerLatticeRoutes = (app2, channelDeps) => {
14461
14920
  }).getCurrentMessages()
14462
14921
  },
14463
14922
  agentResolver: {
14464
- getAgent: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core41.agentInstanceManager.getAgent({
14923
+ getAgent: ({ tenantId, assistantId, threadId, workspaceId, projectId }) => import_core42.agentInstanceManager.getAgent({
14465
14924
  tenant_id: tenantId,
14466
14925
  assistant_id: assistantId,
14467
14926
  thread_id: threadId,
@@ -14479,8 +14938,8 @@ var registerLatticeRoutes = (app2, channelDeps) => {
14479
14938
  if (webApp.tenantId !== preview.tenantId) return false;
14480
14939
  const assistant = await assistantStore.getAssistantById(preview.tenantId, webApp.assistantId);
14481
14940
  if (assistant) return !assistant.ownerUserId || assistant.ownerUserId === preview.userId;
14482
- await import_core41.agentLatticeManager.initializeStoredAssistantsForTenant(preview.tenantId);
14483
- return import_core41.agentLatticeManager.hasAgentLatticeWithTenant(preview.tenantId, webApp.assistantId);
14941
+ await import_core42.agentLatticeManager.initializeStoredAssistantsForTenant(preview.tenantId);
14942
+ return import_core42.agentLatticeManager.hasAgentLatticeWithTenant(preview.tenantId, webApp.assistantId);
14484
14943
  }
14485
14944
  })
14486
14945
  });
@@ -14780,12 +15239,12 @@ function registerResourceRoutes(app2, controller) {
14780
15239
  }
14781
15240
 
14782
15241
  // src/export_registrations/index.ts
14783
- var import_core52 = require("@axiom-lattice/core");
15242
+ var import_core53 = require("@axiom-lattice/core");
14784
15243
 
14785
15244
  // src/export_registrations/skill.registration.ts
14786
- var import_core42 = require("@axiom-lattice/core");
15245
+ var import_core43 = require("@axiom-lattice/core");
14787
15246
  function getStore2(context) {
14788
- return new import_core42.SandboxSkillStore({
15247
+ return new import_core43.SandboxSkillStore({
14789
15248
  workspaceId: context?.workspaceId,
14790
15249
  projectId: context?.projectId
14791
15250
  });
@@ -14803,7 +15262,7 @@ var skillRegistration = {
14803
15262
  async listForExport(tenantId, context) {
14804
15263
  const store2 = getStore2(context);
14805
15264
  const skills = await store2.getAllSkills(tenantId, toStoreContext(context));
14806
- return skills.filter((s) => !(0, import_core42.isBuiltInSkill)(s.id)).map((s) => ({
15265
+ return skills.filter((s) => !(0, import_core43.isBuiltInSkill)(s.id)).map((s) => ({
14807
15266
  _exportId: "",
14808
15267
  data: {
14809
15268
  id: s.id,
@@ -14868,7 +15327,7 @@ var skillRegistration = {
14868
15327
  const insertions = [];
14869
15328
  for (const entity of entities) {
14870
15329
  const id = entity.data.id;
14871
- if ((0, import_core42.isBuiltInSkill)(id)) continue;
15330
+ if ((0, import_core43.isBuiltInSkill)(id)) continue;
14872
15331
  if (existingIds.has(id)) {
14873
15332
  conflicts.push({
14874
15333
  _exportId: entity._exportId,
@@ -14927,9 +15386,9 @@ var skillRegistration = {
14927
15386
  };
14928
15387
 
14929
15388
  // src/export_registrations/agent.registration.ts
14930
- var import_core43 = require("@axiom-lattice/core");
15389
+ var import_core44 = require("@axiom-lattice/core");
14931
15390
  function getStore3() {
14932
- return (0, import_core43.getStoreLattice)("default", "assistant").store;
15391
+ return (0, import_core44.getStoreLattice)("default", "assistant").store;
14933
15392
  }
14934
15393
  var agentRegistration = {
14935
15394
  entityType: "agent",
@@ -15009,9 +15468,9 @@ var agentRegistration = {
15009
15468
  };
15010
15469
 
15011
15470
  // src/export_registrations/database-config.registration.ts
15012
- var import_core44 = require("@axiom-lattice/core");
15471
+ var import_core45 = require("@axiom-lattice/core");
15013
15472
  function getStore4() {
15014
- return (0, import_core44.getStoreLattice)("default", "database").store;
15473
+ return (0, import_core45.getStoreLattice)("default", "database").store;
15015
15474
  }
15016
15475
  var databaseConfigRegistration = {
15017
15476
  entityType: "database_config",
@@ -15091,9 +15550,9 @@ var databaseConfigRegistration = {
15091
15550
  };
15092
15551
 
15093
15552
  // src/export_registrations/metrics-config.registration.ts
15094
- var import_core45 = require("@axiom-lattice/core");
15553
+ var import_core46 = require("@axiom-lattice/core");
15095
15554
  function getStore5() {
15096
- return (0, import_core45.getStoreLattice)("default", "metrics").store;
15555
+ return (0, import_core46.getStoreLattice)("default", "metrics").store;
15097
15556
  }
15098
15557
  var metricsConfigRegistration = {
15099
15558
  entityType: "metrics_config",
@@ -15173,9 +15632,9 @@ var metricsConfigRegistration = {
15173
15632
  };
15174
15633
 
15175
15634
  // src/export_registrations/mcp-config.registration.ts
15176
- var import_core46 = require("@axiom-lattice/core");
15635
+ var import_core47 = require("@axiom-lattice/core");
15177
15636
  function getStore6() {
15178
- return (0, import_core46.getStoreLattice)("default", "mcp").store;
15637
+ return (0, import_core47.getStoreLattice)("default", "mcp").store;
15179
15638
  }
15180
15639
  var mcpConfigRegistration = {
15181
15640
  entityType: "mcp_config",
@@ -15258,9 +15717,9 @@ var mcpConfigRegistration = {
15258
15717
  };
15259
15718
 
15260
15719
  // src/export_registrations/connection.registration.ts
15261
- var import_core47 = require("@axiom-lattice/core");
15720
+ var import_core48 = require("@axiom-lattice/core");
15262
15721
  function getStore7() {
15263
- return (0, import_core47.getStoreLattice)("default", "connection").store;
15722
+ return (0, import_core48.getStoreLattice)("default", "connection").store;
15264
15723
  }
15265
15724
  async function listAllConnections(tenantId) {
15266
15725
  const store2 = getStore7();
@@ -15342,9 +15801,9 @@ var connectionRegistration = {
15342
15801
  };
15343
15802
 
15344
15803
  // src/export_registrations/collection.registration.ts
15345
- var import_core48 = require("@axiom-lattice/core");
15804
+ var import_core49 = require("@axiom-lattice/core");
15346
15805
  function getStore8() {
15347
- return (0, import_core48.getStoreLattice)("default", "collection").store;
15806
+ return (0, import_core49.getStoreLattice)("default", "collection").store;
15348
15807
  }
15349
15808
  var collectionRegistration = {
15350
15809
  entityType: "collection",
@@ -15415,11 +15874,11 @@ var collectionRegistration = {
15415
15874
  };
15416
15875
 
15417
15876
  // src/export_registrations/channel-installation.registration.ts
15418
- var import_core49 = require("@axiom-lattice/core");
15877
+ var import_core50 = require("@axiom-lattice/core");
15419
15878
  var import_crypto10 = require("crypto");
15420
15879
  var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
15421
15880
  function getStore9() {
15422
- return (0, import_core49.getStoreLattice)("default", "channelInstallation").store;
15881
+ return (0, import_core50.getStoreLattice)("default", "channelInstallation").store;
15423
15882
  }
15424
15883
  var channelInstallationRegistration = {
15425
15884
  entityType: "channel_installation",
@@ -15518,9 +15977,9 @@ var channelInstallationRegistration = {
15518
15977
  };
15519
15978
 
15520
15979
  // src/export_registrations/menu.registration.ts
15521
- var import_core50 = require("@axiom-lattice/core");
15980
+ var import_core51 = require("@axiom-lattice/core");
15522
15981
  function getStore10() {
15523
- return (0, import_core50.getStoreLattice)("default", "menu").store;
15982
+ return (0, import_core51.getStoreLattice)("default", "menu").store;
15524
15983
  }
15525
15984
  var menuRegistration = {
15526
15985
  entityType: "menu",
@@ -15598,9 +16057,9 @@ var menuRegistration = {
15598
16057
  };
15599
16058
 
15600
16059
  // src/export_registrations/eval.registration.ts
15601
- var import_core51 = require("@axiom-lattice/core");
16060
+ var import_core52 = require("@axiom-lattice/core");
15602
16061
  function getStore11() {
15603
- return (0, import_core51.getStoreLattice)("default", "eval").store;
16062
+ return (0, import_core52.getStoreLattice)("default", "eval").store;
15604
16063
  }
15605
16064
  var evalRegistration = {
15606
16065
  entityType: "eval",
@@ -15926,7 +16385,7 @@ var evalRegistration = {
15926
16385
 
15927
16386
  // src/export_registrations/index.ts
15928
16387
  function registerAllBuiltinEntities() {
15929
- const registry = import_core52.ExportableEntityRegistry.getInstance();
16388
+ const registry = import_core53.ExportableEntityRegistry.getInstance();
15930
16389
  registry.register(skillRegistration);
15931
16390
  registry.register(agentRegistration);
15932
16391
  registry.register(databaseConfigRegistration);
@@ -15940,7 +16399,7 @@ function registerAllBuiltinEntities() {
15940
16399
  }
15941
16400
 
15942
16401
  // src/router/MessageRouter.ts
15943
- var import_core53 = require("@axiom-lattice/core");
16402
+ var import_core54 = require("@axiom-lattice/core");
15944
16403
  var import_crypto11 = require("crypto");
15945
16404
  var BindingNotFoundError = class extends Error {
15946
16405
  constructor(message) {
@@ -16110,7 +16569,7 @@ var MessageRouter = class {
16110
16569
  channel: message.channel,
16111
16570
  adapterChannel: adapter.channel
16112
16571
  }, "Thread resolved by adapter strategy");
16113
- const threadStore = (0, import_core53.getStoreLattice)("default", "thread").store;
16572
+ const threadStore = (0, import_core54.getStoreLattice)("default", "thread").store;
16114
16573
  try {
16115
16574
  await threadStore.createThread(
16116
16575
  tenantId,
@@ -16147,7 +16606,7 @@ var MessageRouter = class {
16147
16606
  }
16148
16607
  }
16149
16608
  if (!threadId) {
16150
- const threadStore = (0, import_core53.getStoreLattice)("default", "thread").store;
16609
+ const threadStore = (0, import_core54.getStoreLattice)("default", "thread").store;
16151
16610
  const newThreadId = (0, import_crypto11.randomUUID)();
16152
16611
  console.log({
16153
16612
  event: "dispatch:thread:create",
@@ -16187,7 +16646,7 @@ var MessageRouter = class {
16187
16646
  senderId: message.sender.id,
16188
16647
  contentLength: message.content.text.length
16189
16648
  }, "Dispatching to agent");
16190
- const agent = import_core53.agentInstanceManager.getAgent({
16649
+ const agent = import_core54.agentInstanceManager.getAgent({
16191
16650
  tenant_id: tenantId,
16192
16651
  assistant_id: agentId,
16193
16652
  thread_id: threadId,
@@ -16395,13 +16854,13 @@ function createRateLimitMiddleware(maxRequests = 10, windowMs = 60 * 1e3, maxEnt
16395
16854
 
16396
16855
  // src/router/middlewares/auditLogger.ts
16397
16856
  init_Logger();
16398
- var logger3 = new Logger({ serviceName: "lattice/gateway/audit" });
16857
+ var logger4 = new Logger({ serviceName: "lattice/gateway/audit" });
16399
16858
  function createAuditLoggerMiddleware() {
16400
16859
  return async (ctx, next) => {
16401
16860
  const start2 = Date.now();
16402
16861
  try {
16403
16862
  await next();
16404
- logger3.info("message routed", {
16863
+ logger4.info("message routed", {
16405
16864
  event: "message:routed",
16406
16865
  channel: ctx.inboundMessage.channel,
16407
16866
  senderId: ctx.inboundMessage.sender.id,
@@ -16411,7 +16870,7 @@ function createAuditLoggerMiddleware() {
16411
16870
  status: "success"
16412
16871
  });
16413
16872
  } catch (error) {
16414
- logger3.error(
16873
+ logger4.error(
16415
16874
  error instanceof Error ? error.message : String(error),
16416
16875
  {
16417
16876
  event: "message:error",
@@ -16427,7 +16886,7 @@ function createAuditLoggerMiddleware() {
16427
16886
  }
16428
16887
 
16429
16888
  // src/index.ts
16430
- var import_core58 = require("@axiom-lattice/core");
16889
+ var import_core59 = require("@axiom-lattice/core");
16431
16890
 
16432
16891
  // src/swagger.ts
16433
16892
  var import_swagger = __toESM(require("@fastify/swagger"));
@@ -16492,7 +16951,7 @@ var configureSwagger = async (app2, customSwaggerConfig, customSwaggerUiConfig)
16492
16951
  };
16493
16952
 
16494
16953
  // src/services/agent_task_consumer.ts
16495
- var import_core54 = require("@axiom-lattice/core");
16954
+ var import_core55 = require("@axiom-lattice/core");
16496
16955
  var handleAgentTask = async (taskRequest, retryCount = 0) => {
16497
16956
  const {
16498
16957
  assistant_id,
@@ -16510,17 +16969,17 @@ var handleAgentTask = async (taskRequest, retryCount = 0) => {
16510
16969
  console.log(
16511
16970
  `\u5F00\u59CB\u5904\u7406\u4EFB\u52A1 [assistant_id: ${assistant_id}, thread_id: ${thread_id}]`
16512
16971
  );
16513
- const agent = import_core54.agentInstanceManager.getAgent({ assistant_id, thread_id, tenant_id, workspace_id: runConfig?.workspaceId, project_id: runConfig?.projectId, custom_run_config: runConfig });
16514
- await agent.addMessage({ input, command, custom_run_config: runConfig }, import_core54.QueueMode.STEER);
16972
+ const agent = import_core55.agentInstanceManager.getAgent({ assistant_id, thread_id, tenant_id, workspace_id: runConfig?.workspaceId, project_id: runConfig?.projectId, custom_run_config: runConfig });
16973
+ await agent.addMessage({ input, command, custom_run_config: runConfig }, import_core55.QueueMode.STEER);
16515
16974
  if (callback_event) {
16516
16975
  agent.subscribeOnce("message:completed", (evt) => {
16517
- import_core54.eventBus.publish(callback_event, {
16976
+ import_core55.eventBus.publish(callback_event, {
16518
16977
  success: true,
16519
16978
  state: evt.state
16520
16979
  });
16521
16980
  if (main_thread_id && main_tenant_id) {
16522
16981
  try {
16523
- const mainAgent = import_core54.agentInstanceManager.getAgent({
16982
+ const mainAgent = import_core55.agentInstanceManager.getAgent({
16524
16983
  assistant_id: main_assistant_id ?? assistant_id,
16525
16984
  thread_id: main_thread_id,
16526
16985
  tenant_id: main_tenant_id,
@@ -16550,7 +17009,7 @@ ${summary}`
16550
17009
  }
16551
17010
  });
16552
17011
  agent.subscribeOnce("message:interrupted", (evt) => {
16553
- import_core54.eventBus.publish(callback_event, {
17012
+ import_core55.eventBus.publish(callback_event, {
16554
17013
  success: true,
16555
17014
  state: evt.state
16556
17015
  });
@@ -16573,7 +17032,7 @@ ${summary}`
16573
17032
  return handleAgentTask(taskRequest, nextRetryCount);
16574
17033
  }
16575
17034
  if (callback_event) {
16576
- import_core54.eventBus.publish(callback_event, {
17035
+ import_core55.eventBus.publish(callback_event, {
16577
17036
  success: false,
16578
17037
  error: error instanceof Error ? error.message : String(error)
16579
17038
  });
@@ -16610,7 +17069,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
16610
17069
  * 初始化事件监听和队列轮询
16611
17070
  */
16612
17071
  initialize() {
16613
- import_core54.eventBus.subscribe(import_core54.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
17072
+ import_core55.eventBus.subscribe(import_core55.AGENT_TASK_EVENT, this.trigger_agent_task.bind(this));
16614
17073
  this.startPollingQueue();
16615
17074
  console.log("Agent\u4EFB\u52A1\u6D88\u8D39\u8005\u5DF2\u542F\u52A8\u5E76\u76D1\u542C\u4EFB\u52A1\u4E8B\u4EF6\u548C\u961F\u5217");
16616
17075
  }
@@ -16729,7 +17188,7 @@ var _AgentTaskConsumer = class _AgentTaskConsumer {
16729
17188
  handleAgentTask(taskRequest).catch((error) => {
16730
17189
  console.error("\u5904\u7406Agent\u4EFB\u52A1\u65F6\u53D1\u751F\u672A\u6355\u83B7\u7684\u9519\u8BEF:", error);
16731
17190
  if (taskRequest.callback_event) {
16732
- import_core54.eventBus.publish(taskRequest.callback_event, {
17191
+ import_core55.eventBus.publish(taskRequest.callback_event, {
16733
17192
  success: false,
16734
17193
  error: error instanceof Error ? error.message : String(error)
16735
17194
  });
@@ -16744,7 +17203,7 @@ _AgentTaskConsumer.agent_run_endpoint = "http://localhost:4001/api/runs";
16744
17203
  var AgentTaskConsumer = _AgentTaskConsumer;
16745
17204
 
16746
17205
  // src/index.ts
16747
- var import_core59 = require("@axiom-lattice/core");
17206
+ var import_core60 = require("@axiom-lattice/core");
16748
17207
  var import_protocols9 = require("@axiom-lattice/protocols");
16749
17208
  var import_meta = {};
16750
17209
  process.on("unhandledRejection", (reason, promise) => {
@@ -16758,13 +17217,13 @@ var DEFAULT_LOGGER_CONFIG = {
16758
17217
  loggerName: "lattice/gateway"
16759
17218
  };
16760
17219
  var loggerLattice = initializeLogger(DEFAULT_LOGGER_CONFIG);
16761
- var logger5 = loggerLattice.client;
17220
+ var logger6 = loggerLattice.client;
16762
17221
  function initializeLogger(config) {
16763
- if (import_core59.loggerLatticeManager.hasLattice("default")) {
16764
- import_core59.loggerLatticeManager.removeLattice("default");
17222
+ if (import_core60.loggerLatticeManager.hasLattice("default")) {
17223
+ import_core60.loggerLatticeManager.removeLattice("default");
16765
17224
  }
16766
- (0, import_core59.registerLoggerLattice)("default", config);
16767
- return (0, import_core59.getLoggerLattice)("default");
17225
+ (0, import_core60.registerLoggerLattice)("default", config);
17226
+ return (0, import_core60.getLoggerLattice)("default");
16768
17227
  }
16769
17228
  var app = (0, import_fastify.default)({
16770
17229
  logger: false,
@@ -16791,7 +17250,9 @@ var getHeaderValue = (header) => {
16791
17250
  var authRequired = process.env.AUTH_REQUIRED === "true";
16792
17251
  registerConsoleAuthHook(app, { authRequired });
16793
17252
  app.addHook("onRequest", (request, reply, done) => {
16794
- if (!request.headers["x-project-id"]) {
17253
+ const requestPath = request.url.split("?", 1)[0];
17254
+ const isAgentRunRequest = requestPath === "/api/runs" || requestPath === "/api/resume_stream" || requestPath.includes("/threads/") && requestPath.endsWith("/recover");
17255
+ if (!request.headers["x-project-id"] && !isAgentRunRequest) {
16795
17256
  request.headers["x-project-id"] = "default";
16796
17257
  }
16797
17258
  done();
@@ -16841,7 +17302,7 @@ app.setErrorHandler((error, request, reply) => {
16841
17302
  "x-request-id": getHeaderValue(request.headers["x-request-id"]),
16842
17303
  "x-user-id": getHeaderValue(request.headers["x-user-id"])
16843
17304
  };
16844
- logger5.error(
17305
+ logger6.error(
16845
17306
  `\u8BF7\u6C42\u9519\u8BEF: ${request.method} ${request.url} error:${error.message}`,
16846
17307
  {
16847
17308
  ...context,
@@ -16857,7 +17318,7 @@ app.setErrorHandler((error, request, reply) => {
16857
17318
  });
16858
17319
  function getConfiguredSandboxProvider() {
16859
17320
  const sandboxProviderType = process.env.SANDBOX_PROVIDER_TYPE || "microsandbox-remote";
16860
- return (0, import_core59.createSandboxProvider)({
17321
+ return (0, import_core60.createSandboxProvider)({
16861
17322
  type: sandboxProviderType,
16862
17323
  remoteBaseURL: process.env.SANDBOX_BASE_URL,
16863
17324
  microsandboxServiceBaseURL: process.env.MICROSANDBOX_SERVICE_BASE_URL,
@@ -16873,37 +17334,37 @@ function getConfiguredSandboxProvider() {
16873
17334
  }
16874
17335
  async function restoreMcpConnections() {
16875
17336
  try {
16876
- const storeLattice = (0, import_core59.getStoreLattice)("default", "mcp");
17337
+ const storeLattice = (0, import_core60.getStoreLattice)("default", "mcp");
16877
17338
  const store2 = storeLattice.store;
16878
17339
  if (!store2) {
16879
- logger5.info("MCP store not configured, skipping connection restoration");
17340
+ logger6.info("MCP store not configured, skipping connection restoration");
16880
17341
  return;
16881
17342
  }
16882
17343
  const configs = await store2.getAllConfigs("default");
16883
17344
  const connectedConfigs = configs.filter((c2) => c2.status === "connected");
16884
17345
  if (connectedConfigs.length === 0) return;
16885
- logger5.info(`Restoring ${connectedConfigs.length} MCP server connections...`);
17346
+ logger6.info(`Restoring ${connectedConfigs.length} MCP server connections...`);
16886
17347
  const { convertToConnection: convertToConnection2 } = await Promise.resolve().then(() => (init_mcp_configs(), mcp_configs_exports));
16887
17348
  for (const config of connectedConfigs) {
16888
17349
  try {
16889
17350
  const connection = convertToConnection2(config.config);
16890
- import_core59.mcpManager.addServer(config.key, connection);
17351
+ import_core60.mcpManager.addServer(config.key, connection);
16891
17352
  } catch (err) {
16892
- logger5.warn(`Failed to prepare MCP server "${config.key}" for restoration`, { error: err });
17353
+ logger6.warn(`Failed to prepare MCP server "${config.key}" for restoration`, { error: err });
16893
17354
  }
16894
17355
  }
16895
- await import_core59.mcpManager.connect();
17356
+ await import_core60.mcpManager.connect();
16896
17357
  for (const config of connectedConfigs) {
16897
17358
  try {
16898
- await import_core59.mcpManager.registerToolsToToolLattice(config.key, config.selectedTools);
16899
- logger5.info(`MCP server "${config.key}" restored with ${config.selectedTools.length} tools`);
17359
+ await import_core60.mcpManager.registerToolsToToolLattice(config.key, config.selectedTools);
17360
+ logger6.info(`MCP server "${config.key}" restored with ${config.selectedTools.length} tools`);
16900
17361
  } catch (err) {
16901
- logger5.warn(`Failed to register tools for MCP server "${config.key}"`, { error: err });
17362
+ logger6.warn(`Failed to register tools for MCP server "${config.key}"`, { error: err });
16902
17363
  }
16903
17364
  }
16904
- logger5.info(`MCP connection restoration complete: ${connectedConfigs.length} servers`);
17365
+ logger6.info(`MCP connection restoration complete: ${connectedConfigs.length} servers`);
16905
17366
  } catch (err) {
16906
- logger5.error("MCP connection restoration failed", { error: err });
17367
+ logger6.error("MCP connection restoration failed", { error: err });
16907
17368
  }
16908
17369
  }
16909
17370
  var start = async (config) => {
@@ -16916,7 +17377,7 @@ var start = async (config) => {
16916
17377
  file: config.loggerConfig.file || DEFAULT_LOGGER_CONFIG.file
16917
17378
  };
16918
17379
  loggerLattice = initializeLogger(loggerConfig);
16919
- logger5 = loggerLattice.client;
17380
+ logger6 = loggerLattice.client;
16920
17381
  }
16921
17382
  app.decorate("loggerLattice", loggerLattice);
16922
17383
  let channelDeps;
@@ -16928,7 +17389,7 @@ var start = async (config) => {
16928
17389
  const { getStoreLattice: getStore12 } = await import("@axiom-lattice/core");
16929
17390
  const bindingStore = getStore12("default", "channelBinding").store;
16930
17391
  const installationStore = getStore12("default", "channelInstallation").store;
16931
- (0, import_core58.setBindingRegistry)(bindingStore);
17392
+ (0, import_core59.setBindingRegistry)(bindingStore);
16932
17393
  const router = new MessageRouter({
16933
17394
  middlewares: [
16934
17395
  createDeduplicationMiddleware(),
@@ -16941,15 +17402,15 @@ var start = async (config) => {
16941
17402
  });
16942
17403
  channelDeps = { router, installationStore };
16943
17404
  } catch (err) {
16944
- logger5.warn("Channel infrastructure unavailable", {
17405
+ logger6.warn("Channel infrastructure unavailable", {
16945
17406
  error: err instanceof Error ? err.message : String(err)
16946
17407
  });
16947
17408
  }
16948
- (0, import_core58.setEvalRunService)(evalRunner);
17409
+ (0, import_core59.setEvalRunService)(evalRunner);
16949
17410
  try {
16950
- const menuStore = (0, import_core59.getStoreLattice)("default", "menu").store;
16951
- (0, import_core58.setMenuRegistry)(menuStore);
16952
- logger5.info("Menu registry initialized");
17411
+ const menuStore = (0, import_core60.getStoreLattice)("default", "menu").store;
17412
+ (0, import_core59.setMenuRegistry)(menuStore);
17413
+ logger6.info("Menu registry initialized");
16953
17414
  } catch {
16954
17415
  }
16955
17416
  registerAllBuiltinEntities();
@@ -16961,10 +17422,10 @@ var start = async (config) => {
16961
17422
  const { A2AAuthService: A2AAuthService2, parseEnvKeys: parseEnvKeys2 } = await Promise.resolve().then(() => (init_A2AAuthService(), A2AAuthService_exports));
16962
17423
  const { registerA2AStandardRoutes: registerA2AStandardRoutes2 } = await Promise.resolve().then(() => (init_a2a_standard(), a2a_standard_exports));
16963
17424
  const a2a = await Promise.resolve().then(() => (init_a2a(), a2a_exports));
16964
- const a2aKeyStore = (0, import_core59.getStoreLattice)("default", "a2aApiKey").store;
16965
- const assistantStore = (0, import_core59.getStoreLattice)("default", "assistant").store;
16966
- const projectStore = (0, import_core59.getStoreLattice)("default", "project").store;
16967
- const taskStore = (0, import_core59.getStoreLattice)("default", "task").store;
17425
+ const a2aKeyStore = (0, import_core60.getStoreLattice)("default", "a2aApiKey").store;
17426
+ const assistantStore = (0, import_core60.getStoreLattice)("default", "assistant").store;
17427
+ const projectStore = (0, import_core60.getStoreLattice)("default", "project").store;
17428
+ const taskStore = (0, import_core60.getStoreLattice)("default", "task").store;
16968
17429
  const authService = new A2AAuthService2({
16969
17430
  keyStore: a2aKeyStore,
16970
17431
  assistantStore,
@@ -16982,30 +17443,30 @@ var start = async (config) => {
16982
17443
  getProjectStore: () => projectStore
16983
17444
  });
16984
17445
  a2a.registerA2ARoutes(app);
16985
- logger5.info("A2A standard routes registered");
17446
+ logger6.info("A2A standard routes registered");
16986
17447
  } catch (err) {
16987
- logger5.warn("A2A standard routes unavailable", {
17448
+ logger6.warn("A2A standard routes unavailable", {
16988
17449
  error: err instanceof Error ? err.message : String(err)
16989
17450
  });
16990
17451
  }
16991
- if (!import_core59.sandboxLatticeManager.hasLattice("default")) {
16992
- import_core59.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
16993
- logger5.info("Registered sandbox manager from env configuration");
17452
+ if (!import_core60.sandboxLatticeManager.hasLattice("default")) {
17453
+ import_core60.sandboxLatticeManager.registerLattice("default", getConfiguredSandboxProvider());
17454
+ logger6.info("Registered sandbox manager from env configuration");
16994
17455
  }
16995
17456
  try {
16996
17457
  const { ResourceController: ResourceController2 } = await Promise.resolve().then(() => (init_resources(), resources_exports));
16997
- const sharedResourceStore = (0, import_core59.getStoreLattice)("default", "sharedResource").store;
16998
- const cache = new import_core59.TokenCache();
17458
+ const sharedResourceStore = (0, import_core60.getStoreLattice)("default", "sharedResource").store;
17459
+ const cache = new import_core60.TokenCache();
16999
17460
  const resourceController = new ResourceController2({
17000
17461
  store: sharedResourceStore,
17001
- sandboxManager: import_core59.sandboxLatticeManager,
17462
+ sandboxManager: import_core60.sandboxLatticeManager,
17002
17463
  cache,
17003
- logger: logger5
17464
+ logger: logger6
17004
17465
  });
17005
17466
  registerResourceRoutes(app, resourceController);
17006
- logger5.info("Resource share routes registered");
17467
+ logger6.info("Resource share routes registered");
17007
17468
  } catch (err) {
17008
- logger5.warn("Resource share infrastructure unavailable", {
17469
+ logger6.warn("Resource share infrastructure unavailable", {
17009
17470
  error: err instanceof Error ? err.message : String(err)
17010
17471
  });
17011
17472
  }
@@ -17017,14 +17478,14 @@ var start = async (config) => {
17017
17478
  { deps: { router: channelDeps.router } }
17018
17479
  );
17019
17480
  } catch (err) {
17020
- logger5.error("Failed to start channel connections", {
17481
+ logger6.error("Failed to start channel connections", {
17021
17482
  error: err instanceof Error ? err.message : String(err)
17022
17483
  });
17023
17484
  }
17024
17485
  }
17025
17486
  const target_port = config?.port || Number(process.env.PORT) || 4001;
17026
17487
  await app.listen({ port: target_port, host: "0.0.0.0" });
17027
- logger5.info(`Lattice Gateway is running on port: ${target_port}`);
17488
+ logger6.info(`Lattice Gateway is running on port: ${target_port}`);
17028
17489
  const queueServiceConfig = config?.queueServiceConfig;
17029
17490
  if (queueServiceConfig) {
17030
17491
  setQueueServiceType(queueServiceConfig.type);
@@ -17034,17 +17495,17 @@ var start = async (config) => {
17034
17495
  }
17035
17496
  }
17036
17497
  if (process.env.AXIOM_RESTORE_PENDING_ON_STARTUP === "true") {
17037
- import_core59.agentInstanceManager.restore().then((stats) => {
17038
- logger5.info(`Agent recovery complete: ${stats.restored} threads restored, ${stats.errors} errors`);
17498
+ import_core60.agentInstanceManager.restore().then((stats) => {
17499
+ logger6.info(`Agent recovery complete: ${stats.restored} threads restored, ${stats.errors} errors`);
17039
17500
  }).catch((error) => {
17040
- logger5.error("Agent recovery failed", { error });
17501
+ logger6.error("Agent recovery failed", { error });
17041
17502
  });
17042
17503
  }
17043
17504
  restoreMcpConnections().catch((error) => {
17044
- logger5.error("MCP connection restoration failed", { error });
17505
+ logger6.error("MCP connection restoration failed", { error });
17045
17506
  });
17046
17507
  } catch (err) {
17047
- logger5.error("Server start failed", { error: err });
17508
+ logger6.error("Server start failed", { error: err });
17048
17509
  process.exit(1);
17049
17510
  }
17050
17511
  };