@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,353 @@
1
+ /**
2
+ * Memory Module - MAMA Memory Integration
3
+ * @module modules/memory
4
+ * @version 1.0.0
5
+ *
6
+ * Handles Memory tab functionality including:
7
+ * - Semantic search of MAMA decisions
8
+ * - Related decision suggestions for chat messages
9
+ * - Save decision form modal
10
+ */
11
+
12
+ /* eslint-env browser */
13
+ /* global lucide */
14
+
15
+ import { escapeHtml, debounce, showToast } from '../utils/dom.js';
16
+ import { formatRelativeTime, truncateText } from '../utils/format.js';
17
+ import { API } from '../utils/api.js';
18
+
19
+ /**
20
+ * Memory Module Class
21
+ */
22
+ export class MemoryModule {
23
+ constructor() {
24
+ // State
25
+ this.searchData = [];
26
+ this.debouncedSearch = debounce(() => this.performSearch(), 300);
27
+
28
+ // Initialize event listeners
29
+ this.initEventListeners();
30
+ }
31
+
32
+ /**
33
+ * Initialize all event listeners
34
+ */
35
+ initEventListeners() {
36
+ // Modal click outside to close
37
+ document.addEventListener('click', (e) => {
38
+ const modal = document.getElementById('save-decision-modal');
39
+ if (modal && e.target === modal) {
40
+ this.hideSaveForm();
41
+ }
42
+ });
43
+
44
+ // Escape key to close modal
45
+ document.addEventListener('keydown', (e) => {
46
+ if (e.key === 'Escape') {
47
+ const modal = document.getElementById('save-decision-modal');
48
+ if (modal && modal.classList.contains('visible')) {
49
+ this.hideSaveForm();
50
+ }
51
+ }
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Handle memory search input event
57
+ * @param {KeyboardEvent} event - Keyboard event
58
+ */
59
+ handleSearchInput(event) {
60
+ if (event.key === 'Enter') {
61
+ this.search();
62
+ } else {
63
+ this.debouncedSearch();
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Perform search (internal, debounced)
69
+ */
70
+ async performSearch() {
71
+ const input = document.getElementById('memory-search-input');
72
+ const query = input.value.trim();
73
+
74
+ if (!query) {
75
+ this.showPlaceholder();
76
+ return;
77
+ }
78
+
79
+ await this.search();
80
+ }
81
+
82
+ /**
83
+ * Search memory decisions via API
84
+ */
85
+ async search() {
86
+ const input = document.getElementById('memory-search-input');
87
+ const query = input.value.trim();
88
+
89
+ if (!query) {
90
+ this.showPlaceholder();
91
+ return;
92
+ }
93
+
94
+ this.setStatus('Searching...', 'loading');
95
+
96
+ try {
97
+ const data = await API.searchMemory(query, 10);
98
+ this.searchData = data.results || [];
99
+ this.renderResults(this.searchData, query);
100
+ this.setStatus(`Found ${this.searchData.length} decision(s)`, '');
101
+ } catch (error) {
102
+ console.error('[Memory] Search error:', error);
103
+ this.setStatus(`Error: ${error.message}`, 'error');
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Search for related decisions (called automatically for chat messages)
109
+ * @param {string} message - Chat message text
110
+ * @returns {Promise<Array>} Related decisions
111
+ */
112
+ async searchRelated(message) {
113
+ if (!message || message.length < 3) {
114
+ return [];
115
+ }
116
+
117
+ try {
118
+ const data = await API.searchMemory(message, 5);
119
+ return data.results || [];
120
+ } catch (error) {
121
+ console.error('[Memory] Related search error:', error);
122
+ return [];
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Show related decisions for a chat message
128
+ * @param {string} message - Chat message text
129
+ */
130
+ async showRelatedForMessage(message) {
131
+ const results = await this.searchRelated(message);
132
+
133
+ if (results.length > 0) {
134
+ this.searchData = results;
135
+
136
+ // Update search input with the query
137
+ const input = document.getElementById('memory-search-input');
138
+ input.value = message.substring(0, 50) + (message.length > 50 ? '...' : '');
139
+
140
+ // Render results
141
+ this.renderResults(results, message);
142
+ this.setStatus(`${results.length} related decision(s) found`, '');
143
+
144
+ // Show notification
145
+ showToast(`🧠 ${results.length} related MAMA decision(s) found`);
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Render search results
151
+ * @param {Array} results - Search results
152
+ * @param {string} query - Search query
153
+ */
154
+ renderResults(results, query) {
155
+ const container = document.getElementById('memory-results');
156
+
157
+ if (!results || results.length === 0) {
158
+ container.innerHTML = `
159
+ <div class="memory-placeholder">
160
+ <p>No decisions found for "${escapeHtml(query)}"</p>
161
+ <p class="memory-hint">Try different keywords or check if you have saved decisions</p>
162
+ </div>
163
+ `;
164
+ return;
165
+ }
166
+
167
+ const html = results
168
+ .map(
169
+ (item, idx) => `
170
+ <div class="memory-card" onclick="window.memoryModule.toggleCard(${idx})">
171
+ <div class="memory-card-header">
172
+ <span class="memory-card-topic">${escapeHtml(item.topic || 'Unknown')}</span>
173
+ ${item.similarity ? `<span class="memory-card-score">${Math.round(item.similarity * 100)}%</span>` : ''}
174
+ </div>
175
+ <div class="memory-card-decision">${escapeHtml(truncateText(item.decision, 150))}</div>
176
+ <div class="memory-card-meta">
177
+ <span class="memory-card-outcome ${(item.outcome || 'pending').toLowerCase()}">${item.outcome || 'PENDING'}</span>
178
+ <span>${formatRelativeTime(item.created_at)}</span>
179
+ </div>
180
+ <div class="memory-card-reasoning">${escapeHtml(item.reasoning || 'No reasoning provided')}</div>
181
+ </div>
182
+ `
183
+ )
184
+ .join('');
185
+
186
+ container.innerHTML = html;
187
+ }
188
+
189
+ /**
190
+ * Toggle memory card expand/collapse
191
+ * @param {number} idx - Card index
192
+ */
193
+ toggleCard(idx) {
194
+ const cards = document.querySelectorAll('.memory-card');
195
+ cards.forEach((card, i) => {
196
+ if (i === idx) {
197
+ card.classList.toggle('expanded');
198
+ } else {
199
+ card.classList.remove('expanded');
200
+ }
201
+ });
202
+ }
203
+
204
+ /**
205
+ * Show memory placeholder
206
+ */
207
+ showPlaceholder() {
208
+ const container = document.getElementById('memory-results');
209
+ container.innerHTML = `
210
+ <div class="memory-placeholder">
211
+ <p><i data-lucide="brain"></i> Search your MAMA decisions</p>
212
+ <p class="memory-hint">Type a keyword or send a chat message to see related decisions</p>
213
+ </div>
214
+ `;
215
+ this.setStatus('', '');
216
+ // Reinitialize Lucide icons for dynamic content
217
+ if (typeof lucide !== 'undefined' && typeof window.lucideConfig !== 'undefined') {
218
+ lucide.createIcons(window.lucideConfig);
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Set memory status message
224
+ * @param {string} message - Status message
225
+ * @param {string} type - Status type (loading, error, success, '')
226
+ */
227
+ setStatus(message, type) {
228
+ const status = document.getElementById('memory-status');
229
+ status.textContent = message;
230
+ status.className = 'memory-status ' + (type || '');
231
+ }
232
+
233
+ /**
234
+ * Show save decision form modal
235
+ */
236
+ showSaveForm() {
237
+ const modal = document.getElementById('save-decision-modal');
238
+ modal.classList.add('visible');
239
+
240
+ // Clear form
241
+ document.getElementById('save-topic').value = '';
242
+ document.getElementById('save-decision').value = '';
243
+ document.getElementById('save-reasoning').value = '';
244
+ document.getElementById('save-confidence').value = '0.8';
245
+ document.getElementById('save-form-status').textContent = '';
246
+ document.getElementById('save-form-status').className = 'save-form-status';
247
+
248
+ // Focus on topic field
249
+ setTimeout(() => {
250
+ document.getElementById('save-topic').focus();
251
+ }, 100);
252
+ }
253
+
254
+ /**
255
+ * Show save form with pre-filled text (for /save command)
256
+ */
257
+ showSaveFormWithText(text) {
258
+ const modal = document.getElementById('save-decision-modal');
259
+ modal.classList.add('visible');
260
+
261
+ // Pre-fill decision field
262
+ document.getElementById('save-topic').value = '';
263
+ document.getElementById('save-decision').value = text;
264
+ document.getElementById('save-reasoning').value = '';
265
+ document.getElementById('save-confidence').value = '0.8';
266
+ document.getElementById('save-form-status').textContent = '';
267
+ document.getElementById('save-form-status').className = 'save-form-status';
268
+
269
+ // Focus on topic field
270
+ setTimeout(() => {
271
+ document.getElementById('save-topic').focus();
272
+ }, 100);
273
+ }
274
+
275
+ /**
276
+ * Hide save decision form modal
277
+ */
278
+ hideSaveForm() {
279
+ const modal = document.getElementById('save-decision-modal');
280
+ modal.classList.remove('visible');
281
+ }
282
+
283
+ /**
284
+ * Execute search with query (for /search command)
285
+ */
286
+ async searchWithQuery(query) {
287
+ const searchInput = document.getElementById('memory-search');
288
+ if (searchInput) {
289
+ searchInput.value = query;
290
+ }
291
+ this.currentQuery = query;
292
+ await this.search();
293
+ }
294
+
295
+ /**
296
+ * Submit save decision form
297
+ */
298
+ async submitSaveForm() {
299
+ const topic = document.getElementById('save-topic').value.trim();
300
+ const decision = document.getElementById('save-decision').value.trim();
301
+ const reasoning = document.getElementById('save-reasoning').value.trim();
302
+ const confidence = parseFloat(document.getElementById('save-confidence').value);
303
+
304
+ const statusEl = document.getElementById('save-form-status');
305
+ const submitBtn = document.querySelector('.save-form-submit');
306
+
307
+ // Validation
308
+ if (!topic || !decision || !reasoning) {
309
+ statusEl.textContent = 'Please fill in all required fields';
310
+ statusEl.className = 'save-form-status error';
311
+ return;
312
+ }
313
+
314
+ if (isNaN(confidence) || confidence < 0 || confidence > 1) {
315
+ statusEl.textContent = 'Confidence must be between 0.0 and 1.0';
316
+ statusEl.className = 'save-form-status error';
317
+ return;
318
+ }
319
+
320
+ // Disable submit button
321
+ submitBtn.disabled = true;
322
+ statusEl.textContent = 'Saving...';
323
+ statusEl.className = 'save-form-status';
324
+
325
+ try {
326
+ await API.saveDecision({ topic, decision, reasoning, confidence });
327
+
328
+ // Success
329
+ statusEl.textContent = '✓ Decision saved successfully!';
330
+ statusEl.className = 'save-form-status success';
331
+
332
+ // Show toast notification
333
+ showToast('✓ Decision saved to MAMA memory');
334
+
335
+ // Close modal after 1.5 seconds
336
+ setTimeout(() => {
337
+ this.hideSaveForm();
338
+
339
+ // Refresh memory search if there's a query
340
+ const searchInput = document.getElementById('memory-search-input');
341
+ if (searchInput.value.trim()) {
342
+ this.search();
343
+ }
344
+ }, 1500);
345
+ } catch (error) {
346
+ console.error('[Memory] Save error:', error);
347
+ statusEl.textContent = `Error: ${error.message}`;
348
+ statusEl.className = 'save-form-status error';
349
+ } finally {
350
+ submitBtn.disabled = false;
351
+ }
352
+ }
353
+ }
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Settings Module - MAMA OS Settings Management
3
+ * @module modules/settings
4
+ * @version 1.0.0
5
+ *
6
+ * Handles Settings tab functionality including:
7
+ * - Load current configuration
8
+ * - Save configuration changes
9
+ * - Form validation
10
+ * - Gateway enable/disable toggles
11
+ */
12
+
13
+ /* eslint-env browser */
14
+
15
+ import { showToast } from '../utils/dom.js';
16
+
17
+ /**
18
+ * Settings Module Class
19
+ */
20
+ export class SettingsModule {
21
+ constructor() {
22
+ this.config = null;
23
+ this.initialized = false;
24
+ }
25
+
26
+ /**
27
+ * Initialize settings module
28
+ */
29
+ async init() {
30
+ if (this.initialized) {
31
+ return;
32
+ }
33
+ this.initialized = true;
34
+
35
+ await this.loadSettings();
36
+ }
37
+
38
+ /**
39
+ * Load current settings from API
40
+ */
41
+ async loadSettings() {
42
+ this.setStatus('Loading...');
43
+
44
+ try {
45
+ const response = await fetch('/api/config');
46
+ if (!response.ok) {
47
+ throw new Error(`HTTP ${response.status}`);
48
+ }
49
+
50
+ this.config = await response.json();
51
+ this.populateForm();
52
+ this.setStatus('');
53
+ } catch (error) {
54
+ console.error('[Settings] Load error:', error);
55
+ this.setStatus(`Error: ${error.message}`, 'error');
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Populate form with current config values
61
+ */
62
+ populateForm() {
63
+ if (!this.config) {
64
+ return;
65
+ }
66
+
67
+ // Discord
68
+ this.setCheckbox('settings-discord-enabled', this.config.discord?.enabled);
69
+ this.setValue('settings-discord-token', this.config.discord?.token || '');
70
+ this.setValue('settings-discord-channel', this.config.discord?.default_channel_id || '');
71
+
72
+ // Slack
73
+ this.setCheckbox('settings-slack-enabled', this.config.slack?.enabled);
74
+ this.setValue('settings-slack-bot-token', this.config.slack?.bot_token || '');
75
+ this.setValue('settings-slack-app-token', this.config.slack?.app_token || '');
76
+
77
+ // Telegram
78
+ this.setCheckbox('settings-telegram-enabled', this.config.telegram?.enabled);
79
+ this.setValue('settings-telegram-token', this.config.telegram?.token || '');
80
+
81
+ // Chatwork
82
+ this.setCheckbox('settings-chatwork-enabled', this.config.chatwork?.enabled);
83
+ this.setValue('settings-chatwork-token', this.config.chatwork?.api_token || '');
84
+
85
+ // Heartbeat
86
+ this.setCheckbox('settings-heartbeat-enabled', this.config.heartbeat?.enabled);
87
+ this.setValue(
88
+ 'settings-heartbeat-interval',
89
+ Math.round((this.config.heartbeat?.interval || 1800000) / 60000)
90
+ );
91
+ this.setValue('settings-heartbeat-quiet-start', this.config.heartbeat?.quiet_start ?? 23);
92
+ this.setValue('settings-heartbeat-quiet-end', this.config.heartbeat?.quiet_end ?? 8);
93
+
94
+ // Agent
95
+ this.setSelectValue(
96
+ 'settings-agent-model',
97
+ this.config.agent?.model || 'claude-sonnet-4-20250514'
98
+ );
99
+ this.setValue('settings-agent-max-turns', this.config.agent?.max_turns || 10);
100
+ this.setValue(
101
+ 'settings-agent-timeout',
102
+ Math.round((this.config.agent?.timeout || 300000) / 1000)
103
+ );
104
+ }
105
+
106
+ /**
107
+ * Save settings to API
108
+ */
109
+ async saveSettings() {
110
+ this.setStatus('Saving...');
111
+
112
+ try {
113
+ const updates = this.collectFormData();
114
+
115
+ const response = await fetch('/api/config', {
116
+ method: 'PUT',
117
+ headers: { 'Content-Type': 'application/json' },
118
+ body: JSON.stringify(updates),
119
+ });
120
+
121
+ const result = await response.json();
122
+
123
+ if (!response.ok) {
124
+ throw new Error(result.message || `HTTP ${response.status}`);
125
+ }
126
+
127
+ this.setStatus('Saved!', 'success');
128
+ showToast('Settings saved successfully');
129
+
130
+ // Reload to get updated masked values
131
+ setTimeout(() => this.loadSettings(), 1500);
132
+ } catch (error) {
133
+ console.error('[Settings] Save error:', error);
134
+ this.setStatus(`Error: ${error.message}`, 'error');
135
+ showToast(`Failed to save: ${error.message}`);
136
+ }
137
+ }
138
+
139
+ /**
140
+ * Collect form data into config update object
141
+ */
142
+ collectFormData() {
143
+ return {
144
+ discord: {
145
+ enabled: this.getCheckbox('settings-discord-enabled'),
146
+ token: this.getValue('settings-discord-token'),
147
+ default_channel_id: this.getValue('settings-discord-channel'),
148
+ },
149
+ slack: {
150
+ enabled: this.getCheckbox('settings-slack-enabled'),
151
+ bot_token: this.getValue('settings-slack-bot-token'),
152
+ app_token: this.getValue('settings-slack-app-token'),
153
+ },
154
+ telegram: {
155
+ enabled: this.getCheckbox('settings-telegram-enabled'),
156
+ token: this.getValue('settings-telegram-token'),
157
+ },
158
+ chatwork: {
159
+ enabled: this.getCheckbox('settings-chatwork-enabled'),
160
+ api_token: this.getValue('settings-chatwork-token'),
161
+ },
162
+ heartbeat: {
163
+ enabled: this.getCheckbox('settings-heartbeat-enabled'),
164
+ interval: parseInt(this.getValue('settings-heartbeat-interval') || '30', 10) * 60000,
165
+ quiet_start: parseInt(this.getValue('settings-heartbeat-quiet-start') || '23', 10),
166
+ quiet_end: parseInt(this.getValue('settings-heartbeat-quiet-end') || '8', 10),
167
+ },
168
+ agent: {
169
+ model: this.getSelectValue('settings-agent-model'),
170
+ max_turns: parseInt(this.getValue('settings-agent-max-turns') || '10', 10),
171
+ timeout: parseInt(this.getValue('settings-agent-timeout') || '300', 10) * 1000,
172
+ },
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Reset form to current saved values
178
+ */
179
+ resetForm() {
180
+ this.populateForm();
181
+ this.setStatus('Form reset');
182
+ setTimeout(() => this.setStatus(''), 2000);
183
+ }
184
+
185
+ /**
186
+ * Helper: Set checkbox value
187
+ */
188
+ setCheckbox(id, checked) {
189
+ const el = document.getElementById(id);
190
+ if (el) {
191
+ el.checked = !!checked;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Helper: Get checkbox value
197
+ */
198
+ getCheckbox(id) {
199
+ const el = document.getElementById(id);
200
+ return el ? el.checked : false;
201
+ }
202
+
203
+ /**
204
+ * Helper: Set input value
205
+ */
206
+ setValue(id, value) {
207
+ const el = document.getElementById(id);
208
+ if (el) {
209
+ el.value = value;
210
+ }
211
+ }
212
+
213
+ /**
214
+ * Helper: Get input value
215
+ */
216
+ getValue(id) {
217
+ const el = document.getElementById(id);
218
+ return el ? el.value : '';
219
+ }
220
+
221
+ /**
222
+ * Helper: Set select value
223
+ */
224
+ setSelectValue(id, value) {
225
+ const el = document.getElementById(id);
226
+ if (el) {
227
+ el.value = value;
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Helper: Get select value
233
+ */
234
+ getSelectValue(id) {
235
+ const el = document.getElementById(id);
236
+ return el ? el.value : '';
237
+ }
238
+
239
+ /**
240
+ * Set status message
241
+ */
242
+ setStatus(message, type = '') {
243
+ const statusEl = document.getElementById('settings-status');
244
+ if (statusEl) {
245
+ statusEl.textContent = message;
246
+ statusEl.className = `text-sm ${
247
+ type === 'error'
248
+ ? 'text-red-500'
249
+ : type === 'success'
250
+ ? 'text-green-500'
251
+ : 'text-gray-500 dark:text-gray-400'
252
+ }`;
253
+ }
254
+ }
255
+ }