@askexenow/exe-os 0.9.218 → 0.9.220

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 (237) hide show
  1. package/deploy/compose/.env.customer.example +12 -2
  2. package/deploy/compose/.env.example +42 -16
  3. package/deploy/compose/PROTECTED_FILES.md +1 -0
  4. package/deploy/compose/README.md +1 -1
  5. package/deploy/compose/backup.sh +3 -1
  6. package/deploy/compose/clickhouse-config.xml +18 -0
  7. package/deploy/compose/docker-compose.yml +37 -13
  8. package/deploy/compose/gateway.json +12 -2
  9. package/deploy/compose/generate-env.ts +17 -1
  10. package/deploy/compose/init-db.sql +12 -0
  11. package/deploy/compose/restore.sh +1 -0
  12. package/deploy/compose/setup.sh +3 -1
  13. package/deploy/compose/uptime-check.sh +143 -0
  14. package/dist/{active-agent-R7QDYADX.js → active-agent-JYQI3DAH.js} +2 -2
  15. package/dist/{active-agent-4XH2Q6KJ.js → active-agent-YNZ7YA74.js} +2 -2
  16. package/dist/{agentic-ontology-CHAWPTEY.js → agentic-ontology-6JMLSYYU.js} +1 -1
  17. package/dist/{backfill-metadata-I6VR7JZ2.js → backfill-metadata-WFASPP6Y.js} +3 -3
  18. package/dist/{behaviors-YJ3HEQED.js → behaviors-TT72JVF4.js} +2 -2
  19. package/dist/bin/agentic-ontology-backfill.js +4 -4
  20. package/dist/bin/agentic-reflection-backfill.js +5 -5
  21. package/dist/bin/agentic-semantic-label.js +4 -4
  22. package/dist/bin/backfill-conversations.js +3 -3
  23. package/dist/bin/backfill-responses.js +3 -3
  24. package/dist/bin/backfill-vectors.js +4 -4
  25. package/dist/bin/bulk-sync-postgres.js +5 -5
  26. package/dist/bin/cleanup-stale-review-tasks.js +8 -8
  27. package/dist/bin/cli.js +30 -12
  28. package/dist/bin/exe-agent-config.js +1 -1
  29. package/dist/bin/exe-agent.js +6 -6
  30. package/dist/bin/exe-assign.js +4 -4
  31. package/dist/bin/exe-boot.js +15 -15
  32. package/dist/bin/exe-call.js +3 -3
  33. package/dist/bin/exe-cloud.js +3 -3
  34. package/dist/bin/exe-dispatch.js +8 -8
  35. package/dist/bin/exe-doctor.js +1 -1
  36. package/dist/bin/exe-export-behaviors.js +6 -6
  37. package/dist/bin/exe-forget.js +5 -5
  38. package/dist/bin/exe-gateway.js +38 -12
  39. package/dist/bin/exe-heartbeat.js +8 -8
  40. package/dist/bin/exe-kill.js +11 -11
  41. package/dist/bin/exe-launch-agent.js +15 -15
  42. package/dist/bin/exe-new-employee.js +5 -5
  43. package/dist/bin/exe-pending-messages.js +9 -9
  44. package/dist/bin/exe-pending-notifications.js +8 -8
  45. package/dist/bin/exe-pending-reviews.js +8 -8
  46. package/dist/bin/exe-rename.js +3 -3
  47. package/dist/bin/exe-review.js +10 -10
  48. package/dist/bin/exe-search.js +4 -4
  49. package/dist/bin/exe-session-cleanup.js +13 -13
  50. package/dist/bin/exe-settings.js +3 -3
  51. package/dist/bin/exe-start-codex.js +10 -10
  52. package/dist/bin/exe-start-opencode.js +7 -7
  53. package/dist/bin/exe-status.js +9 -9
  54. package/dist/bin/exe-team.js +2 -2
  55. package/dist/bin/git-sweep.js +8 -8
  56. package/dist/bin/graph-backfill.js +3 -3
  57. package/dist/bin/graph-export.js +4 -4
  58. package/dist/bin/import-history.js +4 -4
  59. package/dist/bin/install.js +5 -5
  60. package/dist/bin/intercom-check.js +4 -4
  61. package/dist/bin/mcp-sessions.js +2 -2
  62. package/dist/bin/orchestration-metrics.js +3 -3
  63. package/dist/bin/postgres-agentic-reflection-backfill.js +2 -2
  64. package/dist/bin/postgres-agentic-semantic-backfill.js +1 -1
  65. package/dist/bin/scan-tasks.js +8 -8
  66. package/dist/bin/setup.js +1 -1
  67. package/dist/bin/shard-migrate.js +3 -3
  68. package/dist/bin/stack-update.js +1 -1
  69. package/dist/bin/vps-health-gate.js +1 -1
  70. package/dist/{capacity-monitor-XFMZSJDB.js → capacity-monitor-HBSR35IL.js} +9 -9
  71. package/dist/{catchup-brief-D5IZFZDO.js → catchup-brief-JSUYYPQ3.js} +10 -10
  72. package/dist/{chunk-RSHVFBKD.js → chunk-3IBL2IIP.js} +8 -8
  73. package/dist/{chunk-JXJV64JW.js → chunk-44PHDWBT.js} +14 -9
  74. package/dist/{chunk-4ANCHFE2.js → chunk-47AYA4NC.js} +1 -1
  75. package/dist/{chunk-NEGJAEZ7.js → chunk-4DCP2XYD.js} +3 -3
  76. package/dist/{chunk-WEJ45ZFF.js → chunk-4SKD6TQ7.js} +2 -2
  77. package/dist/{chunk-2QNMGFIF.js → chunk-5Y5I65H6.js} +2 -2
  78. package/dist/{chunk-SDQSOQOE.js → chunk-6LDJZ6YC.js} +2 -2
  79. package/dist/{chunk-FXD53Q32.js → chunk-6XWI25AO.js} +3 -3
  80. package/dist/{chunk-GKNYEJQ3.js → chunk-7FEIB32Y.js} +1 -1
  81. package/dist/{chunk-BFLBZGPZ.js → chunk-7TKOVU64.js} +1 -1
  82. package/dist/{chunk-I22ZH3XF.js → chunk-A74RTD5M.js} +1 -1
  83. package/dist/{chunk-4GXXYDNU.js → chunk-A77WVNU2.js} +41 -0
  84. package/dist/{chunk-PKIOJQ2N.js → chunk-ANNJ4GH5.js} +1 -1
  85. package/dist/{chunk-5G643UWZ.js → chunk-AVJGBAJR.js} +117 -8
  86. package/dist/{chunk-IFSAR5IX.js → chunk-BMWBBDHF.js} +5 -5
  87. package/dist/{chunk-R766IOBQ.js → chunk-BPV3F7M6.js} +1 -1
  88. package/dist/{chunk-BN3HRSEU.js → chunk-BXJCPGN3.js} +2 -2
  89. package/dist/{chunk-I6474EQW.js → chunk-BXQCL72Y.js} +1 -1
  90. package/dist/{chunk-S4I3UITZ.js → chunk-EFDIUJWC.js} +1 -1
  91. package/dist/{chunk-GEFZHKEN.js → chunk-FYK4QDZ6.js} +5 -5
  92. package/dist/{chunk-B7NO5U7H.js → chunk-GKEEC3P7.js} +1 -1
  93. package/dist/{chunk-T43SC2XX.js → chunk-GLSU6RYP.js} +2 -2
  94. package/dist/{chunk-W7OCXE2L.js → chunk-IC6NXF2N.js} +1 -1
  95. package/dist/{chunk-JJHJOGYR.js → chunk-J3GQXXQR.js} +1 -1
  96. package/dist/{chunk-64DYFA5X.js → chunk-LIOPFUTM.js} +3 -3
  97. package/dist/{chunk-7X6QKJGM.js → chunk-LMLSZFPH.js} +2 -2
  98. package/dist/{chunk-O6LFXATW.js → chunk-LNRYYEGG.js} +3 -3
  99. package/dist/{chunk-5VOC35A3.js → chunk-LZL5MGMH.js} +1 -1
  100. package/dist/{chunk-RSVJQ4E2.js → chunk-MPWYUOB7.js} +1 -1
  101. package/dist/{chunk-5QKUR5KS.js → chunk-MSSB6VBT.js} +1 -1
  102. package/dist/{chunk-NUUAYDD6.js → chunk-NERANZPH.js} +1 -1
  103. package/dist/{chunk-NO5GHSNU.js → chunk-NLEWVXX4.js} +4 -3
  104. package/dist/{chunk-QOY6CTHV.js → chunk-NO6PSA2A.js} +2 -2
  105. package/dist/{chunk-2DRWIXOO.js → chunk-NU3NSUDL.js} +2 -2
  106. package/dist/{chunk-UO3IEPSY.js → chunk-NWNWETME.js} +244 -339
  107. package/dist/{chunk-6UY62EGD.js → chunk-O4JHGHLZ.js} +4 -4
  108. package/dist/chunk-OC2JSGTJ.js +225 -0
  109. package/dist/{chunk-46WQ76VA.js → chunk-OFPDYF24.js} +1 -1
  110. package/dist/{chunk-F54CVIXL.js → chunk-OQUWRF5K.js} +1 -1
  111. package/dist/{chunk-XPKACO5A.js → chunk-ORYGKBVB.js} +8 -8
  112. package/dist/{chunk-HURS5JVX.js → chunk-OV2DYWB6.js} +21 -3
  113. package/dist/{chunk-S2T7CE4P.js → chunk-R3HP5EZQ.js} +1 -1
  114. package/dist/{chunk-KEFHCL4U.js → chunk-RUM6GJKH.js} +1 -1
  115. package/dist/{chunk-2IMUAL3X.js → chunk-S6OEMZ76.js} +8 -8
  116. package/dist/{chunk-HW46Q4AR.js → chunk-SEV5S5AQ.js} +257 -10
  117. package/dist/{chunk-R2MZDZTQ.js → chunk-TEF5NCBV.js} +3 -3
  118. package/dist/{chunk-YJNRRQOG.js → chunk-U3AATEDZ.js} +2 -2
  119. package/dist/{chunk-ALVYUOBW.js → chunk-UCHIXGLP.js} +1 -1
  120. package/dist/{chunk-RTGN42GD.js → chunk-UTQTHZ4H.js} +2 -2
  121. package/dist/{chunk-CIANVJ3G.js → chunk-UVUA2DQM.js} +61 -6
  122. package/dist/{chunk-ACOW43IN.js → chunk-X3ZMMUTS.js} +1 -1
  123. package/dist/{chunk-S5TTV7PC.js → chunk-XFLVRS2F.js} +1 -1
  124. package/dist/{chunk-CUKIMXQ7.js → chunk-Y7HLJSYI.js} +1 -1
  125. package/dist/{chunk-6I7O6YW3.js → chunk-YKTV34T6.js} +3 -3
  126. package/dist/{co-occurrence-EWVCCFOI.js → co-occurrence-VWWDUBWI.js} +1 -1
  127. package/dist/{crdt-sync-TSO4O67N.js → crdt-sync-RCMMFHSQ.js} +1 -1
  128. package/dist/{crm-webhook-WMAW6ZT2.js → crm-webhook-GD2UTF2H.js} +2 -2
  129. package/dist/{cto-delegation-gate-YNWMQEQB.js → cto-delegation-gate-5DEH7LAZ.js} +7 -7
  130. package/dist/{daemon-orchestration-5KUKQOZ4.js → daemon-orchestration-FPHCMQX5.js} +14 -10
  131. package/dist/{exe-drift-KP5RZCXA.js → exe-drift-TFXY2LTU.js} +2 -2
  132. package/dist/{exe-export-RAYK76SO.js → exe-export-MFVCOY5E.js} +4 -4
  133. package/dist/{exe-import-SAJBGUN5.js → exe-import-XXOTZX6Y.js} +4 -4
  134. package/dist/{exe-key-W3CME65M.js → exe-key-MGIZ2LCZ.js} +1 -1
  135. package/dist/{fast-db-init-5VDTKVKX.js → fast-db-init-MS7MJ2B2.js} +1 -1
  136. package/dist/gateway/index.js +6 -6
  137. package/dist/{git-staleness-M7WLXBAA.js → git-staleness-WTLCKKNF.js} +1 -1
  138. package/dist/{git-task-sweep-GED54WTZ.js → git-task-sweep-QU4Y5RHC.js} +8 -8
  139. package/dist/{global-procedures-EYWKFVOO.js → global-procedures-S6ZVVLBM.js} +2 -2
  140. package/dist/{graph-auto-extract-B4W4BEOZ.js → graph-auto-extract-ZJ7LNTSH.js} +1 -1
  141. package/dist/hooks/bug-report-worker.js +9 -9
  142. package/dist/hooks/codex-stop-task-finalizer.js +9 -9
  143. package/dist/hooks/commit-complete.js +10 -10
  144. package/dist/hooks/error-recall.js +5 -5
  145. package/dist/hooks/exe-heartbeat-hook.js +2 -2
  146. package/dist/hooks/ingest.js +5 -5
  147. package/dist/hooks/instructions-loaded.js +3 -3
  148. package/dist/hooks/manifest.json +19 -19
  149. package/dist/hooks/notification.js +3 -3
  150. package/dist/hooks/post-compact.js +9 -9
  151. package/dist/hooks/post-tool-combined.js +4 -4
  152. package/dist/hooks/pre-compact.js +10 -10
  153. package/dist/hooks/pre-tool-use.js +13 -13
  154. package/dist/hooks/prompt-submit.js +19 -19
  155. package/dist/hooks/session-end.js +13 -13
  156. package/dist/hooks/session-start.js +28 -9
  157. package/dist/hooks/stop.js +13 -13
  158. package/dist/hooks/subagent-stop.js +9 -9
  159. package/dist/hooks/summary-worker.js +13 -13
  160. package/dist/import-conversations-K7HNDJN7.js +23 -0
  161. package/dist/index.js +15 -15
  162. package/dist/{installer-WVPFKMDW.js → installer-42KVGDGD.js} +4 -4
  163. package/dist/{installer-X6XJE2EA.js → installer-KZVGXCRL.js} +4 -4
  164. package/dist/{installer-EYRABPEC.js → installer-VH4GYJQO.js} +4 -4
  165. package/dist/lib/cloud-sync.js +3 -3
  166. package/dist/lib/consolidation.js +4 -4
  167. package/dist/lib/database.js +1 -1
  168. package/dist/lib/db.js +1 -1
  169. package/dist/lib/employee-templates.js +3 -3
  170. package/dist/lib/employees.js +1 -1
  171. package/dist/lib/exe-daemon.js +79 -35
  172. package/dist/lib/hybrid-search.js +4 -4
  173. package/dist/lib/identity.js +1 -1
  174. package/dist/lib/messaging.js +8 -8
  175. package/dist/lib/reminders.js +2 -2
  176. package/dist/lib/schedules.js +4 -4
  177. package/dist/lib/session-registry.js +3 -3
  178. package/dist/lib/skill-learning.js +3 -3
  179. package/dist/lib/store.js +3 -3
  180. package/dist/lib/task-router.js +2 -2
  181. package/dist/lib/tasks.js +8 -8
  182. package/dist/lib/tmux-routing.js +7 -7
  183. package/dist/lib/token-spend.js +2 -2
  184. package/dist/mcp/register-tools.js +47 -46
  185. package/dist/mcp/server.js +48 -47
  186. package/dist/mcp/tools/complete-reminder.js +3 -3
  187. package/dist/mcp/tools/create-reminder.js +3 -3
  188. package/dist/mcp/tools/create-task.js +10 -10
  189. package/dist/mcp/tools/deactivate-behavior.js +4 -4
  190. package/dist/mcp/tools/list-reminders.js +3 -3
  191. package/dist/mcp/tools/list-tasks.js +10 -10
  192. package/dist/mcp/tools/send-message.js +10 -10
  193. package/dist/mcp/tools/update-task.js +9 -9
  194. package/dist/{mcp-http-config-L4U52ZAF.js → mcp-http-config-QFVZZ4P6.js} +2 -2
  195. package/dist/{memory-cards-I55OBMVE.js → memory-cards-7TZMVN4S.js} +1 -1
  196. package/dist/{memory-graph-extractor-6M6J5FNX.js → memory-graph-extractor-ZENXY3L6.js} +2 -2
  197. package/dist/{memory-poisoning-defense-UXB75NB7.js → memory-poisoning-defense-T6AN332J.js} +1 -1
  198. package/dist/{memory-reflection-3BMVNA6T.js → memory-reflection-5AYMWWGN.js} +1 -1
  199. package/dist/{notifications-SCHILQCQ.js → notifications-2RAIJMID.js} +7 -7
  200. package/dist/{orchestration-events-RDW7BTCK.js → orchestration-events-IDQXVP34.js} +2 -2
  201. package/dist/{orchestrator-NCEFZF32.js → orchestrator-BOSGXSGR.js} +9 -9
  202. package/dist/{plan-limits-YE5WKMQM.js → plan-limits-WAZUVFZQ.js} +2 -2
  203. package/dist/{projection-worker-ENYZ7THQ.js → projection-worker-4DV5SIDZ.js} +1 -1
  204. package/dist/{reranker-QFLVGVRT.js → reranker-HN6E3YET.js} +1 -1
  205. package/dist/{review-polling-ZKYFETP3.js → review-polling-6ALBGRQM.js} +8 -8
  206. package/dist/runtime/index.js +10 -10
  207. package/dist/{session-events-XCNQDXF4.js → session-events-7RWZYWPX.js} +8 -8
  208. package/dist/{session-kill-telemetry-SPB6LEI5.js → session-kill-telemetry-SXLEJ2PW.js} +2 -2
  209. package/dist/{session-scope-FEZQJMD4.js → session-scope-2TPIWVAK.js} +7 -7
  210. package/dist/{setup-wizard-KUYMMP35.js → setup-wizard-HOFPOKHS.js} +1 -1
  211. package/dist/{skill-refinement-QHOS6CGQ.js → skill-refinement-JH3EF5GK.js} +1 -1
  212. package/dist/{stack-update-UCIPCTBO.js → stack-update-SASYGDOB.js} +1 -1
  213. package/dist/{task-enforcement-HVY36QRD.js → task-enforcement-2QFS3YYE.js} +7 -7
  214. package/dist/{task-scope-ODSOEGTH.js → task-scope-HHNLGA7M.js} +7 -7
  215. package/dist/{tasks-crud-RIUHZJGR.js → tasks-crud-T4HZTUEJ.js} +17 -7
  216. package/dist/{tasks-review-EBUVFQUJ.js → tasks-review-YHRQHOI3.js} +7 -7
  217. package/dist/{telemetry-upload-DFISOB2V.js → telemetry-upload-5OOAFOOI.js} +3 -3
  218. package/dist/{token-budget-6TTILQW7.js → token-budget-D5LTVJNN.js} +1 -1
  219. package/dist/{tool-telemetry-BNZJICWG.js → tool-telemetry-A47IJB4I.js} +1 -1
  220. package/dist/tui/App.js +15 -15
  221. package/dist/{tui-data-UM6LR4EQ.js → tui-data-NEJQFARB.js} +7 -7
  222. package/dist/{worker-gate-K5YTO2H5.js → worker-gate-FWMGWC6D.js} +1 -1
  223. package/dist/{workflow-engine-WUU5OZ3N.js → workflow-engine-YI2GCCWL.js} +2 -2
  224. package/dist/{worktree-XZBJQWQZ.js → worktree-EO73ZMHX.js} +3 -3
  225. package/package.json +1 -1
  226. package/release-notes.json +62 -62
  227. /package/dist/{chunk-KVOTLCAX.js → chunk-3L2RG3ZB.js} +0 -0
  228. /package/dist/{chunk-WRVFZ433.js → chunk-ED4MQPBW.js} +0 -0
  229. /package/dist/{chunk-54JMB5UI.js → chunk-I7K6NY34.js} +0 -0
  230. /package/dist/{chunk-Y2B6MB3J.js → chunk-MLCYKSTC.js} +0 -0
  231. /package/dist/{chunk-MQA6K7DH.js → chunk-MOM2Z2QO.js} +0 -0
  232. /package/dist/{chunk-HNXHUG7A.js → chunk-OMJW5FZ5.js} +0 -0
  233. /package/dist/{chunk-K77FHRYS.js → chunk-T6UW3VZN.js} +0 -0
  234. /package/dist/{chunk-DXB3CB2O.js → chunk-TEFFJZGT.js} +0 -0
  235. /package/dist/{chunk-4AJYZFDE.js → chunk-YDE4RYQF.js} +0 -0
  236. /package/dist/{core-memory-NZOLAIOE.js → core-memory-ZML3QGOE.js} +0 -0
  237. /package/dist/{wiki-acl-QYGMJDUT.js → wiki-acl-GVQMBGRQ.js} +0 -0
