@xopcai/xopc 0.0.269 → 0.0.272

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 (293) hide show
  1. package/dist/browser-ext/dist/assets/{auth-cwEj8rFb.js → auth-C1QI-uMG.js} +65 -14
  2. package/dist/browser-ext/dist/background.js +23 -2
  3. package/dist/browser-ext/dist/pairing-handoff.js +51 -0
  4. package/dist/browser-ext/dist/sidepanel.html +1 -1
  5. package/dist/browser-ext/dist/sidepanel.js +39 -27
  6. package/dist/browser-ext/manifest.json +12 -1
  7. package/dist/extensions/telegram/xopc.extension.json +1 -1
  8. package/dist/gateway/static/root/assets/{activity-store-DcwCSY6s.js → activity-store-DffqjeqQ.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-D0NBOWC4.js → agent-avatar-dicebear-Cwj4HCYY.js} +1 -1
  10. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-6CLfLxVc.js +1 -0
  11. package/dist/gateway/static/root/assets/agents-B6mu64fY.js +1 -0
  12. package/dist/gateway/static/root/assets/{api-eaPO-mdr.js → api-CGLdye4i.js} +1 -1
  13. package/dist/gateway/static/root/assets/{app-management-settings-panel-E3xm2teY.js → app-management-settings-panel-BLujSbaw.js} +1 -1
  14. package/dist/gateway/static/root/assets/{appearance-settings-CiZOjgls.js → appearance-settings-BXMcueb8.js} +1 -1
  15. package/dist/gateway/static/root/assets/apps-page-BEgy4hY3.js +1 -0
  16. package/dist/gateway/static/root/assets/{archive-plugin-D09yo_Hc.js → archive-plugin-D4bUampf.js} +1 -1
  17. package/dist/gateway/static/root/assets/{attachment-load-CNYb8Qru.js → attachment-load-CBGNA2Ys.js} +1 -1
  18. package/dist/gateway/static/root/assets/{automations-page-DsrfW5ii.js → automations-page-dQyolNmy.js} +1 -1
  19. package/dist/gateway/static/root/assets/automations-workspace-DxRFrmrV.js +6 -0
  20. package/dist/gateway/static/root/assets/{binary-plugins-OWlaGqlY.js → binary-plugins-bbvp81h2.js} +1 -1
  21. package/dist/gateway/static/root/assets/{block-editor-CVND3M6r.js → block-editor-C8e6Wri4.js} +3 -3
  22. package/dist/gateway/static/root/assets/{browser-automation-inputs-D7IzVK_J.js → browser-automation-inputs-oJWJtQa6.js} +1 -1
  23. package/dist/gateway/static/root/assets/{browser-automations-page-CQ6cCpIv.js → browser-automations-page-CAcJQSjN.js} +2 -2
  24. package/dist/gateway/static/root/assets/browser-settings-page-TLAlqcPo.js +8 -0
  25. package/dist/gateway/static/root/assets/capabilities-settings-panel-z-K_jrZz.js +8 -0
  26. package/dist/gateway/static/root/assets/channels-settings-Dzrk33aB.js +1 -0
  27. package/dist/gateway/static/root/assets/{channels-status-swr-D4JrgJKa.js → channels-status-swr-CfOPNnVr.js} +1 -1
  28. package/dist/gateway/static/root/assets/{chat-terminal-dock-BUjnhT7C.js → chat-terminal-dock-9ZOl92kh.js} +2 -2
  29. package/dist/gateway/static/root/assets/clock-3-DnrAnuyZ.js +1 -0
  30. package/dist/gateway/static/root/assets/connectors-page-B1dIoRNi.js +2 -0
  31. package/dist/gateway/static/root/assets/cron-expression-C26e13YU.js +2 -0
  32. package/dist/gateway/static/root/assets/date-picker-Dj6FRLF9.js +1 -0
  33. package/dist/gateway/static/root/assets/{dependency-picker-Z6Nf0Wjq.js → dependency-picker-D1q89tVc.js} +1 -1
  34. package/dist/gateway/static/root/assets/{desktop-pet-C0F5Iqnc.js → desktop-pet-DfqZBvhp.js} +1 -1
  35. package/dist/gateway/static/root/assets/{desktop-pet-settings-Bj_W6HL1.js → desktop-pet-settings-HCEh2MOm.js} +1 -1
  36. package/dist/gateway/static/root/assets/device-pairing-wizard-CPth92s6.js +1 -0
  37. package/dist/gateway/static/root/assets/{extension-debug-page-Ba09EnAn.js → extension-debug-page-C8cAWVoK.js} +1 -1
  38. package/dist/gateway/static/root/assets/{extension-page-C88aGXJs.js → extension-page-5N87Vaym.js} +1 -1
  39. package/dist/gateway/static/root/assets/extension-settings-page-D85SAUFP.js +1 -0
  40. package/dist/gateway/static/root/assets/{gateway-config-swr-bjzk_4hn.js → gateway-config-swr-BjsDnB_n.js} +1 -1
  41. package/dist/gateway/static/root/assets/gateway-settings-Dqx8PmcT.js +1 -0
  42. package/dist/gateway/static/root/assets/{gateway-startup-retry-DrbIzFyB.js → gateway-startup-retry-BIf0eLWX.js} +1 -1
  43. package/dist/gateway/static/root/assets/git-branch-Dh9uxTot.js +1 -0
  44. package/dist/gateway/static/root/assets/heartbeat-settings-BpDWGE1a.js +1 -0
  45. package/dist/gateway/static/root/assets/home-page-DJaqpC8-.js +1 -0
  46. package/dist/gateway/static/root/assets/{image-generation-api-CBWU9Ner.js → image-generation-api-1m8xTVS_.js} +1 -1
  47. package/dist/gateway/static/root/assets/index-C6PmD0cK.js +74 -0
  48. package/dist/gateway/static/root/assets/index-DKy1Qn1_.css +2 -0
  49. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-B8Z7kKQY.js → keyboard-shortcuts-settings-Byy8mCSq.js} +1 -1
  50. package/dist/gateway/static/root/assets/local-app-workbench-page-l2AEiG2C.js +2 -0
  51. package/dist/gateway/static/root/assets/{local-apps-page-CLSfzkRp.js → local-apps-page-BPo0wBgM.js} +1 -1
  52. package/dist/gateway/static/root/assets/locale-store-CRNble2Z.js +1 -0
  53. package/dist/gateway/static/root/assets/logs-page-X5FdLlXK.js +2 -0
  54. package/dist/gateway/static/root/assets/management-settings-DT6NoIjm.js +1 -0
  55. package/dist/gateway/static/root/assets/{markdown-view-DIcfrLmG.js → markdown-view-AglreSOj.js} +1 -1
  56. package/dist/gateway/static/root/assets/{media-plugins-CSv6-xTA.js → media-plugins-Bzka9qXu.js} +1 -1
  57. package/dist/gateway/static/root/assets/message-circle-Badhj-4D.js +1 -0
  58. package/dist/gateway/static/root/assets/message-square-fVE7Ghj1.js +1 -0
  59. package/dist/gateway/static/root/assets/{messages-BRjoarIr.js → messages-DH_HCgmw.js} +3 -3
  60. package/dist/gateway/static/root/assets/note-detail-panel-BUJPoaGZ.js +5 -0
  61. package/dist/gateway/static/root/assets/notes-page-BwFpWRuo.js +8 -0
  62. package/dist/gateway/static/root/assets/{page-tabs-BfV-PQa5.js → page-tabs-Ys0p65Lt.js} +1 -1
  63. package/dist/gateway/static/root/assets/popover-select-Dz_Qis2R.js +1 -0
  64. package/dist/gateway/static/root/assets/{preview-open-alternatives-DQS7NFpg.js → preview-open-alternatives-iknB5xEp.js} +1 -1
  65. package/dist/gateway/static/root/assets/proactive-card-BPZDgNNR.js +1 -0
  66. package/dist/gateway/static/root/assets/proactive-page-CxdZR-p2.js +1 -0
  67. package/dist/gateway/static/root/assets/{product-open-page-BIhjZLKg.js → product-open-page-W1o3f-kz.js} +1 -1
  68. package/dist/gateway/static/root/assets/project-detail-page-BU1RKAcy.js +1 -0
  69. package/dist/gateway/static/root/assets/projects-page-z0X0tL8G.js +1 -0
  70. package/dist/gateway/static/root/assets/{registry-api-CwveUfe8.js → registry-api-DmYFpjsH.js} +1 -1
  71. package/dist/gateway/static/root/assets/remote-access-hub-NNTut2I8.js +1 -0
  72. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DMQ0wpNg.js → runtime-tools-settings-panel-DP1XyYO8.js} +1 -1
  73. package/dist/gateway/static/root/assets/{schema-form-C91g2PRU.js → schema-form-BMYKdzsH.js} +1 -1
  74. package/dist/gateway/static/root/assets/sessions-page-B6SsHlz5.js +1 -0
  75. package/dist/gateway/static/root/assets/settings-advanced-gate-BQu8bAcN.js +1 -0
  76. package/dist/gateway/static/root/assets/{settings-form-section-Cem6L49Y.js → settings-form-section-2LGjz7bu.js} +1 -1
  77. package/dist/gateway/static/root/assets/{settings-page-afDUxqlV.js → settings-page-7DjpC9_C.js} +1 -1
  78. package/dist/gateway/static/root/assets/setup-status-panel-Dj9jFWJt.js +1 -0
  79. package/dist/gateway/static/root/assets/{share-preview-page-CVEVHksg.js → share-preview-page-BxYdSi8c.js} +1 -1
  80. package/dist/gateway/static/root/assets/shares-settings-CMqE0KuK.js +1 -0
  81. package/dist/gateway/static/root/assets/skill-reload-api-BXqSJymN.js +1 -0
  82. package/dist/gateway/static/root/assets/{skills-page-CNrq1W6C.js → skills-page-DNEScMZH.js} +1 -1
  83. package/dist/gateway/static/root/assets/skills-page.utils-q88l65YU.js +1 -0
  84. package/dist/gateway/static/root/assets/{system-settings-panel-BLE8PxWE.js → system-settings-panel-8NIssGKj.js} +1 -1
  85. package/dist/gateway/static/root/assets/task-detail-page-L6dp9v2y.js +1 -0
  86. package/dist/gateway/static/root/assets/{theme-store-BejLVjIT.js → theme-store-BXZG3S25.js} +1 -1
  87. package/dist/gateway/static/root/assets/tunnel-api-CWsRPM84.js +1 -0
  88. package/dist/gateway/static/root/assets/{use-autosave-DmgEA8Qb.js → use-autosave-BwQuoTQU.js} +1 -1
  89. package/dist/gateway/static/root/assets/user-model-page-D4BucMrZ.js +2 -0
  90. package/dist/gateway/static/root/assets/{voice-api-key-field-sZ0J83SF.js → voice-api-key-field-Bd03Ic0s.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-config-api-BEbz3avx.js → voice-config-api-gggUp3u9.js} +1 -1
  92. package/dist/gateway/static/root/assets/{work-discovery-overlay-BXnAlbmO.js → work-discovery-overlay-DF8PR_pK.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-BkwFey0a.js → workflow-run-setup-panel-BiAAWlir.js} +2 -2
  94. package/dist/gateway/static/root/assets/workflows-page-DryKUMfA.js +6 -0
  95. package/dist/gateway/static/root/index.html +15 -11
  96. package/dist/package.js +1 -1
  97. package/dist/packages/gateway-contract/src/device-pairing.js +2 -1
  98. package/dist/packages/gateway-contract/src/notifications.js +2 -2
  99. package/dist/packages/gateway-contract/src/proactive.js +22 -6
  100. package/dist/packages/gateway-contract/src/session-identity.js +37 -0
  101. package/dist/src/agent/memory/compaction-chunks.d.ts +18 -0
  102. package/dist/src/agent/memory/compaction-chunks.js +53 -0
  103. package/dist/src/agent/memory/compaction-request.d.ts +12 -0
  104. package/dist/src/agent/memory/compaction-request.js +72 -0
  105. package/dist/src/agent/memory/compaction.d.ts +3 -0
  106. package/dist/src/agent/memory/compaction.js +166 -118
  107. package/dist/src/agent/service.js +1 -0
  108. package/dist/src/agent/tool-manuals/xopc-use.d.ts +1 -1
  109. package/dist/src/agent/tool-manuals/xopc-use.js +19 -1
  110. package/dist/src/agent/tools/factory.js +1 -0
  111. package/dist/src/agent/tools/xopc-use-tool.d.ts +3 -2
  112. package/dist/src/agent/tools/xopc-use-tool.js +48 -4
  113. package/dist/src/browser/automations/schema.d.ts +1 -1
  114. package/dist/src/browser/automations/service.d.ts +1 -1
  115. package/dist/src/browser/native-messaging-host.js +3 -1
  116. package/dist/src/cli/commands/connectors.js +1 -1
  117. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  118. package/dist/src/cli/commands/tunnel.js +5 -0
  119. package/dist/src/connectors/connected-source-ingestion.js +1 -1
  120. package/dist/src/connectors/connected-source-normalizers.js +3 -0
  121. package/dist/src/connectors/connection-recovery-service.js +1 -1
  122. package/dist/src/connectors/health.js +1 -1
  123. package/dist/src/gateway/heartbeat/service.js +1 -1
  124. package/dist/src/gateway/hono/app.js +1 -0
  125. package/dist/src/gateway/hono/middleware/auth.d.ts +1 -2
  126. package/dist/src/gateway/hono/middleware/auth.js +49 -31
  127. package/dist/src/gateway/hono/middleware/strict-rate-limit.js +11 -15
  128. package/dist/src/gateway/hono/routes/browser-session.d.ts +3 -0
  129. package/dist/src/gateway/hono/routes/browser-session.js +43 -0
  130. package/dist/src/gateway/hono/routes/capabilities.js +1 -1
  131. package/dist/src/gateway/hono/routes/connectors.js +1 -1
  132. package/dist/src/gateway/hono/routes/devices.js +61 -96
  133. package/dist/src/gateway/hono/routes/exposure.js +3 -7
  134. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  135. package/dist/src/gateway/hono/routes/mcp.js +1 -1
  136. package/dist/src/gateway/hono/routes/models.js +60 -1
  137. package/dist/src/gateway/hono/routes/notes.js +3 -7
  138. package/dist/src/gateway/hono/routes/proactive-control.js +31 -24
  139. package/dist/src/gateway/hono/routes/sessions.js +11 -0
  140. package/dist/src/gateway/hono/routes/shares.js +8 -20
  141. package/dist/src/gateway/hono/routes/site-shares.js +4 -8
  142. package/dist/src/gateway/hono/routes/tunnel.js +13 -13
  143. package/dist/src/gateway/image-generation-setup.d.ts +17 -0
  144. package/dist/src/gateway/image-generation-setup.js +30 -21
  145. package/dist/src/gateway/rate-limit/buckets.d.ts +3 -0
  146. package/dist/src/gateway/rate-limit/buckets.js +10 -0
  147. package/dist/src/gateway/runtime-config.js +2 -0
  148. package/dist/src/gateway/security/browser-session.d.ts +5 -0
  149. package/dist/src/gateway/security/browser-session.js +45 -0
  150. package/dist/src/gateway/security/gateway-principal.d.ts +1 -0
  151. package/dist/src/gateway/service.d.ts +1 -0
  152. package/dist/src/gateway/service.js +21 -11
  153. package/dist/src/heartbeat/index.js +1 -1
  154. package/dist/src/infra/rate-limit/keyed-store.d.ts +3 -0
  155. package/dist/src/infra/rate-limit/keyed-store.js +9 -2
  156. package/dist/src/notifications/web-push.js +1 -1
  157. package/dist/src/proactive/actions/service.js +4 -2
  158. package/dist/src/proactive/execution/authorization.d.ts +2 -0
  159. package/dist/src/proactive/execution/authorization.js +39 -1
  160. package/dist/src/proactive/execution/context.d.ts +4 -0
  161. package/dist/src/proactive/execution/context.js +51 -5
  162. package/dist/src/proactive/execution/insight.js +3 -1
  163. package/dist/src/proactive/execution/repository.js +15 -5
  164. package/dist/src/proactive/execution/types.d.ts +2 -0
  165. package/dist/src/proactive/execution/worker.js +7 -2
  166. package/dist/src/proactive/experience.d.ts +69 -0
  167. package/dist/src/proactive/experience.js +90 -0
  168. package/dist/src/proactive/follow-ups.d.ts +123 -0
  169. package/dist/src/proactive/follow-ups.js +169 -0
  170. package/dist/src/proactive/inbox/cards.js +35 -6
  171. package/dist/src/proactive/inbox/delivery.js +4 -2
  172. package/dist/src/proactive/inbox/digest.js +2 -2
  173. package/dist/src/proactive/inbox/lifecycle.js +4 -1
  174. package/dist/src/proactive/inbox/notification-policy.js +4 -2
  175. package/dist/src/proactive/inbox/repository.js +17 -11
  176. package/dist/src/proactive/inbox/types.d.ts +2 -0
  177. package/dist/src/proactive/inbox/worker.js +1 -1
  178. package/dist/src/proactive/index.js +2 -2
  179. package/dist/src/proactive/mail-thread.d.ts +13 -0
  180. package/dist/src/proactive/mail-thread.js +54 -0
  181. package/dist/src/proactive/policy/service.d.ts +3 -5
  182. package/dist/src/proactive/policy/service.js +3 -5
  183. package/dist/src/proactive/scenarios/control.d.ts +4 -7
  184. package/dist/src/proactive/scenarios/control.js +3 -4
  185. package/dist/src/proactive/scenarios/preview.js +1 -1
  186. package/dist/src/proactive/scenarios/prompt-composer.js +2 -0
  187. package/dist/src/proactive/service.js +1 -1
  188. package/dist/src/proactive/temporal/worker.d.ts +1 -0
  189. package/dist/src/proactive/temporal/worker.js +18 -4
  190. package/dist/src/realtime/runtime.d.ts +2 -1
  191. package/dist/src/realtime/runtime.js +9 -3
  192. package/dist/src/realtime/tickets.d.ts +1 -0
  193. package/dist/src/realtime/tickets.js +3 -0
  194. package/dist/src/session/store.d.ts +2 -0
  195. package/dist/src/session/store.js +17 -2
  196. package/dist/src/session/types.d.ts +2 -1
  197. package/dist/src/storage/sqlite/browser-session-repository.d.ts +17 -0
  198. package/dist/src/storage/sqlite/browser-session-repository.js +54 -0
  199. package/dist/src/storage/sqlite/device-pairing-approval.js +2 -1
  200. package/dist/src/storage/sqlite/device-pairing-repository.d.ts +4 -10
  201. package/dist/src/storage/sqlite/device-pairing-repository.js +10 -62
  202. package/dist/src/storage/sqlite/index.d.ts +1 -1
  203. package/dist/src/storage/sqlite/index.js +2 -2
  204. package/dist/src/storage/sqlite/migrations/162_proactive_product.sql +7 -0
  205. package/dist/src/storage/sqlite/migrations/163_proactive_follow_ups.sql +29 -0
  206. package/dist/src/storage/sqlite/migrations/164_browser_sessions.sql +8 -0
  207. package/dist/src/storage/sqlite/migrations/165_device_pairing_target.sql +40 -0
  208. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  209. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  210. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  211. package/dist/src/storage/sqlite/schema.js +1 -1
  212. package/dist/src/storage/sqlite/session-identity-sql.d.ts +2 -0
  213. package/dist/src/storage/sqlite/session-identity-sql.js +18 -0
  214. package/dist/src/storage/sqlite/session-repository.js +26 -22
  215. package/dist/src/tasks/home-query-service.js +1 -1
  216. package/dist/src/tasks/index.js +4 -4
  217. package/dist/src/tui/tui-startup-resources.js +1 -1
  218. package/dist/src/tunnel/auth-policy.d.ts +3 -0
  219. package/dist/src/tunnel/auth-policy.js +8 -0
  220. package/dist/src/tunnel/broker-client.d.ts +5 -15
  221. package/dist/src/tunnel/broker-client.js +37 -49
  222. package/dist/src/tunnel/frpc-binary.d.ts +8 -6
  223. package/dist/src/tunnel/frpc-binary.js +76 -88
  224. package/dist/src/tunnel/frpc-config.d.ts +2 -1
  225. package/dist/src/tunnel/frpc-config.js +29 -12
  226. package/dist/src/tunnel/frpc-release.d.ts +27 -0
  227. package/dist/src/tunnel/frpc-release.js +30 -0
  228. package/dist/src/tunnel/gateway-lifecycle.js +8 -2
  229. package/dist/src/tunnel/index.js +2 -1
  230. package/dist/src/tunnel/registration-proof.d.ts +19 -0
  231. package/dist/src/tunnel/registration-proof.js +37 -0
  232. package/dist/src/tunnel/tunnel-persist.js +3 -1
  233. package/dist/src/tunnel/tunnel-service.d.ts +1 -0
  234. package/dist/src/tunnel/tunnel-service.js +35 -8
  235. package/dist/src/tunnel/tunnel-state.js +11 -5
  236. package/dist/src/tunnel/tunnel-types.d.ts +2 -0
  237. package/dist/src/tunnel/well-known.js +5 -1
  238. package/dist/src/user-context/config.js +2 -2
  239. package/dist/src/utils/logger/redact.js +4 -0
  240. package/dist/src/voice/dashscope/streaming-stt-session.js +1 -0
  241. package/dist/src/voice/dashscope/streaming-tts-stream.d.ts +1 -0
  242. package/dist/src/voice/dashscope/streaming-tts-stream.js +8 -0
  243. package/dist/src/voice/realtime/agentBroker.js +1 -1
  244. package/dist/src/voice/realtime/agentEngine.js +1 -1
  245. package/dist/src/voice/realtime/pcm-output-gain.d.ts +2 -0
  246. package/dist/src/voice/realtime/pcm-output-gain.js +16 -0
  247. package/dist/src/voice/realtime/runtime.d.ts +1 -0
  248. package/dist/src/voice/realtime/runtime.js +21 -3
  249. package/dist/src/voice/realtime/runtime.types.d.ts +1 -0
  250. package/dist/src/workflows/service/workflow-run-service.js +3 -1
  251. package/dist/src/workflows/service/workflow-session-bridge.d.ts +1 -0
  252. package/dist/src/workflows/service/workflow-session-bridge.js +1 -0
  253. package/package.json +4 -4
  254. package/dist/gateway/static/root/assets/agent-defaults-settings-panel-qKCezlBg.js +0 -1
  255. package/dist/gateway/static/root/assets/agents-BMhnZKhP.js +0 -1
  256. package/dist/gateway/static/root/assets/apps-page-DduJDWGY.js +0 -1
  257. package/dist/gateway/static/root/assets/automations-workspace-X7hNHCjW.js +0 -6
  258. package/dist/gateway/static/root/assets/browser-settings-page-BZ7nK_pN.js +0 -8
  259. package/dist/gateway/static/root/assets/capabilities-settings-panel-BfKvJO1C.js +0 -7
  260. package/dist/gateway/static/root/assets/channels-settings-D1UDxJuA.js +0 -1
  261. package/dist/gateway/static/root/assets/connectors-page-C2nuqs_O.js +0 -2
  262. package/dist/gateway/static/root/assets/cron-expression-DlyRIyUn.js +0 -2
  263. package/dist/gateway/static/root/assets/date-picker-CU-ij_yE.js +0 -1
  264. package/dist/gateway/static/root/assets/extension-settings-page-CMyt0A32.js +0 -1
  265. package/dist/gateway/static/root/assets/gateway-settings-ogv8ZbvG.js +0 -1
  266. package/dist/gateway/static/root/assets/heartbeat-settings-BnrMRKaZ.js +0 -1
  267. package/dist/gateway/static/root/assets/home-page-CbcJCREd.js +0 -1
  268. package/dist/gateway/static/root/assets/index-7PZ6jmhy.css +0 -2
  269. package/dist/gateway/static/root/assets/index-CfyyA9-g.js +0 -74
  270. package/dist/gateway/static/root/assets/local-app-workbench-page-D5XVZnK1.js +0 -2
  271. package/dist/gateway/static/root/assets/locale-store-BQ2HKTWb.js +0 -1
  272. package/dist/gateway/static/root/assets/logs-page-CWDU1AGN.js +0 -2
  273. package/dist/gateway/static/root/assets/management-settings-CuFNgQUy.js +0 -1
  274. package/dist/gateway/static/root/assets/mobile-pairing-wizard-C7d_ztgp.js +0 -1
  275. package/dist/gateway/static/root/assets/note-detail-panel-D5JuBLyt.js +0 -5
  276. package/dist/gateway/static/root/assets/notes-page-C5-ccCi4.js +0 -8
  277. package/dist/gateway/static/root/assets/popover-select-CKBYnT3c.js +0 -1
  278. package/dist/gateway/static/root/assets/proactive-page-fHjPigmx.js +0 -1
  279. package/dist/gateway/static/root/assets/project-detail-page-6v_khvEt.js +0 -1
  280. package/dist/gateway/static/root/assets/projects-page-CCy1aK4V.js +0 -1
  281. package/dist/gateway/static/root/assets/remote-access-hub-pkqKRnch.js +0 -1
  282. package/dist/gateway/static/root/assets/sessions-page-Cr4E4cap.js +0 -1
  283. package/dist/gateway/static/root/assets/settings-advanced-gate-D1JRDRyL.js +0 -1
  284. package/dist/gateway/static/root/assets/setup-status-panel-Cc_iP_vv.js +0 -1
  285. package/dist/gateway/static/root/assets/shares-settings-BrMECMAB.js +0 -1
  286. package/dist/gateway/static/root/assets/skill-reload-api-DuqIDYjc.js +0 -1
  287. package/dist/gateway/static/root/assets/skills-page.utils-D1wGfm22.js +0 -1
  288. package/dist/gateway/static/root/assets/task-detail-page-m0oXUKl2.js +0 -1
  289. package/dist/gateway/static/root/assets/tunnel-api-Dur80zSQ.js +0 -1
  290. package/dist/gateway/static/root/assets/user-model-page-Dl10D_5q.js +0 -2
  291. package/dist/gateway/static/root/assets/workflows-page-CswgoIFU.js +0 -6
  292. package/dist/src/proactive/actions/workflow.d.ts +0 -15
  293. package/dist/src/proactive/actions/workflow.js +0 -88
