agor-live 0.21.2 → 0.22.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 (431) hide show
  1. package/dist/cli/commands/branch/env/restart.js +1 -1
  2. package/dist/cli/commands/branch/env/start.js +1 -1
  3. package/dist/cli/commands/branch/env/stop.js +1 -1
  4. package/dist/core/api/index.cjs +5 -1
  5. package/dist/core/api/index.d.ts +6 -1
  6. package/dist/core/api/index.d.ts.map +1 -1
  7. package/dist/core/api/index.js +5 -1
  8. package/dist/core/claude/index.cjs +162 -14
  9. package/dist/core/claude/index.js +166 -18
  10. package/dist/core/client/index.cjs +43 -3
  11. package/dist/core/client/index.js +37 -3
  12. package/dist/core/config/browser.cjs +2 -2
  13. package/dist/core/config/browser.js +2 -2
  14. package/dist/core/config/config-manager.d.ts.map +1 -1
  15. package/dist/core/config/constants.d.ts +1 -1
  16. package/dist/core/config/index.cjs +174 -20
  17. package/dist/core/config/index.js +178 -24
  18. package/dist/core/config/types.d.ts +8 -0
  19. package/dist/core/config/types.d.ts.map +1 -1
  20. package/dist/core/db/index.cjs +495 -86
  21. package/dist/core/db/index.js +482 -75
  22. package/dist/core/db/repositories/artifacts.d.ts.map +1 -1
  23. package/dist/core/db/repositories/branches.d.ts +13 -1
  24. package/dist/core/db/repositories/branches.d.ts.map +1 -1
  25. package/dist/core/db/repositories/gateway-channels.d.ts.map +1 -1
  26. package/dist/core/db/repositories/index.d.ts +1 -0
  27. package/dist/core/db/repositories/index.d.ts.map +1 -1
  28. package/dist/core/db/repositories/session-relationships.d.ts +30 -0
  29. package/dist/core/db/repositories/session-relationships.d.ts.map +1 -0
  30. package/dist/core/db/repositories/users.d.ts +11 -0
  31. package/dist/core/db/repositories/users.d.ts.map +1 -1
  32. package/dist/core/db/schema.d.ts +421 -4
  33. package/dist/core/db/schema.d.ts.map +1 -1
  34. package/dist/core/db/schema.postgres.d.ts +226 -2
  35. package/dist/core/db/schema.postgres.d.ts.map +1 -1
  36. package/dist/core/db/schema.sqlite.d.ts +228 -2
  37. package/dist/core/db/schema.sqlite.d.ts.map +1 -1
  38. package/dist/core/drizzle/postgres/0050_artifact_source_session.sql +3 -0
  39. package/dist/core/drizzle/postgres/0051_session_relationships.sql +26 -0
  40. package/dist/core/drizzle/postgres/meta/_journal.json +14 -0
  41. package/dist/core/drizzle/sqlite/0059_artifact_source_session.sql +2 -0
  42. package/dist/core/drizzle/sqlite/0060_session_relationships.sql +23 -0
  43. package/dist/core/drizzle/sqlite/meta/_journal.json +14 -0
  44. package/dist/core/gateway/connector-registry.d.ts.map +1 -1
  45. package/dist/core/gateway/connector.d.ts +22 -0
  46. package/dist/core/gateway/connector.d.ts.map +1 -1
  47. package/dist/core/gateway/connectors/slack.d.ts +35 -3
  48. package/dist/core/gateway/connectors/slack.d.ts.map +1 -1
  49. package/dist/core/gateway/connectors/teams.d.ts +107 -0
  50. package/dist/core/gateway/connectors/teams.d.ts.map +1 -0
  51. package/dist/core/gateway/context.d.ts.map +1 -1
  52. package/dist/core/gateway/index.cjs +552 -52
  53. package/dist/core/gateway/index.d.ts +3 -2
  54. package/dist/core/gateway/index.d.ts.map +1 -1
  55. package/dist/core/gateway/index.js +544 -52
  56. package/dist/core/gateway/system-message.d.ts +21 -0
  57. package/dist/core/gateway/system-message.d.ts.map +1 -1
  58. package/dist/core/index.cjs +616 -127
  59. package/dist/core/index.js +597 -116
  60. package/dist/core/mcp/index.cjs +146 -9
  61. package/dist/core/mcp/index.js +146 -9
  62. package/dist/core/mcp/template-resolver.d.ts.map +1 -1
  63. package/dist/core/seed/index.cjs +375 -59
  64. package/dist/core/seed/index.js +378 -62
  65. package/dist/core/sessions/index.cjs +19 -0
  66. package/dist/core/sessions/index.js +19 -0
  67. package/dist/core/templates/agor-system-prompt.md +21 -53
  68. package/dist/core/templates/session-context.cjs +2 -73
  69. package/dist/core/templates/session-context.d.ts +9 -53
  70. package/dist/core/templates/session-context.d.ts.map +1 -1
  71. package/dist/core/templates/session-context.js +2 -72
  72. package/dist/core/tools/mcp/jwt-auth.cjs +2 -20
  73. package/dist/core/tools/mcp/jwt-auth.d.ts.map +1 -1
  74. package/dist/core/tools/mcp/jwt-auth.js +2 -20
  75. package/dist/core/tools/mcp/oauth-mcp-transport.cjs +2 -15
  76. package/dist/core/tools/mcp/oauth-mcp-transport.d.ts.map +1 -1
  77. package/dist/core/tools/mcp/oauth-mcp-transport.js +2 -15
  78. package/dist/core/tools/mcp/oauth-refresh.cjs +167 -19
  79. package/dist/core/tools/mcp/oauth-refresh.js +167 -19
  80. package/dist/core/types/artifact.d.ts +5 -1
  81. package/dist/core/types/artifact.d.ts.map +1 -1
  82. package/dist/core/types/branch.d.ts +14 -0
  83. package/dist/core/types/branch.d.ts.map +1 -1
  84. package/dist/core/types/gateway.d.ts +1 -1
  85. package/dist/core/types/gateway.d.ts.map +1 -1
  86. package/dist/core/types/id.d.ts +1 -0
  87. package/dist/core/types/id.d.ts.map +1 -1
  88. package/dist/core/types/index.cjs +36 -0
  89. package/dist/core/types/index.js +30 -0
  90. package/dist/core/types/session.d.ts +65 -1
  91. package/dist/core/types/session.d.ts.map +1 -1
  92. package/dist/core/types/task.d.ts +9 -0
  93. package/dist/core/types/task.d.ts.map +1 -1
  94. package/dist/core/unix/index.cjs +371 -55
  95. package/dist/core/unix/index.js +374 -58
  96. package/dist/core/unix/unix-integration-service.d.ts +10 -7
  97. package/dist/core/unix/unix-integration-service.d.ts.map +1 -1
  98. package/dist/core/utils/permission-mode-mapper.cjs +19 -0
  99. package/dist/core/utils/permission-mode-mapper.js +19 -0
  100. package/dist/daemon/declarations.d.ts +7 -0
  101. package/dist/daemon/declarations.d.ts.map +1 -1
  102. package/dist/daemon/hooks/gateway-route.d.ts.map +1 -1
  103. package/dist/daemon/hooks/gateway-route.js +53 -1
  104. package/dist/daemon/index.js +3760 -2107
  105. package/dist/daemon/main.js +3760 -2107
  106. package/dist/daemon/mcp/server.js +155 -17
  107. package/dist/daemon/mcp/tools/analytics.js +6 -7
  108. package/dist/daemon/mcp/tools/artifacts.d.ts.map +1 -1
  109. package/dist/daemon/mcp/tools/artifacts.js +7 -7
  110. package/dist/daemon/mcp/tools/boards.js +6 -7
  111. package/dist/daemon/mcp/tools/branches.js +6 -7
  112. package/dist/daemon/mcp/tools/card-types.js +6 -7
  113. package/dist/daemon/mcp/tools/cards.js +6 -7
  114. package/dist/daemon/mcp/tools/environment.d.ts.map +1 -1
  115. package/dist/daemon/mcp/tools/environment.js +19 -12
  116. package/dist/daemon/mcp/tools/knowledge.js +6 -7
  117. package/dist/daemon/mcp/tools/mcp-servers.js +6 -7
  118. package/dist/daemon/mcp/tools/messages.js +6 -7
  119. package/dist/daemon/mcp/tools/proxies.js +6 -7
  120. package/dist/daemon/mcp/tools/repos.js +6 -7
  121. package/dist/daemon/mcp/tools/schedules.js +6 -7
  122. package/dist/daemon/mcp/tools/search.js +6 -7
  123. package/dist/daemon/mcp/tools/sessions.d.ts.map +1 -1
  124. package/dist/daemon/mcp/tools/sessions.js +140 -11
  125. package/dist/daemon/mcp/tools/tasks.js +6 -7
  126. package/dist/daemon/mcp/tools/users.js +6 -7
  127. package/dist/daemon/mcp/tools/widgets.js +7 -8
  128. package/dist/daemon/register-hooks.d.ts +5 -1
  129. package/dist/daemon/register-hooks.d.ts.map +1 -1
  130. package/dist/daemon/register-hooks.js +404 -179
  131. package/dist/daemon/register-routes.d.ts.map +1 -1
  132. package/dist/daemon/register-routes.js +360 -162
  133. package/dist/daemon/register-services.d.ts.map +1 -1
  134. package/dist/daemon/register-services.js +1928 -671
  135. package/dist/daemon/services/artifacts.d.ts +10 -1
  136. package/dist/daemon/services/artifacts.d.ts.map +1 -1
  137. package/dist/daemon/services/artifacts.js +25 -1
  138. package/dist/daemon/services/branches.d.ts +11 -1
  139. package/dist/daemon/services/branches.d.ts.map +1 -1
  140. package/dist/daemon/services/branches.js +470 -184
  141. package/dist/daemon/services/claude-models.js +879 -339
  142. package/dist/daemon/services/gateway.d.ts +58 -2
  143. package/dist/daemon/services/gateway.d.ts.map +1 -1
  144. package/dist/daemon/services/gateway.js +590 -47
  145. package/dist/daemon/services/groups.d.ts +2 -0
  146. package/dist/daemon/services/groups.d.ts.map +1 -1
  147. package/dist/daemon/services/groups.js +56 -0
  148. package/dist/daemon/services/mcp-servers.d.ts.map +1 -1
  149. package/dist/daemon/services/mcp-servers.js +0 -6
  150. package/dist/daemon/services/scheduler.d.ts.map +1 -1
  151. package/dist/daemon/services/scheduler.js +6 -2
  152. package/dist/daemon/services/sessions.d.ts +11 -3
  153. package/dist/daemon/services/sessions.d.ts.map +1 -1
  154. package/dist/daemon/services/sessions.js +68 -7
  155. package/dist/daemon/services/tasks.d.ts +13 -2
  156. package/dist/daemon/services/tasks.d.ts.map +1 -1
  157. package/dist/daemon/services/tasks.js +42 -26
  158. package/dist/daemon/startup.js +6 -2
  159. package/dist/daemon/utils/session-stop.d.ts +43 -0
  160. package/dist/daemon/utils/session-stop.d.ts.map +1 -0
  161. package/dist/daemon/utils/session-stop.js +102 -0
  162. package/dist/daemon/utils/session-task-state.d.ts +7 -2
  163. package/dist/daemon/utils/session-task-state.d.ts.map +1 -1
  164. package/dist/daemon/utils/session-task-state.js +9 -3
  165. package/dist/daemon/utils/session-tasks.d.ts +4 -4
  166. package/dist/daemon/utils/session-tasks.d.ts.map +1 -1
  167. package/dist/daemon/utils/session-tasks.js +4 -8
  168. package/dist/executor/commands/environment.d.ts +13 -0
  169. package/dist/executor/commands/environment.d.ts.map +1 -0
  170. package/dist/executor/commands/environment.js +287 -0
  171. package/dist/executor/commands/index.d.ts.map +1 -1
  172. package/dist/executor/commands/index.js +5 -1
  173. package/dist/executor/commands/unix.d.ts +8 -1
  174. package/dist/executor/commands/unix.d.ts.map +1 -1
  175. package/dist/executor/commands/unix.js +157 -2
  176. package/dist/executor/payload-types.d.ts +201 -5
  177. package/dist/executor/payload-types.d.ts.map +1 -1
  178. package/dist/executor/payload-types.js +98 -0
  179. package/dist/executor/sdk-handlers/base/mcp-scoping.d.ts.map +1 -1
  180. package/dist/executor/sdk-handlers/base/mcp-scoping.js +14 -0
  181. package/dist/executor/sdk-handlers/claude/message-processor.d.ts.map +1 -1
  182. package/dist/executor/sdk-handlers/claude/message-processor.js +0 -1
  183. package/dist/executor/sdk-handlers/claude/query-builder.d.ts +1 -0
  184. package/dist/executor/sdk-handlers/claude/query-builder.d.ts.map +1 -1
  185. package/dist/executor/sdk-handlers/claude/query-builder.js +91 -39
  186. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts +12 -5
  187. package/dist/executor/sdk-handlers/codex/prompt-service.d.ts.map +1 -1
  188. package/dist/executor/sdk-handlers/codex/prompt-service.js +72 -30
  189. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts +2 -4
  190. package/dist/executor/sdk-handlers/copilot/prompt-service.d.ts.map +1 -1
  191. package/dist/executor/sdk-handlers/copilot/prompt-service.js +4 -13
  192. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts +2 -4
  193. package/dist/executor/sdk-handlers/gemini/prompt-service.d.ts.map +1 -1
  194. package/dist/executor/sdk-handlers/gemini/prompt-service.js +4 -13
  195. package/dist/ui/assets/App-DcEY8Ota.js +3 -0
  196. package/dist/ui/assets/App-DcEY8Ota.js.gz +0 -0
  197. package/dist/ui/assets/{ArtifactConsentModal-ParNk5kW.js → ArtifactConsentModal-CiCbK9iv.js} +1 -1
  198. package/dist/ui/assets/ArtifactConsentModal-CiCbK9iv.js.gz +0 -0
  199. package/dist/ui/assets/ArtifactFullscreenPage-CfsTEGKd.js +9 -0
  200. package/dist/ui/assets/ArtifactFullscreenPage-CfsTEGKd.js.gz +0 -0
  201. package/dist/ui/assets/AutocompleteTextarea-BAFFH_5e.js +18 -0
  202. package/dist/ui/assets/AutocompleteTextarea-BAFFH_5e.js.gz +0 -0
  203. package/dist/ui/assets/BoardObjectNodes-D-O6bZIG.js +34 -0
  204. package/dist/ui/assets/BoardObjectNodes-D-O6bZIG.js.gz +0 -0
  205. package/dist/ui/assets/{CodeEditor.inner-D51Z_CLQ.js → CodeEditor.inner-DBgsP4tn.js} +2 -2
  206. package/dist/ui/assets/CodeEditor.inner-DBgsP4tn.js.gz +0 -0
  207. package/dist/ui/assets/ConversationView-CUWR0gR6.js +1 -0
  208. package/dist/ui/assets/ConversationView-CUWR0gR6.js.gz +0 -0
  209. package/dist/ui/assets/KnowledgePage-B2bzlXfn.js +24 -0
  210. package/dist/ui/assets/KnowledgePage-B2bzlXfn.js.gz +0 -0
  211. package/dist/ui/assets/MarketingScreenshotPage-9Qd7eZsm.css +1 -0
  212. package/dist/ui/assets/MarketingScreenshotPage-zv5RUCuV.js +143 -0
  213. package/dist/ui/assets/MarketingScreenshotPage-zv5RUCuV.js.gz +0 -0
  214. package/dist/ui/assets/MobileApp-VgVnsnsN.js +1 -0
  215. package/dist/ui/assets/MobileApp-VgVnsnsN.js.gz +0 -0
  216. package/dist/ui/assets/SessionCanvas-f1-1Gbcw.js +20 -0
  217. package/dist/ui/assets/SessionCanvas-f1-1Gbcw.js.gz +0 -0
  218. package/dist/ui/assets/{App-BAdBsEnV.css → SessionCanvas-mEmYGZhC.css} +1 -1
  219. package/dist/ui/assets/SessionCanvas-mEmYGZhC.css.gz +0 -0
  220. package/dist/ui/assets/{StreamdownDemoPage-B9wbgp2s.js → StreamdownDemoPage-wzWaqWwr.js} +1 -1
  221. package/dist/ui/assets/StreamdownDemoPage-wzWaqWwr.js.gz +0 -0
  222. package/dist/ui/assets/{ThemeSwitcher-ubn6IOz9.js → ThemeSwitcher-Dly2y9pi.js} +1 -1
  223. package/dist/ui/assets/ThemeSwitcher-Dly2y9pi.js.gz +0 -0
  224. package/dist/ui/assets/antd-CfbbHJOz.js +401 -0
  225. package/dist/ui/assets/antd-CfbbHJOz.js.gz +0 -0
  226. package/dist/ui/assets/architecture-U656AL7Q-CykGFbQU.js +1 -0
  227. package/dist/ui/assets/{architectureDiagram-VXUJARFQ-ChmZt3zk.js → architectureDiagram-VXUJARFQ-C8HXAenz.js} +1 -1
  228. package/dist/ui/assets/architectureDiagram-VXUJARFQ-C8HXAenz.js.gz +0 -0
  229. package/dist/ui/assets/{blockDiagram-VD42YOAC-CzGHAHao.js → blockDiagram-VD42YOAC-BhZaEN19.js} +1 -1
  230. package/dist/ui/assets/blockDiagram-VD42YOAC-BhZaEN19.js.gz +0 -0
  231. package/dist/ui/assets/{c4Diagram-YG6GDRKO-DscJyaWN.js → c4Diagram-YG6GDRKO-Dk_UH-sY.js} +1 -1
  232. package/dist/ui/assets/c4Diagram-YG6GDRKO-Dk_UH-sY.js.gz +0 -0
  233. package/dist/ui/assets/channel-D6_nUWlW.js +1 -0
  234. package/dist/ui/assets/{chunk-4BX2VUAB-DoWpTvP8.js → chunk-4BX2VUAB-XprbG2TG.js} +1 -1
  235. package/dist/ui/assets/chunk-55IACEB6-ByzqIgSb.js +1 -0
  236. package/dist/ui/assets/{chunk-ABZYJK2D-RzDCrjE6.js → chunk-ABZYJK2D-BJcrryHK.js} +1 -1
  237. package/dist/ui/assets/chunk-ABZYJK2D-BJcrryHK.js.gz +0 -0
  238. package/dist/ui/assets/{chunk-AGHRB4JF-jidCS5Of.js → chunk-AGHRB4JF-DvxmfbM0.js} +1 -1
  239. package/dist/ui/assets/chunk-AGHRB4JF-DvxmfbM0.js.gz +0 -0
  240. package/dist/ui/assets/{chunk-ATLVNIR6-BEIIfJtC.js → chunk-ATLVNIR6-DbeJ0OrR.js} +1 -1
  241. package/dist/ui/assets/chunk-ATLVNIR6-DbeJ0OrR.js.gz +0 -0
  242. package/dist/ui/assets/{chunk-B4BG7PRW-B8b6dQQ2.js → chunk-B4BG7PRW-C53q2ggf.js} +1 -1
  243. package/dist/ui/assets/chunk-B4BG7PRW-C53q2ggf.js.gz +0 -0
  244. package/dist/ui/assets/{chunk-CVBHYZKI-D-mQAfrk.js → chunk-CVBHYZKI-B3EBSlb3.js} +1 -1
  245. package/dist/ui/assets/{chunk-DI55MBZ5-BfATX3V8.js → chunk-DI55MBZ5-vIyNEQN-.js} +1 -1
  246. package/dist/ui/assets/chunk-DI55MBZ5-vIyNEQN-.js.gz +0 -0
  247. package/dist/ui/assets/chunk-EXTU4WIE-B3ObkuOm.js +1 -0
  248. package/dist/ui/assets/{chunk-FMBD7UC4-fqXscNvc.js → chunk-FMBD7UC4-rddmfK-Z.js} +1 -1
  249. package/dist/ui/assets/{chunk-HN2XXSSU-BCHvD80g.js → chunk-HN2XXSSU-Dttqcg3b.js} +1 -1
  250. package/dist/ui/assets/chunk-HN2XXSSU-Dttqcg3b.js.gz +0 -0
  251. package/dist/ui/assets/{chunk-JA3XYJ7Z-Cp6dqHnY.js → chunk-JA3XYJ7Z-DbNDev3D.js} +1 -1
  252. package/dist/ui/assets/chunk-JA3XYJ7Z-DbNDev3D.js.gz +0 -0
  253. package/dist/ui/assets/{chunk-JZLCHNYA-cKMooY3y.js → chunk-JZLCHNYA-EUmx2y4H.js} +1 -1
  254. package/dist/ui/assets/chunk-JZLCHNYA-EUmx2y4H.js.gz +0 -0
  255. package/dist/ui/assets/{chunk-MI3HLSF2-BlzO5wOE.js → chunk-MI3HLSF2-65n9Mkyc.js} +1 -1
  256. package/dist/ui/assets/chunk-MI3HLSF2-65n9Mkyc.js.gz +0 -0
  257. package/dist/ui/assets/chunk-N4CR4FBY-mv5koXqW.js +2 -0
  258. package/dist/ui/assets/chunk-N4CR4FBY-mv5koXqW.js.gz +0 -0
  259. package/dist/ui/assets/{chunk-QN33PNHL-DIHGQ_pd.js → chunk-QN33PNHL-DsRKK6NR.js} +1 -1
  260. package/dist/ui/assets/{chunk-QXUST7PY-C9l0muI0.js → chunk-QXUST7PY-BCYnMiS3.js} +1 -1
  261. package/dist/ui/assets/chunk-QXUST7PY-BCYnMiS3.js.gz +0 -0
  262. package/dist/ui/assets/chunk-QZHKN3VN-HucAw4xW.js +1 -0
  263. package/dist/ui/assets/{chunk-S3R3BYOJ-VJiLzt2o.js → chunk-S3R3BYOJ-CWMEa9Dc.js} +1 -1
  264. package/dist/ui/assets/chunk-S3R3BYOJ-CWMEa9Dc.js.gz +0 -0
  265. package/dist/ui/assets/{chunk-TZMSLE5B-DZwI0C_2.js → chunk-TZMSLE5B-BuQUQcTr.js} +1 -1
  266. package/dist/ui/assets/chunk-TZMSLE5B-BuQUQcTr.js.gz +0 -0
  267. package/dist/ui/assets/classDiagram-2ON5EDUG-CUT3rPTB.js +1 -0
  268. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-CUT3rPTB.js +1 -0
  269. package/dist/ui/assets/{cose-bilkent-S5V4N54A-Ipik-oSD.js → cose-bilkent-S5V4N54A-CnPB3ARO.js} +1 -1
  270. package/dist/ui/assets/cose-bilkent-S5V4N54A-CnPB3ARO.js.gz +0 -0
  271. package/dist/ui/assets/cursor-QEb7m-rN.png +0 -0
  272. package/dist/ui/assets/{dagre-6UL2VRFP-BDpyWQnh.js → dagre-6UL2VRFP-DhS-k_Se.js} +1 -1
  273. package/dist/ui/assets/dagre-6UL2VRFP-DhS-k_Se.js.gz +0 -0
  274. package/dist/ui/assets/{dagre-CgA4KhUX.js → dagre-KgLoHEuy.js} +1 -1
  275. package/dist/ui/assets/dagre-KgLoHEuy.js.gz +0 -0
  276. package/dist/ui/assets/{diagram-PSM6KHXK-B4GRzxLJ.js → diagram-PSM6KHXK-BZg3MJmb.js} +1 -1
  277. package/dist/ui/assets/diagram-PSM6KHXK-BZg3MJmb.js.gz +0 -0
  278. package/dist/ui/assets/{diagram-QEK2KX5R-BWPW28XI.js → diagram-QEK2KX5R-BPCitvbo.js} +1 -1
  279. package/dist/ui/assets/diagram-QEK2KX5R-BPCitvbo.js.gz +0 -0
  280. package/dist/ui/assets/{diagram-S2PKOQOG-BIHhcGoV.js → diagram-S2PKOQOG-NW4uK6sx.js} +1 -1
  281. package/dist/ui/assets/diagram-S2PKOQOG-NW4uK6sx.js.gz +0 -0
  282. package/dist/ui/assets/{editor-C-HJ7Yw0.js → editor-CzFWIUw2.js} +1 -1
  283. package/dist/ui/assets/editor-CzFWIUw2.js.gz +0 -0
  284. package/dist/ui/assets/{emoji-D8F6B62m.js → emoji-Dkz4Zzv_.js} +1 -1
  285. package/dist/ui/assets/emoji-Dkz4Zzv_.js.gz +0 -0
  286. package/dist/ui/assets/{erDiagram-Q2GNP2WA-ubTaAFcK.js → erDiagram-Q2GNP2WA-me1fboaf.js} +1 -1
  287. package/dist/ui/assets/erDiagram-Q2GNP2WA-me1fboaf.js.gz +0 -0
  288. package/dist/ui/assets/{flowDiagram-NV44I4VS-BHLCTYjI.js → flowDiagram-NV44I4VS-DzE8dGsh.js} +1 -1
  289. package/dist/ui/assets/flowDiagram-NV44I4VS-DzE8dGsh.js.gz +0 -0
  290. package/dist/ui/assets/{ganttDiagram-LVOFAZNH-ClC3pay1.js → ganttDiagram-LVOFAZNH-CFQD09Mi.js} +2 -2
  291. package/dist/ui/assets/ganttDiagram-LVOFAZNH-CFQD09Mi.js.gz +0 -0
  292. package/dist/ui/assets/{gitGraph-F6HP7TQM-DghoobE6.js → gitGraph-F6HP7TQM-CfFE_uAC.js} +1 -1
  293. package/dist/ui/assets/{gitGraphDiagram-NY62KEGX-Clqpiswu.js → gitGraphDiagram-NY62KEGX-CaVoxU4C.js} +1 -1
  294. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-CaVoxU4C.js.gz +0 -0
  295. package/dist/ui/assets/index-BN5_Qq7R.js +324 -0
  296. package/dist/ui/assets/index-BN5_Qq7R.js.gz +0 -0
  297. package/dist/ui/assets/index-DxuPq13l.css +1 -0
  298. package/dist/ui/assets/index-DxuPq13l.css.gz +0 -0
  299. package/dist/ui/assets/{info-NVLQJR56-0ZldEXPQ.js → info-NVLQJR56-i_xHYg3f.js} +1 -1
  300. package/dist/ui/assets/{infoDiagram-ER5ION4S-DMmPX-il.js → infoDiagram-ER5ION4S-2NL93b78.js} +1 -1
  301. package/dist/ui/assets/{journeyDiagram-XKPGCS4Q-CrVickA2.js → journeyDiagram-XKPGCS4Q-CZF-2DHU.js} +1 -1
  302. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CZF-2DHU.js.gz +0 -0
  303. package/dist/ui/assets/{kanban-definition-3W4ZIXB7-C_BsdHYL.js → kanban-definition-3W4ZIXB7-CfvJIOny.js} +1 -1
  304. package/dist/ui/assets/kanban-definition-3W4ZIXB7-CfvJIOny.js.gz +0 -0
  305. package/dist/ui/assets/{line-CfBP7Yic.js → line-DDv8kOJk.js} +1 -1
  306. package/dist/ui/assets/{linear-BsjageUB.js → linear-Daef-l29.js} +1 -1
  307. package/dist/ui/assets/linear-Daef-l29.js.gz +0 -0
  308. package/dist/ui/assets/{mermaid-parser.core-DZdP-NFq.js → mermaid-parser.core-CdK9QgYV.js} +2 -2
  309. package/dist/ui/assets/mermaid-parser.core-CdK9QgYV.js.gz +0 -0
  310. package/dist/ui/assets/{mermaid.core-TNrI0pHG.js → mermaid.core-D6GS9mU-.js} +3 -3
  311. package/dist/ui/assets/mermaid.core-D6GS9mU-.js.gz +0 -0
  312. package/dist/ui/assets/message-SqLqNYcv.js +36 -0
  313. package/dist/ui/assets/message-SqLqNYcv.js.gz +0 -0
  314. package/dist/ui/assets/{mindmap-definition-VGOIOE7T-BbmaUjMY.js → mindmap-definition-VGOIOE7T-Cb3QMflX.js} +1 -1
  315. package/dist/ui/assets/mindmap-definition-VGOIOE7T-Cb3QMflX.js.gz +0 -0
  316. package/dist/ui/assets/{packet-BFZMPI3H-D_ZhkXuT.js → packet-BFZMPI3H-Bm2uwz4i.js} +1 -1
  317. package/dist/ui/assets/{particles-Dv28pjOd.js → particles-DsJFOarW.js} +1 -1
  318. package/dist/ui/assets/particles-DsJFOarW.js.gz +0 -0
  319. package/dist/ui/assets/{pie-7BOR55EZ-Dn0Q3qNx.js → pie-7BOR55EZ-5i17tVnF.js} +1 -1
  320. package/dist/ui/assets/{pieDiagram-ADFJNKIX-BbyjfYu8.js → pieDiagram-ADFJNKIX-BxIwQWvw.js} +1 -1
  321. package/dist/ui/assets/pieDiagram-ADFJNKIX-BxIwQWvw.js.gz +0 -0
  322. package/dist/ui/assets/{quadrantDiagram-AYHSOK5B-Bc3GqMKz.js → quadrantDiagram-AYHSOK5B-B5HPe4ga.js} +1 -1
  323. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-B5HPe4ga.js.gz +0 -0
  324. package/dist/ui/assets/{radar-NHE76QYJ-BHwoAy1q.js → radar-NHE76QYJ-BTn-tq0k.js} +1 -1
  325. package/dist/ui/assets/{reactflow-BVYPxNhc.js → reactflow-Bf74ngoo.js} +2 -2
  326. package/dist/ui/assets/reactflow-Bf74ngoo.js.gz +0 -0
  327. package/dist/ui/assets/{requirementDiagram-UZGBJVZJ-BQaKKL09.js → requirementDiagram-UZGBJVZJ-YfI6llkX.js} +1 -1
  328. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-YfI6llkX.js.gz +0 -0
  329. package/dist/ui/assets/{sandpack-BQW_FQ7G.js → sandpack-D7koO5op.js} +1 -1
  330. package/dist/ui/assets/sandpack-D7koO5op.js.gz +0 -0
  331. package/dist/ui/assets/{sankeyDiagram-TZEHDZUN-DiJvDvhb.js → sankeyDiagram-TZEHDZUN-DOk_B10B.js} +1 -1
  332. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DOk_B10B.js.gz +0 -0
  333. package/dist/ui/assets/{sequenceDiagram-WL72ISMW-Dw32824o.js → sequenceDiagram-WL72ISMW-DAe4Um17.js} +1 -1
  334. package/dist/ui/assets/sequenceDiagram-WL72ISMW-DAe4Um17.js.gz +0 -0
  335. package/dist/ui/assets/{stateDiagram-FKZM4ZOC-BCOpNdHV.js → stateDiagram-FKZM4ZOC-CCesDu_C.js} +1 -1
  336. package/dist/ui/assets/stateDiagram-FKZM4ZOC-CCesDu_C.js.gz +0 -0
  337. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-CMlIrsoO.js +1 -0
  338. package/dist/ui/assets/{syntax-VJrU5BEu.js → syntax-C-M-8jOU.js} +1 -1
  339. package/dist/ui/assets/syntax-C-M-8jOU.js.gz +0 -0
  340. package/dist/ui/assets/{theme-DZtFA8b4.js → theme-BQZdiqwv.js} +1 -1
  341. package/dist/ui/assets/{timeline-definition-IT6M3QCI-Jh_WZzXv.js → timeline-definition-IT6M3QCI-D6P5txjT.js} +1 -1
  342. package/dist/ui/assets/timeline-definition-IT6M3QCI-D6P5txjT.js.gz +0 -0
  343. package/dist/ui/assets/{treemap-KMMF4GRG-CPYIgjxE.js → treemap-KMMF4GRG-Bitm3gy4.js} +1 -1
  344. package/dist/ui/assets/{knowledgeRoutes-CivaUqha.js → useUserLocalStorage-Ckb8HsIw.js} +1 -1
  345. package/dist/ui/assets/useUserLocalStorage-Ckb8HsIw.js.gz +0 -0
  346. package/dist/ui/assets/{xychartDiagram-PRI3JC2R-CERc7Rdb.js → xychartDiagram-PRI3JC2R-CsybjUbd.js} +1 -1
  347. package/dist/ui/assets/xychartDiagram-PRI3JC2R-CsybjUbd.js.gz +0 -0
  348. package/dist/ui/index.html +13 -11
  349. package/dist/ui/index.html.gz +0 -0
  350. package/package.json +10 -9
  351. package/dist/ui/assets/App-9s2WHM6S.js +0 -22
  352. package/dist/ui/assets/App-9s2WHM6S.js.gz +0 -0
  353. package/dist/ui/assets/App-BAdBsEnV.css.gz +0 -0
  354. package/dist/ui/assets/ArtifactConsentModal-ParNk5kW.js.gz +0 -0
  355. package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js +0 -9
  356. package/dist/ui/assets/ArtifactFullscreenPage-VQxLMCiN.js.gz +0 -0
  357. package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js +0 -18
  358. package/dist/ui/assets/AutocompleteTextarea-3RchrIgk.js.gz +0 -0
  359. package/dist/ui/assets/CodeEditor.inner-D51Z_CLQ.js.gz +0 -0
  360. package/dist/ui/assets/ConversationView-Dyddw2b1.js +0 -34
  361. package/dist/ui/assets/ConversationView-Dyddw2b1.js.gz +0 -0
  362. package/dist/ui/assets/KnowledgePage-CdftslnF.js +0 -24
  363. package/dist/ui/assets/KnowledgePage-CdftslnF.js.gz +0 -0
  364. package/dist/ui/assets/MobileApp-BdBMpnJ1.js +0 -1
  365. package/dist/ui/assets/MobileApp-BdBMpnJ1.js.gz +0 -0
  366. package/dist/ui/assets/StreamdownDemoPage-B9wbgp2s.js.gz +0 -0
  367. package/dist/ui/assets/ThemeSwitcher-ubn6IOz9.js.gz +0 -0
  368. package/dist/ui/assets/antd-C-HfEC4E.js +0 -400
  369. package/dist/ui/assets/antd-C-HfEC4E.js.gz +0 -0
  370. package/dist/ui/assets/architecture-U656AL7Q-dkBewUpN.js +0 -1
  371. package/dist/ui/assets/architectureDiagram-VXUJARFQ-ChmZt3zk.js.gz +0 -0
  372. package/dist/ui/assets/blockDiagram-VD42YOAC-CzGHAHao.js.gz +0 -0
  373. package/dist/ui/assets/c4Diagram-YG6GDRKO-DscJyaWN.js.gz +0 -0
  374. package/dist/ui/assets/channel-DvRQqEqC.js +0 -1
  375. package/dist/ui/assets/chunk-55IACEB6-DojF2pZN.js +0 -1
  376. package/dist/ui/assets/chunk-ABZYJK2D-RzDCrjE6.js.gz +0 -0
  377. package/dist/ui/assets/chunk-AGHRB4JF-jidCS5Of.js.gz +0 -0
  378. package/dist/ui/assets/chunk-ATLVNIR6-BEIIfJtC.js.gz +0 -0
  379. package/dist/ui/assets/chunk-B4BG7PRW-B8b6dQQ2.js.gz +0 -0
  380. package/dist/ui/assets/chunk-DI55MBZ5-BfATX3V8.js.gz +0 -0
  381. package/dist/ui/assets/chunk-EXTU4WIE-BKt6lPJM.js +0 -1
  382. package/dist/ui/assets/chunk-HN2XXSSU-BCHvD80g.js.gz +0 -0
  383. package/dist/ui/assets/chunk-JA3XYJ7Z-Cp6dqHnY.js.gz +0 -0
  384. package/dist/ui/assets/chunk-JZLCHNYA-cKMooY3y.js.gz +0 -0
  385. package/dist/ui/assets/chunk-MI3HLSF2-BlzO5wOE.js.gz +0 -0
  386. package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js +0 -2
  387. package/dist/ui/assets/chunk-N4CR4FBY-pASDorUx.js.gz +0 -0
  388. package/dist/ui/assets/chunk-QXUST7PY-C9l0muI0.js.gz +0 -0
  389. package/dist/ui/assets/chunk-QZHKN3VN-CZskCFCf.js +0 -1
  390. package/dist/ui/assets/chunk-S3R3BYOJ-VJiLzt2o.js.gz +0 -0
  391. package/dist/ui/assets/chunk-TZMSLE5B-DZwI0C_2.js.gz +0 -0
  392. package/dist/ui/assets/classDiagram-2ON5EDUG-BFASUbmZ.js +0 -1
  393. package/dist/ui/assets/classDiagram-v2-WZHVMYZB-BFASUbmZ.js +0 -1
  394. package/dist/ui/assets/cose-bilkent-S5V4N54A-Ipik-oSD.js.gz +0 -0
  395. package/dist/ui/assets/dagre-6UL2VRFP-BDpyWQnh.js.gz +0 -0
  396. package/dist/ui/assets/dagre-CgA4KhUX.js.gz +0 -0
  397. package/dist/ui/assets/diagram-PSM6KHXK-B4GRzxLJ.js.gz +0 -0
  398. package/dist/ui/assets/diagram-QEK2KX5R-BWPW28XI.js.gz +0 -0
  399. package/dist/ui/assets/diagram-S2PKOQOG-BIHhcGoV.js.gz +0 -0
  400. package/dist/ui/assets/editor-C-HJ7Yw0.js.gz +0 -0
  401. package/dist/ui/assets/emoji-D8F6B62m.js.gz +0 -0
  402. package/dist/ui/assets/erDiagram-Q2GNP2WA-ubTaAFcK.js.gz +0 -0
  403. package/dist/ui/assets/flowDiagram-NV44I4VS-BHLCTYjI.js.gz +0 -0
  404. package/dist/ui/assets/ganttDiagram-LVOFAZNH-ClC3pay1.js.gz +0 -0
  405. package/dist/ui/assets/gitGraphDiagram-NY62KEGX-Clqpiswu.js.gz +0 -0
  406. package/dist/ui/assets/index-D9OElx9A.css +0 -1
  407. package/dist/ui/assets/index-D9OElx9A.css.gz +0 -0
  408. package/dist/ui/assets/index-DxPuzG7E.js +0 -350
  409. package/dist/ui/assets/index-DxPuzG7E.js.gz +0 -0
  410. package/dist/ui/assets/journeyDiagram-XKPGCS4Q-CrVickA2.js.gz +0 -0
  411. package/dist/ui/assets/kanban-definition-3W4ZIXB7-C_BsdHYL.js.gz +0 -0
  412. package/dist/ui/assets/knowledgeRoutes-CivaUqha.js.gz +0 -0
  413. package/dist/ui/assets/linear-BsjageUB.js.gz +0 -0
  414. package/dist/ui/assets/mermaid-parser.core-DZdP-NFq.js.gz +0 -0
  415. package/dist/ui/assets/mermaid.core-TNrI0pHG.js.gz +0 -0
  416. package/dist/ui/assets/message-BtWWJ9Af.js +0 -36
  417. package/dist/ui/assets/message-BtWWJ9Af.js.gz +0 -0
  418. package/dist/ui/assets/mindmap-definition-VGOIOE7T-BbmaUjMY.js.gz +0 -0
  419. package/dist/ui/assets/particles-Dv28pjOd.js.gz +0 -0
  420. package/dist/ui/assets/pieDiagram-ADFJNKIX-BbyjfYu8.js.gz +0 -0
  421. package/dist/ui/assets/quadrantDiagram-AYHSOK5B-Bc3GqMKz.js.gz +0 -0
  422. package/dist/ui/assets/reactflow-BVYPxNhc.js.gz +0 -0
  423. package/dist/ui/assets/requirementDiagram-UZGBJVZJ-BQaKKL09.js.gz +0 -0
  424. package/dist/ui/assets/sandpack-BQW_FQ7G.js.gz +0 -0
  425. package/dist/ui/assets/sankeyDiagram-TZEHDZUN-DiJvDvhb.js.gz +0 -0
  426. package/dist/ui/assets/sequenceDiagram-WL72ISMW-Dw32824o.js.gz +0 -0
  427. package/dist/ui/assets/stateDiagram-FKZM4ZOC-BCOpNdHV.js.gz +0 -0
  428. package/dist/ui/assets/stateDiagram-v2-4FDKWEC3-Cuqwvgfg.js +0 -1
  429. package/dist/ui/assets/syntax-VJrU5BEu.js.gz +0 -0
  430. package/dist/ui/assets/timeline-definition-IT6M3QCI-Jh_WZzXv.js.gz +0 -0
  431. package/dist/ui/assets/xychartDiagram-PRI3JC2R-CERc7Rdb.js.gz +0 -0