@@ -13,6 +13,14 @@ CLICKHOUSE_PASSWORD=CHANGEME_CLICKHOUSE_PASSWORD
13
13
 
14
14
  REDIS_PASSWORD=CHANGEME_REDIS_PASSWORD
15
15
 
16
+ # --- GoTrue (shared auth) ---
17
+ GOTRUE_JWT_SECRET=CHANGEME_GOTRUE_JWT_SECRET
18
+ GOTRUE_API_PORT=9999
19
+ GOTRUE_SITE_URL=https://crm.CHANGEME_DOMAIN
20
+ GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN
21
+ GOTRUE_DISABLE_SIGNUP=false
22
+ GOTRUE_MAILER_AUTOCONFIRM=true
23
+
16
24
  # --- CRM ---
17
25
  CRM_IMAGE_TAG=update.askexe.com/askexe/exe-crm:v0.9.3
18
26
  CRM_SERVER_URL=https://CHANGEME_DOMAIN
@@ -33,6 +41,8 @@ WIKI_HOST_PORT=3001
33
41
  EXE_OS_IMAGE_TAG=update.askexe.com/askexe/exe-os:v0.9.9
34
42
  EXED_MCP_TOKEN=CHANGEME_EXED_MCP_TOKEN
35
43
  EXED_DEVICE_ID=hygo-vps
