openryoko 0.9.4-ryoko.2

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 (514) hide show
  1. package/dist/bin/jimmy.d.ts +3 -0
  2. package/dist/bin/jimmy.d.ts.map +1 -0
  3. package/dist/bin/jimmy.js +149 -0
  4. package/dist/bin/jimmy.js.map +1 -0
  5. package/dist/package.json +54 -0
  6. package/dist/src/cli/__tests__/migrate.test.d.ts +2 -0
  7. package/dist/src/cli/__tests__/migrate.test.d.ts.map +1 -0
  8. package/dist/src/cli/__tests__/migrate.test.js +79 -0
  9. package/dist/src/cli/__tests__/migrate.test.js.map +1 -0
  10. package/dist/src/cli/chrome-allow.d.ts +5 -0
  11. package/dist/src/cli/chrome-allow.d.ts.map +1 -0
  12. package/dist/src/cli/chrome-allow.js +250 -0
  13. package/dist/src/cli/chrome-allow.js.map +1 -0
  14. package/dist/src/cli/create.d.ts +2 -0
  15. package/dist/src/cli/create.d.ts.map +1 -0
  16. package/dist/src/cli/create.js +72 -0
  17. package/dist/src/cli/create.js.map +1 -0
  18. package/dist/src/cli/instances.d.ts +14 -0
  19. package/dist/src/cli/instances.d.ts.map +1 -0
  20. package/dist/src/cli/instances.js +43 -0
  21. package/dist/src/cli/instances.js.map +1 -0
  22. package/dist/src/cli/list.d.ts +2 -0
  23. package/dist/src/cli/list.d.ts.map +1 -0
  24. package/dist/src/cli/list.js +38 -0
  25. package/dist/src/cli/list.js.map +1 -0
  26. package/dist/src/cli/migrate.d.ts +5 -0
  27. package/dist/src/cli/migrate.d.ts.map +1 -0
  28. package/dist/src/cli/migrate.js +222 -0
  29. package/dist/src/cli/migrate.js.map +1 -0
  30. package/dist/src/cli/nuke.d.ts +2 -0
  31. package/dist/src/cli/nuke.d.ts.map +1 -0
  32. package/dist/src/cli/nuke.js +91 -0
  33. package/dist/src/cli/nuke.js.map +1 -0
  34. package/dist/src/cli/remove.d.ts +4 -0
  35. package/dist/src/cli/remove.d.ts.map +1 -0
  36. package/dist/src/cli/remove.js +47 -0
  37. package/dist/src/cli/remove.js.map +1 -0
  38. package/dist/src/cli/setup.d.ts +4 -0
  39. package/dist/src/cli/setup.d.ts.map +1 -0
  40. package/dist/src/cli/setup.js +491 -0
  41. package/dist/src/cli/setup.js.map +1 -0
  42. package/dist/src/cli/skills.d.ts +28 -0
  43. package/dist/src/cli/skills.d.ts.map +1 -0
  44. package/dist/src/cli/skills.js +284 -0
  45. package/dist/src/cli/skills.js.map +1 -0
  46. package/dist/src/cli/start.d.ts +5 -0
  47. package/dist/src/cli/start.d.ts.map +1 -0
  48. package/dist/src/cli/start.js +34 -0
  49. package/dist/src/cli/start.js.map +1 -0
  50. package/dist/src/cli/status.d.ts +2 -0
  51. package/dist/src/cli/status.d.ts.map +1 -0
  52. package/dist/src/cli/status.js +69 -0
  53. package/dist/src/cli/status.js.map +1 -0
  54. package/dist/src/cli/stop.d.ts +2 -0
  55. package/dist/src/cli/stop.d.ts.map +1 -0
  56. package/dist/src/cli/stop.js +11 -0
  57. package/dist/src/cli/stop.js.map +1 -0
  58. package/dist/src/connectors/cron/index.d.ts +21 -0
  59. package/dist/src/connectors/cron/index.d.ts.map +1 -0
  60. package/dist/src/connectors/cron/index.js +75 -0
  61. package/dist/src/connectors/cron/index.js.map +1 -0
  62. package/dist/src/connectors/discord/format.d.ts +3 -0
  63. package/dist/src/connectors/discord/format.d.ts.map +1 -0
  64. package/dist/src/connectors/discord/format.js +33 -0
  65. package/dist/src/connectors/discord/format.js.map +1 -0
  66. package/dist/src/connectors/discord/index.d.ts +47 -0
  67. package/dist/src/connectors/discord/index.d.ts.map +1 -0
  68. package/dist/src/connectors/discord/index.js +308 -0
  69. package/dist/src/connectors/discord/index.js.map +1 -0
  70. package/dist/src/connectors/discord/remote.d.ts +33 -0
  71. package/dist/src/connectors/discord/remote.d.ts.map +1 -0
  72. package/dist/src/connectors/discord/remote.js +89 -0
  73. package/dist/src/connectors/discord/remote.js.map +1 -0
  74. package/dist/src/connectors/discord/threads.d.ts +5 -0
  75. package/dist/src/connectors/discord/threads.d.ts.map +1 -0
  76. package/dist/src/connectors/discord/threads.js +22 -0
  77. package/dist/src/connectors/discord/threads.js.map +1 -0
  78. package/dist/src/connectors/slack/__tests__/active-threads.test.d.ts +2 -0
  79. package/dist/src/connectors/slack/__tests__/active-threads.test.d.ts.map +1 -0
  80. package/dist/src/connectors/slack/__tests__/active-threads.test.js +57 -0
  81. package/dist/src/connectors/slack/__tests__/active-threads.test.js.map +1 -0
  82. package/dist/src/connectors/slack/__tests__/format.test.d.ts +2 -0
  83. package/dist/src/connectors/slack/__tests__/format.test.d.ts.map +1 -0
  84. package/dist/src/connectors/slack/__tests__/format.test.js +115 -0
  85. package/dist/src/connectors/slack/__tests__/format.test.js.map +1 -0
  86. package/dist/src/connectors/slack/__tests__/speaker.test.d.ts +2 -0
  87. package/dist/src/connectors/slack/__tests__/speaker.test.d.ts.map +1 -0
  88. package/dist/src/connectors/slack/__tests__/speaker.test.js +59 -0
  89. package/dist/src/connectors/slack/__tests__/speaker.test.js.map +1 -0
  90. package/dist/src/connectors/slack/__tests__/triage-prompt.test.d.ts +2 -0
  91. package/dist/src/connectors/slack/__tests__/triage-prompt.test.d.ts.map +1 -0
  92. package/dist/src/connectors/slack/__tests__/triage-prompt.test.js +102 -0
  93. package/dist/src/connectors/slack/__tests__/triage-prompt.test.js.map +1 -0
  94. package/dist/src/connectors/slack/__tests__/triage.test.d.ts +2 -0
  95. package/dist/src/connectors/slack/__tests__/triage.test.d.ts.map +1 -0
  96. package/dist/src/connectors/slack/__tests__/triage.test.js +88 -0
  97. package/dist/src/connectors/slack/__tests__/triage.test.js.map +1 -0
  98. package/dist/src/connectors/slack/active-threads.d.ts +39 -0
  99. package/dist/src/connectors/slack/active-threads.d.ts.map +1 -0
  100. package/dist/src/connectors/slack/active-threads.js +71 -0
  101. package/dist/src/connectors/slack/active-threads.js.map +1 -0
  102. package/dist/src/connectors/slack/format.d.ts +17 -0
  103. package/dist/src/connectors/slack/format.d.ts.map +1 -0
  104. package/dist/src/connectors/slack/format.js +85 -0
  105. package/dist/src/connectors/slack/format.js.map +1 -0
  106. package/dist/src/connectors/slack/index.d.ts +51 -0
  107. package/dist/src/connectors/slack/index.d.ts.map +1 -0
  108. package/dist/src/connectors/slack/index.js +562 -0
  109. package/dist/src/connectors/slack/index.js.map +1 -0
  110. package/dist/src/connectors/slack/speaker.d.ts +39 -0
  111. package/dist/src/connectors/slack/speaker.d.ts.map +1 -0
  112. package/dist/src/connectors/slack/speaker.js +30 -0
  113. package/dist/src/connectors/slack/speaker.js.map +1 -0
  114. package/dist/src/connectors/slack/threads.d.ts +12 -0
  115. package/dist/src/connectors/slack/threads.d.ts.map +1 -0
  116. package/dist/src/connectors/slack/threads.js +41 -0
  117. package/dist/src/connectors/slack/threads.js.map +1 -0
  118. package/dist/src/connectors/slack/threads.test.d.ts +2 -0
  119. package/dist/src/connectors/slack/threads.test.d.ts.map +1 -0
  120. package/dist/src/connectors/slack/threads.test.js +79 -0
  121. package/dist/src/connectors/slack/threads.test.js.map +1 -0
  122. package/dist/src/connectors/slack/triage-prompt.d.ts +50 -0
  123. package/dist/src/connectors/slack/triage-prompt.d.ts.map +1 -0
  124. package/dist/src/connectors/slack/triage-prompt.js +127 -0
  125. package/dist/src/connectors/slack/triage-prompt.js.map +1 -0
  126. package/dist/src/connectors/slack/triage.d.ts +41 -0
  127. package/dist/src/connectors/slack/triage.d.ts.map +1 -0
  128. package/dist/src/connectors/slack/triage.js +120 -0
  129. package/dist/src/connectors/slack/triage.js.map +1 -0
  130. package/dist/src/connectors/telegram/__tests__/connector.test.d.ts +2 -0
  131. package/dist/src/connectors/telegram/__tests__/connector.test.d.ts.map +1 -0
  132. package/dist/src/connectors/telegram/__tests__/connector.test.js +257 -0
  133. package/dist/src/connectors/telegram/__tests__/connector.test.js.map +1 -0
  134. package/dist/src/connectors/telegram/__tests__/format.test.d.ts +2 -0
  135. package/dist/src/connectors/telegram/__tests__/format.test.d.ts.map +1 -0
  136. package/dist/src/connectors/telegram/__tests__/format.test.js +79 -0
  137. package/dist/src/connectors/telegram/__tests__/format.test.js.map +1 -0
  138. package/dist/src/connectors/telegram/__tests__/threads.test.d.ts +2 -0
  139. package/dist/src/connectors/telegram/__tests__/threads.test.d.ts.map +1 -0
  140. package/dist/src/connectors/telegram/__tests__/threads.test.js +51 -0
  141. package/dist/src/connectors/telegram/__tests__/threads.test.js.map +1 -0
  142. package/dist/src/connectors/telegram/format.d.ts +12 -0
  143. package/dist/src/connectors/telegram/format.d.ts.map +1 -0
  144. package/dist/src/connectors/telegram/format.js +61 -0
  145. package/dist/src/connectors/telegram/format.js.map +1 -0
  146. package/dist/src/connectors/telegram/index.d.ts +28 -0
  147. package/dist/src/connectors/telegram/index.d.ts.map +1 -0
  148. package/dist/src/connectors/telegram/index.js +213 -0
  149. package/dist/src/connectors/telegram/index.js.map +1 -0
  150. package/dist/src/connectors/telegram/threads.d.ts +29 -0
  151. package/dist/src/connectors/telegram/threads.d.ts.map +1 -0
  152. package/dist/src/connectors/telegram/threads.js +26 -0
  153. package/dist/src/connectors/telegram/threads.js.map +1 -0
  154. package/dist/src/connectors/whatsapp/__tests__/format.test.d.ts +2 -0
  155. package/dist/src/connectors/whatsapp/__tests__/format.test.d.ts.map +1 -0
  156. package/dist/src/connectors/whatsapp/__tests__/format.test.js +70 -0
  157. package/dist/src/connectors/whatsapp/__tests__/format.test.js.map +1 -0
  158. package/dist/src/connectors/whatsapp/format.d.ts +12 -0
  159. package/dist/src/connectors/whatsapp/format.d.ts.map +1 -0
  160. package/dist/src/connectors/whatsapp/format.js +53 -0
  161. package/dist/src/connectors/whatsapp/format.js.map +1 -0
  162. package/dist/src/connectors/whatsapp/index.d.ts +42 -0
  163. package/dist/src/connectors/whatsapp/index.d.ts.map +1 -0
  164. package/dist/src/connectors/whatsapp/index.js +279 -0
  165. package/dist/src/connectors/whatsapp/index.js.map +1 -0
  166. package/dist/src/cron/jobs.d.ts +5 -0
  167. package/dist/src/cron/jobs.d.ts.map +1 -0
  168. package/dist/src/cron/jobs.js +23 -0
  169. package/dist/src/cron/jobs.js.map +1 -0
  170. package/dist/src/cron/runner.d.ts +4 -0
  171. package/dist/src/cron/runner.d.ts.map +1 -0
  172. package/dist/src/cron/runner.js +88 -0
  173. package/dist/src/cron/runner.js.map +1 -0
  174. package/dist/src/cron/scheduler.d.ts +8 -0
  175. package/dist/src/cron/scheduler.d.ts.map +1 -0
  176. package/dist/src/cron/scheduler.js +64 -0
  177. package/dist/src/cron/scheduler.js.map +1 -0
  178. package/dist/src/engines/__tests__/gemini.test.d.ts +2 -0
  179. package/dist/src/engines/__tests__/gemini.test.d.ts.map +1 -0
  180. package/dist/src/engines/__tests__/gemini.test.js +404 -0
  181. package/dist/src/engines/__tests__/gemini.test.js.map +1 -0
  182. package/dist/src/engines/claude.d.ts +20 -0
  183. package/dist/src/engines/claude.d.ts.map +1 -0
  184. package/dist/src/engines/claude.js +520 -0
  185. package/dist/src/engines/claude.js.map +1 -0
  186. package/dist/src/engines/codex.d.ts +15 -0
  187. package/dist/src/engines/codex.d.ts.map +1 -0
  188. package/dist/src/engines/codex.js +351 -0
  189. package/dist/src/engines/codex.js.map +1 -0
  190. package/dist/src/engines/gemini.d.ts +32 -0
  191. package/dist/src/engines/gemini.d.ts.map +1 -0
  192. package/dist/src/engines/gemini.js +328 -0
  193. package/dist/src/engines/gemini.js.map +1 -0
  194. package/dist/src/engines/mock.d.ts +16 -0
  195. package/dist/src/engines/mock.d.ts.map +1 -0
  196. package/dist/src/engines/mock.js +47 -0
  197. package/dist/src/engines/mock.js.map +1 -0
  198. package/dist/src/gateway/__tests__/api-last-n.test.d.ts +2 -0
  199. package/dist/src/gateway/__tests__/api-last-n.test.d.ts.map +1 -0
  200. package/dist/src/gateway/__tests__/api-last-n.test.js +32 -0
  201. package/dist/src/gateway/__tests__/api-last-n.test.js.map +1 -0
  202. package/dist/src/gateway/__tests__/costs.test.d.ts +2 -0
  203. package/dist/src/gateway/__tests__/costs.test.d.ts.map +1 -0
  204. package/dist/src/gateway/__tests__/costs.test.js +32 -0
  205. package/dist/src/gateway/__tests__/costs.test.js.map +1 -0
  206. package/dist/src/gateway/__tests__/org-hierarchy.test.d.ts +2 -0
  207. package/dist/src/gateway/__tests__/org-hierarchy.test.d.ts.map +1 -0
  208. package/dist/src/gateway/__tests__/org-hierarchy.test.js +161 -0
  209. package/dist/src/gateway/__tests__/org-hierarchy.test.js.map +1 -0
  210. package/dist/src/gateway/__tests__/org-update.test.d.ts +2 -0
  211. package/dist/src/gateway/__tests__/org-update.test.d.ts.map +1 -0
  212. package/dist/src/gateway/__tests__/org-update.test.js +99 -0
  213. package/dist/src/gateway/__tests__/org-update.test.js.map +1 -0
  214. package/dist/src/gateway/__tests__/org.test.d.ts +2 -0
  215. package/dist/src/gateway/__tests__/org.test.d.ts.map +1 -0
  216. package/dist/src/gateway/__tests__/org.test.js +77 -0
  217. package/dist/src/gateway/__tests__/org.test.js.map +1 -0
  218. package/dist/src/gateway/__tests__/services.test.d.ts +2 -0
  219. package/dist/src/gateway/__tests__/services.test.d.ts.map +1 -0
  220. package/dist/src/gateway/__tests__/services.test.js +153 -0
  221. package/dist/src/gateway/__tests__/services.test.js.map +1 -0
  222. package/dist/src/gateway/api.d.ts +19 -0
  223. package/dist/src/gateway/api.d.ts.map +1 -0
  224. package/dist/src/gateway/api.js +2261 -0
  225. package/dist/src/gateway/api.js.map +1 -0
  226. package/dist/src/gateway/budgets.d.ts +16 -0
  227. package/dist/src/gateway/budgets.d.ts.map +1 -0
  228. package/dist/src/gateway/budgets.js +39 -0
  229. package/dist/src/gateway/budgets.js.map +1 -0
  230. package/dist/src/gateway/costs.d.ts +19 -0
  231. package/dist/src/gateway/costs.d.ts.map +1 -0
  232. package/dist/src/gateway/costs.js +39 -0
  233. package/dist/src/gateway/costs.js.map +1 -0
  234. package/dist/src/gateway/daemon-entry.d.ts +2 -0
  235. package/dist/src/gateway/daemon-entry.d.ts.map +1 -0
  236. package/dist/src/gateway/daemon-entry.js +12 -0
  237. package/dist/src/gateway/daemon-entry.js.map +1 -0
  238. package/dist/src/gateway/files.d.ts +6 -0
  239. package/dist/src/gateway/files.d.ts.map +1 -0
  240. package/dist/src/gateway/files.js +442 -0
  241. package/dist/src/gateway/files.js.map +1 -0
  242. package/dist/src/gateway/goals.d.ts +11 -0
  243. package/dist/src/gateway/goals.d.ts.map +1 -0
  244. package/dist/src/gateway/goals.js +72 -0
  245. package/dist/src/gateway/goals.js.map +1 -0
  246. package/dist/src/gateway/lifecycle.d.ts +10 -0
  247. package/dist/src/gateway/lifecycle.d.ts.map +1 -0
  248. package/dist/src/gateway/lifecycle.js +152 -0
  249. package/dist/src/gateway/lifecycle.js.map +1 -0
  250. package/dist/src/gateway/org-hierarchy.d.ts +5 -0
  251. package/dist/src/gateway/org-hierarchy.d.ts.map +1 -0
  252. package/dist/src/gateway/org-hierarchy.js +174 -0
  253. package/dist/src/gateway/org-hierarchy.js.map +1 -0
  254. package/dist/src/gateway/org.d.ts +17 -0
  255. package/dist/src/gateway/org.d.ts.map +1 -0
  256. package/dist/src/gateway/org.js +136 -0
  257. package/dist/src/gateway/org.js.map +1 -0
  258. package/dist/src/gateway/server.d.ts +4 -0
  259. package/dist/src/gateway/server.d.ts.map +1 -0
  260. package/dist/src/gateway/server.js +764 -0
  261. package/dist/src/gateway/server.js.map +1 -0
  262. package/dist/src/gateway/services.d.ts +28 -0
  263. package/dist/src/gateway/services.d.ts.map +1 -0
  264. package/dist/src/gateway/services.js +112 -0
  265. package/dist/src/gateway/services.js.map +1 -0
  266. package/dist/src/gateway/watcher.d.ts +14 -0
  267. package/dist/src/gateway/watcher.d.ts.map +1 -0
  268. package/dist/src/gateway/watcher.js +111 -0
  269. package/dist/src/gateway/watcher.js.map +1 -0
  270. package/dist/src/index.d.ts +5 -0
  271. package/dist/src/index.d.ts.map +1 -0
  272. package/dist/src/index.js +4 -0
  273. package/dist/src/index.js.map +1 -0
  274. package/dist/src/mcp/gateway-server.d.ts +13 -0
  275. package/dist/src/mcp/gateway-server.d.ts.map +1 -0
  276. package/dist/src/mcp/gateway-server.js +376 -0
  277. package/dist/src/mcp/gateway-server.js.map +1 -0
  278. package/dist/src/mcp/resolver.d.ts +19 -0
  279. package/dist/src/mcp/resolver.d.ts.map +1 -0
  280. package/dist/src/mcp/resolver.js +159 -0
  281. package/dist/src/mcp/resolver.js.map +1 -0
  282. package/dist/src/sessions/__tests__/callbacks.test.d.ts +2 -0
  283. package/dist/src/sessions/__tests__/callbacks.test.d.ts.map +1 -0
  284. package/dist/src/sessions/__tests__/callbacks.test.js +154 -0
  285. package/dist/src/sessions/__tests__/callbacks.test.js.map +1 -0
  286. package/dist/src/sessions/callbacks.d.ts +31 -0
  287. package/dist/src/sessions/callbacks.d.ts.map +1 -0
  288. package/dist/src/sessions/callbacks.js +112 -0
  289. package/dist/src/sessions/callbacks.js.map +1 -0
  290. package/dist/src/sessions/context.d.ts +36 -0
  291. package/dist/src/sessions/context.d.ts.map +1 -0
  292. package/dist/src/sessions/context.js +741 -0
  293. package/dist/src/sessions/context.js.map +1 -0
  294. package/dist/src/sessions/fork.d.ts +30 -0
  295. package/dist/src/sessions/fork.d.ts.map +1 -0
  296. package/dist/src/sessions/fork.js +178 -0
  297. package/dist/src/sessions/fork.js.map +1 -0
  298. package/dist/src/sessions/manager.d.ts +27 -0
  299. package/dist/src/sessions/manager.d.ts.map +1 -0
  300. package/dist/src/sessions/manager.js +751 -0
  301. package/dist/src/sessions/manager.js.map +1 -0
  302. package/dist/src/sessions/queue.d.ts +36 -0
  303. package/dist/src/sessions/queue.d.ts.map +1 -0
  304. package/dist/src/sessions/queue.js +101 -0
  305. package/dist/src/sessions/queue.js.map +1 -0
  306. package/dist/src/sessions/queue.test.d.ts +2 -0
  307. package/dist/src/sessions/queue.test.d.ts.map +1 -0
  308. package/dist/src/sessions/queue.test.js +28 -0
  309. package/dist/src/sessions/queue.test.js.map +1 -0
  310. package/dist/src/sessions/registry.d.ts +116 -0
  311. package/dist/src/sessions/registry.d.ts.map +1 -0
  312. package/dist/src/sessions/registry.js +480 -0
  313. package/dist/src/sessions/registry.js.map +1 -0
  314. package/dist/src/sessions/registry.test.d.ts +2 -0
  315. package/dist/src/sessions/registry.test.d.ts.map +1 -0
  316. package/dist/src/sessions/registry.test.js +41 -0
  317. package/dist/src/sessions/registry.test.js.map +1 -0
  318. package/dist/src/shared/__tests__/rateLimit.test.d.ts +2 -0
  319. package/dist/src/shared/__tests__/rateLimit.test.d.ts.map +1 -0
  320. package/dist/src/shared/__tests__/rateLimit.test.js +108 -0
  321. package/dist/src/shared/__tests__/rateLimit.test.js.map +1 -0
  322. package/dist/src/shared/__tests__/usageAwareness.test.d.ts +2 -0
  323. package/dist/src/shared/__tests__/usageAwareness.test.d.ts.map +1 -0
  324. package/dist/src/shared/__tests__/usageAwareness.test.js +58 -0
  325. package/dist/src/shared/__tests__/usageAwareness.test.js.map +1 -0
  326. package/dist/src/shared/config.d.ts +3 -0
  327. package/dist/src/shared/config.d.ts.map +1 -0
  328. package/dist/src/shared/config.js +11 -0
  329. package/dist/src/shared/config.js.map +1 -0
  330. package/dist/src/shared/effort.d.ts +17 -0
  331. package/dist/src/shared/effort.d.ts.map +1 -0
  332. package/dist/src/shared/effort.js +44 -0
  333. package/dist/src/shared/effort.js.map +1 -0
  334. package/dist/src/shared/logger.d.ts +12 -0
  335. package/dist/src/shared/logger.d.ts.map +1 -0
  336. package/dist/src/shared/logger.js +35 -0
  337. package/dist/src/shared/logger.js.map +1 -0
  338. package/dist/src/shared/paths.d.ts +31 -0
  339. package/dist/src/shared/paths.d.ts.map +1 -0
  340. package/dist/src/shared/paths.js +92 -0
  341. package/dist/src/shared/paths.js.map +1 -0
  342. package/dist/src/shared/rateLimit.d.ts +20 -0
  343. package/dist/src/shared/rateLimit.d.ts.map +1 -0
  344. package/dist/src/shared/rateLimit.js +61 -0
  345. package/dist/src/shared/rateLimit.js.map +1 -0
  346. package/dist/src/shared/types.d.ts +448 -0
  347. package/dist/src/shared/types.d.ts.map +1 -0
  348. package/dist/src/shared/types.js +4 -0
  349. package/dist/src/shared/types.js.map +1 -0
  350. package/dist/src/shared/usageAwareness.d.ts +10 -0
  351. package/dist/src/shared/usageAwareness.d.ts.map +1 -0
  352. package/dist/src/shared/usageAwareness.js +69 -0
  353. package/dist/src/shared/usageAwareness.js.map +1 -0
  354. package/dist/src/shared/version.d.ts +15 -0
  355. package/dist/src/shared/version.d.ts.map +1 -0
  356. package/dist/src/shared/version.js +56 -0
  357. package/dist/src/shared/version.js.map +1 -0
  358. package/dist/src/stt/stt.d.ts +24 -0
  359. package/dist/src/stt/stt.d.ts.map +1 -0
  360. package/dist/src/stt/stt.js +203 -0
  361. package/dist/src/stt/stt.js.map +1 -0
  362. package/dist/web/404.html +1 -0
  363. package/dist/web/__next.__PAGE__.txt +9 -0
  364. package/dist/web/__next._full.txt +19 -0
  365. package/dist/web/__next._head.txt +6 -0
  366. package/dist/web/__next._index.txt +6 -0
  367. package/dist/web/__next._tree.txt +2 -0
  368. package/dist/web/_next/static/chunks/00yn.jp4tr9l6.js +62 -0
  369. package/dist/web/_next/static/chunks/0398g9fy2i2l..js +5 -0
  370. package/dist/web/_next/static/chunks/03~yq9q893hmn.js +1 -0
  371. package/dist/web/_next/static/chunks/07t-qdutaizlf.js +5 -0
  372. package/dist/web/_next/static/chunks/0_pxvi.u4tzw1.js +5 -0
  373. package/dist/web/_next/static/chunks/0dtbl8648b3u9.js +7 -0
  374. package/dist/web/_next/static/chunks/0e3pdjkorr5zl.js +2 -0
  375. package/dist/web/_next/static/chunks/0ewpxy-mzj3j3.js +1 -0
  376. package/dist/web/_next/static/chunks/0ihbb7~gq42g~.js +5 -0
  377. package/dist/web/_next/static/chunks/0j4uz-g9x1_~s.js +1 -0
  378. package/dist/web/_next/static/chunks/0mlo32yrc7ziu.css +1 -0
  379. package/dist/web/_next/static/chunks/0ru56x83x4rkk.js +1 -0
  380. package/dist/web/_next/static/chunks/0svvev77pb2gu.js +1 -0
  381. package/dist/web/_next/static/chunks/0tf9kpygstdls.js +1 -0
  382. package/dist/web/_next/static/chunks/0wzpea61sn2-k.js +5 -0
  383. package/dist/web/_next/static/chunks/0y3dnnq~kxyz_.js +1 -0
  384. package/dist/web/_next/static/chunks/0y~qqhmf2o7pt.js +1 -0
  385. package/dist/web/_next/static/chunks/0~6m1p5hnsx2f.js +1 -0
  386. package/dist/web/_next/static/chunks/10-liamt-ipcu.js +1 -0
  387. package/dist/web/_next/static/chunks/10l08hq.acixl.js +5 -0
  388. package/dist/web/_next/static/chunks/11rbefjn.e-3-.js +1 -0
  389. package/dist/web/_next/static/chunks/11rodb4s1x4of.js +1 -0
  390. package/dist/web/_next/static/chunks/12_uxtnrqhoo1.js +1 -0
  391. package/dist/web/_next/static/chunks/12h4dws.tz7yb.js +5 -0
  392. package/dist/web/_next/static/chunks/13juizw904g.e.js +1 -0
  393. package/dist/web/_next/static/chunks/14ge_q22f0n.f.js +1 -0
  394. package/dist/web/_next/static/chunks/16b0jvgccyt2i.js +5 -0
  395. package/dist/web/_next/static/chunks/17-u9c_weg12-.js +31 -0
  396. package/dist/web/_next/static/chunks/turbopack-0dt987bw_1nyf.js +1 -0
  397. package/dist/web/_next/static/media/apple-icon.0.wpl4.d-5bkf.jpg +0 -0
  398. package/dist/web/_next/static/media/icon.0.wpl4.d-5bkf.jpg +0 -0
  399. package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_buildManifest.js +11 -0
  400. package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_clientMiddlewareManifest.js +1 -0
  401. package/dist/web/_next/static/uwjABwQIFELOHhVlstvOe/_ssgManifest.js +1 -0
  402. package/dist/web/_not-found/__next._full.txt +17 -0
  403. package/dist/web/_not-found/__next._head.txt +6 -0
  404. package/dist/web/_not-found/__next._index.txt +6 -0
  405. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +5 -0
  406. package/dist/web/_not-found/__next._not-found.txt +5 -0
  407. package/dist/web/_not-found/__next._tree.txt +2 -0
  408. package/dist/web/_not-found.html +1 -0
  409. package/dist/web/_not-found.txt +17 -0
  410. package/dist/web/apple-icon.jpg +0 -0
  411. package/dist/web/chat/__next._full.txt +21 -0
  412. package/dist/web/chat/__next._head.txt +6 -0
  413. package/dist/web/chat/__next._index.txt +6 -0
  414. package/dist/web/chat/__next._tree.txt +2 -0
  415. package/dist/web/chat/__next.chat.__PAGE__.txt +9 -0
  416. package/dist/web/chat/__next.chat.txt +5 -0
  417. package/dist/web/chat.html +1 -0
  418. package/dist/web/chat.txt +21 -0
  419. package/dist/web/cron/__next._full.txt +21 -0
  420. package/dist/web/cron/__next._head.txt +6 -0
  421. package/dist/web/cron/__next._index.txt +6 -0
  422. package/dist/web/cron/__next._tree.txt +2 -0
  423. package/dist/web/cron/__next.cron.__PAGE__.txt +9 -0
  424. package/dist/web/cron/__next.cron.txt +5 -0
  425. package/dist/web/cron.html +1 -0
  426. package/dist/web/cron.txt +21 -0
  427. package/dist/web/icon.jpg +0 -0
  428. package/dist/web/index.html +1 -0
  429. package/dist/web/index.txt +19 -0
  430. package/dist/web/kanban/__next._full.txt +21 -0
  431. package/dist/web/kanban/__next._head.txt +6 -0
  432. package/dist/web/kanban/__next._index.txt +6 -0
  433. package/dist/web/kanban/__next._tree.txt +2 -0
  434. package/dist/web/kanban/__next.kanban.__PAGE__.txt +9 -0
  435. package/dist/web/kanban/__next.kanban.txt +5 -0
  436. package/dist/web/kanban.html +1 -0
  437. package/dist/web/kanban.txt +21 -0
  438. package/dist/web/logs/__next._full.txt +21 -0
  439. package/dist/web/logs/__next._head.txt +6 -0
  440. package/dist/web/logs/__next._index.txt +6 -0
  441. package/dist/web/logs/__next._tree.txt +2 -0
  442. package/dist/web/logs/__next.logs.__PAGE__.txt +9 -0
  443. package/dist/web/logs/__next.logs.txt +5 -0
  444. package/dist/web/logs.html +7 -0
  445. package/dist/web/logs.txt +21 -0
  446. package/dist/web/org/__next._full.txt +21 -0
  447. package/dist/web/org/__next._head.txt +6 -0
  448. package/dist/web/org/__next._index.txt +6 -0
  449. package/dist/web/org/__next._tree.txt +2 -0
  450. package/dist/web/org/__next.org.__PAGE__.txt +9 -0
  451. package/dist/web/org/__next.org.txt +5 -0
  452. package/dist/web/org.html +1 -0
  453. package/dist/web/org.txt +21 -0
  454. package/dist/web/sessions/__next._full.txt +18 -0
  455. package/dist/web/sessions/__next._head.txt +6 -0
  456. package/dist/web/sessions/__next._index.txt +6 -0
  457. package/dist/web/sessions/__next._tree.txt +2 -0
  458. package/dist/web/sessions/__next.sessions.__PAGE__.txt +6 -0
  459. package/dist/web/sessions/__next.sessions.txt +5 -0
  460. package/dist/web/sessions.html +1 -0
  461. package/dist/web/sessions.txt +18 -0
  462. package/dist/web/settings/__next._full.txt +21 -0
  463. package/dist/web/settings/__next._head.txt +6 -0
  464. package/dist/web/settings/__next._index.txt +6 -0
  465. package/dist/web/settings/__next._tree.txt +2 -0
  466. package/dist/web/settings/__next.settings.__PAGE__.txt +9 -0
  467. package/dist/web/settings/__next.settings.txt +5 -0
  468. package/dist/web/settings.html +1 -0
  469. package/dist/web/settings.txt +21 -0
  470. package/dist/web/skills/__next._full.txt +21 -0
  471. package/dist/web/skills/__next._head.txt +6 -0
  472. package/dist/web/skills/__next._index.txt +6 -0
  473. package/dist/web/skills/__next._tree.txt +2 -0
  474. package/dist/web/skills/__next.skills.__PAGE__.txt +9 -0
  475. package/dist/web/skills/__next.skills.txt +5 -0
  476. package/dist/web/skills.html +1 -0
  477. package/dist/web/skills.txt +21 -0
  478. package/package.json +54 -0
  479. package/template/AGENTS.md +285 -0
  480. package/template/CLAUDE.md +285 -0
  481. package/template/config.default.yaml +71 -0
  482. package/template/docs/architecture.md +74 -0
  483. package/template/docs/connectors.md +72 -0
  484. package/template/docs/cron.md +137 -0
  485. package/template/docs/mcp.md +108 -0
  486. package/template/docs/org.md +105 -0
  487. package/template/docs/overview.md +39 -0
  488. package/template/docs/self-modification.md +65 -0
  489. package/template/docs/skills.md +58 -0
  490. package/template/knowledge/.gitkeep +0 -0
  491. package/template/migrations/.gitkeep +0 -0
  492. package/template/migrations/0.1.0/MIGRATION.md +25 -0
  493. package/template/migrations/0.2.0/MIGRATION.md +41 -0
  494. package/template/migrations/0.2.0/files/config.default.yaml +30 -0
  495. package/template/migrations/0.3.0/MIGRATION.md +57 -0
  496. package/template/migrations/0.3.0/files/config.default.yaml +62 -0
  497. package/template/migrations/0.3.0/files/docs/mcp.md +108 -0
  498. package/template/migrations/0.7.3/MIGRATION.md +63 -0
  499. package/template/migrations/0.7.3/files/AGENTS.md +188 -0
  500. package/template/migrations/0.7.3/files/CLAUDE.md +127 -0
  501. package/template/migrations/0.7.5/MIGRATION.md +78 -0
  502. package/template/migrations/0.8.0/MIGRATION.md +73 -0
  503. package/template/migrations/0.9.0/MIGRATION.md +82 -0
  504. package/template/skills/cron-manager/SKILL.md +127 -0
  505. package/template/skills/find-and-install/SKILL.md +92 -0
  506. package/template/skills/management/SKILL.md +226 -0
  507. package/template/skills/migrate/SKILL.md +154 -0
  508. package/template/skills/new/SKILL.md +19 -0
  509. package/template/skills/onboarding/SKILL.md +106 -0
  510. package/template/skills/self-heal/SKILL.md +114 -0
  511. package/template/skills/skill-creator/SKILL.md +112 -0
  512. package/template/skills/status/SKILL.md +19 -0
  513. package/template/skills/sync/SKILL.md +67 -0
  514. package/template/skills.json +3 -0