@@ -480,6 +480,9 @@ async function getBaseUrl() {
480
480
  if (config.daemon?.base_url) {
481
481
  return validateBaseUrl(config.daemon.base_url);
482
482
  }
483
+ if (config.ui?.base_url) {
484
+ return validateBaseUrl(config.ui.base_url);
485
+ }
483
486
  const defaults = getDefaultConfig();
484
487
  const envPort = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : void 0;
485
488
  const port = envPort || config.daemon?.port || defaults.daemon?.port || DAEMON.DEFAULT_PORT;
@@ -494,8 +497,11 @@ async function requirePublicBaseUrl() {
494
497
  if (config.daemon?.base_url) {
495
498
  return validateBaseUrl(config.daemon.base_url);
496
499
  }
500
+ if (config.ui?.base_url) {
501
+ return validateBaseUrl(config.ui.base_url);
502
+ }
497
503
  throw new PublicBaseUrlNotConfiguredError(
498
- "No public base URL configured. Set the AGOR_BASE_URL environment variable or `daemon.base_url` in ~/.agor/config.yaml to the daemon's browser-reachable URL (e.g. https://agor.example.com). This is required so OAuth providers can redirect users back to a URL their browser can reach \u2014 the localhost fallback only works for browsers on the daemon machine."
504
+ "No public base URL configured. Set the AGOR_BASE_URL environment variable or `daemon.base_url` (preferred) / `ui.base_url` (legacy) in ~/.agor/config.yaml to the daemon's browser-reachable URL (e.g. https://agor.example.com). This is required so OAuth providers can redirect users back to a URL their browser can reach \u2014 the localhost fallback only works for browsers on the daemon machine."
499
505
  );
500
506
  }
501
507
  function loadConfigSync() {
@@ -1145,15 +1151,35 @@ var init_schedule = __esm({
1145
1151
  });
1146
1152
 
1147
1153
  // src/types/session.ts
1154
+ var SessionStatus, EXECUTING_SESSION_STATUSES;
1148
1155
  var init_session = __esm({
1149
1156
  "src/types/session.ts"() {
1150
1157
  "use strict";
1151
1158
  init_esm_shims();
1159
+ SessionStatus = {
1160
+ IDLE: "idle",
1161
+ RUNNING: "running",
1162
+ STOPPING: "stopping",
1163
+ // Stop requested, waiting for task to stop
1164
+ AWAITING_PERMISSION: "awaiting_permission",
1165
+ AWAITING_INPUT: "awaiting_input",
1166
+ // Legacy / pre-#1177: AskUserQuestion was disallowed at the SDK; new sessions never enter this state, kept for historical rows
1167
+ TIMED_OUT: "timed_out",
1168
+ // Permission/input request timed out, executor exited — user must re-prompt
1169
+ COMPLETED: "completed",
1170
+ FAILED: "failed"
1171
+ };
1172
+ EXECUTING_SESSION_STATUSES = /* @__PURE__ */ new Set([
1173
+ SessionStatus.RUNNING,
1174
+ SessionStatus.STOPPING,
1175
+ SessionStatus.AWAITING_PERMISSION,
1176
+ SessionStatus.AWAITING_INPUT
1177
+ ]);
1152
1178
  }
1153
1179
  });
1154
1180
 
1155
1181
  // src/types/task.ts
1156
- var TaskStatus, TERMINAL_TASK_STATUSES;
1182
+ var TaskStatus, TERMINAL_TASK_STATUSES, EXECUTING_TASK_STATUSES;
1157
1183
  var init_task = __esm({
1158
1184
  "src/types/task.ts"() {
1159
1185
  "use strict";
@@ -1181,6 +1207,12 @@ var init_task = __esm({
1181
1207
  TaskStatus.STOPPED,
1182
1208
  TaskStatus.TIMED_OUT
1183
1209
  ]);
1210
+ EXECUTING_TASK_STATUSES = /* @__PURE__ */ new Set([
1211
+ TaskStatus.RUNNING,
1212
+ TaskStatus.STOPPING,
1213
+ TaskStatus.AWAITING_PERMISSION,
1214
+ TaskStatus.AWAITING_INPUT
1215
+ ]);
1184
1216
  }
1185
1217
  });
1186
1218
 
@@ -1340,6 +1372,8 @@ __export(schema_postgres_exports, {
1340
1372
  serializedSessions: () => serializedSessions,
1341
1373
  sessionEnvSelections: () => sessionEnvSelections,
1342
1374
  sessionMcpServers: () => sessionMcpServers,
1375
+ sessionRelationships: () => sessionRelationships,
1376
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations,
1343
1377
  sessions: () => sessions,
1344
1378
  sessionsRelations: () => sessionsRelations,
1345
1379
  tasks: () => tasks,
@@ -1363,7 +1397,7 @@ import {
1363
1397
  uniqueIndex,
1364
1398
  varchar
1365
1399
  } from "drizzle-orm/pg-core";
1366
- var bytea, t, sessions, tasks, serializedSessions, messages, boards, repos, branches, branchOwners, boardOwners, schedules, users, groups, groupMemberships, branchGroupGrants, boardGroupGrants, appVariables, userApiKeys, mcpServers, cardTypes, cards, artifacts, artifactTrustGrants, boardObjects, sessionMcpServers, userMcpOauthTokens, boardComments, gatewayChannels, threadSessionMap, sessionEnvSelections, kbNamespaces, kbNamespaceAcl, kbDocuments, kbDocumentVersions, kbDocumentUnits, kbEmbeddingSpaces, kbGraphNodes, kbGraphEdges, sessionsRelations, branchesRelations, schedulesRelations;
1400
+ var bytea, t, sessions, sessionRelationships, tasks, serializedSessions, messages, boards, repos, branches, branchOwners, boardOwners, schedules, users, groups, groupMemberships, branchGroupGrants, boardGroupGrants, appVariables, userApiKeys, mcpServers, cardTypes, cards, artifacts, artifactTrustGrants, boardObjects, sessionMcpServers, userMcpOauthTokens, boardComments, gatewayChannels, threadSessionMap, sessionEnvSelections, kbNamespaces, kbNamespaceAcl, kbDocuments, kbDocumentVersions, kbDocumentUnits, kbEmbeddingSpaces, kbGraphNodes, kbGraphEdges, sessionsRelations, sessionRelationshipsRelations, branchesRelations, schedulesRelations;
1367
1401
  var init_schema_postgres = __esm({
1368
1402
  "src/db/schema.postgres.ts"() {
1369
1403
  "use strict";
@@ -1456,6 +1490,36 @@ var init_schema_postgres = __esm({
1456
1490
  scheduleRunUnique: uniqueIndex("sessions_schedule_run_unique").on(table.schedule_id, table.scheduled_run_at).where(sql2`${table.schedule_id} IS NOT NULL AND ${table.scheduled_run_at} IS NOT NULL`)
1457
1491
  })
1458
1492
  );
1493
+ sessionRelationships = pgTable(
1494
+ "session_relationships",
1495
+ {
1496
+ relationship_id: varchar("relationship_id", { length: 36 }).primaryKey(),
1497
+ source_session_id: varchar("source_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1498
+ target_session_id: varchar("target_session_id", { length: 36 }).notNull().references(() => sessions.session_id, { onDelete: "cascade" }),
1499
+ relationship_type: text("relationship_type", { enum: ["remote_create"] }).notNull(),
1500
+ created_by: varchar("created_by", { length: 36 }).notNull(),
1501
+ created_at: t.timestamp("created_at").notNull(),
1502
+ updated_at: t.timestamp("updated_at"),
1503
+ callback_enabled: t.bool("callback_enabled").notNull().default(false),
1504
+ callback_session_id: varchar("callback_session_id", { length: 36 }).references(
1505
+ () => sessions.session_id,
1506
+ {
1507
+ onDelete: "set null"
1508
+ }
1509
+ ),
1510
+ data: t.json("data")
1511
+ },
1512
+ (table) => ({
1513
+ sourceIdx: index("session_relationships_source_idx").on(table.source_session_id),
1514
+ targetIdx: index("session_relationships_target_idx").on(table.target_session_id),
1515
+ callbackIdx: index("session_relationships_callback_idx").on(table.callback_session_id),
1516
+ sourceTargetTypeUnique: uniqueIndex("session_relationships_source_target_type_unique").on(
1517
+ table.source_session_id,
1518
+ table.target_session_id,
1519
+ table.relationship_type
1520
+ )
1521
+ })
1522
+ );
1459
1523
  tasks = pgTable(
1460
1524
  "tasks",
1461
1525
  {
@@ -1992,6 +2056,12 @@ var init_schema_postgres = __esm({
1992
2056
  branch_id: varchar("branch_id", { length: 36 }).references(() => branches.branch_id, {
1993
2057
  onDelete: "set null"
1994
2058
  }),
2059
+ source_session_id: varchar("source_session_id", { length: 36 }).references(
2060
+ () => sessions.session_id,
2061
+ {
2062
+ onDelete: "set null"
2063
+ }
2064
+ ),
1995
2065
  board_id: varchar("board_id", { length: 36 }).notNull().references(() => boards.board_id, { onDelete: "cascade" }),
1996
2066
  name: text("name").notNull(),
1997
2067
  description: text("description"),
@@ -2018,6 +2088,7 @@ var init_schema_postgres = __esm({
2018
2088
  },
2019
2089
  (table) => ({
2020
2090
  branchIdx: index("artifacts_branch_idx").on(table.branch_id),
2091
+ sourceSessionIdx: index("artifacts_source_session_idx").on(table.source_session_id),
2021
2092
  boardIdx: index("artifacts_board_idx").on(table.board_id),
2022
2093
  archivedIdx: index("artifacts_archived_idx").on(table.archived),
2023
2094
  publicIdx: index("artifacts_public_idx").on(table.public)
@@ -2174,7 +2245,7 @@ var init_schema_postgres = __esm({
2174
2245
  // Materialized for queries
2175
2246
  name: text("name").notNull(),
2176
2247
  channel_type: text("channel_type", {
2177
- enum: ["slack", "discord", "whatsapp", "telegram", "github"]
2248
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
2178
2249
  }).notNull(),
2179
2250
  target_branch_id: varchar("target_branch_id", { length: 36 }).notNull().references(() => branches.branch_id, { onDelete: "cascade" }),
2180
2251
  agor_user_id: varchar("agor_user_id", { length: 36 }).notNull(),
@@ -2558,7 +2629,7 @@ var init_schema_postgres = __esm({
2558
2629
  archivedIdx: index("kb_graph_edges_archived_idx").on(table.archived)
2559
2630
  })
2560
2631
  );
2561
- sessionsRelations = relations(sessions, ({ one }) => ({
2632
+ sessionsRelations = relations(sessions, ({ one, many }) => ({
2562
2633
  branch: one(branches, {
2563
2634
  fields: [sessions.branch_id],
2564
2635
  references: [branches.branch_id]
@@ -2566,6 +2637,24 @@ var init_schema_postgres = __esm({
2566
2637
  schedule: one(schedules, {
2567
2638
  fields: [sessions.schedule_id],
2568
2639
  references: [schedules.schedule_id]
2640
+ }),
2641
+ outboundRelationships: many(sessionRelationships, { relationName: "relationshipSource" }),
2642
+ inboundRelationships: many(sessionRelationships, { relationName: "relationshipTarget" })
2643
+ }));
2644
+ sessionRelationshipsRelations = relations(sessionRelationships, ({ one }) => ({
2645
+ sourceSession: one(sessions, {
2646
+ fields: [sessionRelationships.source_session_id],
2647
+ references: [sessions.session_id],
2648
+ relationName: "relationshipSource"
2649
+ }),
2650
+ targetSession: one(sessions, {
2651
+ fields: [sessionRelationships.target_session_id],
2652
+ references: [sessions.session_id],
2653
+ relationName: "relationshipTarget"
2654
+ }),
2655
+ callbackSession: one(sessions, {
2656
+ fields: [sessionRelationships.callback_session_id],
2657
+ references: [sessions.session_id]
2569
2658
  })
2570
2659
  }));
2571
2660
  branchesRelations = relations(branches, ({ many }) => ({
@@ -2618,6 +2707,8 @@ __export(schema_sqlite_exports, {
2618
2707
  serializedSessions: () => serializedSessions2,
2619
2708
  sessionEnvSelections: () => sessionEnvSelections2,
2620
2709
  sessionMcpServers: () => sessionMcpServers2,
2710
+ sessionRelationships: () => sessionRelationships2,
2711
+ sessionRelationshipsRelations: () => sessionRelationshipsRelations2,
2621
2712
  sessions: () => sessions2,
2622
2713
  sessionsRelations: () => sessionsRelations2,
2623
2714
  tasks: () => tasks2,
@@ -2636,7 +2727,7 @@ import {
2636
2727
  text as text2,
2637
2728
  uniqueIndex as uniqueIndex2
2638
2729
  } from "drizzle-orm/sqlite-core";
2639
- var t2, sessions2, tasks2, serializedSessions2, messages2, boards2, repos2, branches2, branchOwners2, boardOwners2, schedules2, users2, groups2, groupMemberships2, branchGroupGrants2, boardGroupGrants2, appVariables2, userApiKeys2, mcpServers2, cardTypes2, cards2, artifacts2, artifactTrustGrants2, boardObjects2, sessionMcpServers2, userMcpOauthTokens2, boardComments2, gatewayChannels2, threadSessionMap2, sessionEnvSelections2, kbNamespaces2, kbNamespaceAcl2, kbDocuments2, kbDocumentVersions2, kbDocumentUnits2, kbEmbeddingSpaces2, kbGraphNodes2, kbGraphEdges2, sessionsRelations2, branchesRelations2, schedulesRelations2;
2730
+ var t2, sessions2, sessionRelationships2, tasks2, serializedSessions2, messages2, boards2, repos2, branches2, branchOwners2, boardOwners2, schedules2, users2, groups2, groupMemberships2, branchGroupGrants2, boardGroupGrants2, appVariables2, userApiKeys2, mcpServers2, cardTypes2, cards2, artifacts2, artifactTrustGrants2, boardObjects2, sessionMcpServers2, userMcpOauthTokens2, boardComments2, gatewayChannels2, threadSessionMap2, sessionEnvSelections2, kbNamespaces2, kbNamespaceAcl2, kbDocuments2, kbDocumentVersions2, kbDocumentUnits2, kbEmbeddingSpaces2, kbGraphNodes2, kbGraphEdges2, sessionsRelations2, sessionRelationshipsRelations2, branchesRelations2, schedulesRelations2;
2640
2731
  var init_schema_sqlite = __esm({
2641
2732
  "src/db/schema.sqlite.ts"() {
2642
2733
  "use strict";
@@ -2726,6 +2817,36 @@ var init_schema_sqlite = __esm({
2726
2817
  scheduleRunUnique: uniqueIndex2("sessions_schedule_run_unique").on(table.schedule_id, table.scheduled_run_at).where(sql3`${table.schedule_id} IS NOT NULL AND ${table.scheduled_run_at} IS NOT NULL`)
2727
2818
  })
2728
2819
  );
2820
+ sessionRelationships2 = sqliteTable(
2821
+ "session_relationships",
2822
+ {
2823
+ relationship_id: text2("relationship_id", { length: 36 }).primaryKey(),
2824
+ source_session_id: text2("source_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
2825
+ target_session_id: text2("target_session_id", { length: 36 }).notNull().references(() => sessions2.session_id, { onDelete: "cascade" }),
2826
+ relationship_type: text2("relationship_type", { enum: ["remote_create"] }).notNull(),
2827
+ created_by: text2("created_by", { length: 36 }).notNull(),
2828
+ created_at: t2.timestamp("created_at").notNull(),
2829
+ updated_at: t2.timestamp("updated_at"),
2830
+ callback_enabled: t2.bool("callback_enabled").notNull().default(false),
2831
+ callback_session_id: text2("callback_session_id", { length: 36 }).references(
2832
+ () => sessions2.session_id,
2833
+ {
2834
+ onDelete: "set null"
2835
+ }
2836
+ ),
2837
+ data: t2.json("data")
2838
+ },
2839
+ (table) => ({
2840
+ sourceIdx: index2("session_relationships_source_idx").on(table.source_session_id),
2841
+ targetIdx: index2("session_relationships_target_idx").on(table.target_session_id),
2842
+ callbackIdx: index2("session_relationships_callback_idx").on(table.callback_session_id),
2843
+ sourceTargetTypeUnique: uniqueIndex2("session_relationships_source_target_type_unique").on(
2844
+ table.source_session_id,
2845
+ table.target_session_id,
2846
+ table.relationship_type
2847
+ )
2848
+ })
2849
+ );
2729
2850
  tasks2 = sqliteTable(
2730
2851
  "tasks",
2731
2852
  {
@@ -3270,6 +3391,12 @@ var init_schema_sqlite = __esm({
3270
3391
  branch_id: text2("branch_id", { length: 36 }).references(() => branches2.branch_id, {
3271
3392
  onDelete: "set null"
3272
3393
  }),
3394
+ source_session_id: text2("source_session_id", { length: 36 }).references(
3395
+ () => sessions2.session_id,
3396
+ {
3397
+ onDelete: "set null"
3398
+ }
3399
+ ),
3273
3400
  board_id: text2("board_id", { length: 36 }).notNull().references(() => boards2.board_id, { onDelete: "cascade" }),
3274
3401
  name: text2("name").notNull(),
3275
3402
  description: text2("description"),
@@ -3296,6 +3423,7 @@ var init_schema_sqlite = __esm({
3296
3423
  },
3297
3424
  (table) => ({
3298
3425
  branchIdx: index2("artifacts_branch_idx").on(table.branch_id),
3426
+ sourceSessionIdx: index2("artifacts_source_session_idx").on(table.source_session_id),
3299
3427
  boardIdx: index2("artifacts_board_idx").on(table.board_id),
3300
3428
  archivedIdx: index2("artifacts_archived_idx").on(table.archived),
3301
3429
  publicIdx: index2("artifacts_public_idx").on(table.public)
@@ -3454,7 +3582,7 @@ var init_schema_sqlite = __esm({
3454
3582
  // Materialized for queries
3455
3583
  name: text2("name").notNull(),
3456
3584
  channel_type: text2("channel_type", {
3457
- enum: ["slack", "discord", "whatsapp", "telegram", "github"]
3585
+ enum: ["slack", "discord", "whatsapp", "telegram", "github", "teams"]
3458
3586
  }).notNull(),
3459
3587
  target_branch_id: text2("target_branch_id", { length: 36 }).notNull().references(() => branches2.branch_id, { onDelete: "cascade" }),
3460
3588
  agor_user_id: text2("agor_user_id", { length: 36 }).notNull(),
@@ -3837,7 +3965,7 @@ var init_schema_sqlite = __esm({
3837
3965
  archivedIdx: index2("kb_graph_edges_archived_idx").on(table.archived)
3838
3966
  })
3839
3967
  );
3840
- sessionsRelations2 = relations2(sessions2, ({ one }) => ({
3968
+ sessionsRelations2 = relations2(sessions2, ({ one, many }) => ({
3841
3969
  branch: one(branches2, {
3842
3970
  fields: [sessions2.branch_id],
3843
3971
  references: [branches2.branch_id]
@@ -3845,6 +3973,24 @@ var init_schema_sqlite = __esm({
3845
3973
  schedule: one(schedules2, {
3846
3974
  fields: [sessions2.schedule_id],
3847
3975
  references: [schedules2.schedule_id]
3976
+ }),
3977
+ outboundRelationships: many(sessionRelationships2, { relationName: "relationshipSource" }),
3978
+ inboundRelationships: many(sessionRelationships2, { relationName: "relationshipTarget" })
3979
+ }));
3980
+ sessionRelationshipsRelations2 = relations2(sessionRelationships2, ({ one }) => ({
3981
+ sourceSession: one(sessions2, {
3982
+ fields: [sessionRelationships2.source_session_id],
3983
+ references: [sessions2.session_id],
3984
+ relationName: "relationshipSource"
3985
+ }),
3986
+ targetSession: one(sessions2, {
3987
+ fields: [sessionRelationships2.target_session_id],
3988
+ references: [sessions2.session_id],
3989
+ relationName: "relationshipTarget"
3990
+ }),
3991
+ callbackSession: one(sessions2, {
3992
+ fields: [sessionRelationships2.callback_session_id],
3993
+ references: [sessions2.session_id]
3848
3994
  })
3849
3995
  }));
3850
3996
  branchesRelations2 = relations2(branches2, ({ many }) => ({
@@ -3940,6 +4086,7 @@ __export(schema_exports, {
3940
4086
  serializedSessions: () => serializedSessions3,
3941
4087
  sessionEnvSelections: () => sessionEnvSelections3,
3942
4088
  sessionMcpServers: () => sessionMcpServers3,
4089
+ sessionRelationships: () => sessionRelationships3,
3943
4090
  sessions: () => sessions3,
3944
4091
  tasks: () => tasks3,
3945
4092
  threadSessionMap: () => threadSessionMap3,
@@ -3947,7 +4094,7 @@ __export(schema_exports, {
3947
4094
  userMcpOauthTokens: () => userMcpOauthTokens3,
3948
4095
  users: () => users3
3949
4096
  });
3950
- var dialect, schema, sessions3, tasks3, messages3, boards3, repos3, branches3, branchOwners3, boardOwners3, groups3, groupMemberships3, branchGroupGrants3, boardGroupGrants3, schedules3, users3, appVariables3, mcpServers3, cardTypes3, cards3, artifacts3, artifactTrustGrants3, boardObjects3, sessionMcpServers3, sessionEnvSelections3, userMcpOauthTokens3, boardComments3, gatewayChannels3, threadSessionMap3, userApiKeys3, serializedSessions3, kbNamespaces3, kbNamespaceAcl3, kbDocuments3, kbDocumentVersions3, kbDocumentUnits3, kbEmbeddingSpaces3, kbGraphNodes3, kbGraphEdges3;
4097
+ var dialect, schema, sessions3, tasks3, messages3, boards3, repos3, branches3, branchOwners3, boardOwners3, groups3, groupMemberships3, branchGroupGrants3, boardGroupGrants3, schedules3, users3, appVariables3, mcpServers3, cardTypes3, cards3, artifacts3, artifactTrustGrants3, boardObjects3, sessionMcpServers3, sessionRelationships3, sessionEnvSelections3, userMcpOauthTokens3, boardComments3, gatewayChannels3, threadSessionMap3, userApiKeys3, serializedSessions3, kbNamespaces3, kbNamespaceAcl3, kbDocuments3, kbDocumentVersions3, kbDocumentUnits3, kbEmbeddingSpaces3, kbGraphNodes3, kbGraphEdges3;
3951
4098
  var init_schema = __esm({
3952
4099
  "src/db/schema.ts"() {
3953
4100
  "use strict";
@@ -3979,6 +4126,7 @@ var init_schema = __esm({
3979
4126
  artifactTrustGrants3 = schema.artifactTrustGrants;
3980
4127
  boardObjects3 = schema.boardObjects;
3981
4128
  sessionMcpServers3 = schema.sessionMcpServers;
4129
+ sessionRelationships3 = schema.sessionRelationships;
3982
4130
  sessionEnvSelections3 = schema.sessionEnvSelections;
3983
4131
  userMcpOauthTokens3 = schema.userMcpOauthTokens;
3984
4132
  boardComments3 = schema.boardComments;
@@ -5177,17 +5325,17 @@ init_esm_shims();
5177
5325
  init_esm_shims();
5178
5326
  init_ids();
5179
5327
  import {
5180
- and as and22,
5328
+ and as and23,
5181
5329
  asc as asc3,
5182
5330
  desc as desc6,
5183
- eq as eq31,
5331
+ eq as eq32,
5184
5332
  gt,
5185
5333
  gte,
5186
- inArray as inArray7,
5334
+ inArray as inArray8,
5187
5335
  like as like16,
5188
5336
  lte as lte2,
5189
- or as or8,
5190
- sql as sql14
5337
+ or as or9,
5338
+ sql as sql15
5191
5339
  } from "drizzle-orm";
5192
5340
  import bcryptjs from "bcryptjs";
5193
5341
 
@@ -5748,6 +5896,7 @@ var FS_ACCESS_RANK = {
5748
5896
  };
5749
5897
  var VIEW_OR_BETTER_BRANCH_PERMISSIONS = ["view", "session", "prompt", "all"];
5750
5898
  var BRANCH_PERMISSION_SOURCES = ["board", "override"];
5899
+ var FS_ACCESS_BRANCH_PERMISSIONS = ["read", "write"];
5751
5900
  var BranchRepository = class {
5752
5901
  constructor(db) {
5753
5902
  this.db = db;
@@ -6241,6 +6390,83 @@ var BranchRepository = class {
6241
6390
  }
6242
6391
  return Array.from(userIds);
6243
6392
  }
6393
+ /**
6394
+ * Find users whose explicit branch or aligned-board grants should materialize
6395
+ * into filesystem access for the branch.
6396
+ *
6397
+ * This intentionally excludes ambient "others" access because there is no
6398
+ * bounded user set to expand. Board owners apply whenever the branch is
6399
+ * explicitly aligned to board permissions (`permission_source = 'board'`);
6400
+ * board group grants additionally require a shared board. Override branches
6401
+ * must not inherit board grants.
6402
+ */
6403
+ async findExplicitFsAccessUserIds(branchId) {
6404
+ const branchRow = await select(this.db, {
6405
+ board_id: branches3.board_id,
6406
+ permission_source: branches3.permission_source
6407
+ }).from(branches3).where(eq13(branches3.branch_id, branchId)).one();
6408
+ const ownerRows = await select(this.db, { user_id: branchOwners3.user_id }).from(branchOwners3).where(eq13(branchOwners3.branch_id, branchId)).all();
6409
+ const groupRows = await select(this.db, { user_id: groupMemberships3.user_id }).from(branchGroupGrants3).innerJoin(groupMemberships3, eq13(groupMemberships3.group_id, branchGroupGrants3.group_id)).innerJoin(
6410
+ groups3,
6411
+ and9(eq13(groups3.group_id, branchGroupGrants3.group_id), eq13(groups3.archived, false))
6412
+ ).where(
6413
+ and9(
6414
+ eq13(branchGroupGrants3.branch_id, branchId),
6415
+ inArray3(
6416
+ sql7`coalesce(${branchGroupGrants3.fs_access}, 'read')`,
6417
+ FS_ACCESS_BRANCH_PERMISSIONS
6418
+ )
6419
+ )
6420
+ ).all();
6421
+ const isBoardAligned = branchRow?.permission_source === "board" && branchRow.board_id;
6422
+ const boardOwnerRows = isBoardAligned ? await select(this.db, { user_id: boardOwners3.user_id }).from(boardOwners3).where(eq13(boardOwners3.board_id, branchRow.board_id)).all() : [];
6423
+ const boardGroupRows = isBoardAligned ? await select(this.db, { user_id: groupMemberships3.user_id }).from(boardGroupGrants3).innerJoin(groupMemberships3, eq13(groupMemberships3.group_id, boardGroupGrants3.group_id)).innerJoin(
6424
+ groups3,
6425
+ and9(eq13(groups3.group_id, boardGroupGrants3.group_id), eq13(groups3.archived, false))
6426
+ ).innerJoin(
6427
+ boards3,
6428
+ and9(
6429
+ eq13(boards3.board_id, boardGroupGrants3.board_id),
6430
+ eq13(
6431
+ sql7`coalesce(${jsonExtract(this.db, boards3.data, "access_mode")}, 'shared')`,
6432
+ "shared"
6433
+ )
6434
+ )
6435
+ ).where(
6436
+ and9(
6437
+ eq13(boardGroupGrants3.board_id, branchRow.board_id),
6438
+ inArray3(
6439
+ sql7`coalesce(${boardGroupGrants3.fs_access}, 'read')`,
6440
+ FS_ACCESS_BRANCH_PERMISSIONS
6441
+ )
6442
+ )
6443
+ ).all() : [];
6444
+ const userIds = /* @__PURE__ */ new Set();
6445
+ for (const row of ownerRows) {
6446
+ userIds.add(row.user_id);
6447
+ }
6448
+ for (const row of groupRows) {
6449
+ userIds.add(row.user_id);
6450
+ }
6451
+ for (const row of boardOwnerRows) {
6452
+ userIds.add(row.user_id);
6453
+ }
6454
+ for (const row of boardGroupRows) {
6455
+ userIds.add(row.user_id);
6456
+ }
6457
+ return Array.from(userIds);
6458
+ }
6459
+ async findBoardAlignedBranches(boardId) {
6460
+ const rows = await select(this.db).from(branches3).where(
6461
+ and9(
6462
+ eq13(branches3.board_id, boardId),
6463
+ eq13(branches3.permission_source, "board"),
6464
+ eq13(branches3.archived, false)
6465
+ )
6466
+ ).all();
6467
+ const baseUrl = await getBaseUrl();
6468
+ return rows.map((row) => this.rowToBranch(row, baseUrl));
6469
+ }
6244
6470
  /**
6245
6471
  * Get all owners of a branch
6246
6472
  *
@@ -7053,13 +7279,20 @@ import { and as and17, desc as desc5, eq as eq24, inArray as inArray5, like as l
7053
7279
  init_database_wrapper();
7054
7280
  init_schema();
7055
7281
 
7282
+ // src/db/repositories/session-relationships.ts
7283
+ init_esm_shims();
7284
+ init_ids();
7285
+ init_database_wrapper();
7286
+ init_schema();
7287
+ import { and as and19, eq as eq26, inArray as inArray6, or as or8 } from "drizzle-orm";
7288
+
7056
7289
  // src/db/repositories/tasks.ts
7057
7290
  init_esm_shims();
7058
7291
  init_types2();
7059
7292
  init_ids();
7060
7293
  init_database_wrapper();
7061
7294
  init_schema();
7062
- import { eq as eq26, inArray as inArray6, like as like13, sql as sql13 } from "drizzle-orm";
7295
+ import { eq as eq27, inArray as inArray7, like as like13, sql as sql13 } from "drizzle-orm";
7063
7296
 
7064
7297
  // src/db/repositories/thread-session-map.ts
7065
7298
  init_esm_shims();
@@ -7067,7 +7300,7 @@ init_types2();
7067
7300
  init_ids();
7068
7301
  init_database_wrapper();
7069
7302
  init_schema();
7070
- import { and as and19, eq as eq27, like as like14, lt as lt2 } from "drizzle-orm";
7303
+ import { and as and20, eq as eq28, like as like14, lt as lt2 } from "drizzle-orm";
7071
7304
 
7072
7305
  // src/db/repositories/user-api-keys.ts
7073
7306
  init_esm_shims();
@@ -7076,18 +7309,18 @@ init_database_wrapper();
7076
7309
  init_schema();
7077
7310
  import { randomBytes as randomBytes3 } from "crypto";
7078
7311
  import bcrypt2 from "bcryptjs";
7079
- import { and as and20, eq as eq28 } from "drizzle-orm";
7312
+ import { and as and21, eq as eq29 } from "drizzle-orm";
7080
7313
 
7081
7314
  // src/db/repositories/user-mcp-oauth-tokens.ts
7082
7315
  init_esm_shims();
7083
7316
  init_database_wrapper();
7084
7317
  init_schema();
7085
- import { and as and21, eq as eq29, isNull as isNull6 } from "drizzle-orm";
7318
+ import { and as and22, eq as eq30, isNull as isNull6 } from "drizzle-orm";
7086
7319
 
7087
7320
  // src/db/repositories/users.ts
7088
7321
  init_esm_shims();
7089
7322
  init_types2();
7090
- import { eq as eq30, like as like15 } from "drizzle-orm";
7323
+ import { eq as eq31, like as like15, sql as sql14 } from "drizzle-orm";
7091
7324
  init_ids();
7092
7325
  init_database_wrapper();
7093
7326
  init_schema();
@@ -7187,7 +7420,7 @@ var UsersRepository = class {
7187
7420
  * Check if unix_username is already taken by another user
7188
7421
  */
7189
7422
  async isUnixUsernameTaken(unixUsername, excludeUserId) {
7190
- const result = await select(this.db).from(users3).where(eq30(users3.unix_username, unixUsername)).one();
7423
+ const result = await select(this.db).from(users3).where(eq31(users3.unix_username, unixUsername)).one();
7191
7424
  if (!result) {
7192
7425
  return false;
7193
7426
  }
@@ -7210,7 +7443,7 @@ var UsersRepository = class {
7210
7443
  }
7211
7444
  const insertData = this.userToInsert(data);
7212
7445
  await insert(this.db, users3).values(insertData).run();
7213
- const row = await select(this.db).from(users3).where(eq30(users3.user_id, insertData.user_id)).one();
7446
+ const row = await select(this.db).from(users3).where(eq31(users3.user_id, insertData.user_id)).one();
7214
7447
  if (!row) {
7215
7448
  throw new RepositoryError("Failed to retrieve created user");
7216
7449
  }
@@ -7222,7 +7455,7 @@ var UsersRepository = class {
7222
7455
  async findById(id) {
7223
7456
  try {
7224
7457
  const fullId = await this.resolveId(id);
7225
- const result = await select(this.db).from(users3).where(eq30(users3.user_id, fullId)).one();
7458
+ const result = await select(this.db).from(users3).where(eq31(users3.user_id, fullId)).one();
7226
7459
  if (!result) {
7227
7460
  return null;
7228
7461
  }
@@ -7238,12 +7471,41 @@ var UsersRepository = class {
7238
7471
  * Find user by email
7239
7472
  */
7240
7473
  async findByEmail(email) {
7241
- const result = await select(this.db).from(users3).where(eq30(users3.email, email)).one();
7474
+ const result = await select(this.db).from(users3).where(eq31(users3.email, email)).one();
7242
7475
  if (!result) {
7243
7476
  return null;
7244
7477
  }
7245
7478
  return this.rowToUser(result);
7246
7479
  }
7480
+ /**
7481
+ * Find user by email for external identity providers.
7482
+ *
7483
+ * Agor intentionally keeps exact/case-sensitive email lookup semantics for
7484
+ * auth paths because the schema historically allowed case-distinct emails.
7485
+ * External providers such as Slack and GitHub treat email addresses as a
7486
+ * canonical identity hint, so their alignment path needs a case-insensitive
7487
+ * match. Prefer an exact match when present; otherwise return a
7488
+ * case-insensitive match only when it is unambiguous.
7489
+ */
7490
+ async findByEmailForAlignment(email) {
7491
+ const normalizedEmail = email.trim().toLowerCase();
7492
+ if (!normalizedEmail) return null;
7493
+ const exact = await this.findByEmail(normalizedEmail);
7494
+ if (exact) return exact;
7495
+ const results = await select(this.db).from(users3).where(sql14`LOWER(${users3.email}) = ${normalizedEmail}`).all();
7496
+ if (results.length !== 1) {
7497
+ if (results.length > 1) {
7498
+ console.warn(
7499
+ `[users] Ambiguous case-insensitive email alignment for ${normalizedEmail}: ${results.map((row) => {
7500
+ const userRow = row;
7501
+ return `${shortId(userRow.user_id)}:${userRow.email}`;
7502
+ }).join(", ")}`
7503
+ );
7504
+ }
7505
+ return null;
7506
+ }
7507
+ return this.rowToUser(results[0]);
7508
+ }
7247
7509
  /**
7248
7510
  * Find all users
7249
7511
  */
@@ -7280,8 +7542,8 @@ var UsersRepository = class {
7280
7542
  await update(this.db, users3).set({
7281
7543
  ...insertData,
7282
7544
  updated_at: /* @__PURE__ */ new Date()
7283
- }).where(eq30(users3.user_id, fullId)).run();
7284
- const row = await select(this.db).from(users3).where(eq30(users3.user_id, fullId)).one();
7545
+ }).where(eq31(users3.user_id, fullId)).run();
7546
+ const row = await select(this.db).from(users3).where(eq31(users3.user_id, fullId)).one();
7285
7547
  if (!row) {
7286
7548
  throw new RepositoryError("Failed to retrieve updated user");
7287
7549
  }
@@ -7292,7 +7554,7 @@ var UsersRepository = class {
7292
7554
  */
7293
7555
  async delete(id) {
7294
7556
  const fullId = await this.resolveId(id);
7295
- await deleteFrom(this.db, users3).where(eq30(users3.user_id, fullId)).run();
7557
+ await deleteFrom(this.db, users3).where(eq31(users3.user_id, fullId)).run();
7296
7558
  }
7297
7559
  /**
7298
7560
  * Get raw database row (internal use only - includes encrypted keys)
@@ -7300,7 +7562,7 @@ var UsersRepository = class {
7300
7562
  async getRawRow(id) {
7301
7563
  try {
7302
7564
  const fullId = await this.resolveId(id);
7303
- const result = await select(this.db).from(users3).where(eq30(users3.user_id, fullId)).one();
7565
+ const result = await select(this.db).from(users3).where(eq31(users3.user_id, fullId)).one();
7304
7566
  return result;
7305
7567
  } catch (error) {
7306
7568
  if (error instanceof EntityNotFoundError) {
@@ -7382,7 +7644,7 @@ var UsersRepository = class {
7382
7644
  await update(this.db, users3).set({
7383
7645
  data: { ...row.data, agentic_tools: next },
7384
7646
  updated_at: /* @__PURE__ */ new Date()
7385
- }).where(eq30(users3.user_id, fullId)).run();
7647
+ }).where(eq31(users3.user_id, fullId)).run();
7386
7648
  }
7387
7649
  /**
7388
7650
  * Delete a single credential field for a tool.
@@ -7408,7 +7670,7 @@ var UsersRepository = class {
7408
7670
  await update(this.db, users3).set({
7409
7671
  data: { ...row.data, agentic_tools: next },
7410
7672
  updated_at: /* @__PURE__ */ new Date()
7411
- }).where(eq30(users3.user_id, fullId)).run();
7673
+ }).where(eq31(users3.user_id, fullId)).run();
7412
7674
  }
7413
7675
  };
7414
7676
 
@@ -8776,6 +9038,30 @@ var UnixIntegrationService = class {
8776
9038
  this.usersRepo = new UsersRepository(db);
8777
9039
  this.repoRepo = new RepoRepository(db);
8778
9040
  }
9041
+ async getUnixUsernamesForUsers(userIds) {
9042
+ const unixUsernames = /* @__PURE__ */ new Set();
9043
+ for (const userId of userIds) {
9044
+ const user = await this.usersRepo.findById(userId);
9045
+ if (user?.unix_username) {
9046
+ unixUsernames.add(user.unix_username);
9047
+ }
9048
+ }
9049
+ return unixUsernames;
9050
+ }
9051
+ async reconcileUnixGroupMembers(groupName, allowedUnixUsernames, options) {
9052
+ if (this.config.daemonUser) {
9053
+ allowedUnixUsernames.add(this.config.daemonUser);
9054
+ }
9055
+ const result = await this.executor.exec(UnixGroupCommands.listGroupMembers(groupName));
9056
+ const currentMembers = result.stdout.trim().split(",").filter(Boolean);
9057
+ for (const unixUsername of currentMembers) {
9058
+ if (allowedUnixUsernames.has(unixUsername)) continue;
9059
+ console.log(
9060
+ `[UnixIntegration] Removing stale ${options.label} group member ${unixUsername} from ${groupName}`
9061
+ );
9062
+ await this.executor.exec(UnixGroupCommands.removeUserFromGroup(unixUsername, groupName));
9063
+ }
9064
+ }
8779
9065
  /**
8780
9066
  * Get the configured daemon user
8781
9067
  *
@@ -9019,19 +9305,26 @@ var UnixIntegrationService = class {
9019
9305
  /**
9020
9306
  * Initialize Unix group for an existing branch
9021
9307
  *
9022
- * Creates group and adds all current owners.
9308
+ * Creates group and adds all users with explicit filesystem access.
9023
9309
  *
9024
9310
  * @param branchId - Branch ID
9025
9311
  */
9026
9312
  async initializeBranchGroup(branchId) {
9027
9313
  const groupName = await this.createBranchGroup(branchId);
9028
- const ownerIds = await this.branchRepo.getOwners(branchId);
9029
- for (const ownerId of ownerIds) {
9030
- await this.addUserToBranchGroup(branchId, ownerId);
9314
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(branchId);
9315
+ for (const userId of userIds) {
9316
+ await this.addUserToBranchGroup(branchId, userId);
9031
9317
  }
9318
+ await this.reconcileUnixGroupMembers(groupName, await this.getUnixUsernamesForUsers(userIds), {
9319
+ label: "branch"
9320
+ });
9032
9321
  console.log(
9033
- `[UnixIntegration] Initialized group ${groupName} with ${ownerIds.length} owner(s)`
9322
+ `[UnixIntegration] Initialized group ${groupName} with ${userIds.length} explicit filesystem user(s)`
9034
9323
  );
9324
+ const branch = await this.branchRepo.findById(branchId);
9325
+ if (branch?.repo_id) {
9326
+ await this.syncRepo(branch.repo_id);
9327
+ }
9035
9328
  }
9036
9329
  // ============================================================
9037
9330
  // REPO GROUP MANAGEMENT
@@ -9263,8 +9556,8 @@ var UnixIntegrationService = class {
9263
9556
  /**
9264
9557
  * Check if a user should be in a repo's Unix group
9265
9558
  *
9266
- * A user should be in the repo group if they have ownership
9267
- * of ANY branch in that repo.
9559
+ * A user should be in the repo group if they have explicit filesystem access
9560
+ * to ANY branch in that repo.
9268
9561
  *
9269
9562
  * @param repoId - Repo ID
9270
9563
  * @param userId - User ID to check
@@ -9273,8 +9566,8 @@ var UnixIntegrationService = class {
9273
9566
  async shouldUserBeInRepoGroup(repoId, userId) {
9274
9567
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9275
9568
  for (const wt of branches4) {
9276
- const isOwner = await this.branchRepo.isOwner(wt.branch_id, userId);
9277
- if (isOwner) {
9569
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
9570
+ if (userIds.includes(userId)) {
9278
9571
  return true;
9279
9572
  }
9280
9573
  }
@@ -9283,33 +9576,36 @@ var UnixIntegrationService = class {
9283
9576
  /**
9284
9577
  * Initialize Unix group for an existing repo
9285
9578
  *
9286
- * Creates group, sets .git permissions, and adds all users who
9287
- * own any branch in the repo.
9579
+ * Creates group, sets .git permissions, and adds all users who have explicit
9580
+ * filesystem access to any branch in the repo.
9288
9581
  *
9289
9582
  * @param repoId - Repo ID
9290
9583
  */
9291
9584
  async initializeRepoGroup(repoId) {
9292
9585
  const groupName = await this.createRepoGroup(repoId);
9293
9586
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9294
- const ownerIds = /* @__PURE__ */ new Set();
9587
+ const userIds = /* @__PURE__ */ new Set();
9295
9588
  for (const wt of branches4) {
9296
- const wtOwners = await this.branchRepo.getOwners(wt.branch_id);
9297
- for (const ownerId of wtOwners) {
9298
- ownerIds.add(ownerId);
9589
+ const branchUserIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
9590
+ for (const userId of branchUserIds) {
9591
+ userIds.add(userId);
9299
9592
  }
9300
9593
  }
9301
- for (const ownerId of ownerIds) {
9302
- await this.addUserToRepoGroup(repoId, ownerId);
9594
+ for (const userId of userIds) {
9595
+ await this.addUserToRepoGroup(repoId, userId);
9303
9596
  }
9597
+ await this.reconcileUnixGroupMembers(groupName, await this.getUnixUsernamesForUsers(userIds), {
9598
+ label: "repo"
9599
+ });
9304
9600
  console.log(
9305
- `[UnixIntegration] Initialized repo group ${groupName} with ${ownerIds.size} unique owner(s)`
9601
+ `[UnixIntegration] Initialized repo group ${groupName} with ${userIds.size} unique filesystem user(s)`
9306
9602
  );
9307
9603
  }
9308
9604
  /**
9309
9605
  * Full sync for a repo
9310
9606
  *
9311
9607
  * Ensures repo group exists, .git permissions are set, and all
9312
- * branch owners are in the repo group.
9608
+ * branch filesystem-access users are in the repo group.
9313
9609
  *
9314
9610
  * @param repoId - Repo ID
9315
9611
  */
@@ -9317,15 +9613,23 @@ var UnixIntegrationService = class {
9317
9613
  console.log(`[UnixIntegration] Full sync for repo ${shortId(repoId)}`);
9318
9614
  await this.createRepoGroup(repoId);
9319
9615
  const branches4 = await this.branchRepo.findAll({ repo_id: repoId });
9320
- const ownerIds = /* @__PURE__ */ new Set();
9616
+ const userIds = /* @__PURE__ */ new Set();
9321
9617
  for (const wt of branches4) {
9322
- const wtOwners = await this.branchRepo.getOwners(wt.branch_id);
9323
- for (const ownerId of wtOwners) {
9324
- ownerIds.add(ownerId);
9618
+ const branchUserIds = await this.branchRepo.findExplicitFsAccessUserIds(wt.branch_id);
9619
+ for (const userId of branchUserIds) {
9620
+ userIds.add(userId);
9325
9621
  }
9326
9622
  }
9327
- for (const ownerId of ownerIds) {
9328
- await this.addUserToRepoGroup(repoId, ownerId);
9623
+ for (const userId of userIds) {
9624
+ await this.addUserToRepoGroup(repoId, userId);
9625
+ }
9626
+ const repo = await this.repoRepo.findById(repoId);
9627
+ if (repo?.unix_group) {
9628
+ await this.reconcileUnixGroupMembers(
9629
+ repo.unix_group,
9630
+ await this.getUnixUsernamesForUsers(userIds),
9631
+ { label: "repo" }
9632
+ );
9329
9633
  }
9330
9634
  }
9331
9635
  // ============================================================
@@ -9602,16 +9906,28 @@ var UnixIntegrationService = class {
9602
9906
  /**
9603
9907
  * Full sync for a branch
9604
9908
  *
9605
- * Ensures group exists, all owners are in group, and symlinks are created.
9909
+ * Ensures group exists, all explicit filesystem-access users are in group,
9910
+ * and symlinks are created.
9606
9911
  *
9607
9912
  * @param branchId - Branch ID
9608
9913
  */
9609
9914
  async syncBranch(branchId) {
9610
9915
  console.log(`[UnixIntegration] Full sync for branch ${shortId(branchId)}`);
9611
9916
  await this.createBranchGroup(branchId);
9612
- const ownerIds = await this.branchRepo.getOwners(branchId);
9613
- for (const ownerId of ownerIds) {
9614
- await this.addUserToBranchGroup(branchId, ownerId);
9917
+ const userIds = await this.branchRepo.findExplicitFsAccessUserIds(branchId);
9918
+ for (const userId of userIds) {
9919
+ await this.addUserToBranchGroup(branchId, userId);
9920
+ }
9921
+ const branch = await this.branchRepo.findById(branchId);
9922
+ if (branch?.unix_group) {
9923
+ await this.reconcileUnixGroupMembers(
9924
+ branch.unix_group,
9925
+ await this.getUnixUsernamesForUsers(userIds),
9926
+ { label: "branch" }
9927
+ );
9928
+ }
9929
+ if (branch?.repo_id) {
9930
+ await this.syncRepo(branch.repo_id);
9615
9931
  }
9616
9932
  }
9617
9933
  /**