@jungjaehoon/mama-os 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +643 -0
  3. package/dist/agent/agent-loop.d.ts +98 -0
  4. package/dist/agent/agent-loop.d.ts.map +1 -0
  5. package/dist/agent/agent-loop.js +417 -0
  6. package/dist/agent/agent-loop.js.map +1 -0
  7. package/dist/agent/auto-recall.d.ts +48 -0
  8. package/dist/agent/auto-recall.d.ts.map +1 -0
  9. package/dist/agent/auto-recall.js +178 -0
  10. package/dist/agent/auto-recall.js.map +1 -0
  11. package/dist/agent/claude-cli-wrapper.d.ts +130 -0
  12. package/dist/agent/claude-cli-wrapper.d.ts.map +1 -0
  13. package/dist/agent/claude-cli-wrapper.js +227 -0
  14. package/dist/agent/claude-cli-wrapper.js.map +1 -0
  15. package/dist/agent/claude-client.d.ts +50 -0
  16. package/dist/agent/claude-client.d.ts.map +1 -0
  17. package/dist/agent/claude-client.js +214 -0
  18. package/dist/agent/claude-client.js.map +1 -0
  19. package/dist/agent/gateway-tool-executor.d.ts +75 -0
  20. package/dist/agent/gateway-tool-executor.d.ts.map +1 -0
  21. package/dist/agent/gateway-tool-executor.js +348 -0
  22. package/dist/agent/gateway-tool-executor.js.map +1 -0
  23. package/dist/agent/index.d.ts +13 -0
  24. package/dist/agent/index.d.ts.map +1 -0
  25. package/dist/agent/index.js +18 -0
  26. package/dist/agent/index.js.map +1 -0
  27. package/dist/agent/mcp-executor.d.ts +75 -0
  28. package/dist/agent/mcp-executor.d.ts.map +1 -0
  29. package/dist/agent/mcp-executor.js +307 -0
  30. package/dist/agent/mcp-executor.js.map +1 -0
  31. package/dist/agent/session-pool.d.ts +148 -0
  32. package/dist/agent/session-pool.d.ts.map +1 -0
  33. package/dist/agent/session-pool.js +272 -0
  34. package/dist/agent/session-pool.js.map +1 -0
  35. package/dist/agent/streaming-callback-manager.d.ts +85 -0
  36. package/dist/agent/streaming-callback-manager.d.ts.map +1 -0
  37. package/dist/agent/streaming-callback-manager.js +103 -0
  38. package/dist/agent/streaming-callback-manager.js.map +1 -0
  39. package/dist/agent/types.d.ts +437 -0
  40. package/dist/agent/types.d.ts.map +1 -0
  41. package/dist/agent/types.js +29 -0
  42. package/dist/agent/types.js.map +1 -0
  43. package/dist/api/cron-handler.d.ts +44 -0
  44. package/dist/api/cron-handler.d.ts.map +1 -0
  45. package/dist/api/cron-handler.js +195 -0
  46. package/dist/api/cron-handler.js.map +1 -0
  47. package/dist/api/error-handler.d.ts +22 -0
  48. package/dist/api/error-handler.d.ts.map +1 -0
  49. package/dist/api/error-handler.js +104 -0
  50. package/dist/api/error-handler.js.map +1 -0
  51. package/dist/api/heartbeat-handler.d.ts +49 -0
  52. package/dist/api/heartbeat-handler.d.ts.map +1 -0
  53. package/dist/api/heartbeat-handler.js +91 -0
  54. package/dist/api/heartbeat-handler.js.map +1 -0
  55. package/dist/api/index.d.ts +61 -0
  56. package/dist/api/index.d.ts.map +1 -0
  57. package/dist/api/index.js +145 -0
  58. package/dist/api/index.js.map +1 -0
  59. package/dist/api/types.d.ts +156 -0
  60. package/dist/api/types.d.ts.map +1 -0
  61. package/dist/api/types.js +62 -0
  62. package/dist/api/types.js.map +1 -0
  63. package/dist/auth/index.d.ts +7 -0
  64. package/dist/auth/index.d.ts.map +1 -0
  65. package/dist/auth/index.js +11 -0
  66. package/dist/auth/index.js.map +1 -0
  67. package/dist/auth/oauth-manager.d.ts +59 -0
  68. package/dist/auth/oauth-manager.d.ts.map +1 -0
  69. package/dist/auth/oauth-manager.js +237 -0
  70. package/dist/auth/oauth-manager.js.map +1 -0
  71. package/dist/auth/types.d.ts +92 -0
  72. package/dist/auth/types.d.ts.map +1 -0
  73. package/dist/auth/types.js +23 -0
  74. package/dist/auth/types.js.map +1 -0
  75. package/dist/cli/commands/init.d.ts +19 -0
  76. package/dist/cli/commands/init.d.ts.map +1 -0
  77. package/dist/cli/commands/init.js +155 -0
  78. package/dist/cli/commands/init.js.map +1 -0
  79. package/dist/cli/commands/run.d.ts +19 -0
  80. package/dist/cli/commands/run.d.ts.map +1 -0
  81. package/dist/cli/commands/run.js +89 -0
  82. package/dist/cli/commands/run.js.map +1 -0
  83. package/dist/cli/commands/setup.d.ts +19 -0
  84. package/dist/cli/commands/setup.d.ts.map +1 -0
  85. package/dist/cli/commands/setup.js +134 -0
  86. package/dist/cli/commands/setup.js.map +1 -0
  87. package/dist/cli/commands/start.d.ts +24 -0
  88. package/dist/cli/commands/start.d.ts.map +1 -0
  89. package/dist/cli/commands/start.js +1073 -0
  90. package/dist/cli/commands/start.js.map +1 -0
  91. package/dist/cli/commands/status.d.ts +10 -0
  92. package/dist/cli/commands/status.d.ts.map +1 -0
  93. package/dist/cli/commands/status.js +85 -0
  94. package/dist/cli/commands/status.js.map +1 -0
  95. package/dist/cli/commands/stop.d.ts +10 -0
  96. package/dist/cli/commands/stop.d.ts.map +1 -0
  97. package/dist/cli/commands/stop.js +65 -0
  98. package/dist/cli/commands/stop.js.map +1 -0
  99. package/dist/cli/config/config-manager.d.ts +51 -0
  100. package/dist/cli/config/config-manager.d.ts.map +1 -0
  101. package/dist/cli/config/config-manager.js +216 -0
  102. package/dist/cli/config/config-manager.js.map +1 -0
  103. package/dist/cli/config/types.d.ts +172 -0
  104. package/dist/cli/config/types.d.ts.map +1 -0
  105. package/dist/cli/config/types.js +48 -0
  106. package/dist/cli/config/types.js.map +1 -0
  107. package/dist/cli/index.d.ts +8 -0
  108. package/dist/cli/index.d.ts.map +1 -0
  109. package/dist/cli/index.js +92 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/utils/pid-manager.d.ts +66 -0
  112. package/dist/cli/utils/pid-manager.d.ts.map +1 -0
  113. package/dist/cli/utils/pid-manager.js +167 -0
  114. package/dist/cli/utils/pid-manager.js.map +1 -0
  115. package/dist/concurrency/index.d.ts +13 -0
  116. package/dist/concurrency/index.d.ts.map +1 -0
  117. package/dist/concurrency/index.js +22 -0
  118. package/dist/concurrency/index.js.map +1 -0
  119. package/dist/concurrency/lane-manager.d.ts +113 -0
  120. package/dist/concurrency/lane-manager.d.ts.map +1 -0
  121. package/dist/concurrency/lane-manager.js +245 -0
  122. package/dist/concurrency/lane-manager.js.map +1 -0
  123. package/dist/concurrency/session-key.d.ts +41 -0
  124. package/dist/concurrency/session-key.d.ts.map +1 -0
  125. package/dist/concurrency/session-key.js +61 -0
  126. package/dist/concurrency/session-key.js.map +1 -0
  127. package/dist/concurrency/types.d.ts +69 -0
  128. package/dist/concurrency/types.d.ts.map +1 -0
  129. package/dist/concurrency/types.js +16 -0
  130. package/dist/concurrency/types.js.map +1 -0
  131. package/dist/gateways/channel-history.d.ts +102 -0
  132. package/dist/gateways/channel-history.d.ts.map +1 -0
  133. package/dist/gateways/channel-history.js +181 -0
  134. package/dist/gateways/channel-history.js.map +1 -0
  135. package/dist/gateways/context-injector.d.ts +74 -0
  136. package/dist/gateways/context-injector.d.ts.map +1 -0
  137. package/dist/gateways/context-injector.js +121 -0
  138. package/dist/gateways/context-injector.js.map +1 -0
  139. package/dist/gateways/discord.d.ts +122 -0
  140. package/dist/gateways/discord.d.ts.map +1 -0
  141. package/dist/gateways/discord.js +602 -0
  142. package/dist/gateways/discord.js.map +1 -0
  143. package/dist/gateways/index.d.ts +30 -0
  144. package/dist/gateways/index.d.ts.map +1 -0
  145. package/dist/gateways/index.js +49 -0
  146. package/dist/gateways/index.js.map +1 -0
  147. package/dist/gateways/message-router.d.ts +116 -0
  148. package/dist/gateways/message-router.d.ts.map +1 -0
  149. package/dist/gateways/message-router.js +315 -0
  150. package/dist/gateways/message-router.js.map +1 -0
  151. package/dist/gateways/message-splitter.d.ts +54 -0
  152. package/dist/gateways/message-splitter.d.ts.map +1 -0
  153. package/dist/gateways/message-splitter.js +146 -0
  154. package/dist/gateways/message-splitter.js.map +1 -0
  155. package/dist/gateways/plugin-loader.d.ts +76 -0
  156. package/dist/gateways/plugin-loader.d.ts.map +1 -0
  157. package/dist/gateways/plugin-loader.js +221 -0
  158. package/dist/gateways/plugin-loader.js.map +1 -0
  159. package/dist/gateways/session-store.d.ts +77 -0
  160. package/dist/gateways/session-store.d.ts.map +1 -0
  161. package/dist/gateways/session-store.js +233 -0
  162. package/dist/gateways/session-store.js.map +1 -0
  163. package/dist/gateways/slack.d.ts +90 -0
  164. package/dist/gateways/slack.d.ts.map +1 -0
  165. package/dist/gateways/slack.js +281 -0
  166. package/dist/gateways/slack.js.map +1 -0
  167. package/dist/gateways/telegram.d.ts +79 -0
  168. package/dist/gateways/telegram.d.ts.map +1 -0
  169. package/dist/gateways/telegram.js +207 -0
  170. package/dist/gateways/telegram.js.map +1 -0
  171. package/dist/gateways/types.d.ts +340 -0
  172. package/dist/gateways/types.d.ts.map +1 -0
  173. package/dist/gateways/types.js +6 -0
  174. package/dist/gateways/types.js.map +1 -0
  175. package/dist/index.d.ts +7 -0
  176. package/dist/index.d.ts.map +1 -0
  177. package/dist/index.js +26 -0
  178. package/dist/index.js.map +1 -0
  179. package/dist/memory/memory-logger.d.ts +47 -0
  180. package/dist/memory/memory-logger.d.ts.map +1 -0
  181. package/dist/memory/memory-logger.js +126 -0
  182. package/dist/memory/memory-logger.js.map +1 -0
  183. package/dist/onboarding/all-tools.d.ts +18 -0
  184. package/dist/onboarding/all-tools.d.ts.map +1 -0
  185. package/dist/onboarding/all-tools.js +149 -0
  186. package/dist/onboarding/all-tools.js.map +1 -0
  187. package/dist/onboarding/autonomous-discovery-tools.d.ts +13 -0
  188. package/dist/onboarding/autonomous-discovery-tools.d.ts.map +1 -0
  189. package/dist/onboarding/autonomous-discovery-tools.js +268 -0
  190. package/dist/onboarding/autonomous-discovery-tools.js.map +1 -0
  191. package/dist/onboarding/bootstrap-template.d.ts +5 -0
  192. package/dist/onboarding/bootstrap-template.d.ts.map +1 -0
  193. package/dist/onboarding/bootstrap-template.js +142 -0
  194. package/dist/onboarding/bootstrap-template.js.map +1 -0
  195. package/dist/onboarding/complete-autonomous-prompt.d.ts +13 -0
  196. package/dist/onboarding/complete-autonomous-prompt.d.ts.map +1 -0
  197. package/dist/onboarding/complete-autonomous-prompt.js +1220 -0
  198. package/dist/onboarding/complete-autonomous-prompt.js.map +1 -0
  199. package/dist/onboarding/onboarding-state.d.ts +70 -0
  200. package/dist/onboarding/onboarding-state.d.ts.map +1 -0
  201. package/dist/onboarding/onboarding-state.js +184 -0
  202. package/dist/onboarding/onboarding-state.js.map +1 -0
  203. package/dist/onboarding/personality-quiz.d.ts +35 -0
  204. package/dist/onboarding/personality-quiz.d.ts.map +1 -0
  205. package/dist/onboarding/personality-quiz.js +219 -0
  206. package/dist/onboarding/personality-quiz.js.map +1 -0
  207. package/dist/onboarding/phase-5-summary.d.ts +22 -0
  208. package/dist/onboarding/phase-5-summary.d.ts.map +1 -0
  209. package/dist/onboarding/phase-5-summary.js +151 -0
  210. package/dist/onboarding/phase-5-summary.js.map +1 -0
  211. package/dist/onboarding/phase-6-security.d.ts +33 -0
  212. package/dist/onboarding/phase-6-security.d.ts.map +1 -0
  213. package/dist/onboarding/phase-6-security.js +473 -0
  214. package/dist/onboarding/phase-6-security.js.map +1 -0
  215. package/dist/onboarding/phase-7-integrations.d.ts +66 -0
  216. package/dist/onboarding/phase-7-integrations.d.ts.map +1 -0
  217. package/dist/onboarding/phase-7-integrations.js +619 -0
  218. package/dist/onboarding/phase-7-integrations.js.map +1 -0
  219. package/dist/onboarding/phase-8-demo.d.ts +43 -0
  220. package/dist/onboarding/phase-8-demo.d.ts.map +1 -0
  221. package/dist/onboarding/phase-8-demo.js +346 -0
  222. package/dist/onboarding/phase-8-demo.js.map +1 -0
  223. package/dist/onboarding/phase-9-finalization.d.ts +22 -0
  224. package/dist/onboarding/phase-9-finalization.d.ts.map +1 -0
  225. package/dist/onboarding/phase-9-finalization.js +375 -0
  226. package/dist/onboarding/phase-9-finalization.js.map +1 -0
  227. package/dist/onboarding/ritual-prompt.d.ts +2 -0
  228. package/dist/onboarding/ritual-prompt.d.ts.map +1 -0
  229. package/dist/onboarding/ritual-prompt.js +285 -0
  230. package/dist/onboarding/ritual-prompt.js.map +1 -0
  231. package/dist/onboarding/ritual-tools.d.ts +13 -0
  232. package/dist/onboarding/ritual-tools.d.ts.map +1 -0
  233. package/dist/onboarding/ritual-tools.js +93 -0
  234. package/dist/onboarding/ritual-tools.js.map +1 -0
  235. package/dist/runners/cli-runner.d.ts +59 -0
  236. package/dist/runners/cli-runner.d.ts.map +1 -0
  237. package/dist/runners/cli-runner.js +190 -0
  238. package/dist/runners/cli-runner.js.map +1 -0
  239. package/dist/runners/index.d.ts +11 -0
  240. package/dist/runners/index.d.ts.map +1 -0
  241. package/dist/runners/index.js +15 -0
  242. package/dist/runners/index.js.map +1 -0
  243. package/dist/runners/types.d.ts +81 -0
  244. package/dist/runners/types.d.ts.map +1 -0
  245. package/dist/runners/types.js +31 -0
  246. package/dist/runners/types.js.map +1 -0
  247. package/dist/scheduler/cron-scheduler.d.ts +115 -0
  248. package/dist/scheduler/cron-scheduler.d.ts.map +1 -0
  249. package/dist/scheduler/cron-scheduler.js +320 -0
  250. package/dist/scheduler/cron-scheduler.js.map +1 -0
  251. package/dist/scheduler/heartbeat.d.ts +53 -0
  252. package/dist/scheduler/heartbeat.d.ts.map +1 -0
  253. package/dist/scheduler/heartbeat.js +160 -0
  254. package/dist/scheduler/heartbeat.js.map +1 -0
  255. package/dist/scheduler/index.d.ts +22 -0
  256. package/dist/scheduler/index.d.ts.map +1 -0
  257. package/dist/scheduler/index.js +31 -0
  258. package/dist/scheduler/index.js.map +1 -0
  259. package/dist/scheduler/job-lock.d.ts +85 -0
  260. package/dist/scheduler/job-lock.d.ts.map +1 -0
  261. package/dist/scheduler/job-lock.js +137 -0
  262. package/dist/scheduler/job-lock.js.map +1 -0
  263. package/dist/scheduler/recovery.d.ts +78 -0
  264. package/dist/scheduler/recovery.d.ts.map +1 -0
  265. package/dist/scheduler/recovery.js +124 -0
  266. package/dist/scheduler/recovery.js.map +1 -0
  267. package/dist/scheduler/schedule-store.d.ts +112 -0
  268. package/dist/scheduler/schedule-store.d.ts.map +1 -0
  269. package/dist/scheduler/schedule-store.js +259 -0
  270. package/dist/scheduler/schedule-store.js.map +1 -0
  271. package/dist/scheduler/token-keep-alive.d.ts +49 -0
  272. package/dist/scheduler/token-keep-alive.d.ts.map +1 -0
  273. package/dist/scheduler/token-keep-alive.js +102 -0
  274. package/dist/scheduler/token-keep-alive.js.map +1 -0
  275. package/dist/scheduler/types.d.ts +96 -0
  276. package/dist/scheduler/types.d.ts.map +1 -0
  277. package/dist/scheduler/types.js +21 -0
  278. package/dist/scheduler/types.js.map +1 -0
  279. package/dist/setup/setup-prompt.d.ts +2 -0
  280. package/dist/setup/setup-prompt.d.ts.map +1 -0
  281. package/dist/setup/setup-prompt.js +138 -0
  282. package/dist/setup/setup-prompt.js.map +1 -0
  283. package/dist/setup/setup-server.d.ts +8 -0
  284. package/dist/setup/setup-server.d.ts.map +1 -0
  285. package/dist/setup/setup-server.js +71 -0
  286. package/dist/setup/setup-server.js.map +1 -0
  287. package/dist/setup/setup-tools.d.ts +13 -0
  288. package/dist/setup/setup-tools.d.ts.map +1 -0
  289. package/dist/setup/setup-tools.js +103 -0
  290. package/dist/setup/setup-tools.js.map +1 -0
  291. package/dist/setup/setup-websocket.d.ts +6 -0
  292. package/dist/setup/setup-websocket.d.ts.map +1 -0
  293. package/dist/setup/setup-websocket.js +312 -0
  294. package/dist/setup/setup-websocket.js.map +1 -0
  295. package/dist/skills/index.d.ts +10 -0
  296. package/dist/skills/index.d.ts.map +1 -0
  297. package/dist/skills/index.js +26 -0
  298. package/dist/skills/index.js.map +1 -0
  299. package/dist/skills/skill-executor.d.ts +48 -0
  300. package/dist/skills/skill-executor.d.ts.map +1 -0
  301. package/dist/skills/skill-executor.js +483 -0
  302. package/dist/skills/skill-executor.js.map +1 -0
  303. package/dist/skills/skill-loader.d.ts +40 -0
  304. package/dist/skills/skill-loader.d.ts.map +1 -0
  305. package/dist/skills/skill-loader.js +225 -0
  306. package/dist/skills/skill-loader.js.map +1 -0
  307. package/dist/skills/skill-matcher.d.ts +33 -0
  308. package/dist/skills/skill-matcher.d.ts.map +1 -0
  309. package/dist/skills/skill-matcher.js +190 -0
  310. package/dist/skills/skill-matcher.js.map +1 -0
  311. package/dist/skills/types.d.ts +123 -0
  312. package/dist/skills/types.d.ts.map +1 -0
  313. package/dist/skills/types.js +12 -0
  314. package/dist/skills/types.js.map +1 -0
  315. package/dist/tools/browser-tool.d.ts +149 -0
  316. package/dist/tools/browser-tool.d.ts.map +1 -0
  317. package/dist/tools/browser-tool.js +257 -0
  318. package/dist/tools/browser-tool.js.map +1 -0
  319. package/package.json +84 -0
  320. package/public/favicon.ico +0 -0
  321. package/public/setup.html +1026 -0
  322. package/public/viewer/icons/icon-192.png +0 -0
  323. package/public/viewer/icons/icon-512.png +0 -0
  324. package/public/viewer/js/modules/chat.js +1587 -0
  325. package/public/viewer/js/modules/dashboard.js +275 -0
  326. package/public/viewer/js/modules/graph.js +997 -0
  327. package/public/viewer/js/modules/memory.js +353 -0
  328. package/public/viewer/js/modules/settings.js +255 -0
  329. package/public/viewer/js/utils/api.js +169 -0
  330. package/public/viewer/js/utils/dom.js +92 -0
  331. package/public/viewer/js/utils/format.js +192 -0
  332. package/public/viewer/manifest.json +26 -0
  333. package/public/viewer/sw.js +131 -0
  334. package/public/viewer/viewer.css +500 -0
  335. package/public/viewer/viewer.html +1535 -0
  336. package/scripts/postinstall.js +118 -0
  337. package/templates/skills/document-analyze.md +63 -0
  338. package/templates/skills/heartbeat-report.md +75 -0
  339. package/templates/skills/image-translate.md +67 -0
  340. package/templates/workspace/skill-forge/DESIGN.md +115 -0
  341. package/templates/workspace/skill-forge/agents/architect.ts +295 -0
  342. package/templates/workspace/skill-forge/agents/developer.ts +364 -0
  343. package/templates/workspace/skill-forge/agents/qa.ts +313 -0
  344. package/templates/workspace/skill-forge/claude-api.ts +353 -0
  345. package/templates/workspace/skill-forge/discord-ui.ts +580 -0
  346. package/templates/workspace/skill-forge/error-handler.ts +354 -0
  347. package/templates/workspace/skill-forge/mama-integration.ts +357 -0
  348. package/templates/workspace/skill-forge/orchestrator.ts +495 -0
  349. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/README.md +24 -0
  350. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/index.ts +79 -0
  351. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/types.ts +17 -0
  352. package/templates/workspace/skill-forge/package.json +21 -0
  353. package/templates/workspace/skill-forge/state/session.json +132 -0
  354. package/templates/workspace/skill-forge/test-e2e.ts +139 -0
  355. package/templates/workspace/skill-forge/tsconfig.json +20 -0
  356. package/templates/workspace/skill-forge/types.ts +159 -0
