@axiom-lattice/gateway 4.2.4 → 4.3.0

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 (28) hide show
  1. package/dist/embed/agent-chat-loader.js +1 -1
  2. package/dist/embed/{embed-page-AgentDetailSideApp-3LBCEKFU.js → embed-page-AgentDetailSideApp-7FH2JSZI.js} +1 -1
  3. package/dist/embed/{embed-page-AgentGovernanceWorkbench-K3JUQNBW.js → embed-page-AgentGovernanceWorkbench-Y5F3ZPYC.js} +1 -1
  4. package/dist/embed/{embed-page-MessageGraph-3X4ROEN6.js → embed-page-MessageGraph-ONODQPG4.js} +1 -1
  5. package/dist/embed/{embed-page-ReactChart-F6VYCIYY.js → embed-page-ReactChart-GZQSKCUG.js} +1 -1
  6. package/dist/embed/{embed-page-SkillFlow-3CF7R3CW.js → embed-page-SkillFlow-TPESM4DI.js} +1 -1
  7. package/dist/embed/{embed-page-TasksSideApp-3WRDBZU3.js → embed-page-TasksSideApp-HYKCJ356.js} +1 -1
  8. package/dist/embed/{embed-page-TeamWorkspace-6JSMZYUF.js → embed-page-TeamWorkspace-IOHS4RJV.js} +1 -1
  9. package/dist/embed/{embed-page-TopologyRuntimeView-YDFENLHH.js → embed-page-TopologyRuntimeView-QLMZ4OE7.js} +1 -1
  10. package/dist/embed/{embed-page-WorkflowAutomationView-MP5B7Q2Q.js → embed-page-WorkflowAutomationView-FJJSGY7Z.js} +1 -1
  11. package/dist/embed/{embed-page-chunk-QEYWJHEK.js → embed-page-chunk-6LL6YULZ.js} +1 -1
  12. package/dist/embed/{embed-page-chunk-UOL6CUAL.js → embed-page-chunk-D3NRIME3.js} +1 -1
  13. package/dist/embed/embed-page-chunk-EMPMOO53.js +466 -0
  14. package/dist/embed/{embed-page-chunk-GDTBDOUE.js → embed-page-chunk-FXTSVMPN.js} +89 -38
  15. package/dist/embed/embed-page-chunk-KFUAWYJ7.js +5 -0
  16. package/dist/embed/{embed-page-chunk-IRP6JSSX.js → embed-page-chunk-L7RMIQ7C.js} +9 -9
  17. package/dist/embed/{embed-page-chunk-YMJGPA3F.js → embed-page-chunk-MCUFFMAW.js} +116 -124
  18. package/dist/embed/{embed-page-chunk-PAJ5NG2Z.js → embed-page-chunk-SMQZEZYG.js} +1 -1
  19. package/dist/embed/{embed-page-chunk-FFO7CAYL.js → embed-page-chunk-VVYB3C4O.js} +1 -1
  20. package/dist/embed/{embed-page-chunk-RVXX5HKF.js → embed-page-chunk-ZTRCHYWV.js} +1 -1
  21. package/dist/embed/embed-page.js +3 -3
  22. package/dist/index.js +239 -144
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.mjs +117 -22
  25. package/dist/index.mjs.map +1 -1
  26. package/package.json +7 -7
  27. package/dist/embed/embed-page-chunk-B2E2XOH2.js +0 -467
  28. package/dist/embed/embed-page-chunk-URNZX66S.js +0 -5
package/dist/index.js CHANGED
@@ -1570,11 +1570,11 @@ function devModeDefaults() {
1570
1570
  const projectId = process.env[DEFAULT_PROJECT_ENV] || void 0;
1571
1571
  return { tenantId, projectId };
1572
1572
  }
