@desplega.ai/agent-swarm 2.5.1 → 2.5.2

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 (155) hide show
  1. package/dist/{acp-adapter-7g6bpwbk.js → acp-adapter-csh0zz3b.js} +1 -1
  2. package/dist/{actions-w8xd014k.js → actions-6xx079d1.js} +17 -17
  3. package/dist/{amp-adapter-z4qvhacj.js → amp-adapter-8n6f0hz8.js} +2 -2
  4. package/dist/{app-nndcvftq.js → app-ft6r6v23.js} +3 -3
  5. package/dist/{assistant-hjmqyscx.js → assistant-vt2cyfzd.js} +18 -18
  6. package/dist/{boot-reembed-r8rhf9h8.js → boot-reembed-r3e808ky.js} +1 -1
  7. package/dist/{boot-reembed-vwcj2y5d.js → boot-reembed-tgrfy27t.js} +1 -1
  8. package/dist/{boot-scrub-sweep-fr9q36ne.js → boot-scrub-sweep-masdwxkm.js} +2 -2
  9. package/dist/{boot-seeds-9jqwnegq.js → boot-seeds-0n82qc7q.js} +4 -4
  10. package/dist/{claude-adapter-2f8b85df.js → claude-adapter-s7j47k06.js} +2 -2
  11. package/dist/{claude-managed-setup-c3hp36ph.js → claude-managed-setup-3hzrgrnk.js} +1 -1
  12. package/dist/{claude-sdk-session-05kat8rv.js → claude-sdk-session-0zrdzyx2.js} +6905 -6855
  13. package/dist/{cli-mz2ygeyq.js → cli-0vgy5wfw.js} +2 -2
  14. package/dist/{cli-eym3jg7w.js → cli-14v1sxxy.js} +6 -6
  15. package/dist/{cli-e9btqw4y.js → cli-15xd0j7w.js} +18 -13
  16. package/dist/{cli-v2g93k4v.js → cli-3e9vs93g.js} +4 -4
  17. package/dist/{cli-1dp1zj04.js → cli-4qkg9968.js} +3 -3
  18. package/dist/{cli-ba8ne1es.js → cli-4rvr7zfx.js} +10 -0
  19. package/dist/{cli-rngde2jv.js → cli-6y43v79h.js} +1 -1
  20. package/dist/{cli-z63a269p.js → cli-7ccf7akh.js} +1 -1
  21. package/dist/{cli-z2dv25mf.js → cli-86zpfje5.js} +116 -5
  22. package/dist/{cli-fes51ya2.js → cli-aaqnqpyw.js} +2 -2
  23. package/dist/{cli-qfm6my86.js → cli-b1tv22wr.js} +1 -1
  24. package/dist/{cli-xc65x52q.js → cli-b63d08rs.js} +1 -1
  25. package/dist/{cli-gwcf52gz.js → cli-b6tnjdvx.js} +11 -7
  26. package/dist/{cli-9mm5ade4.js → cli-bpbcpd8b.js} +1 -1
  27. package/dist/{cli-qfjm4gvt.js → cli-cf63dnxj.js} +2 -2
  28. package/dist/{cli-q9pzwxvk.js → cli-csh8fnbg.js} +82 -16
  29. package/dist/{cli-0jy85zz4.js → cli-cyfgxnvb.js} +7 -7
  30. package/dist/{cli-y3zyaee5.js → cli-d172svcw.js} +5 -5
  31. package/dist/{cli-mq7kg1b1.js → cli-e91vshb1.js} +41 -6
  32. package/dist/{cli-cah5detr.js → cli-edtm741g.js} +5 -5
  33. package/dist/{cli-ajqhxtnz.js → cli-f3pfn4x3.js} +1 -1
  34. package/dist/{cli-hadv0725.js → cli-f55b6ky0.js} +1 -1
  35. package/dist/{cli-r9fy0ddc.js → cli-fgn7yg5r.js} +1 -1
  36. package/dist/{cli-kcsd1ez8.js → cli-h5d22pfs.js} +249 -68
  37. package/dist/{cli-2wba1ac9.js → cli-ha22h0eg.js} +20 -20
  38. package/dist/{cli-pyy4c9ch.js → cli-j3dwd4kz.js} +173 -134
  39. package/dist/{cli-j1eghqfm.js → cli-jmcjbjkt.js} +1 -1
  40. package/dist/{cli-22rmcjkg.js → cli-kcnwn85g.js} +4 -3
  41. package/dist/{cli-rh5smt8t.js → cli-mntxtkhn.js} +12 -2
  42. package/dist/{cli-2jg61wab.js → cli-n2918sed.js} +9 -9
  43. package/dist/{cli-3ee5z0q0.js → cli-qrjv7t18.js} +1 -1
  44. package/dist/{cli-sn1vbtg2.js → cli-vaxw3bg0.js} +3 -3
  45. package/dist/{cli-cwyafhw1.js → cli-wadzapwb.js} +1 -1
  46. package/dist/{cli-jpxsrxcb.js → cli-xw9q173h.js} +1 -1
  47. package/dist/{cli-znvq0k3t.js → cli-xzge46sj.js} +2 -2
  48. package/dist/{cli-nj12tn2c.js → cli-y3dzwyy3.js} +3 -3
  49. package/dist/{cli-xd4eqtr2.js → cli-ydg6ep51.js} +1 -1
  50. package/dist/cli.js +16 -15
  51. package/dist/{codex-adapter-p4ptwar5.js → codex-adapter-brh2tcxr.js} +1 -1
  52. package/dist/{codex-session-runner-964c7dnk.js → codex-session-runner-0dnj21qs.js} +1 -1
  53. package/dist/{commands-mbvhbrcy.js → commands-1cnvseqx.js} +2 -2
  54. package/dist/{controller-gnq1k1mf.js → controller-kc7s9xhn.js} +2 -2
  55. package/dist/{controllers-connect-6dkm71tg.js → controllers-connect-jzx7t4bn.js} +18 -18
  56. package/dist/{cursor-adapter-yq5xgfcg.js → cursor-adapter-qpwp5sfg.js} +1 -1
  57. package/dist/{db-af9y8nkf.js → db-4vq88jkc.js} +3 -3
  58. package/dist/{db-88wcymxt.js → db-v5ytg5pw.js} +1 -1
  59. package/dist/{dispatcher-606ydx5v.js → dispatcher-trtcrqae.js} +16 -16
  60. package/dist/{dsh-adapter-tvhc4k2d.js → dsh-adapter-f20xwn1z.js} +1 -1
  61. package/dist/{external-channel-y8q5z8z2.js → external-channel-n9bymc2n.js} +2 -2
  62. package/dist/{grok-adapter-39aha52t.js → grok-adapter-4kpmmnr6.js} +2 -2
  63. package/dist/{handlers-rk9dqech.js → handlers-ptsraqa8.js} +19 -19
  64. package/dist/{heartbeat-jfe9zfjr.js → heartbeat-60qtxtjf.js} +19 -19
  65. package/dist/{hook-ffevzed1.js → hook-ngtvh729.js} +1 -1
  66. package/dist/{hook-b1mez1m8.js → hook-rbktcstg.js} +1 -1
  67. package/dist/{http-d5b44f1r.js → http-z8xy72gp.js} +334 -86
  68. package/dist/{index-nq8hhv28.js → index-06qkmcx6.js} +10 -9
  69. package/dist/{index-d2qeem97.js → index-1cscynkb.js} +16 -16
  70. package/dist/{index-5en23s5z.js → index-a9nsavhx.js} +1 -1
  71. package/dist/{index-4q3vj1yr.js → index-r70q0xjx.js} +16 -16
  72. package/dist/{index-mj46rk9k.js → index-s193j5fh.js} +19 -19
  73. package/dist/{keepalive-wsby1btq.js → keepalive-a9srcphj.js} +3 -3
  74. package/dist/{lead-paa141j6.js → lead-3devneqy.js} +26 -26
  75. package/dist/{maintenance-vnshcyv9.js → maintenance-0er16h2y.js} +1 -1
  76. package/dist/{oauth-refresh-sweep-d6sqn5np.js → oauth-refresh-sweep-b65jcyw2.js} +2 -2
  77. package/dist/{onboard-nr4xhpzy.js → onboard-wqywz5py.js} +2 -2
  78. package/dist/{otel-impl-ytn9wyv9.js → otel-impl-vk32s884.js} +1 -1
  79. package/dist/{pricing-refresh-pva04zee.js → pricing-refresh-t27anv4z.js} +3 -3
  80. package/dist/rbac-roles-452665y0.js +26 -0
  81. package/dist/{rbac-roles-7rc1q3g4.js → rbac-roles-bmcgsxjn.js} +12 -2
  82. package/dist/{render-v2-pyfsg9zk.js → render-v2-0ttsk2j4.js} +3 -3
  83. package/dist/{resume-phj8xhqr.js → resume-a26kvr41.js} +5 -5
  84. package/dist/{session-access-jzx2z9h5.js → session-access-dgh9nkwk.js} +4 -4
  85. package/dist/{setup-rfg0f0sg.js → setup-9vc9qahm.js} +1 -1
  86. package/dist/{work-objects-44z2yjg8.js → work-objects-vn8nkxwn.js} +19 -19
  87. package/dist/{worker-zsfqzxhm.js → worker-1x1h8vnm.js} +26 -26
  88. package/openapi.json +463 -3
  89. package/package.json +4 -3
  90. package/src/be/db/session-tree.ts +89 -2
  91. package/src/be/db/session-visibility.ts +31 -0
  92. package/src/be/db/tasks/read.ts +18 -5
  93. package/src/be/db.ts +2 -0
  94. package/src/be/migrations/233_script_run_session_tokens.sql +8 -0
  95. package/src/be/migrations/235_chat_relay_defer.sql +86 -0
  96. package/src/be/migrations/237_session_inbox_cleanup.sql +75 -0
  97. package/src/be/rbac-roles.ts +138 -0
  98. package/src/be/scripts/run-credential.ts +64 -0
  99. package/src/be/scripts/run-saved.ts +3 -2
  100. package/src/be/users.ts +28 -4
  101. package/src/http/all-routes.ts +1 -0
  102. package/src/http/approval-requests.ts +46 -6
  103. package/src/http/index.ts +2 -0
  104. package/src/http/schedules.ts +26 -0
  105. package/src/http/scripts.ts +2 -2
  106. package/src/http/sessions.ts +93 -2
  107. package/src/http/user-roles.ts +173 -0
  108. package/src/http/users.ts +9 -0
  109. package/src/http/x.ts +2 -2
  110. package/src/integrations/chat-sdk/commands.ts +14 -1
  111. package/src/integrations/chat-sdk/inbound.ts +40 -5
  112. package/src/integrations/chat-sdk/outbound.ts +35 -10
  113. package/src/integrations/chat-sdk/reactions.ts +107 -0
  114. package/src/integrations/chat-sdk/relay.ts +75 -7
  115. package/src/integrations/chat-sdk/thread-buffer.ts +2 -0
  116. package/src/integrations/reaction-events.ts +20 -0
  117. package/src/providers/amp-adapter.ts +1 -1
  118. package/src/rbac/legacy-policy.ts +3 -0
  119. package/src/rbac/permissions.ts +8 -0
  120. package/src/scheduler/schedule-task.ts +44 -3
  121. package/src/scheduler/scheduler.ts +4 -4
  122. package/src/scripts-runtime/loader.ts +8 -1
  123. package/src/slack/ack.ts +2 -1
  124. package/src/slack/reaction-shortcode.ts +4 -7
  125. package/src/tasks/worker-follow-up.ts +30 -0
  126. package/src/tests/approval-requests-notifications.test.ts +189 -0
  127. package/src/tests/chat-sdk-commands.test.ts +12 -0
  128. package/src/tests/chat-sdk-inbound.test.ts +163 -9
  129. package/src/tests/chat-sdk-outbound-files.test.ts +9 -2
  130. package/src/tests/chat-sdk-relay.test.ts +361 -10
  131. package/src/tests/chat-sdk-tools.test.ts +104 -0
  132. package/src/tests/docs-index-footprint.test.js +3 -3
  133. package/src/tests/http-users.test.ts +38 -0
  134. package/src/tests/migration-237-session-inbox-cleanup.test.ts +136 -0
  135. package/src/tests/rbac-engine.test.ts +2 -0
  136. package/src/tests/rbac-roles.test.ts +10 -0
  137. package/src/tests/schedule-http-triage-tools.test.ts +44 -0
  138. package/src/tests/script-api-credential.test.ts +173 -0
  139. package/src/tests/script-connections.test.ts +4 -0
  140. package/src/tests/script-run-config-scope.test.ts +120 -0
  141. package/src/tests/script-run-token.test.ts +75 -0
  142. package/src/tests/scripts-http.test.ts +19 -0
  143. package/src/tests/sessions-tree.test.ts +242 -0
  144. package/src/tests/user-roles-http.test.ts +204 -0
  145. package/src/tests/workflow-hitl-dynamic-questions.test.ts +1 -1
  146. package/src/tools/chat-reply.ts +2 -0
  147. package/src/tools/schedules/patch-schedule.ts +18 -0
  148. package/src/tools/schedules/update-schedule.ts +18 -0
  149. package/src/types.ts +16 -0
  150. package/src/workflows/approval-notifications.ts +214 -0
  151. package/src/workflows/executors/human-in-the-loop.ts +11 -172
  152. package/src/workflows/executors/swarm-script.ts +2 -2
  153. package/templates/schedules/weekly-harness-upgrade-check/content.md +1 -1
  154. package/templates/skills/code-quality/content.md +1 -1
  155. package/dist/rbac-roles-ff1ffmec.js +0 -12