44
+ EXE_MCP_HOST_BIND=0.0.0.0
45
+ EXE_MCP_HOST_PORT=48739
36
46
  # VPS-only: enables cloud/local SQLite -> exe-db Postgres projection.
37
47
  # Keep false on laptops/dev boxes.
38
48
  EXE_CLOUD_SYNC_TO_POSTGRES=true
@@ -55,8 +65,8 @@ GATEWAY_WS_HOST_PORT=3101
55
65
 
56
66
  # --- Monitoring agent (standard for managed customer VPSs) ---
57
67
  MONITOR_AGENT_IMAGE_TAG=update.askexe.com/askexe/exe-monitor-agent:v0.9.3
58
- MONITOR_HUB_URL=https://monitor.askexe.com
59
- # Required: values copied from monitor.askexe.com when adding the Hygo/customer system.
68
+ MONITOR_HUB_URL=http://exe-monitor-hub:8090
69
+ # Required: values copied from the local exe-monitor-hub when adding the Hygo/customer system.
60
70
  MONITOR_AGENT_TOKEN=CHANGEME_MONITOR_AGENT_TOKEN_FROM_MONITOR_HUB
61
71
  MONITOR_AGENT_KEY=CHANGEME_MONITOR_AGENT_PUBLIC_KEY_FROM_MONITOR_HUB
62
72
  MONITOR_AGENT_LISTEN=:45876
@@ -1,6 +1,6 @@
1
1
  # exe-os VPS stack — example environment variables
2
- # Run `exe-os stack-init` or `node deploy/compose/generate-env.js` to auto-generate
3
- # all secrets. Or copy to .env and replace CHANGEME_* values manually.
2
+ # Copy to .env before deployment and replace every CHANGEME_* value.
3
+ # Values under # SET_MANUALLY must be provided by the operator.
4
4
 
5
5
  # --- Data Layer ---
