boten-gemma 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/README.md +860 -0
  2. package/dist/automation/cron/index.d.ts +6 -0
  3. package/dist/automation/cron/index.d.ts.map +1 -0
  4. package/dist/automation/cron/index.js +4 -0
  5. package/dist/automation/cron/index.js.map +1 -0
  6. package/dist/automation/cron/parse-schedule.d.ts +11 -0
  7. package/dist/automation/cron/parse-schedule.d.ts.map +1 -0
  8. package/dist/automation/cron/parse-schedule.js +36 -0
  9. package/dist/automation/cron/parse-schedule.js.map +1 -0
  10. package/dist/automation/cron/schedule.d.ts +7 -0
  11. package/dist/automation/cron/schedule.d.ts.map +1 -0
  12. package/dist/automation/cron/schedule.js +28 -0
  13. package/dist/automation/cron/schedule.js.map +1 -0
  14. package/dist/automation/cron/service.d.ts +70 -0
  15. package/dist/automation/cron/service.d.ts.map +1 -0
  16. package/dist/automation/cron/service.js +207 -0
  17. package/dist/automation/cron/service.js.map +1 -0
  18. package/dist/automation/cron/store.d.ts +12 -0
  19. package/dist/automation/cron/store.d.ts.map +1 -0
  20. package/dist/automation/cron/store.js +27 -0
  21. package/dist/automation/cron/store.js.map +1 -0
  22. package/dist/automation/cron/types.d.ts +67 -0
  23. package/dist/automation/cron/types.d.ts.map +1 -0
  24. package/dist/automation/cron/types.js +5 -0
  25. package/dist/automation/cron/types.js.map +1 -0
  26. package/dist/automation/cron.d.ts +15 -0
  27. package/dist/automation/cron.d.ts.map +1 -0
  28. package/dist/automation/cron.js +10 -0
  29. package/dist/automation/cron.js.map +1 -0
  30. package/dist/automation/heartbeat.d.ts +14 -0
  31. package/dist/automation/heartbeat.d.ts.map +1 -0
  32. package/dist/automation/heartbeat.js +27 -0
  33. package/dist/automation/heartbeat.js.map +1 -0
  34. package/dist/channels/cli.d.ts +17 -0
  35. package/dist/channels/cli.d.ts.map +1 -0
  36. package/dist/channels/cli.js +125 -0
  37. package/dist/channels/cli.js.map +1 -0
  38. package/dist/channels/telegram.d.ts +27 -0
  39. package/dist/channels/telegram.d.ts.map +1 -0
  40. package/dist/channels/telegram.js +288 -0
  41. package/dist/channels/telegram.js.map +1 -0
  42. package/dist/channels/types.d.ts +50 -0
  43. package/dist/channels/types.d.ts.map +1 -0
  44. package/dist/channels/types.js +6 -0
  45. package/dist/channels/types.js.map +1 -0
  46. package/dist/channels/web.d.ts +149 -0
  47. package/dist/channels/web.d.ts.map +1 -0
  48. package/dist/channels/web.js +1113 -0
  49. package/dist/channels/web.js.map +1 -0
  50. package/dist/config/defaults.d.ts +11 -0
  51. package/dist/config/defaults.d.ts.map +1 -0
  52. package/dist/config/defaults.js +80 -0
  53. package/dist/config/defaults.js.map +1 -0
  54. package/dist/config/loader.d.ts +22 -0
  55. package/dist/config/loader.d.ts.map +1 -0
  56. package/dist/config/loader.js +158 -0
  57. package/dist/config/loader.js.map +1 -0
  58. package/dist/config/schema.d.ts +261 -0
  59. package/dist/config/schema.d.ts.map +1 -0
  60. package/dist/config/schema.js +119 -0
  61. package/dist/config/schema.js.map +1 -0
  62. package/dist/confirm/audit.d.ts +34 -0
  63. package/dist/confirm/audit.d.ts.map +1 -0
  64. package/dist/confirm/audit.js +49 -0
  65. package/dist/confirm/audit.js.map +1 -0
  66. package/dist/confirm/auto-approve.d.ts +20 -0
  67. package/dist/confirm/auto-approve.d.ts.map +1 -0
  68. package/dist/confirm/auto-approve.js +62 -0
  69. package/dist/confirm/auto-approve.js.map +1 -0
  70. package/dist/confirm/gate.d.ts +50 -0
  71. package/dist/confirm/gate.d.ts.map +1 -0
  72. package/dist/confirm/gate.js +138 -0
  73. package/dist/confirm/gate.js.map +1 -0
  74. package/dist/confirm/parser.d.ts +23 -0
  75. package/dist/confirm/parser.d.ts.map +1 -0
  76. package/dist/confirm/parser.js +76 -0
  77. package/dist/confirm/parser.js.map +1 -0
  78. package/dist/confirm/presenter.d.ts +23 -0
  79. package/dist/confirm/presenter.d.ts.map +1 -0
  80. package/dist/confirm/presenter.js +92 -0
  81. package/dist/confirm/presenter.js.map +1 -0
  82. package/dist/core/agent-loop.d.ts +44 -0
  83. package/dist/core/agent-loop.d.ts.map +1 -0
  84. package/dist/core/agent-loop.js +156 -0
  85. package/dist/core/agent-loop.js.map +1 -0
  86. package/dist/core/compaction.d.ts +17 -0
  87. package/dist/core/compaction.d.ts.map +1 -0
  88. package/dist/core/compaction.js +70 -0
  89. package/dist/core/compaction.js.map +1 -0
  90. package/dist/core/context-builder.d.ts +38 -0
  91. package/dist/core/context-builder.d.ts.map +1 -0
  92. package/dist/core/context-builder.js +137 -0
  93. package/dist/core/context-builder.js.map +1 -0
  94. package/dist/core/logger.d.ts +42 -0
  95. package/dist/core/logger.d.ts.map +1 -0
  96. package/dist/core/logger.js +95 -0
  97. package/dist/core/logger.js.map +1 -0
  98. package/dist/core/queue.d.ts +25 -0
  99. package/dist/core/queue.d.ts.map +1 -0
  100. package/dist/core/queue.js +33 -0
  101. package/dist/core/queue.js.map +1 -0
  102. package/dist/core/router.d.ts +21 -0
  103. package/dist/core/router.d.ts.map +1 -0
  104. package/dist/core/router.js +27 -0
  105. package/dist/core/router.js.map +1 -0
  106. package/dist/core/session-store.d.ts +53 -0
  107. package/dist/core/session-store.d.ts.map +1 -0
  108. package/dist/core/session-store.js +367 -0
  109. package/dist/core/session-store.js.map +1 -0
  110. package/dist/core/session.d.ts +89 -0
  111. package/dist/core/session.d.ts.map +1 -0
  112. package/dist/core/session.js +49 -0
  113. package/dist/core/session.js.map +1 -0
  114. package/dist/daemon/launchd.d.ts +8 -0
  115. package/dist/daemon/launchd.d.ts.map +1 -0
  116. package/dist/daemon/launchd.js +155 -0
  117. package/dist/daemon/launchd.js.map +1 -0
  118. package/dist/daemon/service.d.ts +12 -0
  119. package/dist/daemon/service.d.ts.map +1 -0
  120. package/dist/daemon/service.js +42 -0
  121. package/dist/daemon/service.js.map +1 -0
  122. package/dist/daemon/systemd.d.ts +11 -0
  123. package/dist/daemon/systemd.d.ts.map +1 -0
  124. package/dist/daemon/systemd.js +145 -0
  125. package/dist/daemon/systemd.js.map +1 -0
  126. package/dist/daemon/types.d.ts +14 -0
  127. package/dist/daemon/types.d.ts.map +1 -0
  128. package/dist/daemon/types.js +2 -0
  129. package/dist/daemon/types.js.map +1 -0
  130. package/dist/daemon/update.d.ts +41 -0
  131. package/dist/daemon/update.d.ts.map +1 -0
  132. package/dist/daemon/update.js +106 -0
  133. package/dist/daemon/update.js.map +1 -0
  134. package/dist/gateway.d.ts +103 -0
  135. package/dist/gateway.d.ts.map +1 -0
  136. package/dist/gateway.js +1063 -0
  137. package/dist/gateway.js.map +1 -0
  138. package/dist/index.d.ts +3 -0
  139. package/dist/index.d.ts.map +1 -0
  140. package/dist/index.js +572 -0
  141. package/dist/index.js.map +1 -0
  142. package/dist/llm/auth/oauth-callback.d.ts +20 -0
  143. package/dist/llm/auth/oauth-callback.d.ts.map +1 -0
  144. package/dist/llm/auth/oauth-callback.js +95 -0
  145. package/dist/llm/auth/oauth-callback.js.map +1 -0
  146. package/dist/llm/auth/oauth.d.ts +30 -0
  147. package/dist/llm/auth/oauth.d.ts.map +1 -0
  148. package/dist/llm/auth/oauth.js +331 -0
  149. package/dist/llm/auth/oauth.js.map +1 -0
  150. package/dist/llm/auth/resolver.d.ts +24 -0
  151. package/dist/llm/auth/resolver.d.ts.map +1 -0
  152. package/dist/llm/auth/resolver.js +97 -0
  153. package/dist/llm/auth/resolver.js.map +1 -0
  154. package/dist/llm/auth/token-store.d.ts +15 -0
  155. package/dist/llm/auth/token-store.d.ts.map +1 -0
  156. package/dist/llm/auth/token-store.js +94 -0
  157. package/dist/llm/auth/token-store.js.map +1 -0
  158. package/dist/llm/auth/types.d.ts +20 -0
  159. package/dist/llm/auth/types.d.ts.map +1 -0
  160. package/dist/llm/auth/types.js +3 -0
  161. package/dist/llm/auth/types.js.map +1 -0
  162. package/dist/llm/gemini.d.ts +28 -0
  163. package/dist/llm/gemini.d.ts.map +1 -0
  164. package/dist/llm/gemini.js +524 -0
  165. package/dist/llm/gemini.js.map +1 -0
  166. package/dist/llm/openai-compat.d.ts +14 -0
  167. package/dist/llm/openai-compat.d.ts.map +1 -0
  168. package/dist/llm/openai-compat.js +200 -0
  169. package/dist/llm/openai-compat.js.map +1 -0
  170. package/dist/llm/provider.d.ts +2 -0
  171. package/dist/llm/provider.d.ts.map +1 -0
  172. package/dist/llm/provider.js +4 -0
  173. package/dist/llm/provider.js.map +1 -0
  174. package/dist/llm/types.d.ts +75 -0
  175. package/dist/llm/types.d.ts.map +1 -0
  176. package/dist/llm/types.js +3 -0
  177. package/dist/llm/types.js.map +1 -0
  178. package/dist/mcp/adapter.d.ts +14 -0
  179. package/dist/mcp/adapter.d.ts.map +1 -0
  180. package/dist/mcp/adapter.js +58 -0
  181. package/dist/mcp/adapter.js.map +1 -0
  182. package/dist/mcp/index.d.ts +4 -0
  183. package/dist/mcp/index.d.ts.map +1 -0
  184. package/dist/mcp/index.js +3 -0
  185. package/dist/mcp/index.js.map +1 -0
  186. package/dist/mcp/manager.d.ts +48 -0
  187. package/dist/mcp/manager.d.ts.map +1 -0
  188. package/dist/mcp/manager.js +109 -0
  189. package/dist/mcp/manager.js.map +1 -0
  190. package/dist/memory/daily-log.d.ts +19 -0
  191. package/dist/memory/daily-log.d.ts.map +1 -0
  192. package/dist/memory/daily-log.js +47 -0
  193. package/dist/memory/daily-log.js.map +1 -0
  194. package/dist/memory/memory-manager.d.ts +41 -0
  195. package/dist/memory/memory-manager.d.ts.map +1 -0
  196. package/dist/memory/memory-manager.js +97 -0
  197. package/dist/memory/memory-manager.js.map +1 -0
  198. package/dist/memory/workspace.d.ts +21 -0
  199. package/dist/memory/workspace.d.ts.map +1 -0
  200. package/dist/memory/workspace.js +63 -0
  201. package/dist/memory/workspace.js.map +1 -0
  202. package/dist/panels/bridge.d.ts +19 -0
  203. package/dist/panels/bridge.d.ts.map +1 -0
  204. package/dist/panels/bridge.js +74 -0
  205. package/dist/panels/bridge.js.map +1 -0
  206. package/dist/panels/registry.d.ts +30 -0
  207. package/dist/panels/registry.d.ts.map +1 -0
  208. package/dist/panels/registry.js +102 -0
  209. package/dist/panels/registry.js.map +1 -0
  210. package/dist/panels/routes.d.ts +8 -0
  211. package/dist/panels/routes.d.ts.map +1 -0
  212. package/dist/panels/routes.js +252 -0
  213. package/dist/panels/routes.js.map +1 -0
  214. package/dist/panels/sdk/gemma-panel.js +331 -0
  215. package/dist/panels/service-context.d.ts +28 -0
  216. package/dist/panels/service-context.d.ts.map +1 -0
  217. package/dist/panels/service-context.js +84 -0
  218. package/dist/panels/service-context.js.map +1 -0
  219. package/dist/panels/service-loader.d.ts +19 -0
  220. package/dist/panels/service-loader.d.ts.map +1 -0
  221. package/dist/panels/service-loader.js +61 -0
  222. package/dist/panels/service-loader.js.map +1 -0
  223. package/dist/panels/service-manager.d.ts +40 -0
  224. package/dist/panels/service-manager.d.ts.map +1 -0
  225. package/dist/panels/service-manager.js +148 -0
  226. package/dist/panels/service-manager.js.map +1 -0
  227. package/dist/panels/storage.d.ts +14 -0
  228. package/dist/panels/storage.d.ts.map +1 -0
  229. package/dist/panels/storage.js +47 -0
  230. package/dist/panels/storage.js.map +1 -0
  231. package/dist/panels/types.d.ts +39 -0
  232. package/dist/panels/types.d.ts.map +1 -0
  233. package/dist/panels/types.js +8 -0
  234. package/dist/panels/types.js.map +1 -0
  235. package/dist/shared/ws-types.d.ts +332 -0
  236. package/dist/shared/ws-types.d.ts.map +1 -0
  237. package/dist/shared/ws-types.js +7 -0
  238. package/dist/shared/ws-types.js.map +1 -0
  239. package/dist/skills/gating.d.ts +15 -0
  240. package/dist/skills/gating.d.ts.map +1 -0
  241. package/dist/skills/gating.js +49 -0
  242. package/dist/skills/gating.js.map +1 -0
  243. package/dist/skills/loader.d.ts +32 -0
  244. package/dist/skills/loader.d.ts.map +1 -0
  245. package/dist/skills/loader.js +66 -0
  246. package/dist/skills/loader.js.map +1 -0
  247. package/dist/skills/parser.d.ts +22 -0
  248. package/dist/skills/parser.d.ts.map +1 -0
  249. package/dist/skills/parser.js +29 -0
  250. package/dist/skills/parser.js.map +1 -0
  251. package/dist/skills/prompt-injector.d.ts +10 -0
  252. package/dist/skills/prompt-injector.d.ts.map +1 -0
  253. package/dist/skills/prompt-injector.js +29 -0
  254. package/dist/skills/prompt-injector.js.map +1 -0
  255. package/dist/tools/builtin/cron.d.ts +3 -0
  256. package/dist/tools/builtin/cron.d.ts.map +1 -0
  257. package/dist/tools/builtin/cron.js +198 -0
  258. package/dist/tools/builtin/cron.js.map +1 -0
  259. package/dist/tools/builtin/edit.d.ts +3 -0
  260. package/dist/tools/builtin/edit.d.ts.map +1 -0
  261. package/dist/tools/builtin/edit.js +77 -0
  262. package/dist/tools/builtin/edit.js.map +1 -0
  263. package/dist/tools/builtin/exec.d.ts +3 -0
  264. package/dist/tools/builtin/exec.d.ts.map +1 -0
  265. package/dist/tools/builtin/exec.js +88 -0
  266. package/dist/tools/builtin/exec.js.map +1 -0
  267. package/dist/tools/builtin/panel.d.ts +14 -0
  268. package/dist/tools/builtin/panel.d.ts.map +1 -0
  269. package/dist/tools/builtin/panel.js +521 -0
  270. package/dist/tools/builtin/panel.js.map +1 -0
  271. package/dist/tools/builtin/read.d.ts +3 -0
  272. package/dist/tools/builtin/read.d.ts.map +1 -0
  273. package/dist/tools/builtin/read.js +61 -0
  274. package/dist/tools/builtin/read.js.map +1 -0
  275. package/dist/tools/builtin/web-fetch.d.ts +3 -0
  276. package/dist/tools/builtin/web-fetch.d.ts.map +1 -0
  277. package/dist/tools/builtin/web-fetch.js +68 -0
  278. package/dist/tools/builtin/web-fetch.js.map +1 -0
  279. package/dist/tools/builtin/web-search.d.ts +3 -0
  280. package/dist/tools/builtin/web-search.d.ts.map +1 -0
  281. package/dist/tools/builtin/web-search.js +67 -0
  282. package/dist/tools/builtin/web-search.js.map +1 -0
  283. package/dist/tools/builtin/write.d.ts +3 -0
  284. package/dist/tools/builtin/write.d.ts.map +1 -0
  285. package/dist/tools/builtin/write.js +40 -0
  286. package/dist/tools/builtin/write.js.map +1 -0
  287. package/dist/tools/executor.d.ts +16 -0
  288. package/dist/tools/executor.d.ts.map +1 -0
  289. package/dist/tools/executor.js +142 -0
  290. package/dist/tools/executor.js.map +1 -0
  291. package/dist/tools/registry.d.ts +23 -0
  292. package/dist/tools/registry.d.ts.map +1 -0
  293. package/dist/tools/registry.js +72 -0
  294. package/dist/tools/registry.js.map +1 -0
  295. package/dist/tools/types.d.ts +58 -0
  296. package/dist/tools/types.d.ts.map +1 -0
  297. package/dist/tools/types.js +8 -0
  298. package/dist/tools/types.js.map +1 -0
  299. package/dist/ui/assets/code-block-OCS4YCEC-D5mQabi7.js +2 -0
  300. package/dist/ui/assets/index-0RdIdnZu.js +456 -0
  301. package/dist/ui/assets/index-CjWH8YjU.css +1 -0
  302. package/dist/ui/index.html +16 -0
  303. package/package.json +89 -0
  304. package/skills/coding/SKILL.md +52 -0
  305. package/skills/file-ops/SKILL.md +50 -0
  306. package/skills/panel-dev/SKILL.md +742 -0
  307. package/skills/system-admin/SKILL.md +56 -0
  308. package/skills/web-research/SKILL.md +44 -0
  309. package/templates/BOOTSTRAP.md +19 -0
  310. package/templates/IDENTITY.md +9 -0
  311. package/templates/INSTRUCTIONS.md +19 -0
  312. package/templates/MEMORY.md +5 -0
  313. package/templates/SOUL.md +21 -0
  314. package/templates/TOOLS.md +13 -0
  315. package/templates/USER.md +12 -0
  316. package/templates/panel/gemma-panel-sdk.d.ts +27 -0
  317. package/templates/panel/gemma-panel.d.ts +46 -0
  318. package/templates/panel/index.html +59 -0
  319. package/templates/panel/package.json +15 -0
  320. package/templates/panel/panel.json +12 -0
  321. package/templates/panel/service.ts +69 -0
  322. package/templates/panel/tsconfig.json +17 -0
  323. package/templates/panel/vite.config.ts +13 -0
  324. package/templates/panel-react/index.html +12 -0
  325. package/templates/panel-react/package.json +22 -0
  326. package/templates/panel-react/panel.json +10 -0
  327. package/templates/panel-react/service.ts +69 -0
  328. package/templates/panel-react/src/App.tsx +108 -0
  329. package/templates/panel-react/src/gemma.d.ts +13 -0
  330. package/templates/panel-react/src/main.tsx +9 -0
  331. package/templates/panel-react/src/vite-env.d.ts +1 -0
  332. package/templates/panel-react/tsconfig.json +17 -0
  333. package/templates/panel-react/tsconfig.service.json +16 -0
  334. package/templates/panel-react/vite.config.ts +14 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Structured logger for the Gemma gateway.