@@ -301,7 +301,7 @@ import {
301
301
  hasCapability,
302
302
  getEnabledCapabilities,
303
303
  createServer
304
- } from "./cli-kcsd1ez8.js";
304
+ } from "./cli-h5d22pfs.js";
305
305
  import {
306
306
  chatThreadOfContextKey,
307
307
  agentContextKey,
@@ -424,6 +424,7 @@ import {
424
424
  init_session_moves,
425
425
  getSessionReadState,
426
426
  getSessionTree,
427
+ triageSessionList,
427
428
  init_session_tree,
428
429
  setHumanFreeQueueListener,
429
430
  drainHumanFreeReclassifyQueue,
@@ -750,31 +751,39 @@ import {
750
751
  countScriptRunJournalSteps2,
751
752
  countScriptRunJournalAgentTaskSteps2,
752
753
  init_db3
753
- } from "./cli-q9pzwxvk.js";
754
+ } from "./cli-csh8fnbg.js";
754
755
  import {
756
+ PRIMARY_ROLE_NAMES2,
755
757
  getUserGrant2,
758
+ listUserRoles2,
759
+ listRbacRoles2,
760
+ InvalidRoleSetError2,
761
+ LastAdminError2,
762
+ assertNotLastAdmin2,
763
+ setUserRoles2,
756
764
  init_rbac_roles
757
- } from "./cli-z2dv25mf.js";
758
- import"./cli-v2g93k4v.js";
765
+ } from "./cli-86zpfje5.js";
766
+ import"./cli-3e9vs93g.js";
759
767
  import {
760
768
  normalizeModelKey
761
- } from "./cli-9mm5ade4.js";
769
+ } from "./cli-bpbcpd8b.js";
762
770
  import {
763
771
  upsertModelCatalogOverlay,
764
772
  deleteModelCatalogOverlay,
765
773
  loadModelsCatalog,
766
774
  requestModelCatalogRefresh2
767
- } from "./cli-mz2ygeyq.js";
775
+ } from "./cli-0vgy5wfw.js";
768
776
  import {
769
777
  AMP_ESTIMATE_MODELS,
770
778
  ampBillsCacheWrites,
771
779
  resolveAmpModel
772
- } from "./cli-jpxsrxcb.js";
780
+ } from "./cli-xw9q173h.js";
773
781
  import {
774
782
  automationIntegrationFixUrl,
775
783
  preflightAutomation,
776
784
  getAutomationSetupStates,
777
785
  listEnabledAutomationPreflightInputs,
786
+ dispatchApprovalNotifications,
778
787
  createApprovalFollowUpTask,
779
788
  validateJsonSchema,
780
789
  workflowSaveWarnings,
@@ -783,7 +792,7 @@ import {
783
792
  generateEdges,
784
793
  definitionNodeIds,
785
794
  validateDefinition
786
- } from "./cli-pyy4c9ch.js";
795
+ } from "./cli-j3dwd4kz.js";
787
796
  import {
788
797
  require_dist2,
789
798
  isInvalidClientError,
@@ -847,7 +856,7 @@ import {
847
856
  MAX_SCRIPT_WALL_CLOCK_MS,
848
857
  require_typescript2,
849
858
  checkImportAllowlist,
850
- runScript,
859
+ runScriptWithRunCredential,
851
860
  extractScriptSignature,
852
861
  extractArgsJsonSchema,
853
862
  checkQuickJSCompat,
@@ -863,14 +872,14 @@ import {
863
872
  typecheckWithAmbient,
864
873
  typecheckScript,
865
874
  parseSkillContent
866
- } from "./cli-mq7kg1b1.js";
875
+ } from "./cli-e91vshb1.js";
867
876
  import {
868
877
  buildAuthorizationUrl,
869
878
  exchangeAuthorizationCode,
870
879
  oauthAppRowToProviderConfig,
871
880
  forceRefreshAuthorizationOrThrow,
872
881
  forceRefreshTokenOrThrow
873
- } from "./cli-rngde2jv.js";
882
+ } from "./cli-6y43v79h.js";
874
883
  import {
875
884
  signalProcessGroup,
876
885
  detachedProcessGroup,
@@ -898,8 +907,8 @@ import {
898
907
  getSlackApp2,
899
908
  startSlackApp2,
900
909
  stopSlackApp2
901
- } from "./cli-e9btqw4y.js";
902
- import"./cli-xc65x52q.js";
910
+ } from "./cli-15xd0j7w.js";
911
+ import"./cli-b63d08rs.js";
903
912
  import"./cli-qqzmjxkf.js";
