@zerwiz/ymir 0.1.34 → 0.1.35

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 (929) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/apps/README.md +4 -0
  3. package/apps/hlidskjalf/README.md +68 -0
  4. package/apps/hlidskjalf/android/app/build.gradle +73 -0
  5. package/apps/hlidskjalf/android/app/capacitor.build.gradle +19 -0
  6. package/apps/hlidskjalf/android/app/proguard-rules.pro +21 -0
  7. package/apps/hlidskjalf/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
  8. package/apps/hlidskjalf/android/app/src/main/AndroidManifest.xml +41 -0
  9. package/apps/hlidskjalf/android/app/src/main/java/org/zerwiz/ymir/MainActivity.java +5 -0
  10. package/apps/hlidskjalf/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
  11. package/apps/hlidskjalf/android/app/src/main/res/drawable/splash.png +0 -0
  12. package/apps/hlidskjalf/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
  13. package/apps/hlidskjalf/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
  14. package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
  15. package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
  16. package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
  17. package/apps/hlidskjalf/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
  18. package/apps/hlidskjalf/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
  19. package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
  20. package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
  21. package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
  22. package/apps/hlidskjalf/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
  23. package/apps/hlidskjalf/android/app/src/main/res/layout/activity_main.xml +12 -0
  24. package/apps/hlidskjalf/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
  25. package/apps/hlidskjalf/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
  26. package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  27. package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
  28. package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  29. package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  30. package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
  31. package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  32. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  33. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
  34. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  35. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  36. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
  37. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  38. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  39. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
  40. package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  41. package/apps/hlidskjalf/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
  42. package/apps/hlidskjalf/android/app/src/main/res/values/strings.xml +7 -0
  43. package/apps/hlidskjalf/android/app/src/main/res/values/styles.xml +22 -0
  44. package/apps/hlidskjalf/android/app/src/main/res/xml/file_paths.xml +5 -0
  45. package/apps/hlidskjalf/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
  46. package/apps/hlidskjalf/android/build.gradle +29 -0
  47. package/apps/hlidskjalf/android/capacitor.settings.gradle +3 -0
  48. package/apps/hlidskjalf/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  49. package/apps/hlidskjalf/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  50. package/apps/hlidskjalf/android/gradle.properties +22 -0
  51. package/apps/hlidskjalf/android/gradlew +248 -0
  52. package/apps/hlidskjalf/android/gradlew.bat +92 -0
  53. package/apps/hlidskjalf/android/settings.gradle +5 -0
  54. package/apps/hlidskjalf/android/variables.gradle +16 -0
  55. package/apps/hlidskjalf/capacitor.config.ts +26 -0
  56. package/apps/hlidskjalf/dist/apple-touch-icon.png +0 -0
  57. package/apps/hlidskjalf/dist/assets/index-BWmNIyaG.css +1 -0
  58. package/apps/hlidskjalf/dist/assets/index-k7QEfNto.js +88 -0
  59. package/apps/hlidskjalf/dist/assets/index-k7QEfNto.js.map +1 -0
  60. package/apps/hlidskjalf/dist/icon.svg +7 -0
  61. package/apps/hlidskjalf/dist/index.html +64 -0
  62. package/apps/hlidskjalf/dist/manifest.webmanifest +31 -0
  63. package/apps/hlidskjalf/dist/og.jpg +0 -0
  64. package/apps/hlidskjalf/dist/og.png +0 -0
  65. package/apps/hlidskjalf/dist/og.svg +64 -0
  66. package/apps/hlidskjalf/dist/sw.js +39 -0
  67. package/apps/hlidskjalf/dist/ymir-icon.png +0 -0
  68. package/apps/hlidskjalf/dist/ymir-mark.svg +62 -0
  69. package/apps/hlidskjalf/electron/icon.png +0 -0
  70. package/apps/hlidskjalf/electron/main.cjs +236 -0
  71. package/apps/hlidskjalf/electron/preload.cjs +8 -0
  72. package/apps/hlidskjalf/electron/smidja-icon.png +0 -0
  73. package/apps/hlidskjalf/electron/ymir-hlidskjalf.desktop.in +12 -0
  74. package/apps/hlidskjalf/electron/ymir-smidja.desktop.in +12 -0
  75. package/apps/hlidskjalf/index.html +63 -0
  76. package/apps/hlidskjalf/package-lock.json +5398 -0
  77. package/apps/hlidskjalf/package.json +55 -0
  78. package/apps/hlidskjalf/public/apple-touch-icon.png +0 -0
  79. package/apps/hlidskjalf/public/icon.svg +7 -0
  80. package/apps/hlidskjalf/public/manifest.webmanifest +31 -0
  81. package/apps/hlidskjalf/public/og.jpg +0 -0
  82. package/apps/hlidskjalf/public/og.png +0 -0
  83. package/apps/hlidskjalf/public/og.svg +64 -0
  84. package/apps/hlidskjalf/public/sw.js +39 -0
  85. package/apps/hlidskjalf/public/ymir-icon.png +0 -0
  86. package/apps/hlidskjalf/public/ymir-mark.svg +62 -0
  87. package/apps/hlidskjalf/server/accounts.ts +159 -0
  88. package/apps/hlidskjalf/server/index.ts +2045 -0
  89. package/apps/hlidskjalf/src/app/App.tsx +116 -0
  90. package/apps/hlidskjalf/src/app/BottomStream.tsx +128 -0
  91. package/apps/hlidskjalf/src/app/MobileNav.tsx +87 -0
  92. package/apps/hlidskjalf/src/app/Rail.tsx +106 -0
  93. package/apps/hlidskjalf/src/app/Shell.tsx +135 -0
  94. package/apps/hlidskjalf/src/app/Topbar.tsx +130 -0
  95. package/apps/hlidskjalf/src/components/AccentPicker.tsx +207 -0
  96. package/apps/hlidskjalf/src/components/AccountMenu.tsx +115 -0
  97. package/apps/hlidskjalf/src/components/AgentCard.tsx +75 -0
  98. package/apps/hlidskjalf/src/components/EmberBackground.tsx +36 -0
  99. package/apps/hlidskjalf/src/components/Emblem.tsx +48 -0
  100. package/apps/hlidskjalf/src/components/Halls.tsx +155 -0
  101. package/apps/hlidskjalf/src/components/LoginModal.tsx +329 -0
  102. package/apps/hlidskjalf/src/components/Markdown.tsx +10 -0
  103. package/apps/hlidskjalf/src/components/MetricTile.tsx +40 -0
  104. package/apps/hlidskjalf/src/components/ModelPicker.tsx +100 -0
  105. package/apps/hlidskjalf/src/components/Overlay.tsx +134 -0
  106. package/apps/hlidskjalf/src/components/PRCard.tsx +154 -0
  107. package/apps/hlidskjalf/src/components/RecallPanel.tsx +116 -0
  108. package/apps/hlidskjalf/src/components/RuneTag.tsx +23 -0
  109. package/apps/hlidskjalf/src/components/Status.tsx +35 -0
  110. package/apps/hlidskjalf/src/components/TaskChip.tsx +23 -0
  111. package/apps/hlidskjalf/src/components/TraceRow.tsx +28 -0
  112. package/apps/hlidskjalf/src/data/lore.ts +127 -0
  113. package/apps/hlidskjalf/src/data/metadata.ts +147 -0
  114. package/apps/hlidskjalf/src/data/mythology.ts +95 -0
  115. package/apps/hlidskjalf/src/data/realms.ts +167 -0
  116. package/apps/hlidskjalf/src/gates/Cron.tsx +77 -0
  117. package/apps/hlidskjalf/src/gates/Decisions.tsx +67 -0
  118. package/apps/hlidskjalf/src/gates/Files.tsx +138 -0
  119. package/apps/hlidskjalf/src/gates/Fleet.tsx +184 -0
  120. package/apps/hlidskjalf/src/gates/Forge.tsx +486 -0
  121. package/apps/hlidskjalf/src/gates/OmniChat.tsx +217 -0
  122. package/apps/hlidskjalf/src/gates/Processes.tsx +162 -0
  123. package/apps/hlidskjalf/src/gates/Profile.tsx +225 -0
  124. package/apps/hlidskjalf/src/gates/Reviews.tsx +33 -0
  125. package/apps/hlidskjalf/src/gates/Runes.tsx +116 -0
  126. package/apps/hlidskjalf/src/gates/Runtime.tsx +106 -0
  127. package/apps/hlidskjalf/src/gates/Sessions.tsx +109 -0
  128. package/apps/hlidskjalf/src/gates/Stats.tsx +268 -0
  129. package/apps/hlidskjalf/src/gates/Tasks.tsx +173 -0
  130. package/apps/hlidskjalf/src/gates/Trace.tsx +155 -0
  131. package/apps/hlidskjalf/src/gates/Well.tsx +154 -0
  132. package/apps/hlidskjalf/src/gates/Worktrees.tsx +48 -0
  133. package/apps/hlidskjalf/src/hooks/useTenantDef.ts +13 -0
  134. package/apps/hlidskjalf/src/main.tsx +31 -0
  135. package/apps/hlidskjalf/src/services/api.ts +404 -0
  136. package/apps/hlidskjalf/src/services/auth.ts +107 -0
  137. package/apps/hlidskjalf/src/services/stream.ts +35 -0
  138. package/apps/hlidskjalf/src/state/store.ts +648 -0
  139. package/apps/hlidskjalf/src/state/ui.ts +62 -0
  140. package/apps/hlidskjalf/src/styles/auth.css +485 -0
  141. package/apps/hlidskjalf/src/styles/components.css +1259 -0
  142. package/apps/hlidskjalf/src/styles/forge.css +115 -0
  143. package/apps/hlidskjalf/src/styles/global.css +167 -0
  144. package/apps/hlidskjalf/src/styles/menus.css +175 -0
  145. package/apps/hlidskjalf/src/styles/mobile.css +298 -0
  146. package/apps/hlidskjalf/src/styles/overlays.css +205 -0
  147. package/apps/hlidskjalf/src/styles/shell.css +641 -0
  148. package/apps/hlidskjalf/src/types.ts +251 -0
  149. package/apps/hlidskjalf/src/vite-env.d.ts +9 -0
  150. package/apps/hlidskjalf/static/landing.md +6 -0
  151. package/apps/hlidskjalf/tsconfig.json +25 -0
  152. package/apps/hlidskjalf/vite.config.ts +49 -0
  153. package/apps/hlidskjalf-mobile/App.tsx +93 -0
  154. package/apps/hlidskjalf-mobile/app.json +13 -0
  155. package/apps/hlidskjalf-mobile/index.ts +4 -0
  156. package/apps/hlidskjalf-mobile/package.json +35 -0
  157. package/apps/hlidskjalf-mobile/public/icon.svg +7 -0
  158. package/apps/hlidskjalf-mobile/tsconfig.json +4 -0
  159. package/apps/odrerir/.astro/content.d.ts +159 -0
  160. package/apps/odrerir/.astro/dev.json +24 -0
  161. package/apps/odrerir/.astro/settings.json +5 -0
  162. package/apps/odrerir/.astro/types.d.ts +2 -0
  163. package/apps/odrerir/astro.config.mjs +79 -0
  164. package/apps/odrerir/dist/apple-touch-icon.png +0 -0
  165. package/apps/odrerir/dist/favicon-192.png +0 -0
  166. package/apps/odrerir/dist/favicon-32.png +0 -0
  167. package/apps/odrerir/dist/favicon-512.png +0 -0
  168. package/apps/odrerir/dist/favicon.svg +53 -0
  169. package/apps/odrerir/dist/icon.svg +7 -0
  170. package/apps/odrerir/dist/index.html +837 -0
  171. package/apps/odrerir/dist/og-square.png +0 -0
  172. package/apps/odrerir/dist/og-story.png +0 -0
  173. package/apps/odrerir/dist/og.png +0 -0
  174. package/apps/odrerir/dist/safari-pinned-tab.svg +7 -0
  175. package/apps/odrerir/dist/site.webmanifest +16 -0
  176. package/apps/odrerir/dist/styles/cloth.css +112 -0
  177. package/apps/odrerir/dist/styles/livehall.css +278 -0
  178. package/apps/odrerir/electron/icon.png +0 -0
  179. package/apps/odrerir/electron/main.cjs +183 -0
  180. package/apps/odrerir/electron/ymir-odrerir.desktop.in +12 -0
  181. package/apps/odrerir/package-lock.json +4195 -0
  182. package/apps/odrerir/package.json +30 -0
  183. package/apps/odrerir/public/apple-touch-icon.png +0 -0
  184. package/apps/odrerir/public/favicon-192.png +0 -0
  185. package/apps/odrerir/public/favicon-32.png +0 -0
  186. package/apps/odrerir/public/favicon-512.png +0 -0
  187. package/apps/odrerir/public/favicon.svg +53 -0
  188. package/apps/odrerir/public/icon.svg +7 -0
  189. package/apps/odrerir/public/og-square.png +0 -0
  190. package/apps/odrerir/public/og-story.png +0 -0
  191. package/apps/odrerir/public/og.png +0 -0
  192. package/apps/odrerir/public/safari-pinned-tab.svg +7 -0
  193. package/apps/odrerir/public/site.webmanifest +16 -0
  194. package/apps/odrerir/scripts/extract-cloth.mjs +101 -0
  195. package/apps/odrerir/src/index.html +837 -0
  196. package/apps/odrerir/src/styles/cloth.css +112 -0
  197. package/apps/odrerir/src/styles/livehall.css +278 -0
  198. package/apps/sessrumnir/.github/ISSUE_TEMPLATE/bug_report.yml +99 -0
  199. package/apps/sessrumnir/.github/ISSUE_TEMPLATE/config.yml +8 -0
  200. package/apps/sessrumnir/.github/ISSUE_TEMPLATE/feature_request.yml +46 -0
  201. package/apps/sessrumnir/.github/PULL_REQUEST_TEMPLATE.md +56 -0
  202. package/apps/sessrumnir/.github/SUPPORT.md +18 -0
  203. package/apps/sessrumnir/.github/workflows/build.yml +133 -0
  204. package/apps/sessrumnir/AGENTS.md +540 -0
  205. package/apps/sessrumnir/CLA.md +63 -0
  206. package/apps/sessrumnir/CONTRIBUTING.md +233 -0
  207. package/apps/sessrumnir/LICENSE +200 -0
  208. package/apps/sessrumnir/NOTICE +33 -0
  209. package/apps/sessrumnir/README.md +329 -0
  210. package/apps/sessrumnir/bin/sessrumnir-web.sh +117 -0
  211. package/apps/sessrumnir/bin/sessrumnir.js +169 -0
  212. package/apps/sessrumnir/docs/CNAME +1 -0
  213. package/apps/sessrumnir/docs/favicon.ico +0 -0
  214. package/apps/sessrumnir/docs/icon-512.png +0 -0
  215. package/apps/sessrumnir/docs/index.html +441 -0
  216. package/apps/sessrumnir/docs/robots.txt +4 -0
  217. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_181929.png +0 -0
  218. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182005.png +0 -0
  219. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182020.png +0 -0
  220. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182039.png +0 -0
  221. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182117.png +0 -0
  222. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182225.png +0 -0
  223. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182248.png +0 -0
  224. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182322.png +0 -0
  225. package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182340.png +0 -0
  226. package/apps/sessrumnir/docs/sitemap.xml +9 -0
  227. package/apps/sessrumnir/electron.vite.config.ts +49 -0
  228. package/apps/sessrumnir/eslint.config.mjs +75 -0
  229. package/apps/sessrumnir/i18next.config.ts +33 -0
  230. package/apps/sessrumnir/install.sh +144 -0
  231. package/apps/sessrumnir/out/main/index.js +10881 -0
  232. package/apps/sessrumnir/out/preload/index.js +722 -0
  233. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-400-normal-C8QS47vb.woff2 +0 -0
  234. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-400-normal-D3EsxgFc.woff +0 -0
  235. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-500-normal-B7dJQtg-.woff +0 -0
  236. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-500-normal-BLlg2W5x.woff2 +0 -0
  237. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-600-normal-BcIsDXzC.woff2 +0 -0
  238. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-600-normal-CBymlcNF.woff +0 -0
  239. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-400-normal-Bgrpe4p1.woff +0 -0
  240. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-400-normal-BlcaxZtM.woff2 +0 -0
  241. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-500-normal-CdQuyvtc.woff +0 -0
  242. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-500-normal-pZw22qtS.woff2 +0 -0
  243. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-600-normal-Dr-wLyOm.woff +0 -0
  244. package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-600-normal-dLR2-a_v.woff2 +0 -0
  245. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-400-normal-BGH8Vunh.woff2 +0 -0
  246. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-400-normal-C3_-2Ua-.woff +0 -0
  247. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-500-normal-Dj3SQ6fR.woff +0 -0
  248. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-500-normal-EBdSCOD3.woff2 +0 -0
  249. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-600-normal-B254Xisw.woff2 +0 -0
  250. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-600-normal-DUW-TI76.woff +0 -0
  251. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-400-normal-DuQ88yz3.woff2 +0 -0
  252. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-400-normal-DuXFa1Dr.woff +0 -0
  253. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2 +0 -0
  254. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-500-normal-DAuUCO41.woff +0 -0
  255. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-600-normal-CD-dlDpD.woff +0 -0
  256. package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-600-normal-D3T6BBXG.woff2 +0 -0
  257. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-400-normal-C-RiYxEf.woff2 +0 -0
  258. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-400-normal-DmUuA7Y2.woff +0 -0
  259. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-500-normal-DsPuwQHi.woff2 +0 -0
  260. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-500-normal-tGBW_mI7.woff +0 -0
  261. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-600-normal-Dar_cCT6.woff2 +0 -0
  262. package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-600-normal-GIs8CF2x.woff +0 -0
  263. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-300-normal-Ba-HN6uq.woff +0 -0
  264. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-300-normal-ByB2hQUF.woff2 +0 -0
  265. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
  266. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
  267. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
  268. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
  269. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-300-normal-B8O3uHbr.woff +0 -0
  270. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-300-normal-BbtBtHoB.woff2 +0 -0
  271. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
  272. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
  273. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
  274. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
  275. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-300-normal-BPU54Tw3.woff +0 -0
  276. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-300-normal-BRS-C4KA.woff2 +0 -0
  277. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  278. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  279. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  280. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  281. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-300-normal-BEtQ2wm2.woff2 +0 -0
  282. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-300-normal-CQbCaAQ4.woff +0 -0
  283. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
  284. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
  285. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
  286. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
  287. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-300-normal-B6fSpYYV.woff +0 -0
  288. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-300-normal-CpdbWO_2.woff2 +0 -0
  289. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
  290. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
  291. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
  292. package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
  293. package/apps/sessrumnir/out/renderer/assets/index-BxqsRq2x.css +4858 -0
  294. package/apps/sessrumnir/out/renderer/assets/index-TaD69rFk.js +99435 -0
  295. package/apps/sessrumnir/out/renderer/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  296. package/apps/sessrumnir/out/renderer/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  297. package/apps/sessrumnir/out/renderer/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  298. package/apps/sessrumnir/out/renderer/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  299. package/apps/sessrumnir/out/renderer/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  300. package/apps/sessrumnir/out/renderer/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  301. package/apps/sessrumnir/out/renderer/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  302. package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
  303. package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
  304. package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  305. package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  306. package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
  307. package/apps/sessrumnir/out/renderer/assets/newsreader-latin-ext-wght-italic-DFS986qL.woff2 +0 -0
  308. package/apps/sessrumnir/out/renderer/assets/newsreader-latin-ext-wght-normal-C-3rgBeH.woff2 +0 -0
  309. package/apps/sessrumnir/out/renderer/assets/newsreader-latin-wght-italic-Bxi8ein9.woff2 +0 -0
  310. package/apps/sessrumnir/out/renderer/assets/newsreader-latin-wght-normal-CCVVNp6i.woff2 +0 -0
  311. package/apps/sessrumnir/out/renderer/assets/newsreader-vietnamese-wght-italic-xAqemagA.woff2 +0 -0
  312. package/apps/sessrumnir/out/renderer/assets/newsreader-vietnamese-wght-normal-Czsa-EzN.woff2 +0 -0
  313. package/apps/sessrumnir/out/renderer/assets/openmoji-color-9qo_2DLG.woff2 +0 -0
  314. package/apps/sessrumnir/out/renderer/assets/pi-logo-B6SVnhuS.svg +7 -0
  315. package/apps/sessrumnir/out/renderer/index.html +19 -0
  316. package/apps/sessrumnir/out/renderer/theme-boot.js +30 -0
  317. package/apps/sessrumnir/package-lock.json +10636 -0
  318. package/apps/sessrumnir/package.json +183 -0
  319. package/apps/sessrumnir/public/apple-touch-icon.png +0 -0
  320. package/apps/sessrumnir/public/icon.svg +7 -0
  321. package/apps/sessrumnir/resources/icons/generate_icons.py +38 -0
  322. package/apps/sessrumnir/resources/icons/icon-128.png +0 -0
  323. package/apps/sessrumnir/resources/icons/icon-16.png +0 -0
  324. package/apps/sessrumnir/resources/icons/icon-256.png +0 -0
  325. package/apps/sessrumnir/resources/icons/icon-32.png +0 -0
  326. package/apps/sessrumnir/resources/icons/icon-48.png +0 -0
  327. package/apps/sessrumnir/resources/icons/icon-512.png +0 -0
  328. package/apps/sessrumnir/resources/icons/icon-64.png +0 -0
  329. package/apps/sessrumnir/resources/icons/icon.icns +0 -0
  330. package/apps/sessrumnir/resources/icons/icon.ico +0 -0
  331. package/apps/sessrumnir/resources/icons/icon.png +0 -0
  332. package/apps/sessrumnir/resources/icons/icon.svg +7 -0
  333. package/apps/sessrumnir/resources/linux/after-install.sh +23 -0
  334. package/apps/sessrumnir/resources/linux/after-remove.sh +18 -0
  335. package/apps/sessrumnir/resources/locales/en/translation.json +1735 -0
  336. package/apps/sessrumnir/resources/permission-prompt-text.test.ts +111 -0
  337. package/apps/sessrumnir/resources/permission-prompt-text.ts +84 -0
  338. package/apps/sessrumnir/resources/permission-rules.test.ts +351 -0
  339. package/apps/sessrumnir/resources/permission-rules.ts +293 -0
  340. package/apps/sessrumnir/resources/pi-desktop-permissions.ts +62 -0
  341. package/apps/sessrumnir/resources/ymir-sessrumnir.desktop.in +12 -0
  342. package/apps/sessrumnir/scripts/check-semantic-colors.mjs +57 -0
  343. package/apps/sessrumnir/src/main/activity-stats.test.ts +240 -0
  344. package/apps/sessrumnir/src/main/activity-stats.ts +596 -0
  345. package/apps/sessrumnir/src/main/agent-detection.test.ts +25 -0
  346. package/apps/sessrumnir/src/main/agent-detection.ts +114 -0
  347. package/apps/sessrumnir/src/main/app-data-paths.test.ts +90 -0
  348. package/apps/sessrumnir/src/main/app-data-paths.ts +95 -0
  349. package/apps/sessrumnir/src/main/app-log.test.ts +114 -0
  350. package/apps/sessrumnir/src/main/app-log.ts +210 -0
  351. package/apps/sessrumnir/src/main/archived-sessions.test.ts +50 -0
  352. package/apps/sessrumnir/src/main/archived-sessions.ts +95 -0
  353. package/apps/sessrumnir/src/main/attachment-reader.test.ts +56 -0
  354. package/apps/sessrumnir/src/main/attachment-reader.ts +52 -0
  355. package/apps/sessrumnir/src/main/auto-tag.test.ts +38 -0
  356. package/apps/sessrumnir/src/main/auto-tag.ts +75 -0
  357. package/apps/sessrumnir/src/main/autostart-linux.test.ts +56 -0
  358. package/apps/sessrumnir/src/main/autostart-linux.ts +58 -0
  359. package/apps/sessrumnir/src/main/cmd-escape.test.ts +424 -0
  360. package/apps/sessrumnir/src/main/cmd-escape.ts +186 -0
  361. package/apps/sessrumnir/src/main/council-manager.test.ts +167 -0
  362. package/apps/sessrumnir/src/main/council-manager.ts +265 -0
  363. package/apps/sessrumnir/src/main/diagnostics-report.test.ts +140 -0
  364. package/apps/sessrumnir/src/main/diagnostics-report.ts +91 -0
  365. package/apps/sessrumnir/src/main/diagnostics.ts +111 -0
  366. package/apps/sessrumnir/src/main/editor-guard.test.ts +59 -0
  367. package/apps/sessrumnir/src/main/editor-guard.ts +50 -0
  368. package/apps/sessrumnir/src/main/extension-ui-ipc.test.ts +299 -0
  369. package/apps/sessrumnir/src/main/extension-ui-ipc.ts +117 -0
  370. package/apps/sessrumnir/src/main/file-service.test.ts +279 -0
  371. package/apps/sessrumnir/src/main/file-service.ts +652 -0
  372. package/apps/sessrumnir/src/main/fs-errors.ts +42 -0
  373. package/apps/sessrumnir/src/main/get-messages-trim.test.ts +77 -0
  374. package/apps/sessrumnir/src/main/get-messages-trim.ts +97 -0
  375. package/apps/sessrumnir/src/main/git-conveyor.test.ts +305 -0
  376. package/apps/sessrumnir/src/main/git-conveyor.ts +338 -0
  377. package/apps/sessrumnir/src/main/git-worktree.test.ts +101 -0
  378. package/apps/sessrumnir/src/main/git-worktree.ts +201 -0
  379. package/apps/sessrumnir/src/main/i18n.ts +31 -0
  380. package/apps/sessrumnir/src/main/index.ts +619 -0
  381. package/apps/sessrumnir/src/main/ipc/active-engine.ts +15 -0
  382. package/apps/sessrumnir/src/main/ipc/context.ts +58 -0
  383. package/apps/sessrumnir/src/main/ipc/council-handlers.ts +126 -0
  384. package/apps/sessrumnir/src/main/ipc/diagnostics-handlers.ts +8 -0
  385. package/apps/sessrumnir/src/main/ipc/file-handlers.ts +96 -0
  386. package/apps/sessrumnir/src/main/ipc/git-conveyor-handlers.ts +55 -0
  387. package/apps/sessrumnir/src/main/ipc/model-handlers.ts +33 -0
  388. package/apps/sessrumnir/src/main/ipc/models-config-handlers.ts +80 -0
  389. package/apps/sessrumnir/src/main/ipc/notes-handlers.ts +65 -0
  390. package/apps/sessrumnir/src/main/ipc/package-handlers.ts +330 -0
  391. package/apps/sessrumnir/src/main/ipc/permission-rules-handlers.ts +223 -0
  392. package/apps/sessrumnir/src/main/ipc/pi-handlers.ts +136 -0
  393. package/apps/sessrumnir/src/main/ipc/pi-start-options.ts +150 -0
  394. package/apps/sessrumnir/src/main/ipc/run-pi-cli.ts +53 -0
  395. package/apps/sessrumnir/src/main/ipc/session-handlers.ts +491 -0
  396. package/apps/sessrumnir/src/main/ipc/settings.ts +120 -0
  397. package/apps/sessrumnir/src/main/ipc/skills-mcp-handlers.ts +192 -0
  398. package/apps/sessrumnir/src/main/ipc/system-handlers.ts +131 -0
  399. package/apps/sessrumnir/src/main/ipc/tag-handlers.ts +69 -0
  400. package/apps/sessrumnir/src/main/ipc/terminal-handlers.ts +41 -0
  401. package/apps/sessrumnir/src/main/ipc/theme-handlers.ts +131 -0
  402. package/apps/sessrumnir/src/main/ipc/update-handlers.ts +61 -0
  403. package/apps/sessrumnir/src/main/ipc/validation.ts +45 -0
  404. package/apps/sessrumnir/src/main/ipc/workflow-handlers.ts +108 -0
  405. package/apps/sessrumnir/src/main/ipc/workspace-activity-wiring.ts +179 -0
  406. package/apps/sessrumnir/src/main/ipc/workspace-handlers.ts +133 -0
  407. package/apps/sessrumnir/src/main/ipc-handlers.ts +98 -0
  408. package/apps/sessrumnir/src/main/map-concurrent.test.ts +80 -0
  409. package/apps/sessrumnir/src/main/map-concurrent.ts +30 -0
  410. package/apps/sessrumnir/src/main/models-file.test.ts +114 -0
  411. package/apps/sessrumnir/src/main/models-file.ts +89 -0
  412. package/apps/sessrumnir/src/main/notes-manager.test.ts +64 -0
  413. package/apps/sessrumnir/src/main/notes-manager.ts +183 -0
  414. package/apps/sessrumnir/src/main/notify-decision.test.ts +39 -0
  415. package/apps/sessrumnir/src/main/notify-decision.ts +25 -0
  416. package/apps/sessrumnir/src/main/omp-fork-points.test.ts +119 -0
  417. package/apps/sessrumnir/src/main/omp-fork-points.ts +105 -0
  418. package/apps/sessrumnir/src/main/omp-plugin-list.test.ts +94 -0
  419. package/apps/sessrumnir/src/main/omp-plugin-list.ts +103 -0
  420. package/apps/sessrumnir/src/main/package-catalog.test.ts +157 -0
  421. package/apps/sessrumnir/src/main/package-catalog.ts +166 -0
  422. package/apps/sessrumnir/src/main/package-updates.test.ts +149 -0
  423. package/apps/sessrumnir/src/main/package-updates.ts +185 -0
  424. package/apps/sessrumnir/src/main/path-authorization.test.ts +64 -0
  425. package/apps/sessrumnir/src/main/path-authorization.ts +31 -0
  426. package/apps/sessrumnir/src/main/pi-binary-resolution.test.ts +582 -0
  427. package/apps/sessrumnir/src/main/pi-binary-resolution.ts +649 -0
  428. package/apps/sessrumnir/src/main/pi-event-router.test.ts +388 -0
  429. package/apps/sessrumnir/src/main/pi-event-router.ts +290 -0
  430. package/apps/sessrumnir/src/main/pi-paths.test.ts +134 -0
  431. package/apps/sessrumnir/src/main/pi-paths.ts +74 -0
  432. package/apps/sessrumnir/src/main/pi-rpc-manager.test.ts +467 -0
  433. package/apps/sessrumnir/src/main/pi-rpc-manager.ts +1319 -0
  434. package/apps/sessrumnir/src/main/process-tree.test.ts +94 -0
  435. package/apps/sessrumnir/src/main/renderer-origin.test.ts +33 -0
  436. package/apps/sessrumnir/src/main/renderer-origin.ts +35 -0
  437. package/apps/sessrumnir/src/main/session-lineage-reader.test.ts +317 -0
  438. package/apps/sessrumnir/src/main/session-lineage-reader.ts +111 -0
  439. package/apps/sessrumnir/src/main/session-metadata.test.ts +508 -0
  440. package/apps/sessrumnir/src/main/session-metadata.ts +526 -0
  441. package/apps/sessrumnir/src/main/session-name.test.ts +71 -0
  442. package/apps/sessrumnir/src/main/session-name.ts +69 -0
  443. package/apps/sessrumnir/src/main/session-paths.test.ts +110 -0
  444. package/apps/sessrumnir/src/main/session-paths.ts +88 -0
  445. package/apps/sessrumnir/src/main/session-tags.test.ts +61 -0
  446. package/apps/sessrumnir/src/main/session-tags.ts +253 -0
  447. package/apps/sessrumnir/src/main/session-trash.test.ts +66 -0
  448. package/apps/sessrumnir/src/main/session-trash.ts +65 -0
  449. package/apps/sessrumnir/src/main/settings-logic.ts +66 -0
  450. package/apps/sessrumnir/src/main/skills-discovery.test.ts +149 -0
  451. package/apps/sessrumnir/src/main/skills-discovery.ts +179 -0
  452. package/apps/sessrumnir/src/main/startup-launch.ts +63 -0
  453. package/apps/sessrumnir/src/main/terminal-service.ts +96 -0
  454. package/apps/sessrumnir/src/main/theme-store.test.ts +440 -0
  455. package/apps/sessrumnir/src/main/theme-store.ts +495 -0
  456. package/apps/sessrumnir/src/main/tray-decision.test.ts +46 -0
  457. package/apps/sessrumnir/src/main/tray-decision.ts +49 -0
  458. package/apps/sessrumnir/src/main/tray-manager.ts +220 -0
  459. package/apps/sessrumnir/src/main/tsconfig.json +20 -0
  460. package/apps/sessrumnir/src/main/window-background.test.ts +29 -0
  461. package/apps/sessrumnir/src/main/window-background.ts +16 -0
  462. package/apps/sessrumnir/src/main/workflow-discovery.test.ts +252 -0
  463. package/apps/sessrumnir/src/main/workflow-monitor.test.ts +371 -0
  464. package/apps/sessrumnir/src/main/workflow-monitor.ts +1020 -0
  465. package/apps/sessrumnir/src/main/workspace-activity.test.ts +227 -0
  466. package/apps/sessrumnir/src/main/workspace-activity.ts +215 -0
  467. package/apps/sessrumnir/src/main/workspace-manager.test.ts +680 -0
  468. package/apps/sessrumnir/src/main/workspace-manager.ts +1199 -0
  469. package/apps/sessrumnir/src/main/workspace-trust.test.ts +78 -0
  470. package/apps/sessrumnir/src/main/workspace-trust.ts +84 -0
  471. package/apps/sessrumnir/src/preload/index.ts +358 -0
  472. package/apps/sessrumnir/src/preload/tsconfig.json +20 -0
  473. package/apps/sessrumnir/src/renderer/index.html +18 -0
  474. package/apps/sessrumnir/src/renderer/public/theme-boot.js +30 -0
  475. package/apps/sessrumnir/src/renderer/src/app.tsx +194 -0
  476. package/apps/sessrumnir/src/renderer/src/assets/openmoji-color.woff2 +0 -0
  477. package/apps/sessrumnir/src/renderer/src/assets/pi-logo.svg +7 -0
  478. package/apps/sessrumnir/src/renderer/src/assets/ymir-mark.svg +55 -0
  479. package/apps/sessrumnir/src/renderer/src/assets.d.ts +7 -0
  480. package/apps/sessrumnir/src/renderer/src/components/chat-code-highlight.ts +239 -0
  481. package/apps/sessrumnir/src/renderer/src/components/chat-file-link.ts +140 -0
  482. package/apps/sessrumnir/src/renderer/src/components/chat-input.tsx +729 -0
  483. package/apps/sessrumnir/src/renderer/src/components/chat-panel-widths.test.ts +175 -0
  484. package/apps/sessrumnir/src/renderer/src/components/chat-panel-widths.ts +100 -0
  485. package/apps/sessrumnir/src/renderer/src/components/chat-panel.tsx +523 -0
  486. package/apps/sessrumnir/src/renderer/src/components/chat-project-picker.tsx +193 -0
  487. package/apps/sessrumnir/src/renderer/src/components/chat-search.tsx +251 -0
  488. package/apps/sessrumnir/src/renderer/src/components/code-editor-highlight.ts +85 -0
  489. package/apps/sessrumnir/src/renderer/src/components/code-editor-language.test.ts +19 -0
  490. package/apps/sessrumnir/src/renderer/src/components/code-editor-language.ts +88 -0
  491. package/apps/sessrumnir/src/renderer/src/components/code-editor.tsx +128 -0
  492. package/apps/sessrumnir/src/renderer/src/components/command-palette.tsx +315 -0
  493. package/apps/sessrumnir/src/renderer/src/components/command-results.tsx +80 -0
  494. package/apps/sessrumnir/src/renderer/src/components/composer-permission-menu.tsx +91 -0
  495. package/apps/sessrumnir/src/renderer/src/components/context-menu.tsx +457 -0
  496. package/apps/sessrumnir/src/renderer/src/components/copy-button.tsx +36 -0
  497. package/apps/sessrumnir/src/renderer/src/components/council-panels.tsx +193 -0
  498. package/apps/sessrumnir/src/renderer/src/components/custom-models-editor.tsx +330 -0
  499. package/apps/sessrumnir/src/renderer/src/components/diagnostics-panel.tsx +380 -0
  500. package/apps/sessrumnir/src/renderer/src/components/diff-viewer.tsx +318 -0
  501. package/apps/sessrumnir/src/renderer/src/components/ember-background.tsx +113 -0
  502. package/apps/sessrumnir/src/renderer/src/components/error-boundary.tsx +38 -0
  503. package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog-helpers.test.ts +43 -0
  504. package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog-helpers.ts +51 -0
  505. package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog.tsx +486 -0
  506. package/apps/sessrumnir/src/renderer/src/components/file-tree.tsx +784 -0
  507. package/apps/sessrumnir/src/renderer/src/components/git-conveyor-actions.tsx +246 -0
  508. package/apps/sessrumnir/src/renderer/src/components/home-screen.tsx +396 -0
  509. package/apps/sessrumnir/src/renderer/src/components/image-viewer.tsx +100 -0
  510. package/apps/sessrumnir/src/renderer/src/components/line-numbered-code.tsx +58 -0
  511. package/apps/sessrumnir/src/renderer/src/components/markdown-renderer.tsx +237 -0
  512. package/apps/sessrumnir/src/renderer/src/components/message-bubble.tsx +1006 -0
  513. package/apps/sessrumnir/src/renderer/src/components/mission-control.tsx +341 -0
  514. package/apps/sessrumnir/src/renderer/src/components/model-selector.tsx +219 -0
  515. package/apps/sessrumnir/src/renderer/src/components/note-picker.tsx +155 -0
  516. package/apps/sessrumnir/src/renderer/src/components/notes-panel.tsx +437 -0
  517. package/apps/sessrumnir/src/renderer/src/components/package-browser.tsx +604 -0
  518. package/apps/sessrumnir/src/renderer/src/components/permission-mode.test.ts +22 -0
  519. package/apps/sessrumnir/src/renderer/src/components/permission-mode.ts +49 -0
  520. package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor-helpers.test.ts +44 -0
  521. package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor-helpers.ts +35 -0
  522. package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor.tsx +226 -0
  523. package/apps/sessrumnir/src/renderer/src/components/permission-selector.tsx +104 -0
  524. package/apps/sessrumnir/src/renderer/src/components/resize-handle.tsx +51 -0
  525. package/apps/sessrumnir/src/renderer/src/components/review-rail.tsx +194 -0
  526. package/apps/sessrumnir/src/renderer/src/components/session-menu-position.test.ts +22 -0
  527. package/apps/sessrumnir/src/renderer/src/components/session-menu-position.ts +34 -0
  528. package/apps/sessrumnir/src/renderer/src/components/session-panel.tsx +711 -0
  529. package/apps/sessrumnir/src/renderer/src/components/session-runtime-indicator.tsx +43 -0
  530. package/apps/sessrumnir/src/renderer/src/components/settings-panel.tsx +1360 -0
  531. package/apps/sessrumnir/src/renderer/src/components/sidebar-activity.test.ts +47 -0
  532. package/apps/sessrumnir/src/renderer/src/components/sidebar-activity.ts +76 -0
  533. package/apps/sessrumnir/src/renderer/src/components/sidebar-session-labels.test.ts +73 -0
  534. package/apps/sessrumnir/src/renderer/src/components/sidebar-session-labels.ts +47 -0
  535. package/apps/sessrumnir/src/renderer/src/components/sidebar.tsx +1045 -0
  536. package/apps/sessrumnir/src/renderer/src/components/skills-panel.tsx +159 -0
  537. package/apps/sessrumnir/src/renderer/src/components/stats-panel.tsx +368 -0
  538. package/apps/sessrumnir/src/renderer/src/components/status-bar.tsx +274 -0
  539. package/apps/sessrumnir/src/renderer/src/components/status-popover.tsx +481 -0
  540. package/apps/sessrumnir/src/renderer/src/components/streaming-bubble.tsx +128 -0
  541. package/apps/sessrumnir/src/renderer/src/components/subagent-progress.tsx +254 -0
  542. package/apps/sessrumnir/src/renderer/src/components/task-launcher.tsx +168 -0
  543. package/apps/sessrumnir/src/renderer/src/components/terminal.tsx +203 -0
  544. package/apps/sessrumnir/src/renderer/src/components/theme-editor-helpers.test.ts +35 -0
  545. package/apps/sessrumnir/src/renderer/src/components/theme-editor-helpers.ts +35 -0
  546. package/apps/sessrumnir/src/renderer/src/components/theme-editor.tsx +440 -0
  547. package/apps/sessrumnir/src/renderer/src/components/theme-gallery.tsx +373 -0
  548. package/apps/sessrumnir/src/renderer/src/components/thinking-level-selector.tsx +85 -0
  549. package/apps/sessrumnir/src/renderer/src/components/timeline.tsx +289 -0
  550. package/apps/sessrumnir/src/renderer/src/components/tool-call-icon.ts +32 -0
  551. package/apps/sessrumnir/src/renderer/src/components/workflow-navigator.tsx +901 -0
  552. package/apps/sessrumnir/src/renderer/src/components/workspace-tabs.tsx +241 -0
  553. package/apps/sessrumnir/src/renderer/src/global.d.ts +8 -0
  554. package/apps/sessrumnir/src/renderer/src/hooks/use-folder-drop.ts +101 -0
  555. package/apps/sessrumnir/src/renderer/src/hooks.test.ts +88 -0
  556. package/apps/sessrumnir/src/renderer/src/hooks.ts +574 -0
  557. package/apps/sessrumnir/src/renderer/src/i18n.test.ts +54 -0
  558. package/apps/sessrumnir/src/renderer/src/i18n.ts +89 -0
  559. package/apps/sessrumnir/src/renderer/src/index.css +425 -0
  560. package/apps/sessrumnir/src/renderer/src/main.tsx +42 -0
  561. package/apps/sessrumnir/src/renderer/src/message-grouping.test.ts +422 -0
  562. package/apps/sessrumnir/src/renderer/src/message-grouping.ts +410 -0
  563. package/apps/sessrumnir/src/renderer/src/message-parsing.test.ts +86 -0
  564. package/apps/sessrumnir/src/renderer/src/message-parsing.ts +166 -0
  565. package/apps/sessrumnir/src/renderer/src/store-external-prompts.test.ts +161 -0
  566. package/apps/sessrumnir/src/renderer/src/store-session-transitions.test.ts +2090 -0
  567. package/apps/sessrumnir/src/renderer/src/store-timeline.test.ts +52 -0
  568. package/apps/sessrumnir/src/renderer/src/store-turn-error.test.ts +136 -0
  569. package/apps/sessrumnir/src/renderer/src/store.ts +3726 -0
  570. package/apps/sessrumnir/src/renderer/src/subagent-detection.test.ts +55 -0
  571. package/apps/sessrumnir/src/renderer/src/theme/engine.test.ts +29 -0
  572. package/apps/sessrumnir/src/renderer/src/theme/engine.ts +20 -0
  573. package/apps/sessrumnir/src/renderer/src/themes/breeze-claudius.json +69 -0
  574. package/apps/sessrumnir/src/renderer/src/themes/breeze-dark.json +69 -0
  575. package/apps/sessrumnir/src/renderer/src/themes/breeze-light.json +69 -0
  576. package/apps/sessrumnir/src/renderer/src/themes/builtin-themes.test.ts +95 -0
  577. package/apps/sessrumnir/src/renderer/src/themes/dark.json +46 -0
  578. package/apps/sessrumnir/src/renderer/src/themes/fensalir.json +82 -0
  579. package/apps/sessrumnir/src/renderer/src/themes/gruvbox.json +69 -0
  580. package/apps/sessrumnir/src/renderer/src/themes/index.ts +60 -0
  581. package/apps/sessrumnir/src/renderer/src/themes/light.json +46 -0
  582. package/apps/sessrumnir/src/renderer/src/themes/nord.json +69 -0
  583. package/apps/sessrumnir/src/renderer/src/themes/sessrumnir.json +82 -0
  584. package/apps/sessrumnir/src/renderer/src/utils/debounced-buffer.test.ts +81 -0
  585. package/apps/sessrumnir/src/renderer/src/utils/debounced-buffer.ts +57 -0
  586. package/apps/sessrumnir/src/renderer/src/utils/format-relative-time.test.ts +62 -0
  587. package/apps/sessrumnir/src/renderer/src/utils/format-relative-time.ts +28 -0
  588. package/apps/sessrumnir/src/renderer/src/utils/heatmap-grid.test.ts +57 -0
  589. package/apps/sessrumnir/src/renderer/src/utils/heatmap-grid.ts +41 -0
  590. package/apps/sessrumnir/src/renderer/src/utils/ipc-error.test.ts +22 -0
  591. package/apps/sessrumnir/src/renderer/src/utils/ipc-error.ts +12 -0
  592. package/apps/sessrumnir/src/renderer/src/utils/model-search.test.ts +63 -0
  593. package/apps/sessrumnir/src/renderer/src/utils/model-search.ts +20 -0
  594. package/apps/sessrumnir/src/renderer/src/utils/planning-prompt.test.ts +31 -0
  595. package/apps/sessrumnir/src/renderer/src/utils/planning-prompt.ts +27 -0
  596. package/apps/sessrumnir/src/renderer/src/utils/preview-load-error.test.ts +15 -0
  597. package/apps/sessrumnir/src/renderer/src/utils/preview-load-error.ts +22 -0
  598. package/apps/sessrumnir/src/renderer/src/utils/process-status-label.test.ts +13 -0
  599. package/apps/sessrumnir/src/renderer/src/utils/process-status-label.ts +19 -0
  600. package/apps/sessrumnir/src/renderer/src/utils/quick-switcher.test.ts +68 -0
  601. package/apps/sessrumnir/src/renderer/src/utils/quick-switcher.ts +52 -0
  602. package/apps/sessrumnir/src/renderer/src/utils/rank-file-results.test.ts +46 -0
  603. package/apps/sessrumnir/src/renderer/src/utils/rank-file-results.ts +23 -0
  604. package/apps/sessrumnir/src/renderer/src/utils/relative-time.tsx +25 -0
  605. package/apps/sessrumnir/src/renderer/src/utils/session-title.test.ts +98 -0
  606. package/apps/sessrumnir/src/renderer/src/utils/session-title.ts +58 -0
  607. package/apps/sessrumnir/src/renderer/src/utils/stale-guard.test.ts +29 -0
  608. package/apps/sessrumnir/src/renderer/src/utils/stale-guard.ts +20 -0
  609. package/apps/sessrumnir/src/renderer/src/utils/theme.test.ts +174 -0
  610. package/apps/sessrumnir/src/renderer/src/utils/theme.ts +159 -0
  611. package/apps/sessrumnir/src/renderer/src/utils/workflow-runs.test.ts +130 -0
  612. package/apps/sessrumnir/src/renderer/src/utils/workflow-runs.ts +84 -0
  613. package/apps/sessrumnir/src/renderer/tsconfig.json +24 -0
  614. package/apps/sessrumnir/src/shared/agent-engine-label.test.ts +45 -0
  615. package/apps/sessrumnir/src/shared/agent-engine-label.ts +53 -0
  616. package/apps/sessrumnir/src/shared/app-settings.test.ts +25 -0
  617. package/apps/sessrumnir/src/shared/app-settings.ts +23 -0
  618. package/apps/sessrumnir/src/shared/bridge-http.ts +341 -0
  619. package/apps/sessrumnir/src/shared/bridge.ts +337 -0
  620. package/apps/sessrumnir/src/shared/council-config.test.ts +300 -0
  621. package/apps/sessrumnir/src/shared/council-config.ts +356 -0
  622. package/apps/sessrumnir/src/shared/default-settings.ts +39 -0
  623. package/apps/sessrumnir/src/shared/folder-drop.test.ts +118 -0
  624. package/apps/sessrumnir/src/shared/folder-drop.ts +74 -0
  625. package/apps/sessrumnir/src/shared/fork-point.test.ts +30 -0
  626. package/apps/sessrumnir/src/shared/fork-point.ts +24 -0
  627. package/apps/sessrumnir/src/shared/i18n/i18next.d.ts +10 -0
  628. package/apps/sessrumnir/src/shared/i18n/index.test.ts +51 -0
  629. package/apps/sessrumnir/src/shared/i18n/index.ts +50 -0
  630. package/apps/sessrumnir/src/shared/i18n/languages.ts +12 -0
  631. package/apps/sessrumnir/src/shared/i18n/locale-checks.ts +98 -0
  632. package/apps/sessrumnir/src/shared/i18n/locales.test.ts +92 -0
  633. package/apps/sessrumnir/src/shared/i18n/pseudo.test.ts +39 -0
  634. package/apps/sessrumnir/src/shared/i18n/pseudo.ts +44 -0
  635. package/apps/sessrumnir/src/shared/i18n/resolve.test.ts +43 -0
  636. package/apps/sessrumnir/src/shared/i18n/resolve.ts +41 -0
  637. package/apps/sessrumnir/src/shared/i18n/resources.ts +11 -0
  638. package/apps/sessrumnir/src/shared/ipc-contracts.ts +1539 -0
  639. package/apps/sessrumnir/src/shared/models-config.test.ts +124 -0
  640. package/apps/sessrumnir/src/shared/models-config.ts +167 -0
  641. package/apps/sessrumnir/src/shared/package-filter.ts +19 -0
  642. package/apps/sessrumnir/src/shared/package-spec.test.ts +51 -0
  643. package/apps/sessrumnir/src/shared/package-spec.ts +25 -0
  644. package/apps/sessrumnir/src/shared/path-compare.test.ts +38 -0
  645. package/apps/sessrumnir/src/shared/path-compare.ts +76 -0
  646. package/apps/sessrumnir/src/shared/permission-mode.ts +8 -0
  647. package/apps/sessrumnir/src/shared/pi-command.test.ts +165 -0
  648. package/apps/sessrumnir/src/shared/pi-command.ts +139 -0
  649. package/apps/sessrumnir/src/shared/product-name.ts +7 -0
  650. package/apps/sessrumnir/src/shared/session-lineage.test.ts +103 -0
  651. package/apps/sessrumnir/src/shared/session-lineage.ts +50 -0
  652. package/apps/sessrumnir/src/shared/session-preview.test.ts +93 -0
  653. package/apps/sessrumnir/src/shared/session-preview.ts +56 -0
  654. package/apps/sessrumnir/src/shared/sidebar-width.test.ts +58 -0
  655. package/apps/sessrumnir/src/shared/sidebar-width.ts +37 -0
  656. package/apps/sessrumnir/src/shared/theme/builtin-ids.ts +16 -0
  657. package/apps/sessrumnir/src/shared/theme/resolve.test.ts +66 -0
  658. package/apps/sessrumnir/src/shared/theme/resolve.ts +29 -0
  659. package/apps/sessrumnir/src/shared/theme/syntax-defaults.ts +24 -0
  660. package/apps/sessrumnir/src/shared/theme/theme-file.test.ts +88 -0
  661. package/apps/sessrumnir/src/shared/theme/theme-file.ts +132 -0
  662. package/apps/sessrumnir/src/shared/theme/tokens.test.ts +35 -0
  663. package/apps/sessrumnir/src/shared/theme/tokens.ts +86 -0
  664. package/apps/sessrumnir/src/shared/tsconfig.json +17 -0
  665. package/apps/sessrumnir/src/shared/untrusted-data.test.ts +32 -0
  666. package/apps/sessrumnir/src/shared/untrusted-data.ts +22 -0
  667. package/apps/sessrumnir/src/shared/version-compare.test.ts +33 -0
  668. package/apps/sessrumnir/src/shared/version-compare.ts +50 -0
  669. package/apps/sessrumnir/src/shared/workflow-control.ts +33 -0
  670. package/apps/sessrumnir/src/web-server.ts +315 -0
  671. package/apps/sessrumnir/tsconfig.json +26 -0
  672. package/apps/smidja/smidja_build.py +45 -0
  673. package/apps/smidja/smidja_build_review.py +76 -0
  674. package/apps/smidja/smidja_build_test.py +79 -0
  675. package/apps/smidja/smidja_document.py +76 -0
  676. package/apps/smidja/smidja_modules/agent_cc.py +15 -0
  677. package/apps/smidja/smidja_modules/agent_opencode.py +194 -0
  678. package/apps/smidja/smidja_modules/agent_pi.py +392 -0
  679. package/apps/smidja/smidja_modules/agents.py +993 -0
  680. package/apps/smidja/smidja_modules/changes.py +103 -0
  681. package/apps/smidja/smidja_modules/console.py +131 -0
  682. package/apps/smidja/smidja_modules/data_types.py +447 -0
  683. package/apps/smidja/smidja_modules/gates.py +108 -0
  684. package/apps/smidja/smidja_modules/git_helper.py +120 -0
  685. package/apps/smidja/smidja_modules/lm_local.py +144 -0
  686. package/apps/smidja/smidja_modules/permissions.py +194 -0
  687. package/apps/smidja/smidja_modules/prompts.py +21 -0
  688. package/apps/smidja/smidja_modules/quality.py +240 -0
  689. package/apps/smidja/smidja_modules/runner.py +155 -0
  690. package/apps/smidja/smidja_modules/session.py +50 -0
  691. package/apps/smidja/smidja_modules/stall_watch.py +149 -0
  692. package/apps/smidja/smidja_modules/tracer.py +271 -0
  693. package/apps/smidja/smidja_modules/utils.py +77 -0
  694. package/apps/smidja/smidja_orchestrate.py +162 -0
  695. package/apps/smidja/smidja_plan.py +45 -0
  696. package/apps/smidja/smidja_plan_build.py +55 -0
  697. package/apps/smidja/smidja_plan_build_test.py +86 -0
  698. package/apps/smidja/smidja_plan_build_test_quality.py +98 -0
  699. package/apps/smidja/smidja_prompt.py +44 -0
  700. package/apps/smidja/smidja_quality.py +49 -0
  701. package/apps/smidja/smidja_recon_iv.py +202 -0
  702. package/apps/smidja/smidja_scout.py +45 -0
  703. package/apps/smidja/smidja_simple_sdlc.py +183 -0
  704. package/apps/smidja/smidja_smidja_config/smidja.config.yaml +143 -0
  705. package/apps/smidja-factory/AGENTS.md +165 -0
  706. package/apps/smidja-factory/README.md +3 -0
  707. package/apps/smidja-factory/SKILL.md +18 -0
  708. package/apps/smidja-factory/apps/visualizer/.oxlintrc.json +18 -0
  709. package/apps/smidja-factory/apps/visualizer/bun.lock +269 -0
  710. package/apps/smidja-factory/apps/visualizer/desktop/icon.png +0 -0
  711. package/apps/smidja-factory/apps/visualizer/desktop/main.js +140 -0
  712. package/apps/smidja-factory/apps/visualizer/desktop/package-lock.json +871 -0
  713. package/apps/smidja-factory/apps/visualizer/desktop/package.json +18 -0
  714. package/apps/smidja-factory/apps/visualizer/desktop/preload.js +19 -0
  715. package/apps/smidja-factory/apps/visualizer/index.html +28 -0
  716. package/apps/smidja-factory/apps/visualizer/package.json +31 -0
  717. package/apps/smidja-factory/apps/visualizer/public/icon.svg +7 -0
  718. package/apps/smidja-factory/apps/visualizer/public/models/claude.png +0 -0
  719. package/apps/smidja-factory/apps/visualizer/public/models/gemini.png +0 -0
  720. package/apps/smidja-factory/apps/visualizer/public/models/kimi.png +0 -0
  721. package/apps/smidja-factory/apps/visualizer/public/models/openai.png +0 -0
  722. package/apps/smidja-factory/apps/visualizer/public/models/zai.png +0 -0
  723. package/apps/smidja-factory/apps/visualizer/server/chat.ts +425 -0
  724. package/apps/smidja-factory/apps/visualizer/server/db.ts +1050 -0
  725. package/apps/smidja-factory/apps/visualizer/server/index.ts +648 -0
  726. package/apps/smidja-factory/apps/visualizer/server/model-catalog.ts +90 -0
  727. package/apps/smidja-factory/apps/visualizer/server/roster-api.ts +75 -0
  728. package/apps/smidja-factory/apps/visualizer/server/roster_resolve.py +170 -0
  729. package/apps/smidja-factory/apps/visualizer/server/settings.ts +106 -0
  730. package/apps/smidja-factory/apps/visualizer/shared/types.ts +630 -0
  731. package/apps/smidja-factory/apps/visualizer/src/App.vue +379 -0
  732. package/apps/smidja-factory/apps/visualizer/src/components/ChatInput.vue +155 -0
  733. package/apps/smidja-factory/apps/visualizer/src/components/ChatThread.vue +219 -0
  734. package/apps/smidja-factory/apps/visualizer/src/components/ChatView.vue +335 -0
  735. package/apps/smidja-factory/apps/visualizer/src/components/DecisionsView.vue +177 -0
  736. package/apps/smidja-factory/apps/visualizer/src/components/DetailSection.vue +76 -0
  737. package/apps/smidja-factory/apps/visualizer/src/components/MemoryView.vue +397 -0
  738. package/apps/smidja-factory/apps/visualizer/src/components/PhaseDetail.vue +1354 -0
  739. package/apps/smidja-factory/apps/visualizer/src/components/PhaseDots.vue +55 -0
  740. package/apps/smidja-factory/apps/visualizer/src/components/SessionCard.vue +583 -0
  741. package/apps/smidja-factory/apps/visualizer/src/components/SessionMiniCard.vue +58 -0
  742. package/apps/smidja-factory/apps/visualizer/src/components/SessionPanel.vue +272 -0
  743. package/apps/smidja-factory/apps/visualizer/src/components/SessionStartForm.vue +152 -0
  744. package/apps/smidja-factory/apps/visualizer/src/components/SessionTrace.vue +1157 -0
  745. package/apps/smidja-factory/apps/visualizer/src/components/SessionsList.vue +96 -0
  746. package/apps/smidja-factory/apps/visualizer/src/components/SettingsView.vue +152 -0
  747. package/apps/smidja-factory/apps/visualizer/src/components/StatChip.vue +98 -0
  748. package/apps/smidja-factory/apps/visualizer/src/components/StatsView.vue +382 -0
  749. package/apps/smidja-factory/apps/visualizer/src/components/StatusChip.vue +73 -0
  750. package/apps/smidja-factory/apps/visualizer/src/components/ToolCallCard.vue +156 -0
  751. package/apps/smidja-factory/apps/visualizer/src/lib/api.ts +177 -0
  752. package/apps/smidja-factory/apps/visualizer/src/lib/chat-api.ts +95 -0
  753. package/apps/smidja-factory/apps/visualizer/src/lib/chat-store.ts +351 -0
  754. package/apps/smidja-factory/apps/visualizer/src/lib/events.ts +131 -0
  755. package/apps/smidja-factory/apps/visualizer/src/lib/format.ts +92 -0
  756. package/apps/smidja-factory/apps/visualizer/src/lib/highlight.ts +54 -0
  757. package/apps/smidja-factory/apps/visualizer/src/lib/markdown.ts +120 -0
  758. package/apps/smidja-factory/apps/visualizer/src/lib/models.ts +42 -0
  759. package/apps/smidja-factory/apps/visualizer/src/lib/router.ts +67 -0
  760. package/apps/smidja-factory/apps/visualizer/src/lib/types.ts +61 -0
  761. package/apps/smidja-factory/apps/visualizer/src/main.ts +13 -0
  762. package/apps/smidja-factory/apps/visualizer/src/style.css +592 -0
  763. package/apps/smidja-factory/apps/visualizer/tsconfig.json +30 -0
  764. package/apps/smidja-factory/apps/visualizer/vite.config.js +32 -0
  765. package/apps/smidja-factory/apps/visualizer/vite.config.ts +31 -0
  766. package/apps/smidja-factory/cookbooks/create_config.md +61 -0
  767. package/apps/smidja-factory/cookbooks/create_smidja.md +120 -0
  768. package/apps/smidja-factory/cookbooks/how_to_prompt_for_the_eng.md +110 -0
  769. package/apps/smidja-factory/cookbooks/install.md +56 -0
  770. package/apps/smidja-factory/cookbooks/run_smidja.md +122 -0
  771. package/apps/smidja-factory/cookbooks/smidja_overview.md +88 -0
  772. package/apps/smidja-factory/cookbooks/update_config.md +103 -0
  773. package/apps/smidja-factory/cookbooks/update_modules.md +100 -0
  774. package/apps/smidja-factory/cookbooks/update_smidja.md +90 -0
  775. package/apps/smidja-factory/docs/enhancement-plan.md +420 -0
  776. package/apps/smidja-factory/references/config.md +202 -0
  777. package/apps/smidja-factory/references/handoff.md +161 -0
  778. package/apps/smidja-factory/references/observability.md +166 -0
  779. package/apps/smidja-factory/scripts/install.py +113 -0
  780. package/apps/smidja-factory/scripts/make_config.py +35 -0
  781. package/apps/smidja-factory/scripts/make_smidja.py +119 -0
  782. package/apps/smidja-factory/skills/add-or-edit-ai-models/SKILL.md +151 -0
  783. package/apps/smidja-factory/skills/create-new-agent/SKILL.md +125 -0
  784. package/apps/smidja-factory/skills/create-new-teams/SKILL.md +151 -0
  785. package/apps/smidja-factory/skills/git-ops/README.md +25 -0
  786. package/apps/smidja-factory/skills/git-ops/SKILL.md +18 -0
  787. package/apps/smidja-factory/skills/git-ops/create_branch.sh +79 -0
  788. package/apps/smidja-factory/skills/git-ops/safe_commit.sh +82 -0
  789. package/apps/smidja-factory/skills/git-ops/sync_upstream.sh +94 -0
  790. package/apps/smidja-factory/skills/how-to-run-agent-teams/SKILL.md +117 -0
  791. package/apps/smidja-factory/skills/smidja-instructions/SKILL.md +168 -0
  792. package/apps/smidja-factory/skills/smidja-launcher/SKILL.md +155 -0
  793. package/apps/smidja-factory/skills/smidja-start/SKILL.md +266 -0
  794. package/apps/smidja-factory/skills/volundr/SKILL.md +232 -0
  795. package/apps/smidja-factory/skills/volundr/prompt/dispatch-prompt.md +91 -0
  796. package/apps/smidja-factory/skills/volundr/prompt/volundr-system.md +63 -0
  797. package/apps/smidja-factory/skills/volundr/scripts/volundr-observe.py +52 -0
  798. package/apps/smidja-factory/skills/volundr/scripts/volundr-recall.py +54 -0
  799. package/apps/smidja-factory/skills/volundr/scripts/volundr-status.py +51 -0
  800. package/apps/smidja-factory/skills/volundr/scripts/volundr-teach.py +47 -0
  801. package/apps/smidja-factory/templates/env.sample +28 -0
  802. package/apps/smidja-factory/templates/harness_engineering/subagents.ts +706 -0
  803. package/apps/smidja-factory/templates/harness_engineering/themeMap.ts +145 -0
  804. package/apps/smidja-factory/templates/justfile +89 -0
  805. package/apps/smidja-factory/templates/prompt_engineering/builder/system.md +13 -0
  806. package/apps/smidja-factory/templates/prompt_engineering/builder/user.md +34 -0
  807. package/apps/smidja-factory/templates/prompt_engineering/documenter/system.md +17 -0
  808. package/apps/smidja-factory/templates/prompt_engineering/documenter/user.md +48 -0
  809. package/apps/smidja-factory/templates/prompt_engineering/orchestrator/system.md +55 -0
  810. package/apps/smidja-factory/templates/prompt_engineering/orchestrator/user.md +39 -0
  811. package/apps/smidja-factory/templates/prompt_engineering/planner/system.md +21 -0
  812. package/apps/smidja-factory/templates/prompt_engineering/planner/user.md +45 -0
  813. package/apps/smidja-factory/templates/prompt_engineering/recon_orchestrator/system.md +51 -0
  814. package/apps/smidja-factory/templates/prompt_engineering/recon_orchestrator/user.md +26 -0
  815. package/apps/smidja-factory/templates/prompt_engineering/reviewer/system.md +16 -0
  816. package/apps/smidja-factory/templates/prompt_engineering/reviewer/user.md +44 -0
  817. package/apps/smidja-factory/templates/prompt_engineering/scout/system.md +32 -0
  818. package/apps/smidja-factory/templates/prompt_engineering/scout/user.md +34 -0
  819. package/apps/smidja-factory/templates/smidja/smidja_build.py +45 -0
  820. package/apps/smidja-factory/templates/smidja/smidja_build_review.py +76 -0
  821. package/apps/smidja-factory/templates/smidja/smidja_build_test.py +79 -0
  822. package/apps/smidja-factory/templates/smidja/smidja_document.py +76 -0
  823. package/apps/smidja-factory/templates/smidja/smidja_modules/agent_cc.py +15 -0
  824. package/apps/smidja-factory/templates/smidja/smidja_modules/agent_opencode.py +194 -0
  825. package/apps/smidja-factory/templates/smidja/smidja_modules/agent_pi.py +392 -0
  826. package/apps/smidja-factory/templates/smidja/smidja_modules/agents.py +993 -0
  827. package/apps/smidja-factory/templates/smidja/smidja_modules/changes.py +103 -0
  828. package/apps/smidja-factory/templates/smidja/smidja_modules/console.py +131 -0
  829. package/apps/smidja-factory/templates/smidja/smidja_modules/data_types.py +447 -0
  830. package/apps/smidja-factory/templates/smidja/smidja_modules/gates.py +108 -0
  831. package/apps/smidja-factory/templates/smidja/smidja_modules/git_helper.py +120 -0
  832. package/apps/smidja-factory/templates/smidja/smidja_modules/lm_local.py +144 -0
  833. package/apps/smidja-factory/templates/smidja/smidja_modules/permissions.py +194 -0
  834. package/apps/smidja-factory/templates/smidja/smidja_modules/prompts.py +21 -0
  835. package/apps/smidja-factory/templates/smidja/smidja_modules/quality.py +240 -0
  836. package/apps/smidja-factory/templates/smidja/smidja_modules/runner.py +155 -0
  837. package/apps/smidja-factory/templates/smidja/smidja_modules/session.py +50 -0
  838. package/apps/smidja-factory/templates/smidja/smidja_modules/stall_watch.py +149 -0
  839. package/apps/smidja-factory/templates/smidja/smidja_modules/tracer.py +271 -0
  840. package/apps/smidja-factory/templates/smidja/smidja_modules/utils.py +77 -0
  841. package/apps/smidja-factory/templates/smidja/smidja_orchestrate.py +162 -0
  842. package/apps/smidja-factory/templates/smidja/smidja_plan.py +45 -0
  843. package/apps/smidja-factory/templates/smidja/smidja_plan_build.py +55 -0
  844. package/apps/smidja-factory/templates/smidja/smidja_plan_build_test.py +86 -0
  845. package/apps/smidja-factory/templates/smidja/smidja_plan_build_test_quality.py +98 -0
  846. package/apps/smidja-factory/templates/smidja/smidja_prompt.py +44 -0
  847. package/apps/smidja-factory/templates/smidja/smidja_quality.py +49 -0
  848. package/apps/smidja-factory/templates/smidja/smidja_recon_iv.py +202 -0
  849. package/apps/smidja-factory/templates/smidja/smidja_scout.py +45 -0
  850. package/apps/smidja-factory/templates/smidja/smidja_simple_sdlc.py +183 -0
  851. package/apps/smidja-factory/templates/smidja.config.yaml +143 -0
  852. package/bin/app-build.sh +36 -0
  853. package/bin/electron-lib.sh +25 -0
  854. package/bin/sessrumnir.sh +1 -1
  855. package/bin/ymir-install.sh +7 -0
  856. package/package.json +15 -7
  857. package/scripts/electron.sh +6 -2
  858. package/.agents/bus/messages.json +0 -1
  859. package/.agents/config/agents.machine.example.yaml +0 -16
  860. package/.pi/mcp.json +0 -16
  861. package/assets/reference/state/.branch-eligible-owner +0 -4
  862. package/assets/reference/state/.branch-mirror-cursor +0 -1
  863. package/assets/reference/state/.branch-outcomes-cursor +0 -1
  864. package/assets/reference/state/.branch-session +0 -1
  865. package/assets/reference/state/.count-default_wF_p5 +0 -1
  866. package/assets/reference/state/.count-default_wF_p6 +0 -1
  867. package/assets/reference/state/.count-default_wR_p2 +0 -1
  868. package/assets/reference/state/.count-default_wS_p2 +0 -1
  869. package/assets/reference/state/.count-firstmate_fm-server-knowledge +0 -1
  870. package/assets/reference/state/.hash-default_wF_p5 +0 -1
  871. package/assets/reference/state/.hash-default_wF_p6 +0 -1
  872. package/assets/reference/state/.hash-default_wR_p2 +0 -1
  873. package/assets/reference/state/.hash-default_wS_p2 +0 -1
  874. package/assets/reference/state/.hash-firstmate_fm-server-knowledge +0 -1
  875. package/assets/reference/state/.heartbeat-streak +0 -1
  876. package/assets/reference/state/.inactive-outcome-reconcile +0 -2
  877. package/assets/reference/state/.lock +0 -1
  878. package/assets/reference/state/.pi-branch-extension-loaded +0 -1
  879. package/assets/reference/state/.pi-turnend-extension-loaded +0 -2
  880. package/assets/reference/state/.pi-watch-extension-loaded +0 -2
  881. package/assets/reference/state/.seen-server-knowledge_turn-ended +0 -1
  882. package/assets/reference/state/.session-start-agents-baseline +0 -2
  883. package/assets/reference/state/.session-start-complete +0 -1
  884. package/assets/reference/state/.stale-default_wF_p5 +0 -1
  885. package/assets/reference/state/.stale-default_wR_p2 +0 -1
  886. package/assets/reference/state/.stale-firstmate_fm-server-knowledge +0 -1
  887. package/assets/reference/state/.stale-since-default_wF_p5 +0 -1
  888. package/assets/reference/state/.stale-since-default_wR_p2 +0 -1
  889. package/assets/reference/state/.stale-since-firstmate_fm-server-knowledge +0 -1
  890. package/assets/reference/state/.startup-network.delivered +0 -1
  891. package/assets/reference/state/.startup-network.report +0 -1
  892. package/assets/reference/state/.startup-network.status +0 -10
  893. package/assets/reference/state/.startup-network.timings +0 -6
  894. package/assets/reference/state/.trace-context-effective +0 -1
  895. package/assets/reference/state/.wake-queue +0 -0
  896. package/assets/reference/state/.wake-queue.seq +0 -1
  897. package/assets/reference/state/.wake-rows.consume.BcqXSq +0 -0
  898. package/assets/reference/state/.wake-rows.consume.NDZZei +0 -0
  899. package/assets/reference/state/.wake-rows.consume.VGkhYm +0 -0
  900. package/assets/reference/state/.wake-rows.consume.tR2rTy +0 -0
  901. package/assets/reference/state/.watch-arm-output.3581p6 +0 -0
  902. package/assets/reference/state/.watch-arm-output.3ciDNP +0 -0
  903. package/assets/reference/state/.watch-arm-output.SksR6k +0 -0
  904. package/assets/reference/state/.watch-cycle-exits.log +0 -22
  905. package/assets/reference/state/.watch-deliveries.log +0 -19
  906. package/assets/reference/state/.watch-triage.log +0 -38
  907. package/assets/reference/state/.watch.lock/fm-home +0 -1
  908. package/assets/reference/state/.watch.lock/pid +0 -1
  909. package/assets/reference/state/.watch.lock/pid-identity +0 -1
  910. package/assets/reference/state/.watch.lock/watcher-path +0 -1
  911. package/assets/reference/state/.watch.lock.owner.qqbxmS/fm-home +0 -1
  912. package/assets/reference/state/.watch.lock.owner.qqbxmS/pid +0 -1
  913. package/assets/reference/state/.watch.lock.owner.qqbxmS/pid-identity +0 -1
  914. package/assets/reference/state/.watch.lock.owner.qqbxmS/watcher-path +0 -1
  915. package/assets/reference/state/.watcher-down +0 -1
  916. package/assets/reference/state/branch-outcomes.jsonl +0 -1
  917. package/assets/reference/state/branch-session/2026-09-04T16-49-38-671Z_01a06d53-6b6f-7619-930d-e6dfd9a4a29e.jsonl +0 -211
  918. package/assets/reference/state/home-summary.json +0 -42
  919. package/assets/reference/state/server-knowledge.busy-gen +0 -1
  920. package/assets/reference/state/server-knowledge.busy-state +0 -1
  921. package/assets/reference/state/server-knowledge.herdr-presentation +0 -12
  922. package/assets/reference/state/server-knowledge.meta +0 -18
  923. package/assets/reference/state/server-knowledge.pi-ext.ts +0 -26
  924. package/assets/reference/state/server-knowledge.turn-ended +0 -0
  925. /package/{assets/reference/state/.last-check → apps/hlidskjalf/src/app/.gitkeep} +0 -0
  926. /package/{assets/reference/state/.last-heartbeat → apps/hlidskjalf/src/components/.gitkeep} +0 -0
  927. /package/{assets/reference/state/.last-watcher-beat → apps/hlidskjalf/src/services/.gitkeep} +0 -0
  928. /package/{assets/reference/state/.main-eligible-rows.tmp.p2HMKo → apps/smidja/smidja_modules/__init__.py} +0 -0
  929. /package/{assets/reference/state/.main-eligible-rows.tmp.Exxm82 → apps/smidja-factory/templates/smidja/smidja_modules/__init__.py} +0 -0
