@juspay/shooter 1.20.0 → 1.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/build/client/_app/immutable/assets/2.BHi6pjT2.css +1 -0
  2. package/build/client/_app/immutable/assets/2.BHi6pjT2.css.br +0 -0
  3. package/build/client/_app/immutable/assets/2.BHi6pjT2.css.gz +0 -0
  4. package/build/client/_app/immutable/chunks/{ZS5XYDx_.js → B1bOvemT.js} +1 -1
  5. package/build/client/_app/immutable/chunks/B1bOvemT.js.br +0 -0
  6. package/build/client/_app/immutable/chunks/{ZS5XYDx_.js.gz → B1bOvemT.js.gz} +0 -0
  7. package/build/client/_app/immutable/chunks/{DT4H19pV.js → BmfLecb1.js} +1 -1
  8. package/build/client/_app/immutable/chunks/BmfLecb1.js.br +0 -0
  9. package/build/client/_app/immutable/chunks/BmfLecb1.js.gz +0 -0
  10. package/build/client/_app/immutable/chunks/C87ZRWX0.js +1 -0
  11. package/build/client/_app/immutable/chunks/C87ZRWX0.js.br +0 -0
  12. package/build/client/_app/immutable/chunks/C87ZRWX0.js.gz +0 -0
  13. package/build/client/_app/immutable/chunks/{BvmdJful.js → CJulw9ux.js} +1 -1
  14. package/build/client/_app/immutable/chunks/CJulw9ux.js.br +0 -0
  15. package/build/client/_app/immutable/chunks/CJulw9ux.js.gz +0 -0
  16. package/build/client/_app/immutable/chunks/{C_YNQL8b.js → DOEXXmsh.js} +2 -2
  17. package/build/client/_app/immutable/chunks/DOEXXmsh.js.br +0 -0
  18. package/build/client/_app/immutable/chunks/DOEXXmsh.js.gz +0 -0
  19. package/build/client/_app/immutable/chunks/{ClIPTXf3.js → DomZZqvG.js} +1 -1
  20. package/build/client/_app/immutable/chunks/DomZZqvG.js.br +0 -0
  21. package/build/client/_app/immutable/chunks/DomZZqvG.js.gz +0 -0
  22. package/build/client/_app/immutable/chunks/{DIZ3Qst5.js → EqMAkEha.js} +1 -1
  23. package/build/client/_app/immutable/chunks/EqMAkEha.js.br +0 -0
  24. package/build/client/_app/immutable/chunks/EqMAkEha.js.gz +0 -0
  25. package/build/client/_app/immutable/chunks/{BB2l8o4X.js → i5iZvmIH.js} +1 -1
  26. package/build/client/_app/immutable/chunks/i5iZvmIH.js.br +0 -0
  27. package/build/client/_app/immutable/chunks/i5iZvmIH.js.gz +0 -0
  28. package/build/client/_app/immutable/entry/{app.Bd-DfeJi.js → app.CeSxgGat.js} +2 -2
  29. package/build/client/_app/immutable/entry/app.CeSxgGat.js.br +0 -0
  30. package/build/client/_app/immutable/entry/app.CeSxgGat.js.gz +0 -0
  31. package/build/client/_app/immutable/entry/start.DrnJFwxA.js +1 -0
  32. package/build/client/_app/immutable/entry/start.DrnJFwxA.js.br +2 -0
  33. package/build/client/_app/immutable/entry/start.DrnJFwxA.js.gz +0 -0
  34. package/build/client/_app/immutable/nodes/0.oaPwxh1O.js +10 -0
  35. package/build/client/_app/immutable/nodes/0.oaPwxh1O.js.br +0 -0
  36. package/build/client/_app/immutable/nodes/0.oaPwxh1O.js.gz +0 -0
  37. package/build/client/_app/immutable/nodes/{1.DT4dq6Ay.js → 1.DMPyoM-M.js} +1 -1
  38. package/build/client/_app/immutable/nodes/1.DMPyoM-M.js.br +0 -0
  39. package/build/client/_app/immutable/nodes/1.DMPyoM-M.js.gz +0 -0
  40. package/build/client/_app/immutable/nodes/{10.CF7RGXpe.js → 10.Cbm7nQKK.js} +1 -1
  41. package/build/client/_app/immutable/nodes/10.Cbm7nQKK.js.br +0 -0
  42. package/build/client/_app/immutable/nodes/10.Cbm7nQKK.js.gz +0 -0
  43. package/build/client/_app/immutable/nodes/{11.BV_G7yLI.js → 11.CKmZjP_a.js} +1 -1
  44. package/build/client/_app/immutable/nodes/11.CKmZjP_a.js.br +0 -0
  45. package/build/client/_app/immutable/nodes/11.CKmZjP_a.js.gz +0 -0
  46. package/build/client/_app/immutable/nodes/2.zlrdNFtH.js +13 -0
  47. package/build/client/_app/immutable/nodes/2.zlrdNFtH.js.br +0 -0
  48. package/build/client/_app/immutable/nodes/2.zlrdNFtH.js.gz +0 -0
  49. package/build/client/_app/immutable/nodes/{3.0MMe3oxR.js → 3.BgLpGnzb.js} +1 -1
  50. package/build/client/_app/immutable/nodes/3.BgLpGnzb.js.br +0 -0
  51. package/build/client/_app/immutable/nodes/3.BgLpGnzb.js.gz +0 -0
  52. package/build/client/_app/immutable/nodes/{4.CBX9A3ka.js → 4.BFYS2g9C.js} +3 -3
  53. package/build/client/_app/immutable/nodes/4.BFYS2g9C.js.br +0 -0
  54. package/build/client/_app/immutable/nodes/4.BFYS2g9C.js.gz +0 -0
  55. package/build/client/_app/immutable/nodes/{5.DIVKuZc9.js → 5.Avc1-gVb.js} +1 -1
  56. package/build/client/_app/immutable/nodes/5.Avc1-gVb.js.br +0 -0
  57. package/build/client/_app/immutable/nodes/5.Avc1-gVb.js.gz +0 -0
  58. package/build/client/_app/immutable/nodes/{6.ComiWlV6.js → 6.Dw2wEssJ.js} +1 -1
  59. package/build/client/_app/immutable/nodes/6.Dw2wEssJ.js.br +0 -0
  60. package/build/client/_app/immutable/nodes/6.Dw2wEssJ.js.gz +0 -0
  61. package/build/client/_app/immutable/nodes/{7.vkPx1kVP.js → 7.DwKZjoBg.js} +1 -1
  62. package/build/client/_app/immutable/nodes/7.DwKZjoBg.js.br +0 -0
  63. package/build/client/_app/immutable/nodes/7.DwKZjoBg.js.gz +0 -0
  64. package/build/client/_app/immutable/nodes/{8.Bmr3sWbS.js → 8.ZUAI6g5E.js} +1 -1
  65. package/build/client/_app/immutable/nodes/8.ZUAI6g5E.js.br +0 -0
  66. package/build/client/_app/immutable/nodes/8.ZUAI6g5E.js.gz +0 -0
  67. package/build/client/_app/immutable/nodes/{9.CAJucyeI.js → 9.I_KGXPwB.js} +1 -1
  68. package/build/client/_app/immutable/nodes/9.I_KGXPwB.js.br +0 -0
  69. package/build/client/_app/immutable/nodes/9.I_KGXPwB.js.gz +0 -0
  70. package/build/client/_app/version.json +1 -1
  71. package/build/client/_app/version.json.br +0 -0
  72. package/build/client/_app/version.json.gz +0 -0
  73. package/build/server/chunks/{0-DDGB6CRT.js → 0-vrTNAfZB.js} +4 -2
  74. package/build/server/chunks/0-vrTNAfZB.js.map +1 -0
  75. package/build/server/chunks/{1-DEjonQXD.js → 1-nbr-bOoF.js} +2 -2
  76. package/build/server/chunks/{1-DEjonQXD.js.map → 1-nbr-bOoF.js.map} +1 -1
  77. package/build/server/chunks/{10-BK1kiiiw.js → 10-ChyvvJ6w.js} +2 -2
  78. package/build/server/chunks/{10-BK1kiiiw.js.map → 10-ChyvvJ6w.js.map} +1 -1
  79. package/build/server/chunks/{11-CJPjkEF3.js → 11-6ZAjL3uU.js} +2 -2
  80. package/build/server/chunks/{11-CJPjkEF3.js.map → 11-6ZAjL3uU.js.map} +1 -1
  81. package/build/server/chunks/{2-RLnhlWh5.js → 2-DWFRVDWJ.js} +3 -3
  82. package/build/server/chunks/{2-RLnhlWh5.js.map → 2-DWFRVDWJ.js.map} +1 -1
  83. package/build/server/chunks/{3-Dd4pJBqZ.js → 3-CKANM_WM.js} +2 -2
  84. package/build/server/chunks/{3-Dd4pJBqZ.js.map → 3-CKANM_WM.js.map} +1 -1
  85. package/build/server/chunks/{4-Bb5VFhsO.js → 4-D92KnTmb.js} +3 -3
  86. package/build/server/chunks/{4-Bb5VFhsO.js.map → 4-D92KnTmb.js.map} +1 -1
  87. package/build/server/chunks/{5-oNoWuIsn.js → 5-BxVjs2qi.js} +2 -2
  88. package/build/server/chunks/{5-oNoWuIsn.js.map → 5-BxVjs2qi.js.map} +1 -1
  89. package/build/server/chunks/{6-DdRMnKNa.js → 6-Cbf1AAMQ.js} +2 -2
  90. package/build/server/chunks/{6-DdRMnKNa.js.map → 6-Cbf1AAMQ.js.map} +1 -1
  91. package/build/server/chunks/{7-vLOMMetm.js → 7-CMK2quEf.js} +2 -2
  92. package/build/server/chunks/{7-vLOMMetm.js.map → 7-CMK2quEf.js.map} +1 -1
  93. package/build/server/chunks/{8-rJyiQLFs.js → 8-DhdfkfDM.js} +2 -2
  94. package/build/server/chunks/{8-rJyiQLFs.js.map → 8-DhdfkfDM.js.map} +1 -1
  95. package/build/server/chunks/{9-CVSNNYED.js → 9-CPpxtRM5.js} +2 -2
  96. package/build/server/chunks/{9-CVSNNYED.js.map → 9-CPpxtRM5.js.map} +1 -1
  97. package/build/server/chunks/Banner-BgaAs1rs.js.map +1 -1
  98. package/build/server/chunks/Button-D0hZ7JYt.js.map +1 -1
  99. package/build/server/chunks/Icon-D0GBnDcs.js.map +1 -1
  100. package/build/server/chunks/Input-OmIiydSx.js.map +1 -1
  101. package/build/server/chunks/Pill-4xJ-VhAA.js.map +1 -1
  102. package/build/server/chunks/Shimmer-Dw2uvTC1.js.map +1 -1
  103. package/build/server/chunks/_error.svelte-CZnkxeLr.js.map +1 -1
  104. package/build/server/chunks/_layout.svelte-DfgNGGiM.js.map +1 -1
  105. package/build/server/chunks/_page.svelte-BTlfUsBp.js.map +1 -1
  106. package/build/server/chunks/_page.svelte-C7B0qdrC.js.map +1 -1
  107. package/build/server/chunks/{_page.svelte-BLo2v_8E.js → _page.svelte-Gv9p8nlS.js} +3 -4
  108. package/build/server/chunks/_page.svelte-Gv9p8nlS.js.map +1 -0
  109. package/build/server/chunks/_page.svelte-dabsQl9c.js.map +1 -1
  110. package/build/server/chunks/_page.svelte-tBuIq8Pg.js.map +1 -1
  111. package/build/server/chunks/_server.ts-BB46Fbqn.js +59 -0
  112. package/build/server/chunks/_server.ts-BB46Fbqn.js.map +1 -0
  113. package/build/server/chunks/{_server.ts-bk_EeAdY.js → _server.ts-BWVlO8iV.js} +8 -5
  114. package/build/server/chunks/_server.ts-BWVlO8iV.js.map +1 -0
  115. package/build/server/chunks/{_server.ts-BRAzC6W1.js → _server.ts-BevnuePu.js} +27 -6
  116. package/build/server/chunks/_server.ts-BevnuePu.js.map +1 -0
  117. package/build/server/chunks/{_server.ts-B2wIgsW4.js → _server.ts-CA5KUENM.js} +3 -3
  118. package/build/server/chunks/{_server.ts-B2wIgsW4.js.map → _server.ts-CA5KUENM.js.map} +1 -1
  119. package/build/server/chunks/{_server.ts-DEx9-epI.js → _server.ts-CC2K8-L2.js} +3 -3
  120. package/build/server/chunks/{_server.ts-DEx9-epI.js.map → _server.ts-CC2K8-L2.js.map} +1 -1
  121. package/build/server/chunks/{_server.ts-CJGyN8mw.js → _server.ts-CD7JP3fz.js} +3 -3
  122. package/build/server/chunks/{_server.ts-CJGyN8mw.js.map → _server.ts-CD7JP3fz.js.map} +1 -1
  123. package/build/server/chunks/{_server.ts-AnBXfZXh.js → _server.ts-D0zRDSx0.js} +2 -2
  124. package/build/server/chunks/{_server.ts-AnBXfZXh.js.map → _server.ts-D0zRDSx0.js.map} +1 -1
  125. package/build/server/chunks/{_server.ts-DKNIsQeH.js → _server.ts-Dp-hXW_I.js} +3 -3
  126. package/build/server/chunks/{_server.ts-DKNIsQeH.js.map → _server.ts-Dp-hXW_I.js.map} +1 -1
  127. package/build/server/chunks/_server.ts-VzDcFFgy.js +157 -0
  128. package/build/server/chunks/_server.ts-VzDcFFgy.js.map +1 -0
  129. package/build/server/chunks/{_server.ts-Dz9Jd9Jh.js → _server.ts-X1R7L_QI.js} +3 -3
  130. package/build/server/chunks/{_server.ts-Dz9Jd9Jh.js.map → _server.ts-X1R7L_QI.js.map} +1 -1
  131. package/build/server/chunks/cache-BlMaDsHi.js.map +1 -1
  132. package/build/server/chunks/{guest-registry-t0-7Zv5q.js → guest-registry-Dxvd7p-g.js} +10 -1
  133. package/build/server/chunks/guest-registry-Dxvd7p-g.js.map +1 -0
  134. package/build/server/chunks/index-CoYB03g7.js.map +1 -1
  135. package/build/server/chunks/index2-dSGQ9Eaa.js.map +1 -1
  136. package/build/server/chunks/{pty-manager-CkZNoW1t.js → pty-manager-ZqXqa-6A.js} +2 -2
  137. package/build/server/chunks/{pty-manager-CkZNoW1t.js.map → pty-manager-ZqXqa-6A.js.map} +1 -1
  138. package/build/server/chunks/root-D4IoFC8F.js.map +1 -1
  139. package/build/server/chunks/state.svelte-CmHqngc_.js.map +1 -1
  140. package/build/server/index.js +1 -1
  141. package/build/server/index.js.map +1 -1
  142. package/build/server/manifest.js +35 -21
  143. package/build/server/manifest.js.map +1 -1
  144. package/package.json +2 -2
  145. package/server.ts +2 -0
  146. package/src/lib/modules/client/dashboard/AutopilotPanel.svelte +400 -0
  147. package/src/lib/modules/client/dashboard/index.ts +1 -0
  148. package/src/lib/modules/client/neurolink/provider-config.ts +13 -37
  149. package/src/lib/modules/server/sessions/autopilot-engine.ts +346 -0
  150. package/src/lib/modules/server/sessions/litellm-client.ts +115 -0
  151. package/src/lib/modules/server/sessions/next-step-consensus.ts +185 -0
  152. package/src/lib/modules/server/sessions/summary-store.ts +111 -0
  153. package/src/lib/modules/server/ws/events-handler.ts +32 -0
  154. package/src/lib/types/autopilot.ts +73 -0
  155. package/src/lib/types/index.ts +1 -0
  156. package/src/lib/types/terminal-client.ts +2 -0
  157. package/src/routes/+layout.server.ts +2 -0
  158. package/src/routes/+layout.svelte +19 -4
  159. package/src/routes/+page.svelte +9 -1
  160. package/src/routes/api/autopilot/+server.ts +74 -0
  161. package/src/routes/api/neurolink-proxy/+server.ts +31 -6
  162. package/src/routes/api/notify/+server.ts +20 -3
  163. package/src/routes/api/summaries/+server.ts +99 -0
  164. package/build/client/_app/immutable/assets/2.DjiwkLqE.css +0 -1
  165. package/build/client/_app/immutable/assets/2.DjiwkLqE.css.br +0 -0
  166. package/build/client/_app/immutable/assets/2.DjiwkLqE.css.gz +0 -0
  167. package/build/client/_app/immutable/chunks/BB2l8o4X.js.br +0 -0
  168. package/build/client/_app/immutable/chunks/BB2l8o4X.js.gz +0 -0
  169. package/build/client/_app/immutable/chunks/BvmdJful.js.br +0 -0
  170. package/build/client/_app/immutable/chunks/BvmdJful.js.gz +0 -0
  171. package/build/client/_app/immutable/chunks/C_YNQL8b.js.br +0 -0
  172. package/build/client/_app/immutable/chunks/C_YNQL8b.js.gz +0 -0
  173. package/build/client/_app/immutable/chunks/ClIPTXf3.js.br +0 -0
  174. package/build/client/_app/immutable/chunks/ClIPTXf3.js.gz +0 -0
  175. package/build/client/_app/immutable/chunks/DIZ3Qst5.js.br +0 -0
  176. package/build/client/_app/immutable/chunks/DIZ3Qst5.js.gz +0 -0
  177. package/build/client/_app/immutable/chunks/DT4H19pV.js.br +0 -0
  178. package/build/client/_app/immutable/chunks/DT4H19pV.js.gz +0 -0
  179. package/build/client/_app/immutable/chunks/ZS5XYDx_.js.br +0 -0
  180. package/build/client/_app/immutable/chunks/pRcLbE0d.js +0 -1
  181. package/build/client/_app/immutable/chunks/pRcLbE0d.js.br +0 -0
  182. package/build/client/_app/immutable/chunks/pRcLbE0d.js.gz +0 -0
  183. package/build/client/_app/immutable/entry/app.Bd-DfeJi.js.br +0 -0
  184. package/build/client/_app/immutable/entry/app.Bd-DfeJi.js.gz +0 -0
  185. package/build/client/_app/immutable/entry/start.evvp4tX7.js +0 -1
  186. package/build/client/_app/immutable/entry/start.evvp4tX7.js.br +0 -2
  187. package/build/client/_app/immutable/entry/start.evvp4tX7.js.gz +0 -0
  188. package/build/client/_app/immutable/nodes/0.Bl-1LQWM.js +0 -10
  189. package/build/client/_app/immutable/nodes/0.Bl-1LQWM.js.br +0 -0
  190. package/build/client/_app/immutable/nodes/0.Bl-1LQWM.js.gz +0 -0
  191. package/build/client/_app/immutable/nodes/1.DT4dq6Ay.js.br +0 -0
  192. package/build/client/_app/immutable/nodes/1.DT4dq6Ay.js.gz +0 -0
  193. package/build/client/_app/immutable/nodes/10.CF7RGXpe.js.br +0 -0
  194. package/build/client/_app/immutable/nodes/10.CF7RGXpe.js.gz +0 -0
  195. package/build/client/_app/immutable/nodes/11.BV_G7yLI.js.br +0 -0
  196. package/build/client/_app/immutable/nodes/11.BV_G7yLI.js.gz +0 -0
  197. package/build/client/_app/immutable/nodes/2.DcRhsjYp.js +0 -13
  198. package/build/client/_app/immutable/nodes/2.DcRhsjYp.js.br +0 -0
  199. package/build/client/_app/immutable/nodes/2.DcRhsjYp.js.gz +0 -0
  200. package/build/client/_app/immutable/nodes/3.0MMe3oxR.js.br +0 -0
  201. package/build/client/_app/immutable/nodes/3.0MMe3oxR.js.gz +0 -0
  202. package/build/client/_app/immutable/nodes/4.CBX9A3ka.js.br +0 -0
  203. package/build/client/_app/immutable/nodes/4.CBX9A3ka.js.gz +0 -0
  204. package/build/client/_app/immutable/nodes/5.DIVKuZc9.js.br +0 -0
  205. package/build/client/_app/immutable/nodes/5.DIVKuZc9.js.gz +0 -0
  206. package/build/client/_app/immutable/nodes/6.ComiWlV6.js.br +0 -0
  207. package/build/client/_app/immutable/nodes/6.ComiWlV6.js.gz +0 -0
  208. package/build/client/_app/immutable/nodes/7.vkPx1kVP.js.br +0 -0
  209. package/build/client/_app/immutable/nodes/7.vkPx1kVP.js.gz +0 -0
  210. package/build/client/_app/immutable/nodes/8.Bmr3sWbS.js.br +0 -0
  211. package/build/client/_app/immutable/nodes/8.Bmr3sWbS.js.gz +0 -0
  212. package/build/client/_app/immutable/nodes/9.CAJucyeI.js.br +0 -0
  213. package/build/client/_app/immutable/nodes/9.CAJucyeI.js.gz +0 -0
  214. package/build/server/chunks/0-DDGB6CRT.js.map +0 -1
  215. package/build/server/chunks/_page.svelte-BLo2v_8E.js.map +0 -1
  216. package/build/server/chunks/_server.ts-BRAzC6W1.js.map +0 -1
  217. package/build/server/chunks/_server.ts-bk_EeAdY.js.map +0 -1
  218. package/build/server/chunks/guest-registry-t0-7Zv5q.js.map +0 -1