904
913
  import {
905
914
  _fetchHolder,
@@ -919,7 +928,7 @@ import {
919
928
  import {
920
929
  retryFailedRun2,
921
930
  cancelWorkflowRun2
922
- } from "./cli-nj12tn2c.js";
931
+ } from "./cli-y3dzwyy3.js";
923
932
  import {
924
933
  duplicateGuardedQueryKey,
925
934
  warnIfCorsAllowsAnyOrigin,
@@ -964,7 +973,7 @@ import {
964
973
  bodyListTask,
965
974
  describeRequestRoute,
966
975
  route
967
- } from "./cli-y3zyaee5.js";
976
+ } from "./cli-d172svcw.js";
968
977
  import {
969
978
  isMultiRuntimeEnabled
970
979
  } from "./cli-e8xyjvfc.js";
@@ -995,7 +1004,7 @@ import {
995
1004
  resolvePoolDelivery2,
996
1005
  createPoolAgent2,
997
1006
  init_db
998
- } from "./cli-1dp1zj04.js";
1007
+ } from "./cli-4qkg9968.js";
999
1008
  import {
1000
1009
  RATING_MODEL_MAX_LENGTH,
1001
1010
  REFERENCES_SOURCE_MAX_LENGTH,
@@ -1011,8 +1020,8 @@ import {
1011
1020
  checkHeartbeatChecklist2,
1012
1021
  runHeartbeatSweep2,
1013
1022
  stopHeartbeat2
1014
- } from "./cli-2jg61wab.js";
1015
- import"./cli-xd4eqtr2.js";
1023
+ } from "./cli-n2918sed.js";
1024
+ import"./cli-ydg6ep51.js";
1016
1025
  import {
1017
1026
  import_websocket,
1018
1027
  import_websocket_server
@@ -1021,7 +1030,7 @@ import {
1021
1030
  runtimeSupervisorStatus,
1022
1031
  startRuntimeSupervisor,
1023
1032
  stopRuntimeSupervisor
1024
- } from "./cli-0jy85zz4.js";
1033
+ } from "./cli-cyfgxnvb.js";
1025
1034
  import"./cli-ns59dc6r.js";
1026
1035
  import {
1027
1036
  ACP_TARGET_IDS
@@ -1041,11 +1050,11 @@ import {
1041
1050
  memoryRelevance,
1042
1051
  isUnknownModelError,
1043
1052
  writeSkillsToFilesystem
1044
- } from "./cli-cwyafhw1.js";
1053
+ } from "./cli-wadzapwb.js";
1045
1054
  import {
1046
1055
  inviteEmailToSharedOrg,
1047
1056
  ensureAgentFsCredentialsForAgent
1048
- } from "./cli-r9fy0ddc.js";
1057
+ } from "./cli-fgn7yg5r.js";
1049
1058
  import {
1050
1059
  Anthropic
1051
1060
  } from "./cli-3qv8naq8.js";
