@sifxprime/krouter 0.5.146 → 0.5.148

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 (245) hide show
  1. package/app/.next-cli-build/BUILD_ID +1 -1
  2. package/app/.next-cli-build/app-path-routes-manifest.json +10 -10
  3. package/app/.next-cli-build/build-manifest.json +2 -2
  4. package/app/.next-cli-build/prerender-manifest.json +19 -19
  5. package/app/.next-cli-build/server/app/(dashboard)/dashboard/basic-chat/page_client-reference-manifest.js +1 -1
  6. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/[toolId]/page_client-reference-manifest.js +1 -1
  7. package/app/.next-cli-build/server/app/(dashboard)/dashboard/cli-tools/page_client-reference-manifest.js +1 -1
  8. package/app/.next-cli-build/server/app/(dashboard)/dashboard/combos/page_client-reference-manifest.js +1 -1
  9. package/app/.next-cli-build/server/app/(dashboard)/dashboard/console-log/page_client-reference-manifest.js +1 -1
  10. package/app/.next-cli-build/server/app/(dashboard)/dashboard/endpoint/page_client-reference-manifest.js +1 -1
  11. package/app/.next-cli-build/server/app/(dashboard)/dashboard/environment/page_client-reference-manifest.js +1 -1
  12. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page.js +1 -1
  13. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/[id]/page_client-reference-manifest.js +1 -1
  14. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/[kind]/page_client-reference-manifest.js +1 -1
  15. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/combo/[id]/page_client-reference-manifest.js +1 -1
  16. package/app/.next-cli-build/server/app/(dashboard)/dashboard/media-providers/web/page_client-reference-manifest.js +1 -1
  17. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page.js +1 -1
  18. package/app/.next-cli-build/server/app/(dashboard)/dashboard/mitm/page_client-reference-manifest.js +1 -1
  19. package/app/.next-cli-build/server/app/(dashboard)/dashboard/page_client-reference-manifest.js +1 -1
  20. package/app/.next-cli-build/server/app/(dashboard)/dashboard/presidio/page_client-reference-manifest.js +1 -1
  21. package/app/.next-cli-build/server/app/(dashboard)/dashboard/profile/page_client-reference-manifest.js +1 -1
  22. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page.js +2 -2
  23. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/[id]/page_client-reference-manifest.js +1 -1
  24. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/new/page_client-reference-manifest.js +1 -1
  25. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page.js +1 -1
  26. package/app/.next-cli-build/server/app/(dashboard)/dashboard/providers/page_client-reference-manifest.js +1 -1
  27. package/app/.next-cli-build/server/app/(dashboard)/dashboard/proxy-pools/page_client-reference-manifest.js +1 -1
  28. package/app/.next-cli-build/server/app/(dashboard)/dashboard/pxpipe/page_client-reference-manifest.js +1 -1
  29. package/app/.next-cli-build/server/app/(dashboard)/dashboard/quota/page_client-reference-manifest.js +1 -1
  30. package/app/.next-cli-build/server/app/(dashboard)/dashboard/skills/page_client-reference-manifest.js +1 -1
  31. package/app/.next-cli-build/server/app/(dashboard)/dashboard/token-saver/page_client-reference-manifest.js +1 -1
  32. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page.js +1 -1
  33. package/app/.next-cli-build/server/app/(dashboard)/dashboard/translator/page_client-reference-manifest.js +1 -1
  34. package/app/.next-cli-build/server/app/(dashboard)/dashboard/usage/page_client-reference-manifest.js +1 -1
  35. package/app/.next-cli-build/server/app/_global-error/page_client-reference-manifest.js +1 -1
  36. package/app/.next-cli-build/server/app/_global-error.html +1 -1
  37. package/app/.next-cli-build/server/app/_global-error.rsc +1 -1
  38. package/app/.next-cli-build/server/app/_global-error.segments/_full.segment.rsc +1 -1
  39. package/app/.next-cli-build/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  40. package/app/.next-cli-build/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  41. package/app/.next-cli-build/server/app/_not-found/page_client-reference-manifest.js +1 -1
  42. package/app/.next-cli-build/server/app/_not-found.html +1 -1
  43. package/app/.next-cli-build/server/app/_not-found.rsc +4 -4
  44. package/app/.next-cli-build/server/app/_not-found.segments/_full.segment.rsc +4 -4
  45. package/app/.next-cli-build/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +4 -4
  46. package/app/.next-cli-build/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  47. package/app/.next-cli-build/server/app/api/cli-tools/all-statuses/route.js +1 -1
  48. package/app/.next-cli-build/server/app/api/cli-tools/kilo-settings/route.js +1 -1
  49. package/app/.next-cli-build/server/app/api/import/route.js +1 -1
  50. package/app/.next-cli-build/server/app/api/models/route.js +1 -1
  51. package/app/.next-cli-build/server/app/api/providers/route.js +1 -1
  52. package/app/.next-cli-build/server/app/api/providers/validate/route.js +1 -1
  53. package/app/.next-cli-build/server/app/api/pxpipe/health/route.js +2 -2
  54. package/app/.next-cli-build/server/app/api/pxpipe/install/route.js +2 -2
  55. package/app/.next-cli-build/server/app/api/pxpipe/restart/route.js +2 -2
  56. package/app/.next-cli-build/server/app/api/pxpipe/start/route.js +2 -2
  57. package/app/.next-cli-build/server/app/api/pxpipe/stats/route.js +2 -2
  58. package/app/.next-cli-build/server/app/api/pxpipe/status/route.js +2 -2
  59. package/app/.next-cli-build/server/app/api/pxpipe/stop/route.js +2 -2
  60. package/app/.next-cli-build/server/app/api/settings/environment/route.js +1 -1
  61. package/app/.next-cli-build/server/app/api/settings/presidio/route.js +1 -1
  62. package/app/.next-cli-build/server/app/api/translator/console-logs/route.js +1 -1
  63. package/app/.next-cli-build/server/app/api/translator/console-logs/stream/route.js +1 -1
  64. package/app/.next-cli-build/server/app/api/tunnel/enable/route.js +1 -1
  65. package/app/.next-cli-build/server/app/api/tunnel/tailscale-enable/route.js +1 -1
  66. package/app/.next-cli-build/server/app/api/version/route.js +1 -1
  67. package/app/.next-cli-build/server/app/api/version/shutdown/route.js +1 -1
  68. package/app/.next-cli-build/server/app/api/version/update/route.js +1 -1
  69. package/app/.next-cli-build/server/app/callback/page_client-reference-manifest.js +1 -1
  70. package/app/.next-cli-build/server/app/callback.html +1 -1
  71. package/app/.next-cli-build/server/app/callback.rsc +4 -4
  72. package/app/.next-cli-build/server/app/callback.segments/_full.segment.rsc +4 -4
  73. package/app/.next-cli-build/server/app/callback.segments/_tree.segment.rsc +2 -2
  74. package/app/.next-cli-build/server/app/callback.segments/callback/__PAGE__.segment.rsc +4 -4
  75. package/app/.next-cli-build/server/app/dashboard/basic-chat.html +1 -1
  76. package/app/.next-cli-build/server/app/dashboard/basic-chat.rsc +6 -6
  77. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/!KGRhc2hib2FyZCk/dashboard/basic-chat/__PAGE__.segment.rsc +6 -6
  78. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_full.segment.rsc +6 -6
  79. package/app/.next-cli-build/server/app/dashboard/basic-chat.segments/_tree.segment.rsc +2 -2
  80. package/app/.next-cli-build/server/app/dashboard/cli-tools.html +1 -1
  81. package/app/.next-cli-build/server/app/dashboard/cli-tools.rsc +6 -6
  82. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/!KGRhc2hib2FyZCk/dashboard/cli-tools/__PAGE__.segment.rsc +6 -6
  83. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_full.segment.rsc +6 -6
  84. package/app/.next-cli-build/server/app/dashboard/cli-tools.segments/_tree.segment.rsc +2 -2
  85. package/app/.next-cli-build/server/app/dashboard/combos.html +1 -1
  86. package/app/.next-cli-build/server/app/dashboard/combos.rsc +6 -6
  87. package/app/.next-cli-build/server/app/dashboard/combos.segments/!KGRhc2hib2FyZCk/dashboard/combos/__PAGE__.segment.rsc +6 -6
  88. package/app/.next-cli-build/server/app/dashboard/combos.segments/_full.segment.rsc +6 -6
  89. package/app/.next-cli-build/server/app/dashboard/combos.segments/_tree.segment.rsc +2 -2
  90. package/app/.next-cli-build/server/app/dashboard/endpoint.html +1 -1
  91. package/app/.next-cli-build/server/app/dashboard/endpoint.rsc +6 -6
  92. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/!KGRhc2hib2FyZCk/dashboard/endpoint/__PAGE__.segment.rsc +6 -6
  93. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_full.segment.rsc +6 -6
  94. package/app/.next-cli-build/server/app/dashboard/endpoint.segments/_tree.segment.rsc +2 -2
  95. package/app/.next-cli-build/server/app/dashboard/environment.html +1 -1
  96. package/app/.next-cli-build/server/app/dashboard/environment.rsc +6 -6
  97. package/app/.next-cli-build/server/app/dashboard/environment.segments/!KGRhc2hib2FyZCk/dashboard/environment/__PAGE__.segment.rsc +6 -6
  98. package/app/.next-cli-build/server/app/dashboard/environment.segments/_full.segment.rsc +6 -6
  99. package/app/.next-cli-build/server/app/dashboard/environment.segments/_tree.segment.rsc +2 -2
  100. package/app/.next-cli-build/server/app/dashboard/media-providers/web.html +1 -1
  101. package/app/.next-cli-build/server/app/dashboard/media-providers/web.rsc +6 -6
  102. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/!KGRhc2hib2FyZCk/dashboard/media-providers/web/__PAGE__.segment.rsc +6 -6
  103. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_full.segment.rsc +6 -6
  104. package/app/.next-cli-build/server/app/dashboard/media-providers/web.segments/_tree.segment.rsc +2 -2
  105. package/app/.next-cli-build/server/app/dashboard/mitm.html +1 -1
  106. package/app/.next-cli-build/server/app/dashboard/mitm.rsc +6 -6
  107. package/app/.next-cli-build/server/app/dashboard/mitm.segments/!KGRhc2hib2FyZCk/dashboard/mitm/__PAGE__.segment.rsc +6 -6
  108. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_full.segment.rsc +6 -6
  109. package/app/.next-cli-build/server/app/dashboard/mitm.segments/_tree.segment.rsc +2 -2
  110. package/app/.next-cli-build/server/app/dashboard/presidio.html +1 -1
  111. package/app/.next-cli-build/server/app/dashboard/presidio.rsc +6 -6
  112. package/app/.next-cli-build/server/app/dashboard/presidio.segments/!KGRhc2hib2FyZCk/dashboard/presidio/__PAGE__.segment.rsc +6 -6
  113. package/app/.next-cli-build/server/app/dashboard/presidio.segments/_full.segment.rsc +6 -6
  114. package/app/.next-cli-build/server/app/dashboard/presidio.segments/_tree.segment.rsc +2 -2
  115. package/app/.next-cli-build/server/app/dashboard/profile.html +1 -1
  116. package/app/.next-cli-build/server/app/dashboard/profile.rsc +6 -6
  117. package/app/.next-cli-build/server/app/dashboard/profile.segments/!KGRhc2hib2FyZCk/dashboard/profile/__PAGE__.segment.rsc +6 -6
  118. package/app/.next-cli-build/server/app/dashboard/profile.segments/_full.segment.rsc +6 -6
  119. package/app/.next-cli-build/server/app/dashboard/profile.segments/_tree.segment.rsc +2 -2
  120. package/app/.next-cli-build/server/app/dashboard/providers/new.html +1 -1
  121. package/app/.next-cli-build/server/app/dashboard/providers/new.rsc +6 -6
  122. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/!KGRhc2hib2FyZCk/dashboard/providers/new/__PAGE__.segment.rsc +6 -6
  123. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_full.segment.rsc +6 -6
  124. package/app/.next-cli-build/server/app/dashboard/providers/new.segments/_tree.segment.rsc +2 -2
  125. package/app/.next-cli-build/server/app/dashboard/providers.html +1 -1
  126. package/app/.next-cli-build/server/app/dashboard/providers.rsc +6 -6
  127. package/app/.next-cli-build/server/app/dashboard/providers.segments/!KGRhc2hib2FyZCk/dashboard/providers/__PAGE__.segment.rsc +6 -6
  128. package/app/.next-cli-build/server/app/dashboard/providers.segments/_full.segment.rsc +6 -6
  129. package/app/.next-cli-build/server/app/dashboard/providers.segments/_tree.segment.rsc +2 -2
  130. package/app/.next-cli-build/server/app/dashboard/proxy-pools.html +1 -1
  131. package/app/.next-cli-build/server/app/dashboard/proxy-pools.rsc +6 -6
  132. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/!KGRhc2hib2FyZCk/dashboard/proxy-pools/__PAGE__.segment.rsc +6 -6
  133. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_full.segment.rsc +6 -6
  134. package/app/.next-cli-build/server/app/dashboard/proxy-pools.segments/_tree.segment.rsc +2 -2
  135. package/app/.next-cli-build/server/app/dashboard/pxpipe.html +1 -1
  136. package/app/.next-cli-build/server/app/dashboard/pxpipe.rsc +6 -6
  137. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/!KGRhc2hib2FyZCk/dashboard/pxpipe/__PAGE__.segment.rsc +6 -6
  138. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_full.segment.rsc +6 -6
  139. package/app/.next-cli-build/server/app/dashboard/pxpipe.segments/_tree.segment.rsc +2 -2
  140. package/app/.next-cli-build/server/app/dashboard/quota.html +2 -2
  141. package/app/.next-cli-build/server/app/dashboard/quota.rsc +7 -7
  142. package/app/.next-cli-build/server/app/dashboard/quota.segments/!KGRhc2hib2FyZCk/dashboard/quota/__PAGE__.segment.rsc +7 -7
  143. package/app/.next-cli-build/server/app/dashboard/quota.segments/_full.segment.rsc +7 -7
  144. package/app/.next-cli-build/server/app/dashboard/quota.segments/_tree.segment.rsc +2 -2
  145. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page.js +1 -1
  146. package/app/.next-cli-build/server/app/dashboard/settings/pricing/page_client-reference-manifest.js +1 -1
  147. package/app/.next-cli-build/server/app/dashboard/settings/pricing.html +1 -1
  148. package/app/.next-cli-build/server/app/dashboard/settings/pricing.rsc +5 -5
  149. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_full.segment.rsc +5 -5
  150. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/_tree.segment.rsc +2 -2
  151. package/app/.next-cli-build/server/app/dashboard/settings/pricing.segments/dashboard/settings/pricing/__PAGE__.segment.rsc +5 -5
  152. package/app/.next-cli-build/server/app/dashboard/skills.html +1 -1
  153. package/app/.next-cli-build/server/app/dashboard/skills.rsc +6 -6
  154. package/app/.next-cli-build/server/app/dashboard/skills.segments/!KGRhc2hib2FyZCk/dashboard/skills/__PAGE__.segment.rsc +6 -6
  155. package/app/.next-cli-build/server/app/dashboard/skills.segments/_full.segment.rsc +6 -6
  156. package/app/.next-cli-build/server/app/dashboard/skills.segments/_tree.segment.rsc +2 -2
  157. package/app/.next-cli-build/server/app/dashboard/token-saver.html +1 -1
  158. package/app/.next-cli-build/server/app/dashboard/token-saver.rsc +6 -6
  159. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/!KGRhc2hib2FyZCk/dashboard/token-saver/__PAGE__.segment.rsc +6 -6
  160. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_full.segment.rsc +6 -6
  161. package/app/.next-cli-build/server/app/dashboard/token-saver.segments/_tree.segment.rsc +2 -2
  162. package/app/.next-cli-build/server/app/dashboard/translator.html +1 -1
  163. package/app/.next-cli-build/server/app/dashboard/translator.rsc +6 -6
  164. package/app/.next-cli-build/server/app/dashboard/translator.segments/!KGRhc2hib2FyZCk/dashboard/translator/__PAGE__.segment.rsc +6 -6
  165. package/app/.next-cli-build/server/app/dashboard/translator.segments/_full.segment.rsc +6 -6
  166. package/app/.next-cli-build/server/app/dashboard/translator.segments/_tree.segment.rsc +2 -2
  167. package/app/.next-cli-build/server/app/dashboard/usage.html +1 -1
  168. package/app/.next-cli-build/server/app/dashboard/usage.rsc +6 -6
  169. package/app/.next-cli-build/server/app/dashboard/usage.segments/!KGRhc2hib2FyZCk/dashboard/usage/__PAGE__.segment.rsc +6 -6
  170. package/app/.next-cli-build/server/app/dashboard/usage.segments/_full.segment.rsc +6 -6
  171. package/app/.next-cli-build/server/app/dashboard/usage.segments/_tree.segment.rsc +2 -2
  172. package/app/.next-cli-build/server/app/dashboard.html +1 -1
  173. package/app/.next-cli-build/server/app/dashboard.rsc +6 -6
  174. package/app/.next-cli-build/server/app/dashboard.segments/!KGRhc2hib2FyZCk/dashboard/__PAGE__.segment.rsc +6 -6
  175. package/app/.next-cli-build/server/app/dashboard.segments/_full.segment.rsc +6 -6
  176. package/app/.next-cli-build/server/app/dashboard.segments/_tree.segment.rsc +2 -2
  177. package/app/.next-cli-build/server/app/index.html +1 -1
  178. package/app/.next-cli-build/server/app/index.rsc +4 -4
  179. package/app/.next-cli-build/server/app/index.segments/__PAGE__.segment.rsc +4 -4
  180. package/app/.next-cli-build/server/app/index.segments/_full.segment.rsc +4 -4
  181. package/app/.next-cli-build/server/app/index.segments/_tree.segment.rsc +2 -2
  182. package/app/.next-cli-build/server/app/landing/page_client-reference-manifest.js +1 -1
  183. package/app/.next-cli-build/server/app/landing.html +1 -1
  184. package/app/.next-cli-build/server/app/landing.rsc +4 -4
  185. package/app/.next-cli-build/server/app/landing.segments/_full.segment.rsc +4 -4
  186. package/app/.next-cli-build/server/app/landing.segments/_tree.segment.rsc +2 -2
  187. package/app/.next-cli-build/server/app/landing.segments/landing/__PAGE__.segment.rsc +4 -4
  188. package/app/.next-cli-build/server/app/login/page.js +1 -1
  189. package/app/.next-cli-build/server/app/login/page_client-reference-manifest.js +1 -1
  190. package/app/.next-cli-build/server/app/login.html +1 -1
  191. package/app/.next-cli-build/server/app/login.rsc +5 -5
  192. package/app/.next-cli-build/server/app/login.segments/_full.segment.rsc +5 -5
  193. package/app/.next-cli-build/server/app/login.segments/_tree.segment.rsc +2 -2
  194. package/app/.next-cli-build/server/app/login.segments/login/__PAGE__.segment.rsc +5 -5
  195. package/app/.next-cli-build/server/app/page_client-reference-manifest.js +1 -1
  196. package/app/.next-cli-build/server/app-paths-manifest.json +10 -10
  197. package/app/.next-cli-build/server/chunks/192.js +9 -0
  198. package/app/.next-cli-build/server/chunks/2365.js +1 -1
  199. package/app/.next-cli-build/server/chunks/2722.js +1 -1
  200. package/app/.next-cli-build/server/chunks/412.js +2 -2
  201. package/app/.next-cli-build/server/chunks/4884.js +2 -2
  202. package/app/.next-cli-build/server/chunks/523.js +1 -0
  203. package/app/.next-cli-build/server/chunks/5718.js +1 -1
  204. package/app/.next-cli-build/server/chunks/6200.js +2 -2
  205. package/app/.next-cli-build/server/chunks/6298.js +1 -1
  206. package/app/.next-cli-build/server/chunks/706.js +4 -3
  207. package/app/.next-cli-build/server/chunks/7153.js +1 -1
  208. package/app/.next-cli-build/server/chunks/7276.js +1 -1
  209. package/app/.next-cli-build/server/chunks/7833.js +9 -0
  210. package/app/.next-cli-build/server/chunks/8238.js +1 -1
  211. package/app/.next-cli-build/server/chunks/8782.js +1 -0
  212. package/app/.next-cli-build/server/chunks/8895.js +1 -1
  213. package/app/.next-cli-build/server/middleware-build-manifest.js +1 -1
  214. package/app/.next-cli-build/server/middleware.js +2 -2
  215. package/app/.next-cli-build/server/pages/404.html +1 -1
  216. package/app/.next-cli-build/server/pages/500.html +1 -1
  217. package/app/.next-cli-build/static/chunks/{1321-6c49a954d60cdf8d.js → 1321-87af378bc3a6718a.js} +1 -1
  218. package/app/.next-cli-build/static/chunks/{3395-ee203e7ee50296be.js → 3395-be2d0ce6411ddbf0.js} +2 -2
  219. package/app/.next-cli-build/static/chunks/5497-d4a2fb8d25696366.js +7 -0
  220. package/app/.next-cli-build/static/chunks/{6069-dd3d88032deffd6b.js → 6069-db27e074bc47d5fe.js} +1 -1
  221. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/media-providers/[kind]/[id]/{page-783b478197298c31.js → page-1c13f46a5c077d38.js} +1 -1
  222. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-81f0e1ae55f87925.js +1 -0
  223. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/presidio/{page-d99bb3a54c3dbb50.js → page-99353b884e6df533.js} +1 -1
  224. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/[id]/{page-f52892e5e4b5f25b.js → page-b92667a32e2aeffa.js} +2 -2
  225. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/page-69f5c1cd75191fc4.js +1 -0
  226. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/translator/{page-97596f6b0ed5c791.js → page-719a6bedc7b221df.js} +1 -1
  227. package/app/.next-cli-build/static/chunks/app/dashboard/settings/pricing/page-625fde09367a7c35.js +1 -0
  228. package/app/.next-cli-build/static/chunks/app/login/page-fd5112b2e7b69783.js +1 -0
  229. package/app/.next-cli-build/static/css/{ec08ba27b16d57e9.css → 8e737cade791a545.css} +1 -1
  230. package/app/cli/package.json +1 -1
  231. package/app/package.json +1 -1
  232. package/app/src/lib/db/backup.js +35 -0
  233. package/cli.js +211 -106
  234. package/package.json +1 -1
  235. package/src/cli/tray/tray.ps1 +38 -14
  236. package/src/cli/utils/input.js +13 -1
  237. package/app/.next-cli-build/server/chunks/4055.js +0 -9
  238. package/app/.next-cli-build/server/chunks/5217.js +0 -9
  239. package/app/.next-cli-build/static/chunks/5497-df084be192db340d.js +0 -7
  240. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/mitm/page-6c89f0a1ddd99c41.js +0 -1
  241. package/app/.next-cli-build/static/chunks/app/(dashboard)/dashboard/providers/page-b1182e42595e08ba.js +0 -1
  242. package/app/.next-cli-build/static/chunks/app/dashboard/settings/pricing/page-045957f92dd4e66b.js +0 -1
  243. package/app/.next-cli-build/static/chunks/app/login/page-aaf3ff5ba99cdda7.js +0 -1
  244. /package/app/.next-cli-build/static/{alT51K3CdFyFBv27IY7wb → 9-AyxnJk9NDhO4WOXHEPp}/_buildManifest.js +0 -0
  245. /package/app/.next-cli-build/static/{alT51K3CdFyFBv27IY7wb → 9-AyxnJk9NDhO4WOXHEPp}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sifxprime/krouter",