6
6
  POSTGRES_USER=exe
@@ -15,14 +15,15 @@ REDIS_PASSWORD=CHANGEME_REDIS_PASSWORD
15
15
 
16
16
  # --- GoTrue (shared auth) ---
17
17
  GOTRUE_JWT_SECRET=CHANGEME_GOTRUE_JWT_SECRET
18
- GOTRUE_SITE_URL=https://crm.askexe.com
19
- GOTRUE_EXTERNAL_URL=https://auth.askexe.com
18
+ GOTRUE_API_PORT=9999
19
+ GOTRUE_SITE_URL=https://crm.CHANGEME_DOMAIN
20
+ GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN
20
21
  GOTRUE_DISABLE_SIGNUP=false
21
22
  GOTRUE_MAILER_AUTOCONFIRM=true
22
23
 
23
24
  # --- CRM ---
24
- CRM_IMAGE_TAG=ghcr.io/askexe/exe-crm:v0.9.3
25
- CRM_SERVER_URL=https://crm.askexe.com
25
+ CRM_IMAGE_TAG=ghcr.io/askexe/exe-crm:v0.9.4
26
+ CRM_SERVER_URL=https://CHANGEME_DOMAIN
26
27
  CRM_APP_SECRET=CHANGEME_CRM_APP_SECRET
27
28
  EXE_CRM_ADMIN_TOKEN=CHANGEME_EXE_CRM_ADMIN_TOKEN
28
29
  CRM_HOST_PORT=3000
@@ -38,28 +39,53 @@ WIKI_SIG_KEY=CHANGEME_WIKI_SIG_KEY
38
39
  WIKI_SIG_SALT=CHANGEME_WIKI_SIG_SALT
39
40
  WIKI_HOST_PORT=3001
40
41
 
41
- # --- exe-os (daemon) ---
42
+ # --- exe-os ---
42
43
  EXE_OS_IMAGE_TAG=ghcr.io/askexe/exe-os:v0.9.154
43
44
  EXED_MCP_TOKEN=CHANGEME_EXED_MCP_TOKEN
44
45
  EXED_DEVICE_ID=vps-default
46
+ EXE_MCP_HOST_BIND=0.0.0.0
47
+ EXE_MCP_HOST_PORT=48739
48
+ # VPS-only: enables cloud/local SQLite -> exe-db Postgres projection.
49
+ # Keep false on laptops/dev boxes.
45
50
  EXE_CLOUD_SYNC_TO_POSTGRES=true
46
- EXE_LICENSE_KEY=CHANGEME_EXE_LICENSE_KEY
47
51
 
48
52
  # --- Gateway ---
49
- GATEWAY_IMAGE_TAG=ghcr.io/askexe/exe-gateway:v0.9.3
53
+ GATEWAY_IMAGE_TAG=ghcr.io/askexe/exe-gateway:v0.9.4
50
54
  EXE_GATEWAY_AUTH_TOKEN=CHANGEME_EXE_GATEWAY_AUTH_TOKEN
51
55
  EXE_GATEWAY_WS_RELAY_AUTH_TOKEN=CHANGEME_EXE_GATEWAY_WS_RELAY_AUTH_TOKEN
52
56
  EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN=CHANGEME_EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN
57
+ # SET_MANUALLY
58
+ WHATSAPP_ACCESS_TOKEN=CHANGEME_WHATSAPP_ACCESS_TOKEN
53
59
  API_ROUTER_URL=https://gateway.askexe.com
60
+ API_ROUTER_KEY=CHANGEME_API_ROUTER_KEY
61
+ # BYOK: to use your own API keys instead of the Exe API Router,
62
+ # set BYOK_ENABLED=true and provide ANTHROPIC_API_KEY below.
63
+ # BYOK_ENABLED=false
64
+ # ANTHROPIC_API_KEY=CHANGEME_ANTHROPIC_API_KEY
54
65
  GATEWAY_HTTP_HOST_PORT=3100
55
66
  GATEWAY_WS_HOST_PORT=3101
56
67
 
57
- # --- Monitoring ---
58
- MONITOR_HUB_IMAGE_TAG=ghcr.io/askexe/exe-monitor-hub:v0.9.4
68
+ # --- Monitoring agent (standard for managed customer VPSs) ---
59
69
  MONITOR_AGENT_IMAGE_TAG=ghcr.io/askexe/exe-monitor-agent:v0.9.4
60
- EXE_MONITOR_ADMIN_TOKEN=CHANGEME_EXE_MONITOR_ADMIN_TOKEN
61
- MONITOR_HUB_URL=https://monitor.askexe.com
62
- MONITOR_AGENT_TOKEN=CHANGEME_MONITOR_AGENT_TOKEN
63
- MONITOR_AGENT_KEY=CHANGEME_MONITOR_AGENT_KEY
70
+ MONITOR_HUB_URL=http://exe-monitor-hub:8090
71
+ # Values copied from monitor.askexe.com when adding a new system.
72
+ MONITOR_AGENT_TOKEN=CHANGEME_MONITOR_AGENT_TOKEN_FROM_MONITOR_HUB
73
+ MONITOR_AGENT_KEY=CHANGEME_MONITOR_AGENT_PUBLIC_KEY_FROM_MONITOR_HUB
64
74
  MONITOR_AGENT_LISTEN=:45876
65
- MONITOR_HUB_PORT=8090
75
+
76
+ # --- AskExe central monitoring hub auth (AskExe-owned infra only) ---
77
+ # Customer VPSs normally run only MONITOR_AGENT_* above. These hub values are
78
+ # for monitor.askexe.com on exe-db-jkt.
79
+ MONITOR_HUB_PUBLIC_URL=https://monitor.askexe.com
80
+ MONITOR_HUB_SOURCE_DIR=/opt/exe-monitor
81
+ MONITOR_HUB_HOST_PORT=8090
82
+ MONITOR_HUB_DATA_DIR=/opt/exe-monitor-data
83
+ MONITOR_TRUSTED_AUTH_HEADER=X-AskExe-User-Email
84
+ # Keep false during bootstrap; flip true after the GoTrue auth proxy is live.
85
+ MONITOR_DISABLE_PASSWORD_AUTH=false
86
+ MONITOR_USER_CREATION=true
87
+ MONITOR_SHARE_ALL_SYSTEMS=false
88
+
89
+ # --- License ---
90
+ # injected by deploy_client
91
+ EXE_LICENSE_KEY=CHANGEME_EXE_LICENSE_KEY
@@ -8,6 +8,7 @@ and log a migration notice, not replace the existing one.
8
8
  - `.env` — all secrets, tokens, passwords (PATCHED, never replaced)
9
9
  - `gateway.json` — WhatsApp adapter config, account names
10
10
  - `branding.json` — customer brand colors, fonts, logo
11
+ - `clickhouse-config.xml` — ClickHouse memory/log guardrails
11
12
  - `cloudflared/config.yml` — tunnel ID, credentials, ingress routes
12
13
  - `cloudflared/*.json` — tunnel credential files
13
14
 
@@ -65,7 +65,7 @@ stray `DATABASE_URL`; both the explicit gate and the DB URL are required.
65
65
  ## Volumes
66
66
 
67
67
  `postgres_data`, `clickhouse_data`, `clickhouse_logs`, `redis_data`,
68
- `crm_data`, `wiki_data`, `exed_data`, `gateway_data` — local driver, persisted
68
+ `crm_data`, `wiki_data`, `exe_os_data`, `gateway_data` — local driver, persisted
69
69
  under `/var/lib/docker/volumes/exe-os_*`. Backups (Lane G, Wave 2) snapshot
70
70
  these.
71
71
 
@@ -39,11 +39,12 @@ echo "[backup] Dumping postgres..."
39
39
  docker exec exe-db pg_dumpall -U exe > "$ARCHIVE/postgres.sql" 2>/dev/null || echo "[backup] Postgres dump failed"
40
40
  gzip "$ARCHIVE/postgres.sql" 2>/dev/null || true
41
41
 
42
- # 2. Customer config files (.env, gateway.json, branding.json, cloudflared)
42
+ # 2. Customer config files (.env, gateway.json, branding.json, clickhouse-config.xml, cloudflared)
43
43
  echo "[backup] Backing up config files..."