@@ -0,0 +1,741 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { JINN_HOME, ORG_DIR, CRON_JOBS, DOCS_DIR } from "../shared/paths.js";
4
+ import { scanOrg } from "../gateway/org.js";
5
+ import { buildServiceRegistry } from "../gateway/services.js";
6
+ /**
7
+ * Token budget strategy:
8
+ *
9
+ * Sections are split into three tiers that are assembled in order.
10
+ * If the accumulated prompt exceeds the configurable budget (default 100K chars),
11
+ * lower-tier sections are progressively replaced with compact summaries.
12
+ *
13
+ * ESSENTIAL – identity, session, config (always included)
14
+ * STANDARD – org summary, cron summary, connectors,
15
+ * API ref, evolution, language (included when budget allows)
16
+ * OPTIONAL – knowledge listing, environment scan,
17
+ * delegation protocol (trimmed first when over budget)
18
+ *
19
+ * Knowledge and docs files are NEVER inlined — only filenames are listed.
20
+ * The AI can read files on demand, saving ~200K+ chars per session.
21
+ */
22
+ const DEFAULT_MAX_CONTEXT_CHARS = 100_000;
23
+ // ── Tier enum for progressive trimming ────────────────────────
24
+ var Tier;
25
+ (function (Tier) {
26
+ Tier[Tier["ESSENTIAL"] = 0] = "ESSENTIAL";
27
+ Tier[Tier["STANDARD"] = 1] = "STANDARD";
28
+ Tier[Tier["OPTIONAL"] = 2] = "OPTIONAL";
29
+ })(Tier || (Tier = {}));
30
+ /**
31
+ * Build a rich system prompt for engine sessions.
32
+ * This is what makes Jinn "smart" — the engine sees all of this context
33
+ * before responding to the user.
34
+ */
35
+ export function buildContext(opts) {
36
+ const maxChars = opts.config?.context?.maxChars ?? DEFAULT_MAX_CONTEXT_CHARS;
37
+ const sections = [];
38
+ // Compute gateway URL once — used by multiple sections
39
+ const gatewayUrl = opts.config
40
+ ? `http://${opts.config.gateway.host || "127.0.0.1"}:${opts.config.gateway.port || 7777}`
41
+ : "http://127.0.0.1:7777";
42
+ // Resolve personalized names from config
43
+ const portalName = opts.portalName || opts.config?.portal?.portalName || "Ryoko";
44
+ const operatorName = opts.operatorName || opts.config?.portal?.operatorName;
45
+ const language = opts.language || opts.config?.portal?.language || "English";
46
+ // ── ESSENTIAL: Identity ─────────────────────────────────────
47
+ if (opts.employee) {
48
+ sections.push({
49
+ tier: Tier.ESSENTIAL,
50
+ marker: "# You are",
51
+ content: buildEmployeeIdentity(opts.employee, portalName, language, opts.hierarchy?.nodes[opts.employee.name], opts.hierarchy),
52
+ summary: `# You are ${opts.employee.displayName}\nEmployee: ${opts.employee.name}, ${opts.employee.department}, ${opts.employee.rank}`,
53
+ });
54
+ }
55
+ else {
56
+ sections.push({
57
+ tier: Tier.ESSENTIAL,
58
+ marker: "# You are",
59
+ content: buildIdentity(portalName, operatorName, language, opts.speakerName),
60
+ summary: `# You are ${portalName}\nYour working directory is \`~/.ryoko\` (${JINN_HOME}).`,
61
+ });
62
+ }
63
+ // ── STANDARD: Self-evolution ────────────────────────────────
64
+ if (!opts.employee) {
65
+ sections.push({
66
+ tier: Tier.STANDARD,
67
+ marker: "## Self-evolution",
68
+ content: buildEvolutionContext(portalName),
69
+ summary: `## Self-evolution\nUpdate knowledge files in \`~/.jinn/knowledge/\` when you learn new info about the user or their projects.`,
70
+ });
71
+ }
72
+ // ── ESSENTIAL: Session context ──────────────────────────────
73
+ sections.push({
74
+ tier: Tier.ESSENTIAL,
75
+ marker: "## Current session",
76
+ content: buildSessionContext({ ...opts, sessionId: opts.sessionId, operatorName }),
77
+ summary: "", // always included, no trimming
78
+ });
79
+ // ── ESSENTIAL: Configuration awareness ──────────────────────
80
+ if (opts.config) {
81
+ sections.push({
82
+ tier: Tier.ESSENTIAL,
83
+ marker: "## Current configuration",
84
+ content: buildConfigContext(opts.config, gatewayUrl),
85
+ summary: "", // always included
86
+ });
87
+ }
88
+ // ── STANDARD: Organization ──────────────────────────────────
89
+ const orgCtx = buildOrgContext(opts.hierarchy);
90
+ if (orgCtx) {
91
+ sections.push({
92
+ tier: Tier.STANDARD,
93
+ marker: "## Organization",
94
+ content: orgCtx,
95
+ summary: `## Organization\nEmployee files are in \`${ORG_DIR}/\`. Read them directly when needed.`,
96
+ });
97
+ }
98
+ // ── STANDARD: Available services (for employees only) ────────
99
+ if (opts.employee) {
100
+ const svcCtx = buildServicesContext(opts.employee, gatewayUrl);
101
+ if (svcCtx) {
102
+ sections.push({
103
+ tier: Tier.STANDARD,
104
+ marker: "## Available services",
105
+ content: svcCtx,
106
+ summary: `## Available services\nUse \`POST ${gatewayUrl}/api/org/cross-request\` to request services from other employees.`,
107
+ });
108
+ }
109
+ }
110
+ // ── STANDARD: Cron jobs (only enabled, with disabled count) ─
111
+ const cronCtx = buildCronContext();
112
+ if (cronCtx) {
113
+ sections.push({
114
+ tier: Tier.STANDARD,
115
+ marker: "## Scheduled cron",
116
+ content: cronCtx,
117
+ summary: "## Scheduled cron jobs\nCron definitions are in `~/.jinn/cron/jobs.json`. Read directly when needed.",
118
+ });
119
+ }
120
+ // ── OPTIONAL: Knowledge / docs (filenames only, never inlined)
121
+ const knowledgeCtx = buildKnowledgeContext();
122
+ if (knowledgeCtx) {
123
+ sections.push({
124
+ tier: Tier.OPTIONAL,
125
+ marker: "## Knowledge base",
126
+ content: knowledgeCtx,
127
+ summary: "## Knowledge base\nKnowledge files are in `~/.jinn/knowledge/` and `~/.jinn/docs/`. Read them directly when needed.",
128
+ });
129
+ }
130
+ // ── STANDARD: Language override for skills ──────────────────
131
+ if (language !== "English") {
132
+ sections.push({
133
+ tier: Tier.STANDARD,
134
+ marker: "When following skill",
135
+ content: `When following skill instructions, always communicate with the user in ${language}, even if the skill contains English examples or dialogue.`,
136
+ summary: `Communicate in ${language}.`,
137
+ });
138
+ }
139
+ // ── STANDARD: Connectors (Slack, etc.) ──────────────────────
140
+ if (opts.connectors && opts.connectors.length > 0) {
141
+ sections.push({
142
+ tier: Tier.STANDARD,
143
+ marker: "## Available connectors",
144
+ content: buildConnectorContext(opts.connectors, gatewayUrl, portalName),
145
+ summary: `## Available connectors: ${opts.connectors.join(", ")}\nUse \`curl POST ${gatewayUrl}/api/connectors/<name>/send\` to send messages.`,
146
+ });
147
+ }
148
+ // ── OPTIONAL: Local environment ─────────────────────────────
149
+ const envCtx = buildEnvironmentContext();
150
+ if (envCtx) {
151
+ sections.push({
152
+ tier: Tier.OPTIONAL,
153
+ marker: "## Local environment",
154
+ content: envCtx,
155
+ summary: "## Local environment\nRun `ls ~/` to explore the local filesystem.",
156
+ });
157
+ }
158
+ // ── OPTIONAL: Delegation protocol (COO only) ───────────────
159
+ if (!opts.employee) {
160
+ sections.push({
161
+ tier: Tier.OPTIONAL,
162
+ marker: "## Employee Delegation",
163
+ content: buildDelegationProtocol(gatewayUrl, portalName, opts.config),
164
+ summary: `## Employee Delegation Protocol\nDelegate via \`POST ${gatewayUrl}/api/sessions\` with \`{prompt, employee, parentSessionId}\`. Check children via \`GET /api/sessions/:id/children\`.`,
165
+ });
166
+ }
167
+ // ── STANDARD: Gateway API reference ─────────────────────────
168
+ sections.push({
169
+ tier: Tier.STANDARD,
170
+ marker: `## ${portalName} Gateway API`,
171
+ content: buildApiReference(gatewayUrl, portalName),
172
+ summary: `## ${portalName} Gateway API (${gatewayUrl})\nEndpoints: /api/status, /api/sessions, /api/cron, /api/org, /api/skills, /api/config, /api/connectors, /api/logs`,
173
+ });
174
+ // ── Assemble with progressive trimming by tier ──────────────
175
+ return trimContext(sections, maxChars);
176
+ }
177
+ // ═══════════════════════════════════════════════════════════════
178
+ // Section builders
179
+ // ═══════════════════════════════════════════════════════════════
180
+ function buildEmployeeIdentity(employee, portalName, language, node, hierarchy) {
181
+ const languageInstruction = language !== "English"
182
+ ? `\n**Language**: Always respond in ${language}. All your communication with the user must be in ${language}.\n`
183
+ : "";
184
+ const chainOfCommand = buildChainOfCommand(employee, portalName, node, hierarchy);
185
+ return `# You are ${employee.displayName}
186
+
187
+ You are an AI employee in the ${portalName} gateway system.
188
+
189
+ ## Your persona
190
+ ${employee.persona}
191
+ ${languageInstruction}
192
+ ## Your role
193
+ - **Name**: ${employee.name}
194
+ - **Display name**: ${employee.displayName}
195
+ - **Department**: ${employee.department}
196
+ - **Rank**: ${employee.rank}
197
+ - **Engine**: ${employee.engine}
198
+ - **Model**: ${employee.model}
199
+ ${chainOfCommand}
200
+ ## System context
201
+ You are part of the ${portalName} AI gateway — a system that orchestrates AI workers. You have access to the filesystem, can run commands, call APIs, and send messages via connectors. Your working directory is \`~/.jinn\` (${JINN_HOME}).
202
+
203
+ You can:
204
+ - Read and write files in the home directory
205
+ - Run shell commands
206
+ - Call the gateway API to interact with other parts of the system
207
+ - Send messages via connectors (Slack, etc.)
208
+ - Access skills, knowledge base, and documentation
209
+ - Collaborate with other employees by mentioning them or creating sessions
210
+
211
+ Be proactive, take initiative, and deliver results. You're not a chatbot — you're a worker.`;
212
+ }
213
+ function buildChainOfCommand(employee, portalName, node, hierarchy) {
214
+ if (!node || !hierarchy)
215
+ return "";
216
+ const lines = ["## Chain of command"];
217
+ lines.push(`- **Department**: ${employee.department}`);
218
+ // Your manager
219
+ if (node.parentName) {
220
+ const parent = hierarchy.nodes[node.parentName];
221
+ if (parent) {
222
+ lines.push(`- **Your manager**: ${parent.employee.displayName} (${parent.employee.rank})`);
223
+ }
224
+ else {
225
+ lines.push(`- **Your manager**: ${node.parentName}`);
226
+ }
227
+ }
228
+ else {
229
+ lines.push(`- **Your manager**: ${portalName} (COO)`);
230
+ }
231
+ // Direct reports
232
+ if (node.directReports.length > 0) {
233
+ const reports = node.directReports.map((name) => {
234
+ const r = hierarchy.nodes[name];
235
+ return r ? `${r.employee.displayName} (${r.employee.rank})` : name;
236
+ });
237
+ lines.push(`- **Your direct reports**: ${reports.join(", ")}`);
238
+ }
239
+ // Escalation path
240
+ const escalation = [];
241
+ let current = node.parentName;
242
+ const visited = new Set();
243
+ while (current && !visited.has(current)) {
244
+ visited.add(current);
245
+ const mgr = hierarchy.nodes[current];
246
+ escalation.push(mgr ? mgr.employee.displayName : current);
247
+ current = mgr?.parentName ?? null;
248
+ }
249
+ escalation.push(`${portalName} (COO)`);
250
+ const unique = [...new Set(escalation)];
251
+ lines.push(`- **Escalation path**: ${unique.join(" → ")}`);
252
+ return "\n" + lines.join("\n") + "\n";
253
+ }
254
+ function buildServicesContext(employee, gatewayUrl) {
255
+ try {
256
+ const registry = scanOrg();
257
+ const services = buildServiceRegistry(registry);
258
+ if (services.size === 0)
259
+ return null;
260
+ const lines = ["## Available services"];
261
+ lines.push("Other employees provide the following services. To request one, use the cross-request API:");
262
+ lines.push(`\`POST ${gatewayUrl}/api/org/cross-request\` with \`{"fromEmployee": "${employee.name}", "service": "<name>", "prompt": "<what you need>"}\``);
263
+ lines.push("");
264
+ for (const [svcName, entry] of services) {
265
+ // Skip services from own department
266
+ if (entry.provider.department === employee.department)
267
+ continue;
268
+ lines.push(`- **${svcName}** — ${entry.declaration.description} (provided by ${entry.provider.displayName}, ${entry.provider.department})`);
269
+ }
270
+ // If no external services remain after filtering, skip
271
+ if (lines.length <= 4)
272
+ return null;
273
+ return lines.join("\n");
274
+ }
275
+ catch {
276
+ return null;
277
+ }
278
+ }
279
+ function buildIdentity(portalName, operatorName, language, speakerName) {
280
+ const speakerIsOperator = !!speakerName && !!operatorName && speakerName.trim() === operatorName.trim();
281
+ const operatorLine = operatorName
282
+ ? speakerIsOperator || !speakerName
283
+ ? `\nYour operator (the person who runs this Jinn instance) is **${operatorName}**. Address them by name when appropriate.`
284
+ : `\nYour operator (the person who runs this Jinn instance) is **${operatorName}** — but the current speaker is someone else.\nAlways identify the person you are addressing via \`## Current session → Speaker\`. Never call the current speaker "${operatorName}" unless confirmed — that name belongs to the operator, not to every person you talk to.`
285
+ : "";
286
+ const languageInstruction = language && language !== "English"
287
+ ? `\n**Language**: Always respond in ${language}. All your communication with the user must be in ${language}.`
288
+ : "";
289
+ return `# You are ${portalName}
290
+
291
+ ${portalName} is a personal AI assistant and gateway daemon. You are proactive, helpful, and opinionated — not a passive tool. You anticipate needs, suggest improvements, and take initiative when appropriate.${operatorLine}
292
+
293
+ ## Core principles
294
+ - **Be proactive**: Don't just answer questions — suggest next steps, flag issues, offer to do related tasks.
295
+ - **Be concise**: Respect the user's time. Lead with the answer, not the reasoning.
296
+ - **Be capable**: You have access to the filesystem, can run commands, call APIs, send messages via connectors, and manage the system.
297
+ - **Be honest**: If you don't know something or can't do something, say so clearly.
298
+ - **Remember context**: You're part of a persistent system. Sessions can be resumed. Build on previous work.
299
+ ${languageInstruction}
300
+ ## Your home directory
301
+ Your working directory is \`~/.jinn\` (${JINN_HOME}). This contains:
302
+ - \`config.yaml\` — your configuration (engines, connectors, logging)
303
+ - \`org/\` — employee definitions (YAML files defining AI workers)
304
+ - \`skills/\` — reusable skill prompts
305
+ - \`docs/\` — documentation and knowledge base
306
+ - \`knowledge/\` — persistent knowledge files
307
+ - \`cron/\` — scheduled job definitions and run history
308
+ - \`sessions/\` — session database
309
+ - \`logs/\` — gateway logs
310
+ - \`CLAUDE.md\` — user-defined instructions (always follow these)
311
+ - \`AGENTS.md\` — agent/employee documentation
312
+
313
+ You can read, write, and modify any of these files to configure yourself, create new employees, add skills, etc.`;
314
+ }
315
+ function buildSessionContext(opts) {
316
+ let ctx = `## Current session\n`;
317
+ if (opts.sessionId)
318
+ ctx += `- Session ID: ${opts.sessionId}\n`;
319
+ ctx += `- Source: ${opts.source}\n`;
320
+ if (opts.channelName) {
321
+ ctx += `- Channel: #${opts.channelName} (${opts.channel})\n`;
322
+ }
323
+ else if (opts.source === "slack" && opts.channel.startsWith("D")) {
324
+ ctx += `- Channel: Direct Message (${opts.channel})\n`;
325
+ }
326
+ else {
327
+ ctx += `- Channel: ${opts.channel}\n`;
328
+ }
329
+ if (opts.thread)
330
+ ctx += `- Thread: ${opts.thread}\n`;
331
+ if (opts.speakerName) {
332
+ const aliasParts = [];
333
+ if (opts.speakerRealName && opts.speakerRealName !== opts.speakerName) {
334
+ aliasParts.push(`real name: "${opts.speakerRealName}"`);
335
+ }
336
+ if (opts.speakerHandle && opts.speakerHandle !== opts.speakerName) {
337
+ aliasParts.push(`handle: @${opts.speakerHandle}`);
338
+ }
339
+ if (opts.speakerSlackId) {
340
+ aliasParts.push(`Slack ID: ${opts.speakerSlackId}`);
341
+ }
342
+ const aliasSuffix = aliasParts.length > 0 ? ` (${aliasParts.join(", ")})` : "";
343
+ const botSuffix = opts.speakerIsBot ? " [BOT]" : "";
344
+ ctx += `- Speaker: **${opts.speakerName}**${aliasSuffix}${botSuffix}\n`;
345
+ if (opts.speakerTz)
346
+ ctx += ` - Timezone: ${opts.speakerTz}\n`;
347
+ const operator = opts.operatorName?.trim();
348
+ const speakerAliases = [opts.speakerName, opts.speakerRealName, opts.speakerDisplayName, opts.speakerHandle]
349
+ .filter((v) => !!v)
350
+ .map((v) => v.trim());
351
+ const isOperator = operator ? speakerAliases.includes(operator) : false;
352
+ if (operator && !isOperator) {
353
+ ctx += ` - ⚠ NOT the operator. Address this person as "${opts.speakerName}", not "${operator}".\n`;
354
+ }
355
+ else if (operator && isOperator) {
356
+ ctx += ` - This speaker is the operator.\n`;
357
+ }
358
+ }
359
+ else {
360
+ ctx += `- User: ${opts.user}\n`;
361
+ }
362
+ ctx += `- Working directory: ${JINN_HOME}`;
363
+ return ctx;
364
+ }
365
+ function buildConfigContext(config, gatewayUrl) {
366
+ const lines = [`## Current configuration`];
367
+ lines.push(`- Gateway: ${gatewayUrl}`);
368
+ lines.push(`- Default engine: ${config.engines.default}`);
369
+ if (config.engines.claude?.model) {
370
+ lines.push(`- Claude model: ${config.engines.claude.model}`);
371
+ }
372
+ if (config.engines.codex?.model) {
373
+ lines.push(`- Codex model: ${config.engines.codex.model}`);
374
+ }
375
+ if (config.engines.gemini?.model) {
376
+ lines.push(`- Gemini model: ${config.engines.gemini.model}`);
377
+ }
378
+ if (config.logging) {
379
+ lines.push(`- Log level: ${config.logging.level || "info"}`);
380
+ }
381
+ return lines.join("\n");
382
+ }
383
+ function buildOrgContext(hierarchy) {
384
+ try {
385
+ if (hierarchy && Object.keys(hierarchy.nodes).length > 0) {
386
+ const MAX_DEPTH = 3;
387
+ const count = Object.keys(hierarchy.nodes).length;
388
+ const lines = [`## Organization (${count} employee(s))`];
389
+ let deepCount = 0;
390
+ for (const name of hierarchy.sorted) {
391
+ const node = hierarchy.nodes[name];
392
+ if (node.depth >= MAX_DEPTH) {
393
+ deepCount++;
394
+ continue;
395
+ }
396
+ const emp = node.employee;
397
+ const indent = " ".repeat(node.depth);
398
+ let entry = `${indent}- **${emp.displayName}** (${name}) — ${emp.department}, ${emp.rank}`;
399
+ if (emp.persona) {
400
+ const firstLine = emp.persona.trim().split("\n")[0].trim().slice(0, 120);
401
+ entry += `\n${indent} _${firstLine}_`;
402
+ }
403
+ lines.push(entry);
404
+ }
405
+ if (deepCount > 0) {
406
+ lines.push(`${" ".repeat(MAX_DEPTH)}- ... and ${deepCount} more at deeper levels`);
407
+ }
408
+ lines.push(`\nYou can create new employees by writing YAML files to \`${ORG_DIR}/\``);
409
+ return lines.join("\n");
410
+ }
411
+ // Fallback: filesystem-based flat rendering (backwards compat)
412
+ // Recursively collect all employee yaml files (skip department.yaml)
413
+ const employeeFiles = [];
414
+ function scanDir(dir) {
415
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
416
+ for (const entry of entries) {
417
+ const fullPath = path.join(dir, entry.name);
418
+ if (entry.isDirectory()) {
419
+ scanDir(fullPath);
420
+ }
421
+ else if ((entry.name.endsWith(".yaml") || entry.name.endsWith(".yml")) &&
422
+ entry.name !== "department.yaml") {
423
+ employeeFiles.push({ fullPath, name: entry.name.replace(/\.ya?ml$/, "") });
424
+ }
425
+ }
426
+ }
427
+ scanDir(ORG_DIR);
428
+ if (employeeFiles.length === 0)
429
+ return null;
430
+ const lines = [`## Organization (${employeeFiles.length} employee(s))`];
431
+ for (const { fullPath, name } of employeeFiles) {
432
+ const content = fs.readFileSync(fullPath, "utf-8");
433
+ const displayMatch = content.match(/displayName:\s*(.+)/);
434
+ const deptMatch = content.match(/department:\s*(.+)/);
435
+ const rankMatch = content.match(/rank:\s*(.+)/);
436
+ const personaMatch = content.match(/persona:\s*[|>]?\s*\n?\s*(.+)/);
437
+ let entry = `- **${displayMatch?.[1] || name}** (${name}) — ${deptMatch?.[1] || "unassigned"}, ${rankMatch?.[1] || "employee"}`;
438
+ if (personaMatch?.[1]) {
439
+ entry += `\n _${personaMatch[1].trim().slice(0, 120)}_`;
440
+ }
441
+ lines.push(entry);
442
+ }
443
+ lines.push(`\nYou can create new employees by writing YAML files to \`${ORG_DIR}/\``);
444
+ return lines.join("\n");
445
+ }
446
+ catch {
447
+ return null;
448
+ }
449
+ }
450
+ /**
451
+ * Cron context: shows only enabled jobs inline, with a count of disabled jobs.
452
+ * Previously listed all 77+ jobs; now only active ones are shown to save tokens.
453
+ */
454
+ function buildCronContext() {
455
+ try {
456
+ const raw = fs.readFileSync(CRON_JOBS, "utf-8");
457
+ const jobs = JSON.parse(raw);
458
+ if (!Array.isArray(jobs) || jobs.length === 0)
459
+ return null;
460
+ const enabled = jobs.filter((j) => j.enabled !== false);
461
+ const disabledCount = jobs.length - enabled.length;
462
+ const lines = [`## Scheduled cron jobs (${enabled.length} active, ${disabledCount} disabled)`];
463
+ for (const job of enabled) {
464
+ lines.push(`- **${job.name}**: \`${job.schedule}\`${job.employee ? ` → ${job.employee}` : ""}`);
465
+ }
466
+ if (disabledCount > 0) {
467
+ lines.push(`\n_${disabledCount} disabled jobs not shown. See \`~/.jinn/cron/jobs.json\` for the full list._`);
468
+ }
469
+ return lines.join("\n");
470
+ }
471
+ catch {
472
+ return null;
473
+ }
474
+ }
475
+ /**
476
+ * Knowledge context: lists filenames and sizes only — never inlines content.
477
+ * The AI reads files on demand. This saves ~200K+ chars compared to full inlining.
478
+ */
479
+ function buildKnowledgeContext() {
480
+ const dirs = [
481
+ { dir: DOCS_DIR, label: "docs" },
482
+ { dir: path.join(JINN_HOME, "knowledge"), label: "knowledge" },
483
+ ];
484
+ const entries = [];
485
+ for (const { dir, label } of dirs) {
486
+ try {
487
+ const files = fs.readdirSync(dir).filter(f => f.endsWith(".md") || f.endsWith(".txt") || f.endsWith(".yaml"));
488
+ for (const f of files) {
489
+ try {
490
+ const stat = fs.statSync(path.join(dir, f));
491
+ entries.push({
492
+ name: f,
493
+ dir: label,
494
+ sizeKb: (stat.size / 1024).toFixed(1),
495
+ });
496
+ }
497
+ catch {
498
+ entries.push({ name: f, dir: label, sizeKb: "?" });
499
+ }
500
+ }
501
+ }
502
+ catch {
503
+ // dir doesn't exist
504
+ }
505
+ }
506
+ if (entries.length === 0)
507
+ return null;
508
+ const lines = [
509
+ `## Knowledge base`,
510
+ `Knowledge files are in \`~/.jinn/knowledge/\` and \`~/.jinn/docs/\`. Read them directly when needed.`,
511
+ ``,
512
+ ];
513
+ // Group by directory
514
+ for (const label of ["docs", "knowledge"]) {
515
+ const group = entries.filter(e => e.dir === label);
516
+ if (group.length === 0)
517
+ continue;
518
+ lines.push(`**${label}/** (${group.length} files):`);
519
+ for (const e of group) {
520
+ lines.push(`- \`${e.name}\` (${e.sizeKb} KB)`);
521
+ }
522
+ lines.push("");
523
+ }
524
+ return lines.join("\n");
525
+ }
526
+ function buildConnectorContext(connectors, gatewayUrl, portalName) {
527
+ const lines = [`## Available connectors: ${connectors.join(", ")}`];
528
+ lines.push(`You can send messages and interact with external services via the ${portalName} gateway API.`);
529
+ lines.push(`Use bash with curl to call these endpoints:\n`);
530
+ for (const name of connectors) {
531
+ lines.push(`### ${name}`);
532
+ lines.push(`- **Send message**: \`curl -X POST ${gatewayUrl}/api/connectors/${name}/send -H 'Content-Type: application/json' -d '{"channel":"CHANNEL_ID","text":"message"}'\``);
533
+ lines.push(`- **Send threaded reply**: add \`"thread":"THREAD_TS"\` to the JSON body`);
534
+ lines.push(`- You can proactively send messages without being asked — e.g., to notify about completed tasks, errors, or status updates`);
535
+ }
536
+ lines.push(`\n- **List all connectors**: \`curl ${gatewayUrl}/api/connectors\``);
537
+ lines.push(`- Channel IDs and connector config can be found in \`~/.jinn/config.yaml\``);
538
+ return lines.join("\n");
539
+ }
540
+ function buildEnvironmentContext() {
541
+ const home = process.env.HOME || process.env.USERPROFILE || "";
542
+ const lines = [`## Local environment`];
543
+ let hasContent = false;
544
+ const toolDirs = [
545
+ { dir: ".openclaw", label: "OpenClaw", description: "AI agent platform (agents, cron, memory, hooks, credentials)" },
546
+ { dir: ".claude", label: "Claude Code", description: "Claude Code CLI config and projects" },
547
+ { dir: ".codex", label: "Codex", description: "OpenAI Codex CLI config" },
548
+ ];
549
+ for (const tool of toolDirs) {
550
+ const toolPath = path.join(home, tool.dir);
551
+ try {
552
+ const stat = fs.statSync(toolPath);
553
+ if (stat.isDirectory()) {
554
+ const contents = fs.readdirSync(toolPath).filter(f => !f.startsWith("."));
555
+ lines.push(`- **${tool.label}** (\`~/${tool.dir}/\`): ${tool.description}`);
556
+ if (contents.length > 0) {
557
+ lines.push(` Contents: ${contents.slice(0, 15).join(", ")}${contents.length > 15 ? `, ... (${contents.length} total)` : ""}`);
558
+ }
559
+ hasContent = true;
560
+ }
561
+ }
562
+ catch {
563
+ // doesn't exist
564
+ }
565
+ }
566
+ // Scan ~/Projects for user's codebases
567
+ const projectsDir = path.join(home, "Projects");
568
+ try {
569
+ const projects = fs.readdirSync(projectsDir).filter(f => {
570
+ try {
571
+ return fs.statSync(path.join(projectsDir, f)).isDirectory();
572
+ }
573
+ catch {
574
+ return false;
575
+ }
576
+ });
577
+ if (projects.length > 0) {
578
+ lines.push(`- **Projects** (\`~/Projects/\`): ${projects.join(", ")}`);
579
+ hasContent = true;
580
+ }
581
+ }
582
+ catch {
583
+ // no Projects dir
584
+ }
585
+ if (!hasContent)
586
+ return null;
587
+ lines.push(`\nWhen the user asks about tools or systems on their machine, check these directories first before saying you don't know. Be resourceful — explore the filesystem.`);
588
+ return lines.join("\n");
589
+ }
590
+ function buildEvolutionContext(portalName) {
591
+ const profilePath = path.join(JINN_HOME, "knowledge", "user-profile.md");
592
+ let profileContent = "";
593
+ try {
594
+ profileContent = fs.readFileSync(profilePath, "utf-8").trim();
595
+ }
596
+ catch { }
597
+ const isNew = profileContent.length < 50;
598
+ const lines = [`## Self-evolution`];
599
+ if (isNew) {
600
+ lines.push(`**ONBOARDING MODE**: This is a new or unconfigured ${portalName} installation.`);
601
+ lines.push(`Before answering the user's request, introduce yourself briefly and ask them:`);
602
+ lines.push(`1. What's your name and what do you do? (business, role, projects)`);
603
+ lines.push(`2. What should ${portalName} help you automate? (code reviews, deployments, monitoring, etc.)`);
604
+ lines.push(`3. Communication preferences — emoji style, verbosity (concise vs detailed), language`);
605
+ lines.push(`4. Any active projects ${portalName} should know about?`);
606
+ lines.push(`\nAfter the user responds, write their answers to \`~/.jinn/knowledge/user-profile.md\` and \`~/.jinn/knowledge/preferences.md\`.`);
607
+ lines.push(`Then proceed to help with their original request.`);
608
+ }
609
+ else {
610
+ lines.push(`You learn and evolve over time. When you discover new information about the user, their projects, or their preferences:`);
611
+ lines.push(`- Update \`~/.jinn/knowledge/user-profile.md\` with business/identity info`);
612
+ lines.push(`- Update \`~/.jinn/knowledge/preferences.md\` with style/communication preferences`);
613
+ lines.push(`- Update \`~/.jinn/knowledge/projects.md\` with project details`);
614
+ lines.push(`- If the user gives you persistent feedback (e.g. "always do X", "never do Y"), update \`~/.jinn/CLAUDE.md\``);
615
+ lines.push(`\nDo this silently — don't announce every file update. Just evolve.`);
616
+ }
617
+ return lines.join("\n");
618
+ }
619
+ /**
620
+ * Delegation protocol: condensed version focusing on the essential API patterns.
621
+ * Verbose examples and multi-paragraph explanations have been trimmed.
622
+ */
623
+ function buildDelegationProtocol(gatewayUrl, _portalName, config) {
624
+ const defaultEngine = config?.engines.default || "claude";
625
+ const engineConfig = defaultEngine === "codex"
626
+ ? config?.engines.codex
627
+ : defaultEngine === "gemini"
628
+ ? config?.engines.gemini ?? config?.engines.claude
629
+ : config?.engines.claude;
630
+ const childOverride = engineConfig?.childEffortOverride;
631
+ const effortOverrideNote = childOverride
632
+ ? `\n> **Note**: \`childEffortOverride\` is set to \`"${childOverride}"\`. All child sessions use this effort level.`
633
+ : "";
634
+ return `## Employee Delegation Protocol
635
+
636
+ You are the COO. You orchestrate employees by creating **linked child sessions**.
637
+
638
+ ### How delegation works
639
+
640
+ 1. **Detect**: Spot \`@employee-name\` tags or infer the right employee from context.
641
+
642
+ 2. **Check for existing children first**:
643
+ \`\`\`bash
644
+ curl -s ${gatewayUrl}/api/sessions/<your-session-id>/children
645
+ \`\`\`
646
+ If a child exists for this employee, reuse it (skip to step 5).
647
+
648
+ 3. **Brief**: Craft clear, targeted instructions — translate user words into actionable briefs.
649
+
650
+ 4. **Spawn**:
651
+ \`\`\`bash
652
+ curl -s -X POST ${gatewayUrl}/api/sessions \\
653
+ -H 'Content-Type: application/json' \\
654
+ -d '{"prompt": "<brief>", "employee": "<name>", "parentSessionId": "<your-session-id>"}'
655
+ \`\`\`
656
+
657
+ 5. **Follow up** (existing child):
658
+ \`\`\`bash
659
+ curl -s -X POST ${gatewayUrl}/api/sessions/<child-id>/message \\
660
+ -H 'Content-Type: application/json' \\
661
+ -d '{"message": "<follow-up>"}'
662
+ \`\`\`
663
+
664
+ 6. **Respond immediately**: Tell the user you've delegated and will follow up when it's done. **Do NOT poll or wait** — end your turn now.
665
+
666
+ 7. **onComplete callback**: When the child session finishes, the gateway automatically sends you a notification message with the result. You will receive this as a new message in your session — no polling needed.
667
+
668
+ 8. **Review**: When the onComplete notification arrives, assess work using oversight levels (TRUST / VERIFY / THOROUGH) based on complexity and risk, then relay the result to the user.
669
+
670
+ ### Key rules
671
+ - **NEVER poll or wait for child sessions**. After spawning, reply to the user and end your turn. The gateway's onComplete callback will message you automatically when the child finishes.
672
+ - **Always reuse** child sessions — never create duplicates for the same employee.
673
+ - **Parallel spawning**: For independent sub-tasks, spawn multiple employees simultaneously.
674
+ - **Cross-reference**: Compare results from multiple employees before responding.
675
+ - **Effort levels**: Include \`"effortLevel"\` in the API body: \`"low"\` (lookups), \`"medium"\` (routine), \`"high"\` (code/architecture).
676
+
677
+ ### Oversight Levels
678
+
679
+ | Level | When | You do |
680
+ |-------|------|--------|
681
+ | **TRUST** | Simple lookups, status checks | Skim, relay directly |
682
+ | **VERIFY** | Code changes, routine work | Read fully, spot-check key files |
683
+ | **THOROUGH** | Architecture, breaking changes, security | Full review, multi-turn follow-up, verify changes |
684
+
685
+ ### Manager Delegation
686
+
687
+ When a department has 3+ employees, promote a senior to **manager**. Managers handle their own delegation; you review their summaries, not individual work.
688
+
689
+ ### Your session ID
690
+
691
+ Your current session ID is in the "Current session" section above. Use it as \`parentSessionId\`.${effortOverrideNote}`;
692
+ }
693
+ function buildApiReference(gatewayUrl, portalName) {
694
+ return `## ${portalName} Gateway API (${gatewayUrl})
695
+
696
+ You can call these endpoints with curl to inspect and manage the gateway:
697
+
698
+ | Endpoint | Method | Description |
699
+ |----------|--------|-------------|
700
+ | \`/api/status\` | GET | Gateway status, uptime, engine info |
701
+ | \`/api/sessions\` | GET | List all sessions |
702
+ | \`/api/sessions/:id\` | GET | Session detail (includes messages) |
703
+ | \`/api/sessions\` | POST | Create new session (\`{prompt, engine?, employee?, parentSessionId?}\`) |
704
+ | \`/api/sessions/:id/message\` | POST | Send follow-up message to existing session (\`{message}\`) |
705
+ | \`/api/sessions/:id/children\` | GET | List child sessions of a parent |
706
+ | \`/api/cron\` | GET | List cron jobs |
707
+ | \`/api/cron/:id\` | PUT | Update cron job (toggle enabled, etc.) |
708
+ | \`/api/cron/:id/runs\` | GET | Cron run history |
709
+ | \`/api/org\` | GET | Organization structure |
710
+ | \`/api/org/employees/:name\` | GET | Employee details |
711
+ | \`/api/skills\` | GET | List skills |
712
+ | \`/api/skills/:name\` | GET | Skill content |
713
+ | \`/api/config\` | GET | Current config |
714
+ | \`/api/config\` | PUT | Update config |
715
+ | \`/api/connectors\` | GET | List connectors |
716
+ | \`/api/connectors/:name/send\` | POST | Send message via connector |
717
+ | \`/api/logs\` | GET | Recent log lines |`;
718
+ }
719
+ /**
720
+ * Progressive trimming by tier: OPTIONAL sections are replaced with summaries first,
721
+ * then STANDARD, then (as a last resort) ESSENTIAL sections.
722
+ */
723
+ function trimContext(sections, maxChars) {
724
+ let parts = sections.map(s => s.content);
725
+ let result = parts.join("\n\n");
726
+ if (result.length <= maxChars)
727
+ return result;
728
+ // Trim OPTIONAL sections first, then STANDARD
729
+ for (const tier of [Tier.OPTIONAL, Tier.STANDARD]) {
730
+ for (let i = sections.length - 1; i >= 0; i--) {
731
+ if (result.length <= maxChars)
732
+ break;
733
+ if (sections[i].tier === tier && sections[i].summary) {
734
+ parts[i] = sections[i].summary;
735
+ result = parts.join("\n\n");
736
+ }
737
+ }
738
+ }
739
+ return result;
740
+ }
741
+ //# sourceMappingURL=context.js.map