@@ -0,0 +1,400 @@
1
+ <script lang="ts">
2
+ import type { NextStep, SessionSummaryRecord } from '$lib/types';
3
+
4
+ import { formatRelativeTime, getApiKey } from '$lib/modules/client/common';
5
+ import { onMount } from 'svelte';
6
+
7
+ // Read-only view of the always-on SERVER autopilot engine: fetches persisted
8
+ // summaries from /api/summaries and toggles the engine via /api/autopilot.
9
+ // No engine runs in the browser — the panel just reflects server state.
10
+
11
+ let enabled = $state(false);
12
+ let summaries = $state<SessionSummaryRecord[]>([]);
13
+
14
+ /** Latest summary per session, newest first. */
15
+ const latest = $derived.by(() => {
16
+ // eslint-disable-next-line svelte/prefer-svelte-reactivity -- transient local dedup, not reactive state
17
+ const seen = new Set<string>();
18
+ const out: SessionSummaryRecord[] = [];
19
+ for (const s of summaries) {
20
+ const key = s.sessionId ?? s.terminalId ?? s.id;
21
+ if (!seen.has(key)) {
22
+ seen.add(key);
23
+ out.push(s);
24
+ }
25
+ }
26
+ return out;
27
+ });
28
+
29
+ function authHeaders(): Record<string, string> {
30
+ const key = getApiKey();
31
+ return key ? { Authorization: `Bearer ${key}` } : {};
32
+ }
33
+
34
+ async function refreshState(): Promise<void> {
35
+ try {
36
+ const res = await fetch('/api/autopilot', { headers: authHeaders() });
37
+ if (res.ok) {
38
+ enabled = Boolean(((await res.json()) as { enabled?: boolean }).enabled);
39
+ }
40
+ } catch {
41
+ // ignore transient errors
42
+ }
43
+ }
44
+
45
+ async function refreshSummaries(): Promise<void> {
46
+ try {
47
+ const res = await fetch('/api/summaries?limit=30', { headers: authHeaders() });
48
+ if (res.ok) {
49
+ summaries = ((await res.json()) as { summaries?: SessionSummaryRecord[] }).summaries ?? [];
50
+ }
51
+ } catch {
52
+ // ignore transient errors
53
+ }
54
+ }
55
+
56
+ async function toggle(): Promise<void> {
57
+ const next = !enabled;
58
+ enabled = next;
59
+ try {
60
+ const res = await fetch('/api/autopilot', {
61
+ body: JSON.stringify({ enabled: next }),
62
+ headers: { ...authHeaders(), 'Content-Type': 'application/json' },
63
+ method: 'POST',
64
+ });
65
+ if (res.ok) {
66
+ enabled = Boolean(((await res.json()) as { enabled?: boolean }).enabled);
67
+ }
68
+ } catch {
69
+ enabled = !next;
70
+ }
71
+ }
72
+
73
+ function parseSteps(raw: string): NextStep[] {
74
+ try {
75
+ const value: unknown = JSON.parse(raw);
76
+ return Array.isArray(value) ? (value as NextStep[]) : [];
77
+ } catch {
78
+ return [];
79
+ }
80
+ }
81
+
82
+ function stepBadgeClass(step: NextStep): string {
83
+ if (step.tentative) {
84
+ return 'step-badge step-badge--tentative';
85
+ }
86
+ const v = step.votes ?? 1;
87
+ if (v >= 4) {
88
+ return 'step-badge step-badge--strong';
89
+ }
90
+ if (v >= 3) {
91
+ return 'step-badge step-badge--medium';
92
+ }
93
+ return 'step-badge step-badge--weak';
94
+ }
95
+
96
+ function voteLabel(step: NextStep): string {
97
+ return step.tentative ? '~' : `${step.votes ?? 1}`;
98
+ }
99
+
100
+ onMount(() => {
101
+ void refreshState();
102
+ void refreshSummaries();
103
+ const timer = setInterval(() => {
104
+ void refreshSummaries();
105
+ void refreshState();
106
+ }, 8000);
107
+ return (): void => {
108
+ clearInterval(timer);
109
+ };
110
+ });
111
+ </script>
112
+
113
+ <div class="autopilot-panel">
114
+ <div class="panel-header">
115
+ <div class="panel-title-row">
116
+ <span class="panel-title">Auto-pilot</span>
117
+ {#if enabled}
118
+ <span class="status-dot-active" aria-hidden="true"></span>
119
+ {/if}
120
+ </div>
121
+ <button
122
+ class={enabled ? 'toggle-btn toggle-btn--on' : 'toggle-btn toggle-btn--off'}
123
+ onclick={toggle}
124
+ aria-label={enabled ? 'Stop Auto-pilot' : 'Start Auto-pilot'}
125
+ aria-pressed={enabled}
126
+ >
127
+ {enabled ? 'Stop' : 'Start'}
128
+ </button>
129
+ </div>
130
+
131
+ {#if latest.length > 0}
132
+ <div class="sessions-list">
133
+ {#each latest as s (s.id)}
134
+ {@const steps = parseSteps(s.nextSteps)}
135
+ <div class="session-card">
136
+ <div class="session-header">
137
+ <span class="session-name">{s.projectName ?? s.terminalId}</span>
138
+ <span class="session-status session-status--idle">{s.trigger}</span>
139
+ </div>
140
+
141
+ {#if s.summary}
142
+ <p class="session-summary">{s.summary}</p>
143
+ {/if}
144
+
145
+ {#if steps.length > 0}
146
+ <div class="next-steps">
147
+ <span class="next-steps-label">Next steps</span>
148
+ <ul class="steps-list">
149
+ {#each steps as step (step.text)}
150
+ <li class="step-item">
151
+ <span class={stepBadgeClass(step)} title="{step.votes ?? 1} vote(s)">
152
+ {voteLabel(step)}
153
+ </span>
154
+ <span class="step-text">{step.text}</span>
155
+ </li>
156
+ {/each}
157
+ </ul>
158
+ </div>
159
+ {/if}
160
+
161
+ <span class="last-updated">Updated {formatRelativeTime(s.createdAt)}</span>
162
+ </div>
163
+ {/each}
164
+ </div>
165
+ {:else}
166
+ <p class="panel-empty">
167
+ {enabled
168
+ ? 'Watching all active sessions…'
169
+ : 'Start Auto-pilot for AI summaries + next steps across all sessions — runs on the server, even with this page closed.'}
170
+ </p>
171
+ {/if}
172
+ </div>
173
+
174
+ <style>
175
+ .autopilot-panel {
176
+ background: var(--component-bg, #1a1a1a);
177
+ border: 1px solid var(--border, #2e2e2e);
178
+ border-radius: var(--radius-lg, 8px);
179
+ padding: var(--space-4, 16px);
180
+ margin-bottom: var(--space-4, 16px);
181
+ }
182
+
183
+ .panel-header {
184
+ display: flex;
185
+ align-items: center;
186
+ justify-content: space-between;
187
+ margin-bottom: var(--space-3, 12px);
188
+ }
189
+
190
+ .panel-title-row {
191
+ display: flex;
192
+ align-items: center;
193
+ gap: var(--space-2, 8px);
194
+ }
195
+
196
+ .panel-title {
197
+ color: var(--text-primary, #ededed);
198
+ font-size: var(--text-sm, 13px);
199
+ font-weight: 600;
200
+ letter-spacing: 0.04em;
201
+ text-transform: uppercase;
202
+ }
203
+
204
+ @keyframes pulse {
205
+ 0%,
206
+ 100% {
207
+ opacity: 1;
208
+ }
209
+ 50% {
210
+ opacity: 0.4;
211
+ }
212
+ }
213
+
214
+ .status-dot-active {
215
+ animation: pulse 2s ease-in-out infinite;
216
+ background: var(--ds-green-700, #16a34a);
217
+ border-radius: 50%;
218
+ display: inline-block;
219
+ flex-shrink: 0;
220
+ height: 7px;
221
+ width: 7px;
222
+ }
223
+
224
+ .toggle-btn {
225
+ border: 1px solid transparent;
226
+ border-radius: var(--radius-full, 9999px);
227
+ cursor: pointer;
228
+ font-size: var(--text-xs, 12px);
229
+ font-weight: 600;
230
+ padding: 4px 14px;
231
+ transition:
232
+ background var(--transition-fast, 150ms ease),
233
+ color var(--transition-fast, 150ms ease);
234
+ }
235
+
236
+ .toggle-btn--off {
237
+ background: var(--ds-green-alpha-200, rgba(22, 163, 74, 0.12));
238
+ border-color: var(--ds-green-alpha-400, rgba(22, 163, 74, 0.3));
239
+ color: var(--ds-green-700, #16a34a);
240
+ }
241
+
242
+ .toggle-btn--off:hover {
243
+ background: var(--ds-green-alpha-400, rgba(22, 163, 74, 0.2));
244
+ }
245
+
246
+ .toggle-btn--on {
247
+ background: var(--ds-gray-alpha-200, rgba(255, 255, 255, 0.06));
248
+ border-color: var(--border, #2e2e2e);
249
+ color: var(--text-secondary, #a1a1a1);
250
+ }
251
+
252
+ .toggle-btn--on:hover {
253
+ background: var(--ds-gray-alpha-300, rgba(255, 255, 255, 0.1));
254
+ color: var(--text-primary, #ededed);
255
+ }
256
+
257
+ .toggle-btn:focus-visible {
258
+ outline: 2px solid var(--ds-blue-700, #0070f3);
259
+ outline-offset: 2px;
260
+ }
261
+
262
+ .panel-empty {
263
+ color: var(--text-tertiary, #7d7d7d);
264
+ font-size: var(--text-xs, 12px);
265
+ font-style: italic;
266
+ margin: 0;
267
+ }
268
+
269
+ .sessions-list {
270
+ display: flex;
271
+ flex-direction: column;
272
+ gap: var(--space-3, 12px);
273
+ }
274
+
275
+ .session-card {
276
+ background: var(--bg-subtle, rgba(255, 255, 255, 0.02));
277
+ border: 1px solid var(--border-subtle, rgba(255, 255, 255, 0.06));
278
+ border-radius: var(--radius-md, 6px);
279
+ display: flex;
280
+ flex-direction: column;
281
+ gap: var(--space-2, 8px);
282
+ padding: var(--space-3, 12px);
283
+ }
284
+
285
+ .session-header {
286
+ align-items: center;
287
+ display: flex;
288
+ gap: var(--space-2, 8px);
289
+ justify-content: space-between;
290
+ }
291
+
292
+ .session-name {
293
+ color: var(--text-primary, #ededed);
294
+ flex: 1;
295
+ font-size: var(--text-sm, 13px);
296
+ font-weight: 600;
297
+ min-width: 0;
298
+ overflow: hidden;
299
+ text-overflow: ellipsis;
300
+ white-space: nowrap;
301
+ }
302
+
303
+ .session-status {
304
+ flex-shrink: 0;
305
+ font-size: var(--text-xs, 12px);
306
+ font-weight: 500;
307
+ }
308
+
309
+ .session-status--idle {
310
+ color: var(--text-tertiary, #7d7d7d);
311
+ }
312
+
313
+ .session-summary {
314
+ -webkit-box-orient: vertical;
315
+ -webkit-line-clamp: 2;
316
+ color: var(--text-secondary, #a1a1a1);
317
+ display: -webkit-box;
318
+ font-size: var(--text-xs, 12px);
319
+ line-clamp: 2;
320
+ line-height: var(--leading-normal, 1.5);
321
+ margin: 0;
322
+ overflow: hidden;
323
+ }
324
+
325
+ .next-steps {
326
+ display: flex;
327
+ flex-direction: column;
328
+ gap: 6px;
329
+ }
330
+
331
+ .next-steps-label {
332
+ color: var(--text-tertiary, #7d7d7d);
333
+ font-size: var(--text-xs, 12px);
334
+ font-weight: 600;
335
+ letter-spacing: 0.06em;
336
+ text-transform: uppercase;
337
+ }
338
+
339
+ .steps-list {
340
+ display: flex;
341
+ flex-direction: column;
342
+ gap: 5px;
343
+ list-style: none;
344
+ margin: 0;
345
+ padding: 0;
346
+ }
347
+
348
+ .step-item {
349
+ align-items: baseline;
350
+ display: flex;
351
+ gap: 8px;
352
+ }
353
+
354
+ .step-badge {
355
+ align-items: center;
356
+ border-radius: var(--radius-full, 9999px);
357
+ cursor: default;
358
+ display: inline-flex;
359
+ flex-shrink: 0;
360
+ font-size: 10px;
361
+ font-weight: 700;
362
+ height: 18px;
363
+ justify-content: center;
364
+ min-width: 20px;
365
+ padding: 0 5px;
366
+ }
367
+
368
+ .step-badge--strong {
369
+ background: var(--ds-green-alpha-200, rgba(22, 163, 74, 0.12));
370
+ color: var(--ds-green-700, #16a34a);
371
+ }
372
+
373
+ .step-badge--medium {
374
+ background: var(--ds-blue-alpha-200, rgba(0, 112, 243, 0.12));
375
+ color: var(--ds-blue-700, #0070f3);
376
+ }
377
+
378
+ .step-badge--weak {
379
+ background: var(--ds-gray-alpha-200, rgba(255, 255, 255, 0.06));
380
+ color: var(--text-tertiary, #7d7d7d);
381
+ }
382
+
383
+ .step-badge--tentative {
384
+ background: var(--ds-amber-alpha-200, rgba(217, 119, 6, 0.12));
385
+ color: var(--ds-amber-700, #d97706);
386
+ font-style: italic;
387
+ }
388
+
389
+ .step-text {
390
+ color: var(--text-secondary, #a1a1a1);
391
+ font-size: var(--text-xs, 12px);
392
+ line-height: var(--leading-normal, 1.5);
393
+ }
394
+
395
+ .last-updated {
396
+ color: var(--text-tertiary, #7d7d7d);
397
+ font-size: 10px;
398
+ margin-top: 2px;
399
+ }
400
+ </style>
@@ -1,3 +1,4 @@
1
+ export { default as AutopilotPanel } from './AutopilotPanel.svelte';
1
2
  export { default as DashboardCard } from './DashboardCard.svelte';
2
3
  export { default as DashboardView } from './DashboardView.svelte';
3
4
  export {
@@ -33,9 +33,8 @@ export const PROVIDERS = [
33
33
  model: 'mistral-small-2506',
34
34
  },
35
35
  {
36
- cors: 'direct' as const,
37
- envKeys: ['LITELLM_API_KEY', 'LITELLM_BASE_URL'],
38
- extraEnvKeys: ['LITELLM_MODEL'],
36
+ cors: 'proxy' as const,
37
+ envKeys: ['LITELLM_BASE_URL'],
39
38
  id: 'litellm' as const,
40
39
  label: 'LiteLLM',
41
40
  model: 'open-large',
@@ -46,8 +45,9 @@ export const PROVIDERS = [
46
45
 
47
46
  /**
48
47
  * Detect which provider to use based on available env vars.
49
- * Checks window.process.env for browser-side keys (litellm)
50
- * and trusts server-passed flags for proxy providers (google-ai, anthropic, openai, mistral).
48
+ * Trusts server-passed flags for all proxy providers (including litellm).
49
+ * The `cors: 'direct'` branch (window.process.env check) is reserved for
50
+ * future providers that expose keys browser-side directly.
51
51
  *
52
52
  * @param serverFlags - Per-provider availability from +page.server.ts
53
53
  * @param preferredProvider - Optional override (from NEUROLINK_PROVIDER env var)
@@ -57,44 +57,20 @@ export function detectActiveProvider(
57
57
  preferredProvider?: string
58
58
  ): null | { model: string; provider: ProviderId } {
59
59
  // If user explicitly set a preferred provider, try it first — but only if
60
- // credentials are actually available (serverFlags for proxy providers,
61
- // browser env for direct providers). Without this gate a misconfigured
62
- // NEUROLINK_PROVIDER would bypass the fallback loop and silently fail.
60
+ // credentials are actually available (serverFlags). Without this gate a
61
+ // misconfigured NEUROLINK_PROVIDER would bypass the fallback loop and
62
+ // silently fail.
63
63
  if (preferredProvider) {
64
64
  const prov = PROVIDERS.find((p) => p.id === preferredProvider);
65
- if (prov) {
66
- if (prov.cors === 'direct') {
67
- const env =
68
- typeof window !== 'undefined'
69
- ? ((window as unknown as { process?: { env?: Record<string, string> } }).process?.env ??
70
- {})
71
- : {};
72
- if (prov.envKeys.every((k) => Boolean(env[k]))) {
73
- return { model: prov.model, provider: prov.id };
74
- }
75
- } else if (serverFlags?.[prov.id]) {
76
- return { model: prov.model, provider: prov.id };
77
- }
65
+ if (prov && serverFlags?.[prov.id]) {
66
+ return { model: prov.model, provider: prov.id };
78
67
  }
79
68
  }
80
69
 
81
- const env =
82
- typeof window !== 'undefined'
83
- ? ((window as unknown as { process?: { env?: Record<string, string> } }).process?.env ?? {})
84
- : {};
85
-
86
70
  for (const prov of PROVIDERS) {
87
- if (prov.cors === 'direct') {
88
- // Check browser env vars
89
- const hasKey = prov.envKeys.every((k) => Boolean(env[k]));
90
- if (hasKey) {
91
- return { model: prov.model, provider: prov.id };
92
- }
93
- } else {
94
- // Check server-passed flags
95
- if (serverFlags?.[prov.id]) {
96
- return { model: prov.model, provider: prov.id };
97
- }
71
+ // All current providers are proxy-based — check server-passed flags.
72
+ if (serverFlags?.[prov.id]) {
73
+ return { model: prov.model, provider: prov.id };
98
74
  }
99
75
  }
100
76