@@ -0,0 +1,574 @@
1
+ import { useEffect, useLayoutEffect, useMemo, useRef, useCallback, useState, useSyncExternalStore } from 'react'
2
+ import { useTranslation } from 'react-i18next'
3
+ import { useAppStore } from './store'
4
+ import { getAppliedThemeId, subscribeAppliedTheme } from './utils/theme'
5
+ import { DEFAULT_SETTINGS } from '../../shared/default-settings'
6
+ import { BUILTIN_SOURCE, type PiCommand } from '../../shared/pi-command'
7
+ import type { WorkspaceActivationIntent } from '../../shared/ipc-contracts'
8
+ import { t } from '../../shared/i18n'
9
+
10
+ /**
11
+ * Subscribes to Pi events from the main process and routes them to the store.
12
+ * Must be called once in the top-level component tree.
13
+ */
14
+ export function usePiEvents(): void {
15
+ const handlePiEvent = useAppStore((state) => state.handlePiEvent)
16
+ const handlePendingPromptCounts = useAppStore((state) => state.handlePendingPromptCounts)
17
+ const handleWorkspaceActivity = useAppStore((state) => state.handleWorkspaceActivity)
18
+ const handleSessionRuntime = useAppStore((state) => state.handleSessionRuntime)
19
+ const recoverPendingPrompts = useAppStore((state) => state.recoverPendingPrompts)
20
+
21
+ useEffect(() => {
22
+ // Subscribe to Pi events (status changes arrive here too, as 'status_change').
23
+ const unsubscribeEvent = window.piDesktop.onEvent(handlePiEvent)
24
+ const unsubscribeCounts = window.piDesktop.onPendingPrompts(handlePendingPromptCounts)
25
+ const unsubscribeActivity = window.piDesktop.onWorkspaceActivity(handleWorkspaceActivity)
26
+ const unsubscribeSessionRuntime = window.piDesktop.onSessionRuntime(handleSessionRuntime)
27
+
28
+ // A desktop-notification click hands the renderer the switch intent so the
29
+ // usual streaming/dirty-editor confirms still run; landing on chat shows
30
+ // the finished (or waiting) turn the notification was about.
31
+ const activateWorkspaceIntent = (intent: WorkspaceActivationIntent): void => {
32
+ const state = useAppStore.getState()
33
+ const { workspaceId, sessionPath } = intent
34
+ // A stale intent for a removed workspace must not run confirm dialogs
35
+ // for a doomed switch. An empty list means it just hasn't loaded yet
36
+ // (boot) — proceed and let main validate.
37
+ if (state.workspaces.length > 0 && !state.workspaces.some((ws) => ws.id === workspaceId)) return
38
+
39
+ void (async () => {
40
+ if (sessionPath) {
41
+ if (state.activeWorkspace?.id !== workspaceId) {
42
+ if (!(await state.activateWorkspace(workspaceId, { awaitingSession: true }))) return
43
+ }
44
+ const workspace = useAppStore.getState().activeWorkspace
45
+ if (!workspace) return
46
+ await useAppStore.getState().switchSession(sessionPath, workspace.path)
47
+ useAppStore.getState().setCurrentView('chat')
48
+ return
49
+ }
50
+ if (state.activeWorkspace?.id === workspaceId) {
51
+ if (state.currentView !== 'chat') state.setCurrentView('chat')
52
+ return
53
+ }
54
+ const switched = await state.activateWorkspace(workspaceId)
55
+ if (switched) useAppStore.getState().setCurrentView('chat')
56
+ })()
57
+ }
58
+ const unsubscribeActivate = window.piDesktop.onActivateWorkspace((intent) => {
59
+ // Main stashes every click's intent in case this broadcast never lands
60
+ // (boot/reload race). It did land — consume the stash so a later boot
61
+ // cannot replay a long-stale activation.
62
+ void window.piDesktop.workspace.takePendingActivation().catch(() => undefined)
63
+ activateWorkspaceIntent(intent)
64
+ })
65
+
66
+ // A reload leaves the dialog slot empty while main still holds the prompt.
67
+ void recoverPendingPrompts()
68
+
69
+ // A notification clicked while no window existed stashed its intent in
70
+ // main; deliver it now that the subscriptions above are live.
71
+ void window.piDesktop.workspace
72
+ .takePendingActivation()
73
+ .then((intent) => {
74
+ if (intent) activateWorkspaceIntent(intent)
75
+ })
76
+ .catch(() => {
77
+ // Non-fatal: the user can switch manually.
78
+ })
79
+
80
+ return () => {
81
+ unsubscribeEvent()
82
+ unsubscribeCounts()
83
+ unsubscribeActivity()
84
+ unsubscribeSessionRuntime()
85
+ unsubscribeActivate()
86
+ }
87
+ }, [handlePiEvent, handlePendingPromptCounts, handleWorkspaceActivity, handleSessionRuntime, recoverPendingPrompts])
88
+ }
89
+
90
+ /**
91
+ * Subscribes to menu actions from the application menu.
92
+ */
93
+ export function useMenuActions(): void {
94
+ const createNewSession = useAppStore((state) => state.createNewSession)
95
+ const setCurrentView = useAppStore((state) => state.setCurrentView)
96
+
97
+ useEffect(() => {
98
+ const unsubscribe = window.piDesktop.onMenuAction((action) => {
99
+ switch (action) {
100
+ case 'menu:new-session':
101
+ createNewSession()
102
+ break
103
+ case 'menu:new-workspace':
104
+ setCurrentView('settings') // Open settings where workspace creation lives
105
+ break
106
+ case 'menu:open-project': {
107
+ void window.piDesktop.system.openDialog({ title: t('dialogs.openProject.title') }).then((path) => {
108
+ if (path) void useAppStore.getState().openFolderAsWorkspace(path)
109
+ })
110
+ break
111
+ }
112
+ }
113
+ })
114
+
115
+ return unsubscribe
116
+ }, [createNewSession, setCurrentView])
117
+ }
118
+
119
+ /**
120
+ * The workflow navigator's scope, as the store holds it. Structural so the
121
+ * predicate below can be exercised without building a whole store state.
122
+ */
123
+ interface WorkflowPanelScope {
124
+ workflowPanelOpen: boolean
125
+ workflowPanelFilter: string | null
126
+ workflowPanelWorkspaceId: string | null
127
+ }
128
+
129
+ /**
130
+ * Whether the global "All Workflows" surface owns the main pane — the navigator
131
+ * opened with neither a session nor a project scope. Session-scoped and
132
+ * project-scoped runs render in the docked panel instead and leave the current
133
+ * view on screen. Shared so every consumer (main pane, workspace tabs, sidebar,
134
+ * chat scroll) agrees on what "global" means.
135
+ */
136
+ export function isGlobalWorkflowOpen(scope: WorkflowPanelScope): boolean {
137
+ return (
138
+ scope.workflowPanelOpen && !scope.workflowPanelFilter && scope.workflowPanelWorkspaceId === null
139
+ )
140
+ }
141
+
142
+ /** Component-side subscription to {@link isGlobalWorkflowOpen}. */
143
+ export function useGlobalWorkflowOpen(): boolean {
144
+ return useAppStore(isGlobalWorkflowOpen)
145
+ }
146
+
147
+ // Distance (px) from the bottom within which we consider the user "at bottom"
148
+ // and keep following new content.
149
+ const AT_BOTTOM_THRESHOLD = 48
150
+
151
+ // A content-relative scroll position. We store this instead of a raw scrollTop
152
+ // so the reading spot survives content-height changes that happen while the chat
153
+ // is hidden — chiefly toggling Show Thinking in Settings, which shows/hides every
154
+ // thinking block. A raw scrollTop would then point at different content.
155
+ type ScrollAnchor =
156
+ | { kind: 'bottom' }
157
+ // Preserve distance from the bottom. Used when no prose is on screen to anchor
158
+ // against (e.g. the viewport shows only tool boxes).
159
+ | { kind: 'fromBottom'; distanceFromBottom: number }
160
+ // `id` identifies a message's *text body* (the `data-scroll-anchor` marker on
161
+ // assistant text / user messages — never on tool boxes or thinking blocks).
162
+ // `viewportOffset` is its top edge relative to the container's top (often
163
+ // negative — it starts above the fold). Anchoring to the prose the reader is
164
+ // actually looking at — below any thinking block, even one in the same message
165
+ // — means collapsing thinking above it doesn't shift it. `distanceFromBottom`
166
+ // is a last-resort fallback if the element is somehow gone on restore.
167
+ | { kind: 'body'; id: string; viewportOffset: number; distanceFromBottom: number }
168
+
169
+ // Snapshot the current reading position of the scroll container.
170
+ function captureAnchor(el: HTMLElement): ScrollAnchor {
171
+ const distanceFromBottom = el.scrollHeight - el.clientHeight - el.scrollTop
172
+ if (distanceFromBottom <= AT_BOTTOM_THRESHOLD) return { kind: 'bottom' }
173
+ const containerTop = el.getBoundingClientRect().top
174
+ const nodes = el.querySelectorAll<HTMLElement>('[data-scroll-anchor]')
175
+ for (const node of nodes) {
176
+ const rect = node.getBoundingClientRect()
177
+ // First text body whose bottom edge is below the container's top — i.e. the
178
+ // topmost at least partially visible piece of prose.
179
+ if (rect.bottom > containerTop) {
180
+ return {
181
+ kind: 'body',
182
+ id: node.dataset.scrollAnchor as string,
183
+ viewportOffset: rect.top - containerTop,
184
+ distanceFromBottom,
185
+ }
186
+ }
187
+ }
188
+ return { kind: 'fromBottom', distanceFromBottom }
189
+ }
190
+
191
+ // Restore a previously captured anchor, absorbing any height change above it.
192
+ function restoreAnchor(el: HTMLElement, anchor: ScrollAnchor): void {
193
+ if (anchor.kind === 'bottom') {
194
+ el.scrollTop = el.scrollHeight
195
+ return
196
+ }
197
+ if (anchor.kind === 'fromBottom') {
198
+ el.scrollTop = el.scrollHeight - el.clientHeight - anchor.distanceFromBottom
199
+ return
200
+ }
201
+ const node = el.querySelector<HTMLElement>(`[data-scroll-anchor="${CSS.escape(anchor.id)}"]`)
202
+ if (!node) {
203
+ el.scrollTop = el.scrollHeight - el.clientHeight - anchor.distanceFromBottom
204
+ return
205
+ }
206
+ const containerTop = el.getBoundingClientRect().top
207
+ const currentOffset = node.getBoundingClientRect().top - containerTop
208
+ el.scrollTop += currentOffset - anchor.viewportOffset
209
+ }
210
+
211
+ /**
212
+ * Manages the chat scroll container:
213
+ * - remembers each session's scroll offset and restores it when you switch back
214
+ * - follows new/streamed content (a new prompt or live tokens) while Auto Scroll
215
+ * is enabled; leaves the position alone when it's off
216
+ * - jumps to the bottom when `chatScrollBottomNonce` changes (Home resume)
217
+ *
218
+ * `active` is whether the chat view is currently visible; while hidden the panel
219
+ * stays mounted (so scrollTop persists) but we defer any scrolling until it's
220
+ * shown again, so measurements are valid.
221
+ */
222
+ export function useChatScroll(active: boolean): {
223
+ scrollRef: React.RefObject<HTMLDivElement | null>
224
+ onScroll: () => void
225
+ atBottom: boolean
226
+ scrollToBottom: () => void
227
+ } {
228
+ const ref = useRef<HTMLDivElement>(null)
229
+ const autoScroll = useAppStore(
230
+ (state) => state.settingsDraft.autoScroll ?? state.settings?.autoScroll ?? DEFAULT_SETTINGS.autoScroll
231
+ )
232
+ const sessionId = useAppStore((state) => state.sessionState?.sessionId ?? null)
233
+ const messages = useAppStore((state) => state.messages)
234
+ const streamingContent = useAppStore((state) => state.streamingContent)
235
+ const scrollBottomNonce = useAppStore((state) => state.chatScrollBottomNonce)
236
+
237
+ const positions = useRef<Map<string, ScrollAnchor>>(new Map())
238
+ const activeSession = useRef<string | null>(null)
239
+ const seenNonce = useRef(scrollBottomNonce)
240
+ const forceBottom = useRef(false)
241
+ // Whether the chat was visible on the previous run, so we can re-anchor when it
242
+ // becomes visible again (e.g. returning from Settings after toggling thinking).
243
+ const prevActive = useRef(false)
244
+ // While a just-switched session's messages are still loading (async), keep
245
+ // re-applying the target scroll until content is actually present.
246
+ const pendingRestore = useRef(false)
247
+ // Track content size to distinguish genuinely new content from unrelated
248
+ // re-renders (e.g. re-showing the panel), so returning to chat doesn't scroll.
249
+ const prevMsgCount = useRef(0)
250
+ const prevStreamLen = useRef(0)
251
+
252
+ // Whether the viewport is at (or within a hair of) the bottom. `atBottom` (state)
253
+ // drives the jump-to-bottom button; `atBottomRef` is read synchronously in the
254
+ // layout effect to decide whether streamed content should keep following.
255
+ const [atBottom, setAtBottom] = useState(true)
256
+ const atBottomRef = useRef(true)
257
+
258
+ // Recompute at-bottom from the live DOM and publish it to both the ref and the
259
+ // button state (setState no-ops when unchanged, so this is cheap to call often).
260
+ const syncAtBottom = useCallback(() => {
261
+ const el = ref.current
262
+ if (!el) return
263
+ const next = el.scrollHeight - el.clientHeight - el.scrollTop <= AT_BOTTOM_THRESHOLD
264
+ atBottomRef.current = next
265
+ setAtBottom(next)
266
+ }, [])
267
+
268
+ const scrollToBottom = useCallback(() => {
269
+ const el = ref.current
270
+ if (!el) return
271
+ el.scrollTop = el.scrollHeight
272
+ atBottomRef.current = true
273
+ setAtBottom(true)
274
+ }, [])
275
+
276
+ const onScroll = useCallback(() => {
277
+ const el = ref.current
278
+ if (!el) return
279
+ const scrollable = el.scrollHeight - el.clientHeight
280
+ // Only remember a position while there's a real scroll range — avoids
281
+ // clobbering the saved offset with 0 when messages are momentarily cleared
282
+ // during a session switch.
283
+ if (activeSession.current !== null && scrollable > AT_BOTTOM_THRESHOLD) {
284
+ positions.current.set(activeSession.current, captureAnchor(el))
285
+ }
286
+ const next = scrollable - el.scrollTop <= AT_BOTTOM_THRESHOLD
287
+ atBottomRef.current = next
288
+ setAtBottom(next)
289
+ }, [])
290
+
291
+ useLayoutEffect(() => {
292
+ const el = ref.current
293
+
294
+ // Did content actually grow (new message or streamed text)? Tracked even
295
+ // while hidden so re-showing the panel isn't mistaken for new content.
296
+ const messagesGrew = messages.length > prevMsgCount.current
297
+ const grew = messagesGrew || streamingContent.length > prevStreamLen.current
298
+ prevMsgCount.current = messages.length
299
+ prevStreamLen.current = streamingContent.length
300
+
301
+ // Defer scrolling while hidden: a display:none element has no layout, so
302
+ // scrollHeight is 0 and any positioning would be wrong.
303
+ if (!el || !active) {
304
+ prevActive.current = active
305
+ return
306
+ }
307
+
308
+ const becameActive = !prevActive.current
309
+ prevActive.current = active
310
+
311
+ if (scrollBottomNonce !== seenNonce.current) {
312
+ seenNonce.current = scrollBottomNonce
313
+ forceBottom.current = true
314
+ }
315
+
316
+ const sessionKey = sessionId ?? '__none__'
317
+ if (activeSession.current !== sessionKey) {
318
+ activeSession.current = sessionKey
319
+ pendingRestore.current = true
320
+ }
321
+
322
+ if (pendingRestore.current) {
323
+ const saved = positions.current.get(sessionKey)
324
+ if (forceBottom.current || saved === undefined) {
325
+ el.scrollTop = el.scrollHeight
326
+ } else {
327
+ restoreAnchor(el, saved)
328
+ }
329
+ // Consider the switch settled once the session's messages have loaded.
330
+ if (messages.length > 0) {
331
+ pendingRestore.current = false
332
+ forceBottom.current = false
333
+ }
334
+ syncAtBottom()
335
+ return
336
+ }
337
+
338
+ // Returned to the chat view (e.g. from Settings) in the same session. The
339
+ // content height may have changed while hidden — Show Thinking toggles every
340
+ // thinking block — so re-anchor to the saved reading position rather than
341
+ // leaving the now-stale scrollTop, which would show different content.
342
+ if (becameActive) {
343
+ const saved = positions.current.get(sessionKey)
344
+ if (forceBottom.current || saved === undefined) {
345
+ el.scrollTop = el.scrollHeight
346
+ } else {
347
+ restoreAnchor(el, saved)
348
+ }
349
+ forceBottom.current = false
350
+ // Refresh the jump-to-bottom button against the restored position: content
351
+ // height may have changed while hidden (e.g. Show Thinking toggled), so the
352
+ // stale at-bottom state would otherwise hide the chevron until the next scroll.
353
+ syncAtBottom()
354
+ return
355
+ }
356
+
357
+ if (forceBottom.current) {
358
+ el.scrollTop = el.scrollHeight
359
+ forceBottom.current = false
360
+ syncAtBottom()
361
+ return
362
+ }
363
+
364
+ // A new user message means the user just sent a prompt — always reveal it.
365
+ const lastIsUser = messagesGrew && messages[messages.length - 1]?.role === 'user'
366
+
367
+ // Follow new/streamed content only when Auto Scroll is on AND the user was
368
+ // already at the bottom. If they scrolled up, leave their position put and
369
+ // let the jump-to-bottom button take them down on demand.
370
+ if (autoScroll && (lastIsUser || (grew && atBottomRef.current))) {
371
+ el.scrollTop = el.scrollHeight
372
+ }
373
+
374
+ syncAtBottom()
375
+ }, [active, sessionId, messages, streamingContent, scrollBottomNonce, autoScroll, syncAtBottom])
376
+
377
+ return { scrollRef: ref, onScroll, atBottom, scrollToBottom }
378
+ }
379
+
380
+ /**
381
+ * Escape aborts the running turn unless another surface (an extension prompt
382
+ * hiding itself, for example) already consumed the key press.
383
+ */
384
+ export function isAbortShortcut(event: { key: string; defaultPrevented: boolean }, isStreaming: boolean): boolean {
385
+ return event.key === 'Escape' && isStreaming && !event.defaultPrevented
386
+ }
387
+
388
+ /**
389
+ * Keyboard shortcut handler for the chat input.
390
+ */
391
+ export function useChatKeyboard(
392
+ onSend: (message: string) => void,
393
+ onAbort: () => void,
394
+ inputRef: React.RefObject<HTMLTextAreaElement | null>
395
+ ): void {
396
+ const isStreaming = useAppStore((state) => state.isStreaming)
397
+
398
+ useEffect(() => {
399
+ const handleKeyDown = (e: KeyboardEvent) => {
400
+ if (isAbortShortcut(e, isStreaming)) {
401
+ e.preventDefault()
402
+ onAbort()
403
+ return
404
+ }
405
+
406
+ // Enter: send message (without Shift)
407
+ if (e.key === 'Enter' && !e.shiftKey && document.activeElement === inputRef.current) {
408
+ e.preventDefault()
409
+ const value = inputRef.current?.value.trim()
410
+ if (value) {
411
+ onSend(value)
412
+ if (inputRef.current) inputRef.current.value = ''
413
+ }
414
+ }
415
+ }
416
+
417
+ window.addEventListener('keydown', handleKeyDown)
418
+ return () => window.removeEventListener('keydown', handleKeyDown)
419
+ }, [isStreaming, onSend, onAbort, inputRef])
420
+ }
421
+
422
+ /** A Pi built-in that maps to a GUI action rather than being inserted as text. */
423
+ export interface BuiltinCommand {
424
+ name: string
425
+ description: string
426
+ run: () => void
427
+ }
428
+
429
+ /**
430
+ * The command set offered by both command UIs (Ctrl+K palette and the
431
+ * composer's inline slash popup): everything the agent reports plus the GUI's
432
+ * built-in actions, ready for filtering. Built-ins cover Pi commands with a
433
+ * direct GUI equivalent; ones that need an argument or aren't supported in the
434
+ * GUI (e.g. /name, /tree) are excluded.
435
+ */
436
+ export function useCommandCatalog(): { builtins: BuiltinCommand[]; allCommands: PiCommand[] } {
437
+ const { t } = useTranslation()
438
+ const commands = useAppStore((s) => s.commands)
439
+ const compactContext = useAppStore((s) => s.compactContext)
440
+ const cloneBranch = useAppStore((s) => s.cloneBranch)
441
+ const createNewSession = useAppStore((s) => s.createNewSession)
442
+ const setTaskLauncherOpen = useAppStore((s) => s.setTaskLauncherOpen)
443
+ const setCurrentView = useAppStore((s) => s.setCurrentView)
444
+ const piEngine = useAppStore((s) => s.piEngine)
445
+
446
+ const builtins = useMemo<BuiltinCommand[]>(
447
+ () => [
448
+ { name: 'compact', description: t('commands.compact.description'), run: () => { void compactContext() } },
449
+ // OMP has no clone RPC command, so the action is not offered there.
450
+ ...(piEngine === 'omp'
451
+ ? []
452
+ : [{ name: 'clone', description: t('commands.clone.description'), run: () => { void cloneBranch() } }]),
453
+ { name: 'new', description: t('commands.new.description'), run: () => { void createNewSession() } },
454
+ { name: 'task', description: t('commands.task.description'), run: () => setTaskLauncherOpen(true) },
455
+ { name: 'resume', description: t('commands.resume.description'), run: () => setCurrentView('sessions') },
456
+ { name: 'fork', description: t('commands.fork.description'), run: () => setCurrentView('timeline') },
457
+ { name: 'settings', description: t('commands.settings.description'), run: () => setCurrentView('settings') },
458
+ ],
459
+ [compactContext, cloneBranch, createNewSession, setTaskLauncherOpen, setCurrentView, piEngine, t]
460
+ )
461
+
462
+ const allCommands = useMemo<PiCommand[]>(
463
+ () => [
464
+ ...commands,
465
+ ...builtins.map((b) => ({ name: b.name, description: b.description, source: BUILTIN_SOURCE })),
466
+ ],
467
+ [commands, builtins]
468
+ )
469
+
470
+ return { builtins, allCommands }
471
+ }
472
+
473
+ /**
474
+ * Loads initial data on mount — workspaces, settings, then Pi.
475
+ */
476
+ export function useInitialize(): void {
477
+ const startPi = useAppStore((state) => state.startPi)
478
+ const loadSettings = useAppStore((state) => state.loadSettings)
479
+ const loadWorkspaces = useAppStore((state) => state.loadWorkspaces)
480
+ const refreshSessionStats = useAppStore((state) => state.refreshSessionStats)
481
+ const refreshSessionList = useAppStore((state) => state.refreshSessionList)
482
+
483
+ const initialized = useRef(false)
484
+
485
+ useEffect(() => {
486
+ if (initialized.current) return
487
+ initialized.current = true
488
+
489
+ const initialize = async (): Promise<void> => {
490
+ await loadSettings()
491
+ const openToHome = useAppStore.getState().settings?.openToHomeOnLaunch ?? DEFAULT_SETTINGS.openToHomeOnLaunch
492
+
493
+ // Workspaces are needed for the shell chrome; land the UI immediately after.
494
+ await loadWorkspaces()
495
+ void window.piDesktop.session.listRuntimes()
496
+ .then((runtimes) => runtimes.forEach((runtime) => useAppStore.getState().handleSessionRuntime(runtime)))
497
+ .catch(() => undefined)
498
+
499
+ if (openToHome) {
500
+ // Interactive ASAP — do NOT wait on the session-store walk (can be tens
501
+ // of seconds on a large ~/.pi/agent/sessions tree and freezes main IPC).
502
+ useAppStore.getState().setCurrentView('home')
503
+ } else {
504
+ useAppStore.getState().setCurrentView('chat')
505
+ }
506
+
507
+ // The status bar is on screen before any agent starts, and the engine is
508
+ // only carried on status payloads. Ask once at boot, or the bar reads
509
+ // "Pi stopped" for a user whose configured engine is OMP. Only the
510
+ // engine is adopted: the status itself is owned by the lifecycle
511
+ // actions, which may already be starting a session by now.
512
+ void window.piDesktop.pi.getStatus()
513
+ .then((status) => {
514
+ if (status.engine) useAppStore.setState({ piEngine: status.engine })
515
+ })
516
+ .catch(() => undefined)
517
+
518
+ // Background: session list, tags, notes, models, updates.
519
+ void refreshSessionList()
520
+ // Load the workflow journal once at boot so the status-bar badge and the
521
+ // sidebar workflow entries show live runs before the navigator is first
522
+ // opened (its poll loop keeps it fresh afterwards).
523
+ void useAppStore.getState().refreshWorkflowRuns()
524
+ void useAppStore.getState().loadTags()
525
+ void useAppStore.getState().loadArchivedSessions()
526
+ void useAppStore.getState().loadNotes()
527
+ void useAppStore.getState().loadCustomModels()
528
+ void useAppStore.getState().checkForUpdates()
529
+
530
+ if (openToHome) {
531
+ // Pi starts lazily on first action from Home.
532
+ return
533
+ }
534
+
535
+ // Boot Pi in the background. The shell is already interactive; the
536
+ // session-runtime running event hydrates Chat when the process is ready.
537
+ void startPi().then(() => refreshSessionStats()).catch(() => undefined)
538
+ void window.piDesktop.workspace.getActivity()
539
+ .then((activity) => useAppStore.getState().handleWorkspaceActivity(activity))
540
+ .catch(() => undefined)
541
+ }
542
+
543
+ initialize()
544
+ }, [startPi, loadSettings, loadWorkspaces, refreshSessionStats, refreshSessionList])
545
+ }
546
+
547
+ /**
548
+ * Global shortcut (Ctrl+Shift+P) that toggles the quick note picker, letting
549
+ * the user insert a saved prompt from anywhere in the app. (Ctrl+Shift+N is
550
+ * reserved for the New Workspace menu accelerator.)
551
+ */
552
+ export function useNotePickerShortcut(): void {
553
+ useEffect(() => {
554
+ const handleKeyDown = (e: KeyboardEvent): void => {
555
+ if (e.ctrlKey && e.shiftKey && (e.key === 'P' || e.key === 'p')) {
556
+ e.preventDefault()
557
+ const { notePickerOpen, setNotePickerOpen } = useAppStore.getState()
558
+ setNotePickerOpen(!notePickerOpen)
559
+ }
560
+ }
561
+
562
+ window.addEventListener('keydown', handleKeyDown)
563
+ return () => window.removeEventListener('keydown', handleKeyDown)
564
+ }, [])
565
+ }
566
+
567
+ /**
568
+ * The concrete id of the theme on screen ('system' already resolved). Changes
569
+ * on every applied theme switch, including an OS light/dark change under the
570
+ * System theme, which the saved `theme` setting does not reflect.
571
+ */
572
+ export function useAppliedThemeId(): string | null {
573
+ return useSyncExternalStore(subscribeAppliedTheme, getAppliedThemeId)
574
+ }
@@ -0,0 +1,54 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert/strict'
3
+ import { bootLanguageFrom, languagePickerOptions, loadedI18nEnvironment, loadI18nEnvironment } from './i18n'
4
+ import { PSEUDO_LANGUAGE, SOURCE_LANGUAGE, SYSTEM_LANGUAGE } from '../../shared/i18n/languages'
5
+
6
+ const ENVIRONMENT_LOAD_FAILURE = new Error('environment load failed')
7
+ const RETRIED_ENVIRONMENT = { systemLanguages: [], pseudoLanguageEnabled: false }
8
+
9
+ test('bootLanguageFrom accepts a stored available code', () => {
10
+ assert.equal(bootLanguageFrom(SOURCE_LANGUAGE), SOURCE_LANGUAGE)
11
+ assert.equal(bootLanguageFrom(PSEUDO_LANGUAGE), PSEUDO_LANGUAGE)
12
+ })
13
+
14
+ test('bootLanguageFrom falls back to English for missing or unknown values', () => {
15
+ assert.equal(bootLanguageFrom(null), SOURCE_LANGUAGE)
16
+ assert.equal(bootLanguageFrom('xx-unknown'), SOURCE_LANGUAGE)
17
+ })
18
+
19
+ test('the picker starts with System default and names the resolved system language', () => {
20
+ const options = languagePickerOptions({ systemLanguages: ['fr-FR'], pseudoLanguageEnabled: false })
21
+ assert.deepEqual(options, [
22
+ { value: SYSTEM_LANGUAGE, label: 'System default (English)' },
23
+ { value: SOURCE_LANGUAGE, label: 'English' },
24
+ ])
25
+ })
26
+
27
+ test('the picker offers the pseudo-language only when enabled', () => {
28
+ const values = languagePickerOptions({ systemLanguages: [], pseudoLanguageEnabled: true }).map((o) => o.value)
29
+ assert.ok(values.includes(PSEUDO_LANGUAGE))
30
+ const plain = languagePickerOptions({ systemLanguages: [], pseudoLanguageEnabled: false }).map((o) => o.value)
31
+ assert.ok(!plain.includes(PSEUDO_LANGUAGE))
32
+ })
33
+
34
+ test('loadI18nEnvironment retries after a failed request instead of caching the rejection', async () => {
35
+ let callCount = 0
36
+ const originalWindow = (globalThis as { window?: unknown }).window
37
+ ;(globalThis as { window: unknown }).window = {
38
+ piDesktop: {
39
+ i18n: {
40
+ getEnvironment: () => {
41
+ callCount += 1
42
+ return callCount === 1 ? Promise.reject(ENVIRONMENT_LOAD_FAILURE) : Promise.resolve(RETRIED_ENVIRONMENT)
43
+ },
44
+ },
45
+ },
46
+ }
47
+ try {
48
+ await assert.rejects(loadI18nEnvironment(), ENVIRONMENT_LOAD_FAILURE)
49
+ assert.deepEqual(await loadI18nEnvironment(), RETRIED_ENVIRONMENT)
50
+ assert.deepEqual(loadedI18nEnvironment(), RETRIED_ENVIRONMENT)
51
+ } finally {
52
+ ;(globalThis as { window?: unknown }).window = originalWindow
53
+ }
54
+ })