@@ -0,0 +1,18 @@
1
+ import { SESSION_SOURCE_CHANNELS } from "../../../packages/gateway-contract/src/session-identity.js";
2
+ //#region src/storage/sqlite/session-identity-sql.ts
3
+ const custom = (key) => `json_extract(CASE WHEN json_valid(s.custom_data_json) THEN s.custom_data_json ELSE '{}' END, '$.${key}')`;
4
+ const channel = "LOWER(TRIM(s.source_channel))";
5
+ const SESSION_SOURCE_SQL = `(CASE
6
+ WHEN s.session_type = 'heartbeat' THEN 'system'
7
+ WHEN ${custom("origin")} = 'automation' OR ${custom("triggerSource")} = 'automation' OR s.session_type = 'cron' THEN 'automation'
8
+ WHEN ${custom("createdSurface")} = 'browser_extension' THEN 'browser'
9
+ ${Object.entries(SESSION_SOURCE_CHANNELS).map(([name, aliases]) => `WHEN ${channel} IN (${aliases.map((alias) => `'${alias}'`).join(",")}) THEN '${name}'`).join("\n ")}
10
+ ELSE 'other' END)`;
11
+ const SESSION_PURPOSE_SQL = `(CASE
12
+ WHEN ${SESSION_SOURCE_SQL} = 'system' THEN 'system'
13
+ WHEN s.session_type = 'workflow-subagent' THEN 'subagent'
14
+ WHEN s.session_type = 'workflow-run' THEN 'workflow'
15
+ WHEN ${SESSION_SOURCE_SQL} = 'automation' THEN 'automation'
16
+ ELSE 'chat' END)`;
17
+ //#endregion
18
+ export { SESSION_PURPOSE_SQL, SESSION_SOURCE_SQL };
@@ -5,6 +5,7 @@ import { buildGlobalSessionStats, metadataToSessionInsert, sessionRowToMetadata
5
5
  import { cancelConnectionObjective } from "./connection-wait-repository.js";
6
6
  import { notifyUserContextChange } from "../../user-context/changes.js";
7
7
  import { validateSessionId } from "../../session/session-id.js";
8
+ import { SESSION_PURPOSE_SQL, SESSION_SOURCE_SQL } from "./session-identity-sql.js";
8
9
  import { buildFts5SearchQuery } from "./fts.js";
9
10
  import { randomUUID } from "node:crypto";
10
11
  //#region src/storage/sqlite/session-repository.ts
@@ -81,7 +82,7 @@ function listSessionMetadata(query = {}) {
81
82
  if (query.sessionTypes?.length) {
82
83
  conditions.push(`s.session_type IN (${query.sessionTypes.map(() => "?").join(", ")})`);
83
84
  params.push(...query.sessionTypes);
84
- } else if (!query.includeHidden) {
85
+ } else if (!query.includeHidden && !query.purposes?.length && !query.activity && !query.sources?.length) {
85
86
  conditions.push(`s.session_type = ?`);
86
87
  params.push("chat");
87
88
  }
@@ -90,6 +91,21 @@ function listSessionMetadata(query = {}) {
90
91
  conditions.push(`s.status IN (${statuses.map(() => "?").join(", ")})`);
91
92
  params.push(...statuses);
92
93
  }
94
+ if (query.excludeArchived) conditions.push(`s.status != 'archived'`);
95
+ if (query.sources?.length) {
96
+ conditions.push(`${SESSION_SOURCE_SQL} IN (${query.sources.map(() => "?").join(",")})`);
97
+ params.push(...query.sources);
98
+ }
99
+ if (query.purposes?.length) {
100
+ conditions.push(`${SESSION_PURPOSE_SQL} IN (${query.purposes.map(() => "?").join(",")})`);
101
+ params.push(...query.purposes);
102
+ }
103
+ if (query.activity === "automatic") conditions.push(`${SESSION_SOURCE_SQL} IN ('automation', 'system')`);
104
+ if (query.activity === "manual") conditions.push(`${SESSION_PURPOSE_SQL} = 'chat' AND ${SESSION_SOURCE_SQL} NOT IN ('automation', 'system')`);
105
+ if (query.agentId) {
106
+ conditions.push("s.agent_id = ?");
107
+ params.push(query.agentId);
108
+ }
93
109
  if (query.projectId) {
94
110
  conditions.push(`s.project_id = ?`);
95
111
  params.push(query.projectId);
@@ -126,29 +142,17 @@ function listSessionMetadata(query = {}) {
126
142
  conditions.push(`s.tags_json LIKE ?`);
127
143
  params.push(`%"${tag}"%`);
128
144
  }
129
- let searchKeys = null;
130
145
  if (query.search?.trim()) {
131
146
  const rawSearch = query.search.trim();
132
- const ftsQuery = buildFts5SearchQuery(rawSearch);
133
- const ftsRows = db.prepare(`SELECT DISTINCT session_key FROM transcript_fts WHERE transcript_fts MATCH ? LIMIT 500`).all(ftsQuery);
134
- const ftsKeys = new Set(ftsRows.map((r) => r.session_key));
135
147
  const like = `%${rawSearch.toLowerCase()}%`;
136
- const metaRows = db.prepare(`SELECT session_key FROM sessions
137
- WHERE LOWER(session_key) LIKE ?
138
- OR LOWER(COALESCE(name, '')) LIKE ?
139
- OR LOWER(source_channel) LIKE ?
140
- OR LOWER(source_chat_id) LIKE ?
141
- OR LOWER(tags_json) LIKE ?`).all(like, like, like, like, like);
142
- searchKeys = [...new Set([...ftsKeys, ...metaRows.map((r) => r.session_key)])];
143
- if (searchKeys.length === 0) return {
144
- items: [],
145
- total: 0,
146
- limit: query.limit ?? 50,
147
- offset: query.offset ?? 0,
148
- hasMore: false
149
- };
150
- conditions.push(`s.session_key IN (${searchKeys.map(() => "?").join(", ")})`);
151
- params.push(...searchKeys);
148
+ conditions.push(`(s.session_key IN (
149
+ SELECT session_key FROM transcript_fts WHERE transcript_fts MATCH ?
150
+ ) OR LOWER(s.session_key) LIKE ?
151
+ OR LOWER(COALESCE(s.name, '')) LIKE ?
152
+ OR LOWER(s.source_channel) LIKE ?
153
+ OR LOWER(s.source_chat_id) LIKE ?
154
+ OR LOWER(s.tags_json) LIKE ?)`);
155
+ params.push(buildFts5SearchQuery(rawSearch), like, like, like, like, like);
152
156
  }
153
157
  const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
154
158
  const sortColumn = sessionSortColumn(query.sortBy);
@@ -158,7 +162,7 @@ function listSessionMetadata(query = {}) {
158
162
  const offset = query.offset ?? 0;
159
163
  return {
160
164
  items: db.prepare(`SELECT ${SESSION_COLUMNS} ${SESSION_FROM_JOIN} ${where}
161
- ORDER BY ${sortColumn} ${sortOrder}
165
+ ORDER BY ${sortColumn} ${sortOrder}, s.session_key ASC
162
166
  LIMIT ? OFFSET ?`).all(...params, limit, offset).map((row) => sessionRowToMetadata(row.session_key, row)),
163
167
  total,
164
168
  limit,
@@ -336,7 +336,7 @@ var HomeQueryService = class {
336
336
  detail: item.insight.summary,
337
337
  reason: item.insight.disposition === "request_approval" ? "approval_required" : item.insight.attentionKind === "decision" ? "decision_needed" : "insight_available",
338
338
  urgency: item.insight.urgency === "critical" || item.insight.urgency === "high" ? "now" : "soon",
339
- href: `/?judgment=${encodeURIComponent(item.id)}`,
339
+ href: `/assistant-work?item=${encodeURIComponent(item.id)}`,
340
340
  updatedAt: Date.parse(item.updatedAt),
341
341
  judgment: {
342
342
  inboxItemId: item.id,
@@ -3,18 +3,18 @@ import { TaskRunRepository } from "./task-run-repository.js";
3
3
  import { TaskRepository } from "./task-repository.js";
4
4
  import { TaskConversationConflictError, TaskConversationRepository } from "./task-conversation-repository.js";
5
5
  import { TaskReadModelProjector } from "./task-read-model-projector.js";
6
- import { resolveExecutionContext } from "./execution-context.js";
7
- import { AttentionGovernor } from "./attention-governor.js";
8
- import { HomeQueryService, buildHomeWorkbench, decisionFromTask } from "./home-query-service.js";
9
6
  import { TaskContextRepository } from "./task-context-repository.js";
10
7
  import { TaskDependencyError, TaskDependencyService } from "./task-dependency-service.js";
11
8
  import { TaskApplicationService } from "./task-application-service.js";
9
+ import { ProjectMonitoringService, decideProactiveDisposition, isInQuietHours, nextQuietHoursEnd, proactiveDispositionReason } from "./project-monitoring-service.js";
10
+ import { resolveExecutionContext } from "./execution-context.js";
11
+ import { AttentionGovernor } from "./attention-governor.js";
12
+ import { HomeQueryService, buildHomeWorkbench, decisionFromTask } from "./home-query-service.js";
12
13
  import { TaskWorkflowCoordinator } from "./task-workflow-coordinator.js";
13
14
  import { defineTaskContract } from "./task-contract-definition.js";
14
15
  import { ModelTaskContractPlanner, parseTaskContractResponse } from "./task-contract-planner.js";
15
16
  import { assembleTaskContext, buildTaskExecutionDirective, getTaskContextManifest, getTaskExecutionBrief } from "./task-context-assembler.js";
16
17
  import { TaskRunCoordinator } from "./task-run-coordinator.js";
17
- import { ProjectMonitoringService, decideProactiveDisposition, isInQuietHours, nextQuietHoursEnd, proactiveDispositionReason } from "./project-monitoring-service.js";
18
18
  import { ProjectOperatingViewService, summarizeProjectOperatingView } from "./project-operating-view-service.js";
19
19
  import { TaskValueMetricsService } from "./task-value-metrics-service.js";
20
20
  import { TaskHandoffService } from "./task-handoff-service.js";
@@ -5,9 +5,9 @@ import { resolveBootstrapFilesSync } from "../agent/bootstrap/bootstrap-files.js
5
5
  import { createSkillConfigManager, isSkillEnabled } from "../agent/skills/config.js";
6
6
  import { loadSkills } from "../agent/skills/index.js";
7
7
  import { createWorkflowCatalog } from "../agent/workflow/catalog.js";
8
+ import { listConnectorInstances } from "../connectors/instances.js";
8
9
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
9
10
  import "../config/index.js";
10
- import { listConnectorInstances } from "../connectors/instances.js";
11
11
  import { basename } from "node:path";
12
12
  //#region src/tui/tui-startup-resources.ts
13
13
  init_paths();
@@ -0,0 +1,3 @@
1
+ import type { ResolvedGatewayAuth } from '../gateway/auth.js';
2
+ /** A public FRP ingress cannot trust local sockets or proxy identity headers. */
3
+ export declare function requireTunnelGatewayToken(auth: ResolvedGatewayAuth): string;
@@ -0,0 +1,8 @@
1
+ //#region src/tunnel/auth-policy.ts
2
+ /** A public FRP ingress cannot trust local sockets or proxy identity headers. */
3
+ function requireTunnelGatewayToken(auth) {
4
+ if (auth.mode !== "token" || !auth.token?.trim()) throw new Error("Public remote access requires gateway token authentication.");
5
+ return auth.token;
6
+ }
7
+ //#endregion
8
+ export { requireTunnelGatewayToken };
@@ -4,9 +4,13 @@ export type BrokerRegisterInput = {
4
4
  registrationSecret: string;
5
5
  gatewayVersion: string;
6
6
  platform: string;
7
- gatewayTokenHash: string;
7
+ recoveryToken?: string;
8
8
  preferredSubdomain?: string;
9
9
  };
10
+ export declare class TunnelBrokerError extends Error {
11
+ readonly status: number;
12
+ constructor(status: number, message: string);
13
+ }
10
14
  export declare class TunnelBrokerClient {
11
15
  private readonly baseUrl;
12
16
  constructor(baseUrl: string);
@@ -14,19 +18,5 @@ export declare class TunnelBrokerClient {
14
18
  register(input: BrokerRegisterInput): Promise<TunnelRegistration>;
15
19
  heartbeat(tunnelId: string, tunnelToken: string): Promise<void>;
16
20
  deregister(tunnelId: string, tunnelToken: string): Promise<void>;
17
- setDnsChallenge(input: {
18
- tunnelId: string;
19
- tunnelToken: string;
20
- subdomain: string;
21
- txtValue: string;
22
- }): Promise<{
23
- recordId: string;
24
- fqdn: string;
25
- }>;
26
- cleanupDnsChallenge(input: {
27
- tunnelId: string;
28
- tunnelToken: string;
29
- recordId: string;
30
- }): Promise<void>;
31
21
  }
32
22
  export declare function resolveBrokerApiBase(brokerUrl: string): string;
@@ -1,8 +1,31 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
+ import { createTunnelRegistrationProof } from "./registration-proof.js";
4
+ import { z } from "zod";
3
5
  //#region src/tunnel/broker-client.ts
4
6
  init_logger();
5
7
  const log = createLogger("TunnelBroker");
8
+ var TunnelBrokerError = class extends Error {
9
+ constructor(status, message) {
10
+ super(message);
11
+ this.status = status;
12
+ }
13
+ };
14
+ const registrationResponseSchema = z.object({
15
+ tunnelId: z.string().regex(/^[a-zA-Z0-9_-]{1,128}$/),
16
+ tunnelToken: z.string().min(1).max(256),
17
+ subdomain: z.string().regex(/^[a-z0-9]{4,16}$/),
18
+ publicUrl: z.url(),
19
+ frpc: z.object({
20
+ serverAddr: z.string().min(1).max(253),
21
+ serverPort: z.number().int().min(1).max(65535),
22
+ authToken: z.string().min(1).max(256),
23
+ proxyName: z.string().regex(/^[a-zA-Z0-9_-]{1,128}$/),
24
+ subdomain: z.string().regex(/^[a-z0-9]{4,16}$/)
25
+ }),
26
+ expiresAt: z.iso.datetime(),
27
+ heartbeatIntervalMs: z.number().int().min(5e3).max(6e4)
28
+ });
6
29
  var TunnelBrokerClient = class {
7
30
  constructor(baseUrl) {
8
31
  this.baseUrl = baseUrl;
@@ -13,39 +36,40 @@ var TunnelBrokerClient = class {
13
36
  async register(input) {
14
37
  const url = this.apiUrl("/tunnels/register");
15
38
  const res = await fetch(url, {
39
+ redirect: "error",
40
+ signal: AbortSignal.timeout(15e3),
16
41
  method: "POST",
17
42
  headers: {
18
43
  "Content-Type": "application/json",
19
44
  "X-Registration-Secret": input.registrationSecret
20
45
  },
21
- body: JSON.stringify({
22
- gatewayVersion: input.gatewayVersion,
23
- platform: input.platform,
24
- gatewayTokenHash: input.gatewayTokenHash,
25
- preferredSubdomain: input.preferredSubdomain
26
- })
46
+ body: JSON.stringify(createTunnelRegistrationProof(input))
27
47
  });
28
48
  if (!res.ok) {
29
- const body = await res.text().catch(() => "");
30
49
  log.error({
31
50
  status: res.status,
32
- url,
33
- bodyPreview: body.slice(0, 200)
51
+ url
34
52
  }, "Tunnel register failed");
35
- throw new Error(`Tunnel register failed: ${res.status} ${res.statusText}`);
53
+ throw new TunnelBrokerError(res.status, `Tunnel register failed: ${res.status}`);
36
54
  }
37
- return await res.json();
55
+ const registration = registrationResponseSchema.parse(await res.json());
56
+ if (new URL(registration.publicUrl).protocol !== "https:") throw new Error("Tunnel requires HTTPS");
57
+ return registration;
38
58
  }
39
59
  async heartbeat(tunnelId, tunnelToken) {
40
60
  const res = await fetch(this.apiUrl(`/tunnels/${encodeURIComponent(tunnelId)}/heartbeat`), {
61
+ redirect: "error",
62
+ signal: AbortSignal.timeout(15e3),
41
63
  method: "POST",
42
64
  headers: { "X-Tunnel-Token": tunnelToken }
43
65
  });
44
- if (res.status === 401 || res.status === 410) throw new Error(`Tunnel heartbeat rejected: ${res.status}`);
66
+ if (res.status === 401 || res.status === 403 || res.status === 410) throw new TunnelBrokerError(res.status, `Tunnel heartbeat rejected: ${res.status}`);
45
67
  if (!res.ok) throw new Error(`Tunnel heartbeat failed: ${res.status}`);
46
68
  }
47
69
  async deregister(tunnelId, tunnelToken) {
48
70
  const res = await fetch(this.apiUrl(`/tunnels/${encodeURIComponent(tunnelId)}`), {
71
+ redirect: "error",
72
+ signal: AbortSignal.timeout(15e3),
49
73
  method: "DELETE",
50
74
  headers: { "X-Tunnel-Token": tunnelToken }
51
75
  });
@@ -54,42 +78,6 @@ var TunnelBrokerClient = class {
54
78
  status: res.status
55
79
  }, "Tunnel deregister returned non-OK");
56
80
  }
57
- async setDnsChallenge(input) {
58
- const res = await fetch(this.apiUrl("/dns/challenge"), {
59
- method: "POST",
60
- headers: {
61
- "Content-Type": "application/json",
62
- "X-Tunnel-Token": input.tunnelToken
63
- },
64
- body: JSON.stringify({
65
- tunnelId: input.tunnelId,
66
- subdomain: input.subdomain,
67
- txtValue: input.txtValue
68
- })
69
- });
70
- if (!res.ok) {
71
- const body = await res.text().catch(() => "");
72
- throw new Error(`Broker DNS challenge failed: ${res.status} ${body.slice(0, 200)}`);
73
- }
74
- return await res.json();
75
- }
76
- async cleanupDnsChallenge(input) {
77
- const res = await fetch(this.apiUrl("/dns/cleanup"), {
78
- method: "POST",
79
- headers: {
80
- "Content-Type": "application/json",
81
- "X-Tunnel-Token": input.tunnelToken
82
- },
83
- body: JSON.stringify({
84
- tunnelId: input.tunnelId,
85
- recordId: input.recordId
86
- })
87
- });
88
- if (!res.ok && res.status !== 404) log.warn({
89
- recordId: input.recordId,
90
- status: res.status
91
- }, "Broker DNS cleanup returned non-OK");
92
- }
93
81
  };
94
82
  function resolveBrokerApiBase(brokerUrl) {
95
83
  const trimmed = brokerUrl.replace(/\/+$/, "");
@@ -97,4 +85,4 @@ function resolveBrokerApiBase(brokerUrl) {
97
85
  return `${trimmed}/api`;
98
86
  }
99
87
  //#endregion
100
- export { TunnelBrokerClient, resolveBrokerApiBase };
88
+ export { TunnelBrokerClient, TunnelBrokerError, resolveBrokerApiBase };
@@ -1,14 +1,16 @@
1
1
  import { type FrpcReleasePlatform } from './frpc-extract.js';
2
+ import { FRPC_VERSION } from './frpc-release.js';
2
3
  import type { FrpcDownloadProgress } from './tunnel-types.js';
3
- export declare const FRPC_VERSION = "0.62.1";
4
+ export { FRPC_VERSION };
4
5
  export type { FrpcDownloadProgress };
5
6
  export type EnsureFrpcBinaryOptions = {
6
7
  onProgress?: (progress: FrpcDownloadProgress) => void;
8
+ platform?: FrpcReleasePlatform;
9
+ arch?: string;
7
10
  };
8
- export declare function buildFrpcReleaseBasename(frpPlatform: FrpcReleasePlatform, arch: string, version?: string): string;
9
- export declare function frpcDownloadUrlsForTarget(frpPlatform: FrpcReleasePlatform, arch: string, version?: string): string[];
10
- /** Set after a successful tunnel start so subprocesses can resolve the same binary. */
11
- export declare function publishFrpcPathForProcess(binPath: string): void;
12
- /** Clear runtime frpc path when the tunnel stops (no bundled Electron binary). */
11
+ export declare function buildFrpcReleaseBasename(platform: FrpcReleasePlatform, arch: string, version?: string): string;
12
+ export declare function frpcDownloadUrlsForTarget(platform: FrpcReleasePlatform, arch: string, version?: string): string[];
13
+ export declare function verifyFrpcDigest(path: string, expected: string): Promise<void>;
14
+ export declare function publishFrpcPathForProcess(path: string): void;
13
15
  export declare function clearFrpcPathForProcess(): void;
14
16
  export declare function ensureFrpcBinary(opts?: EnsureFrpcBinaryOptions): Promise<string>;
@@ -2,127 +2,115 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { init_paths, resolveBinDir } from "../config/paths.js";
4
4
  import { extractFrpcFromReleaseArchive, frpcReleaseArchiveExtension, nodePlatformForFrpTarget } from "./frpc-extract.js";
5
- import { tmpdir } from "node:os";
5
+ import { FRPC_RELEASES, FRPC_VERSION } from "./frpc-release.js";
6
6
  import { join } from "node:path";
7
- import { chmodSync, createWriteStream, existsSync, mkdirSync, rmSync } from "node:fs";
8
- import { randomBytes } from "node:crypto";
7
+ import { chmodSync, createReadStream, createWriteStream, existsSync, mkdirSync, mkdtempSync, renameSync, rmSync } from "node:fs";
8
+ import { createHash } from "node:crypto";
9
9
  import { pipeline } from "node:stream/promises";
10
- import { Readable } from "node:stream";
10
+ import { Readable, Transform } from "node:stream";
11
11
  //#region src/tunnel/frpc-binary.ts
12
12
  init_paths();
13
13
  init_logger();
14
14
  const log = createLogger("TunnelFrpc");
15
- const FRPC_VERSION = "0.62.1";
16
- const PLATFORM_MAP = {
17
- darwin: "darwin",
18
- linux: "linux",
19
- win32: "windows"
20
- };
21
- const ARCH_MAP = {
22
- x64: "amd64",
23
- arm64: "arm64",
24
- ia32: "386"
25
- };
26
- function buildFrpcReleaseBasename(frpPlatform, arch, version = FRPC_VERSION) {
27
- return `frp_${version}_${frpPlatform}_${arch}`;
15
+ const MAX_ARCHIVE_BYTES = 64 * 1024 * 1024;
16
+ function buildFrpcReleaseBasename(platform, arch, version = FRPC_VERSION) {
17
+ return `frp_${version}_${platform}_${arch}`;
28
18
  }
29
- function frpcDownloadUrlsForTarget(frpPlatform, arch, version = FRPC_VERSION) {
30
- const folder = buildFrpcReleaseBasename(frpPlatform, arch, version);
31
- const ext = frpcReleaseArchiveExtension(frpPlatform);
32
- return [
33
- `https://frp.xopc.ai/bin/${folder}${ext}`,
34
- `https://github.com/fatedier/frp/releases/download/v${version}/${folder}${ext}`,
35
- `https://ghfast.top/https://github.com/fatedier/frp/releases/download/v${version}/${folder}${ext}`
36
- ];
19
+ function frpcDownloadUrlsForTarget(platform, arch, version = FRPC_VERSION) {
20
+ const archive = buildFrpcReleaseBasename(platform, arch, version) + frpcReleaseArchiveExtension(platform);
21
+ return [`https://frp.xopc.ai/bin/${archive}`, `https://github.com/fatedier/frp/releases/download/v${version}/${archive}`];
37
22
  }
38
- function frpcPlatformArch() {
39
- const platform = PLATFORM_MAP[process.platform] ?? process.platform;
40
- const arch = ARCH_MAP[process.arch] ?? process.arch;
41
- return {
42
- platform,
43
- arch,
44
- folder: buildFrpcReleaseBasename(platform, arch)
45
- };
23
+ async function verifyFrpcDigest(path, expected) {
24
+ const hash = createHash("sha256");
25
+ await pipeline(createReadStream(path), hash);
26
+ if (hash.digest("hex") !== expected) throw new Error("COMPONENT_VERIFY_FAILED: frpc checksum mismatch");
46
27
  }
47
- function frpcDownloadUrls() {
48
- const { platform, arch } = frpcPlatformArch();
49
- return frpcDownloadUrlsForTarget(platform, arch);
50
- }
51
- async function downloadToFile(url, destPath, onProgress) {
52
- const res = await fetch(url);
53
- if (!res.ok || !res.body) throw new Error(`Download failed: ${res.status} ${url}`);
54
- const contentLength = res.headers.get("content-length");
55
- const totalBytes = contentLength && Number.isFinite(Number(contentLength)) ? Number(contentLength) : null;
28
+ async function downloadToFile(url, path, onProgress) {
29
+ const response = await fetch(url, { signal: AbortSignal.timeout(6e4) });
30
+ if (!response.ok || !response.body) throw new Error(`frpc download failed: ${response.status}`);
31
+ const length = Number(response.headers.get("content-length"));
32
+ const totalBytes = length > 0 ? length : null;
33
+ if (totalBytes && totalBytes > MAX_ARCHIVE_BYTES) {
34
+ await response.body.cancel();
35
+ throw new Error("frpc archive exceeds size limit");
36
+ }
56
37
  let bytesReceived = 0;
57
- const report = () => {
38
+ const bounded = new Transform({ transform(chunk, _encoding, callback) {
39
+ bytesReceived += chunk.length;
40
+ if (bytesReceived > MAX_ARCHIVE_BYTES) return callback(/* @__PURE__ */ new Error("frpc archive exceeds size limit"));
58
41
  onProgress?.({
59
42
  phase: "downloading",
60
43
  url,
61
44
  bytesReceived,
62
45
  totalBytes,
63
- percent: totalBytes && totalBytes > 0 ? Math.min(100, Math.round(bytesReceived / totalBytes * 100)) : null
46
+ percent: totalBytes ? Math.min(100, Math.round(bytesReceived / totalBytes * 100)) : null
64
47
  });
65
- };
66
- report();
67
- const nodeStream = Readable.fromWeb(res.body);
68
- nodeStream.on("data", (chunk) => {
69
- bytesReceived += typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.length;
70
- report();
71
- });
72
- await pipeline(nodeStream, createWriteStream(destPath));
73
- report();
48
+ callback(null, chunk);
49
+ } });
50
+ await pipeline(Readable.fromWeb(response.body), bounded, createWriteStream(path, { mode: 384 }));
74
51
  }
75
- /** Set after a successful tunnel start so subprocesses can resolve the same binary. */
76
- function publishFrpcPathForProcess(binPath) {
77
- process.env.XOPC_FRPC_PATH = binPath;
52
+ function publishFrpcPathForProcess(path) {
53
+ process.env.XOPC_FRPC_PATH = path;
78
54
  }
79
- /** Clear runtime frpc path when the tunnel stops (no bundled Electron binary). */
80
55
  function clearFrpcPathForProcess() {
81
56
  delete process.env.XOPC_FRPC_PATH;
82
57
  }
83
- async function ensureFrpcBinary(opts) {
84
- const onProgress = opts?.onProgress;
85
- const binName = `frpc${process.platform === "win32" ? ".exe" : ""}`;
86
- const fromEnv = process.env.XOPC_FRPC_PATH?.trim();
87
- if (fromEnv && existsSync(fromEnv)) return fromEnv;
88
- const cacheDir = resolveBinDir();
89
- mkdirSync(cacheDir, { recursive: true });
58
+ async function ensureFrpcBinary(opts = {}) {
59
+ const platform = opts.platform ?? (process.platform === "win32" ? "windows" : process.platform);
60
+ const arch = opts.arch ?? (process.arch === "x64" ? "amd64" : process.arch);
61
+ const target = `${platform}_${arch}`;
62
+ if (!Object.hasOwn(FRPC_RELEASES, target)) throw new Error(`Unsupported frpc target: ${target}`);
63
+ const release = FRPC_RELEASES[target];
64
+ const fromEnv = !opts.platform && !opts.arch ? process.env.XOPC_FRPC_PATH?.trim() : void 0;
65
+ if (fromEnv) {
66
+ await verifyFrpcDigest(fromEnv, release.binary);
67
+ return fromEnv;
68
+ }
69
+ const cacheDir = join(resolveBinDir(), "frpc", FRPC_VERSION, target);
70
+ mkdirSync(cacheDir, {
71
+ recursive: true,
72
+ mode: 448
73
+ });
74
+ chmodSync(cacheDir, 448);
75
+ const binName = platform === "windows" ? "frpc.exe" : "frpc";
90
76
  const cachePath = join(cacheDir, binName);
91
- if (existsSync(cachePath)) return cachePath;
92
- const tmpBase = join(tmpdir(), `xopc-frpc-${randomBytes(6).toString("hex")}`);
93
- mkdirSync(tmpBase, { recursive: true });
94
- const { platform, arch, folder } = frpcPlatformArch();
95
- const archivePath = join(tmpBase, `frpc${frpcReleaseArchiveExtension(platform)}`);
96
- const urls = frpcDownloadUrls();
97
- let lastErr;
77
+ if (existsSync(cachePath)) try {
78
+ await verifyFrpcDigest(cachePath, release.binary);
79
+ return cachePath;
80
+ } catch {
81
+ log.warn({ target }, "Discarding unverified frpc cache");
82
+ }
83
+ const temporary = mkdtempSync(join(cacheDir, ".download-"));
84
+ const archivePath = join(temporary, "release" + frpcReleaseArchiveExtension(platform));
85
+ const executablePath = join(temporary, binName);
86
+ let lastError;
98
87
  try {
99
- for (const url of urls) try {
100
- log.info({ url }, "Downloading frpc");
101
- await downloadToFile(url, archivePath, onProgress);
102
- onProgress?.({
88
+ for (const url of frpcDownloadUrlsForTarget(platform, arch)) try {
89
+ await downloadToFile(url, archivePath, opts.onProgress);
90
+ await verifyFrpcDigest(archivePath, release.archive);
91
+ opts.onProgress?.({
103
92
  phase: "extracting",
104
- url,
105
- bytesReceived: 0,
106
- totalBytes: null,
107
- percent: null
93
+ url
108
94
  });
109
- await extractFrpcFromReleaseArchive(archivePath, cachePath, folder, nodePlatformForFrpTarget(platform));
110
- if (process.platform !== "win32") chmodSync(cachePath, 493);
95
+ await extractFrpcFromReleaseArchive(archivePath, executablePath, buildFrpcReleaseBasename(platform, arch), nodePlatformForFrpTarget(platform));
96
+ await verifyFrpcDigest(executablePath, release.binary);
97
+ if (platform !== "windows") chmodSync(executablePath, 448);
98
+ renameSync(executablePath, cachePath);
111
99
  return cachePath;
112
- } catch (err) {
113
- lastErr = err;
100
+ } catch (error) {
101
+ lastError = error;
114
102
  log.warn({
115
103
  url,
116
- err
117
- }, "frpc download attempt failed");
104
+ err: error
105
+ }, "Verified frpc download failed");
118
106
  }
119
107
  } finally {
120
- rmSync(tmpBase, {
108
+ rmSync(temporary, {
121
109
  recursive: true,
122
110
  force: true
123
111
  });
124
112
  }
125
- throw new Error(`Failed to download frpc v${FRPC_VERSION} for ${platform}/${arch}: ${lastErr instanceof Error ? lastErr.message : String(lastErr)}`);
113
+ throw new Error(`Failed to obtain verified frpc for ${target}`, { cause: lastError });
126
114
  }
127
115
  //#endregion
128
- export { FRPC_VERSION, buildFrpcReleaseBasename, clearFrpcPathForProcess, ensureFrpcBinary, frpcDownloadUrlsForTarget, publishFrpcPathForProcess };
116
+ export { FRPC_VERSION, buildFrpcReleaseBasename, clearFrpcPathForProcess, ensureFrpcBinary, frpcDownloadUrlsForTarget, publishFrpcPathForProcess, verifyFrpcDigest };
@@ -1,3 +1,4 @@
1
1
  import type { TunnelRegistration } from './tunnel-types.js';
2
2
  export declare function resolveFrpcConfigPath(tunnelId: string): string;
3
- export declare function writeFrpcConfig(registration: TunnelRegistration, localPort: number, localHost?: string, mode?: 'http' | 'https'): string;
3
+ export declare function removeFrpcConfig(tunnelId: string): void;
4
+ export declare function writeFrpcConfig(registration: TunnelRegistration, localPort: number, localHost?: string): string;
@@ -1,34 +1,51 @@
1
1
  import { resolveStateDir } from "../config/paths-state.js";
2
2
  import { init_paths } from "../config/paths.js";
3
3
  import { join } from "node:path";
4
- import { mkdirSync, writeFileSync } from "node:fs";
4
+ import { chmodSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
5
+ import { rootCertificates } from "node:tls";
5
6
  //#region src/tunnel/frpc-config.ts
6
7
  init_paths();
7
8
  function resolveFrpcConfigPath(tunnelId) {
9
+ if (!/^[a-zA-Z0-9_-]+$/.test(tunnelId)) throw new Error("Invalid tunnel id");
8
10
  const tmpDir = join(resolveStateDir(), "tmp");
9
- mkdirSync(tmpDir, { recursive: true });
11
+ mkdirSync(tmpDir, {
12
+ recursive: true,
13
+ mode: 448
14
+ });
15
+ chmodSync(tmpDir, 448);
10
16
  return join(tmpDir, `frpc-${tunnelId}.toml`);
11
17
  }
12
- function writeFrpcConfig(registration, localPort, localHost = "127.0.0.1", mode = "http") {
18
+ function removeFrpcConfig(tunnelId) {
19
+ rmSync(resolveFrpcConfigPath(tunnelId), { force: true });
20
+ }
21
+ function writeFrpcConfig(registration, localPort, localHost = "127.0.0.1") {
13
22
  const configPath = resolveFrpcConfigPath(registration.tunnelId);
23
+ const caPath = join(resolveStateDir(), "tmp", "frp-trusted-roots.pem");
24
+ writeFileSync(caPath, rootCertificates.join("\n"), { mode: 384 });
14
25
  const { frpc } = registration;
26
+ for (const port of [localPort, frpc.serverPort]) if (!Number.isInteger(port) || port < 1 || port > 65535) throw new Error("Invalid tunnel port");
27
+ const quote = JSON.stringify;
15
28
  writeFileSync(configPath, `# Auto-generated by xopc — do not edit
16
- serverAddr = "${frpc.serverAddr}"
29
+ serverAddr = ${quote(frpc.serverAddr)}
17
30
  serverPort = ${frpc.serverPort}
18
- metadatas.token = "${frpc.authToken}"
19
-
31
+ metadatas.token = ${quote(frpc.authToken)}
20
32
  loginFailExit = false
33
+ transport.tls.enable = true
34
+ transport.tls.serverName = ${quote(frpc.serverAddr)}
35
+ transport.tls.trustedCaFile = ${quote(caPath)}
21
36
  transport.heartbeatInterval = 10
22
37
  transport.heartbeatTimeout = 30
23
38
 
24
39
  [[proxies]]
25
- name = "${frpc.proxyName}"
26
- type = "${mode}"
27
- localIP = "${localHost}"
40
+ name = ${quote(frpc.proxyName)}
41
+ type = "http"
42
+ localIP = ${quote(localHost)}
28
43
  localPort = ${localPort}
29
- subdomain = "${registration.subdomain}"
30
- `, "utf8");
44
+ subdomain = ${quote(frpc.subdomain)}
45
+ hostHeaderRewrite = ${quote(new URL(registration.publicUrl).hostname)}
46
+ `, { mode: 384 });
47
+ chmodSync(configPath, 384);
31
48
  return configPath;
32
49
  }
33
50
  //#endregion
34
- export { resolveFrpcConfigPath, writeFrpcConfig };
51
+ export { removeFrpcConfig, resolveFrpcConfigPath, writeFrpcConfig };