@@ -1084,7 +1093,7 @@ import {
1084
1093
  revokeAgentTokens,
1085
1094
  fingerprintApiKey,
1086
1095
  init_users
1087
- } from "./cli-gwcf52gz.js";
1096
+ } from "./cli-b6tnjdvx.js";
1088
1097
  import"./cli-v41kn3cd.js";
1089
1098
  import"./cli-wgtk7xxr.js";
1090
1099
  import"./cli-1f0gp9vz.js";
@@ -1099,7 +1108,7 @@ import {
1099
1108
  clearAuditSink,
1100
1109
  can,
1101
1110
  init_rbac
1102
- } from "./cli-ba8ne1es.js";
1111
+ } from "./cli-4rvr7zfx.js";
1103
1112
  import {
1104
1113
  ASSET_KEY_MAX_LENGTH,
1105
1114
  normalizeAssetKey,
@@ -1136,6 +1145,8 @@ import {
1136
1145
  AgentTaskSchema,
1137
1146
  TaskAttachmentSchema,
1138
1147
  UserSchema,
1148
+ RbacRoleSchema,
1149
+ UserRbacRolesSchema,
1139
1150
  UserCommsPrefsSchema,
1140
1151
  InboxItemTypeSchema,
1141
1152
  InboxItemStatusSchema,
@@ -1246,7 +1257,7 @@ import {
1246
1257
  KvKeySchema,
1247
1258
  KvEntrySchema,
1248
1259
  init_types
1249
- } from "./cli-rh5smt8t.js";
1260
+ } from "./cli-mntxtkhn.js";
1250
1261
  import {
1251
1262
  IDENTITY_FIELD_BUDGETS,
1252
1263
  IdentityFieldBudgetError,
@@ -1319,7 +1330,7 @@ import {
1319
1330
  import {
1320
1331
  init_package,
1321
1332
  package_default
1322
- } from "./cli-22rmcjkg.js";
1333
+ } from "./cli-kcnwn85g.js";
1323
1334
  import {
1324
1335
  realtimeBus,
1325
1336
  init_bus
@@ -5989,6 +6000,7 @@ init_db3();
5989
6000
  init_users();
5990
6001
  init_rbac();
5991
6002
  init_request_auth_context();
6003
+ init_secret_scrubber();
5992
6004
  init_event_bus();
5993
6005
  var QuestionSchema = object2({
5994
6006
  id: string2(),
@@ -6154,14 +6166,15 @@ var createRoute = route({
6154
6166
  notifications: array2(object2({
6155
6167
  channel: _enum2(["slack", "email"]),
6156
6168
  target: string2()
6157
- })).optional()
6169
+ })).optional().describe("Where to announce the request. A Slack target (channel or user ID) gets a card with the title, the questions and a link to the dashboard page that answers it. Slack targets need a lead agent caller (403 otherwise). Email is not supported yet and is skipped.")
6158
6170
  }),
6159
6171
  responses: {
6160
6172
  201: {
6161
6173
  description: "Approval request created",
6162
6174
  schema: object2({ approvalRequest: ApprovalRequestSchema })
6163
6175
  },
6164
- 400: { description: "Validation error" }
6176
+ 400: { description: "Validation error" },
6177
+ 403: { description: "Slack notifications require a lead agent" }
6165
6178
  },
6166
6179
  auth: { apiKey: true }
6167
6180
  });
@@ -6375,7 +6388,7 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
6375
6388
  const parsed = await cancelRoute.parse(req, res, pathSegments, queryParams);
6376
6389
  if (!parsed)
6377
6390
  return true;
6378
- const { principal, resolvedBy } = await approvalCancelPrincipal(req);
6391
+ const { principal, resolvedBy } = await approvalCallerPrincipal(req);
6379
6392
  const result = await cancelApprovalRequest({
6380
6393
  id: parsed.params.id,
6381
6394
  reason: parsed.body.reason,
@@ -6411,6 +6424,14 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
6411
6424
  const parsed = await createRoute.parse(req, res, pathSegments, queryParams);
6412
6425
  if (!parsed)
6413
6426
  return true;
6427
+ if (parsed.body.notifications?.some((notification) => notification.channel === "slack")) {
6428
+ const { principal } = await approvalCallerPrincipal(req);
6429
+ const decision = can({ principal, verb: "integration.slack.post", source: "http" });
6430
+ if (!decision.allow) {
6431
+ jsonError(res, SLACK_NOTIFICATION_REFUSED, 403);
6432
+ return true;
6433
+ }
6434
+ }
6414
6435
  const id = crypto.randomUUID();
6415
6436
  const auth = getRequestAuth(req);
6416
6437
  const rawCallerAgentId = req.headers["x-agent-id"];
@@ -6428,6 +6449,18 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
6428
6449
  notificationChannels: parsed.body.notifications,
6429
6450
  createdBy
6430
6451
  });
6452
+ const notifications = parsed.body.notifications;
6453
+ if (notifications?.length && request.status === "pending") {
6454
+ dispatchApprovalNotifications({
6455
+ requestId: request.id,
6456
+ title: request.title,
6457
+ questions: parsed.body.questions,
6458
+ timeoutSeconds: parsed.body.timeoutSeconds,
6459
+ notifications
6460
+ }).catch((err) => {
6461
+ console.error("[approval-requests] Unexpected error dispatching notifications:", scrubSecrets(err instanceof Error ? err.message : String(err)));
6462
+ });
6463
+ }
6431
6464
  createRoute.respond(res, 201, {
6432
6465
  approvalRequest: await toApprovalRequestResponse(request)
6433
6466
  });
@@ -6456,7 +6489,8 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
6456
6489
  }
6457
6490
  return false;
6458
6491
  }