1573
- var import_protocols30, A2AAuthError, DEFAULT_TENANT_ENV, DEFAULT_TENANT_ID, DEFAULT_PROJECT_ENV, BEARER_SCHEME_RE, A2AAuthService;
1573
+ var import_protocols31, A2AAuthError, DEFAULT_TENANT_ENV, DEFAULT_TENANT_ID, DEFAULT_PROJECT_ENV, BEARER_SCHEME_RE, A2AAuthService;
1574
1574
  var init_A2AAuthService = __esm({
1575
1575
  "src/services/a2a/A2AAuthService.ts"() {
1576
1576
  "use strict";
1577
- import_protocols30 = require("@axiom-lattice/protocols");
1577
+ import_protocols31 = require("@axiom-lattice/protocols");
1578
1578
  A2AAuthError = class extends Error {
1579
1579
  constructor(message, statusCode) {
1580
1580
  super(message);
@@ -1629,7 +1629,7 @@ var init_A2AAuthService = __esm({
1629
1629
  const entry = merged.get(token);
1630
1630
  if (!entry) return { authenticated: false };
1631
1631
  const hasExplicitGrants = Array.isArray(entry.grants) && entry.grants.length > 0;
1632
- const agentGrant = (0, import_protocols30.effectiveGrants)(entry).find((g) => g.domain === "agent");
1632
+ const agentGrant = (0, import_protocols31.effectiveGrants)(entry).find((g) => g.domain === "agent");
1633
1633
  const assistantIds = hasExplicitGrants ? agentGrant?.items ?? [] : entry.assistantIds;
1634
1634
  return {
1635
1635
  authenticated: true,
@@ -2234,13 +2234,13 @@ function assistantHasGovernedTask(assistant) {
2234
2234
  const allowedTools = taskMiddleware?.allowedTools;
2235
2235
  return !!taskMiddleware && (allowedTools === void 0 || Array.isArray(allowedTools) && (allowedTools.length === 0 || allowedTools.includes("manage_task")));
2236
2236
  }
2237
- var import_uuid11, import_core67, import_protocols31, _AxiomAgentExecutor, AxiomAgentExecutor;
2237
+ var import_uuid11, import_core67, import_protocols32, _AxiomAgentExecutor, AxiomAgentExecutor;
2238
2238
  var init_AxiomAgentExecutor = __esm({
2239
2239
  "src/services/a2a/AxiomAgentExecutor.ts"() {
2240
2240
  "use strict";
2241
2241
  import_uuid11 = require("uuid");
2242
2242
  import_core67 = require("@axiom-lattice/core");
2243
- import_protocols31 = require("@axiom-lattice/protocols");
2243
+ import_protocols32 = require("@axiom-lattice/protocols");
2244
2244
  init_a2aFileRefs();
2245
2245
  init_task_file_refs();
2246
2246
  _AxiomAgentExecutor = class _AxiomAgentExecutor {
@@ -2344,7 +2344,7 @@ ${formatFileRefsSection(inputFiles)}` : text;
2344
2344
  custom_run_config: { taskId: ctx.taskId }
2345
2345
  });
2346
2346
  const stream = agent.chunkStream(messageId, [
2347
- import_protocols31.MessageChunkTypes.MESSAGE_COMPLETED
2347
+ import_protocols32.MessageChunkTypes.MESSAGE_COMPLETED
2348
2348
  ]);
2349
2349
  let outputText = "";
2350
2350
  let interrupted = false;
@@ -2352,14 +2352,14 @@ ${formatFileRefsSection(inputFiles)}` : text;
2352
2352
  if (execution.canceled) return;
2353
2353
  const chunkType = chunk.type;
2354
2354
  const chunkText = chunk.data?.content ?? "";
2355
- if (chunkType === import_protocols31.MessageChunkTypes.INTERRUPT) {
2355
+ if (chunkType === import_protocols32.MessageChunkTypes.INTERRUPT) {
2356
2356
  interrupted = true;
2357
2357
  break;
2358
2358
  }
2359
- if (chunkType === import_protocols31.MessageChunkTypes.AI && chunkText) {
2359
+ if (chunkType === import_protocols32.MessageChunkTypes.AI && chunkText) {
2360
2360
  outputText += chunkText;
2361
2361
  }
2362
- if (chunkType === import_protocols31.MessageChunkTypes.AI || chunkType === import_protocols31.MessageChunkTypes.TOOL) {
2362
+ if (chunkType === import_protocols32.MessageChunkTypes.AI || chunkType === import_protocols32.MessageChunkTypes.TOOL) {
2363
2363
  if (chunkText) {
2364
2364
  bus.publish({
2365
2365
  kind: "status-update",
@@ -3323,11 +3323,11 @@ var init_a2a = __esm({
3323
3323
  });
3324
3324
 
3325
3325
  // src/services/open/openAuthService.ts
3326
- var import_protocols32, OpenAuthService;
3326
+ var import_protocols33, OpenAuthService;
3327
3327
  var init_openAuthService = __esm({
3328
3328
  "src/services/open/openAuthService.ts"() {
3329
3329
  "use strict";
3330
- import_protocols32 = require("@axiom-lattice/protocols");
3330
+ import_protocols33 = require("@axiom-lattice/protocols");
3331
3331
  OpenAuthService = class {
3332
3332
  constructor(keyStore) {
3333
3333
  this.keyStore = keyStore;
@@ -3341,7 +3341,7 @@ var init_openAuthService = __esm({
3341
3341
  kind: "api_key",
3342
3342
  tenantId: record.tenantId,
3343
3343
  projectId: record.projectId,
3344
- grants: (0, import_protocols32.effectiveGrants)(record)
3344
+ grants: (0, import_protocols33.effectiveGrants)(record)
3345
3345
  };
3346
3346
  }
3347
3347
  };
@@ -3349,11 +3349,11 @@ var init_openAuthService = __esm({
3349
3349
  });
3350
3350
 
3351
3351
  // src/services/open/openCredentialService.ts
3352
- var import_protocols33, OpenCredentialService;
3352
+ var import_protocols34, OpenCredentialService;
3353
3353
  var init_openCredentialService = __esm({
3354
3354
  "src/services/open/openCredentialService.ts"() {
3355
3355
  "use strict";
3356
- import_protocols33 = require("@axiom-lattice/protocols");
3356
+ import_protocols34 = require("@axiom-lattice/protocols");
3357
3357
  init_openToken();
3358
3358
  init_openAuthService();
3359
3359
  OpenCredentialService = class {
@@ -4351,7 +4351,7 @@ function registerOpenExposureRoutes(app2) {
4351
4351
  if (!record || record.tenantId !== tenantId) {
4352
4352
  return reply.status(404).send({ success: false, error: "Key not found" });
4353
4353
  }
4354
- const grants = (0, import_protocols34.effectiveGrants)(record);
4354
+ const grants = (0, import_protocols35.effectiveGrants)(record);
4355
4355
  const forwardedHost = request.headers["x-forwarded-host"];
4356
4356
  const host = (Array.isArray(forwardedHost) ? forwardedHost[0] : forwardedHost) ?? (Array.isArray(request.headers.host) ? request.headers.host[0] : request.headers.host) ?? request.hostname;
4357
4357
  const baseUrl = `${request.protocol}://${host}`;
@@ -4390,12 +4390,12 @@ function registerOpenExposureRoutes(app2) {
4390
4390
  }
4391
4391
  );
4392
4392
  }
4393
- var import_core75, import_protocols34;
4393
+ var import_core75, import_protocols35;
4394
4394
  var init_open_exposure = __esm({
4395
4395
  "src/routes/open-exposure.ts"() {
4396
4396
  "use strict";
4397
4397
  import_core75 = require("@axiom-lattice/core");
4398
- import_protocols34 = require("@axiom-lattice/protocols");
4398
+ import_protocols35 = require("@axiom-lattice/protocols");
4399
4399
  init_openLattice();
4400
4400
  init_A2AAgentCardBuilder();
4401
4401
  }
@@ -4527,8 +4527,8 @@ function createAgentProvider(deps = {}) {
4527
4527
  const stream = agent.chunkStream(messageId, [...STOP_TYPES]);
4528
4528
  for await (const chunk of stream) {
4529
4529
  const text = chunk.data?.content;
4530
- if (chunk.type === import_protocols35.MessageChunkTypes.INTERRUPT) break;
4531
- if (chunk.type === import_protocols35.MessageChunkTypes.AI && text) {
4530
+ if (chunk.type === import_protocols36.MessageChunkTypes.INTERRUPT) break;
4531
+ if (chunk.type === import_protocols36.MessageChunkTypes.AI && text) {
4532
4532
  parts.push(text);
4533
4533
  }
4534
4534
  }
@@ -4538,14 +4538,14 @@ function createAgentProvider(deps = {}) {
4538
4538
  }
4539
4539
  };
4540
4540
  }
4541
- var import_zod20, import_core76, import_protocols35, STOP_TYPES;
4541
+ var import_zod20, import_core76, import_protocols36, STOP_TYPES;
4542
4542
  var init_agentProvider = __esm({
4543
4543
  "src/services/open/providers/agentProvider.ts"() {
4544
4544
  "use strict";
4545
4545
  import_zod20 = require("zod");
4546
4546
  import_core76 = require("@axiom-lattice/core");
4547
- import_protocols35 = require("@axiom-lattice/protocols");
4548
- STOP_TYPES = [import_protocols35.MessageChunkTypes.MESSAGE_COMPLETED];
4547
+ import_protocols36 = require("@axiom-lattice/protocols");
4548
+ STOP_TYPES = [import_protocols36.MessageChunkTypes.MESSAGE_COMPLETED];
4549
4549
  }
4550
4550
  });
4551
4551
 
@@ -5081,7 +5081,7 @@ var import_path = __toESM(require("path"));
5081
5081
 
5082
5082
  // src/routes/index.ts
5083
5083
  var import_node_crypto23 = require("crypto");
5084
- var import_protocols27 = require("@axiom-lattice/protocols");
5084
+ var import_protocols28 = require("@axiom-lattice/protocols");
5085
5085
 
5086
5086
  // src/controllers/assistant.ts
5087
5087
  var import_core = require("@axiom-lattice/core");
@@ -10327,12 +10327,12 @@ var NoopRoomBindingLifecycle = class {
10327
10327
  // src/services/collaboration/WorkspacePublicRoomService.ts
10328
10328
  var import_node_crypto2 = require("crypto");
10329
10329
  var import_node_crypto3 = require("crypto");
10330
- var WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX = "workspace_public_";
10330
+ var import_protocols5 = require("@axiom-lattice/protocols");
10331
10331
  var PUBLIC_ROOM_PROJECT_NAME = "General";
10332
10332
  var PUBLIC_ROOM_PROJECT_DESCRIPTION = "Public room for everyone in the workspace";
10333
10333
  function workspacePublicRoomProjectId(tenantId, workspaceId) {
10334
10334
  const hash = (0, import_node_crypto2.createHash)("sha256").update([tenantId, workspaceId].join(":")).digest("hex");
10335
- return `${WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX}${hash}`;
10335
+ return `${import_protocols5.WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX}${hash}`;
10336
10336
  }
10337
10337
  var WorkspacePublicRoomService = class {
10338
10338
  /** Creates the service from explicitly injected stores and provisioners. */
@@ -10505,7 +10505,7 @@ function createProjectCollaborationInitializer(deps) {
10505
10505
  } catch {
10506
10506
  throw new ProjectCollaborationInitializationError("room");
10507
10507
  }
10508
- if (project.kind === "business" && deps.ensureCoordinator) {
10508
+ if ((project.kind === "business" || project.kind === "public") && deps.ensureCoordinator) {
10509
10509
  try {
10510
10510
  await deps.ensureCoordinator({
10511
10511
  tenantId,
@@ -10673,12 +10673,6 @@ var WorkspaceController = class {
10673
10673
  message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
10674
10674
  });
10675
10675
  }
10676
- if (data.kind === "public") {
10677
- return reply.status(409).send({
10678
- success: false,
10679
- error: "The public room project is managed automatically"
10680
- });
10681
- }
10682
10676
  if (user?.id && this.projectCollaboration) {
10683
10677
  try {
10684
10678
  const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: user.id });
@@ -10756,16 +10750,10 @@ var WorkspaceController = class {
10756
10750
  }
10757
10751
  if (updates.kind !== void 0) {
10758
10752
  const existingProject = await this.projectStore.getProjectById(tenantId, projectId);
10759
- if (existingProject && updates.kind === "public") {
10753
+ if (existingProject && existingProject.id === workspacePublicRoomProjectId(tenantId, existingProject.workspaceId)) {
10760
10754
  return reply.status(409).send({
10761
10755
  success: false,
10762
- error: "kind public is reserved for the workspace public room"
10763
- });
10764
- }
10765
- if (existingProject?.kind === "public") {
10766
- return reply.status(409).send({
10767
- success: false,
10768
- error: "The public room project classification cannot be changed"
10756
+ error: "The workspace public room classification cannot be changed"
10769
10757
  });
10770
10758
  }
10771
10759
  }
@@ -10799,10 +10787,10 @@ var WorkspaceController = class {
10799
10787
  });
10800
10788
  }
10801
10789
  }
10802
- if (project.kind === "public") {
10790
+ if (project.id === workspacePublicRoomProjectId(tenantId, project.workspaceId ?? workspaceId)) {
10803
10791
  return reply.status(409).send({
10804
10792
  success: false,
10805
- error: "The public room project cannot be deleted"
10793
+ error: "The workspace public room cannot be deleted"
10806
10794
  });
10807
10795
  }
10808
10796
  const deleted = await this.projectStore.deleteProject(tenantId, projectId);
@@ -14588,7 +14576,7 @@ function registerChannelRoutes(app2, dependencies) {
14588
14576
 
14589
14577
  // src/controllers/channel-installations.ts
14590
14578
  var import_crypto10 = require("crypto");
14591
- var import_protocols5 = require("@axiom-lattice/protocols");
14579
+ var import_protocols6 = require("@axiom-lattice/protocols");
14592
14580
  var _adapterRegistry;
14593
14581
  var _router;
14594
14582
  function setChannelControllerDeps(deps) {
@@ -14702,7 +14690,7 @@ function snapshotPlainObject(value) {
14702
14690
  const enumerable = Object.getOwnPropertyDescriptor(descriptor, "enumerable");
14703
14691
  if (!enumerable || !Object.prototype.hasOwnProperty.call(enumerable, "value")) return null;
14704
14692
  if (enumerable.value !== true) continue;
14705
- const data = (0, import_protocols5.descriptorDataValue)(descriptor);
14693
+ const data = (0, import_protocols6.descriptorDataValue)(descriptor);
14706
14694
  if (!data) return null;
14707
14695
  snapshot[key] = data.value;
14708
14696
  }
@@ -15028,7 +15016,7 @@ function registerChannelInstallationRoutes(app2) {
15028
15016
  }
15029
15017
 
15030
15018
  // src/controllers/channel-bindings.ts
15031
- var import_protocols6 = require("@axiom-lattice/protocols");
15019
+ var import_protocols7 = require("@axiom-lattice/protocols");
15032
15020
  var import_core38 = require("@axiom-lattice/core");
15033
15021
  function getTenantId14(request) {
15034
15022
  const userTenantId = request.user?.tenantId;
@@ -15048,7 +15036,7 @@ function snapshotPlainObject2(value) {
15048
15036
  const enumerable = Object.getOwnPropertyDescriptor(descriptor, "enumerable");
15049
15037
  if (!enumerable || !Object.prototype.hasOwnProperty.call(enumerable, "value")) return null;
15050
15038
  if (enumerable.value !== true) continue;
15051
- const data = (0, import_protocols6.descriptorDataValue)(descriptor);
15039
+ const data = (0, import_protocols7.descriptorDataValue)(descriptor);
15052
15040
  if (!data) return null;
15053
15041
  snapshot[key] = data.value;
15054
15042
  }
@@ -15152,7 +15140,7 @@ async function createBinding(request, reply) {
15152
15140
  reply.status(201);
15153
15141
  return { success: true, message: "Binding created", data: binding };
15154
15142
  } catch (error) {
15155
- if (error instanceof import_protocols6.DuplicateChannelBindingSubjectError) {
15143
+ if (error instanceof import_protocols7.DuplicateChannelBindingSubjectError) {
15156
15144
  reply.code(409);
15157
15145
  return { success: false, message: "Binding already exists" };
15158
15146
  }
@@ -15588,7 +15576,7 @@ var registerSTTRoutes = (app2) => {
15588
15576
 
15589
15577
  // src/controllers/local-a2a.ts
15590
15578
  var import_core41 = require("@axiom-lattice/core");
15591
- var import_protocols7 = require("@axiom-lattice/protocols");
15579
+ var import_protocols8 = require("@axiom-lattice/protocols");
15592
15580
  function getTenantId16(request) {
15593
15581
  const userTenantId = request.user?.tenantId;
15594
15582
  if (userTenantId) return userTenantId;
@@ -15597,7 +15585,7 @@ function getTenantId16(request) {
15597
15585
  function getLocalRuntime(assistant) {
15598
15586
  const graphDefinition = assistant.graphDefinition;
15599
15587
  if (!graphDefinition || typeof graphDefinition !== "object") return void 0;
15600
- if (graphDefinition.type !== import_protocols7.AgentType.A2A_REMOTE) return void 0;
15588
+ if (graphDefinition.type !== import_protocols8.AgentType.A2A_REMOTE) return void 0;
15601
15589
  return graphDefinition.localRuntime;
15602
15590
  }
15603
15591
  async function getLocalA2AAssistants(tenantId) {
@@ -15858,15 +15846,15 @@ function registerTaskRoutes(app2, controller) {
15858
15846
  var import_core52 = require("@axiom-lattice/core");
15859
15847
 
15860
15848
  // src/controllers/tasks.ts
15861
- var import_protocols10 = require("@axiom-lattice/protocols");
15849
+ var import_protocols11 = require("@axiom-lattice/protocols");
15862
15850
  var import_core43 = require("@axiom-lattice/core");
15863
15851
 
15864
15852
  // src/services/collaboration/ProjectTaskThreadService.ts
15865
15853
  var import_core42 = require("@axiom-lattice/core");
15866
- var import_protocols9 = require("@axiom-lattice/protocols");
15854
+ var import_protocols10 = require("@axiom-lattice/protocols");
15867
15855
 
15868
15856
  // src/services/collaboration/ProjectTaskSnapshots.ts
15869
- var import_protocols8 = require("@axiom-lattice/protocols");
15857
+ var import_protocols9 = require("@axiom-lattice/protocols");
15870
15858
  function snapshotJsonValue(value, stack = /* @__PURE__ */ new WeakSet()) {
15871
15859
  if (value === null || typeof value === "string" || typeof value === "boolean") return value;
15872
15860
  if (typeof value === "number" && Number.isFinite(value)) return value;
@@ -15912,7 +15900,7 @@ function cloneExactDate(value) {
15912
15900
  }
15913
15901
  }
15914
15902
  function snapshotTaskItem(value) {
15915
- const row = (0, import_protocols8.snapshotExactRecord)(value, [
15903
+ const row = (0, import_protocols9.snapshotExactRecord)(value, [
15916
15904
  "id",
15917
15905
  "tenantId",
15918
15906
  "ownerType",
@@ -15980,7 +15968,7 @@ function snapshotTaskItem(value) {
15980
15968
  }
15981
15969
  }
15982
15970
  function snapshotProjectRoom(value) {
15983
- const row = (0, import_protocols8.snapshotExactRecord)(value, ["id", "tenantId", "workspaceId", "projectId", "type", "name", "createdAt", "updatedAt"]);
15971
+ const row = (0, import_protocols9.snapshotExactRecord)(value, ["id", "tenantId", "workspaceId", "projectId", "type", "name", "createdAt", "updatedAt"]);
15984
15972
  const createdAt = cloneExactDate(row?.createdAt);
15985
15973
  const updatedAt = cloneExactDate(row?.updatedAt);
15986
15974
  if (!row || !createdAt || !updatedAt || row.type !== "main") return void 0;
@@ -15999,7 +15987,7 @@ function snapshotProjectRoom(value) {
15999
15987
  };
16000
15988
  }
16001
15989
  function snapshotBotMembership(value) {
16002
- const row = (0, import_protocols8.snapshotExactRecord)(value, [
15990
+ const row = (0, import_protocols9.snapshotExactRecord)(value, [
16003
15991
  "id",
16004
15992
  "tenantId",
16005
15993
  "workspaceId",
@@ -16038,7 +16026,7 @@ function snapshotBotMembership(value) {
16038
16026
  };
16039
16027
  }
16040
16028
  function snapshotThread(value) {
16041
- const row = (0, import_protocols8.snapshotExactRecord)(value, ["id", "tenantId", "assistantId", "createdAt", "updatedAt"], ["metadata"]);
16029
+ const row = (0, import_protocols9.snapshotExactRecord)(value, ["id", "tenantId", "assistantId", "createdAt", "updatedAt"], ["metadata"]);
16042
16030
  const createdAt = cloneExactDate(row?.createdAt);
16043
16031
  const updatedAt = cloneExactDate(row?.updatedAt);
16044
16032
  if (!row || !createdAt || !updatedAt || typeof row.id !== "string" || !row.id || typeof row.tenantId !== "string" || !row.tenantId || typeof row.assistantId !== "string" || !row.assistantId) return void 0;
@@ -16061,7 +16049,7 @@ function isRecord(value) {
16061
16049
  return typeof value === "object" && value !== null && !Array.isArray(value);
16062
16050
  }
16063
16051
  function isTaskFileRef(value) {
16064
- const row = (0, import_protocols8.snapshotExactRecord)(value, ["uri"], ["name", "mimeType", "addedBy"]);
16052
+ const row = (0, import_protocols9.snapshotExactRecord)(value, ["uri"], ["name", "mimeType", "addedBy"]);
16065
16053
  return !!row && typeof row.uri === "string" && !!row.uri && (row.name === void 0 || typeof row.name === "string") && (row.mimeType === void 0 || typeof row.mimeType === "string") && (row.addedBy === void 0 || row.addedBy === "user" || row.addedBy === "agent");
16066
16054
  }
16067
16055
 
@@ -16148,7 +16136,7 @@ function taskMetadata(task, room, membership) {
16148
16136
  };
16149
16137
  }
16150
16138
  function exactTaskMetadata(value, expected) {
16151
- const row = (0, import_protocols9.snapshotExactRecord)(value, [
16139
+ const row = (0, import_protocols10.snapshotExactRecord)(value, [
16152
16140
  "source",
16153
16141
  "kind",
16154
16142
  "workspaceId",
@@ -16161,7 +16149,7 @@ function exactTaskMetadata(value, expected) {
16161
16149
  return !!row && row.source === expected.source && row.kind === expected.kind && row.workspaceId === expected.workspaceId && row.projectId === expected.projectId && row.roomId === expected.roomId && row.membershipId === expected.membershipId && row.assistantId === expected.assistantId && row.taskId === expected.taskId && row.parentTaskId === expected.parentTaskId && Object.prototype.hasOwnProperty.call(row, "parentTaskId") === Object.prototype.hasOwnProperty.call(expected, "parentTaskId");
16162
16150
  }
16163
16151
  function snapshotEnsureInput(input) {
16164
- const row = (0, import_protocols9.snapshotExactRecord)(input, ["task", "room", "membership", "mode"]);
16152
+ const row = (0, import_protocols10.snapshotExactRecord)(input, ["task", "room", "membership", "mode"]);
16165
16153
  if (!row || row.mode !== "current_owner" && row.mode !== "reassignment") {
16166
16154
  throw new ProjectTaskThreadError("PROJECT_TASK_THREAD_SCOPE_INVALID", "Invalid ensure input");
16167
16155
  }
@@ -16285,7 +16273,7 @@ function offsetInteger(value) {
16285
16273
  return parsed;
16286
16274
  }
16287
16275
  function exactObject(value, allowed, required = []) {
16288
- const row = (0, import_protocols10.snapshotExactRecord)(value, required, allowed.filter((key) => !required.includes(key)));
16276
+ const row = (0, import_protocols11.snapshotExactRecord)(value, required, allowed.filter((key) => !required.includes(key)));
16289
16277
  if (!row) throw new HttpTaskError(400, "INVALID_TASK_INPUT");
16290
16278
  return row;
16291
16279
  }
@@ -16336,7 +16324,7 @@ function validateUpdateTaskInput(row) {
16336
16324
  }
16337
16325
  }
16338
16326
  function taskFile(value) {
16339
- const row = (0, import_protocols10.snapshotExactRecord)(value, ["uri"], ["name", "mimeType", "addedBy"]);
16327
+ const row = (0, import_protocols11.snapshotExactRecord)(value, ["uri"], ["name", "mimeType", "addedBy"]);
16340
16328
  return !!row && typeof row.uri === "string" && !!row.uri && (row.name === void 0 || typeof row.name === "string") && (row.mimeType === void 0 || typeof row.mimeType === "string") && (row.addedBy === void 0 || row.addedBy === "user" || row.addedBy === "agent");
16341
16329
  }
16342
16330
  function snapshotCreate(value) {
@@ -16956,10 +16944,15 @@ var agentWebAppFeaturesSchema = import_zod4.z.object({
16956
16944
  genUI: import_zod4.z.boolean(),
16957
16945
  files: import_zod4.z.boolean().optional()
16958
16946
  }).strict();
16947
+ var agentWebAppQuickPromptSchema = import_zod4.z.object({
16948
+ label: import_zod4.z.string().min(1).max(40),
16949
+ text: import_zod4.z.string().min(1).max(500)
16950
+ }).strict();
16959
16951
  var agentWebAppAppearanceSchema = import_zod4.z.object({
16960
16952
  title: import_zod4.z.string().max(120).optional(),
16961
16953
  welcomeMessage: import_zod4.z.string().max(1e3).optional(),
16962
- primaryColor: import_zod4.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional()
16954
+ primaryColor: import_zod4.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(),
16955
+ quickPrompts: import_zod4.z.array(agentWebAppQuickPromptSchema).max(6).optional()
16963
16956
  }).strict();
16964
16957
  var agentWebAppIssuerSchema = import_zod4.z.object({
16965
16958
  iss: import_zod4.z.string().min(1).max(255),
@@ -17083,7 +17076,7 @@ var import_zod6 = require("zod");
17083
17076
 
17084
17077
  // src/services/agent-web-app/AgentWebAppRuntimeService.ts
17085
17078
  var import_node_crypto7 = require("crypto");
17086
- var import_protocols11 = require("@axiom-lattice/protocols");
17079
+ var import_protocols12 = require("@axiom-lattice/protocols");
17087
17080
  init_task_file_refs();
17088
17081
  function isRecord2(value) {
17089
17082
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -17201,7 +17194,7 @@ var AgentWebAppRuntimeService = class {
17201
17194
  });
17202
17195
  return messages.flatMap((message) => {
17203
17196
  if (!isRecord2(message) || typeof message.id !== "string" || message.role !== "human" && message.role !== "ai") return [];
17204
- const content = typeof message.content === "string" ? message.content : runtime.webApp.features.genUI && Array.isArray(message.content) ? message.content.map(import_protocols11.parseAgentWebAppGenUIBlock).filter((block) => block !== void 0) : void 0;
17197
+ const content = typeof message.content === "string" ? message.content : runtime.webApp.features.genUI && Array.isArray(message.content) ? message.content.map(import_protocols12.parseAgentWebAppGenUIBlock).filter((block) => block !== void 0) : void 0;
17205
17198
  return [{ id: message.id, role: message.role, ...content && (typeof content === "string" || content.length > 0) ? { content } : {} }];
17206
17199
  });
17207
17200
  }
@@ -17319,7 +17312,7 @@ ${formatFileRefsSection(refs)}` : input.content;
17319
17312
  return executeScopedAgentMessage(agent, {
17320
17313
  ...request,
17321
17314
  ...runtime.modelKey ? { custom_run_config: { modelConfig: { modelKey: runtime.modelKey } } } : {}
17322
- }, [import_protocols11.MessageChunkTypes.MESSAGE_COMPLETED, import_protocols11.MessageChunkTypes.INTERRUPT, import_protocols11.MessageChunkTypes.MESSAGE_FAILED]);
17315
+ }, [import_protocols12.MessageChunkTypes.MESSAGE_COMPLETED, import_protocols12.MessageChunkTypes.INTERRUPT, import_protocols12.MessageChunkTypes.MESSAGE_FAILED]);
17323
17316
  }
17324
17317
  async resolveRuntime(webAppId, selection) {
17325
17318
  const webApp = await this.deps.webAppStore.findById(webAppId);
@@ -17590,7 +17583,7 @@ async function verifyWebAppToken(token, issuer, options = {}) {
17590
17583
  }
17591
17584
 
17592
17585
  // src/routes/agent-web-app-runtime.ts
17593
- var import_protocols12 = require("@axiom-lattice/protocols");
17586
+ var import_protocols13 = require("@axiom-lattice/protocols");
17594
17587
  var idSchema = import_zod6.z.string().min(1).max(128);
17595
17588
  var paramsSchema = import_zod6.z.object({ webAppId: idSchema }).strict();
17596
17589
  var threadParamsSchema = import_zod6.z.object({ webAppId: idSchema, threadId: idSchema }).strict();
@@ -18065,9 +18058,9 @@ function withPreview(selection, preview) {
18065
18058
  return { ...selection, ...preview ? { preview } : {} };
18066
18059
  }
18067
18060
  async function pipeAgentWebAppStream(raw, stream, options = {}) {
18068
- const projection = (0, import_protocols12.createAgentWebAppStreamProjectionContext)(options);
18061
+ const projection = (0, import_protocols13.createAgentWebAppStreamProjectionContext)(options);
18069
18062
  await pipeAsyncIterableToSse(raw, stream, {
18070
- project: (chunk) => (0, import_protocols12.projectAgentWebAppChunk)(chunk, projection),
18063
+ project: (chunk) => (0, import_protocols13.projectAgentWebAppChunk)(chunk, projection),
18071
18064
  onError: (error) => {
18072
18065
  const code = error?.code;
18073
18066
  if (code === "aborted" || code === "superseded") return [{ type: "stream.completed" }];
@@ -18717,7 +18710,7 @@ var ProjectRoomService = class {
18717
18710
  */
18718
18711
  async ensureMainRoomWithCoordinator(input) {
18719
18712
  const { project, room } = await this.authorizedRoom(input);
18720
- if (project.kind === "business" && this.deps.ensureCoordinator) {
18713
+ if ((project.kind === "business" || project.kind === "public") && this.deps.ensureCoordinator) {
18721
18714
  try {
18722
18715
  await this.deps.ensureCoordinator({
18723
18716
  tenantId: input.tenantId,
@@ -19158,12 +19151,12 @@ var ProjectRosterService = class {
19158
19151
  var import_node_crypto14 = require("crypto");
19159
19152
 
19160
19153
  // src/services/collaboration/ProjectBotMembershipSnapshot.ts
19161
- var import_protocols13 = require("@axiom-lattice/protocols");
19154
+ var import_protocols14 = require("@axiom-lattice/protocols");
19162
19155
  var requiredKeys = ["assistantId", "id", "joinedAt", "mentionName", "projectId", "role", "roomId", "roomThreadId", "status", "tenantId", "title", "updatedAt", "workspaceId"];
19163
19156
  function snapshotProjectBotMembership(value) {
19164
19157
  try {
19165
19158
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
19166
- const values = (0, import_protocols13.snapshotExactRecord)(value, requiredKeys, ["responsibility"]);
19159
+ const values = (0, import_protocols14.snapshotExactRecord)(value, requiredKeys, ["responsibility"]);
19167
19160
  if (!values) return void 0;
19168
19161
  const read = (key) => values[key];
19169
19162
  const id3 = read("id");
@@ -19494,7 +19487,7 @@ function matchesNormalizedPayload(message, input) {
19494
19487
 
19495
19488
  // src/routes/project-rooms.ts
19496
19489
  var import_zod11 = require("zod");
19497
- var import_protocols14 = require("@axiom-lattice/protocols");
19490
+ var import_protocols15 = require("@axiom-lattice/protocols");
19498
19491
 
19499
19492
  // src/services/collaboration/RoomInterruptService.ts
19500
19493
  var import_node_crypto15 = require("crypto");
@@ -19736,7 +19729,7 @@ function actor(request, projectId) {
19736
19729
  return { tenantId: user.tenantId, userId: user.id, projectId };
19737
19730
  }
19738
19731
  function toProjectRoomMessage(message) {
19739
- const publicMessage = (0, import_protocols14.toProjectRoomPublicMessage)(message);
19732
+ const publicMessage = (0, import_protocols15.toProjectRoomPublicMessage)(message);
19740
19733
  if (publicMessage === void 0) throw new Error("Room message could not be mapped to its public DTO");
19741
19734
  return publicMessage;
19742
19735
  }
@@ -19803,7 +19796,7 @@ async function execute(reply, operation) {
19803
19796
  var import_node_crypto16 = require("crypto");
19804
19797
  var import_zod13 = require("zod");
19805
19798
  var import_core45 = require("@axiom-lattice/core");
19806
- var import_protocols15 = require("@axiom-lattice/protocols");
19799
+ var import_protocols16 = require("@axiom-lattice/protocols");
19807
19800
  var CoSpaceAuthError = class extends Error {
19808
19801
  constructor() {
19809
19802
  super(...arguments);
@@ -19856,13 +19849,13 @@ function registerCoSpaceRoutes(app2, deps) {
19856
19849
  );
19857
19850
  const accessibleProjects = [];
19858
19851
  for (const project of allProjects) {
19859
- if (project.kind === "public") continue;
19852
+ if (project.id.startsWith(import_protocols5.WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX)) continue;
19860
19853
  const membership = await deps.membershipStore.findByUser(
19861
19854
  actor3.tenantId,
19862
19855
  project.id,
19863
19856
  actor3.userId
19864
19857
  );
19865
- if (membership && membership.status === "active") {
19858
+ if (project.kind === "public" || membership && membership.status === "active") {
19866
19859
  accessibleProjects.push(project);
19867
19860
  }
19868
19861
  }
@@ -19880,7 +19873,7 @@ function registerCoSpaceRoutes(app2, deps) {
19880
19873
  limit: 1
19881
19874
  });
19882
19875
  const lastMessage = messages[0];
19883
- const publicLastMessage = lastMessage === void 0 ? void 0 : (0, import_protocols15.toProjectRoomPublicMessage)(lastMessage);
19876
+ const publicLastMessage = lastMessage === void 0 ? void 0 : (0, import_protocols16.toProjectRoomPublicMessage)(lastMessage);
19884
19877
  const memberships = await deps.membershipStore.list(
19885
19878
  actor3.tenantId,
19886
19879
  project.id
@@ -19905,6 +19898,7 @@ function registerCoSpaceRoutes(app2, deps) {
19905
19898
  ).length,
19906
19899
  participantNames,
19907
19900
  ...displayName === void 0 ? {} : { displayName },
19901
+ ...project.kind === "public" ? { isPublic: true } : {},
19908
19902
  unreadCount: await computeUnread(
19909
19903
  deps,
19910
19904
  actor3.tenantId,
@@ -19946,7 +19940,7 @@ function registerCoSpaceRoutes(app2, deps) {
19946
19940
  rooms.unshift({
19947
19941
  project: publicRoom.project,
19948
19942
  room: publicRoom.room,
19949
- lastMessage: publicLastMessage === void 0 ? void 0 : (0, import_protocols15.toProjectRoomPublicMessage)(publicLastMessage),
19943
+ lastMessage: publicLastMessage === void 0 ? void 0 : (0, import_protocols16.toProjectRoomPublicMessage)(publicLastMessage),
19950
19944
  participantCount: publicMemberships.filter((m) => m.status === "active").length,
19951
19945
  participantNames: publicParticipantNames,
19952
19946
  isPublic: true,
@@ -20659,7 +20653,7 @@ var RoomTargetResolver = class {
20659
20653
  };
20660
20654
 
20661
20655
  // src/services/collaboration/RoomDispatchService.ts
20662
- var import_protocols16 = require("@axiom-lattice/protocols");
20656
+ var import_protocols17 = require("@axiom-lattice/protocols");
20663
20657
 
20664
20658
  // src/router/InternalRoomDispatch.ts
20665
20659
  var INTERNAL_ROOM_DISPATCH = Symbol("internal-room-dispatch");
@@ -20760,7 +20754,7 @@ function snapshotDispatchSource(value) {
20760
20754
  };
20761
20755
  }
20762
20756
  function snapshotMentions(value) {
20763
- const rows = (0, import_protocols16.snapshotExactArray)(value);
20757
+ const rows = (0, import_protocols17.snapshotExactArray)(value);
20764
20758
  if (!rows) return void 0;
20765
20759
  const result = [];
20766
20760
  for (const row of rows) {
@@ -20778,7 +20772,7 @@ function snapshotMentions(value) {
20778
20772
  function exactValues(value, required, optional = []) {
20779
20773
  try {
20780
20774
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
20781
- return (0, import_protocols16.snapshotExactRecord)(value, required, optional);
20775
+ return (0, import_protocols17.snapshotExactRecord)(value, required, optional);
20782
20776
  } catch {
20783
20777
  return void 0;
20784
20778
  }
@@ -20787,7 +20781,7 @@ function exactValues(value, required, optional = []) {
20787
20781
  // src/services/collaboration/CoordinatorWakeNotifier.ts
20788
20782
  var import_node_crypto17 = require("crypto");
20789
20783
  var import_core46 = require("@axiom-lattice/core");
20790
- var import_protocols17 = require("@axiom-lattice/protocols");
20784
+ var import_protocols18 = require("@axiom-lattice/protocols");
20791
20785
  var SYNTHETIC_WAKE_AUTHOR = "coordinator-wake";
20792
20786
  var CoordinatorWakeNotifier = class {
20793
20787
  /** Creates a bounded Project Task lifecycle observer that wakes the Room Coordinator. */
@@ -20943,7 +20937,7 @@ var CoordinatorWakeNotifier = class {
20943
20937
  }
20944
20938
  }
20945
20939
  parse(value) {
20946
- const row = (0, import_protocols17.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
20940
+ const row = (0, import_protocols18.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
20947
20941
  const actions = ["in_progress", "interrupted", "failed", "completed", "cancelled", "reassigned"];
20948
20942
  const statuses = ["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"];
20949
20943
  if (!row || !actions.includes(String(row.action)) || !statuses.includes(String(row.status)) || !["tenantId", "workspaceId", "projectId", "taskId", "eventKey", "updatedAt"].every((key) => typeof row[key] === "string" && row[key].length > 0) || !Number.isFinite(Date.parse(row.updatedAt)) || row.threadId !== void 0 && typeof row.threadId !== "string") return void 0;
@@ -20984,10 +20978,102 @@ function readSourceMessageId(context) {
20984
20978
  return typeof value === "string" && value.length > 0 ? value : void 0;
20985
20979
  }
20986
20980
 
20981
+ // src/services/collaboration/RoomMessageRetentionJob.ts
20982
+ var DAY_MS = 24 * 60 * 60 * 1e3;
20983
+ var DEFAULT_INTERVAL_MS = 6 * 60 * 60 * 1e3;
20984
+ var DEFAULT_INITIAL_DELAY_MS = 6e4;
20985
+ var DEFAULT_BATCH_SIZE = 500;
20986
+ var MAX_BATCHES_PER_RUN = 1e3;
20987
+ var DEFAULT_RETENTION_DAYS = 60;
20988
+ function parseRetentionDays(value) {
20989
+ if (value === void 0 || value === null) return DEFAULT_RETENTION_DAYS;
20990
+ if (typeof value !== "string") return void 0;
20991
+ const trimmed = value.trim();
20992
+ if (trimmed.length === 0) return DEFAULT_RETENTION_DAYS;
20993
+ const parsed = Number(trimmed);
20994
+ return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : void 0;
20995
+ }
20996
+ var RoomMessageRetentionJob = class {
20997
+ /**
20998
+ * Creates a retention sweep job.
20999
+ *
21000
+ * @param deps Message store slice, positive retention days, and logger.
21001
+ * @param options Optional interval, initial delay, batch size, and clock overrides.
21002
+ */
21003
+ constructor(deps, options = {}) {
21004
+ this.deps = deps;
21005
+ this.disposed = false;
21006
+ this.running = false;
21007
+ this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;
21008
+ this.initialDelayMs = options.initialDelayMs ?? DEFAULT_INITIAL_DELAY_MS;
21009
+ this.batchSize = options.batchSize ?? DEFAULT_BATCH_SIZE;
21010
+ this.now = options.now ?? (() => /* @__PURE__ */ new Date());
21011
+ for (const [name, value] of Object.entries({ intervalMs: this.intervalMs, initialDelayMs: this.initialDelayMs, batchSize: this.batchSize })) {
21012
+ if (!Number.isSafeInteger(value) || value < 1) throw new RangeError(`Room message retention ${name} must be a positive safe integer`);
21013
+ }
21014
+ }
21015
+ /** Schedules one delayed initial sweep plus the recurring interval (both unref'd). */
21016
+ start() {
21017
+ if (this.disposed || this.initial !== void 0 || this.interval !== void 0) return;
21018
+ this.initial = setTimeout(() => {
21019
+ this.initial = void 0;
21020
+ void this.runOnce();
21021
+ }, this.initialDelayMs);
21022
+ this.initial.unref?.();
21023
+ this.interval = setInterval(() => void this.runOnce(), this.intervalMs);
21024
+ this.interval.unref?.();
21025
+ }
21026
+ /**
21027
+ * Runs one bounded sweep: batches until a short batch or the per-run batch cap.
21028
+ *
21029
+ * @returns The number of deleted rows (0 on disabled/overlapping runs or failures).
21030
+ */
21031
+ async runOnce() {
21032
+ if (this.disposed || this.running) return 0;
21033
+ this.running = true;
21034
+ try {
21035
+ const before = new Date(this.now().getTime() - this.deps.days * DAY_MS);
21036
+ let deleted = 0;
21037
+ for (let batch = 0; batch < MAX_BATCHES_PER_RUN; batch += 1) {
21038
+ const removed = await this.deps.messages.deleteChatOlderThan({ before, limit: this.batchSize });
21039
+ deleted += removed;
21040
+ if (removed < this.batchSize) break;
21041
+ }
21042
+ if (deleted > 0) this.deps.log.info?.("project-room:message-retention-swept", { deleted, days: this.deps.days });
21043
+ return deleted;
21044
+ } catch (error) {
21045
+ this.deps.log.warn("project-room:message-retention-failed", {
21046
+ days: this.deps.days,
21047
+ error: error instanceof Error ? error.name : "UnknownError"
21048
+ });
21049
+ return 0;
21050
+ } finally {
21051
+ this.running = false;
21052
+ }
21053
+ }
21054
+ /** Stops the timers; an in-flight sweep finishes on its own. */
21055
+ dispose() {
21056
+ this.disposed = true;
21057
+ if (this.initial !== void 0) {
21058
+ clearTimeout(this.initial);
21059
+ this.initial = void 0;
21060
+ }
21061
+ if (this.interval !== void 0) {
21062
+ clearInterval(this.interval);
21063
+ this.interval = void 0;
21064
+ }
21065
+ }
21066
+ };
21067
+ function createRoomMessageRetentionJob(input) {
21068
+ const days = parseRetentionDays(input.days);
21069
+ if (days === void 0) return void 0;
21070
+ return new RoomMessageRetentionJob({ messages: input.messages, days, log: input.log }, input.options);
21071
+ }
21072
+
20987
21073
  // src/services/collaboration/ProjectTaskExecutionMutex.ts
20988
- var import_protocols18 = require("@axiom-lattice/protocols");
21074
+ var import_protocols19 = require("@axiom-lattice/protocols");
20989
21075
  function machineKey(scope) {
20990
- const snapshot = (0, import_protocols18.snapshotExactRecord)(scope, ["tenantId", "assistantId", "projectId"]);
21076
+ const snapshot = (0, import_protocols19.snapshotExactRecord)(scope, ["tenantId", "assistantId", "projectId"]);
20991
21077
  if (!snapshot) throw new Error("Invalid Project task machine scope");
20992
21078
  const values = [snapshot.tenantId, snapshot.assistantId, snapshot.projectId];
20993
21079
  for (const value of values) {
@@ -21065,7 +21151,7 @@ var ProjectTaskExecutionMutex = class {
21065
21151
  // src/services/collaboration/ProjectTaskExecutionService.ts
21066
21152
  var import_node_crypto18 = require("crypto");
21067
21153
  var import_core47 = require("@axiom-lattice/core");
21068
- var import_protocols19 = require("@axiom-lattice/protocols");
21154
+ var import_protocols20 = require("@axiom-lattice/protocols");
21069
21155
  var SYSTEM_ACTOR = "system";
21070
21156
  var QUEUE_CLASSIFICATION_ATTEMPTS = 3;
21071
21157
  var ProjectTaskExecutionError = class extends Error {
@@ -21656,7 +21742,7 @@ function buildTrustedTaskContext(task, thread, inputMessageId) {
21656
21742
  };
21657
21743
  }
21658
21744
  function taskThreadMetadata(thread) {
21659
- const row = (0, import_protocols19.snapshotExactRecord)(thread.metadata, [
21745
+ const row = (0, import_protocols20.snapshotExactRecord)(thread.metadata, [
21660
21746
  "source",
21661
21747
  "kind",
21662
21748
  "workspaceId",
@@ -21697,7 +21783,7 @@ function classifyRecoveryRows(task, thread, pending2, processingBefore, processi
21697
21783
  }
21698
21784
  function validRecoveryRow(row, task, thread) {
21699
21785
  try {
21700
- const trusted = (0, import_protocols19.parseTrustedRunContext)(row.trusted_run_context).projectTask;
21786
+ const trusted = (0, import_protocols20.parseTrustedRunContext)(row.trusted_run_context).projectTask;
21701
21787
  const metadata = taskThreadMetadata(thread);
21702
21788
  return row.execution_mode === "followup" && !!trusted && trusted.tenantId === task.tenantId && trusted.workspaceId === task.workspaceId && trusted.projectId === task.projectId && trusted.assistantId === task.ownerId && trusted.taskId === task.id && trusted.threadId === thread.id && trusted.inputMessageId === row.id && !!metadata && trusted.roomId === metadata.roomId && trusted.membershipId === metadata.membershipId && metadata.assistantId === task.ownerId && metadata.taskId === task.id;
21703
21789
  } catch {
@@ -21708,7 +21794,7 @@ function validRecoveryRow(row, task, thread) {
21708
21794
  // src/services/collaboration/ProjectTaskObserver.ts
21709
21795
  var import_node_crypto19 = require("crypto");
21710
21796
  var import_core48 = require("@axiom-lattice/core");
21711
- var import_protocols20 = require("@axiom-lattice/protocols");
21797
+ var import_protocols21 = require("@axiom-lattice/protocols");
21712
21798
  var SYSTEM_ACTOR2 = "system";
21713
21799
  var TERMINAL_ACTIONS = ["completed", "failed", "interrupted", "cancelled"];
21714
21800
  var MAX_LEARNING_ROUND_ANCESTORS = 8;
@@ -22445,7 +22531,7 @@ function errorMessage3(error) {
22445
22531
  }
22446
22532
  function readCreatedBy(value) {
22447
22533
  try {
22448
- const row = (0, import_protocols20.snapshotExactRecord)(value, ["assistantId", "membershipId"]);
22534
+ const row = (0, import_protocols21.snapshotExactRecord)(value, ["assistantId", "membershipId"]);
22449
22535
  return row && typeof row.assistantId === "string" && row.assistantId.length > 0 && typeof row.membershipId === "string" && row.membershipId.length > 0 ? { assistantId: row.assistantId, membershipId: row.membershipId } : void 0;
22450
22536
  } catch {
22451
22537
  return void 0;
@@ -22461,7 +22547,7 @@ function combineSignals(left, right) {
22461
22547
  // src/services/collaboration/RoomProjectionService.ts
22462
22548
  var import_node_crypto20 = require("crypto");
22463
22549
  var import_core49 = require("@axiom-lattice/core");
22464
- var import_protocols21 = require("@axiom-lattice/protocols");
22550
+ var import_protocols22 = require("@axiom-lattice/protocols");
22465
22551
  var ROOM_PROJECTABLE_ACTIONS = [
22466
22552
  "interrupted",
22467
22553
  "failed",
@@ -22540,7 +22626,7 @@ var RoomProjectionService = class {
22540
22626
  projectId: task.projectId,
22541
22627
  roomId: room.id,
22542
22628
  author: { type: "system" },
22543
- content: { type: "text", text: `${import_protocols21.PROJECT_ROOM_TASK_DELEGATED_LABEL}${import_protocols21.PROJECT_ROOM_TASK_DELEGATED_SEPARATOR}${input.fromLabel} \u2192 ${input.toLabel}` },
22629
+ content: { type: "text", text: `${import_protocols22.PROJECT_ROOM_TASK_DELEGATED_LABEL}${import_protocols22.PROJECT_ROOM_TASK_DELEGATED_SEPARATOR}${input.fromLabel} \u2192 ${input.toLabel}` },
22544
22630
  mentions: [],
22545
22631
  source: "task",
22546
22632
  sourceId: task.id,
@@ -22691,7 +22777,7 @@ function parseProjectionInput(taskValue, itemValue) {
22691
22777
  }
22692
22778
  }
22693
22779
  function snapshotProjectableWorkItem(value) {
22694
- const row = (0, import_protocols21.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
22780
+ const row = (0, import_protocols22.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
22695
22781
  "workspaceId",
22696
22782
  "projectId",
22697
22783
  "threadId",
@@ -22701,7 +22787,7 @@ function snapshotProjectableWorkItem(value) {
22701
22787
  "eventKey"
22702
22788
  ]);
22703
22789
  const createdAt = cloneExactDate(row?.createdAt);
22704
- if (!row || !createdAt || typeof row.id !== "string" || !row.id || typeof row.taskId !== "string" || !row.taskId || typeof row.tenantId !== "string" || !row.tenantId || typeof row.workspaceId !== "string" || !row.workspaceId || typeof row.projectId !== "string" || !row.projectId || typeof row.actor !== "string" || !row.actor || typeof row.eventKey !== "string" || !row.eventKey || !import_protocols21.PROJECT_TASK_LIFECYCLE_ACTIONS.includes(row.action) || row.threadId !== void 0 && typeof row.threadId !== "string" || row.summary !== void 0 && typeof row.summary !== "string" || row.attempt !== void 0 && (typeof row.attempt !== "number" || !Number.isFinite(row.attempt))) return void 0;
22790
+ if (!row || !createdAt || typeof row.id !== "string" || !row.id || typeof row.taskId !== "string" || !row.taskId || typeof row.tenantId !== "string" || !row.tenantId || typeof row.workspaceId !== "string" || !row.workspaceId || typeof row.projectId !== "string" || !row.projectId || typeof row.actor !== "string" || !row.actor || typeof row.eventKey !== "string" || !row.eventKey || !import_protocols22.PROJECT_TASK_LIFECYCLE_ACTIONS.includes(row.action) || row.threadId !== void 0 && typeof row.threadId !== "string" || row.summary !== void 0 && typeof row.summary !== "string" || row.attempt !== void 0 && (typeof row.attempt !== "number" || !Number.isFinite(row.attempt))) return void 0;
22705
22791
  try {
22706
22792
  const detail = row.detail === void 0 ? void 0 : snapshotJsonValue(row.detail);
22707
22793
  if (detail !== void 0 && !isRecord3(detail)) return void 0;
@@ -22728,12 +22814,12 @@ function parseIso(value) {
22728
22814
  return typeof value === "string" && value.length > 0 && Number.isFinite(Date.parse(value));
22729
22815
  }
22730
22816
  function parseInterruption(value) {
22731
- const common = (0, import_protocols21.snapshotExactRecord)(value, ["type", "summary", "requestedAt"]);
22817
+ const common = (0, import_protocols22.snapshotExactRecord)(value, ["type", "summary", "requestedAt"]);
22732
22818
  if (common && (common.type === "missing_input" || common.type === "user_decision") && typeof common.summary === "string" && common.summary.length > 0 && parseIso(common.requestedAt)) {
22733
22819
  return { type: common.type, summary: common.summary, requestedAt: common.requestedAt };
22734
22820
  }
22735
- const external = (0, import_protocols21.snapshotExactRecord)(value, ["type", "summary", "requestedAt", "dependencyTaskIds"]);
22736
- const ids = (0, import_protocols21.snapshotExactArray)(external?.dependencyTaskIds);
22821
+ const external = (0, import_protocols22.snapshotExactRecord)(value, ["type", "summary", "requestedAt", "dependencyTaskIds"]);
22822
+ const ids = (0, import_protocols22.snapshotExactArray)(external?.dependencyTaskIds);
22737
22823
  if (external?.type === "external_dependency" && typeof external.summary === "string" && external.summary.length > 0 && parseIso(external.requestedAt) && ids && ids.length > 0 && ids.every((id3) => typeof id3 === "string" && id3.length > 0) && new Set(ids).size === ids.length) {
22738
22824
  return {
22739
22825
  type: "external_dependency",
@@ -22742,22 +22828,22 @@ function parseInterruption(value) {
22742
22828
  dependencyTaskIds: [...ids]
22743
22829
  };
22744
22830
  }
22745
- const review = (0, import_protocols21.snapshotExactRecord)(value, ["type", "evidenceId"]);
22831
+ const review = (0, import_protocols22.snapshotExactRecord)(value, ["type", "evidenceId"]);
22746
22832
  return review?.type === "review_required" && typeof review.evidenceId === "string" && review.evidenceId.length > 0 ? { type: "review_required", evidenceId: review.evidenceId } : void 0;
22747
22833
  }
22748
22834
  function parseBeliefImpact(value) {
22749
- const rows = (0, import_protocols21.snapshotExactArray)(value);
22835
+ const rows = (0, import_protocols22.snapshotExactArray)(value);
22750
22836
  if (!rows) return void 0;
22751
22837
  const impacts = [];
22752
22838
  for (const row of rows) {
22753
- const entry = (0, import_protocols21.snapshotExactRecord)(row, ["key", "after", "basis"]);
22839
+ const entry = (0, import_protocols22.snapshotExactRecord)(row, ["key", "after", "basis"]);
22754
22840
  if (!entry || typeof entry.key !== "string" || !entry.key || typeof entry.after !== "number" || !Number.isFinite(entry.after) || typeof entry.basis !== "string" || !entry.basis) return void 0;
22755
22841
  impacts.push({ key: entry.key, after: entry.after, basis: entry.basis });
22756
22842
  }
22757
22843
  return impacts;
22758
22844
  }
22759
22845
  function parseCompletion(item) {
22760
- const row = (0, import_protocols21.snapshotExactRecord)(item.detail, ["evidenceId", "eventKey", "result", "beliefImpact"]);
22846
+ const row = (0, import_protocols22.snapshotExactRecord)(item.detail, ["evidenceId", "eventKey", "result", "beliefImpact"]);
22761
22847
  const beliefImpact = parseBeliefImpact(row?.beliefImpact);
22762
22848
  if (!row || typeof row.evidenceId !== "string" || !row.evidenceId || typeof row.eventKey !== "string" || !row.eventKey || item.eventKey !== `${row.eventKey}:completed` || typeof row.result !== "string" || !beliefImpact) return void 0;
22763
22849
  return { evidenceId: row.evidenceId, eventKey: row.eventKey, result: row.result, beliefImpact };
@@ -22767,19 +22853,19 @@ function parseProjection(item) {
22767
22853
  return parseInterruption(item.detail) ? { kind: "interrupted", text: "Task interrupted" } : void 0;
22768
22854
  }
22769
22855
  if (item.action === "failed") {
22770
- const row = (0, import_protocols21.snapshotExactRecord)(item.detail, ["failureReason"]);
22856
+ const row = (0, import_protocols22.snapshotExactRecord)(item.detail, ["failureReason"]);
22771
22857
  return typeof row?.failureReason === "string" && row.failureReason ? { kind: "failed", text: "Task failed" } : void 0;
22772
22858
  }
22773
22859
  if (item.action === "completed") {
22774
22860
  return parseCompletion(item) ? { kind: "completed", text: "Task completed" } : void 0;
22775
22861
  }
22776
22862
  if (item.action === "cancelled") {
22777
- const empty = (0, import_protocols21.snapshotExactRecord)(item.detail, []);
22778
- const summarized = (0, import_protocols21.snapshotExactRecord)(item.detail, ["summary"]);
22863
+ const empty = (0, import_protocols22.snapshotExactRecord)(item.detail, []);
22864
+ const summarized = (0, import_protocols22.snapshotExactRecord)(item.detail, ["summary"]);
22779
22865
  return empty || typeof summarized?.summary === "string" && summarized.summary ? { kind: "cancelled", text: "Task cancelled" } : void 0;
22780
22866
  }
22781
22867
  if (item.action === "reassigned") {
22782
- const row = (0, import_protocols21.snapshotExactRecord)(
22868
+ const row = (0, import_protocols22.snapshotExactRecord)(
22783
22869
  item.detail,
22784
22870
  ["previousOwnerId", "previousThreadId", "ownerId", "membershipId", "threadId"]
22785
22871
  );
@@ -22788,7 +22874,7 @@ function parseProjection(item) {
22788
22874
  return void 0;
22789
22875
  }
22790
22876
  function assertCanonicalProjection(value, expected) {
22791
- const row = (0, import_protocols21.snapshotExactRecord)(value, [
22877
+ const row = (0, import_protocols22.snapshotExactRecord)(value, [
22792
22878
  "id",
22793
22879
  "tenantId",
22794
22880
  "workspaceId",
@@ -22802,9 +22888,9 @@ function assertCanonicalProjection(value, expected) {
22802
22888
  "idempotencyKey",
22803
22889
  "createdAt"
22804
22890
  ]);
22805
- const author = (0, import_protocols21.snapshotExactRecord)(row?.author, ["type"]);
22806
- const content = (0, import_protocols21.snapshotExactRecord)(row?.content, ["type", "text"]);
22807
- const mentions = (0, import_protocols21.snapshotExactArray)(row?.mentions);
22891
+ const author = (0, import_protocols22.snapshotExactRecord)(row?.author, ["type"]);
22892
+ const content = (0, import_protocols22.snapshotExactRecord)(row?.content, ["type", "text"]);
22893
+ const mentions = (0, import_protocols22.snapshotExactArray)(row?.mentions);
22808
22894
  const createdAt = cloneExactDate(row?.createdAt);
22809
22895
  if (!row || !createdAt || author?.type !== "system" || content?.type !== "text" || content.text !== expected.content.text || !mentions || mentions.length !== 0 || typeof row.id !== "string" || !row.id || row.tenantId !== expected.tenantId || row.workspaceId !== expected.workspaceId || row.projectId !== expected.projectId || row.roomId !== expected.roomId || row.source !== "task" || row.sourceId !== expected.sourceId || row.idempotencyKey !== expected.idempotencyKey) {
22810
22896
  throw new Error("Invalid canonical task projection");
@@ -22825,7 +22911,7 @@ function assertCanonicalProjection(value, expected) {
22825
22911
  };
22826
22912
  }
22827
22913
  function snapshotLifecycleCursor(value) {
22828
- const row = (0, import_protocols21.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
22914
+ const row = (0, import_protocols22.snapshotExactRecord)(value, ["id", "taskId", "tenantId", "action", "actor", "createdAt"], [
22829
22915
  "workspaceId",
22830
22916
  "projectId",
22831
22917
  "threadId",
@@ -22846,7 +22932,7 @@ var import_core51 = require("@axiom-lattice/core");
22846
22932
 
22847
22933
  // src/services/collaboration/ProjectRoomEventBroker.ts
22848
22934
  var import_node_crypto21 = require("crypto");
22849
- var import_protocols22 = require("@axiom-lattice/protocols");
22935
+ var import_protocols23 = require("@axiom-lattice/protocols");
22850
22936
  var DEFAULT_MAX_EVENTS_PER_ROOM = 1e3;
22851
22937
  var DEFAULT_MAX_EVENT_AGE_MS = 10 * 60 * 1e3;
22852
22938
  var DEFAULT_MAX_ROOMS = 1e3;
@@ -22909,7 +22995,7 @@ var ProjectRoomEventBroker = class {
22909
22995
  const canonicalScope = snapshotScope(scope);
22910
22996
  const key = scopeKey2(canonicalScope);
22911
22997
  const now = this.currentTime();
22912
- if (this.sequence >= Number.MAX_SAFE_INTEGER) throw new import_protocols22.ProjectRoomBrokerCapacityError();
22998
+ if (this.sequence >= Number.MAX_SAFE_INTEGER) throw new import_protocols23.ProjectRoomBrokerCapacityError();
22913
22999
  const nextSequence = this.sequence + 1;
22914
23000
  const event = snapshotJson({
22915
23001
  ...snapshotDraft(draft),
@@ -23092,11 +23178,11 @@ var ProjectRoomEventBroker = class {
23092
23178
  }
23093
23179
  resolveCursor(key, afterEventId, plan) {
23094
23180
  if (afterEventId === void 0) return void 0;
23095
- const cursor = (0, import_protocols22.parseProjectRoomEventId)(afterEventId);
23096
- if (!cursor) throw new import_protocols22.ProjectRoomCursorError("CURSOR_EXPIRED");
23097
- if (cursor.epoch !== this.epoch) throw new import_protocols22.ProjectRoomCursorError("SERVER_RESTART");
23181
+ const cursor = (0, import_protocols23.parseProjectRoomEventId)(afterEventId);
23182
+ if (!cursor) throw new import_protocols23.ProjectRoomCursorError("CURSOR_EXPIRED");
23183
+ if (cursor.epoch !== this.epoch) throw new import_protocols23.ProjectRoomCursorError("SERVER_RESTART");
23098
23184
  if (plan.sequences.has(cursor.sequence) || this.sequenceScopes.get(cursor.sequence) !== key) {
23099
- throw new import_protocols22.ProjectRoomCursorError("CURSOR_EXPIRED");
23185
+ throw new import_protocols23.ProjectRoomCursorError("CURSOR_EXPIRED");
23100
23186
  }
23101
23187
  return cursor.sequence;
23102
23188
  }
@@ -23189,7 +23275,7 @@ function snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
23189
23275
 
23190
23276
  // src/services/collaboration/ProjectRoomRealtimePublisher.ts
23191
23277
  var import_node_crypto22 = require("crypto");
23192
- var import_protocols23 = require("@axiom-lattice/protocols");
23278
+ var import_protocols24 = require("@axiom-lattice/protocols");
23193
23279
  var BrokerProjectRoomRealtimePublisher = class {
23194
23280
  /** Creates a publisher around a broker and structured warning logger. */
23195
23281
  constructor(deps) {
@@ -23203,7 +23289,7 @@ var BrokerProjectRoomRealtimePublisher = class {
23203
23289
  /** Publishes a canonical message after projecting it to its public shape. */
23204
23290
  messageCreated(message) {
23205
23291
  this.publish("message.created", () => {
23206
- const projection = (0, import_protocols23.snapshotProjectRoomMessageRealtime)(message);
23292
+ const projection = (0, import_protocols24.snapshotProjectRoomMessageRealtime)(message);
23207
23293
  if (!projection) return void 0;
23208
23294
  return {
23209
23295
  sourceKey: `message:${projection.publicMessage.id}`,
@@ -23218,7 +23304,7 @@ var BrokerProjectRoomRealtimePublisher = class {
23218
23304
  this.publish("roster.changed", () => {
23219
23305
  const membership = snapshotInput(input, "roster");
23220
23306
  if (membership.membership.tenantId !== membership.tenantId || membership.membership.roomId !== membership.roomId || !safeId2(membership.membership.projectId)) throw new TypeError("Invalid roster scope");
23221
- const projection = (0, import_protocols23.snapshotProjectRoomBotMembershipRealtime)(membership.membership);
23307
+ const projection = (0, import_protocols24.snapshotProjectRoomBotMembershipRealtime)(membership.membership);
23222
23308
  if (!projection) return void 0;
23223
23309
  return {
23224
23310
  sourceKey: membership.sourceKey,
@@ -23233,7 +23319,7 @@ var BrokerProjectRoomRealtimePublisher = class {
23233
23319
  this.publish("membership.changed", () => {
23234
23320
  const membership = snapshotInput(input, "membership");
23235
23321
  if (membership.membership.tenantId !== membership.tenantId || !safeId2(membership.membership.projectId)) throw new TypeError("Invalid membership scope");
23236
- const projection = (0, import_protocols23.snapshotProjectRoomMembershipRealtime)(membership.membership);
23322
+ const projection = (0, import_protocols24.snapshotProjectRoomMembershipRealtime)(membership.membership);
23237
23323
  if (!projection) return void 0;
23238
23324
  return {
23239
23325
  sourceKey: membership.sourceKey,
@@ -23262,11 +23348,11 @@ var BrokerProjectRoomRealtimePublisher = class {
23262
23348
  /** Publishes a membership notice onto the affected user's channel scope. */
23263
23349
  membershipAffected(input) {
23264
23350
  this.publish("membership.affected", () => {
23265
- const value = (0, import_protocols23.snapshotExactRecord)(input, ["tenantId", "userId", "change", "projectId", "roomId", "sourceKey"]);
23351
+ const value = (0, import_protocols24.snapshotExactRecord)(input, ["tenantId", "userId", "change", "projectId", "roomId", "sourceKey"]);
23266
23352
  if (!value || !safeId2(value.tenantId) || !safeId2(value.userId) || !safeId2(value.projectId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || !["added", "removed", "role_changed"].includes(value.change)) {
23267
23353
  throw new TypeError("Invalid membership input");
23268
23354
  }
23269
- const scope = (0, import_protocols23.projectRoomUserEventScope)(value.tenantId, value.userId);
23355
+ const scope = (0, import_protocols24.projectRoomUserEventScope)(value.tenantId, value.userId);
23270
23356
  return {
23271
23357
  sourceKey: value.sourceKey,
23272
23358
  id: value.sourceKey,
@@ -23282,11 +23368,11 @@ var BrokerProjectRoomRealtimePublisher = class {
23282
23368
  /** Publishes a read-marker update onto the acting user's channel scope. */
23283
23369
  readChanged(input) {
23284
23370
  this.publish("read.changed", () => {
23285
- const value = (0, import_protocols23.snapshotExactRecord)(input, ["tenantId", "userId", "projectId", "roomId", "lastReadAt", "sourceKey"]);
23371
+ const value = (0, import_protocols24.snapshotExactRecord)(input, ["tenantId", "userId", "projectId", "roomId", "lastReadAt", "sourceKey"]);
23286
23372
  if (!value || !safeId2(value.tenantId) || !safeId2(value.userId) || !safeId2(value.projectId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || typeof value.lastReadAt !== "string" || !Number.isFinite(Date.parse(value.lastReadAt))) {
23287
23373
  throw new TypeError("Invalid read input");
23288
23374
  }
23289
- const scope = (0, import_protocols23.projectRoomUserEventScope)(value.tenantId, value.userId);
23375
+ const scope = (0, import_protocols24.projectRoomUserEventScope)(value.tenantId, value.userId);
23290
23376
  return {
23291
23377
  sourceKey: value.sourceKey,
23292
23378
  id: value.sourceKey,
@@ -23327,13 +23413,13 @@ var BrokerProjectRoomRealtimePublisher = class {
23327
23413
  };
23328
23414
  function snapshotInput(input, kind) {
23329
23415
  const keys2 = kind === "message" ? ["tenantId", "roomId", "message", "sourceKey"] : kind === "roster" ? ["tenantId", "roomId", "membership", "sourceKey"] : ["tenantId", "roomId", "membership", "sourceKey"];
23330
- const value = (0, import_protocols23.snapshotExactRecord)(input, [...keys2, "change"]);
23416
+ const value = (0, import_protocols24.snapshotExactRecord)(input, [...keys2, "change"]);
23331
23417
  const validChange = kind === "roster" ? ["added", "updated", "paused", "resumed", "removed"].includes(value?.change) : ["added", "role_changed", "removed"].includes(value?.change);
23332
23418
  if (!value || !safeId2(value.tenantId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey) || !validChange) throw new TypeError(`Invalid ${kind} input`);
23333
23419
  return value;
23334
23420
  }
23335
23421
  function snapshotTaskInput(input) {
23336
- const value = (0, import_protocols23.snapshotExactRecord)(input, ["tenantId", "roomId", "projectId", "taskId", "status", "ownerMembershipId", "updatedAt", "sourceKey"]);
23422
+ const value = (0, import_protocols24.snapshotExactRecord)(input, ["tenantId", "roomId", "projectId", "taskId", "status", "ownerMembershipId", "updatedAt", "sourceKey"]);
23337
23423
  if (!value || !safeId2(value.tenantId) || !safeId2(value.roomId) || !safeSourceKey(value.sourceKey)) throw new TypeError("Invalid task input");
23338
23424
  if (!safeId2(value.projectId) || !safeId2(value.taskId) || !safeId2(value.ownerMembershipId) || !["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"].includes(value.status)) throw new TypeError("Invalid task input");
23339
23425
  if (typeof value.updatedAt !== "string") throw new TypeError("Invalid task timestamp");
@@ -23359,7 +23445,7 @@ function safeErrorCode(error) {
23359
23445
 
23360
23446
  // src/services/collaboration/ProjectRoomTaskEventSubscriber.ts
23361
23447
  var import_core50 = require("@axiom-lattice/core");
23362
- var import_protocols24 = require("@axiom-lattice/protocols");
23448
+ var import_protocols25 = require("@axiom-lattice/protocols");
23363
23449
  var ProjectRoomTaskEventSubscriber = class {
23364
23450
  /** Creates a bounded Project task lifecycle observer. */
23365
23451
  constructor(deps) {
@@ -23469,7 +23555,7 @@ var ProjectRoomTaskEventSubscriber = class {
23469
23555
  }
23470
23556
  }
23471
23557
  parse(value) {
23472
- const row = (0, import_protocols24.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
23558
+ const row = (0, import_protocols25.snapshotExactRecord)(value, ["tenantId", "workspaceId", "projectId", "taskId", "status", "action", "eventKey", "updatedAt"], ["threadId"]);
23473
23559
  const actions = ["in_progress", "interrupted", "failed", "completed", "cancelled", "reassigned"];
23474
23560
  const statuses = ["pending", "in_progress", "review", "failed", "interrupted", "completed", "cancelled"];
23475
23561
  if (!row || !actions.includes(String(row.action)) || !statuses.includes(String(row.status)) || !["tenantId", "workspaceId", "projectId", "taskId", "eventKey", "updatedAt"].every((key) => typeof row[key] === "string" && row[key].length > 0) || !Number.isFinite(Date.parse(row.updatedAt)) || row.threadId !== void 0 && typeof row.threadId !== "string") return void 0;
@@ -23665,7 +23751,7 @@ function createRoomPushNotifier(input) {
23665
23751
  }
23666
23752
 
23667
23753
  // src/services/collaboration/WorkspaceRoomEventsService.ts
23668
- var import_protocols25 = require("@axiom-lattice/protocols");
23754
+ var import_protocols26 = require("@axiom-lattice/protocols");
23669
23755
 
23670
23756
  // src/services/collaboration/ProjectRoomSseWriter.ts
23671
23757
  var DEFAULT_MAX_FRAMES = 256;
@@ -23913,7 +23999,7 @@ var WorkspaceRoomEventsService = class {
23913
23999
  const clear = (timer) => {
23914
24000
  if (timer !== void 0) clearTimeout(timer);
23915
24001
  };
23916
- const userScope = (0, import_protocols25.projectRoomUserEventScope)(actor3.tenantId, actor3.userId);
24002
+ const userScope = (0, import_protocols26.projectRoomUserEventScope)(actor3.tenantId, actor3.userId);
23917
24003
  const userScopeKey = JSON.stringify([userScope.tenantId, userScope.roomId, userScope.projectId]);
23918
24004
  const roomScopeKey = (scope) => JSON.stringify([scope.tenantId, scope.roomId, scope.projectId]);
23919
24005
  const serializeScoped = (scope, event) => scope === null ? `id: ${event.id}
@@ -24023,7 +24109,7 @@ data: ${JSON.stringify({ ...event, scope })}
24023
24109
  accessTimer = setTimeout(() => {
24024
24110
  accessTimer = void 0;
24025
24111
  if (closed) return;
24026
- const projectIds = [...subscriptions.values()].map((entry) => entry.scope.projectId).filter((projectId) => projectId !== import_protocols25.PROJECT_ROOM_USER_CHANNEL_PROJECT);
24112
+ const projectIds = [...subscriptions.values()].map((entry) => entry.scope.projectId).filter((projectId) => projectId !== import_protocols26.PROJECT_ROOM_USER_CHANNEL_PROJECT);
24027
24113
  Promise.all(projectIds.map((projectId) => Promise.resolve().then(() => this.deps.requireReadAccess({ tenantId: actor3.tenantId, userId: actor3.userId, projectId })))).then(() => {
24028
24114
  if (!closed) scheduleAccessCheck();
24029
24115
  }, () => {
@@ -24066,7 +24152,7 @@ function createWorkspaceMemberRoomLister(deps) {
24066
24152
  }
24067
24153
 
24068
24154
  // src/routes/workspace-room-events.ts
24069
- var import_protocols26 = require("@axiom-lattice/protocols");
24155
+ var import_protocols27 = require("@axiom-lattice/protocols");
24070
24156
  function registerWorkspaceRoomEventRoutes(app2, deps) {
24071
24157
  app2.get("/api/workspaces/:workspaceId/room-events", async (request, reply) => {
24072
24158
  try {
@@ -24094,7 +24180,7 @@ function registerWorkspaceRoomEventRoutes(app2, deps) {
24094
24180
  });
24095
24181
  }
24096
24182
  function exactParams(params) {
24097
- const value = (0, import_protocols26.snapshotExactRecord)(params, ["workspaceId"]);
24183
+ const value = (0, import_protocols27.snapshotExactRecord)(params, ["workspaceId"]);
24098
24184
  if (!value || typeof value.workspaceId !== "string" || !value.workspaceId.trim()) throw new InvalidRealtimeRequestError();
24099
24185
  return { workspaceId: value.workspaceId };
24100
24186
  }
@@ -24222,7 +24308,7 @@ function snapshotDataRecord(value) {
24222
24308
  for (const key of Reflect.ownKeys(descriptors)) {
24223
24309
  if (typeof key !== "string") return void 0;
24224
24310
  const descriptor = descriptors[key];
24225
- const data = (0, import_protocols27.descriptorDataValue)(descriptor);
24311
+ const data = (0, import_protocols28.descriptorDataValue)(descriptor);
24226
24312
  if (!data) return void 0;
24227
24313
  result[key] = data.value;
24228
24314
  }
@@ -24237,7 +24323,7 @@ function isPublicRoomAddress(message) {
24237
24323
  }
24238
24324
  async function validateReassignmentThread(threads, input) {
24239
24325
  const thread = snapshotThread(await threads.getThreadById(input.tenantId, input.newThreadId));
24240
- const metadata = (0, import_protocols27.snapshotExactRecord)(thread?.metadata, [
24326
+ const metadata = (0, import_protocols28.snapshotExactRecord)(thread?.metadata, [
24241
24327
  "source",
24242
24328
  "kind",
24243
24329
  "workspaceId",
@@ -24269,6 +24355,15 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
24269
24355
  const accessService = new ProjectAccessService({ projectStore, membershipStore: projectMembershipStore, userTenantLinkStore });
24270
24356
  const realtimeMode = resolveProjectRoomRealtimeMode();
24271
24357
  const realtimeLog = options.projectTaskLog ?? { warn: () => void 0 };
24358
+ const roomMessageRetention = createRoomMessageRetentionJob({
24359
+ messages: projectRoomMessageStore,
24360
+ days: process.env.PROJECT_ROOM_MESSAGE_RETENTION_DAYS,
24361
+ log: realtimeLog
24362
+ });
24363
+ if (roomMessageRetention) {
24364
+ roomMessageRetention.start();
24365
+ app2.addHook("onClose", () => roomMessageRetention.dispose());
24366
+ }
24272
24367
  const roomPushNotifier = createRoomPushNotifier({
24273
24368
  subscriptionStore: userPushSubscriptionStore,
24274
24369
  membershipStore: projectMembershipStore,
@@ -24943,9 +25038,9 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
24943
25038
  function tryCreateProjectTaskRuntime(input) {
24944
25039
  let projectWorkItems;
24945
25040
  try {
24946
- projectWorkItems = (0, import_protocols27.requireProjectTaskWorkItemStore)(input.taskWorkItemStore);
25041
+ projectWorkItems = (0, import_protocols28.requireProjectTaskWorkItemStore)(input.taskWorkItemStore);
24947
25042
  } catch (error) {
24948
- if (error instanceof import_protocols27.ProjectTaskStoreUnsupportedError) {
25043
+ if (error instanceof import_protocols28.ProjectTaskStoreUnsupportedError) {
24949
25044
  input.log?.warn("project-task:runtime-unavailable", {
24950
25045
  code: error.code,
24951
25046
  missingMethods: error.missingMethods
@@ -26855,7 +26950,7 @@ var import_core66 = require("@axiom-lattice/core");
26855
26950
 
26856
26951
  // src/router/MessageRouter.ts
26857
26952
  var import_core65 = require("@axiom-lattice/core");
26858
- var import_protocols28 = require("@axiom-lattice/protocols");
26953
+ var import_protocols29 = require("@axiom-lattice/protocols");
26859
26954
  var import_crypto12 = require("crypto");
26860
26955
  var BindingNotFoundError = class extends Error {
26861
26956
  constructor(message) {
@@ -26890,10 +26985,10 @@ function clarifyText(clarify) {
26890
26985
  return ["```clarify", JSON.stringify({ questions: clarify.questions }), "```"].join("\n");
26891
26986
  }
26892
26987
  function exactDataValues(value, required, optional = []) {
26893
- return (0, import_protocols28.snapshotExactRecord)(value, required, optional);
26988
+ return (0, import_protocols29.snapshotExactRecord)(value, required, optional);
26894
26989
  }
26895
26990
  function uniqueNonemptyStrings(value) {
26896
- const snapshot = (0, import_protocols28.snapshotExactArray)(value);
26991
+ const snapshot = (0, import_protocols29.snapshotExactArray)(value);
26897
26992
  if (!snapshot || snapshot.length === 0 || snapshot.some((entry) => typeof entry !== "string" || entry.length === 0)) return void 0;
26898
26993
  const values = snapshot;
26899
26994
  return new Set(values).size === values.length ? values : void 0;
@@ -27401,7 +27496,7 @@ var MessageRouter = class {
27401
27496
 
27402
27497
  // src/channels/room/RoomChannelAdapter.ts
27403
27498
  var import_zod15 = require("zod");
27404
- var import_protocols29 = require("@axiom-lattice/protocols");
27499
+ var import_protocols30 = require("@axiom-lattice/protocols");
27405
27500
  var roomConfigSchema = import_zod15.z.object({}).strict();
27406
27501
  function createRoomChannelAdapter(writer) {
27407
27502
  return {
@@ -27462,7 +27557,7 @@ function exactStrings(value, keys2) {
27462
27557
  function exactValues2(value, required, optional = []) {
27463
27558
  try {
27464
27559
  if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
27465
- return (0, import_protocols29.snapshotExactRecord)(value, required, optional);
27560
+ return (0, import_protocols30.snapshotExactRecord)(value, required, optional);
27466
27561
  } catch {
27467
27562
  return void 0;
27468
27563
  }
@@ -27507,14 +27602,14 @@ async function prepareProjectTaskRuntime(runtime, log2) {
27507
27602
  }
27508
27603
 
27509
27604
  // src/index.ts
27510
- var import_protocols36 = require("@axiom-lattice/protocols");
27605
+ var import_protocols37 = require("@axiom-lattice/protocols");
27511
27606
  process.on("unhandledRejection", (reason, promise) => {
27512
27607
  console.error("\u672A\u5904\u7406\u7684Promise\u62D2\u7EDD:", reason);
27513
27608
  });
27514
27609
  var DEFAULT_LOGGER_CONFIG = {
27515
27610
  name: "default",
27516
27611
  description: "Default logger for lattice-gateway service",
27517
- type: import_protocols36.LoggerType.PINO,
27612
+ type: import_protocols37.LoggerType.PINO,
27518
27613
  serviceName: "lattice/gateway",
27519
27614
  loggerName: "lattice/gateway"
27520
27615
  };