@@ -0,0 +1,1073 @@
1
+ "use strict";
2
+ /**
3
+ * mama start command
4
+ *
5
+ * Start MAMA agent daemon
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ var __importDefault = (this && this.__importDefault) || function (mod) {
41
+ return (mod && mod.__esModule) ? mod : { "default": mod };
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.startCommand = startCommand;
45
+ exports.runAgentLoop = runAgentLoop;
46
+ const node_child_process_1 = require("node:child_process");
47
+ const node_fs_1 = require("node:fs");
48
+ const node_os_1 = require("node:os");
49
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
50
+ const express_1 = __importDefault(require("express"));
51
+ const node_path_1 = __importStar(require("node:path"));
52
+ const ws_1 = require("ws");
53
+ const config_manager_js_1 = require("../config/config-manager.js");
54
+ const pid_manager_js_1 = require("../utils/pid-manager.js");
55
+ const index_js_1 = require("../../auth/index.js");
56
+ const index_js_2 = require("../../agent/index.js");
57
+ const gateway_tool_executor_js_1 = require("../../agent/gateway-tool-executor.js");
58
+ const index_js_3 = require("../../gateways/index.js");
59
+ const index_js_4 = require("../../scheduler/index.js");
60
+ const heartbeat_js_1 = require("../../scheduler/heartbeat.js");
61
+ const index_js_5 = require("../../api/index.js");
62
+ const setup_websocket_js_1 = require("../../setup/setup-websocket.js");
63
+ const onboarding_state_js_1 = require("../../onboarding/onboarding-state.js");
64
+ const { createGraphHandler } = require('../../api/graph-api.js');
65
+ const node_http_1 = __importDefault(require("node:http"));
66
+ // MAMA embedding server (keeps model in memory)
67
+ let embeddingServer = null;
68
+ /**
69
+ * SECURITY P1: Wait for port to become available after shutdown
70
+ * Polls port availability instead of using fixed setTimeout
71
+ */
72
+ async function waitForPortAvailable(port, maxWaitMs = 5000) {
73
+ const startTime = Date.now();
74
+ const pollInterval = 100;
75
+ while (Date.now() - startTime < maxWaitMs) {
76
+ const isAvailable = await new Promise((resolve) => {
77
+ const testServer = node_http_1.default.createServer();
78
+ testServer.once('error', (err) => {
79
+ if (err.code === 'EADDRINUSE') {
80
+ resolve(false);
81
+ }
82
+ else {
83
+ resolve(true);
84
+ }
85
+ });
86
+ testServer.once('listening', () => {
87
+ testServer.close(() => resolve(true));
88
+ });
89
+ testServer.listen(port, '127.0.0.1');
90
+ });
91
+ if (isAvailable)
92
+ return true;
93
+ await new Promise((r) => setTimeout(r, pollInterval));
94
+ }
95
+ return false;
96
+ }
97
+ /**
98
+ * Check existing embedding server and request takeover if needed
99
+ * Returns true if existing server has chat capability (no takeover needed)
100
+ *
101
+ * SECURITY P1: Uses authenticated shutdown with token
102
+ * SECURITY P1: Validates health response before reuse
103
+ * SECURITY P1: Uses port polling instead of fixed timeout
104
+ */
105
+ async function checkAndTakeoverExistingServer(port) {
106
+ return new Promise((resolve) => {
107
+ const req = node_http_1.default.request({
108
+ hostname: '127.0.0.1',
109
+ port,
110
+ path: '/health',
111
+ method: 'GET',
112
+ timeout: 1000,
113
+ }, (res) => {
114
+ let data = '';
115
+ res.on('data', (chunk) => (data += chunk));
116
+ res.on('end', async () => {
117
+ try {
118
+ const health = JSON.parse(data);
119
+ // SECURITY P1: Validate health response before reuse
120
+ if (health.chatEnabled && health.status === 'ok' && health.modelLoaded) {
121
+ // Fully functional server, reuse it
122
+ console.log('✓ Fully functional embedding server (reusing)');
123
+ resolve(true);
124
+ }
125
+ else if (health.status === 'ok') {
126
+ // Server healthy but incomplete features
127
+ if (!health.modelLoaded) {
128
+ console.warn('[EmbeddingServer] Warning: Model not loaded');
129
+ }
130
+ // MCP server running without chat, request shutdown
131
+ console.log('[EmbeddingServer] MCP server detected, requesting takeover...');
132
+ const shutdownReq = node_http_1.default.request({
133
+ hostname: '127.0.0.1',
134
+ port,
135
+ path: '/shutdown',
136
+ method: 'POST',
137
+ timeout: 2000,
138
+ // SECURITY P1: Pass shutdown token
139
+ headers: {
140
+ 'X-Shutdown-Token': process.env.MAMA_SHUTDOWN_TOKEN || '',
141
+ },
142
+ }, async () => {
143
+ console.log('[EmbeddingServer] MCP server shutdown requested');
144
+ // SECURITY P1: Use port polling instead of fixed timeout
145
+ const portAvailable = await waitForPortAvailable(port, 5000);
146
+ if (portAvailable) {
147
+ console.log('[EmbeddingServer] Port available, proceeding');
148
+ }
149
+ else {
150
+ console.warn('[EmbeddingServer] Port still in use after 5s, proceeding anyway');
151
+ }
152
+ resolve(false);
153
+ });
154
+ shutdownReq.on('error', () => resolve(false));
155
+ shutdownReq.end();
156
+ }
157
+ else {
158
+ // Server unhealthy
159
+ console.warn('[EmbeddingServer] Server unhealthy, starting fresh');
160
+ resolve(false);
161
+ }
162
+ }
163
+ catch {
164
+ resolve(false);
165
+ }
166
+ });
167
+ });
168
+ req.on('error', () => resolve(false));
169
+ req.on('timeout', () => {
170
+ req.destroy();
171
+ resolve(false);
172
+ });
173
+ req.end();
174
+ });
175
+ }
176
+ async function startEmbeddingServerIfAvailable(messageRouter, sessionStore, graphHandler) {
177
+ const port = 3847;
178
+ try {
179
+ // Check if server already running
180
+ const existingHasChat = await checkAndTakeoverExistingServer(port);
181
+ if (existingHasChat) {
182
+ // Another Standalone is running with chat, no need to start
183
+ return;
184
+ }
185
+ const embeddingServerModule = require('@jungjaehoon/mama-core/embedding-server');
186
+ embeddingServer = await embeddingServerModule.startEmbeddingServer(port, {
187
+ messageRouter,
188
+ sessionStore,
189
+ graphHandler,
190
+ });
191
+ if (embeddingServer) {
192
+ console.log('✓ Embedding server started (port 3847)');
193
+ if (messageRouter && sessionStore) {
194
+ console.log('✓ Mobile Chat integrated with MessageRouter');
195
+ }
196
+ await embeddingServerModule.warmModel();
197
+ console.log('✓ Embedding model preloaded');
198
+ }
199
+ }
200
+ catch (err) {
201
+ console.warn('[EmbeddingServer] Failed to start (optional):', err.message);
202
+ }
203
+ }
204
+ /**
205
+ * Open URL in default browser (cross-platform)
206
+ */
207
+ function openBrowser(url) {
208
+ const os = (0, node_os_1.platform)();
209
+ let command;
210
+ switch (os) {
211
+ case 'darwin':
212
+ command = `open "${url}"`;
213
+ break;
214
+ case 'win32':
215
+ command = `start "" "${url}"`;
216
+ break;
217
+ default:
218
+ command = `xdg-open "${url}"`;
219
+ }
220
+ (0, node_child_process_1.exec)(command, (error) => {
221
+ if (error) {
222
+ console.warn(`[Browser] Failed to open: ${error.message}`);
223
+ console.log(`\n🌐 Open MAMA OS manually: ${url}\n`);
224
+ }
225
+ });
226
+ }
227
+ /**
228
+ * Check if onboarding is complete (persona files exist)
229
+ */
230
+ function isOnboardingComplete() {
231
+ const mamaHome = (0, node_path_1.join)((0, node_os_1.homedir)(), '.mama');
232
+ return (0, node_fs_1.existsSync)((0, node_path_1.join)(mamaHome, 'USER.md')) && (0, node_fs_1.existsSync)((0, node_path_1.join)(mamaHome, 'SOUL.md'));
233
+ }
234
+ /**
235
+ * Execute start command
236
+ */
237
+ async function startCommand(options = {}) {
238
+ console.log('\n🚀 Starting MAMA Standalone\n');
239
+ // Check if already running
240
+ const runningInfo = await (0, pid_manager_js_1.isDaemonRunning)();
241
+ if (runningInfo) {
242
+ console.log(`⚠️ MAMA is already running. (PID: ${runningInfo.pid})`);
243
+ console.log(' To stop it: mama stop\n');
244
+ process.exit(1);
245
+ }
246
+ // Check config exists
247
+ if (!(0, config_manager_js_1.configExists)()) {
248
+ console.log('⚠️ Config file not found.');
249
+ console.log(' Initialize first: mama init\n');
250
+ process.exit(1);
251
+ }
252
+ // Load config
253
+ let config;
254
+ try {
255
+ config = await (0, config_manager_js_1.loadConfig)();
256
+ }
257
+ catch (error) {
258
+ console.error(`Failed to load config: ${error instanceof Error ? error.message : String(error)}\n`);
259
+ process.exit(1);
260
+ }
261
+ if (!config.use_claude_cli) {
262
+ process.stdout.write('Checking OAuth token... ');
263
+ try {
264
+ const oauthManager = new index_js_1.OAuthManager();
265
+ await oauthManager.getToken();
266
+ console.log('✓');
267
+ }
268
+ catch (error) {
269
+ console.log('❌');
270
+ console.error(`\nOAuth token error: ${error instanceof Error ? error.message : String(error)}`);
271
+ console.error('Please log in again to Claude Code.\n');
272
+ process.exit(1);
273
+ }
274
+ }
275
+ else {
276
+ console.log('✓ Claude CLI mode (OAuth token not needed)');
277
+ }
278
+ if (options.foreground) {
279
+ // Run in foreground
280
+ console.log('Starting agent loop (foreground)... ✓\n');
281
+ console.log('MAMA is running in foreground.');
282
+ console.log('Press Ctrl+C to stop.\n');
283
+ // Auto-open browser (after a delay for server to start)
284
+ const needsOnboarding = !isOnboardingComplete();
285
+ const targetUrl = needsOnboarding
286
+ ? 'http://localhost:3847/setup'
287
+ : 'http://localhost:3847/viewer';
288
+ setTimeout(() => {
289
+ if (needsOnboarding) {
290
+ console.log('🎭 First-time setup - Opening onboarding wizard...\n');
291
+ }
292
+ else {
293
+ console.log('🌐 Opening MAMA OS...\n');
294
+ }
295
+ openBrowser(targetUrl);
296
+ }, 3000); // Wait for embedding server
297
+ await (0, pid_manager_js_1.writePid)(process.pid);
298
+ await runAgentLoop(config);
299
+ }
300
+ else {
301
+ // Run as daemon
302
+ process.stdout.write('Starting agent loop... ');
303
+ try {
304
+ const daemonPid = await startDaemon();
305
+ console.log('✓');
306
+ console.log(`\nMAMA is running in the background.`);
307
+ console.log(`PID: ${daemonPid}\n`);
308
+ console.log('Check status: mama status');
309
+ console.log('Stop: mama stop\n');
310
+ // Auto-open browser after server is ready
311
+ const needsOnboarding = !isOnboardingComplete();
312
+ const targetUrl = needsOnboarding
313
+ ? 'http://localhost:3847/setup'
314
+ : 'http://localhost:3847/viewer';
315
+ // Wait for server to be ready
316
+ setTimeout(() => {
317
+ if (needsOnboarding) {
318
+ console.log('🎭 First-time setup - Opening onboarding wizard...\n');
319
+ }
320
+ else {
321
+ console.log('🌐 Opening MAMA OS...\n');
322
+ }
323
+ openBrowser(targetUrl);
324
+ }, 2000); // Wait 2 seconds for embedding server to start
325
+ }
326
+ catch (error) {
327
+ console.log('❌');
328
+ console.error(`\nFailed to start daemon: ${error instanceof Error ? error.message : String(error)}\n`);
329
+ process.exit(1);
330
+ }
331
+ }
332
+ }
333
+ /**
334
+ * Start daemon process
335
+ */
336
+ async function startDaemon() {
337
+ const { mkdirSync, openSync } = await import('node:fs');
338
+ const { homedir } = await import('node:os');
339
+ // Ensure log directory exists
340
+ const logDir = `${homedir()}/.mama/logs`;
341
+ mkdirSync(logDir, { recursive: true });
342
+ const logFile = `${logDir}/daemon.log`;
343
+ const out = openSync(logFile, 'a');
344
+ // Spawn daemon process directly
345
+ const child = (0, node_child_process_1.spawn)(process.execPath, [process.argv[1], 'daemon'], {
346
+ detached: true,
347
+ stdio: ['ignore', out, out],
348
+ cwd: homedir(),
349
+ env: {
350
+ ...process.env,
351
+ MAMA_DAEMON: '1',
352
+ },
353
+ });
354
+ child.unref();
355
+ if (!child.pid) {
356
+ throw new Error('Failed to spawn daemon process');
357
+ }
358
+ // Give daemon a moment to start
359
+ await new Promise((resolve) => setTimeout(resolve, 500));
360
+ await (0, pid_manager_js_1.writePid)(child.pid);
361
+ return child.pid;
362
+ }
363
+ /**
364
+ * Run agent loop (for foreground and daemon mode)
365
+ */
366
+ async function runAgentLoop(config, options = {}) {
367
+ // Claude CLI is always used (Pi Agent removed for ToS compliance)
368
+ console.log('✓ Claude CLI mode (ToS compliance)');
369
+ const oauthManager = new index_js_1.OAuthManager();
370
+ // Initialize database for session storage
371
+ const dbPath = (0, config_manager_js_1.expandPath)(config.database.path).replace('mama-memory.db', 'mama-sessions.db');
372
+ const db = new better_sqlite3_1.default(dbPath);
373
+ const sessionStore = new index_js_3.SessionStore(db);
374
+ const mamaDbPath = (0, config_manager_js_1.expandPath)(config.database.path);
375
+ const toolExecutor = new gateway_tool_executor_js_1.GatewayToolExecutor({
376
+ mamaDbPath: mamaDbPath,
377
+ sessionStore: sessionStore,
378
+ });
379
+ void toolExecutor;
380
+ // Reasoning collector for Discord display
381
+ let reasoningLog = [];
382
+ let turnCount = 0;
383
+ let autoRecallUsed = false;
384
+ const mamaHome = (0, node_path_1.join)((0, node_os_1.homedir)(), '.mama');
385
+ const personaComplete = (0, node_fs_1.existsSync)((0, node_path_1.join)(mamaHome, 'USER.md')) && (0, node_fs_1.existsSync)((0, node_path_1.join)(mamaHome, 'SOUL.md'));
386
+ let systemPrompt = '';
387
+ let osCapabilities = '';
388
+ if (!personaComplete) {
389
+ console.log('⚙️ Onboarding mode (persona not found)');
390
+ const { COMPLETE_AUTONOMOUS_PROMPT, } = require('../../onboarding/complete-autonomous-prompt.js');
391
+ systemPrompt = COMPLETE_AUTONOMOUS_PROMPT;
392
+ // Check for resume context (interrupted onboarding)
393
+ if ((0, onboarding_state_js_1.isOnboardingInProgress)()) {
394
+ const resumeContext = (0, onboarding_state_js_1.getResumeContext)();
395
+ if (resumeContext) {
396
+ console.log('📋 Resuming previous onboarding session...');
397
+ systemPrompt += '\n\n---\n\n' + resumeContext;
398
+ }
399
+ }
400
+ }
401
+ else {
402
+ console.log('✓ Persona loaded (chat mode)');
403
+ }
404
+ // OS Agent mode (Viewer context only)
405
+ if (options.osAgentMode === true) {
406
+ const osAgentPath = (0, node_path_1.join)(__dirname, '../../agent/os-agent-capabilities.md');
407
+ if ((0, node_fs_1.existsSync)(osAgentPath)) {
408
+ osCapabilities = (0, node_fs_1.readFileSync)(osAgentPath, 'utf-8');
409
+ console.log('[start] ✓ OS Agent mode enabled (system control capabilities)');
410
+ }
411
+ }
412
+ // Initialize agent loop with lane-based concurrency and reasoning collection
413
+ const agentLoop = new index_js_2.AgentLoop(oauthManager, {
414
+ model: config.agent.model,
415
+ maxTurns: config.agent.max_turns,
416
+ useLanes: true, // Enable lane-based concurrency for Discord
417
+ sessionKey: 'default', // Will be updated per message
418
+ systemPrompt: systemPrompt + (osCapabilities ? '\n\n---\n\n' + osCapabilities : ''),
419
+ // Collect reasoning for Discord display
420
+ onTurn: (turn) => {
421
+ turnCount++;
422
+ if (Array.isArray(turn.content)) {
423
+ for (const block of turn.content) {
424
+ if (block.type === 'tool_use') {
425
+ reasoningLog.push(`🔧 ${block.name}`);
426
+ }
427
+ }
428
+ }
429
+ },
430
+ onToolUse: (toolName, _input, result) => {
431
+ // Add tool result summary
432
+ const resultObj = result;
433
+ if (resultObj.error) {
434
+ reasoningLog.push(` ❌ ${resultObj.error}`);
435
+ }
436
+ else if (resultObj.results && Array.isArray(resultObj.results)) {
437
+ reasoningLog.push(` ✓ ${resultObj.results.length} items`);
438
+ }
439
+ else if (resultObj.success !== undefined) {
440
+ reasoningLog.push(` ✓ ${resultObj.success ? 'success' : 'failed'}`);
441
+ }
442
+ console.log(`[Tool] ${toolName} → ${JSON.stringify(result).slice(0, 80)}`);
443
+ },
444
+ });
445
+ console.log('✓ Lane-based concurrency enabled (reasoning collection)');
446
+ // Build reasoning header for Discord
447
+ const buildReasoningHeader = (turns, toolsUsed) => {
448
+ const parts = [];
449
+ if (autoRecallUsed)
450
+ parts.push('📚 Memory');
451
+ if (toolsUsed.length > 0)
452
+ parts.push(toolsUsed.join(', '));
453
+ parts.push(`⏱️ ${turns} turns`);
454
+ return `||${parts.join(' | ')}||`;
455
+ };
456
+ // Create AgentLoopClient wrapper (adapts AgentLoopResult -> { response })
457
+ // Also sets session key for lane-based concurrency and includes reasoning
458
+ const agentLoopClient = {
459
+ run: async (prompt, options) => {
460
+ // Reset reasoning log for new request
461
+ reasoningLog = [];
462
+ turnCount = 0;
463
+ autoRecallUsed = false;
464
+ // Set session key for lane-based concurrency
465
+ if (options?.source && options?.channelId) {
466
+ const sessionKey = `${options.source}:${options.channelId}:${options.userId || 'unknown'}`;
467
+ agentLoop.setSessionKey(sessionKey);
468
+ }
469
+ const result = await agentLoop.run(prompt, options);
470
+ // Check if auto-recall was used (by checking if relevant-memories was in the history)
471
+ if (result.history && result.history.length > 0) {
472
+ const firstMsg = result.history[0];
473
+ if (firstMsg && Array.isArray(firstMsg.content)) {
474
+ const textContent = firstMsg.content.find((b) => b.type === 'text');
475
+ if (textContent &&
476
+ typeof textContent.text === 'string' &&
477
+ textContent.text.includes('<relevant-memories>')) {
478
+ autoRecallUsed = true;
479
+ }
480
+ }
481
+ }
482
+ // Always prepend reasoning header
483
+ const header = buildReasoningHeader(result.turns, reasoningLog.filter((l) => l.startsWith('🔧')));
484
+ const response = `${header}\n${result.response}`;
485
+ return { response };
486
+ },
487
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
488
+ runWithContent: async (content, options) => {
489
+ // Reset reasoning log for new request
490
+ reasoningLog = [];
491
+ turnCount = 0;
492
+ autoRecallUsed = false;
493
+ // Set session key for lane-based concurrency
494
+ if (options?.source && options?.channelId) {
495
+ const sessionKey = `${options.source}:${options.channelId}:${options.userId || 'unknown'}`;
496
+ agentLoop.setSessionKey(sessionKey);
497
+ }
498
+ console.log(`[AgentLoop] runWithContent called with ${content.length} blocks`);
499
+ const result = await agentLoop.runWithContent(content, options);
500
+ // Check if auto-recall was used
501
+ if (result.history && result.history.length > 0) {
502
+ const firstMsg = result.history[0];
503
+ if (firstMsg && Array.isArray(firstMsg.content)) {
504
+ const textContent = firstMsg.content.find((b) => b.type === 'text');
505
+ if (textContent &&
506
+ typeof textContent.text === 'string' &&
507
+ textContent.text.includes('<relevant-memories>')) {
508
+ autoRecallUsed = true;
509
+ }
510
+ }
511
+ }
512
+ // Always prepend reasoning header
513
+ const header = buildReasoningHeader(result.turns, reasoningLog.filter((l) => l.startsWith('🔧')));
514
+ const response = `${header}\n${result.response}`;
515
+ return { response };
516
+ },
517
+ };
518
+ // Initialize message router with MAMA database
519
+ const { initDB } = require('@jungjaehoon/mama-core/db-manager');
520
+ const { search, save, update, loadCheckpoint } = require('@jungjaehoon/mama-core');
521
+ // Initialize MAMA database first
522
+ await initDB();
523
+ console.log('✓ MAMA memory API available (loaded directly in auto-recall)');
524
+ // Create MAMA API client for context injection
525
+ const mamaApiClient = {
526
+ search,
527
+ save,
528
+ update,
529
+ loadCheckpoint,
530
+ };
531
+ const messageRouter = new index_js_3.MessageRouter(sessionStore, agentLoopClient, mamaApiClient);
532
+ const graphHandler = createGraphHandler();
533
+ await startEmbeddingServerIfAvailable(messageRouter, sessionStore, graphHandler);
534
+ // Initialize cron scheduler
535
+ const scheduler = new index_js_4.CronScheduler();
536
+ scheduler.setExecuteCallback(async (prompt) => {
537
+ console.log(`[Cron] Executing: ${prompt.substring(0, 50)}...`);
538
+ try {
539
+ const result = await agentLoop.run(prompt);
540
+ console.log(`[Cron] Completed: ${result.response.substring(0, 100)}...`);
541
+ return result.response;
542
+ }
543
+ catch (error) {
544
+ console.error(`[Cron] Error: ${error}`);
545
+ throw error;
546
+ }
547
+ });
548
+ // Track active gateways for cleanup
549
+ const gateways = [];
550
+ // Initialize Discord gateway if enabled (before API server for reference)
551
+ let discordGateway = null;
552
+ if (config.discord?.enabled && config.discord?.token) {
553
+ console.log('Initializing Discord gateway...');
554
+ try {
555
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
556
+ const discordConfig = config.discord;
557
+ discordGateway = new index_js_3.DiscordGateway({
558
+ token: config.discord.token,
559
+ messageRouter,
560
+ config: discordConfig.guilds ? { guilds: discordConfig.guilds } : undefined,
561
+ });
562
+ const gatewayInterface = {
563
+ sendMessage: async (channelId, message) => discordGateway.sendMessage(channelId, message),
564
+ sendImage: async (channelId, imagePath, caption) => discordGateway.sendImage(channelId, imagePath, caption),
565
+ };
566
+ agentLoop.setDiscordGateway(gatewayInterface);
567
+ await discordGateway.start();
568
+ gateways.push(discordGateway);
569
+ console.log('✓ Discord connected');
570
+ }
571
+ catch (error) {
572
+ console.error(`Failed to connect Discord: ${error instanceof Error ? error.message : String(error)}`);
573
+ discordGateway = null;
574
+ }
575
+ }
576
+ // Initialize gateway plugin loader (for additional gateways like Slack, Chatwork)
577
+ const pluginLoader = new index_js_3.PluginLoader({
578
+ gatewayConfigs: {
579
+ // Pass gateway configs from main config
580
+ ...(config.slack
581
+ ? {
582
+ 'slack-gateway': {
583
+ enabled: config.slack.enabled,
584
+ botToken: config.slack.bot_token,
585
+ appToken: config.slack.app_token,
586
+ },
587
+ }
588
+ : {}),
589
+ ...(config.chatwork
590
+ ? {
591
+ 'chatwork-gateway': {
592
+ enabled: config.chatwork.enabled,
593
+ apiToken: config.chatwork.api_token,
594
+ roomIds: config.chatwork.room_ids,
595
+ pollInterval: config.chatwork.poll_interval,
596
+ mentionRequired: config.chatwork.mention_required,
597
+ },
598
+ }
599
+ : {}),
600
+ },
601
+ agentLoop: {
602
+ run: async (prompt) => {
603
+ const result = await agentLoop.run(prompt);
604
+ return { response: result.response };
605
+ },
606
+ runWithContent: async (content) => {
607
+ // Cast to match the expected type (both use same structure)
608
+ console.log(`[AgentLoop] runWithContent called with ${content.length} blocks`);
609
+ const result = await agentLoop.runWithContent(content);
610
+ return { response: result.response };
611
+ },
612
+ },
613
+ });
614
+ // Discover and load gateway plugins
615
+ try {
616
+ const discoveredPlugins = await pluginLoader.discover();
617
+ if (discoveredPlugins.length > 0) {
618
+ console.log(`Plugins discovered: ${discoveredPlugins.map((p) => p.name).join(', ')}`);
619
+ const pluginGateways = await pluginLoader.loadAll();
620
+ for (const gateway of pluginGateways) {
621
+ try {
622
+ await gateway.start();
623
+ gateways.push(gateway);
624
+ console.log(`✓ Plugin gateway connected: ${gateway.source}`);
625
+ }
626
+ catch (error) {
627
+ console.error(`Plugin gateway failed (${gateway.source}):`, error);
628
+ }
629
+ }
630
+ }
631
+ }
632
+ catch (error) {
633
+ console.warn('Plugin loading warning:', error);
634
+ }
635
+ // Initialize heartbeat scheduler
636
+ const heartbeatConfig = config.heartbeat || {};
637
+ const heartbeatScheduler = new heartbeat_js_1.HeartbeatScheduler(agentLoop, {
638
+ interval: heartbeatConfig.interval || 30 * 60 * 1000, // 30 minutes default
639
+ quietStart: heartbeatConfig.quiet_start || 23,
640
+ quietEnd: heartbeatConfig.quiet_end || 8,
641
+ notifyChannelId: heartbeatConfig.notify_channel_id || config.discord?.default_channel_id,
642
+ }, discordGateway
643
+ ? async (channelId, message) => {
644
+ await discordGateway.sendMessage(channelId, message);
645
+ }
646
+ : undefined);
647
+ if (heartbeatConfig.enabled !== false) {
648
+ heartbeatScheduler.start();
649
+ console.log('✓ Heartbeat scheduler started');
650
+ }
651
+ // Initialize token keep-alive (prevents OAuth token expiration)
652
+ const tokenKeepAlive = new index_js_4.TokenKeepAlive({
653
+ intervalMs: 6 * 60 * 60 * 1000, // 6 hours
654
+ onRefresh: () => {
655
+ console.log('✓ OAuth token kept alive');
656
+ },
657
+ onError: (error) => {
658
+ console.warn(`⚠️ Token refresh warning: ${error.message}`);
659
+ },
660
+ });
661
+ tokenKeepAlive.start();
662
+ // Start API server
663
+ const apiServer = (0, index_js_5.createApiServer)({
664
+ scheduler,
665
+ port: 3848,
666
+ onHeartbeat: async (prompt) => {
667
+ try {
668
+ await agentLoop.run(prompt);
669
+ return { success: true };
670
+ }
671
+ catch (error) {
672
+ return { success: false, error: String(error) };
673
+ }
674
+ },
675
+ });
676
+ // Add Discord message sending endpoint
677
+ apiServer.app.post('/api/discord/send', async (req, res) => {
678
+ try {
679
+ const { channelId, message } = req.body;
680
+ if (!channelId || !message) {
681
+ res.status(400).json({ error: 'channelId and message are required' });
682
+ return;
683
+ }
684
+ if (!discordGateway) {
685
+ res.status(503).json({ error: 'Discord gateway not connected' });
686
+ return;
687
+ }
688
+ console.log(`[Discord Send] Sending to ${channelId}: ${message.substring(0, 50)}...`);
689
+ await discordGateway.sendMessage(channelId, message);
690
+ console.log(`[Discord Send] Success`);
691
+ res.json({ success: true });
692
+ }
693
+ catch (error) {
694
+ console.error('[Discord Send] Error:', error);
695
+ res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
696
+ }
697
+ });
698
+ // Add Discord cron job endpoint (run prompt and send result to Discord)
699
+ apiServer.app.post('/api/discord/cron', async (req, res) => {
700
+ try {
701
+ const { channelId, prompt } = req.body;
702
+ if (!channelId || !prompt) {
703
+ res.status(400).json({ error: 'channelId and prompt are required' });
704
+ return;
705
+ }
706
+ if (!discordGateway) {
707
+ res.status(503).json({ error: 'Discord gateway not connected' });
708
+ return;
709
+ }
710
+ console.log(`[Discord Cron] Executing: ${prompt.substring(0, 50)}...`);
711
+ const result = await agentLoop.run(prompt);
712
+ await discordGateway.sendMessage(channelId, result.response);
713
+ console.log(`[Discord Cron] Sent to Discord channel ${channelId}`);
714
+ res.json({ success: true, response: result.response.substring(0, 100) + '...' });
715
+ }
716
+ catch (error) {
717
+ res.status(500).json({ error: String(error) });
718
+ }
719
+ });
720
+ // Report endpoint - collect data and generate report (OpenClaw migration)
721
+ apiServer.app.post('/api/report', async (req, res) => {
722
+ const { exec } = await import('child_process');
723
+ const { promisify } = await import('util');
724
+ const execAsync = promisify(exec);
725
+ const fs = await import('fs/promises');
726
+ try {
727
+ const { channelId, reportType = 'delta' } = req.body;
728
+ if (!channelId) {
729
+ res.status(400).json({ error: 'channelId is required' });
730
+ return;
731
+ }
732
+ if (!discordGateway) {
733
+ res.status(503).json({ error: 'Discord gateway not connected' });
734
+ return;
735
+ }
736
+ console.log(`[Heartbeat] Starting ${reportType} report...`);
737
+ // Get paths from config (with fallbacks)
738
+ const workspacePath = config.workspace?.path?.replace('~', process.env.HOME || '') ||
739
+ `${process.env.HOME}/.mama/workspace`;
740
+ const collectScript = config.integrations?.heartbeat?.collect_script?.replace('~', process.env.HOME || '') ||
741
+ `${workspacePath}/scripts/heartbeat-collect.sh`;
742
+ const dataFile = config.integrations?.heartbeat?.data_file?.replace('~', process.env.HOME || '') ||
743
+ `${workspacePath}/data/heartbeat-report.json`;
744
+ const templateFile = config.integrations?.heartbeat?.template_file?.replace('~', process.env.HOME || '') ||
745
+ `${workspacePath}/HEARTBEAT.md`;
746
+ // 1. Run heartbeat-collect.sh
747
+ console.log('[Heartbeat] Collecting data...');
748
+ await execAsync(`bash ${collectScript}`, {
749
+ timeout: 60000,
750
+ cwd: workspacePath,
751
+ });
752
+ // 2. Read collected data (limit to 50KB to fit in prompt)
753
+ let jsonData = await fs.readFile(dataFile, 'utf-8');
754
+ if (jsonData.length > 50000) {
755
+ console.log(`[Heartbeat] JSON too large (${jsonData.length}), truncating to 50KB`);
756
+ jsonData = jsonData.substring(0, 50000) + '\n... (truncated)';
757
+ }
758
+ const heartbeatMd = await fs.readFile(templateFile, 'utf-8');
759
+ // 3. Generate report with Claude
760
+ console.log('[Heartbeat] Generating report...');
761
+ const prompt = `Here is the collected work data. Please write a ${reportType === 'full' ? 'comprehensive report' : 'delta report'} following the report format in HEARTBEAT.md.
762
+
763
+ ## HEARTBEAT.md (Report Format)
764
+ ${heartbeatMd}
765
+
766
+ ## Collected Data (JSON)
767
+ ${jsonData}
768
+
769
+ ${reportType === 'full'
770
+ ? '📋 Write a comprehensive report. Include all project status.'
771
+ : '🔔 Write a delta report. If there are no new messages, respond with HEARTBEAT_OK only.'}
772
+
773
+ Keep the report under 2000 characters as it will be sent to Discord.`;
774
+ const result = await agentLoop.run(prompt);
775
+ console.log(`[Heartbeat] Claude response length: ${result.response?.length || 0}`);
776
+ console.log(`[Heartbeat] Response preview: ${result.response?.substring(0, 100) || 'EMPTY'}`);
777
+ // 4. Send to Discord
778
+ if (!result.response || result.response.trim() === '') {
779
+ console.error('[Heartbeat] Empty response from Claude');
780
+ res.status(500).json({ error: 'Empty response from Claude' });
781
+ return;
782
+ }
783
+ console.log('[Heartbeat] Sending to Discord...');
784
+ await discordGateway.sendMessage(channelId, result.response);
785
+ console.log('[Heartbeat] Complete');
786
+ res.json({ success: true, reportType, response: result.response.substring(0, 200) + '...' });
787
+ }
788
+ catch (error) {
789
+ console.error('[Heartbeat] Error:', error);
790
+ res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
791
+ }
792
+ });
793
+ // Screenshot endpoint - take HTML screenshot and send to Discord
794
+ apiServer.app.post('/api/screenshot', async (req, res) => {
795
+ const { exec } = await import('child_process');
796
+ const { promisify } = await import('util');
797
+ const path = await import('path');
798
+ const execAsync = promisify(exec);
799
+ try {
800
+ const { channelId, htmlFile, caption } = req.body;
801
+ if (!channelId || !htmlFile) {
802
+ res.status(400).json({ error: 'channelId and htmlFile are required' });
803
+ return;
804
+ }
805
+ if (!discordGateway) {
806
+ res.status(503).json({ error: 'Discord gateway not connected' });
807
+ return;
808
+ }
809
+ const workspacePath = config.workspace?.path?.replace('~', process.env.HOME || '') ||
810
+ `${process.env.HOME}/.mama/workspace`;
811
+ // SECURITY P0: Path traversal prevention
812
+ if (path.isAbsolute(htmlFile)) {
813
+ res.status(400).json({ error: 'Absolute paths not allowed' });
814
+ return;
815
+ }
816
+ const resolvedPath = path.resolve(workspacePath, htmlFile);
817
+ const normalizedWorkspace = path.resolve(workspacePath);
818
+ if (!resolvedPath.startsWith(normalizedWorkspace + path.sep)) {
819
+ res.status(400).json({ error: 'Path traversal detected' });
820
+ return;
821
+ }
822
+ const fs = await import('fs/promises');
823
+ try {
824
+ await fs.access(resolvedPath);
825
+ }
826
+ catch {
827
+ res.status(404).json({ error: 'File not found' });
828
+ return;
829
+ }
830
+ const allowedExtensions = ['.html', '.htm'];
831
+ if (!allowedExtensions.some((ext) => resolvedPath.toLowerCase().endsWith(ext))) {
832
+ res.status(400).json({ error: 'Only HTML files allowed' });
833
+ return;
834
+ }
835
+ const htmlPath = resolvedPath;
836
+ const outputPath = `${workspacePath}/temp/screenshot-${Date.now()}.png`;
837
+ console.log(`[Screenshot] Taking screenshot of: ${htmlPath}`);
838
+ // Run screenshot script
839
+ await execAsync(`node ${workspacePath}/scripts/html-screenshot.mjs "${htmlPath}" "${outputPath}"`, {
840
+ timeout: 30000,
841
+ cwd: workspacePath,
842
+ });
843
+ // Send to Discord
844
+ console.log(`[Screenshot] Sending to Discord: ${outputPath}`);
845
+ await discordGateway.sendImage(channelId, outputPath, caption);
846
+ console.log('[Screenshot] Complete');
847
+ res.json({ success: true, screenshot: outputPath });
848
+ }
849
+ catch (error) {
850
+ console.error('[Screenshot] Error:', error);
851
+ res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
852
+ }
853
+ });
854
+ // Send image endpoint
855
+ // SECURITY P0: Path traversal prevention with 4-layer validation
856
+ apiServer.app.post('/api/discord/image', async (req, res) => {
857
+ const path = await import('path');
858
+ const fs = await import('fs/promises');
859
+ try {
860
+ const { channelId, imagePath, caption } = req.body;
861
+ if (!channelId || !imagePath) {
862
+ res.status(400).json({ error: 'channelId and imagePath are required' });
863
+ return;
864
+ }
865
+ if (!discordGateway) {
866
+ res.status(503).json({ error: 'Discord gateway not connected' });
867
+ return;
868
+ }
869
+ // SECURITY P0: 4-layer path validation
870
+ const workspacePath = config.workspace?.path?.replace('~', process.env.HOME || '') ||
871
+ `${process.env.HOME}/.mama/workspace`;
872
+ const tempPath = path.join(workspacePath, 'temp');
873
+ const tmpPath = '/tmp';
874
+ // Layer 1: Reject absolute paths (unless in allowed directories)
875
+ if (path.isAbsolute(imagePath)) {
876
+ const normalizedInput = path.normalize(imagePath);
877
+ const isInWorkspace = normalizedInput.startsWith(path.resolve(workspacePath) + path.sep);
878
+ const isInTemp = normalizedInput.startsWith(path.resolve(tempPath) + path.sep);
879
+ const isInTmp = normalizedInput.startsWith(tmpPath + path.sep);
880
+ if (!isInWorkspace && !isInTemp && !isInTmp) {
881
+ console.warn(`[Discord Image] SECURITY: Absolute path blocked: ${imagePath}`);
882
+ res
883
+ .status(400)
884
+ .json({ error: 'Absolute paths only allowed in workspace, workspace/temp, or /tmp' });
885
+ return;
886
+ }
887
+ }
888
+ // Layer 2: Resolve and verify within allowed directories
889
+ const resolvedImagePath = path.isAbsolute(imagePath)
890
+ ? path.resolve(imagePath)
891
+ : path.resolve(workspacePath, imagePath);
892
+ const normalizedWorkspace = path.resolve(workspacePath);
893
+ const normalizedTemp = path.resolve(tempPath);
894
+ const isInWorkspace = resolvedImagePath.startsWith(normalizedWorkspace + path.sep);
895
+ const isInTemp = resolvedImagePath.startsWith(normalizedTemp + path.sep);
896
+ const isInTmp = resolvedImagePath.startsWith(tmpPath + path.sep);
897
+ if (!isInWorkspace && !isInTemp && !isInTmp) {
898
+ console.warn(`[Discord Image] SECURITY: Path traversal blocked: ${imagePath} -> ${resolvedImagePath}`);
899
+ res.status(400).json({ error: 'Path traversal detected' });
900
+ return;
901
+ }
902
+ // Layer 3: Verify file exists
903
+ try {
904
+ await fs.access(resolvedImagePath);
905
+ }
906
+ catch {
907
+ res.status(404).json({ error: 'Image file not found' });
908
+ return;
909
+ }
910
+ // Layer 4: Whitelist extensions
911
+ const allowedExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.webp'];
912
+ if (!allowedExtensions.some((ext) => resolvedImagePath.toLowerCase().endsWith(ext))) {
913
+ console.warn(`[Discord Image] SECURITY: Invalid extension blocked: ${resolvedImagePath}`);
914
+ res
915
+ .status(400)
916
+ .json({ error: 'Only image files allowed (.png, .jpg, .jpeg, .gif, .webp)' });
917
+ return;
918
+ }
919
+ console.log(`[Discord Image] Sending: ${resolvedImagePath}`);
920
+ await discordGateway.sendImage(channelId, resolvedImagePath, caption);
921
+ console.log('[Discord Image] Complete');
922
+ res.json({ success: true });
923
+ }
924
+ catch (error) {
925
+ console.error('[Discord Image] Error:', error);
926
+ res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
927
+ }
928
+ });
929
+ apiServer.app.use(async (req, res, next) => {
930
+ const handled = await graphHandler(req, res);
931
+ if (!handled)
932
+ next();
933
+ });
934
+ apiServer.app.use((req, res, next) => {
935
+ if (req.path.startsWith('/api/session')) {
936
+ const http = require('http');
937
+ const bodyData = req.body ? JSON.stringify(req.body) : '';
938
+ const options = {
939
+ hostname: 'localhost',
940
+ port: 3847,
941
+ path: req.url,
942
+ method: req.method,
943
+ headers: {
944
+ ...req.headers,
945
+ host: 'localhost:3847',
946
+ 'content-length': Buffer.byteLength(bodyData),
947
+ },
948
+ };
949
+ const proxy = http.request(options, (proxyRes) => {
950
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
951
+ proxyRes.pipe(res, { end: true });
952
+ });
953
+ if (bodyData) {
954
+ proxy.write(bodyData);
955
+ }
956
+ proxy.end();
957
+ proxy.on('error', (error) => {
958
+ if (!res.headersSent) {
959
+ res.status(500).json({ error: 'Failed to proxy session API', details: error.message });
960
+ }
961
+ });
962
+ }
963
+ else {
964
+ next();
965
+ }
966
+ });
967
+ console.log('✓ Session API proxied to port 3847');
968
+ const publicDir = node_path_1.default.resolve(process.cwd(), 'public');
969
+ // Serve setup page at /setup route
970
+ apiServer.app.get('/setup', (_req, res) => {
971
+ res.sendFile(node_path_1.default.join(publicDir, 'setup.html'));
972
+ });
973
+ apiServer.app.use(express_1.default.static(publicDir, {
974
+ setHeaders: (res) => {
975
+ res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
976
+ res.setHeader('Pragma', 'no-cache');
977
+ res.setHeader('Expires', '0');
978
+ },
979
+ }));
980
+ console.log('✓ Viewer UI available at /viewer');
981
+ console.log('✓ Setup wizard available at /setup');
982
+ await apiServer.start();
983
+ console.log(`API server started: http://localhost:${apiServer.port}`);
984
+ if (apiServer.server) {
985
+ // Setup WebSocket - use noServer mode to avoid conflict
986
+ const setupWss = new ws_1.WebSocketServer({ noServer: true });
987
+ (0, setup_websocket_js_1.createSetupWebSocketHandler)(setupWss);
988
+ console.log('✓ Setup WebSocket handler ready for /setup-ws');
989
+ // Handle ALL WebSocket upgrades manually
990
+ apiServer.server.on('upgrade', (request, socket, head) => {
991
+ const url = new URL(request.url || '', `http://${request.headers.host}`);
992
+ if (url.pathname === '/setup-ws') {
993
+ // Handle setup WebSocket locally
994
+ setupWss.handleUpgrade(request, socket, head, (ws) => {
995
+ setupWss.emit('connection', ws, request);
996
+ });
997
+ }
998
+ else if (url.pathname === '/ws') {
999
+ // Proxy chat WebSocket to embedding server (port 3847)
1000
+ const http = require('http');
1001
+ const options = {
1002
+ hostname: '127.0.0.1',
1003
+ port: 3847,
1004
+ path: request.url,
1005
+ method: 'GET',
1006
+ headers: {
1007
+ ...request.headers,
1008
+ host: '127.0.0.1:3847',
1009
+ },
1010
+ };
1011
+ const proxyReq = http.request(options);
1012
+ proxyReq.on('upgrade', (proxyRes, proxySocket, _proxyHead) => {
1013
+ socket.write(`HTTP/1.1 101 Switching Protocols\r\n` +
1014
+ `Upgrade: websocket\r\n` +
1015
+ `Connection: Upgrade\r\n` +
1016
+ `Sec-WebSocket-Accept: ${proxyRes.headers['sec-websocket-accept']}\r\n` +
1017
+ `\r\n`);
1018
+ proxySocket.pipe(socket);
1019
+ socket.pipe(proxySocket);
1020
+ });
1021
+ proxyReq.on('error', (err) => {
1022
+ console.error('[WS Proxy] Error:', err.message);
1023
+ socket.destroy();
1024
+ });
1025
+ proxyReq.end();
1026
+ }
1027
+ else {
1028
+ // Unknown WebSocket path - close connection
1029
+ socket.destroy();
1030
+ }
1031
+ });
1032
+ console.log('✓ WebSocket upgrade handler registered (/ws → 3847, /setup-ws local)');
1033
+ }
1034
+ gateways.push(apiServer);
1035
+ // Handle graceful shutdown
1036
+ const shutdown = async () => {
1037
+ console.log('\n\n🛑 Shutting down MAMA...');
1038
+ // Stop all gateways
1039
+ for (const gateway of gateways) {
1040
+ try {
1041
+ await gateway.stop();
1042
+ }
1043
+ catch {
1044
+ // Ignore errors during shutdown
1045
+ }
1046
+ }
1047
+ // Stop plugin gateways
1048
+ try {
1049
+ await pluginLoader.stopAll();
1050
+ }
1051
+ catch {
1052
+ // Ignore errors during shutdown
1053
+ }
1054
+ // Stop schedulers
1055
+ scheduler.shutdown();
1056
+ heartbeatScheduler.stop();
1057
+ tokenKeepAlive.stop();
1058
+ // Close session database
1059
+ sessionStore.close();
1060
+ const { deletePid } = await import('../utils/pid-manager.js');
1061
+ await deletePid();
1062
+ process.exit(0);
1063
+ };
1064
+ process.on('SIGINT', shutdown);
1065
+ process.on('SIGTERM', shutdown);
1066
+ console.log('MAMA agent is waiting...\n');
1067
+ // Keep process alive using setInterval
1068
+ // This ensures the Node.js event loop stays active
1069
+ setInterval(() => {
1070
+ // Heartbeat - keeps the process running
1071
+ }, 30000); // Every 30 seconds
1072
+ }
1073
+ //# sourceMappingURL=start.js.map