44
44
  cp "$SCRIPT_DIR/.env" "$ARCHIVE/env.bak" 2>/dev/null || true
45
45
  cp "$SCRIPT_DIR/gateway.json" "$ARCHIVE/gateway.json" 2>/dev/null || true
46
46
  cp "$SCRIPT_DIR/branding.json" "$ARCHIVE/branding.json" 2>/dev/null || true
47
+ cp "$SCRIPT_DIR/clickhouse-config.xml" "$ARCHIVE/clickhouse-config.xml" 2>/dev/null || true
47
48
  cp -r "$SCRIPT_DIR/cloudflared" "$ARCHIVE/cloudflared" 2>/dev/null || true
48
49
 
49
50
  # 3. Gateway auth state (Baileys creds — critical for WhatsApp connection)
@@ -112,6 +113,7 @@ if $DOWNLOAD_MODE; then
112
113
  echo " cp env.bak /opt/exe-stack/.env"
113
114
  echo " cp gateway.json /opt/exe-stack/"
114
115
  echo " cp branding.json /opt/exe-stack/"
116
+ echo " cp clickhouse-config.xml /opt/exe-stack/"
115
117
  echo " cp -r cloudflared/ /opt/exe-stack/"
116
118
  echo " cat postgres.sql.gz | gunzip | docker exec -i exe-db psql -U exe"
117
119
  echo " docker compose up -d"
@@ -0,0 +1,18 @@
1
+ <clickhouse>
2
+ <!--
3
+ Customer VPS guardrails.
4
+ ClickHouse writes its own logs under /var/log/clickhouse-server in addition
5
+ to Docker json-file logs. Keep both bounded so a quiet stack cannot grow
6
+ multi-GB logs with zero application queries.
7
+ -->
8
+ <logger>
9
+ <level>warning</level>
10
+ <size>10000000</size>
11
+ <count>3</count>
12
+ </logger>
13
+
14
+ <!-- Keep ClickHouse from consuming the whole VPS on small 24/7 deployments. -->
15
+ <max_server_memory_usage>1073741824</max_server_memory_usage>
16
+ <mark_cache_size>134217728</mark_cache_size>
17
+ <uncompressed_cache_size>67108864</uncompressed_cache_size>
18
+ </clickhouse>
@@ -65,6 +65,14 @@ services:
65
65
  volumes:
66
66
  - clickhouse_data:/var/lib/clickhouse
67
67
  - clickhouse_logs:/var/log/clickhouse-server
68
+ - ./clickhouse-config.xml:/etc/clickhouse-server/config.d/exe-os-limits.xml:ro
69
+ # ClickHouse calls get_mempolicy()/mbind() during startup; SYS_NICE removes
70
+ # the noisy "Operation not permitted" loop without granting broad privileges.
71
+ cap_add:
72
+ - SYS_NICE
73
+ # Guardrail for small customer VPSs. Query-level limits live in
74
+ # clickhouse-config.xml; mem_limit is the container-level backstop.
75
+ mem_limit: ${CLICKHOUSE_MEM_LIMIT:-1g}
68
76
  ulimits:
69
77
  nofile:
70
78
  soft: 262144
@@ -116,6 +124,7 @@ services:
116
124
  - path: .env
117
125
  required: false
118
126
  environment:
127
+ GOTRUE_API_PORT: ${GOTRUE_API_PORT:-9999}
119
128
  GOTRUE_DB_DRIVER: postgres
120
129
  GOTRUE_DB_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable&search_path=auth
121
130
  GOTRUE_SITE_URL: ${GOTRUE_SITE_URL:-https://crm.askexe.com}
@@ -180,7 +189,7 @@ services:
180
189
  restart: unless-stopped
181
190
  # Auto-migrate on boot: run database init before starting the app.
182
191
  # Twenty CRM won't create tables automatically — this ensures they exist.
183
- command: ["sh", "-c", "yarn database:init:prod 2>/dev/null || true && node dist/src/main"]
192
+ command: ["sh", "-c", "yarn database:init:prod 2>/dev/null || true && node dist/main"]
184
193
  depends_on:
185
194
  exe-db:
186
195
  condition: service_healthy
@@ -201,7 +210,7 @@ services:
201
210
  APP_SECRET: ${CRM_APP_SECRET:?CRM_APP_SECRET is required}
202
211
  EXE_CRM_ADMIN_TOKEN: ${EXE_CRM_ADMIN_TOKEN:-}
203
212
  GOTRUE_URL: http://gotrue:9999
204
- PG_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}
213
+ PG_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable
205
214
  REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD is required}@redis:6379
206
215
  CLICKHOUSE_URL: http://${CLICKHOUSE_USER:-exe}:${CLICKHOUSE_PASSWORD:?CLICKHOUSE_PASSWORD is required}@clickhouse:8123/${CLICKHOUSE_DB:-default}
207
216
  STORAGE_TYPE: local