3
+ *
4
+ * - Emits log entries to registered listeners (for WebSocket broadcasting)
5
+ * - Keeps a ring buffer of recent entries (for late-joining clients)
6
+ * - Pipes to console for Docker/terminal visibility
7
+ *
8
+ * Usage:
9
+ * import { log } from './logger.js';
10
+ * log.info('gateway', 'Gemma is ready');
11
+ * log.error('llm', 'API call failed', { model, error: err.message });
12
+ */
13
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
14
+ export interface LogEntry {
15
+ id: string;
16
+ level: LogLevel;
17
+ source: string;
18
+ message: string;
19
+ timestamp: string;
20
+ meta?: Record<string, unknown>;
21
+ }
22
+ export type LogListener = (entry: LogEntry) => void;
23
+ declare class Logger {
24
+ private listeners;
25
+ private history;
26
+ private minLevel;
27
+ /** Set minimum log level (entries below this are discarded). */
28
+ setLevel(level: LogLevel): void;
29
+ /** Register a listener that receives every log entry in real time. */
30
+ subscribe(listener: LogListener): () => void;
31
+ /** Get recent log entries (for late-joining UI clients). */
32
+ getHistory(): LogEntry[];
33
+ debug(source: string, message: string, meta?: Record<string, unknown>): void;
34
+ info(source: string, message: string, meta?: Record<string, unknown>): void;
35
+ warn(source: string, message: string, meta?: Record<string, unknown>): void;
36
+ error(source: string, message: string, meta?: Record<string, unknown>): void;
37
+ private emit;
38
+ }
39
+ /** Singleton logger instance for the entire gateway. */
40
+ export declare const log: Logger;
41
+ export {};
42
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE3D,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,QAAQ,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC;AAapD,cAAM,MAAM;IACV,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,QAAQ,CAAqB;IAErC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,sEAAsE;IACtE,SAAS,CAAC,QAAQ,EAAE,WAAW,GAAG,MAAM,IAAI;IAK5C,4DAA4D;IAC5D,UAAU,IAAI,QAAQ,EAAE;IAIxB,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5E,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3E,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI3E,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI5E,OAAO,CAAC,IAAI;CA4Cb;AAED,wDAAwD;AACxD,eAAO,MAAM,GAAG,QAAe,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Structured logger for the Gemma gateway.
3
+ *
4
+ * - Emits log entries to registered listeners (for WebSocket broadcasting)
5
+ * - Keeps a ring buffer of recent entries (for late-joining clients)
6
+ * - Pipes to console for Docker/terminal visibility
7
+ *
8
+ * Usage:
9
+ * import { log } from './logger.js';
10
+ * log.info('gateway', 'Gemma is ready');
11
+ * log.error('llm', 'API call failed', { model, error: err.message });
12
+ */
13
+ const LEVEL_PRIORITY = {
14
+ debug: 0,
15
+ info: 1,
16
+ warn: 2,
17
+ error: 3,
18
+ };
19
+ const MAX_HISTORY = 500;
20
+ let idCounter = 0;
21
+ class Logger {
22
+ listeners = new Set();
23
+ history = [];
24
+ minLevel = 'debug';
25
+ /** Set minimum log level (entries below this are discarded). */
26
+ setLevel(level) {
27
+ this.minLevel = level;
28
+ }
29
+ /** Register a listener that receives every log entry in real time. */
30
+ subscribe(listener) {
31
+ this.listeners.add(listener);
32
+ return () => this.listeners.delete(listener);
33
+ }
34
+ /** Get recent log entries (for late-joining UI clients). */
35
+ getHistory() {
36
+ return [...this.history];
37
+ }
38
+ debug(source, message, meta) {
39
+ this.emit('debug', source, message, meta);
40
+ }
41
+ info(source, message, meta) {
42
+ this.emit('info', source, message, meta);
43
+ }
44
+ warn(source, message, meta) {
45
+ this.emit('warn', source, message, meta);
46
+ }
47
+ error(source, message, meta) {
48
+ this.emit('error', source, message, meta);
49
+ }
50
+ emit(level, source, message, meta) {
51
+ if (LEVEL_PRIORITY[level] < LEVEL_PRIORITY[this.minLevel])
52
+ return;
53
+ const entry = {
54
+ id: `log-${Date.now()}-${++idCounter}`,
55
+ level,
56
+ source,
57
+ message,
58
+ timestamp: new Date().toISOString(),
59
+ meta,
60
+ };
61
+ // Ring buffer
62
+ this.history.push(entry);
63
+ if (this.history.length > MAX_HISTORY) {
64
+ this.history.shift();
65
+ }
66
+ // Console output (always, for Docker/terminal)
67
+ const prefix = `[${source}]`;
68
+ switch (level) {
69
+ case 'debug':
70
+ console.debug(prefix, message);
71
+ break;
72
+ case 'info':
73
+ console.log(prefix, message);
74
+ break;
75
+ case 'warn':
76
+ console.warn(prefix, message);
77
+ break;
78
+ case 'error':
79
+ console.error(prefix, message);
80
+ break;
81
+ }
82
+ // Notify listeners
83
+ for (const listener of this.listeners) {
84
+ try {
85
+ listener(entry);
86
+ }
87
+ catch {
88
+ // Never let a listener crash the logger
89
+ }
90
+ }
91
+ }
92
+ }
93
+ /** Singleton logger instance for the entire gateway. */
94
+ export const log = new Logger();
95
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { IncomingMessage } from '../channels/types.js';
2
+ export type QueueMode = 'collect' | 'steer';
3
+ export interface MessageQueue {
4
+ mode: QueueMode;
5
+ enqueue(message: IncomingMessage): boolean;
6
+ drain(): IncomingMessage[];
7
+ peek(): IncomingMessage | undefined;
8
+ isEmpty(): boolean;
9
+ size(): number;
10
+ }
11
+ /**
12
+ * Default message queue implementation.
13
+ * - collect mode: buffer messages, process after current run completes
14
+ * - steer mode: inject new message mid-run (future enhancement)
15
+ */
16
+ export declare class DefaultMessageQueue implements MessageQueue {
17
+ mode: QueueMode;
18
+ private queue;
19
+ enqueue(message: IncomingMessage): boolean;
20
+ drain(): IncomingMessage[];
21
+ peek(): IncomingMessage | undefined;
22
+ isEmpty(): boolean;
23
+ size(): number;
24
+ }
25
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/core/queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAI5C,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC;IAC3C,KAAK,IAAI,eAAe,EAAE,CAAC;IAC3B,IAAI,IAAI,eAAe,GAAG,SAAS,CAAC;IACpC,OAAO,IAAI,OAAO,CAAC;IACnB,IAAI,IAAI,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,YAAW,YAAY;IACtD,IAAI,EAAE,SAAS,CAAa;IAC5B,OAAO,CAAC,KAAK,CAAyB;IAEtC,OAAO,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO;IAS1C,KAAK,IAAI,eAAe,EAAE;IAK1B,IAAI,IAAI,eAAe,GAAG,SAAS;IAInC,OAAO,IAAI,OAAO;IAIlB,IAAI,IAAI,MAAM;CAGf"}
@@ -0,0 +1,33 @@
1
+ // src/core/queue.ts — Per-session message queue
2
+ const MAX_QUEUE_SIZE = 10;
3
+ /**
4
+ * Default message queue implementation.
5
+ * - collect mode: buffer messages, process after current run completes
6
+ * - steer mode: inject new message mid-run (future enhancement)
7
+ */
8
+ export class DefaultMessageQueue {
9
+ mode = 'collect';
10
+ queue = [];
11
+ enqueue(message) {
12
+ if (this.queue.length >= MAX_QUEUE_SIZE) {
13
+ // Drop oldest message when queue is full
14
+ this.queue.shift();
15
+ }
16
+ this.queue.push(message);
17
+ return true;
18
+ }
19
+ drain() {
20
+ const messages = this.queue.splice(0);
21
+ return messages;
22
+ }
23
+ peek() {
24
+ return this.queue[0];
25
+ }
26
+ isEmpty() {
27
+ return this.queue.length === 0;
28
+ }
29
+ size() {
30
+ return this.queue.length;
31
+ }
32
+ }
33
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/core/queue.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAMhD,MAAM,cAAc,GAAG,EAAE,CAAC;AAW1B;;;;GAIG;AACH,MAAM,OAAO,mBAAmB;IAC9B,IAAI,GAAc,SAAS,CAAC;IACpB,KAAK,GAAsB,EAAE,CAAC;IAEtC,OAAO,CAAC,OAAwB;QAC9B,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,cAAc,EAAE,CAAC;YACxC,yCAAyC;YACzC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,IAAI;QACF,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ import type { Session } from './session.js';
2
+ import type { IncomingMessage } from '../channels/types.js';
3
+ import type { SessionStore } from './session-store.js';
4
+ import { type MessageQueue } from './queue.js';
5
+ export interface Router {
6
+ route(message: IncomingMessage): Promise<Session>;
7
+ getQueue(session: Session): MessageQueue;
8
+ }
9
+ /**
10
+ * Default router implementation.
11
+ * Routes messages to sessions based on channel + sender.
12
+ * Each session gets its own message queue.
13
+ */
14
+ export declare class DefaultRouter implements Router {
15
+ private readonly sessionStore;
16
+ private queues;
17
+ constructor(sessionStore: SessionStore);
18
+ route(message: IncomingMessage): Promise<Session>;
19
+ getQueue(session: Session): MessageQueue;
20
+ }
21
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC;CAC1C;AAED;;;;GAIG;AACH,qBAAa,aAAc,YAAW,MAAM;IAG9B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAFzC,OAAO,CAAC,MAAM,CAAmC;gBAEpB,YAAY,EAAE,YAAY;IAEjD,KAAK,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY;CASzC"}
@@ -0,0 +1,27 @@
1
+ // src/core/router.ts — Route incoming messages to sessions
2
+ import { DefaultMessageQueue } from './queue.js';
3
+ /**
4
+ * Default router implementation.
5
+ * Routes messages to sessions based on channel + sender.
6
+ * Each session gets its own message queue.
7
+ */
8
+ export class DefaultRouter {
9
+ sessionStore;
10
+ queues = new Map();
11
+ constructor(sessionStore) {
12
+ this.sessionStore = sessionStore;
13
+ }
14
+ async route(message) {
15
+ return await this.sessionStore.resolve(message.channelType, message.senderId);
16
+ }
17
+ getQueue(session) {
18
+ const key = session.id;
19
+ let queue = this.queues.get(key);
20
+ if (!queue) {
21
+ queue = new DefaultMessageQueue();
22
+ this.queues.set(key, queue);
23
+ }
24
+ return queue;
25
+ }
26
+ }
27
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/core/router.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAK3D,OAAO,EAAE,mBAAmB,EAAqB,MAAM,YAAY,CAAC;AAOpE;;;;GAIG;AACH,MAAM,OAAO,aAAa;IAGK;IAFrB,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAEjD,YAA6B,YAA0B;QAA1B,iBAAY,GAAZ,YAAY,CAAc;IAAG,CAAC;IAE3D,KAAK,CAAC,KAAK,CAAC,OAAwB;QAClC,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAChF,CAAC;IAED,QAAQ,CAAC,OAAgB;QACvB,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC;QACvB,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,IAAI,mBAAmB,EAAE,CAAC;YAClC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
@@ -0,0 +1,53 @@
1
+ import { type Session, type SessionMetadata, type TranscriptEntry } from './session.js';
2
+ export interface SessionStore {
3
+ resolve(channel: string, senderId: string): Promise<Session>;
4
+ save(session: Session): Promise<void>;
5
+ appendTranscript(sessionId: string, entry: TranscriptEntry): Promise<void>;
6
+ list(): Promise<Session[]>;
7
+ delete(sessionId: string): Promise<void>;
8
+ }
9
+ /**
10
+ * File-based session store using JSONL transcripts.
11
+ * Sessions are stored in ~/.gemma/sessions/<sessionId>.jsonl
12
+ */
13
+ export declare class FileSessionStore implements SessionStore {
14
+ private sessions;
15
+ private sessionsDir;
16
+ constructor(gemmaHome: string);
17
+ /**
18
+ * Get or create a session for the given channel + sender.
19
+ * Sessions are keyed by "channel:senderId" to ensure one session
20
+ * per channel per sender.
21
+ */
22
+ resolve(channel: string, senderId: string): Promise<Session>;
23
+ /**
24
+ * Resolve a web session by its session ID.
25
+ * If sessionId is provided and exists, return it.
26
+ * Otherwise, create a new web session.
27
+ */
28
+ resolveWebSession(sessionId?: string): Promise<Session>;
29
+ /**
30
+ * Save session metadata alongside the JSONL file.
31
+ */
32
+ saveMetadata(session: Session): Promise<void>;
33
+ /**
34
+ * List all web sessions, sorted by lastActiveAt descending.
35
+ */
36
+ listWebSessions(): Promise<SessionMetadata[]>;
37
+ /**
38
+ * Load a session by its session ID from disk.
39
+ * Looks for {sessionId}.jsonl file.
40
+ */
41
+ loadById(sessionId: string): Promise<Session | null>;
42
+ /**
43
+ * Rename a session's title in memory and on disk.
44
+ */
45
+ renameSession(sessionId: string, title: string): Promise<void>;
46
+ save(session: Session): Promise<void>;
47
+ appendTranscript(sessionId: string, entry: TranscriptEntry): Promise<void>;
48
+ list(): Promise<Session[]>;
49
+ delete(sessionId: string): Promise<void>;
50
+ private loadLatestSession;
51
+ private loadTranscript;
52
+ }
53
+ //# sourceMappingURL=session-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/core/session-store.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmC,KAAK,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzH,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IACnD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,WAAW,CAAS;gBAEhB,SAAS,EAAE,MAAM;IAI7B;;;;OAIG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BlE;;;;OAIG;IACG,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2B7D;;OAEG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAenD;;OAEG;IACG,eAAe,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IA4BnD;;;OAGG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAwG1D;;OAEG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB9D,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrC,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAc1E,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAI1B,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YA0BhC,iBAAiB;YAqBjB,cAAc;CAsD7B"}