9router 0.4.31 → 0.4.33

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 (266) hide show
  1. package/app/.next/BUILD_ID +1 -1
  2. package/app/.next/app-path-routes-manifest.json +7 -7
  3. package/app/.next/build-manifest.json +2 -2
  4. package/app/.next/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  5. package/app/.next/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  6. package/app/.next/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  7. package/app/.next/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  8. package/app/.next/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  9. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  10. package/app/.next/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  11. package/app/.next/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  12. package/app/.next/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  13. package/app/.next/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  14. package/app/.next/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  15. package/app/.next/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  16. package/app/.next/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  17. package/app/.next/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  18. package/app/.next/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  19. package/app/.next/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  20. package/app/.next/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  21. package/app/.next/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  22. package/app/.next/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  23. package/app/.next/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  24. package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  25. package/app/.next/server/app/_global-error.html +1 -1
  26. package/app/.next/server/app/_global-error.rsc +1 -1
  27. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  28. package/app/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  29. package/app/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  30. package/app/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  31. package/app/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  32. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  33. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  34. package/app/.next/server/app/_not-found.html +1 -1
  35. package/app/.next/server/app/_not-found.rsc +3 -3
  36. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
  37. package/app/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  38. package/app/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
  39. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  40. package/app/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  41. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  42. package/app/.next/server/app/api/models/route.js +1 -1
  43. package/app/.next/server/app/api/models/test/route.js +1 -1
  44. package/app/.next/server/app/api/providers/[id]/test-models/route.js +1 -1
  45. package/app/.next/server/app/api/providers/route.js +1 -1
  46. package/app/.next/server/app/api/translator/console-logs/route.js +1 -1
  47. package/app/.next/server/app/api/translator/console-logs/stream/route.js +1 -1
  48. package/app/.next/server/app/api/version/route.js +1 -1
  49. package/app/.next/server/app/api/version/shutdown/route.js +1 -1
  50. package/app/.next/server/app/api/version/update/route.js +1 -1
  51. package/app/.next/server/app/callback/page_client-reference-manifest.js +1 -1
  52. package/app/.next/server/app/callback.html +1 -1
  53. package/app/.next/server/app/callback.rsc +3 -3
  54. package/app/.next/server/app/callback.segments/_full.segment.rsc +3 -3
  55. package/app/.next/server/app/callback.segments/_head.segment.rsc +1 -1
  56. package/app/.next/server/app/callback.segments/_index.segment.rsc +3 -3
  57. package/app/.next/server/app/callback.segments/_tree.segment.rsc +1 -1
  58. package/app/.next/server/app/callback.segments/callback/__PAGE__.segment.rsc +1 -1
  59. package/app/.next/server/app/callback.segments/callback.segment.rsc +1 -1
  60. package/app/.next/server/app/dashboard/basic-chat.html +1 -1
  61. package/app/.next/server/app/dashboard/basic-chat.rsc +5 -5
  62. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +2 -2
  63. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat.segment.rsc +1 -1
  64. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  65. package/app/.next/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  66. package/app/.next/server/app/dashboard/basic-chat.segments/_full.segment.rsc +5 -5
  67. package/app/.next/server/app/dashboard/basic-chat.segments/_head.segment.rsc +1 -1
  68. package/app/.next/server/app/dashboard/basic-chat.segments/_index.segment.rsc +3 -3
  69. package/app/.next/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +1 -1
  70. package/app/.next/server/app/dashboard/cli-tools.html +1 -1
  71. package/app/.next/server/app/dashboard/cli-tools.rsc +5 -5
  72. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +2 -2
  73. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools.segment.rsc +1 -1
  74. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  75. package/app/.next/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  76. package/app/.next/server/app/dashboard/cli-tools.segments/_full.segment.rsc +5 -5
  77. package/app/.next/server/app/dashboard/cli-tools.segments/_head.segment.rsc +1 -1
  78. package/app/.next/server/app/dashboard/cli-tools.segments/_index.segment.rsc +3 -3
  79. package/app/.next/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +1 -1
  80. package/app/.next/server/app/dashboard/combos.html +1 -1
  81. package/app/.next/server/app/dashboard/combos.rsc +5 -5
  82. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +2 -2
  83. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos.segment.rsc +1 -1
  84. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  85. package/app/.next/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  86. package/app/.next/server/app/dashboard/combos.segments/_full.segment.rsc +5 -5
  87. package/app/.next/server/app/dashboard/combos.segments/_head.segment.rsc +1 -1
  88. package/app/.next/server/app/dashboard/combos.segments/_index.segment.rsc +3 -3
  89. package/app/.next/server/app/dashboard/combos.segments/_tree.segment.rsc +1 -1
  90. package/app/.next/server/app/dashboard/endpoint.html +1 -1
  91. package/app/.next/server/app/dashboard/endpoint.rsc +5 -5
  92. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +2 -2
  93. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint.segment.rsc +1 -1
  94. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  95. package/app/.next/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  96. package/app/.next/server/app/dashboard/endpoint.segments/_full.segment.rsc +5 -5
  97. package/app/.next/server/app/dashboard/endpoint.segments/_head.segment.rsc +1 -1
  98. package/app/.next/server/app/dashboard/endpoint.segments/_index.segment.rsc +3 -3
  99. package/app/.next/server/app/dashboard/endpoint.segments/_tree.segment.rsc +1 -1
  100. package/app/.next/server/app/dashboard/media-providers/web.html +1 -1
  101. package/app/.next/server/app/dashboard/media-providers/web.rsc +5 -5
  102. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +2 -2
  103. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web.segment.rsc +1 -1
  104. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers.segment.rsc +1 -1
  105. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  106. package/app/.next/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  107. package/app/.next/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +5 -5
  108. package/app/.next/server/app/dashboard/media-providers/web.segments/_head.segment.rsc +1 -1
  109. package/app/.next/server/app/dashboard/media-providers/web.segments/_index.segment.rsc +3 -3
  110. package/app/.next/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +1 -1
  111. package/app/.next/server/app/dashboard/mitm.html +1 -1
  112. package/app/.next/server/app/dashboard/mitm.rsc +5 -5
  113. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +2 -2
  114. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm.segment.rsc +1 -1
  115. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  116. package/app/.next/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  117. package/app/.next/server/app/dashboard/mitm.segments/_full.segment.rsc +5 -5
  118. package/app/.next/server/app/dashboard/mitm.segments/_head.segment.rsc +1 -1
  119. package/app/.next/server/app/dashboard/mitm.segments/_index.segment.rsc +3 -3
  120. package/app/.next/server/app/dashboard/mitm.segments/_tree.segment.rsc +1 -1
  121. package/app/.next/server/app/dashboard/profile.html +1 -1
  122. package/app/.next/server/app/dashboard/profile.rsc +5 -5
  123. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +2 -2
  124. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile.segment.rsc +1 -1
  125. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  126. package/app/.next/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  127. package/app/.next/server/app/dashboard/profile.segments/_full.segment.rsc +5 -5
  128. package/app/.next/server/app/dashboard/profile.segments/_head.segment.rsc +1 -1
  129. package/app/.next/server/app/dashboard/profile.segments/_index.segment.rsc +3 -3
  130. package/app/.next/server/app/dashboard/profile.segments/_tree.segment.rsc +1 -1
  131. package/app/.next/server/app/dashboard/providers/new.html +1 -1
  132. package/app/.next/server/app/dashboard/providers/new.rsc +5 -5
  133. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +2 -2
  134. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new.segment.rsc +1 -1
  135. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  136. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  137. package/app/.next/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  138. package/app/.next/server/app/dashboard/providers/new.segments/_full.segment.rsc +5 -5
  139. package/app/.next/server/app/dashboard/providers/new.segments/_head.segment.rsc +1 -1
  140. package/app/.next/server/app/dashboard/providers/new.segments/_index.segment.rsc +3 -3
  141. package/app/.next/server/app/dashboard/providers/new.segments/_tree.segment.rsc +1 -1
  142. package/app/.next/server/app/dashboard/providers.html +1 -1
  143. package/app/.next/server/app/dashboard/providers.rsc +5 -5
  144. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +2 -2
  145. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers.segment.rsc +1 -1
  146. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  147. package/app/.next/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  148. package/app/.next/server/app/dashboard/providers.segments/_full.segment.rsc +5 -5
  149. package/app/.next/server/app/dashboard/providers.segments/_head.segment.rsc +1 -1
  150. package/app/.next/server/app/dashboard/providers.segments/_index.segment.rsc +3 -3
  151. package/app/.next/server/app/dashboard/providers.segments/_tree.segment.rsc +1 -1
  152. package/app/.next/server/app/dashboard/proxy-pools.html +1 -1
  153. package/app/.next/server/app/dashboard/proxy-pools.rsc +5 -5
  154. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +2 -2
  155. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools.segment.rsc +1 -1
  156. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  157. package/app/.next/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  158. package/app/.next/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +5 -5
  159. package/app/.next/server/app/dashboard/proxy-pools.segments/_head.segment.rsc +1 -1
  160. package/app/.next/server/app/dashboard/proxy-pools.segments/_index.segment.rsc +3 -3
  161. package/app/.next/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +1 -1
  162. package/app/.next/server/app/dashboard/quota.html +2 -2
  163. package/app/.next/server/app/dashboard/quota.rsc +6 -6
  164. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +3 -3
  165. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota.segment.rsc +1 -1
  166. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  167. package/app/.next/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  168. package/app/.next/server/app/dashboard/quota.segments/_full.segment.rsc +6 -6
  169. package/app/.next/server/app/dashboard/quota.segments/_head.segment.rsc +1 -1
  170. package/app/.next/server/app/dashboard/quota.segments/_index.segment.rsc +3 -3
  171. package/app/.next/server/app/dashboard/quota.segments/_tree.segment.rsc +1 -1
  172. package/app/.next/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  173. package/app/.next/server/app/dashboard/settings/pricing.html +1 -1
  174. package/app/.next/server/app/dashboard/settings/pricing.rsc +3 -3
  175. package/app/.next/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +3 -3
  176. package/app/.next/server/app/dashboard/settings/pricing.segments/_head.segment.rsc +1 -1
  177. package/app/.next/server/app/dashboard/settings/pricing.segments/_index.segment.rsc +3 -3
  178. package/app/.next/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +1 -1
  179. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +1 -1
  180. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing.segment.rsc +1 -1
  181. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard/settings.segment.rsc +1 -1
  182. package/app/.next/server/app/dashboard/settings/pricing.segments/dashboard.segment.rsc +1 -1
  183. package/app/.next/server/app/dashboard/skills.html +1 -1
  184. package/app/.next/server/app/dashboard/skills.rsc +5 -5
  185. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +2 -2
  186. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills.segment.rsc +1 -1
  187. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  188. package/app/.next/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  189. package/app/.next/server/app/dashboard/skills.segments/_full.segment.rsc +5 -5
  190. package/app/.next/server/app/dashboard/skills.segments/_head.segment.rsc +1 -1
  191. package/app/.next/server/app/dashboard/skills.segments/_index.segment.rsc +3 -3
  192. package/app/.next/server/app/dashboard/skills.segments/_tree.segment.rsc +1 -1
  193. package/app/.next/server/app/dashboard/translator.html +1 -1
  194. package/app/.next/server/app/dashboard/translator.rsc +5 -5
  195. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +2 -2
  196. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator.segment.rsc +1 -1
  197. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  198. package/app/.next/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  199. package/app/.next/server/app/dashboard/translator.segments/_full.segment.rsc +5 -5
  200. package/app/.next/server/app/dashboard/translator.segments/_head.segment.rsc +1 -1
  201. package/app/.next/server/app/dashboard/translator.segments/_index.segment.rsc +3 -3
  202. package/app/.next/server/app/dashboard/translator.segments/_tree.segment.rsc +1 -1
  203. package/app/.next/server/app/dashboard/usage.html +1 -1
  204. package/app/.next/server/app/dashboard/usage.rsc +5 -5
  205. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +2 -2
  206. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage.segment.rsc +1 -1
  207. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  208. package/app/.next/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  209. package/app/.next/server/app/dashboard/usage.segments/_full.segment.rsc +5 -5
  210. package/app/.next/server/app/dashboard/usage.segments/_head.segment.rsc +1 -1
  211. package/app/.next/server/app/dashboard/usage.segments/_index.segment.rsc +3 -3
  212. package/app/.next/server/app/dashboard/usage.segments/_tree.segment.rsc +1 -1
  213. package/app/.next/server/app/dashboard.html +1 -1
  214. package/app/.next/server/app/dashboard.rsc +5 -5
  215. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +2 -2
  216. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard.segment.rsc +1 -1
  217. package/app/.next/server/app/dashboard.segments/!KGRhc2hib2FyZCk.segment.rsc +2 -2
  218. package/app/.next/server/app/dashboard.segments/_full.segment.rsc +5 -5
  219. package/app/.next/server/app/dashboard.segments/_head.segment.rsc +1 -1
  220. package/app/.next/server/app/dashboard.segments/_index.segment.rsc +3 -3
  221. package/app/.next/server/app/dashboard.segments/_tree.segment.rsc +1 -1
  222. package/app/.next/server/app/index.html +1 -1
  223. package/app/.next/server/app/index.rsc +3 -3
  224. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  225. package/app/.next/server/app/index.segments/_full.segment.rsc +3 -3
  226. package/app/.next/server/app/index.segments/_head.segment.rsc +1 -1
  227. package/app/.next/server/app/index.segments/_index.segment.rsc +3 -3
  228. package/app/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  229. package/app/.next/server/app/landing/page_client-reference-manifest.js +1 -1
  230. package/app/.next/server/app/landing.html +1 -1
  231. package/app/.next/server/app/landing.rsc +3 -3
  232. package/app/.next/server/app/landing.segments/_full.segment.rsc +3 -3
  233. package/app/.next/server/app/landing.segments/_head.segment.rsc +1 -1
  234. package/app/.next/server/app/landing.segments/_index.segment.rsc +3 -3
  235. package/app/.next/server/app/landing.segments/_tree.segment.rsc +1 -1
  236. package/app/.next/server/app/landing.segments/landing/__PAGE__.segment.rsc +1 -1
  237. package/app/.next/server/app/landing.segments/landing.segment.rsc +1 -1
  238. package/app/.next/server/app/login/page_client-reference-manifest.js +1 -1
  239. package/app/.next/server/app/login.html +1 -1
  240. package/app/.next/server/app/login.rsc +4 -4
  241. package/app/.next/server/app/login.segments/_full.segment.rsc +4 -4
  242. package/app/.next/server/app/login.segments/_head.segment.rsc +1 -1
  243. package/app/.next/server/app/login.segments/_index.segment.rsc +3 -3
  244. package/app/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  245. package/app/.next/server/app/login.segments/login/__PAGE__.segment.rsc +2 -2
  246. package/app/.next/server/app/login.segments/login.segment.rsc +1 -1
  247. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  248. package/app/.next/server/app-paths-manifest.json +7 -7
  249. package/app/.next/server/chunks/1795.js +1 -1
  250. package/app/.next/server/chunks/6263.js +1 -1
  251. package/app/.next/server/chunks/6283.js +1 -1
  252. package/app/.next/server/chunks/6634.js +1 -1
  253. package/app/.next/server/middleware-build-manifest.js +1 -1
  254. package/app/.next/server/pages/404.html +1 -1
  255. package/app/.next/server/pages/500.html +1 -1
  256. package/app/.next/static/chunks/{505-39ae32473371c4a3.js → 505-b06cfc156450639a.js} +1 -1
  257. package/app/package.json +1 -1
  258. package/cli.js +4 -0
  259. package/hooks/postinstall.js +7 -0
  260. package/hooks/trayRuntime.js +84 -0
  261. package/package.json +3 -3
  262. package/src/cli/tray/tray.js +136 -104
  263. package/src/cli/tray/tray.ps1 +79 -0
  264. package/src/cli/tray/trayWin.js +89 -0
  265. /package/app/.next/static/{xjtYx1FfVtGAPQbE4LiMu → xilRJjRhqJhUZ2VStWKZh}/_buildManifest.js +0 -0
  266. /package/app/.next/static/{xjtYx1FfVtGAPQbE4LiMu → xilRJjRhqJhUZ2VStWKZh}/_ssgManifest.js +0 -0