@@ -249,7 +258,7 @@ services:
249
258
  EXE_LICENSE_KEY: ${EXE_LICENSE_KEY:?EXE_LICENSE_KEY is required — purchase at https://askexe.com}
250
259
  SERVER_URL: ${CRM_SERVER_URL:-https://crm.askexe.com}
251
260
  APP_SECRET: ${CRM_APP_SECRET:?CRM_APP_SECRET is required}
252
- PG_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}
261
+ PG_DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable
253
262
  REDIS_URL: redis://:${REDIS_PASSWORD:?REDIS_PASSWORD is required}@redis:6379
254
263
  CLICKHOUSE_URL: http://${CLICKHOUSE_USER:-exe}:${CLICKHOUSE_PASSWORD:?CLICKHOUSE_PASSWORD is required}@clickhouse:8123/${CLICKHOUSE_DB:-default}
255
264
  STORAGE_TYPE: local
@@ -263,6 +272,12 @@ services:
263
272
  networks:
264
273
  backend:
265
274
  ipv4_address: 10.42.0.24
275
+ healthcheck:
276
+ test: ["CMD-SHELL", "tr '\\0' ' ' < /proc/1/cmdline | grep -q 'worker:prod'"]
277
+ interval: 30s
278
+ timeout: 5s
279
+ start_period: 30s
280
+ retries: 5
266
281
  logging:
267
282
  driver: json-file
268
283
  options: { max-size: "10m", max-file: "3" }
@@ -286,7 +301,7 @@ services:
286
301
  SERVER_PORT: "3001"
287
302
  EXE_LICENSE_KEY: ${EXE_LICENSE_KEY:?EXE_LICENSE_KEY is required — purchase at https://askexe.com}
288
303
  STORAGE_DIR: /app/server/storage
289
- DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?schema=${WIKI_DB_SCHEMA:-wiki}
304
+ DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?schema=${WIKI_DB_SCHEMA:-wiki}&sslmode=disable
290
305
  AUTH_TOKEN: ${WIKI_AUTH_TOKEN:?WIKI_AUTH_TOKEN is required}
291
306
  EXE_WIKI_ADMIN_TOKEN: ${EXE_WIKI_ADMIN_TOKEN:-}
292
307
  GOTRUE_URL: http://gotrue:9999
@@ -325,19 +340,25 @@ services:
325
340
  environment:
326
341
  NODE_ENV: production
327
342
  EXED_PORT: "8765"
328
- EXED_HOST: "127.0.0.1"
343
+ EXED_HOST: "0.0.0.0"
329
344
  EXED_MCP_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
345
+ EXE_DAEMON_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
346
+ EXE_MCP_HOST: "0.0.0.0"
347
+ EXE_MCP_ALLOW_REMOTE: "1"
348
+ EXE_MCP_PORT: "48739"
330
349
  EXED_DEVICE_ID: ${EXED_DEVICE_ID:-vps-default}
331
350
  EXE_LICENSE_KEY: ${EXE_LICENSE_KEY:?EXE_LICENSE_KEY is required — purchase at https://askexe.com}
332
- DATABASE_URL: ${EXED_DATABASE_URL:-postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}}
351
+ DATABASE_URL: ${EXED_DATABASE_URL:-postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable}
333
352
  EXE_CLOUD_SYNC_TO_POSTGRES: ${EXE_CLOUD_SYNC_TO_POSTGRES:-true}
353
+ EXE_OS_DISABLE_NATIVE_KEYCHAIN: "1"
334
354
  EXE_RSS_WARN_MB: ${EXE_RSS_WARN_MB:-6144}
335
355
  EXE_RSS_RESTART_MB: ${EXE_RSS_RESTART_MB:-8192}
336
356
  EXE_OS_DIR: /home/exed/.exe-os
337
357
  volumes:
338
358
  - exe_os_data:/home/exed/.exe-os
339
359
  ports:
340
- - "127.0.0.1:${EXED_HOST_PORT:-8765}:8765"
360
+ - "${EXED_HEALTH_HOST_BIND:-127.0.0.1}:${EXED_HOST_PORT:-8765}:8765"
361
+ - "${EXE_MCP_HOST_BIND:-0.0.0.0}:${EXE_MCP_HOST_PORT:-48739}:48739"
341
362
  networks:
342
363
  backend:
343
364
  ipv4_address: 10.42.0.22
@@ -368,7 +389,7 @@ services:
368
389
  NODE_ENV: production
369
390
  EXE_GATEWAY_HOME: /data
370
391
  EXE_GATEWAY_CONFIG: /data/gateway.json
371
- DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}
392
+ DATABASE_URL: postgres://${POSTGRES_USER:-exe}:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}@exe-db:5432/${POSTGRES_DB:-exedb}?sslmode=disable
372
393
  EXE_GATEWAY_PORT: "3100"
373
394
  EXE_GATEWAY_HOST: "0.0.0.0"
374
395
  EXE_GATEWAY_AUTH_TOKEN: ${EXE_GATEWAY_AUTH_TOKEN:?EXE_GATEWAY_AUTH_TOKEN is required}
@@ -381,7 +402,9 @@ services:
381
402
  WHATSAPP_ACCESS_TOKEN: ${WHATSAPP_ACCESS_TOKEN:-}
382
403
  API_ROUTER_URL: ${API_ROUTER_URL:-https://gateway.askexe.com}
383
404
  API_ROUTER_KEY: ${API_ROUTER_KEY:-}
384
- EXED_MCP_URL: http://exe-os:8765/mcp
405
+ EXED_MCP_URL: http://exe-os:48739/mcp
406
+ EXED_MCP_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
407
+ EXE_DAEMON_TOKEN: ${EXED_MCP_TOKEN:?EXED_MCP_TOKEN is required}
385
408
  BYOK_ENABLED: ${BYOK_ENABLED:-false}
386
409
  ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-}
387
410
  EXE_LICENSE_KEY: ${EXE_LICENSE_KEY:?EXE_LICENSE_KEY is required — purchase at https://askexe.com}
@@ -412,7 +435,7 @@ services:
412
435
  container_name: exe-monitor-agent
413
436
  restart: unless-stopped
414
437
  environment:
415
- HUB_URL: ${MONITOR_HUB_URL:-https://monitor.askexe.com}
438
+ HUB_URL: ${MONITOR_HUB_URL:-http://exe-monitor-hub:8090}
416
439
  TOKEN: ${MONITOR_AGENT_TOKEN:?MONITOR_AGENT_TOKEN is required — create Hygo system in monitor.askexe.com}
417
440
  KEY: ${MONITOR_AGENT_KEY:?MONITOR_AGENT_KEY is required — copy public key from monitor.askexe.com}
418
441
  LISTEN: ${MONITOR_AGENT_LISTEN:-:45876}
@@ -443,6 +466,7 @@ services:
443
466
  exe-update:
444
467
  image: ${EXE_OS_IMAGE_TAG:-${EXED_IMAGE_TAG:-ghcr.io/askexe/exe-os:v0.9.157}}
445
468
  container_name: exe-update
469
+ profiles: ["askexe-control-plane"]
446
470
  restart: unless-stopped
447
471
  entrypoint: ["node", "/app/dist/bin/registry-proxy.js"]
448
472
  env_file:
@@ -452,9 +476,9 @@ services:
452
476
  EXE_REGISTRY_PROXY_PORT: "${EXE_REGISTRY_PROXY_PORT:-3200}"
453
477
  EXE_REGISTRY_PROXY_HOST: "${EXE_REGISTRY_PROXY_HOST:-0.0.0.0}"
454
478
  EXE_REGISTRY_PROXY_UPSTREAM: "${EXE_REGISTRY_PROXY_UPSTREAM:-https://ghcr.io}"
455
- EXE_REGISTRY_PROXY_UPSTREAM_USERNAME: "${EXE_REGISTRY_PROXY_UPSTREAM_USERNAME}"
456
- EXE_REGISTRY_PROXY_UPSTREAM_TOKEN: "${EXE_REGISTRY_PROXY_UPSTREAM_TOKEN}"
457
- EXE_REGISTRY_PROXY_PULL_TOKENS: "${EXE_REGISTRY_PROXY_PULL_TOKENS}"
479
+ EXE_REGISTRY_PROXY_UPSTREAM_USERNAME: "${EXE_REGISTRY_PROXY_UPSTREAM_USERNAME:-}"
480
+ EXE_REGISTRY_PROXY_UPSTREAM_TOKEN: "${EXE_REGISTRY_PROXY_UPSTREAM_TOKEN:-}"
481
+ EXE_REGISTRY_PROXY_PULL_TOKENS: "${EXE_REGISTRY_PROXY_PULL_TOKENS:-}"
458
482
  EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE: "${EXE_REGISTRY_PROXY_ALLOWED_NAMESPACE:-askexe}"
459
483
  ports:
460
484
  - "127.0.0.1:${EXE_UPDATE_HOST_PORT:-3200}:${EXE_REGISTRY_PROXY_PORT:-3200}"
@@ -1,11 +1,21 @@
1
1
  {
2
2
  "port": 3100,
3
3
  "host": "0.0.0.0",
4
+ "authToken": "${EXE_GATEWAY_AUTH_TOKEN}",
5
+ "whatsappVerifyToken": "${EXE_GATEWAY_WHATSAPP_VERIFY_TOKEN}",
4
6
  "readOnly": false,
5
7
  "adapters": {
6
8
  "whatsapp": {
7
- "enabled": false,
8
- "accounts": []
9
+ "enabled": true,
10
+ "credentials": {
11
+ "authDir": "/app/auth_info/default"
12
+ },
13
+ "accounts": [
14
+ {
15
+ "name": "default",
16
+ "authDir": "/app/auth_info/default"
17
+ }
18
+ ]
9
19
  }
10
20
  }
11
21
  }
@@ -31,8 +31,10 @@ const LICENSE_KEY_COMMENT = "# injected by deploy_client";
31
31
  const MANUAL_VALUE_COMMENT = "# SET_MANUALLY";
32
32
  const EXAMPLE_LICENSE_KEY = "CHANGEME_EXE_LICENSE_KEY";
33
33
  const DEFAULT_API_ROUTER_URL = "https://gateway.askexe.com";
34
- const DEFAULT_MONITOR_HUB_URL = "https://monitor.askexe.com";
34
+ const DEFAULT_MONITOR_HUB_URL = "http://exe-monitor-hub:8090";
35
35
  const DEFAULT_MONITOR_AGENT_LISTEN = ":45876";
36
+ const DEFAULT_EXE_MCP_HOST_BIND = "0.0.0.0";
37
+ const DEFAULT_EXE_MCP_HOST_PORT = "48739";
36
38
 
37
39
  export interface GenerateEnvOptions {
38
40
  clientName: string;
@@ -59,6 +61,7 @@ export function generateEnv(options: GenerateEnvOptions): string {
59
61
  "",
60
62
  "# --- GoTrue (shared auth) ---",
61
63
  `GOTRUE_JWT_SECRET=${randomSecret(RANDOM_SECRET_48)}`,
64
+ "GOTRUE_API_PORT=9999",
62
65
  `GOTRUE_SITE_URL=https://crm.${normalizedDomain}`,
63
66
  `GOTRUE_EXTERNAL_URL=https://auth.${normalizedDomain}`,
64
67
  "GOTRUE_DISABLE_SIGNUP=false",
@@ -86,6 +89,8 @@ export function generateEnv(options: GenerateEnvOptions): string {
86
89
  `EXE_OS_IMAGE_TAG=${EXE_OS_IMAGE_TAG}`,
87
90
  `EXED_MCP_TOKEN=${randomSecret(RANDOM_SECRET_48)}`,
88
91
  `EXED_DEVICE_ID=vps-${normalizedClientName}`,
92
+ `EXE_MCP_HOST_BIND=${DEFAULT_EXE_MCP_HOST_BIND}`,
93
+ `EXE_MCP_HOST_PORT=${DEFAULT_EXE_MCP_HOST_PORT}`,
89
94
  "# VPS-only: enables cloud/local SQLite -> exe-db Postgres projection.",
90
95
  "EXE_CLOUD_SYNC_TO_POSTGRES=true",
91
96
  "",
@@ -138,6 +143,14 @@ export function generateExampleEnv(): string {
138
143
  "",
139
144
  "REDIS_PASSWORD=CHANGEME_REDIS_PASSWORD",
140
145
  "",
146
+ "# --- GoTrue (shared auth) ---",
147
+ "GOTRUE_JWT_SECRET=CHANGEME_GOTRUE_JWT_SECRET",
148
+ "GOTRUE_API_PORT=9999",
149
+ "GOTRUE_SITE_URL=https://crm.CHANGEME_DOMAIN",
150
+ "GOTRUE_EXTERNAL_URL=https://auth.CHANGEME_DOMAIN",
151
+ "GOTRUE_DISABLE_SIGNUP=false",
152
+ "GOTRUE_MAILER_AUTOCONFIRM=true",
153
+ "",
141
154
  "# --- CRM ---",
142
155
  `CRM_IMAGE_TAG=${CRM_IMAGE_TAG}`,
143
156
  "CRM_SERVER_URL=https://CHANGEME_DOMAIN",
@@ -150,6 +163,7 @@ export function generateExampleEnv(): string {
150
163
  `WIKI_DB_SCHEMA=${WIKI_DB_SCHEMA}`,
151
164
  `WIKI_VECTOR_DB=${WIKI_VECTOR_DB}`,
152
165
  "WIKI_AUTH_TOKEN=CHANGEME_WIKI_AUTH_TOKEN",
166
+ "EXE_WIKI_ADMIN_TOKEN=CHANGEME_EXE_WIKI_ADMIN_TOKEN",
153
167
  "WIKI_JWT_SECRET=CHANGEME_WIKI_JWT_SECRET",
154
168
  "WIKI_SIG_KEY=CHANGEME_WIKI_SIG_KEY",
155
169
  "WIKI_SIG_SALT=CHANGEME_WIKI_SIG_SALT",
@@ -159,6 +173,8 @@ export function generateExampleEnv(): string {
159
173
  `EXE_OS_IMAGE_TAG=${EXE_OS_IMAGE_TAG}`,
160
174
  "EXED_MCP_TOKEN=CHANGEME_EXED_MCP_TOKEN",
161
175
  "EXED_DEVICE_ID=vps-default",
176
+ `EXE_MCP_HOST_BIND=${DEFAULT_EXE_MCP_HOST_BIND}`,
177
+ `EXE_MCP_HOST_PORT=${DEFAULT_EXE_MCP_HOST_PORT}`,
162
178
  "# VPS-only: enables cloud/local SQLite -> exe-db Postgres projection.",
163
179
  "# Keep false on laptops/dev boxes.",
164
180
  "EXE_CLOUD_SYNC_TO_POSTGRES=true",
@@ -15,6 +15,18 @@ DO $$ BEGIN
15
15
  END IF;
16
16
  END $$;
17
17
 
18
+ -- GoTrue upstream migrations grant privileges to role "postgres" even when
19
+ -- this stack's configured superuser is POSTGRES_USER=exe. Existing customer
20
+ -- volumes do not get docker-entrypoint init scripts re-run, so stack-update
21
+ -- applies this file idempotently before restarting GoTrue.
22
+ DO $$ BEGIN
23
+ IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = 'postgres') THEN
24
+ CREATE ROLE postgres WITH SUPERUSER;
25
+ ELSE
26
+ ALTER ROLE postgres SUPERUSER;
27
+ END IF;
28
+ END $$;
29
+
18
30
  -- Create extensions
19
31
  CREATE EXTENSION IF NOT EXISTS vector;
20
32
  CREATE EXTENSION IF NOT EXISTS pgcrypto;
@@ -36,6 +36,7 @@ info "Restoring config files..."
36
36
  [[ -f "$BACKUP_DIR/env.bak" ]] && cp "$BACKUP_DIR/env.bak" "$SCRIPT_DIR/.env" && info ".env restored"
37
37
  [[ -f "$BACKUP_DIR/gateway.json" ]] && cp "$BACKUP_DIR/gateway.json" "$SCRIPT_DIR/gateway.json" && info "gateway.json restored"
38
38
  [[ -f "$BACKUP_DIR/branding.json" ]] && cp "$BACKUP_DIR/branding.json" "$SCRIPT_DIR/branding.json" && info "branding.json restored"
39
+ [[ -f "$BACKUP_DIR/clickhouse-config.xml" ]] && cp "$BACKUP_DIR/clickhouse-config.xml" "$SCRIPT_DIR/clickhouse-config.xml" && info "clickhouse-config.xml restored"
39
40
  [[ -d "$BACKUP_DIR/cloudflared" ]] && cp -r "$BACKUP_DIR/cloudflared" "$SCRIPT_DIR/" && info "cloudflared config restored"
40
41
 
41
42
  # 2. Restore postgres
@@ -88,6 +88,8 @@ WIKI_HOST_PORT=3001
88
88
  EXE_OS_IMAGE_TAG=ghcr.io/askexe/exe-os:v0.9.155
89
89
  EXED_MCP_TOKEN=$(gen 48)
90
90
  EXED_DEVICE_ID=vps-${CLIENT}
91
+ EXE_MCP_HOST_BIND=0.0.0.0
92
+ EXE_MCP_HOST_PORT=48739
91
93
  EXE_CLOUD_SYNC_TO_POSTGRES=true
92
94
  EXE_LICENSE_KEY=${LICENSE:-CHANGEME_EXE_LICENSE_KEY}
93
95
  GATEWAY_IMAGE_TAG=ghcr.io/askexe/exe-gateway:v0.9.3
@@ -100,7 +102,7 @@ GATEWAY_WS_HOST_PORT=3101
100
102
  MONITOR_HUB_IMAGE_TAG=ghcr.io/askexe/exe-monitor-hub:v0.9.4
101
103
  MONITOR_AGENT_IMAGE_TAG=ghcr.io/askexe/exe-monitor-agent:v0.9.4
102
104
  EXE_MONITOR_ADMIN_TOKEN=$(gen 48)
103
- MONITOR_HUB_URL=https://monitor.${DOMAIN}
105
+ MONITOR_HUB_URL=http://exe-monitor-hub:8090
104
106
  MONITOR_AGENT_TOKEN=CHANGEME_MONITOR_AGENT_TOKEN
105
107
  MONITOR_AGENT_KEY=CHANGEME_MONITOR_AGENT_KEY
106
108
  MONITOR_AGENT_LISTEN=:45876
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env bash
2
+ # exe-os uptime check — runs every 5 min via cron.
3
+ # Checks: CRM, Gateway, WhatsApp state, Postgres.
4
+ # Writes JSONL to /opt/exe-stack/uptime.jsonl.
5
+ # Logs ALERT to stderr (captured by cron/syslog) on any failure.
6
+ #
7
+ # Install:
8
+ # chmod +x /opt/exe-stack/uptime-check.sh
9
+ # echo "*/5 * * * * /opt/exe-stack/uptime-check.sh 2>&1 | logger -t exe-uptime" | crontab -
10
+ #
11
+ # Or add to existing crontab:
12
+ # crontab -l | { cat; echo "*/5 * * * * /opt/exe-stack/uptime-check.sh 2>&1 | logger -t exe-uptime"; } | crontab -
13
+
14
+ set -uo pipefail
15
+
16
+ # --- Config ---
17
+ OUTFILE="${EXE_UPTIME_LOG:-/opt/exe-stack/uptime.jsonl}"
18
+ TIMEOUT=5
19
+ MAX_SIZE_MB=50
20
+
21
+ # Ensure output directory exists
22
+ mkdir -p "$(dirname "$OUTFILE")"
23
+
24
+ # --- Helpers ---
25
+ ts() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
26
+
27
+ check_http() {
28
+ local name="$1" url="$2"
29
+ local code
30
+ code=$(curl -sk -o /dev/null -w "%{http_code}" --max-time "$TIMEOUT" "$url" 2>/dev/null || echo "000")
31
+ if [[ "$code" == "200" ]]; then
32
+ echo "ok"
33
+ else
34
+ echo "fail:$code"
35
+ fi
36
+ }
37
+
38
+ check_postgres() {
39
+ local result
40
+ result=$(docker exec exe-db psql -U "${POSTGRES_USER:-exe}" -d "${POSTGRES_DB:-exedb}" \
41
+ -tAc "SELECT 1" 2>/dev/null | tr -d '[:space:]')
42
+ if [[ "$result" == "1" ]]; then
43
+ echo "ok"
44
+ else
45
+ echo "fail"
46
+ fi
47
+ }
48
+
49
+ check_whatsapp() {
50
+ # WhatsApp state is exposed through the gateway health endpoint.
51
+ # The /health endpoint returns JSON with a whatsapp.state field.
52
+ # If the gateway doesn't expose WhatsApp state directly, fall back
53
+ # to checking recent gateway logs for connection state.
54
+ local health_body state
55
+
56
+ # Try gateway health endpoint first (preferred)
57
+ health_body=$(curl -sk --max-time "$TIMEOUT" "http://127.0.0.1:3100/health" 2>/dev/null || echo "")
58
+
59
+ if [[ -n "$health_body" ]]; then
60
+ # Try to extract whatsapp state from JSON response
61
+ state=$(echo "$health_body" | grep -oP '"whatsapp"\s*:\s*\{[^}]*"state"\s*:\s*"([^"]*)"' | grep -oP '"state"\s*:\s*"\K[^"]*' 2>/dev/null || echo "")
62
+
63
+ # Fallback: simpler grep for state field anywhere in response
64
+ if [[ -z "$state" ]]; then
65
+ state=$(echo "$health_body" | grep -oP '"state"\s*:\s*"\K[^"]*' 2>/dev/null || echo "")
66
+ fi
67
+
68
+ if [[ "$state" == "open" || "$state" == "connected" ]]; then
69
+ echo "ok:$state"
70
+ return
71
+ elif [[ -n "$state" ]]; then
72
+ echo "fail:$state"
73
+ return
74
+ fi
75
+ fi
76
+
77
+ # Fallback: check gateway container logs for recent WhatsApp state
78
+ local log_state
79
+ log_state=$(docker logs exe-gateway --tail 50 2>&1 | \
80
+ grep -iP '(whatsapp|baileys|wa).*(state|status|connect)' | \
81
+ tail -1 2>/dev/null || echo "")
82
+
83
+ if echo "$log_state" | grep -qi "open\|connected\|ready"; then
84
+ echo "ok:log-inferred"
85
+ elif [[ -n "$log_state" ]]; then
86
+ echo "fail:log-inferred"
87
+ else
88
+ echo "unknown"
89
+ fi
90
+ }
91
+
92
+ # --- Run checks ---
93
+ NOW=$(ts)
94
+
95
+ crm_status=$(check_http "CRM" "http://127.0.0.1:3000/healthz")
96
+ gateway_status=$(check_http "Gateway" "http://127.0.0.1:3100/health")
97
+ whatsapp_status=$(check_whatsapp)
98
+ postgres_status=$(check_postgres)
99
+
100
+ # --- Determine overall health ---
101
+ overall="ok"
102
+ alerts=""
103
+
104
+ if [[ "$crm_status" != "ok" ]]; then
105
+ overall="degraded"
106
+ alerts="${alerts}CRM($crm_status) "
107
+ fi
108
+ if [[ "$gateway_status" != "ok" ]]; then
109
+ overall="degraded"
110
+ alerts="${alerts}Gateway($gateway_status) "
111
+ fi
112
+ if [[ "$whatsapp_status" != ok* ]]; then
113
+ overall="degraded"
114
+ alerts="${alerts}WhatsApp($whatsapp_status) "
115
+ fi
116
+ if [[ "$postgres_status" != "ok" ]]; then
117
+ overall="critical"
118
+ alerts="${alerts}Postgres($postgres_status) "
119
+ fi
120
+
121
+ # --- Write JSONL ---
122
+ # Single-line JSON — no jq dependency required
123
+ ENTRY="{\"ts\":\"${NOW}\",\"overall\":\"${overall}\",\"crm\":\"${crm_status}\",\"gateway\":\"${gateway_status}\",\"whatsapp\":\"${whatsapp_status}\",\"postgres\":\"${postgres_status}\"}"
124
+
125
+ echo "$ENTRY" >> "$OUTFILE"
126
+
127
+ # --- Log ALERT on failure ---
128
+ if [[ "$overall" != "ok" ]]; then
129
+ echo "ALERT [${NOW}] exe-os uptime: ${overall} — ${alerts}" >&2
130
+ fi
131
+
132
+ # --- Rotate if too large ---
133
+ FILE_SIZE_KB=$(du -k "$OUTFILE" 2>/dev/null | cut -f1 || echo "0")
134
+ MAX_SIZE_KB=$((MAX_SIZE_MB * 1024))
135
+
136
+ if [[ "$FILE_SIZE_KB" -gt "$MAX_SIZE_KB" ]]; then
137
+ # Keep last 10000 lines, archive the rest
138
+ ARCHIVE="${OUTFILE}.$(date +%Y%m%d%H%M%S).gz"
139
+ head -n -10000 "$OUTFILE" | gzip > "$ARCHIVE"
140
+ tail -n 10000 "$OUTFILE" > "${OUTFILE}.tmp"
141
+ mv "${OUTFILE}.tmp" "$OUTFILE"
142
+ echo "ROTATE [${NOW}] Archived to ${ARCHIVE}" >&2
143
+ fi
@@ -6,10 +6,10 @@ import {
6
6
  getAllActiveAgents,
7
7
  resolveActiveAgentFromTmuxSession,
8
8
  writeActiveAgent
9
- } from "./chunk-S4I3UITZ.js";
9
+ } from "./chunk-EFDIUJWC.js";
10
10
  import "./chunk-CVYC6DUW.js";
11
11
  import "./chunk-GJV3WDWM.js";
12
- import "./chunk-4GXXYDNU.js";
12
+ import "./chunk-A77WVNU2.js";
13
13
  import "./chunk-OSYUNKBM.js";
14
14
  import "./chunk-FXU7JOXK.js";
15
15
  import "./chunk-WXW3XGWX.js";
@@ -5,10 +5,10 @@ import {
5
5
  getAllActiveAgents,
6
6
  resolveActiveAgentFromTmuxSession,
7
7
  writeActiveAgent
8
- } from "./chunk-S4I3UITZ.js";
8
+ } from "./chunk-EFDIUJWC.js";
9
9
  import "./chunk-CVYC6DUW.js";
10
10
  import "./chunk-GJV3WDWM.js";
11
- import "./chunk-4GXXYDNU.js";
11
+ import "./chunk-A77WVNU2.js";
12
12
  import "./chunk-OSYUNKBM.js";
13
13
  import "./chunk-FXU7JOXK.js";
14
14
  import "./chunk-WXW3XGWX.js";
@@ -9,7 +9,7 @@ import {
9
9
  insertOntologyForMemory,
10
10
  ontologyPayload,
11
11
  stableId
12
- } from "./chunk-54JMB5UI.js";
12
+ } from "./chunk-I7K6NY34.js";
13
13
  import "./chunk-MLKGABMK.js";
14
14
  export {
15
15
  clean,