6459
- async function approvalCancelPrincipal(req) {
6492
+ var SLACK_NOTIFICATION_REFUSED = "Slack notifications require lead privileges (integration.slack.post). Create the request without them, or ask the lead to post the link.";
6493
+ async function approvalCallerPrincipal(req) {
6460
6494
  const auth = getRequestAuth(req);
6461
6495
  if (auth?.kind === "user") {
6462
6496
  return { principal: { kind: "user", userId: auth.userId }, resolvedBy: auth.userId };
@@ -28497,6 +28531,7 @@ init_zod();
28497
28531
  var import_cron_parser = __toESM(require_dist2(), 1);
28498
28532
  init_db3();
28499
28533
  init_db2();
28534
+ init_rbac();
28500
28535
  init_types();
28501
28536
  var scheduleUpdateBodySchema = object2({
28502
28537
  key: AssetKeySchema.optional(),
@@ -28649,6 +28684,7 @@ var updateSchedule = route({
28649
28684
  responses: {
28650
28685
  200: { description: "Schedule updated", schema: ScheduledTaskSchema.nullable() },
28651
28686
  400: { description: "Validation error" },
28687
+ 403: { description: "Deferral owned by another agent" },
28652
28688
  404: { description: "Schedule not found" },
28653
28689
  409: { description: "Duplicate name" }
28654
28690
  }
@@ -28665,6 +28701,7 @@ var patchSchedule = route({
28665
28701
  responses: {
28666
28702
  200: { description: "Schedule patched", schema: ScheduledTaskSchema.nullable() },
28667
28703
  400: { description: "Validation error" },
28704
+ 403: { description: "Deferral owned by another agent" },
28668
28705
  404: { description: "Schedule not found" },
28669
28706
  409: { description: "Duplicate name" }
28670
28707
  },
@@ -28936,6 +28973,18 @@ async function handleSchedules(req, res, pathSegments, queryParams, myAgentId) {
28936
28973
  jsonError(res, "Schedule not found", 404);
28937
28974
  return true;
28938
28975
  }
28976
+ if (existing.taskType === "deferred") {
28977
+ const principal = await agentFirstPrincipal(req, myAgentId);
28978
+ if (principal.kind === "agent" && !can({
28979
+ principal,
28980
+ verb: "schedule.deferral.update.any",
28981
+ resource: { kind: "owned", ownerAgentId: existing.createdByAgentId },
28982
+ source: "http"
28983
+ }).allow) {
28984
+ jsonError(res, `Schedule "${existing.name}" defers another agent's task. Only that agent or a lead can change it.`, 403);
28985
+ return true;
28986
+ }
28987
+ }
28939
28988
  const agentChanged = parsed.body.targetAgentId !== undefined && parsed.body.targetAgentId !== existing.targetAgentId;
28940
28989
  if (parsed.body.model !== undefined || parsed.body.modelTier !== undefined) {
28941
28990
  const normalizedModel = splitLegacyModelAlias({
@@ -32377,7 +32426,7 @@ async function handleScripts(req, res, pathSegments, queryParams, agentId) {
32377
32426
  const startedAt = new Date().toISOString();
32378
32427
  const runStartTouch = namedScript?.isScratch ? await touchScratchScriptLastUsed(namedScript.id) : null;
32379
32428
  const credentials = await buildScriptCredentialBindingsWithFailures({ agentId: agent.id });
32380
- const output = await runScript({
32429
+ const output = await runScriptWithRunCredential({
32381
32430
  source,
32382
32431
  args: parsed.body.args,
32383
32432
  fsMode,
@@ -33344,7 +33393,8 @@ var SessionTreeResponseSchema = object2({
33344
33393
  inbox: SessionSectionCountsSchema,
33345
33394
  later: SessionSectionCountsSchema,
33346
33395
  done: SessionSectionCountsSchema,
33347
- noGroup: SessionSectionCountsSchema
33396
+ noGroup: SessionSectionCountsSchema,
33397
+ sources: array2(object2({ source: string2(), total: number2().int() })).describe("Each root source in this view with its session count, hidden sources included.")
33348
33398
  });
33349
33399
  var SessionApprovalSchema = object2({
33350
33400
  id: string2(),
@@ -33603,6 +33653,8 @@ async function handleAgentTokens(req, res, pathSegments, queryParams) {
33603
33653
  revokeAgentTokenRoute.respond(res, 200, { revoked: await revokeAgentTokens(parsed.params.id) });
33604
33654
  return true;
33605
33655
  }
33656
+ var SessionShowSchema = _enum2(["mine", "all"]).optional().describe("Sessions v2 view, for a user viewer with tree scope. mine (default): roots the user started from a human channel (not workflow, schedule, or system) plus sessions shared with the user. all: every tree session. Lists only: access is unchanged.");
33657
+ var SessionHideSourceSchema = string2().refine((value) => value.split(",").length <= 32, "hideSource takes at most 32 sources.").optional().transform((value) => value?.split(",").map((source) => source.trim()).filter(Boolean)).describe("Comma-separated root sources to leave out (the sessions v2 source filter), e.g. `slack,chat`.");
33606
33658
  var listSessions = route({
33607
33659
  method: "get",
33608
33660
  path: "/api/sessions",
@@ -33624,7 +33676,9 @@ var listSessions = route({
33624
33676
  status: _enum2(["running", "failed", "needs"]).optional(),
33625
33677
  withUserId: string2().min(1).optional(),
33626
33678
  fields: _enum2(["full", "slim"]).optional(),
33627
- scope: _enum2(["mine", "shared", "tree"]).optional().describe("mine: owned sessions. shared: sessions shared with me. tree: Sessions that GET /api/session-tree counts: mine plus shared with me, no ownerless roots. A bypass actor sees every root with tree scope.")
33679
+ scope: _enum2(["mine", "shared", "tree"]).optional().describe("mine: owned sessions. shared: sessions shared with me. tree: Sessions that GET /api/session-tree counts: mine plus shared with me, no ownerless roots. A bypass actor sees every root with tree scope."),
33680
+ show: SessionShowSchema,
33681
+ hideSource: SessionHideSourceSchema
33628
33682
  }),
33629
33683
  responses: {
33630
33684
  200: {
@@ -33646,12 +33700,41 @@ var sessionTree = route({
33646
33700
  pattern: ["api", "session-tree"],
33647
33701
  summary: "Get session groups and triage counts",
33648
33702
  tags: ["Sessions"],
33703
+ query: object2({ show: SessionShowSchema, hideSource: SessionHideSourceSchema }),
33649
33704
  responses: {
33650
33705
  200: { description: "Visible groups and section counts", schema: SessionTreeResponseSchema },
33651
33706
  401: { description: "Unauthorized" }
33652
33707
  },
33653
33708
  auth: { apiKey: true }
33654
33709
  });
33710
+ var triageSessionListRoute = route({
33711
+ method: "post",
33712
+ path: "/api/session-triage",
33713
+ pattern: ["api", "session-triage"],
33714
+ summary: "Triage every session of one sidebar list",
33715
+ description: "The bulk bar's 'Select all N': Done, back to the Inbox, read, or unread for every session that one sessions v2 list shows the caller (the `GET /api/sessions?scope=tree` filters). Needs a picked user.",
33716
+ tags: ["Sessions"],
33717
+ body: object2({
33718
+ action: _enum2(["done", "inbox", "read", "unread"]),
33719
+ triage: _enum2(["inbox", "later", "done"]).optional(),
33720
+ noGroup: boolean().optional(),
33721
+ groupKey: SessionKeyFilterSchema.optional(),
33722
+ show: SessionShowSchema,
33723
+ hideSource: array2(string2().min(1)).max(32).optional()
33724
+ }).refine((body) => [body.triage, body.noGroup, body.groupKey].filter(Boolean).length === 1, {
33725
+ message: "Name exactly one list: triage, noGroup, or groupKey"
33726
+ }),
33727
+ responses: {
33728
+ 200: {
33729
+ description: "The number of sessions written",
33730
+ schema: object2({ updated: number2().int() })
33731
+ },
33732
+ 400: { description: "Validation error, or no picked user" },
33733
+ 401: { description: "Unauthorized" }
33734
+ },
33735
+ auth: { apiKey: true },
33736
+ rbac: { ungated: "per-user inbox UI state, same posture as PATCH /api/inbox-state" }
33737
+ });
33655
33738
  var SESSION_MOVE_LIMIT = 200;
33656
33739
  var SESSION_MOVE_OWNER_ONLY = "Only the session owner can move this group";
33657
33740
  var SESSION_MOVE_UNAVAILABLE = "Session not found or not accessible";
@@ -33905,6 +33988,7 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
33905
33988
  }
33906
33989
  const filterOpts = {
33907
33990
  source: sources,
33991
+ hideSource: parsed.query.hideSource,
33908
33992
  q: parsed.query.q,
33909
33993
  requestedByUserId: parsed.query.requestedByUserId,
33910
33994
  contextKeyPrefix: parsed.query.contextKeyPrefix,
@@ -33916,6 +34000,7 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
33916
34000
  withUserId: parsed.query.withUserId,
33917
34001
  now: new Date().toISOString(),
33918
34002
  tree: parsed.query.scope === "tree",
34003
+ mine: parsed.query.scope === "tree" && parsed.query.show !== "all",
33919
34004
  ...actor.kind === "user" ? {
33920
34005
  viewer: {
33921
34006
  userId: actor.userId,
@@ -33942,7 +34027,25 @@ async function handleSessions(req, res, pathSegments, queryParams, myAgentId) {
33942
34027
  const parsed = await sessionTree.parse(req, res, pathSegments, queryParams);
33943
34028
  if (!parsed)
33944
34029
  return true;
33945
- sessionTree.respond(res, 200, await getSessionTree(await resolveSessionActor2(req, myAgentId)));
34030
+ const actor = await resolveSessionActor2(req, myAgentId);
34031
+ sessionTree.respond(res, 200, await getSessionTree(actor, undefined, {
34032
+ mine: parsed.query.show !== "all",
34033
+ hideSource: parsed.query.hideSource
34034
+ }));
34035
+ return true;
34036
+ }
34037
+ if (triageSessionListRoute.match(req.method, pathSegments)) {
34038
+ const parsed = await triageSessionListRoute.parse(req, res, pathSegments, queryParams);
34039
+ if (!parsed)
34040
+ return true;
34041
+ const actor = await resolveSessionActor2(req, myAgentId);
34042
+ if (actor.kind !== "user" || !actor.userId) {
34043
+ jsonError(res, "Pick a user to triage sessions", 400);
34044
+ return true;
34045
+ }
34046
+ const { action, show, ...list } = parsed.body;
34047
+ const updated = await triageSessionList(actor.userId, { ...list, mine: show !== "all" }, action);
34048
+ triageSessionListRoute.respond(res, 200, { updated });
33946
34049
  return true;
33947
34050
  }
33948
34051
  if (moveSessions.match(req.method, pathSegments)) {
@@ -36527,9 +36630,182 @@ async function handleTrackers(req, res, pathSegments) {
36527
36630
  return await handleLinearTracker(req, res, pathSegments);
36528
36631
  }
36529
36632
 
36633
+ // src/http/user-roles.ts
36634
+ init_zod();
36635
+ init_db3();
36636
+ init_rbac_roles();
36637
+ init_users();
36638
+ init_rbac();
36639
+ init_types();
36640
+ init_request_auth_context();
36641
+
36642
+ // src/http/operator-actor.ts
36643
+ init_users();
36644
+ init_api_key();
36645
+ init_request_auth_context();
36646
+ function extractBearer2(req) {
36647
+ const raw = req.headers.authorization;
36648
+ const header = Array.isArray(raw) ? raw[0] : raw;
36649
+ if (!header || !header.startsWith("Bearer "))
36650
+ return null;
36651
+ return header.slice(7);
36652
+ }
36653
+ function getOperatorActor(req, res) {
36654
+ const auth = getRequestAuth(req);
36655
+ if (auth?.kind === "user") {
36656
+ return { kind: "user", id: auth.userId };
36657
+ }
36658
+ if (auth?.kind === "operator") {
36659
+ return { kind: "operator", id: auth.fingerprint };
36660
+ }
36661
+ if (auth?.kind === "guest") {
36662
+ jsonError(res, "Forbidden", 403);
36663
+ return null;
36664
+ }
36665
+ const rawKey = extractBearer2(req);
36666
+ const swarmKey = getApiKey();
36667
+ if (!swarmKey) {
36668
+ return { kind: "operator", id: fingerprintApiKey("") };
36669
+ }
36670
+ if (!rawKey || rawKey !== swarmKey) {
36671
+ jsonError(res, "Unauthorized", 401);
36672
+ return null;
36673
+ }
36674
+ return { kind: "operator", id: fingerprintApiKey(rawKey) };
36675
+ }
36676
+
36677
+ // src/http/user-roles.ts
36678
+ var listRolesRoute = route({
36679
+ method: "get",
36680
+ path: "/api/rbac/roles",
36681
+ pattern: ["api", "rbac", "roles"],
36682
+ operationId: "rbac_listRoles",
36683
+ summary: "List RBAC roles with their verbs",
36684
+ tags: ["Users"],
36685
+ responses: {
36686
+ 200: { description: "Role catalog", schema: object2({ roles: array2(RbacRoleSchema) }) }
36687
+ }
36688
+ });
36689
+ var getUserRolesRoute = route({
36690
+ method: "get",
36691
+ path: "/api/users/{id}/roles",
36692
+ pattern: ["api", "users", null, "roles"],
36693
+ operationId: "users_getRbacRoles",
36694
+ summary: "Get a user's RBAC roles",
36695
+ tags: ["Users"],
36696
+ params: object2({ id: string2().min(1) }),
36697
+ responses: {
36698
+ 200: { description: "The user's roles", schema: UserRbacRolesSchema },
36699
+ 404: { description: "User not found" }
36700
+ }
36701
+ });
36702
+ var setUserRolesRoute = route({
36703
+ method: "put",
36704
+ path: "/api/users/{id}/roles",
36705
+ pattern: ["api", "users", null, "roles"],
36706
+ operationId: "users_setRbacRoles",
36707
+ summary: "Set a user's RBAC roles",
36708
+ description: `Replaces the user's roles. The set holds exactly one of ${PRIMARY_ROLE_NAMES2.join(", ")} plus any extra roles. Demoting a user below admin removes the ability to answer approval requests, even when the user is listed as an approver. Fails with 409 when it would leave no active admin.`,
36709
+ tags: ["Users"],
36710
+ params: object2({ id: string2().min(1) }),
36711
+ body: object2({ roles: array2(string2().min(1)).min(1) }).strict(),
36712
+ responses: {
36713
+ 200: { description: "The user's roles after the change", schema: UserRbacRolesSchema },
36714
+ 400: { description: "Invalid role set" },
36715
+ 403: { description: "Not allowed to change roles" },
36716
+ 404: { description: "User not found" },
36717
+ 409: { description: "Would leave no active admin" }
36718
+ },
36719
+ rbac: { permission: "user.role.manage" }
36720
+ });
36721
+ async function composeRoles(userId) {
36722
+ const [catalog, held] = await Promise.all([listRbacRoles2(), listUserRoles2(userId)]);
36723
+ const names = new Set(held.map((role) => role.name));
36724
+ return { userId, roles: catalog.filter((role) => names.has(role.name)) };
36725
+ }
36726
+ async function ensureRoleManager(req, res) {
36727
+ if (rejectGuest(req, res))
36728
+ return false;
36729
+ const auth = getRequestAuth(req);
36730
+ if (auth?.kind !== "operator" && auth?.kind !== "user") {
36731
+ jsonError(res, "Role changes require operator or user credentials", 403);
36732
+ return false;
36733
+ }
36734
+ const header = req.headers["x-agent-id"];
36735
+ const decision = can({
36736
+ principal: await agentFirstPrincipal(req, Array.isArray(header) ? header[0] : header),
36737
+ verb: "user.role.manage",
36738
+ resource: { kind: "none" },
36739
+ source: "http"
36740
+ });
36741
+ if (!decision.allow) {
36742
+ jsonError(res, decision.reason, 403);
36743
+ return false;
36744
+ }
36745
+ if (auth.kind === "user" && isRbacEnabled() && !(await getUserGrant2(auth.userId)).grantsAll) {
36746
+ jsonError(res, "Role changes require a grant-all role", 403);
36747
+ return false;
36748
+ }
36749
+ return true;
36750
+ }
36751
+ async function handleUserRoles(req, res, pathSegments, queryParams) {
36752
+ if (listRolesRoute.match(req.method, pathSegments)) {
36753
+ if (rejectGuest(req, res))
36754
+ return true;
36755
+ listRolesRoute.respond(res, 200, { roles: await listRbacRoles2() });
36756
+ return true;
36757
+ }
36758
+ if (getUserRolesRoute.match(req.method, pathSegments)) {
36759
+ if (rejectGuest(req, res))
36760
+ return true;
36761
+ const parsed = await getUserRolesRoute.parse(req, res, pathSegments, queryParams);
36762
+ if (!parsed)
36763
+ return true;
36764
+ if (!await getUserById2(parsed.params.id)) {
36765
+ jsonError(res, "User not found", 404);
36766
+ return true;
36767
+ }
36768
+ getUserRolesRoute.respond(res, 200, await composeRoles(parsed.params.id));
36769
+ return true;
36770
+ }
36771
+ if (setUserRolesRoute.match(req.method, pathSegments)) {
36772
+ const parsed = await setUserRolesRoute.parse(req, res, pathSegments, queryParams);
36773
+ if (!parsed)
36774
+ return true;
36775
+ if (!await ensureRoleManager(req, res))
36776
+ return true;
36777
+ const actor = getOperatorActor(req, res);
36778
+ if (!actor)
36779
+ return true;
36780
+ const userId = parsed.params.id;
36781
+ if (!await getUserById2(userId)) {
36782
+ jsonError(res, "User not found", 404);
36783
+ return true;
36784
+ }
36785
+ try {
36786
+ const { before, after } = await setUserRoles2(userId, parsed.body.roles, actor.kind === "user" ? actor.id : null);
36787
+ await recordIdentityEvent(userId, "profile_changed", actor, { rbacRoles: before }, { rbacRoles: after });
36788
+ } catch (err) {
36789
+ if (err instanceof LastAdminError2) {
36790
+ jsonError(res, "last_admin", 409);
36791
+ return true;
36792
+ }
36793
+ if (err instanceof InvalidRoleSetError2) {
36794
+ jsonError(res, err.message, 400);
36795
+ return true;
36796
+ }
36797
+ throw err;
36798
+ }
36799
+ setUserRolesRoute.respond(res, 200, await composeRoles(userId));
36800
+ return true;
36801
+ }
36802
+ return false;
36803
+ }
36804
+
36530
36805
  // src/http/users.ts
36531
36806
  init_zod();
36532
36807
  init_db3();
36808
+ init_rbac_roles();
36533
36809
  init_users();
36534
36810
  init_types();
36535
36811
  init_request_auth_context();
@@ -36600,41 +36876,6 @@ function createIpRateLimiter(options) {
36600
36876
  };
36601
36877
  }
36602
36878
 
36603
- // src/http/operator-actor.ts
36604
- init_users();
36605
- init_api_key();
36606
- init_request_auth_context();
36607
- function extractBearer2(req) {
36608
- const raw = req.headers.authorization;
36609
- const header = Array.isArray(raw) ? raw[0] : raw;
36610
- if (!header || !header.startsWith("Bearer "))
36611
- return null;
36612
- return header.slice(7);
36613
- }
36614
- function getOperatorActor(req, res) {
36615
- const auth = getRequestAuth(req);
36616
- if (auth?.kind === "user") {
36617
- return { kind: "user", id: auth.userId };
36618
- }
36619
- if (auth?.kind === "operator") {
36620
- return { kind: "operator", id: auth.fingerprint };
36621
- }
36622
- if (auth?.kind === "guest") {
36623
- jsonError(res, "Forbidden", 403);
36624
- return null;
36625
- }
36626
- const rawKey = extractBearer2(req);
36627
- const swarmKey = getApiKey();
36628
- if (!swarmKey) {
36629
- return { kind: "operator", id: fingerprintApiKey("") };
36630
- }
36631
- if (!rawKey || rawKey !== swarmKey) {
36632
- jsonError(res, "Unauthorized", 401);
36633
- return null;
36634
- }
36635
- return { kind: "operator", id: fingerprintApiKey(rawKey) };
36636
- }
36637
-
36638
36879
  // src/http/users.ts
36639
36880
  async function composeUser(userId, recentEventLimit = 5) {
36640
36881
  const user = await getUserById2(userId);
@@ -36990,7 +37231,8 @@ var mergeUsersRoute = route({
36990
37231
  },
36991
37232
  400: { description: "Validation error (e.g. target == source)" },
36992
37233
  401: { description: "Unauthorized" },
36993
- 404: { description: "Target or source user not found" }
37234
+ 404: { description: "Target or source user not found" },
37235
+ 409: { description: "Source is the last active admin (last_admin)" }
36994
37236
  },
36995
37237
  auth: { apiKey: true }
36996
37238
  });
@@ -37472,6 +37714,7 @@ async function handleUsers(req, res, pathSegments, queryParams) {
37472
37714
  await recordIdentityEvent(targetId, "email_added", actor, null, { email: alias });
37473
37715
  }
37474
37716
  }
37717
+ await assertNotLastAdmin2(sourceId);
37475
37718
  await deleteUser2(sourceId, targetId);
37476
37719
  const targetAfter = await composeUser(targetId);
37477
37720
  await recordIdentityEvent(targetId, "manual_merge", actor, targetBefore, {
@@ -37486,6 +37729,10 @@ async function handleUsers(req, res, pathSegments, queryParams) {
37486
37729
  });
37487
37730
  mergeUsersRoute.respond(res, 200, { user: mergedUser });
37488
37731
  } catch (err) {
37732
+ if (err instanceof LastAdminError2) {
37733
+ jsonError(res, "last_admin", 409);
37734
+ return true;
37735
+ }
37489
37736
  jsonError(res, err instanceof Error ? err.message : "Failed to merge users", 500);
37490
37737
  }
37491
37738
  return true;
@@ -39619,7 +39866,7 @@ async function handleX(req, res, pathSegments) {
39619
39866
  const credentials = await buildScriptCredentialBindingsWithFailures({
39620
39867
  agentId: endpoint.agentId
39621
39868
  });
39622
- const output = await runScript({
39869
+ const output = await runScriptWithRunCredential({
39623
39870
  source: script.source,
39624
39871
  args: args ?? null,
39625
39872
  fsMode: "none",
@@ -39833,6 +40080,7 @@ var httpServer = createHttpServer(async (req, res) => {
39833
40080
  () => handleRuntimePools(req, res, pathSegments, queryParams, myAgentId),
39834
40081
  () => handleExtensions(req, res, pathSegments, queryParams, myAgentId),
39835
40082
  () => handleFavorites(req, res, pathSegments, queryParams, myAgentId),
40083
+ () => handleUserRoles(req, res, pathSegments, queryParams),
39836
40084
  () => handleUsers(req, res, pathSegments, queryParams),
39837
40085
  () => handleSessions(req, res, pathSegments, queryParams, myAgentId),
39838
40086
  () => handleInboxState(req, res, pathSegments, queryParams),
@@ -39870,7 +40118,7 @@ var httpServer = createHttpServer(async (req, res) => {
39870
40118
  });
39871
40119
  });
39872
40120
  var detachRealtime = attachRealtimeTransport(httpServer);
39873
- var { attachControllerTransport } = await import("./controllers-connect-6dkm71tg.js");
40121
+ var { attachControllerTransport } = await import("./controllers-connect-jzx7t4bn.js");
39874
40122
  var detachControllers = attachControllerTransport(httpServer);
39875
40123
  var stopWorkerNudges = startWorkerNudgeListener();
39876
40124
  var stopRoomDeletion = realtimeBus.subscribe("room:namespace-deleted", (namespace) => {
@@ -39899,7 +40147,7 @@ async function shutdown() {
39899
40147
  sessionsProcessed: getServerSessionsProcessed()
39900
40148
  });
39901
40149
  if (hasCapability("scheduling")) {
39902
- const { stopScheduler } = await import("./index-d2qeem97.js");
40150
+ const { stopScheduler } = await import("./index-1cscynkb.js");
39903
40151
  stopScheduler();
39904
40152
  }
39905
40153
  stopHeartbeat2();
@@ -39911,7 +40159,7 @@ async function shutdown() {
39911
40159
  await stopSlackApp2();
39912
40160
  await stopChatSdk();
39913
40161
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
39914
- const { stopOAuthKeepalive } = await import("./keepalive-wsby1btq.js");
40162
+ const { stopOAuthKeepalive } = await import("./keepalive-a9srcphj.js");
39915
40163
  await stopOAuthKeepalive();
39916
40164
  }
39917
40165
  stopOAuthPendingGc();
@@ -39991,21 +40239,21 @@ try {
39991
40239
  console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
39992
40240
  }
39993
40241
  try {
39994
- const { ensurePricingSeeded } = await import("./boot-seeds-9jqwnegq.js");
40242
+ const { ensurePricingSeeded } = await import("./boot-seeds-0n82qc7q.js");
39995
40243
  ensurePricingSeeded();
39996
- const { startPricingRefreshLoop } = await import("./pricing-refresh-pva04zee.js");
40244
+ const { startPricingRefreshLoop } = await import("./pricing-refresh-t27anv4z.js");
39997
40245
  startPricingRefreshLoop();
39998
40246
  } catch (err) {
39999
40247
  console.error("[startup] Failed to seed pricing rows:", err);
40000
40248
  }
40001
40249
  try {
40002
- const { ensureModelProfilesSeeded } = await import("./boot-seeds-9jqwnegq.js");
40250
+ const { ensureModelProfilesSeeded } = await import("./boot-seeds-0n82qc7q.js");
40003
40251
  await ensureModelProfilesSeeded();
40004
40252
  } catch (err) {
40005
40253
  console.error("[startup] Failed to seed model profiles:", err);
40006
40254
  }
40007
40255
  try {
40008
- const { ensureRbacSeeded } = await import("./boot-seeds-9jqwnegq.js");
40256
+ const { ensureRbacSeeded } = await import("./boot-seeds-0n82qc7q.js");
40009
40257
  ensureRbacSeeded();
40010
40258
  } catch (err) {
40011
40259
  console.error("[startup] Failed to sync RBAC seed rows:", err);
@@ -40013,7 +40261,7 @@ try {
40013
40261
  throw err;
40014
40262
  }
40015
40263
  try {
40016
- const { runAllSeeders } = await import("./index-nq8hhv28.js");
40264
+ const { runAllSeeders } = await import("./index-06qkmcx6.js");
40017
40265
  await runAllSeeders({ scriptEmbeddingMode: "skip" });
40018
40266
  } catch (err) {
40019
40267
  console.error("[startup] Failed to seed built-in entities:", err);
@@ -40076,39 +40324,39 @@ httpServer.listen(port, async () => {
40076
40324
  await initWorkflows2();
40077
40325
  await startScriptRunSupervisor(getMcpBaseUrl());
40078
40326
  if (hasCapability("scheduling")) {
40079
- const { startScheduler } = await import("./index-d2qeem97.js");
40080
- const { getExecutorRegistry } = await import("./index-4q3vj1yr.js");
40327
+ const { startScheduler } = await import("./index-1cscynkb.js");
40328
+ const { getExecutorRegistry } = await import("./index-r70q0xjx.js");
40081
40329
  const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
40082
40330
  startScheduler(getExecutorRegistry(), intervalMs, {
40083
40331
  runId: globalState.__runId
40084
40332
  });
40085
40333
  }
40086
40334
  if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
40087
- const { startHeartbeat } = await import("./index-mj46rk9k.js");
40335
+ const { startHeartbeat } = await import("./index-s193j5fh.js");
40088
40336
  const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
40089
40337
  startHeartbeat(heartbeatMs);
40090
40338
  }
40091
40339
  startPoolRouting();
40092
40340
  startRuntimeSupervisor();
40093
40341
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
40094
- const { startOAuthKeepalive } = await import("./keepalive-wsby1btq.js");
40342
+ const { startOAuthKeepalive } = await import("./keepalive-a9srcphj.js");
40095
40343
  startOAuthKeepalive();
40096
40344
  }
40097
40345
  if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
40098
- const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-d6sqn5np.js");
40346
+ const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-b65jcyw2.js");
40099
40347
  startOAuthRefreshSweep();
40100
40348
  }
40101
40349
  startOAuthPendingGc();
40102
40350
  await startMemoryGc();
40103
40351
  await startDbRetention();
40104
40352
  startHumanFreeDrain();
40105
- import("./boot-reembed-r8rhf9h8.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
40353
+ import("./boot-reembed-r3e808ky.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
40106
40354
  console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
40107
40355
  });
40108
- import("./boot-reembed-vwcj2y5d.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
40356
+ import("./boot-reembed-tgrfy27t.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
40109
40357
  console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
40110
40358
  });
40111
- import("./boot-scrub-sweep-fr9q36ne.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
40359
+ import("./boot-scrub-sweep-masdwxkm.js").then(({ runBootScrubSweep }) => runBootScrubSweep()).catch((err) => {
40112
40360
  console.error("[boot-scrub-sweep] startup scrub failed (non-fatal):", err);
40113
40361
  });
40114
40362
  }).on("error", (err) => {