package/app/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "9router-app",
3
- "version": "0.4.31",
3
+ "version": "0.4.33",
4
4
  "description": "9Router web dashboard",
5
5
  "private": true,
6
6
  "scripts": {
package/cli.js CHANGED
@@ -44,6 +44,7 @@ function createSpinner(text) {
44
44
 
45
45
  const pkg = require("./package.json");
46
46
  const { ensureSqliteRuntime, buildEnvWithRuntime } = require("./hooks/sqliteRuntime");
47
+ const { ensureTrayRuntime } = require("./hooks/trayRuntime");
47
48
  const args = process.argv.slice(2);
48
49
 
49
50
  // Self-heal SQLite runtime deps (sql.js + better-sqlite3) into ~/.9router/runtime
@@ -51,6 +52,9 @@ const args = process.argv.slice(2);
51
52
  // better-sqlite3 is optional. Logs to stderr only on failure.
52
53
  try { ensureSqliteRuntime({ silent: true }); } catch {}
53
54
 
55
+ // Self-heal tray runtime (systray for macOS/Linux only). Windows skipped.
56
+ try { ensureTrayRuntime({ silent: true }); } catch {}
57
+
54
58
  // Configuration constants
55
59
  const APP_NAME = pkg.name; // Use from package.json
56
60
  const INSTALL_CMD_LATEST = `npm i -g ${APP_NAME}@latest --prefer-online`;
@@ -4,6 +4,7 @@
4
4
  // `9router` start doesn't need network. Failure here is non-fatal —
5
5
  // cli.js will retry at runtime if anything is missing.
6
6
  const { ensureSqliteRuntime } = require("./sqliteRuntime");
7
+ const { ensureTrayRuntime } = require("./trayRuntime");
7
8
 
8
9
  try {
9
10
  ensureSqliteRuntime({ silent: false });
@@ -12,4 +13,10 @@ try {
12
13
  console.warn(`[9router] runtime warm-up skipped: ${e.message}`);
13
14
  }
14
15
 
16
+ try {
17
+ ensureTrayRuntime({ silent: false });
18
+ } catch (e) {
19
+ console.warn(`[9router] tray runtime skipped: ${e.message}`);
20
+ }
21
+
15
22
  process.exit(0);
@@ -0,0 +1,84 @@
1
+ // Lazy install systray for macOS/Linux into USER_DATA_DIR/runtime/node_modules.
2
+ // Windows uses PowerShell NotifyIcon (no binary) → no systray needed.
3
+ // This keeps the published npm tarball free of unsigned Go binaries that
4
+ // trigger antivirus false positives (e.g. Kaspersky flagging tray_windows.exe).
5
+ const { spawnSync } = require("child_process");
6
+ const fs = require("fs");
7
+ const path = require("path");
8
+ const { getRuntimeDir, getRuntimeNodeModules } = require("./sqliteRuntime");
9
+
10
+ const SYSTRAY_VERSION = "1.0.5";
11
+
12
+ function hasSystray() {
13
+ return fs.existsSync(path.join(getRuntimeNodeModules(), "systray", "package.json"));
14
+ }
15
+
16
+ // Remove legacy systray from all known locations on Windows (AV false positive cleanup)
17
+ function cleanupWindowsSystray({ silent = false } = {}) {
18
+ if (process.platform !== "win32") return;
19
+ // 1) Runtime dir: %APPDATA%\9router\runtime\node_modules\systray
20
+ // 2) npm global nested: <npm_prefix>\node_modules\9router\node_modules\systray
21
+ // __dirname here = <npm_prefix>\node_modules\9router\hooks → up 1 = pkg root
22
+ const targets = [
23
+ path.join(getRuntimeNodeModules(), "systray"),
24
+ path.join(__dirname, "..", "node_modules", "systray")
25
+ ];
26
+ for (const dir of targets) {
27
+ if (fs.existsSync(dir)) {
28
+ try {
29
+ fs.rmSync(dir, { recursive: true, force: true });
30
+ if (!silent) console.log(`[9router][runtime] removed legacy systray: ${dir}`);
31
+ } catch (e) {
32
+ if (!silent) console.warn(`[9router][runtime] failed to remove ${dir}: ${e.message}`);
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ function ensureRuntimeDir() {
39
+ const dir = getRuntimeDir();
40
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
41
+ const pkgPath = path.join(dir, "package.json");
42
+ if (!fs.existsSync(pkgPath)) {
43
+ fs.writeFileSync(pkgPath, JSON.stringify({
44
+ name: "9router-runtime",
45
+ version: "1.0.0",
46
+ private: true
47
+ }, null, 2));
48
+ }
49
+ return dir;
50
+ }
51
+
52
+ function npmInstall(pkgs, { silent = false } = {}) {
53
+ const cwd = ensureRuntimeDir();
54
+ const args = ["install", ...pkgs, "--no-audit", "--no-fund", "--no-save", "--prefer-online"];
55
+ const npmCmd = process.platform === "win32" ? "npm.cmd" : "npm";
56
+ if (!silent) console.log(`[9router][runtime] ${npmCmd} ${args.join(" ")} (cwd: ${cwd})`);
57
+ const res = spawnSync(npmCmd, args, {
58
+ cwd,
59
+ stdio: silent ? "ignore" : "inherit",
60
+ timeout: 120000,
61
+ shell: process.platform === "win32"
62
+ });
63
+ return res.status === 0;
64
+ }
65
+
66
+ // Public: ensure systray is installed on macOS/Linux only.
67
+ // Windows skips entirely (uses PowerShell tray).
68
+ function ensureTrayRuntime({ silent = false } = {}) {
69
+ if (process.platform === "win32") {
70
+ cleanupWindowsSystray({ silent });
71
+ return { systray: false, skipped: true };
72
+ }
73
+ if (hasSystray()) {
74
+ if (!silent) console.log("[9router][runtime] systray OK");
75
+ return { systray: true };
76
+ }
77
+ const ok = npmInstall([`systray@${SYSTRAY_VERSION}`], { silent });
78
+ if (!ok && !silent) {
79
+ console.warn("[9router][runtime] systray install failed (tray will be disabled)");
80
+ }
81
+ return { systray: ok && hasSystray() };
82
+ }
83
+
84
+ module.exports = { ensureTrayRuntime };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "9router",
3
- "version": "0.4.31",
3
+ "version": "0.4.33",
4
4
  "description": "9Router CLI - Start and manage 9Router server",
5
5
  "bin": {
6
6
  "9router": "./cli.js"
@@ -21,10 +21,10 @@
21
21
  "node-forge": "^1.3.3",
22
22
  "node-machine-id": "^1.1.12",
23
23
  "react": "19.2.1",
24
- "react-dom": "19.2.1",
25
- "systray": "^1.0.5"
24
+ "react-dom": "19.2.1"
26
25
  },
27
26
  "comment_sqlite": "sql.js + better-sqlite3 are NOT bundled here. They are installed into ~/.9router/runtime/node_modules by hooks/postinstall.js (and re-checked at runtime by cli.js). This avoids Windows EBUSY errors when updating the global CLI, since native .node files no longer live under the locked install dir.",
27
+ "comment_systray": "systray is NOT bundled here. It is lazy-installed into ~/.9router/runtime/node_modules by hooks/postinstall.js on macOS/Linux only. Windows uses PowerShell NotifyIcon (zero binary). This avoids shipping the unsigned Go binary tray_windows.exe that triggers antivirus false positives (Kaspersky).",
28
28
  "engines": {
29
29
  "node": ">=18.0.0"
30
30
  },
@@ -3,9 +3,10 @@ const fs = require("fs");
3
3
  const path = require("path");
4
4
 
5
5
  let trayInstance = null;
6
+ let isWinTray = false;
6
7
 
7
8
  /**
8
- * Get icon base64 from file — use .ico on Windows, .png on macOS/Linux
9
+ * Get icon base64 from file — used for systray (mac/linux)
9
10
  */
10
11
  function getIconBase64() {
11
12
  const isWin = process.platform === "win32";
@@ -26,11 +27,9 @@ function getIconBase64() {
26
27
  */
27
28
  function isTraySupported() {
28
29
  const platform = process.platform;
29
- // Supported platforms: darwin (macOS), win32 (Windows), linux
30
30
  if (!["darwin", "win32", "linux"].includes(platform)) {
31
31
  return false;
32
32
  }
33
- // Skip on Linux without display (headless server)
34
33
  if (platform === "linux" && !process.env.DISPLAY) {
35
34
  return false;
36
35
  }
@@ -43,122 +42,156 @@ function isTraySupported() {
43
42
  * @returns {Object|null} tray instance or null if not supported/failed
44
43
  */
45
44
  function initTray(options) {
46
- // Check OS support first
47
45
  if (!isTraySupported()) {
48
46
  return null;
49
47
  }
50
48
 
51
- const { port, onQuit, onOpenDashboard } = options;
49
+ // Windows uses PowerShell NotifyIcon (AV-safe), others use systray
50
+ if (process.platform === "win32") {
51
+ return initWindowsTray(options);
52
+ }
53
+ return initUnixTray(options);
54
+ }
55
+
56
+ /**
57
+ * Build menu items array shared between platforms
58
+ */
59
+ function buildMenuItems(port, autostartEnabled) {
60
+ return [
61
+ { title: `9Router (Port ${port})`, tooltip: "Server is running", enabled: false },
62
+ { title: "Open Dashboard", tooltip: "Open in browser", enabled: true },
63
+ {
64
+ title: autostartEnabled ? "✓ Auto-start Enabled" : "Enable Auto-start",
65
+ tooltip: "Run on OS startup",
66
+ enabled: true
67
+ },
68
+ { title: "Quit", tooltip: "Stop server and exit", enabled: true }
69
+ ];
70
+ }
71
+
72
+ // Menu item indexes
73
+ const MENU_INDEX = { STATUS: 0, DASHBOARD: 1, AUTOSTART: 2, QUIT: 3 };
52
74
 
75
+ /**
76
+ * Get current autostart state
77
+ */
78
+ function getAutostartEnabled() {
53
79
  try {
54
- const SysTray = require("systray").default;
80
+ const { isAutoStartEnabled } = require("./autostart");
81
+ return isAutoStartEnabled();
82
+ } catch (e) {
83
+ return false;
84
+ }
85
+ }
55
86
 
56
- // Check if autostart is enabled
57
- let autostartEnabled = false;
87
+ /**
88
+ * Handle menu item click (shared logic)
89
+ */
90
+ function handleClick(index, options, onAutostartToggle) {
91
+ const { onQuit, onOpenDashboard, port } = options;
92
+ if (index === MENU_INDEX.DASHBOARD) {
93
+ if (onOpenDashboard) onOpenDashboard();
94
+ else openBrowser(`http://localhost:${port}/dashboard`);
95
+ } else if (index === MENU_INDEX.AUTOSTART) {
96
+ const enabled = getAutostartEnabled();
58
97
  try {
59
- const { isAutoStartEnabled } = require("./autostart");
60
- autostartEnabled = isAutoStartEnabled();
98
+ const { enableAutoStart, disableAutoStart } = require("./autostart");
99
+ if (enabled) disableAutoStart();
100
+ else enableAutoStart();
101
+ onAutostartToggle(!enabled);
61
102
  } catch (e) {}
103
+ } else if (index === MENU_INDEX.QUIT) {
104
+ console.log("\n👋 Shutting down...");
105
+ if (onQuit) onQuit();
106
+ killTray();
107
+ setTimeout(() => process.exit(0), 500);
108
+ }
109
+ }
110
+
111
+ /**
112
+ * Windows tray via PowerShell NotifyIcon
113
+ */
114
+ function initWindowsTray(options) {
115
+ const { port } = options;
116
+ try {
117
+ const { initWinTray } = require("./trayWin");
118
+ const iconPath = path.join(__dirname, "icon.ico");
119
+ const autostartEnabled = getAutostartEnabled();
120
+ const items = buildMenuItems(port, autostartEnabled);
121
+
122
+ trayInstance = initWinTray({
123
+ iconPath,
124
+ tooltip: `9Router - Port ${port}`,
125
+ items,
126
+ onClick: (index) => {
127
+ handleClick(index, options, (newEnabled) => {
128
+ const newTitle = newEnabled ? "✓ Auto-start Enabled" : "Enable Auto-start";
129
+ trayInstance.updateItem(MENU_INDEX.AUTOSTART, newTitle, true);
130
+ });
131
+ }
132
+ });
133
+
134
+ isWinTray = true;
135
+ return trayInstance;
136
+ } catch (err) {
137
+ return null;
138
+ }
139
+ }
140
+
141
+ /**
142
+ * macOS/Linux tray via systray binary
143
+ */
144
+ function resolveSystray() {
145
+ // Try local first (dev), then runtime dir (production lazy install)
146
+ try {
147
+ return require("systray").default;
148
+ } catch (e) {}
149
+ try {
150
+ const { getRuntimeNodeModules } = require("../../../hooks/sqliteRuntime");
151
+ const systrayPath = path.join(getRuntimeNodeModules(), "systray");
152
+ return require(systrayPath).default;
153
+ } catch (e) {
154
+ return null;
155
+ }
156
+ }
157
+
158
+ function initUnixTray(options) {
159
+ const { port } = options;
160
+ try {
161
+ const SysTray = resolveSystray();
162
+ if (!SysTray) return null;
163
+ const autostartEnabled = getAutostartEnabled();
164
+ const items = buildMenuItems(port, autostartEnabled);
62
165
 
63
- const isWin = process.platform === "win32";
64
166
  const menu = {
65
167
  icon: getIconBase64(),
66
- // macOS requires empty title; Windows uses title as the tray icon tooltip
67
- title: isWin ? `9Router - Port ${port}` : "",
168
+ title: "",
68
169
  tooltip: `9Router - Port ${port}`,
69
- items: [
70
- {
71
- title: `9Router (Port ${port})`,
72
- tooltip: "Server is running",
73
- enabled: false
74
- },
75
- {
76
- title: "Open Dashboard",
77
- tooltip: "Open in browser",
78
- enabled: true
79
- },
80
- {
81
- title: autostartEnabled ? "✓ Auto-start Enabled" : "Enable Auto-start",
82
- tooltip: "Run on OS startup",
83
- enabled: true
84
- },
85
- {
86
- title: "Quit",
87
- tooltip: "Stop server and exit",
88
- enabled: true
89
- }
90
- ]
170
+ items
91
171
  };
92
172
 
93
- trayInstance = new SysTray({
94
- menu,
95
- debug: false,
96
- copyDir: true
97
- });
98
-
99
- // Menu item index: 0=status, 1=dashboard, 2=autostart, 3=quit
100
- const AUTOSTART_INDEX = 2;
173
+ trayInstance = new SysTray({ menu, debug: false, copyDir: true });
174
+ isWinTray = false;
101
175
 
102
176
  trayInstance.onClick((action) => {
103
- if (action.item.title === "Open Dashboard") {
104
- if (onOpenDashboard) {
105
- onOpenDashboard();
106
- } else {
107
- openBrowser(`http://localhost:${port}/dashboard`);
108
- }
109
- } else if (action.item.title === "✓ Auto-start Enabled") {
110
- // Disable autostart
111
- try {
112
- const { disableAutoStart } = require("./autostart");
113
- disableAutoStart();
114
- // Update menu item
115
- trayInstance.sendAction({
116
- type: "update-item",
117
- item: {
118
- title: "Enable Auto-start",
119
- tooltip: "Run on OS startup",
120
- enabled: true
121
- },
122
- seq_id: AUTOSTART_INDEX
123
- });
124
- } catch (e) {}
125
- } else if (action.item.title === "Enable Auto-start") {
126
- // Enable autostart
127
- try {
128
- const { enableAutoStart } = require("./autostart");
129
- enableAutoStart();
130
- // Update menu item
131
- trayInstance.sendAction({
132
- type: "update-item",
133
- item: {
134
- title: "✓ Auto-start Enabled",
135
- tooltip: "Run on OS startup",
136
- enabled: true
137
- },
138
- seq_id: AUTOSTART_INDEX
139
- });
140
- } catch (e) {}
141
- } else if (action.item.title === "Quit") {
142
- console.log("\n👋 Shutting down...");
143
- if (onQuit) {
144
- onQuit();
145
- }
146
- killTray();
147
- setTimeout(() => process.exit(0), 500);
148
- }
177
+ handleClick(action.seq_id, options, (newEnabled) => {
178
+ trayInstance.sendAction({
179
+ type: "update-item",
180
+ item: {
181
+ title: newEnabled ? "✓ Auto-start Enabled" : "Enable Auto-start",
182
+ tooltip: "Run on OS startup",
183
+ enabled: true
184
+ },
185
+ seq_id: MENU_INDEX.AUTOSTART
186
+ });
187
+ });
149
188
  });
150
189
 
151
- trayInstance.onReady(() => {
152
- // Tray ready - silent
153
- });
154
-
155
- trayInstance.onError((err) => {
156
- // Ignore errors during shutdown
157
- });
190
+ trayInstance.onReady(() => {});
191
+ trayInstance.onError(() => {});
158
192
 
159
193
  return trayInstance;
160
194
  } catch (err) {
161
- // Silent fail - tray is optional, app continues without it
162
195
  return null;
163
196
  }
164
197
  }
@@ -168,15 +201,14 @@ function initTray(options) {
168
201
  */
169
202
  function killTray() {
170
203
  const instance = trayInstance;
171
- trayInstance = null; // Set to null first to prevent error handlers
172
-
204
+ const wasWin = isWinTray;
205
+ trayInstance = null;
206
+
173
207
  if (instance) {
174
208
  try {
175
- // Kill with silent mode to avoid JSON parse errors
176
- instance.kill(true);
177
- } catch (e) {
178
- // Ignore kill errors - tray binary may already be dead
179
- }
209
+ if (wasWin) instance.kill();
210
+ else instance.kill(true);
211
+ } catch (e) {}
180
212
  }
181
213
  }
182
214
 
@@ -0,0 +1,79 @@
1
+ # 9Router tray icon for Windows using NotifyIcon
2
+ # IPC: stdin JSON commands, stdout JSON events
3
+ param([string]$IconPath, [string]$Tooltip)
4
+
5
+ Add-Type -AssemblyName System.Windows.Forms
6
+ Add-Type -AssemblyName System.Drawing
7
+
8
+ $ErrorActionPreference = "Stop"
9
+ [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
10
+ [Console]::InputEncoding = [System.Text.Encoding]::UTF8
11
+ $OutputEncoding = [System.Text.Encoding]::UTF8
12
+
13
+ $script:notifyIcon = New-Object System.Windows.Forms.NotifyIcon
14
+ $script:notifyIcon.Icon = New-Object System.Drawing.Icon($IconPath)
15
+ $script:notifyIcon.Text = $Tooltip
16
+ $script:notifyIcon.Visible = $true
17
+
18
+ $script:menu = New-Object System.Windows.Forms.ContextMenuStrip
19
+ $script:notifyIcon.ContextMenuStrip = $script:menu
20
+ $script:items = @()
21
+
22
+ function Write-Event($obj) {
23
+ $json = $obj | ConvertTo-Json -Compress
24
+ [Console]::Out.WriteLine($json)
25
+ [Console]::Out.Flush()
26
+ }
27
+
28
+ function Add-MenuItem($index, $title, $enabled) {
29
+ $item = New-Object System.Windows.Forms.ToolStripMenuItem
30
+ $item.Text = $title
31
+ $item.Enabled = $enabled
32
+ $idx = $index
33
+ $item.Add_Click({ Write-Event @{ type = "click"; index = $idx } }.GetNewClosure())
34
+ $script:menu.Items.Add($item) | Out-Null
35
+ $script:items += $item
36
+ }
37
+
38
+ function Update-MenuItem($index, $title, $enabled) {
39
+ if ($index -lt $script:items.Count) {
40
+ $script:items[$index].Text = $title
41
+ $script:items[$index].Enabled = $enabled
42
+ }
43
+ }
44
+
45
+ function Set-Tooltip($text) {
46
+ # NotifyIcon.Text max 63 chars
47
+ if ($text.Length -gt 63) { $text = $text.Substring(0, 63) }
48
+ $script:notifyIcon.Text = $text
49
+ }
50
+
51
+ # Background reader thread polls stdin via timer on UI thread
52
+ $script:timer = New-Object System.Windows.Forms.Timer
53
+ $script:timer.Interval = 100
54
+ $script:timer.Add_Tick({
55
+ try {
56
+ while ([Console]::In.Peek() -ne -1) {
57
+ $line = [Console]::In.ReadLine()
58
+ if ([string]::IsNullOrWhiteSpace($line)) { continue }
59
+ $cmd = $line | ConvertFrom-Json
60
+ switch ($cmd.action) {
61
+ "add-item" { Add-MenuItem $cmd.index $cmd.title $cmd.enabled }
62
+ "update-item" { Update-MenuItem $cmd.index $cmd.title $cmd.enabled }
63
+ "set-tooltip" { Set-Tooltip $cmd.text }
64
+ "ready" { Write-Event @{ type = "ready" } }
65
+ "kill" {
66
+ $script:notifyIcon.Visible = $false
67
+ $script:notifyIcon.Dispose()
68
+ [System.Windows.Forms.Application]::Exit()
69
+ }
70
+ }
71
+ }
72
+ } catch {
73
+ Write-Event @{ type = "error"; message = $_.Exception.Message }
74
+ }
75
+ })
76
+ $script:timer.Start()
77
+
78
+ Write-Event @{ type = "started" }
79
+ [System.Windows.Forms.Application]::Run()
@@ -0,0 +1,89 @@
1
+ const { spawn } = require("child_process");
2
+ const path = require("path");
3
+ const readline = require("readline");
4
+
5
+ // PowerShell-based tray for Windows (AV-safe, zero binary deps)
6
+
7
+ let psProcess = null;
8
+ let clickHandler = null;
9
+
10
+ /**
11
+ * Send JSON command to PowerShell tray process via stdin
12
+ */
13
+ function sendCommand(cmd) {
14
+ if (psProcess && psProcess.stdin.writable) {
15
+ psProcess.stdin.write(`${JSON.stringify(cmd)}\n`, "utf8");
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Initialize Windows tray using PowerShell NotifyIcon
21
+ * @param {Object} options - { iconPath, tooltip, items, onClick }
22
+ * items: [{ title, enabled }]
23
+ * @returns {Object|null} controller with sendAction/kill
24
+ */
25
+ function initWinTray(options) {
26
+ const { iconPath, tooltip, items, onClick } = options;
27
+ clickHandler = onClick;
28
+
29
+ const scriptPath = path.join(__dirname, "tray.ps1");
30
+
31
+ try {
32
+ psProcess = spawn(
33
+ "powershell.exe",
34
+ [
35
+ "-NoProfile",
36
+ "-ExecutionPolicy", "Bypass",
37
+ "-WindowStyle", "Hidden",
38
+ "-InputFormat", "Text",
39
+ "-OutputFormat", "Text",
40
+ "-File", scriptPath,
41
+ "-IconPath", iconPath,
42
+ "-Tooltip", tooltip
43
+ ],
44
+ { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] }
45
+ );
46
+ } catch (err) {
47
+ return null;
48
+ }
49
+
50
+ const rl = readline.createInterface({ input: psProcess.stdout });
51
+ rl.on("line", (line) => {
52
+ try {
53
+ const evt = JSON.parse(line);
54
+ if (evt.type === "click" && clickHandler) {
55
+ clickHandler(evt.index);
56
+ }
57
+ } catch (e) {}
58
+ });
59
+
60
+ psProcess.on("error", () => {});
61
+ psProcess.stderr.on("data", () => {});
62
+
63
+ // Send initial menu items
64
+ items.forEach((item, index) => {
65
+ sendCommand({ action: "add-item", index, title: item.title, enabled: item.enabled });
66
+ });
67
+
68
+ return {
69
+ updateItem(index, title, enabled) {
70
+ sendCommand({ action: "update-item", index, title, enabled });
71
+ },
72
+ setTooltip(text) {
73
+ sendCommand({ action: "set-tooltip", text });
74
+ },
75
+ kill() {
76
+ try {
77
+ sendCommand({ action: "kill" });
78
+ } catch (e) {}
79
+ setTimeout(() => {
80
+ if (psProcess && !psProcess.killed) {
81
+ try { psProcess.kill(); } catch (e) {}
82
+ }
83
+ psProcess = null;
84
+ }, 300);
85
+ }
86
+ };
87
+ }
88
+
89
+ module.exports = { initWinTray };