3
- "version": "0.5.146",
3
+ "version": "0.5.148",
4
4
  "description": "kRouter (Kodelyth Router) CLI — Kodelyth AI Infrastructure",
5
5
  "homepage": "https://github.com/sifxprime/krouter",
6
6
  "repository": {
package/app/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "krouter-app",
3
- "version": "0.5.146",
3
+ "version": "0.5.148",
4
4
  "description": "kRouter (Kodelyth Router) web dashboard — Kodelyth AI Infrastructure",
5
5
  "private": true,
6
6
  "scripts": {
@@ -0,0 +1,35 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { BACKUPS_DIR, ensureDirs } from "./paths.js";
4
+ import { timestampSlug, getAppVersion } from "./version.js";
5
+
6
+ const KEEP_BACKUPS = 5;
7
+
8
+ export function makeBackupDir(label) {
9
+ ensureDirs();
10
+ const ver = getAppVersion();
11
+ const slug = `${label}-${ver}-${timestampSlug()}`;
12
+ const dir = path.join(BACKUPS_DIR, slug);
13
+ fs.mkdirSync(dir, { recursive: true });
14
+ return dir;
15
+ }
16
+
17
+ export function backupFile(srcPath, destDir, destName = null) {
18
+ if (!fs.existsSync(srcPath)) return null;
19
+ const name = destName || path.basename(srcPath);
20
+ const dest = path.join(destDir, name);
21
+ fs.copyFileSync(srcPath, dest);
22
+ return dest;
23
+ }
24
+
25
+ export function pruneOldBackups() {
26
+ if (!fs.existsSync(BACKUPS_DIR)) return;
27
+ const entries = fs.readdirSync(BACKUPS_DIR, { withFileTypes: true })
28
+ .filter((e) => e.isDirectory())
29
+ .map((e) => ({ name: e.name, full: path.join(BACKUPS_DIR, e.name), mtime: fs.statSync(path.join(BACKUPS_DIR, e.name)).mtimeMs }))
30
+ .sort((a, b) => b.mtime - a.mtime);
31
+
32
+ for (const old of entries.slice(KEEP_BACKUPS)) {
33
+ try { fs.rmSync(old.full, { recursive: true, force: true }); } catch {}
34
+ }
35
+ }
package/cli.js CHANGED
@@ -50,10 +50,24 @@ const args = process.argv.slice(2);
50
50
  // Self-heal SQLite runtime deps (sql.js + better-sqlite3) into ~/.krouter/runtime
51
51
  // so the server can resolve them via NODE_PATH. Best-effort — sql.js is required,
52
52
  // better-sqlite3 is optional. Logs to stderr only on failure.
53
- try { ensureSqliteRuntime({ silent: true }); } catch {}
54
-
55
- // Self-heal tray runtime (systray for macOS/Linux only). Windows skipped.
56
- try { ensureTrayRuntime({ silent: true }); } catch {}
53
+ //
54
+ // This runs before the argument parser, so `--version` and `--help` used to pay for
55
+ // it too: on a machine where the runtime is missing it shells out to a blocking
56
+ // `npm install` whose spawnSync timeout is 180s, printing nothing the whole time.
57
+ // Asking a program its version should never reach the network.
58
+ //
59
+ // KROUTER_SKIP_RUNTIME_HEAL=1 opts out entirely, for an air-gapped or CI machine where
60
+ // reaching npm is either impossible or unwanted. The server still starts; it just uses
61
+ // whatever runtime is already present instead of trying to repair it.
62
+ const RUNTIME_FREE_ARGS = new Set(["--version", "-v", "--help", "-h"]);
63
+ const skipRuntimeHeal =
64
+ process.env.KROUTER_SKIP_RUNTIME_HEAL === "1" ||
65
+ process.env.KROUTER_SKIP_RUNTIME_HEAL === "true";
66
+ if (!skipRuntimeHeal && !args.some((a) => RUNTIME_FREE_ARGS.has(a))) {
67
+ try { ensureSqliteRuntime({ silent: true }); } catch {}
68
+ // Self-heal tray runtime (systray for macOS/Linux only). Windows skipped.
69
+ try { ensureTrayRuntime({ silent: true }); } catch {}
70
+ }
57
71
 
58
72
  // Sweep autostart entries whose binary path no longer exists on disk (e.g. the
59
73
  // user uninstalled the global kRouter then reinstalled to a different path).
@@ -79,57 +93,14 @@ const PROCESS_IDENTIFIERS = ['krouter'];
79
93
  // fixed in 0.5.51. Safe to re-run — only touches rows that actually
80
94
  // have something to lift.
81
95
  if (args[0] === "backfill-tokens") {
82
- const candidates = [
83
- path.join(process.env.HOME || "", ".krouter", "db", "data.sqlite"),
84
- process.env.APPDATA ? path.join(process.env.APPDATA, "krouter", "db", "data.sqlite") : null,
85
- ].filter(Boolean);
86
- const dbPath = candidates.find(p => fs.existsSync(p));
87
- if (!dbPath) {
88
- console.error("No krouter database found at:", candidates.join(" or "));
89
- process.exit(1);
90
- }
91
- console.log("DB:", dbPath);
92
- const rows = JSON.parse(execSync(
93
- `sqlite3 -json "${dbPath}" "SELECT id, data FROM requestDetails WHERE json_extract(data,'$.tokens.prompt_tokens')=0 AND (json_extract(data,'$.providerResponse.response.usageMetadata.promptTokenCount') IS NOT NULL OR json_extract(data,'$.providerResponse.usageMetadata.promptTokenCount') IS NOT NULL)"`,
94
- { encoding: "utf8", maxBuffer: 512 * 1024 * 1024 }
95
- ) || "[]");
96
- console.log(`Candidates with extractable tokens: ${rows.length}`);
97
- let updated = 0;
98
- // 0.5.53 — stream UPDATEs through stdin so SQLite parses each statement
99
- // itself. Avoids the JSON-in-shell-quoted-SQL mangling that swallowed
100
- // every row silently on the first attempt.
101
- const tmpScript = path.join(os.tmpdir(), `krouter-backfill-${Date.now()}.sql`);
102
- const sqlLines = ["BEGIN;"];
103
- for (const row of rows) {
104
- try {
105
- const d = JSON.parse(row.data);
106
- const um = d.providerResponse?.response?.usageMetadata || d.providerResponse?.usageMetadata;
107
- if (!um) continue;
108
- const promptTokens = um.promptTokenCount || 0;
109
- const completionTokens = um.candidatesTokenCount || 0;
110
- const reasoningTokens = um.thoughtsTokenCount;
111
- if (promptTokens === 0 && completionTokens === 0) continue;
112
- d.tokens = { ...(d.tokens || {}), prompt_tokens: promptTokens, completion_tokens: completionTokens };
113
- if (reasoningTokens !== undefined) d.tokens.reasoning_tokens = reasoningTokens;
114
- const escapedData = JSON.stringify(d).replace(/'/g, "''");
115
- const escapedId = String(row.id).replace(/'/g, "''");
116
- sqlLines.push(`UPDATE requestDetails SET data='${escapedData}' WHERE id='${escapedId}';`);
117
- updated++;
118
- } catch (e) {
119
- console.error(` row ${row.id} skipped: ${e.message}`);
120
- }
121
- }
122
- sqlLines.push("COMMIT;");
123
- fs.writeFileSync(tmpScript, sqlLines.join("\n"));
124
- try {
125
- execSync(`sqlite3 "${dbPath}" < "${tmpScript}"`, { stdio: ["ignore", "pipe", "pipe"] });
126
- console.log(`Backfilled ${updated} rows. Usage page totals will now reflect real token spend.`);
127
- } catch (e) {
128
- console.error(`Failed to apply: ${e.message?.split("\n")?.[0] || e}`);
129
- console.error(`SQL script left at ${tmpScript} for inspection.`);
130
- process.exit(2);
131
- }
132
- try { fs.unlinkSync(tmpScript); } catch { /* ignore */ }
96
+ // Kept so any script that calls it keeps working, but it no longer does the work
97
+ // itself. It used to shell out to the `sqlite3` CLI, which is not present on a
98
+ // stock Windows install, so it exited with a raw Node stack there. The same
99
+ // backfill now runs unconditionally at every server start via
100
+ // autoBackfillTokensIfNeeded() in src/shared/services/initializeApp.js, in pure JS
101
+ // through the app's own DB adapter — no external binary, no shell quoting.
102
+ console.log("Token backfill now runs automatically every time kRouter starts.");
103
+ console.log("Nothing to do here — start kRouter normally and it will be applied.");
133
104
  process.exit(0);
134
105
  }
135
106
 
@@ -141,23 +112,49 @@ let skipUpdate = false;
141
112
  let showLog = false;
142
113
  let trayMode = false;
143
114
 
115
+ // `--flag=value` is the other half of the convention people expect; it used to fall
116
+ // through every branch and be dropped in silence, so `--port=3000` started the server
117
+ // on the default port instead.
118
+ function splitInlineValue(arg) {
119
+ const eq = arg.indexOf("=");
120
+ if (!arg.startsWith("-") || eq < 0) return null;
121
+ return { flag: arg.slice(0, eq), value: arg.slice(eq + 1) };
122
+ }
123
+
144
124
  for (let i = 0; i < args.length; i++) {
145
- if (args[i] === "--port" || args[i] === "-p") {
146
- port = parseInt(args[i + 1], 10) || DEFAULT_PORT;
147
- i++;
148
- } else if (args[i] === "--host" || args[i] === "-H") {
149
- host = args[i + 1] || DEFAULT_HOST;
150
- i++;
151
- } else if (args[i] === "--no-browser" || args[i] === "-n") {
125
+ const inline = splitInlineValue(args[i]);
126
+ const arg = inline ? inline.flag : args[i];
127
+ // Reading a value consumes the next argv entry only when it was not inlined.
128
+ const takeValue = () => (inline ? inline.value : args[++i]);
129
+
130
+ if (arg === "--port" || arg === "-p") {
131
+ const raw = takeValue();
132
+ // parseInt used to accept "3000abc" as 3000 and turn a typo, an empty value or a
133
+ // missing one into DEFAULT_PORT — which is then force-freed by killProcessOnPort.
134
+ // Silently starting on a different port than asked is worse than refusing.
135
+ const parsed = Number(raw);
136
+ if (raw === undefined || raw === "" || !Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
137
+ console.error(`Invalid --port value: ${raw === undefined || raw === "" ? "(missing)" : raw}. Expected an integer between 1 and 65535.`);
138
+ process.exit(2);
139
+ }
140
+ port = parsed;
141
+ } else if (arg === "--host" || arg === "-H") {
142
+ const raw = takeValue();
143
+ if (!raw) {
144
+ console.error("Invalid --host value: (missing). Expected a hostname or IP, e.g. 127.0.0.1.");
145
+ process.exit(2);
146
+ }
147
+ host = raw;
148
+ } else if (arg === "--no-browser" || arg === "-n") {
152
149
  noBrowser = true;
153
- } else if (args[i] === "--log" || args[i] === "-l") {
150
+ } else if (arg === "--log" || arg === "-l") {
154
151
  showLog = true;
155
- } else if (args[i] === "--skip-update") {
152
+ } else if (arg === "--skip-update") {
156
153
  skipUpdate = true;
157
- } else if (args[i] === "--tray" || args[i] === "-t") {
154
+ } else if (arg === "--tray" || arg === "-t") {
158
155
  trayMode = true;
159
156
  process.env.TRAY_MODE = "1";
160
- } else if (args[i] === "--help" || args[i] === "-h") {
157
+ } else if (arg === "--help" || arg === "-h") {
161
158
  console.log(`
162
159
  Usage: ${APP_NAME} [options]
163
160
 
@@ -172,9 +169,16 @@ Options:
172
169
  -v, --version Show version
173
170
  `);
174
171
  process.exit(0);
175
- } else if (args[i] === "--version" || args[i] === "-v") {
172
+ } else if (arg === "--version" || arg === "-v") {
176
173
  console.log(pkg.version);
177
174
  process.exit(0);
175
+ } else {
176
+ // No terminal branch existed, so anything unrecognised was dropped without a
177
+ // word: `krouter --prot 3000` or `krouter start` ran on the default port and
178
+ // looked like it had worked.
179
+ console.error(`Unknown option: ${args[i]}`);
180
+ console.error(`Run \`${APP_NAME} --help\` to see the available options.`);
181
+ process.exit(2);
178
182
  }
179
183
  }
180
184
 
@@ -278,58 +282,92 @@ function killAllAppProcesses(appPort) {
278
282
  if (platform === "win32") {
279
283
  // Windows: use WMI to get full CommandLine (tasklist /V doesn't include it)
280
284
  try {
281
- const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"node.exe\\"' | Select-Object ProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
285
+ // Same ancestry rule as the POSIX branch below: a bare "next-server" match
286
+ // would take down every Next server on the machine, our own being
287
+ // indistinguishable from anyone else's by command line.
288
+ const psCmd = `powershell -NonInteractive -WindowStyle Hidden -Command "Get-WmiObject Win32_Process -Filter 'Name=\\"node.exe\\"' | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Csv -NoTypeInformation"`;
282
289
  const output = execSync(psCmd, {
283
290
  encoding: "utf8",
284
291
  windowsHide: true,
285
292
  timeout: 5000
286
293
  });
287
- const lines = output.split("\n").slice(1).filter(l => l.trim());
288
- lines.forEach(line => {
289
- // Whitelist: real node process running krouter cli.js, or next-server.
290
- // Avoids killing editors/grep/strace/cursor that just incidentally match the name.
291
- const cmd = line.toLowerCase();
292
- const hasAppName = cmd.includes("krouter");
293
- const hasAppPath = cmd.includes("cli.js") || cmd.includes("\\krouter") || cmd.includes("/krouter");
294
- const isAppProcess =
295
- (cmd.includes("node") && hasAppName && hasAppPath)
296
- || cmd.includes("next-server");
297
- if (isAppProcess) {
298
- const match = line.match(/^"(\d+)"/);
299
- if (match && match[1] && match[1] !== process.pid.toString()) {
300
- pids.push(match[1]);
301
- }
294
+ const rows = output.split("\n").slice(1).filter(l => l.trim()).map(line => {
295
+ const m = line.match(/^"(\d+)","(\d+)",(.*)$/);
296
+ return m ? { pid: m[1], ppid: m[2], cmd: (m[3] || "").toLowerCase() } : null;
297
+ }).filter(Boolean);
298
+
299
+ // Same rule as the POSIX branch: the invoked script, not any mention of it.
300
+ const isCliInvocation = (cmd) =>
301
+ /(^|[\s"'])[^\s"']*[\/\\]krouter[\/\\]cli\.js(\s|$|["'])/i.test(cmd) ||
302
+ /(^|[\s"'])[^\s"']*[\/\\]\.bin[\/\\]krouter(\s|$|["'])/i.test(cmd);
303
+ const roots = new Set(rows.filter(r => isCliInvocation(r.cmd)).map(r => r.pid));
304
+ const byParent = new Map();
305
+ for (const r of rows) {
306
+ if (!byParent.has(r.ppid)) byParent.set(r.ppid, []);
307
+ byParent.get(r.ppid).push(r.pid);
308
+ }
309
+ const doomed = new Set(roots);
310
+ const queue = [...roots];
311
+ while (queue.length) {
312
+ for (const child of byParent.get(queue.shift()) || []) {
313
+ if (!doomed.has(child)) { doomed.add(child); queue.push(child); }
302
314
  }
303
- });
315
+ }
316
+ for (const pid of doomed) {
317
+ if (pid !== process.pid.toString()) pids.push(pid);
318
+ }
304
319
  } catch (e) {
305
320
  // No processes found or error - continue
306
321
  }
307
322
  } else {
308
- // macOS/Linux: use ps to find all matching processes
323
+ // macOS/Linux. Identify our own processes by ancestry, never by name.
324
+ //
325
+ // Next renames its server process to a bare "next-server (v16.3.1)" -- no path,
326
+ // no project, nothing tying it to an app. Matching that string killed every
327
+ // Next server on the machine, so starting kRouter SIGKILLed a developer's
328
+ // unrelated dev server. The whitelist above it could not help: our own server
329
+ // matches by that string and nothing else, so the two are indistinguishable
330
+ // from the command line alone. Ancestry is the only thing that separates them.
309
331
  try {
310
- const output = execSync('ps aux 2>/dev/null', {
332
+ const output = execSync('ps -Ao pid,ppid,command 2>/dev/null', {
311
333
  encoding: 'utf8',
312
334
  timeout: 5000
313
335
  });
314
- const lines = output.split('\n');
315
-
316
- lines.forEach(line => {
317
- // Whitelist: real node process running krouter cli.js, or next-server.
318
- // Avoids killing grep/strace/editors/cursor that incidentally match the name.
319
- const cmd = line.toLowerCase();
320
- const hasAppName = cmd.includes("krouter");
321
- const hasAppPath = cmd.includes("cli.js") || cmd.includes("/krouter");
322
- const isAppProcess =
323
- (cmd.includes("node") && hasAppName && hasAppPath)
324
- || cmd.includes("next-server");
325
- if (isAppProcess) {
326
- const parts = line.trim().split(/\s+/);
327
- const pid = parts[1];
328
- if (pid && !isNaN(pid) && pid !== process.pid.toString()) {
329
- pids.push(pid);
330
- }
336
+ const rows = output.split('\n').slice(1)
337
+ .map(l => l.trim().match(/^(\d+)\s+(\d+)\s+(.*)$/))
338
+ .filter(Boolean)
339
+ .map(m => ({ pid: m[1], ppid: m[2], cmd: m[3].toLowerCase() }));
340
+
341
+ // Roots: node processes whose *invoked script* is this CLI. Testing for
342
+ // "krouter" anywhere in the command line would promote any process that
343
+ // merely mentions the app -- a grep, an editor, a script taking the path as
344
+ // an argument -- into a root, and every descendant of a root is killed.
345
+ // Match the argv[1] path instead.
346
+ const isCliInvocation = (cmd) =>
347
+ /(^|[\s"'])[^\s"']*[\/\\]krouter[\/\\]cli\.js(\s|$|["'])/i.test(cmd) ||
348
+ /(^|[\s"'])[^\s"']*[\/\\]\.bin[\/\\]krouter(\s|$|["'])/i.test(cmd);
349
+ const roots = new Set(
350
+ rows.filter(r => r.cmd.includes("node") && isCliInvocation(r.cmd)).map(r => r.pid)
351
+ );
352
+
353
+ // Everything descended from a root, however deep. Next spawns its server as
354
+ // a child, so this reaches it without ever matching on "next-server".
355
+ const byParent = new Map();
356
+ for (const r of rows) {
357
+ if (!byParent.has(r.ppid)) byParent.set(r.ppid, []);
358
+ byParent.get(r.ppid).push(r.pid);
359
+ }
360
+ const doomed = new Set(roots);
361
+ const queue = [...roots];
362
+ while (queue.length) {
363
+ for (const child of byParent.get(queue.shift()) || []) {
364
+ if (!doomed.has(child)) { doomed.add(child); queue.push(child); }
331
365
  }
332
- });
366
+ }
367
+
368
+ for (const pid of doomed) {
369
+ if (pid !== process.pid.toString()) pids.push(pid);
370
+ }
333
371
  } catch (e) {
334
372
  // No processes found or error - continue
335
373
  }
@@ -408,6 +446,42 @@ function killProxyByPidFile() {
408
446
  } catch { }
409
447
  }
410
448
 
449
+ // Is this PID one of our own server processes?
450
+ //
451
+ // killProcessOnPort used to kill-9 whatever `lsof -ti:PORT` returned, with no check on
452
+ // what it was. `krouter --port 3000` destroyed the user's own app on 3000 and
453
+ // `--port 5432` took out their Postgres, silently and before anything was printed.
454
+ //
455
+ // An orphaned kRouter server is the hard case: its parent CLI is gone, so ancestry
456
+ // cannot reach it, and Next has renamed it to a bare "next-server (vX)", so the command
457
+ // line says nothing either. spawnServer pins cwd to standaloneDir, and that survives
458
+ // both — it is the one durable marker of "this install's server".
459
+ function isOwnServerPid(pid) {
460
+ try {
461
+ const mine = fs.realpathSync(standaloneDir);
462
+ if (process.platform === "linux") {
463
+ return fs.realpathSync(`/proc/${pid}/cwd`) === mine;
464
+ }
465
+ if (process.platform === "darwin") {
466
+ const out = execSync(`lsof -a -p ${pid} -d cwd -Fn 2>/dev/null`, {
467
+ encoding: "utf8", timeout: 3000, stdio: ["pipe", "pipe", "ignore"],
468
+ });
469
+ const line = out.split("\n").find((l) => l.startsWith("n"));
470
+ return !!line && fs.realpathSync(line.slice(1).trim()) === mine;
471
+ }
472
+ if (process.platform === "win32") {
473
+ // No cheap cwd read on Windows. Fall back to the executable path, which for our
474
+ // server points inside the package directory.
475
+ const out = execSync(
476
+ `powershell -NonInteractive -WindowStyle Hidden -Command "(Get-Process -Id ${pid} -ErrorAction SilentlyContinue).Path"`,
477
+ { encoding: "utf8", windowsHide: true, timeout: 4000 }
478
+ ).trim();
479
+ return !!out && out.toLowerCase().includes("krouter");
480
+ }
481
+ } catch { /* process gone, or no permission to inspect it — treat as not ours */ }
482
+ return false;
483
+ }
484
+
411
485
  // Kill ALL processes listening on the given port. Returns true if any were killed.
412
486
  // Previous version: on Windows only killed the first PID from netstat, missing
413
487
  // parent/child pairs (next-server has a watcher + worker). Now sweeps all PIDs.
@@ -417,6 +491,7 @@ function killProcessOnPort(port) {
417
491
  try {
418
492
  const platform = process.platform;
419
493
  const pidsToKill = new Set();
494
+ const foreign = [];
420
495
 
421
496
  if (platform === "win32") {
422
497
  try {
@@ -428,7 +503,9 @@ function killProcessOnPort(port) {
428
503
  }).trim();
429
504
  output.split('\n').filter(l => l.includes('LISTENING')).forEach(line => {
430
505
  const pid = line.trim().split(/\s+/).pop();
431
- if (pid && /^\d+$/.test(pid) && pid !== String(process.pid)) pidsToKill.add(pid);
506
+ if (!pid || !/^\d+$/.test(pid) || pid === String(process.pid)) return;
507
+ if (isOwnServerPid(pid)) pidsToKill.add(pid);
508
+ else foreign.push(pid);
432
509
  });
433
510
  for (const pid of pidsToKill) {
434
511
  try {
@@ -447,7 +524,11 @@ function killProcessOnPort(port) {
447
524
  stdio: ['pipe', 'pipe', 'ignore']
448
525
  }).trim();
449
526
  pidOutput.split('\n').filter(Boolean).forEach(pid => {
450
- if (pid !== String(process.pid)) pidsToKill.add(pid);
527
+ if (pid === String(process.pid)) return;
528
+ // Only ever kill our own server. Anything else holding the port is the
529
+ // user's — say so and let them choose the port, rather than killing it.
530
+ if (isOwnServerPid(pid)) pidsToKill.add(pid);
531
+ else foreign.push(pid);
451
532
  });
452
533
  for (const pid of pidsToKill) {
453
534
  try {
@@ -460,6 +541,26 @@ function killProcessOnPort(port) {
460
541
  }
461
542
  }
462
543
 
544
+ // Something that is not ours is holding the port. Say so and name it, instead
545
+ // of failing to start with no explanation -- the caller only learns "port busy".
546
+ if (foreign.length) {
547
+ const described = foreign.map((pid) => {
548
+ try {
549
+ const name = platform === "win32"
550
+ ? execSync(`powershell -NonInteractive -WindowStyle Hidden -Command "(Get-Process -Id ${pid} -ErrorAction SilentlyContinue).ProcessName"`,
551
+ { encoding: "utf8", windowsHide: true, timeout: 4000 }).trim()
552
+ : execSync(`ps -p ${pid} -o comm= 2>/dev/null`, { encoding: "utf8", timeout: 3000 }).trim();
553
+ return name ? `${name} (pid ${pid})` : `pid ${pid}`;
554
+ } catch { return `pid ${pid}`; }
555
+ });
556
+ console.error(`\n⚠️ Port ${port} is held by ${described.join(", ")} — not kRouter.`);
557
+ console.error(` Refusing to kill it. Start kRouter on another port, e.g. --port ${port + 1}.\n`);
558
+ // Exit rather than fall through: we deliberately did not free the port, so
559
+ // every subsequent bind attempt fails. The retry path treats EADDRINUSE as
560
+ // transient and would spin here forever.
561
+ process.exit(1);
562
+ }
563
+
463
564
  // Wait for kernel to release the socket (Windows is slow here, give it 1s).
464
565
  // Then verify the port is actually free — if not, surface the result so
465
566
  // the caller can decide whether to retry or fail-fast.
@@ -648,6 +749,10 @@ function startServer(latestVersion) {
648
749
  const lanIp = getLanIp();
649
750
  if (lanIp) {
650
751
  console.log(`\x1b[33m⚠ Network-exposed: reachable at http://${lanIp}:${port} (bound 0.0.0.0). Use --host 127.0.0.1 for local-only.\x1b[0m`);
752
+ // Remote callers already need an API key for /v1/* and a login for the
753
+ // dashboard, so the exposure is bounded. Say so, rather than leaving the
754
+ // reader to guess whether their provider quota is reachable.
755
+ console.log(`\x1b[33m Remote callers still need an API key for /v1/* and a login for the dashboard.\x1b[0m`);
651
756
  }
652
757
  }
653
758
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sifxprime/krouter",
3
- "version": "0.5.146",
3
+ "version": "0.5.148",
4
4
  "description": "kRouter (Kodelyth Router) CLI — Kodelyth AI Infrastructure",
5
5
  "homepage": "https://github.com/sifxprime/krouter",
6
6
  "repository": {
@@ -48,26 +48,50 @@ function Set-Tooltip($text) {
48
48
  $script:notifyIcon.Text = $text
49
49
  }
50
50
 
51
- # Background reader thread polls stdin via timer on UI thread
51
+ # stdin is polled from a System.Windows.Forms.Timer, whose Tick runs on the very
52
+ # thread Application::Run() pumps. The previous loop guarded on [Console]::In.Peek(),
53
+ # which does not return -1 on an open-but-idle pipe -- it blocks until the next byte
54
+ # arrives. So the first tick after the startup burst never returned, the message pump
55
+ # stopped, and the tray icon appeared but ignored every click: no menu, no Quit.
56
+ #
57
+ # [Console]::In is a SyncTextReader whose ReadLineAsync() is synchronous too, so it
58
+ # cannot be used either. Read the raw handle through our own StreamReader and poll a
59
+ # genuinely async task, so the Tick handler always returns immediately.
60
+ $script:stdin = New-Object System.IO.StreamReader([Console]::OpenStandardInput(), [System.Text.Encoding]::UTF8)
61
+ $script:pending = $null
62
+
52
63
  $script:timer = New-Object System.Windows.Forms.Timer
53
64
  $script:timer.Interval = 100
54
65
  $script:timer.Add_Tick({
55
66
  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()
67
+ if ($null -eq $script:pending) { $script:pending = $script:stdin.ReadLineAsync() }
68
+ while ($script:pending.IsCompleted) {
69
+ $line = $script:pending.Result
70
+ $script:pending = $null
71
+ if ($null -eq $line) {
72
+ # EOF: the Node parent is gone. Exit instead of lingering as a dead icon the
73
+ # user can only clear through Task Manager.
74
+ $script:notifyIcon.Visible = $false
75
+ $script:notifyIcon.Dispose()
76
+ [System.Windows.Forms.Application]::Exit()
77
+ return
78
+ }
79
+ if (-not [string]::IsNullOrWhiteSpace($line)) {
80
+ $cmd = $line | ConvertFrom-Json
81
+ switch ($cmd.action) {
82
+ "add-item" { Add-MenuItem $cmd.index $cmd.title $cmd.enabled }
83
+ "update-item" { Update-MenuItem $cmd.index $cmd.title $cmd.enabled }
84
+ "set-tooltip" { Set-Tooltip $cmd.text }
85
+ "ready" { Write-Event @{ type = "ready" } }
86
+ "kill" {
87
+ $script:notifyIcon.Visible = $false
88
+ $script:notifyIcon.Dispose()
89
+ [System.Windows.Forms.Application]::Exit()
90
+ return
91
+ }
69
92
  }
70
93
  }
94
+ $script:pending = $script:stdin.ReadLineAsync()
71
95
  }
72
96
  } catch {
73
97
  Write-Event @{ type = "error"; message = $_.Exception.Message }
@@ -157,7 +157,19 @@ async function selectMenu(title, items, defaultIndex = 0, subtitle = "", headerC
157
157
  if (key.name === "down") return move(1);
158
158
  if (key.name === "return") { cleanup(); resolve(selectedIndex); return; }
159
159
  if (key.name === "escape") { cleanup(); resolve(-1); return; }
160
- if (key.ctrl && key.name === "c") { cleanup(); process.exit(0); }
160
+ if (key.ctrl && key.name === "c") {
161
+ cleanup();
162
+ // Raw mode clears termios ISIG, so Ctrl-C arrives here as an ordinary
163
+ // keypress rather than as SIGINT. Exiting straight from here skipped
164
+ // cli.js's SIGINT handler -- the only thing that kills the detached server
165
+ // child, the privileged MITM process and any tunnel -- so quitting from the
166
+ // menu left all three running with no UI left to stop them. Restore cooked
167
+ // mode and re-raise the signal so that handler actually runs.
168
+ try { process.stdin.setRawMode(false); } catch {}
169
+ rawPrimed = false;
170
+ process.kill(process.pid, "SIGINT");
171
+ return;
172
+ }
161
173
  };
162
174
 
163
175
  process.stdin.on("keypress", onKeypress);
@@ -1,9 +0,0 @@
1
- "use strict";exports.id=4055,exports.ids=[4055],exports.modules={4055:(a,b,c)=>{c.d(b,{runMigrationOnce:()=>w});var d=c(73024),e=c.n(d),f=c(76760),g=c.n(f),h=c(7841),i=c(76040);let j=[{version:1,name:"initial",up(a){for(let[b,c]of Object.entries(i.CG))for(let d of(a.exec((0,i.zE)(b,c)),c.indexes||[]))a.exec(d)}}].sort((a,b)=>a.version-b.version);var k=c(91117);let l=null;function m(){if(l)return l;try{let a=g().join(process.cwd(),"package.json");l=JSON.parse(e().readFileSync(a,"utf-8")).version||"0.0.0"}catch{l="0.0.0"}return l}function n(a){(0,h.Jh)();let b=m(),c=`${a}-${b}-${function(a=new Date){let b=a=>String(a).padStart(2,"0");return`${a.getFullYear()}${b(a.getMonth()+1)}${b(a.getDate())}-${b(a.getHours())}${b(a.getMinutes())}${b(a.getSeconds())}`}()}`,d=g().join(h.KQ,c);return e().mkdirSync(d,{recursive:!0}),d}function o(a,b,c=null){if(!e().existsSync(a))return null;let d=c||g().basename(a),f=g().join(b,d);return e().copyFileSync(a,f),f}function p(){if(e().existsSync(h.KQ))for(let a of e().readdirSync(h.KQ,{withFileTypes:!0}).filter(a=>a.isDirectory()).map(a=>({name:a.name,full:g().join(h.KQ,a.name),mtime:e().statSync(g().join(h.KQ,a.name)).mtimeMs})).sort((a,b)=>b.mtime-a.mtime).slice(5))try{e().rmSync(a.full,{recursive:!0,force:!0})}catch{}}var q=c(33323);let r=g().join(h.HG,".migrated-from-json"),s=new WeakSet;class t extends Error{constructor(a,b){super(a),this.name="MigrationAborted",this.droppedRows=b}}function u(a,b,c,d,e){let f=[];for(let a of c)try{d(a)}catch(b){f.push({...e(a),reason:b.message})}let g=a.get(`SELECT COUNT(*) as c FROM ${b}`)?.c??0;if(g!==c.length)throw console.warn(`[DB][migrate] ${b} row-count mismatch: expected ${c.length}, got ${g}. Dropped:`,f),new t(`${b} row-count mismatch: expected ${c.length}, got ${g}`,f)}function v(a){if(!e().existsSync(a))return null;try{return JSON.parse(e().readFileSync(a,"utf-8"))}catch{return null}}async function w(a){if(s.has(a))return;s.add(a);let b=function(a){try{let b=a.get("SELECT COUNT(*) as c FROM _meta");return!b||0===b.c}catch{return!0}}(a),c=function(a){a.exec((0,i.zE)("_meta",i.CG._meta));let b=parseInt((0,k.dy)(a,"schemaVersion","0"),10)||0;if(b>=(j.length?j[j.length-1].version:0))return{applied:0,from:b,to:b};let c=j.filter(a=>a.version>b),d=b;for(let b of c)a.transaction(()=>{b.up(a),(0,k.np)(a,"schemaVersion",b.version)}),d=b.version,console.log(`[DB][migrate] applied #${b.version} ${b.name}`);return{applied:c.length,from:b,to:d}}(a);for(let[b,c]of Object.entries(i.CG)){a.exec((0,i.zE)(b,c));let d=new Set(a.all(`PRAGMA table_info(${b})`).map(a=>a.name));for(let[e,f]of Object.entries(c.columns))if(!d.has(e)){let c=f.replace(/PRIMARY KEY( AUTOINCREMENT)?/i,"").replace(/UNIQUE/i,"").trim();try{a.exec(`ALTER TABLE ${b} ADD COLUMN ${e} ${c}`),console.log(`[DB][sync] +column ${b}.${e}`)}catch(a){console.warn(`[DB][sync] add column ${b}.${e} failed: ${a.message}`)}}for(let b of c.indexes||[])try{a.exec(b)}catch{}}let d=e().existsSync(r),f=v(h.Or.main),g=v(h.Or.usage),l=v(h.Or.disabled),w=v(h.Or.details);if(b&&(f||g||l||w)&&!d){let b=Date.now(),c=n("migrate-from-json");for(let a of Object.values(h.Or))o(a,c);try{a.transaction(()=>{if(f&&"object"==typeof f){for(let[b,c]of(f.settings&&a.run("INSERT INTO settings(id, data) VALUES(1, ?) ON CONFLICT(id) DO UPDATE SET data = excluded.data",[(0,q.s)(f.settings)]),u(a,"providerConnections",f.providerConnections||[],b=>{let{id:c,provider:d,authType:e,name:f,email:g,priority:h,isActive:i,createdAt:j,updatedAt:k,...l}=b;a.run("INSERT OR REPLACE INTO providerConnections(id, provider, authType, name, email, priority, isActive, data, createdAt, updatedAt) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[c,d,e||"oauth",f||null,g||null,h||null,+(!1!==i),(0,q.s)(l),j||new Date().toISOString(),k||new Date().toISOString()])},a=>({id:a.id??null,provider:a.provider??null,name:a.name??null})),u(a,"providerNodes",f.providerNodes||[],b=>{let{id:c,type:d,name:e,createdAt:f,updatedAt:g,...h}=b;a.run("INSERT OR REPLACE INTO providerNodes(id, type, name, data, createdAt, updatedAt) VALUES(?, ?, ?, ?, ?, ?)",[c,d||null,e||null,(0,q.s)(h),f||new Date().toISOString(),g||new Date().toISOString()])},a=>({id:a.id??null,type:a.type??null,name:a.name??null})),u(a,"proxyPools",f.proxyPools||[],b=>{let{id:c,isActive:d,testStatus:e,createdAt:f,updatedAt:g,...h}=b;a.run("INSERT OR REPLACE INTO proxyPools(id, isActive, testStatus, data, createdAt, updatedAt) VALUES(?, ?, ?, ?, ?, ?)",[c,+(!1!==d),e||"unknown",(0,q.s)(h),f||new Date().toISOString(),g||new Date().toISOString()])},a=>({id:a.id??null})),u(a,"apiKeys",f.apiKeys||[],b=>{a.run("INSERT OR REPLACE INTO apiKeys(id, key, name, machineId, isActive, createdAt) VALUES(?, ?, ?, ?, ?, ?)",[b.id,b.key,b.name||null,b.machineId||null,+(!1!==b.isActive),b.createdAt||new Date().toISOString()])},a=>({id:a.id??null,name:a.name??null})),u(a,"combos",f.combos||[],b=>{a.run("INSERT OR REPLACE INTO combos(id, name, kind, models, createdAt, updatedAt) VALUES(?, ?, ?, ?, ?, ?)",[b.id,b.name,b.kind||null,(0,q.s)(b.models||[]),b.createdAt||new Date().toISOString(),b.updatedAt||new Date().toISOString()])},a=>({id:a.id??null,name:a.name??null})),Object.entries(f.modelAliases||{})))a.run("INSERT OR REPLACE INTO kv(scope, key, value) VALUES('modelAliases', ?, ?)",[b,(0,q.s)(c)]);for(let b of f.customModels||[]){let c=`${b.providerAlias}|${b.id}|${b.type||"llm"}`;a.run("INSERT OR REPLACE INTO kv(scope, key, value) VALUES('customModels', ?, ?)",[c,(0,q.s)(b)])}for(let[b,c]of Object.entries(f.mitmAlias||{}))a.run("INSERT OR REPLACE INTO kv(scope, key, value) VALUES('mitmAlias', ?, ?)",[b,(0,q.s)(c||{})]);for(let[b,c]of Object.entries(f.pricing||{}))a.run("INSERT OR REPLACE INTO kv(scope, key, value) VALUES('pricing', ?, ?)",[b,(0,q.s)(c||{})])}if(g&&"object"==typeof g){for(let b of g.history||[]){let c=b.tokens||{};a.run("INSERT INTO usageHistory(timestamp, provider, model, connectionId, apiKey, endpoint, promptTokens, completionTokens, cost, status, tokens, meta) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",[b.timestamp||new Date().toISOString(),b.provider||null,b.model||null,b.connectionId||null,b.apiKey||null,b.endpoint||null,c.prompt_tokens||c.input_tokens||0,c.completion_tokens||c.output_tokens||0,b.cost||0,b.status||"ok",(0,q.s)(c),(0,q.s)({})])}for(let[b,c]of Object.entries(g.dailySummary||{}))a.run("INSERT OR REPLACE INTO usageDaily(dateKey, data) VALUES(?, ?)",[b,(0,q.s)(c)]);"number"==typeof g.totalRequestsLifetime&&(0,k.np)(a,"totalRequestsLifetime",g.totalRequestsLifetime)}if(l&&"object"==typeof l.disabled)for(let[b,c]of Object.entries(l.disabled))a.run("INSERT OR REPLACE INTO kv(scope, key, value) VALUES('disabledModels', ?, ?)",[b,(0,q.s)(c||[])]);if(w&&Array.isArray(w.records))for(let b of w.records)a.run("INSERT OR REPLACE INTO requestDetails(id, timestamp, provider, model, connectionId, status, data) VALUES(?, ?, ?, ?, ?, ?, ?)",[b.id,b.timestamp||new Date().toISOString(),b.provider||null,b.model||null,b.connectionId||null,b.status||null,(0,q.s)(b)]);(0,k.np)(a,"appVersion",m()),(0,k.np)(a,"migratedAt",new Date().toISOString())})}catch(a){if(a instanceof t)return void console.error(`[DB][migrate] aborted: ${a.message} | legacy JSON kept | backup: ${c}`);throw a}try{e().writeFileSync(r,new Date().toISOString())}catch{}p(),console.log(`[DB][migrate] JSON → SQLite in ${Date.now()-b}ms | legacy JSON kept at DATA_DIR | backup: ${c}`);return}if(b)return void(0,k.np)(a,"appVersion",m());let x=(0,k.dy)(a,"appVersion",null),y=m();if(x&&x!==y){let b=n(`upgrade-${x}-to-${y}`);try{o(h.AL,b)}catch{}(0,k.np)(a,"appVersion",y),p(),console.log(`[DB][migrate] App ${x} → ${y} | schema ${c.from} → ${c.to} | backup: ${b}`)}else if(c.applied>0){let a=n(`schema-${c.from}-to-${c.to}`);try{o(h.AL,a)}catch{}p()}}},76040:(a,b,c)=>{c.d(b,{CG:()=>e,oG:()=>d,zE:()=>f});let d=`
2
- PRAGMA journal_mode = WAL;
3
- PRAGMA synchronous = NORMAL;
4
- PRAGMA temp_store = MEMORY;
5
- PRAGMA mmap_size = 30000000;
6
- PRAGMA cache_size = -64000;
7
- PRAGMA foreign_keys = ON;
8
- PRAGMA busy_timeout = 5000;
9
- `,e={_meta:{columns:{key:"TEXT PRIMARY KEY",value:"TEXT NOT NULL"}},settings:{columns:{id:"INTEGER PRIMARY KEY CHECK (id = 1)",data:"TEXT NOT NULL"}},providerConnections:{columns:{id:"TEXT PRIMARY KEY",provider:"TEXT NOT NULL",authType:"TEXT NOT NULL",name:"TEXT",email:"TEXT",priority:"INTEGER",isActive:"INTEGER DEFAULT 1",data:"TEXT NOT NULL",createdAt:"TEXT NOT NULL",updatedAt:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_pc_provider ON providerConnections(provider)","CREATE INDEX IF NOT EXISTS idx_pc_provider_active ON providerConnections(provider, isActive)","CREATE INDEX IF NOT EXISTS idx_pc_priority ON providerConnections(provider, priority)"]},providerNodes:{columns:{id:"TEXT PRIMARY KEY",type:"TEXT",name:"TEXT",data:"TEXT NOT NULL",createdAt:"TEXT NOT NULL",updatedAt:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_pn_type ON providerNodes(type)"]},proxyPools:{columns:{id:"TEXT PRIMARY KEY",isActive:"INTEGER DEFAULT 1",testStatus:"TEXT",data:"TEXT NOT NULL",createdAt:"TEXT NOT NULL",updatedAt:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_pp_active ON proxyPools(isActive)","CREATE INDEX IF NOT EXISTS idx_pp_status ON proxyPools(testStatus)"]},apiKeys:{columns:{id:"TEXT PRIMARY KEY",key:"TEXT UNIQUE NOT NULL",name:"TEXT",machineId:"TEXT",isActive:"INTEGER DEFAULT 1",createdAt:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_ak_key ON apiKeys(key)"]},combos:{columns:{id:"TEXT PRIMARY KEY",name:"TEXT UNIQUE NOT NULL",kind:"TEXT",models:"TEXT NOT NULL",createdAt:"TEXT NOT NULL",updatedAt:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_combo_name ON combos(name)"]},kv:{columns:{scope:"TEXT NOT NULL",key:"TEXT NOT NULL",value:"TEXT NOT NULL"},primaryKey:"PRIMARY KEY (scope, key)",indexes:["CREATE INDEX IF NOT EXISTS idx_kv_scope ON kv(scope)"]},usageHistory:{columns:{id:"INTEGER PRIMARY KEY AUTOINCREMENT",timestamp:"TEXT NOT NULL",provider:"TEXT",model:"TEXT",connectionId:"TEXT",apiKey:"TEXT",endpoint:"TEXT",promptTokens:"INTEGER DEFAULT 0",completionTokens:"INTEGER DEFAULT 0",cost:"REAL DEFAULT 0",status:"TEXT",tokens:"TEXT",meta:"TEXT"},indexes:["CREATE INDEX IF NOT EXISTS idx_uh_ts ON usageHistory(timestamp DESC)","CREATE INDEX IF NOT EXISTS idx_uh_provider ON usageHistory(provider)","CREATE INDEX IF NOT EXISTS idx_uh_model ON usageHistory(model)","CREATE INDEX IF NOT EXISTS idx_uh_conn ON usageHistory(connectionId)"]},usageDaily:{columns:{dateKey:"TEXT PRIMARY KEY",data:"TEXT NOT NULL"}},requestDetails:{columns:{id:"TEXT PRIMARY KEY",timestamp:"TEXT NOT NULL",provider:"TEXT",model:"TEXT",connectionId:"TEXT",status:"TEXT",data:"TEXT NOT NULL"},indexes:["CREATE INDEX IF NOT EXISTS idx_rd_ts ON requestDetails(timestamp DESC)","CREATE INDEX IF NOT EXISTS idx_rd_provider ON requestDetails(provider)","CREATE INDEX IF NOT EXISTS idx_rd_model ON requestDetails(model)","CREATE INDEX IF NOT EXISTS idx_rd_conn ON requestDetails(connectionId)"]}};function f(a,b){let c=Object.entries(b.columns).map(([a,b])=>`${a} ${b}`);return b.primaryKey&&c.push(b.primaryKey),`CREATE TABLE IF NOT EXISTS ${a} (${c.join(", ")})`}}};