@xopcai/xopc 0.0.421 → 0.0.422

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 (279) hide show
  1. package/dist/browser-ext/dist/background.js +184 -2
  2. package/dist/browser-ext/dist/sidepanel.js +9 -0
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{activity-store-CKrylgib.js → activity-store-CvJ9rdwP.js} +1 -1
  6. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-Dv5Rda4y.js → agent-avatar-dicebear-CFP6g4w7.js} +1 -1
  7. package/dist/gateway/static/root/assets/{agent-avatar-display-B1ycycx2.js → agent-avatar-display-BHBe88Gu.js} +2 -2
  8. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-D285zy0S.js → agent-defaults-settings-panel-DlGRuKMv.js} +1 -1
  9. package/dist/gateway/static/root/assets/{agent-plugin-dialog-D3yCqVan.js → agent-plugin-dialog-C_Dm-u6_.js} +1 -1
  10. package/dist/gateway/static/root/assets/{agents-DyAuR3rG.js → agents-BdVJHOiK.js} +3 -3
  11. package/dist/gateway/static/root/assets/{agents-admin-api-CASGzvkW.js → agents-admin-api-Do1Pza0R.js} +1 -1
  12. package/dist/gateway/static/root/assets/{api-Uk05lF9i.js → api-BQv5dLcH.js} +1 -1
  13. package/dist/gateway/static/root/assets/{api-C4LxuNzq.js → api-ONg37_fH.js} +1 -1
  14. package/dist/gateway/static/root/assets/app-link-1j40sJ-z.js +1 -0
  15. package/dist/gateway/static/root/assets/{app-management-settings-panel-CDnZNKHt.js → app-management-settings-panel-B4Wqhf4J.js} +1 -1
  16. package/dist/gateway/static/root/assets/{appearance-settings-CmCF7PZ5.js → appearance-settings-Dm1kRzKL.js} +1 -1
  17. package/dist/gateway/static/root/assets/{apps-page-BR9qoA2P.js → apps-page-D1MMk1P7.js} +1 -1
  18. package/dist/gateway/static/root/assets/{archive-plugin-nuHYYVty.js → archive-plugin-p_yLkyaC.js} +1 -1
  19. package/dist/gateway/static/root/assets/{automation-api-DtJfd1QM.js → automation-api-DQaWBR03.js} +1 -1
  20. package/dist/gateway/static/root/assets/automation-result-state-CO_243JM.js +1 -0
  21. package/dist/gateway/static/root/assets/automation-task-card-D2p9qlYE.js +3 -0
  22. package/dist/gateway/static/root/assets/{automations-page-DM4IdUJh.js → automations-page-Ba64H37d.js} +1 -1
  23. package/dist/gateway/static/root/assets/automations-workspace-BkzC3oIM.js +9 -0
  24. package/dist/gateway/static/root/assets/{binary-plugins-CHCAr8jt.js → binary-plugins-B-6kyqtt.js} +1 -1
  25. package/dist/gateway/static/root/assets/{block-editor-B0v8KxsO.js → block-editor-B5ysJ96n.js} +1 -1
  26. package/dist/gateway/static/root/assets/{browser-automation-inputs-DjUW7PEB.js → browser-automation-inputs-C2A3NIt3.js} +1 -1
  27. package/dist/gateway/static/root/assets/{browser-automations-page-Cf8AoQz1.js → browser-automations-page-CnbXFw1_.js} +1 -1
  28. package/dist/gateway/static/root/assets/{browser-control-api-C6NZgaA1.js → browser-control-api-Aj_seKE9.js} +1 -1
  29. package/dist/gateway/static/root/assets/{browser-settings-page-DV2FNEDf.js → browser-settings-page-C7fxPq_z.js} +1 -1
  30. package/dist/gateway/static/root/assets/{capabilities-CwdjWz2r.js → capabilities-BgtCwC_E.js} +1 -1
  31. package/dist/gateway/static/root/assets/{capabilities-D0-HCZ5J.js → capabilities-DOTgaSgA.js} +1 -1
  32. package/dist/gateway/static/root/assets/{capabilities-page-DwDkritH.js → capabilities-page-m3b9sLFG.js} +2 -2
  33. package/dist/gateway/static/root/assets/{capabilities-settings-panel-mme16Fbp.js → capabilities-settings-panel-pYWZtPeU.js} +3 -3
  34. package/dist/gateway/static/root/assets/{channels-lKFLu8p-.js → channels-DGpRM6pj.js} +1 -1
  35. package/dist/gateway/static/root/assets/{chat-agents-api-l80cvSac.js → chat-agents-api-EvJ_Wvuc.js} +1 -1
  36. package/dist/gateway/static/root/assets/{chat-chart-block-BwP5QXEk.js → chat-chart-block-BQDbHLcw.js} +1 -1
  37. package/dist/gateway/static/root/assets/chat-page-GF9NIuZN.js +72 -0
  38. package/dist/gateway/static/root/assets/{chat-terminal-dock-D2bV9YUL.js → chat-terminal-dock-DHFTGoEp.js} +2 -2
  39. package/dist/gateway/static/root/assets/{command-palette-api-CtapG8ck.js → command-palette-api-DPA_yEuy.js} +1 -1
  40. package/dist/gateway/static/root/assets/{composer-payload-handoff-DYuhKZRC.js → composer-payload-handoff-BTjauSNp.js} +1 -1
  41. package/dist/gateway/static/root/assets/{computer-settings-page-DZtMuihL.js → computer-settings-page-BFSSQfcx.js} +1 -1
  42. package/dist/gateway/static/root/assets/{connected-providers-grid-BQH5k3iC.js → connected-providers-grid-DM2glQN3.js} +1 -1
  43. package/dist/gateway/static/root/assets/{connector-service-page-DrvFdP3G.js → connector-service-page-CFvg58qa.js} +1 -1
  44. package/dist/gateway/static/root/assets/{connectors-api-BzkgVBYC.js → connectors-api-CbC6Yht5.js} +1 -1
  45. package/dist/gateway/static/root/assets/{connectors-page-BtRNVCFy.js → connectors-page-D7pipFHA.js} +1 -1
  46. package/dist/gateway/static/root/assets/date-picker-Dd3MbG0x.js +1 -0
  47. package/dist/gateway/static/root/assets/{dependency-picker-Dh8hPmsT.js → dependency-picker-DcsHg2ml.js} +1 -1
  48. package/dist/gateway/static/root/assets/{desktop-pet-CFz8bqyI.js → desktop-pet-DldzQT2h.js} +1 -1
  49. package/dist/gateway/static/root/assets/{desktop-pet-settings-COaboNn1.js → desktop-pet-settings-CYdI4KxB.js} +1 -1
  50. package/dist/gateway/static/root/assets/{dev-view-store-D8XYHVqG.js → dev-view-store-JiJv585f.js} +1 -1
  51. package/dist/gateway/static/root/assets/device-pairing-wizard-D8cLc41G.js +1 -0
  52. package/dist/gateway/static/root/assets/{directory-picker-path-field-Cjv7rdo3.js → directory-picker-path-field-8WOXv8zw.js} +1 -1
  53. package/dist/gateway/static/root/assets/{discussion-annotation-sync-YvlVw17j.js → discussion-annotation-sync-B-grSe0w.js} +1 -1
  54. package/dist/gateway/static/root/assets/{extension-debug-page-CXx3m5-B.js → extension-debug-page-EEQkTNEu.js} +1 -1
  55. package/dist/gateway/static/root/assets/{extension-iframe-host-CnOdNwbo.js → extension-iframe-host-vlZVeMCY.js} +1 -1
  56. package/dist/gateway/static/root/assets/{extension-marketplace-api-BABmUY2s.js → extension-marketplace-api-_o2In_al.js} +1 -1
  57. package/dist/gateway/static/root/assets/{extension-page-C1nGr4DD.js → extension-page-CPrT111s.js} +1 -1
  58. package/dist/gateway/static/root/assets/{extension-provider-BA0Y2Rvs.js → extension-provider-B2Mf3FBu.js} +1 -1
  59. package/dist/gateway/static/root/assets/{extension-settings-page-QIPI8e7k.js → extension-settings-page-CznJEgWV.js} +1 -1
  60. package/dist/gateway/static/root/assets/{file-preview-surface-BsB7bnFH.js → file-preview-surface-7h8_fZul.js} +1 -1
  61. package/dist/gateway/static/root/assets/{gateway-config-swr-Bt8w0Iio.js → gateway-config-swr-DbbNEOKj.js} +1 -1
  62. package/dist/gateway/static/root/assets/{gateway-realtime-CyCCNUxm.js → gateway-realtime-D20ZrAuM.js} +1 -1
  63. package/dist/gateway/static/root/assets/gateway-realtime-store-C6sMzYDT.js +1 -0
  64. package/dist/gateway/static/root/assets/{gateway-restart-Ty4AzDxa.js → gateway-restart-5ut-lhJm.js} +1 -1
  65. package/dist/gateway/static/root/assets/{gateway-settings-BvKq7vuz.js → gateway-settings-BCf_cibp.js} +1 -1
  66. package/dist/gateway/static/root/assets/{gateway-startup-retry-N3k-C7c2.js → gateway-startup-retry-DlHL0DpH.js} +1 -1
  67. package/dist/gateway/static/root/assets/{global-defaults-api-D8EB2vfY.js → global-defaults-api-CmODomcV.js} +1 -1
  68. package/dist/gateway/static/root/assets/{home-page-eRuAzi58.js → home-page-uz22TRB-.js} +2 -2
  69. package/dist/gateway/static/root/assets/{image-generation-api-C99Fsofm.js → image-generation-api-dzPnpUFu.js} +1 -1
  70. package/dist/gateway/static/root/assets/{imports-page-Cp9RquVb.js → imports-page-ChBoNMyE.js} +1 -1
  71. package/dist/gateway/static/root/assets/index-CSIg7V1A.js +11 -0
  72. package/dist/gateway/static/root/assets/index-Dv8mUlNN.css +1 -0
  73. package/dist/gateway/static/root/assets/{install-connector-dialog-CsoAidXp.js → install-connector-dialog-CNcdQDX0.js} +1 -1
  74. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-DFhOP2aD.js → keyboard-shortcuts-settings-CRbYq2_g.js} +1 -1
  75. package/dist/gateway/static/root/assets/{local-app-workbench-page-DbtU_A-l.js → local-app-workbench-page-04cX5TJu.js} +1 -1
  76. package/dist/gateway/static/root/assets/{local-apps-page-rjhHfLpe.js → local-apps-page-fWM0FEhN.js} +1 -1
  77. package/dist/gateway/static/root/assets/{local-session-drafts-DHM4vWDO.js → local-session-drafts-ClrSe5mH.js} +1 -1
  78. package/dist/gateway/static/root/assets/{locale-store-5Hf8J8-_.js → locale-store-VNjH18Dj.js} +1 -1
  79. package/dist/gateway/static/root/assets/{logs-page-Dx_JIOpF.js → logs-page-6GanGLrm.js} +1 -1
  80. package/dist/gateway/static/root/assets/management-settings-BxD_lc4E.js +1 -0
  81. package/dist/gateway/static/root/assets/{markdown-view-pzSRu7av.js → markdown-view-DLCBYWtx.js} +2 -2
  82. package/dist/gateway/static/root/assets/{media-plugins-3cJuHbO7.js → media-plugins-BvtNwKFb.js} +1 -1
  83. package/dist/gateway/static/root/assets/{messages-uXxg5p54.js → messages-Btr7C0hF.js} +2 -2
  84. package/dist/gateway/static/root/assets/{model-selector-ksLo-5B_.js → model-selector-DYUnp917.js} +1 -1
  85. package/dist/gateway/static/root/assets/{models-hub-cache-DhZng2nF.js → models-hub-cache-_qE7L-_H.js} +1 -1
  86. package/dist/gateway/static/root/assets/{note-detail-panel-B6RbjwJq.js → note-detail-panel-bjRZesmS.js} +3 -3
  87. package/dist/gateway/static/root/assets/note-image-lightbox-D7Jqb75C.js +1 -0
  88. package/dist/gateway/static/root/assets/{notes-api-DocbsBbT.js → notes-api-Bxa11X3a.js} +1 -1
  89. package/dist/gateway/static/root/assets/{notes-page-B7889s6-.js → notes-page-D2QpJ3WZ.js} +1 -1
  90. package/dist/gateway/static/root/assets/{oauth-api-CCFIPbA0.js → oauth-api-DIE4UpP7.js} +1 -1
  91. package/dist/gateway/static/root/assets/{oauth-provider-connect-GxkF0vWJ.js → oauth-provider-connect-B95tiddN.js} +1 -1
  92. package/dist/gateway/static/root/assets/{page-context-capture-button-CvWLVeRA.js → page-context-capture-button-C-QbbwmN.js} +1 -1
  93. package/dist/gateway/static/root/assets/{page-context-draft-CMRDNv4d.js → page-context-draft-BHmOfksL.js} +1 -1
  94. package/dist/gateway/static/root/assets/page-header-store-bPV8_tKL.js +1 -0
  95. package/dist/gateway/static/root/assets/{personal-avatar-CqNJ48Ge.js → personal-avatar-nXrmMfrV.js} +1 -1
  96. package/dist/gateway/static/root/assets/personal-page-BCwlYT3F.js +1 -0
  97. package/dist/gateway/static/root/assets/{personal-settings-panel-DAcl8DU4.js → personal-settings-panel-vkYmXK8h.js} +1 -1
  98. package/dist/gateway/static/root/assets/{phone-dependencies-card-DLWblGj7.js → phone-dependencies-card-CZDAxTWv.js} +1 -1
  99. package/dist/gateway/static/root/assets/{phone-model-picker-ugrT9GJu.js → phone-model-picker-4Snfs8Hq.js} +1 -1
  100. package/dist/gateway/static/root/assets/{phone-settings-page-DIIt7JOE.js → phone-settings-page-D8HperfA.js} +1 -1
  101. package/dist/gateway/static/root/assets/{phone-workspace-store-mawKT5kV.js → phone-workspace-store-Di9R9Ux5.js} +1 -1
  102. package/dist/gateway/static/root/assets/{plugin-details-dialog-BdueMT3q.js → plugin-details-dialog-DJsDu-_8.js} +1 -1
  103. package/dist/gateway/static/root/assets/{preference-select-fields-CmLZNwbm.js → preference-select-fields-C6abaM3k.js} +1 -1
  104. package/dist/gateway/static/root/assets/{product-automation-feedback-DYwhL37Y.js → product-automation-feedback-C74s9Mjz.js} +1 -1
  105. package/dist/gateway/static/root/assets/product-delivery-DRyD9_Xq.js +1 -0
  106. package/dist/gateway/static/root/assets/{product-open-page-B5G4X71t.js → product-open-page-AbDP5w1c.js} +1 -1
  107. package/dist/gateway/static/root/assets/product-preview-content-CktjvFbc.js +1 -0
  108. package/dist/gateway/static/root/assets/product-preview-modal-CzsqLwB4.js +2 -0
  109. package/dist/gateway/static/root/assets/{project-detail-page-CRJb69vP.js → project-detail-page-Cf3tggGP.js} +2 -2
  110. package/dist/gateway/static/root/assets/{project-understanding-D3w8cZEm.js → project-understanding-jmhFbHch.js} +1 -1
  111. package/dist/gateway/static/root/assets/{projects-page-CkifzKjz.js → projects-page-jMgZiFnO.js} +1 -1
  112. package/dist/gateway/static/root/assets/{providers-api-CKFg2PZQ.js → providers-api-CJBYFKAK.js} +1 -1
  113. package/dist/gateway/static/root/assets/{recording-upload-ZkmRf0GR.js → recording-upload-Dl9a5yOV.js} +1 -1
  114. package/dist/gateway/static/root/assets/{registry-api-B1Mh3bNo.js → registry-api-BwkbPUYu.js} +1 -1
  115. package/dist/gateway/static/root/assets/{remote-access-hub-Dw5rG-aA.js → remote-access-hub-CBQ_bOy9.js} +1 -1
  116. package/dist/gateway/static/root/assets/{resource-unavailable-BUWsH3fp.js → resource-unavailable-35wBZxmz.js} +1 -1
  117. package/dist/gateway/static/root/assets/route-preload-BcA6SPeC.js +2 -0
  118. package/dist/gateway/static/root/assets/{runtime-tools-api-BXvn5ImA.js → runtime-tools-api-BF28JDAO.js} +1 -1
  119. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-BALcypHp.js → runtime-tools-settings-panel-Bq2xQ2qd.js} +1 -1
  120. package/dist/gateway/static/root/assets/{service-recommendation-list-CpVUnz89.js → service-recommendation-list-CdaS4MPF.js} +1 -1
  121. package/dist/gateway/static/root/assets/{session-api-VquhIBHI.js → session-api-zJXYlRPt.js} +1 -1
  122. package/dist/gateway/static/root/assets/session-manager-wWxpzSo0.js +23 -0
  123. package/dist/gateway/static/root/assets/{sessions-page-DlvPkE5Y.js → sessions-page-BkjD_dUD.js} +1 -1
  124. package/dist/gateway/static/root/assets/settings-advanced-gate-BUMCEtA_.js +1 -0
  125. package/dist/gateway/static/root/assets/{settings-advanced-section-c9_iZ-46.js → settings-advanced-section-C84IghdL.js} +1 -1
  126. package/dist/gateway/static/root/assets/{settings-mode-store-Dem6-TBe.js → settings-mode-store-CtQBJvbO.js} +1 -1
  127. package/dist/gateway/static/root/assets/{settings-page-B_wNfFQe.js → settings-page-eEIz9InP.js} +1 -1
  128. package/dist/gateway/static/root/assets/{settings-page-header-C8a_oOyw.js → settings-page-header-CsPAYlqV.js} +1 -1
  129. package/dist/gateway/static/root/assets/{settings-page-layout-CTSRWljG.js → settings-page-layout-lPLeJQoV.js} +1 -1
  130. package/dist/gateway/static/root/assets/{setup-status-panel-BNZoqF40.js → setup-status-panel-BSU5WpaE.js} +1 -1
  131. package/dist/gateway/static/root/assets/{share-link-dialog-C5JTTxsy.js → share-link-dialog-NaM6jvIz.js} +1 -1
  132. package/dist/gateway/static/root/assets/{share-preview-page-D-KxzXgm.js → share-preview-page-CHjZn27s.js} +1 -1
  133. package/dist/gateway/static/root/assets/{shares-api-CztKbxdd.js → shares-api-B9rVcV1y.js} +1 -1
  134. package/dist/gateway/static/root/assets/{shares-settings-CzR21j6e.js → shares-settings-5sB15V5v.js} +1 -1
  135. package/dist/gateway/static/root/assets/{skill-api-B7kWl6LK.js → skill-api-D6zVfEuK.js} +1 -1
  136. package/dist/gateway/static/root/assets/{skill-list-api-Cn07P6qZ.js → skill-list-api-SLmTBYF5.js} +1 -1
  137. package/dist/gateway/static/root/assets/{skill-reload-api-Bhl0u16_.js → skill-reload-api-UQkq2orI.js} +1 -1
  138. package/dist/gateway/static/root/assets/{skills-page-BmkuxHZe.js → skills-page-Ca0pYZ4i.js} +1 -1
  139. package/dist/gateway/static/root/assets/{system-settings-panel-Ce6zIcki.js → system-settings-panel-BARWbjRN.js} +1 -1
  140. package/dist/gateway/static/root/assets/{task-detail-page-CysJhG3B.js → task-detail-page-roqAsGue.js} +2 -2
  141. package/dist/gateway/static/root/assets/{task-result-evidence-CGZKMnNo.js → task-result-evidence-Bb1F7nAM.js} +1 -1
  142. package/dist/gateway/static/root/assets/{terminal-panel-store-YwLUkuyV.js → terminal-panel-store-DYDeXXAg.js} +1 -1
  143. package/dist/gateway/static/root/assets/{theme-store-DOJ9tu-j.js → theme-store-DbStcH89.js} +1 -1
  144. package/dist/gateway/static/root/assets/{tracing-settings-page-BplBpTdL.js → tracing-settings-page-YfkNCxbP.js} +1 -1
  145. package/dist/gateway/static/root/assets/{tunnel-api-B5-Ypvqa.js → tunnel-api-BK_ivyIb.js} +1 -1
  146. package/dist/gateway/static/root/assets/{understanding-activity-store-CmwtE8Kd.js → understanding-activity-store-p7Z7oq8z.js} +1 -1
  147. package/dist/gateway/static/root/assets/{understanding-refresh-store-9apSmAVL.js → understanding-refresh-store-D-U6rcwZ.js} +1 -1
  148. package/dist/gateway/static/root/assets/{usage-page-cPbirpXX.js → usage-page-URFSiswS.js} +1 -1
  149. package/dist/gateway/static/root/assets/{use-autosave-B3p2QWaF.js → use-autosave-B7cbumro.js} +1 -1
  150. package/dist/gateway/static/root/assets/{use-composer-attachments-D-AEYC85.js → use-composer-attachments-DAtiwLsE.js} +1 -1
  151. package/dist/gateway/static/root/assets/{use-file-preview-expanded-CO4SC-LX.js → use-file-preview-expanded-B8erpWsX.js} +2 -2
  152. package/dist/gateway/static/root/assets/{use-personal-profile-DocmhC9I.js → use-personal-profile-DDW29nm-.js} +1 -1
  153. package/dist/gateway/static/root/assets/{use-workspace-tree-VraTGKx-.js → use-workspace-tree-DCoTf22f.js} +1 -1
  154. package/dist/gateway/static/root/assets/{user-model-page-DuRALzhe.js → user-model-page-DSV5NkNj.js} +1 -1
  155. package/dist/gateway/static/root/assets/{voice-api-key-field-DbSQHZZW.js → voice-api-key-field-DzYdJZN4.js} +1 -1
  156. package/dist/gateway/static/root/assets/{voice-config-api-D9iNJSvm.js → voice-config-api-wotvT6Hw.js} +1 -1
  157. package/dist/gateway/static/root/assets/{voice-input-shortcut-events-hso9_VvT.js → voice-input-shortcut-events-BI6PuiIB.js} +1 -1
  158. package/dist/gateway/static/root/assets/voice-transcribe-api-DAK9eLRr.js +1 -0
  159. package/dist/gateway/static/root/assets/{work-discovery-overlay-fsL9RJqB.js → work-discovery-overlay-BzmB9Rub.js} +1 -1
  160. package/dist/gateway/static/root/assets/{work-discovery-page-DAQPKVDs.js → work-discovery-page-CmGjxUIT.js} +1 -1
  161. package/dist/gateway/static/root/assets/{working-directory-picker-modal-Ta73QrNw.js → working-directory-picker-modal-B-EHm52-.js} +1 -1
  162. package/dist/gateway/static/root/assets/{workspace-api-CgrcNyBc.js → workspace-api-uhiEMPpK.js} +2 -2
  163. package/dist/gateway/static/root/assets/workspace-editor-agent-store-DrPVyikA.js +1 -0
  164. package/dist/gateway/static/root/assets/{workspace-file-preview-dialog-B7uBuPtA.js → workspace-file-preview-dialog-BDm06MZm.js} +1 -1
  165. package/dist/gateway/static/root/assets/{workspace-open-location-menu-Bi2vRvaQ.js → workspace-open-location-menu-Bv83uoqu.js} +1 -1
  166. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-CCOOBG-7.js → xopc-cloud-account-card-Cd5GdpGL.js} +1 -1
  167. package/dist/gateway/static/root/index.html +84 -84
  168. package/dist/gateway/static/root/notification-sw.js +21 -7
  169. package/dist/package.js +1 -1
  170. package/dist/packages/endpoint-tools-protocol/src/context.js +115 -0
  171. package/dist/packages/endpoint-tools-protocol/src/index.js +4 -0
  172. package/dist/packages/endpoint-tools-protocol/src/location-sharing.js +51 -0
  173. package/dist/packages/gateway-contract/src/gateway-scopes.js +5 -1
  174. package/dist/packages/gateway-contract/src/index.js +2 -0
  175. package/dist/packages/gateway-contract/src/phone-workspace.js +6 -0
  176. package/dist/packages/gateway-contract/src/product-delivery.js +9 -3
  177. package/dist/src/agent/embedded/external-tool-discovery.js +1 -1
  178. package/dist/src/agent/embedded/run-for-session.js +2 -2
  179. package/dist/src/agent/embedded/run-turn.js +72 -9
  180. package/dist/src/agent/embedded/session-runner.js +2 -1
  181. package/dist/src/agent/embedded/types.d.ts +1 -1
  182. package/dist/src/agent/prompt/system-prompt.js +1 -0
  183. package/dist/src/agent/service/direct-turn-helpers.d.ts +0 -7
  184. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  185. package/dist/src/agent/service/process-direct-streaming.js +2 -1
  186. package/dist/src/agent/source-context/device-environment.d.ts +3 -0
  187. package/dist/src/agent/source-context/device-environment.js +38 -0
  188. package/dist/src/agent/source-context/injector.js +2 -1
  189. package/dist/src/agent/tool-manuals/phone.d.ts +1 -1
  190. package/dist/src/agent/tool-manuals/phone.js +1 -1
  191. package/dist/src/agent/tools/automation-tool.js +3 -2
  192. package/dist/src/agent/tools/factory.js +1 -1
  193. package/dist/src/agent/tools/personal-read-tool.js +1 -1
  194. package/dist/src/agent/tools/phone-use-tool.js +46 -2
  195. package/dist/src/agent/tools/xopc-use-tool.js +1 -0
  196. package/dist/src/computer/runtime.d.ts +1 -1
  197. package/dist/src/config/schema.d.ts +1 -0
  198. package/dist/src/endpoint-tools/context-store.d.ts +29 -0
  199. package/dist/src/endpoint-tools/context-store.js +138 -0
  200. package/dist/src/endpoint-tools/location-sharing.d.ts +42 -0
  201. package/dist/src/endpoint-tools/location-sharing.js +203 -0
  202. package/dist/src/endpoint-tools/runtime.d.ts +4 -0
  203. package/dist/src/endpoint-tools/runtime.js +8 -0
  204. package/dist/src/endpoint-tools/turn-context.d.ts +2 -1
  205. package/dist/src/endpoint-tools/turn-context.js +4 -2
  206. package/dist/src/gateway/hono/middleware/auth.js +1 -1
  207. package/dist/src/gateway/hono/routes/devices.js +1 -0
  208. package/dist/src/gateway/hono/routes/endpoint-compatibility.js +4 -0
  209. package/dist/src/gateway/hono/routes/endpoint-environment.d.ts +3 -0
  210. package/dist/src/gateway/hono/routes/endpoint-environment.js +98 -0
  211. package/dist/src/gateway/hono/routes/endpoint-tools.js +1 -0
  212. package/dist/src/gateway/hono/routes/lazy-bundles.js +16 -0
  213. package/dist/src/gateway/hono/routes/location-sharing.d.ts +3 -0
  214. package/dist/src/gateway/hono/routes/location-sharing.js +164 -0
  215. package/dist/src/gateway/hono/routes/phone.js +246 -34
  216. package/dist/src/gateway/hono/routes/session-command-handler.js +1 -1
  217. package/dist/src/gateway/hono/routes/session-input-handler.js +2 -1
  218. package/dist/src/gateway/hono/routes/tunnel.js +10 -0
  219. package/dist/src/gateway/security/gateway-scopes.js +6 -0
  220. package/dist/src/gateway/security/phone-access.d.ts +4 -0
  221. package/dist/src/gateway/security/phone-access.js +20 -0
  222. package/dist/src/gateway/service/agent-runner.js +3 -1
  223. package/dist/src/gateway/service/config-coordinator.d.ts +1 -0
  224. package/dist/src/gateway/service/run-gateway-agent.js +2 -1
  225. package/dist/src/gateway/service/session-input-coordinator.d.ts +3 -0
  226. package/dist/src/gateway/service/session-input-coordinator.js +50 -2
  227. package/dist/src/gateway/service.d.ts +1 -0
  228. package/dist/src/gateway/service.js +8 -0
  229. package/dist/src/gateway/session-reset-service.js +4 -0
  230. package/dist/src/notifications/planner.js +6 -6
  231. package/dist/src/phone/assistance-service.d.ts +6 -0
  232. package/dist/src/phone/assistance-service.js +32 -0
  233. package/dist/src/phone/assistance.d.ts +40 -0
  234. package/dist/src/phone/assistance.js +273 -0
  235. package/dist/src/phone/cloud-phones.d.ts +5 -0
  236. package/dist/src/phone/cloud-phones.js +14 -0
  237. package/dist/src/phone/contracts.d.ts +7 -1
  238. package/dist/src/phone/contracts.js +5 -0
  239. package/dist/src/phone/environment-adapter.d.ts +3 -0
  240. package/dist/src/phone/environment-adapter.js +11 -0
  241. package/dist/src/phone/location-baseline-store.d.ts +9 -0
  242. package/dist/src/phone/location-baseline-store.js +61 -0
  243. package/dist/src/phone/location-environment.d.ts +61 -0
  244. package/dist/src/phone/location-environment.js +157 -0
  245. package/dist/src/phone/model-adapter.js +16 -5
  246. package/dist/src/phone/runtime.d.ts +17 -2
  247. package/dist/src/phone/runtime.js +203 -20
  248. package/dist/src/phone/stream-gateway.d.ts +5 -0
  249. package/dist/src/phone/stream-gateway.js +85 -51
  250. package/dist/src/phone/wuying-location.d.ts +18 -0
  251. package/dist/src/phone/wuying-location.js +86 -0
  252. package/dist/src/storage/sqlite/device-access-repository.d.ts +4 -0
  253. package/dist/src/storage/sqlite/device-access-repository.js +18 -1
  254. package/dist/src/tunnel/broker-client.d.ts +8 -0
  255. package/dist/src/tunnel/broker-client.js +18 -1
  256. package/dist/src/voice/realtime/runtime.js +1 -1
  257. package/package.json +4 -3
  258. package/dist/gateway/static/root/assets/app-link-CytZ5zkp.js +0 -1
  259. package/dist/gateway/static/root/assets/automation-display-BlGt8MAC.js +0 -2
  260. package/dist/gateway/static/root/assets/automation-task-card-Cp3RIw5d.js +0 -2
  261. package/dist/gateway/static/root/assets/automations-workspace-CXLu04I-.js +0 -9
  262. package/dist/gateway/static/root/assets/chat-page-CT3K7lFT.js +0 -71
  263. package/dist/gateway/static/root/assets/date-picker-ByTasrfl.js +0 -1
  264. package/dist/gateway/static/root/assets/device-pairing-wizard-BKMpLdIA.js +0 -1
  265. package/dist/gateway/static/root/assets/gateway-realtime-store-0gmDfPeP.js +0 -1
  266. package/dist/gateway/static/root/assets/index-6vVrWfwM.js +0 -11
  267. package/dist/gateway/static/root/assets/index-DDGK6klk.css +0 -1
  268. package/dist/gateway/static/root/assets/management-settings-CuSzixOw.js +0 -1
  269. package/dist/gateway/static/root/assets/note-image-lightbox-BCjvBqwy.js +0 -1
  270. package/dist/gateway/static/root/assets/page-header-store-reh1es-3.js +0 -1
  271. package/dist/gateway/static/root/assets/personal-page-D95FHaw9.js +0 -1
  272. package/dist/gateway/static/root/assets/product-delivery-BU_H84jL.js +0 -1
  273. package/dist/gateway/static/root/assets/product-preview-content-BUheyLqt.js +0 -1
  274. package/dist/gateway/static/root/assets/product-preview-modal-Cj_Zxu4G.js +0 -2
  275. package/dist/gateway/static/root/assets/route-preload-CRKbVwQ1.js +0 -2
  276. package/dist/gateway/static/root/assets/session-manager-DNMosCtW.js +0 -23
  277. package/dist/gateway/static/root/assets/settings-advanced-gate-Ckc1aCLG.js +0 -1
  278. package/dist/gateway/static/root/assets/voice-transcribe-api-BqIs0jgv.js +0 -1
  279. package/dist/gateway/static/root/assets/workspace-editor-agent-store-Dw6wtadX.js +0 -1
@@ -0,0 +1,3 @@
1
+ import { Hono } from 'hono';
2
+ import type { AuthenticatedRouteDeps } from './deps.js';
3
+ export declare function registerLocationSharingRoutes(parent: Hono, deps: AuthenticatedRouteDeps): void;
@@ -0,0 +1,164 @@
1
+ import { hasGatewayScope } from "../../security/gateway-scopes.js";
2
+ import { locationShareRequestSchema } from "../../../../packages/endpoint-tools-protocol/src/location-sharing.js";
3
+ import { endpointTurnClaimSchema, init_src } from "../../../../packages/endpoint-tools-protocol/src/index.js";
4
+ import { PhoneError, init_contracts } from "../../../phone/contracts.js";
5
+ import { getPhoneRuntime } from "../../../phone/runtime.js";
6
+ import { LocationSharingError } from "../../../endpoint-tools/location-sharing.js";
7
+ import { endpointClaimBelongsToPrincipal } from "../../../endpoint-tools/turn-context.js";
8
+ import { getGatewayPrincipal } from "../../security/gateway-principal.js";
9
+ import { z } from "zod";
10
+ import { Hono } from "hono";
11
+ import { bodyLimit } from "hono/body-limit";
12
+ //#region src/gateway/hono/routes/location-sharing.ts
13
+ init_src();
14
+ init_contracts();
15
+ const root = "/api/user-context/environment/location-shares";
16
+ const originBody = z.strictObject({ origin: endpointTurnClaimSchema });
17
+ function registerLocationSharingRoutes(parent, deps) {
18
+ const app = new Hono();
19
+ app.onError((error, c) => {
20
+ if (error instanceof LocationSharingError || error instanceof PhoneError) return c.json({
21
+ ok: false,
22
+ error: {
23
+ code: error.code,
24
+ message: error.message
25
+ }
26
+ }, 409);
27
+ return c.json({
28
+ ok: false,
29
+ error: {
30
+ code: "LOCATION_UNAVAILABLE",
31
+ message: "Location sharing is unavailable"
32
+ }
33
+ }, 503);
34
+ });
35
+ const runtime = deps.service.endpointTools;
36
+ runtime.locations?.setConsumer({
37
+ apply: (input, signal) => getPhoneRuntime().environment.apply(input, signal),
38
+ clear: (id, phoneId) => getPhoneRuntime().environment.clear(id, phoneId),
39
+ state: (id, phoneId) => {
40
+ const state = getPhoneRuntime().environment.status(phoneId);
41
+ return state.status === "clean" || state.shareId !== id ? "clean" : state.status === "applied" ? "applied" : state.status === "pending" ? "pending" : "cleanup_pending";
42
+ }
43
+ });
44
+ const authorize = (c, origin) => endpointClaimBelongsToPrincipal(runtime.registry, origin.endpointId, getGatewayPrincipal(c)) && runtime.registry.verifyTurnClaim(origin.endpointId, origin.token);
45
+ for (const path of [root, `${root}/*`]) app.use(path, bodyLimit({
46
+ maxSize: 4096,
47
+ onError: (c) => c.json({
48
+ ok: false,
49
+ error: {
50
+ code: "LOCATION_TOO_LARGE",
51
+ message: "Location request exceeds 4 KB"
52
+ }
53
+ }, 413)
54
+ }), async (c, next) => {
55
+ c.header("Cache-Control", "no-store");
56
+ await next();
57
+ });
58
+ app.post(root, async (c) => {
59
+ const parsed = originBody.extend({
60
+ request: locationShareRequestSchema,
61
+ disclosureVersion: z.literal("location-sharing-v1")
62
+ }).safeParse(await c.req.json().catch(() => null));
63
+ if (!parsed.success) return c.json({
64
+ ok: false,
65
+ error: {
66
+ code: "LOCATION_INVALID",
67
+ message: "Invalid location sharing request"
68
+ }
69
+ }, 400);
70
+ if (!authorize(c, parsed.data.origin)) return c.json({
71
+ ok: false,
72
+ error: {
73
+ code: "FORBIDDEN",
74
+ message: "Location source is not accessible"
75
+ }
76
+ }, 403);
77
+ if (!hasGatewayScope(getGatewayPrincipal(c).scopes, "agents.run") || !await deps.service.sessions.getSession(parsed.data.request.conversationId)) return c.json({
78
+ ok: false,
79
+ error: {
80
+ code: "FORBIDDEN",
81
+ message: "Conversation is not accessible"
82
+ }
83
+ }, 403);
84
+ if (parsed.data.request.phoneId) {
85
+ if (!deps.service.currentConfig.phone.enabled) return c.json({
86
+ ok: false,
87
+ error: {
88
+ code: "PHONE_DISABLED",
89
+ message: "Enable Phone Use before sharing location"
90
+ }
91
+ }, 409);
92
+ const phone = getPhoneRuntime().repository.get(parsed.data.request.phoneId);
93
+ if (!phone.enabled || phone.connection?.kind !== "aliyun-adb") return c.json({
94
+ ok: false,
95
+ error: {
96
+ code: "PHONE_ENV_UNSUPPORTED",
97
+ message: "Choose an enabled Alibaba cloud phone"
98
+ }
99
+ }, 409);
100
+ }
101
+ return c.json({
102
+ ok: true,
103
+ payload: runtime.locations.create(parsed.data.origin.endpointId, parsed.data.request)
104
+ }, 201);
105
+ });
106
+ app.get(root, (c) => {
107
+ const endpointId = c.req.query("endpointId") ?? "";
108
+ if (!endpointClaimBelongsToPrincipal(runtime.registry, endpointId, getGatewayPrincipal(c))) return c.json({
109
+ ok: false,
110
+ error: {
111
+ code: "FORBIDDEN",
112
+ message: "Location source is not accessible"
113
+ }
114
+ }, 403);
115
+ return c.json({
116
+ ok: true,
117
+ payload: runtime.locations.list(endpointId, c.req.query("conversationId"))
118
+ });
119
+ });
120
+ app.post(`${root}/:id/samples`, async (c) => {
121
+ const parsed = originBody.extend({
122
+ sequence: z.number().int().positive(),
123
+ sample: z.unknown()
124
+ }).safeParse(await c.req.json().catch(() => null));
125
+ if (!parsed.success) return c.json({
126
+ ok: false,
127
+ error: {
128
+ code: "LOCATION_INVALID",
129
+ message: "Invalid location sample"
130
+ }
131
+ }, 400);
132
+ if (!authorize(c, parsed.data.origin)) return c.json({
133
+ ok: false,
134
+ error: {
135
+ code: "FORBIDDEN",
136
+ message: "Location source is not accessible"
137
+ }
138
+ }, 403);
139
+ return c.json({
140
+ ok: true,
141
+ payload: await runtime.locations.sample(c.req.param("id"), parsed.data.origin.endpointId, {
142
+ sequence: parsed.data.sequence,
143
+ sample: parsed.data.sample
144
+ })
145
+ });
146
+ });
147
+ app.delete(`${root}/:id`, async (c) => {
148
+ const parsed = originBody.safeParse(await c.req.json().catch(() => null));
149
+ if (!parsed.success || !authorize(c, parsed.data.origin)) return c.json({
150
+ ok: false,
151
+ error: {
152
+ code: "FORBIDDEN",
153
+ message: "Location source is not accessible"
154
+ }
155
+ }, 403);
156
+ return c.json({
157
+ ok: true,
158
+ payload: await runtime.locations.revoke(c.req.param("id"), parsed.data.origin.endpointId)
159
+ });
160
+ });
161
+ parent.route("/", app);
162
+ }
163
+ //#endregion
164
+ export { registerLocationSharingRoutes };
@@ -1,16 +1,19 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
+ import { setDevicePhoneAccess } from "../../../storage/sqlite/device-access-repository.js";
3
4
  import { MOCK_PHONE_MODEL, PhoneActionSchema, PhoneConfigSchema, PhoneDeviceSchema, PhoneError, PhoneExecutionModeSchema, PhoneInputSchema, init_contracts } from "../../../phone/contracts.js";
4
5
  import { createConversation, init_conversation_repository } from "../../../storage/sqlite/conversation-repository.js";
5
6
  import { getDefaultAgentId, init_resolve_route } from "../../../routing/resolve-route.js";
6
7
  import { getModelRegistry, init_model_registry } from "../../../providers/model-registry.js";
7
8
  import { init_providers, isProviderConfiguredSync } from "../../../providers/index.js";
8
9
  import { normalizePhoneAppAccess, phoneAppAccess } from "../../../phone/app-access.js";
10
+ import { cancelPhoneAssistance, pendingPhoneAssistance, phoneAssistance, phoneAssistanceReport } from "../../../phone/assistance.js";
9
11
  import { resolveAdbPath } from "../../../phone/adb-driver.js";
10
12
  import { createPhoneModel, phoneModelProfile } from "../../../phone/model-adapter.js";
11
13
  import { getPhoneRuntime, phoneExecutionContext } from "../../../phone/runtime.js";
12
14
  import { registerPhoneSetupRoutes } from "./phone-setup.js";
13
15
  import { getGatewayPrincipal } from "../../security/gateway-principal.js";
16
+ import { authorizePhoneAccess, phoneAdministrator } from "../../security/phone-access.js";
14
17
  import { registerPhoneWirelessRoutes } from "./phone-wireless.js";
15
18
  import { randomUUID } from "node:crypto";
16
19
  import { z } from "zod";
@@ -51,20 +54,118 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
51
54
  const { service, strictRateLimitMiddleware } = deps;
52
55
  app.use("/api/phone/*", async (c, next) => {
53
56
  const principal = getGatewayPrincipal(c);
54
- if (principal.kind !== "owner" && principal.kind !== "trusted-proxy" || !principal.scopes.includes("gateway.admin")) return c.json({
55
- ok: false,
56
- error: {
57
- code: "PHONE_ADMIN_REQUIRED",
58
- message: "Phone settings require Gateway administrator access"
57
+ if (!phoneAdministrator(principal)) {
58
+ const path = c.req.path;
59
+ const conversation = /^\/api\/phone\/conversations\/([0-9a-f-]{36})(?:\/(summary|[0-9a-f-]{36}\/(?:frame|video-ticket|control)))?$/i.test(path);
60
+ const summary = path.endsWith("/summary") && c.req.method === "GET";
61
+ if (!(conversation && (c.req.method === "GET" || c.req.method === "POST" && /\/(video-ticket|control)$/.test(path))) || principal.kind !== "device" || !principal.scopes.includes("sessions.read")) throw new PhoneError("PHONE_ADMIN_REQUIRED", "Phone management requires administrator access", 403);
62
+ if (!summary) authorizePhoneAccess(principal, path.endsWith("/control"));
63
+ }
64
+ await next();
65
+ if (principal.kind === "device" && c.res.status === 200 && c.res.headers.get("Content-Type")?.includes("application/json")) {
66
+ const body = await c.res.clone().json();
67
+ const report = body.payload?.report;
68
+ if (report && body.payload) {
69
+ const { sessionId, deviceId, deviceName, status, mode, controlOwner, controlEpoch, handoff, assistanceId, reconnectRequired, stopReason, currentAction, updatedAt } = report;
70
+ body.payload = {
71
+ ownControl: body.payload.ownControl,
72
+ textInput: body.payload.textInput,
73
+ report: {
74
+ sessionId,
75
+ deviceId,
76
+ deviceName,
77
+ status,
78
+ mode,
79
+ controlOwner,
80
+ controlEpoch,
81
+ handoff,
82
+ assistanceId,
83
+ reconnectRequired,
84
+ stopReason,
85
+ currentAction,
86
+ updatedAt
87
+ }
88
+ };
89
+ c.res = c.json(body);
90
+ c.header("Cache-Control", "no-store");
91
+ }
92
+ }
93
+ });
94
+ app.patch("/api/phone/device-access/:id", strictRateLimitMiddleware, async (c) => {
95
+ const actor = getGatewayPrincipal(c);
96
+ if (actor.kind === "device" || !actor.scopes.includes("gateway.admin")) return c.json({ ok: false }, 403);
97
+ const input = z.object({ access: z.enum([
98
+ "none",
99
+ "view",
100
+ "control"
101
+ ]) }).strict().safeParse(await c.req.json().catch(() => null));
102
+ if (!input.success) return c.json({ ok: false }, 400);
103
+ const device = setDevicePhoneAccess(c.req.param("id"), input.data.access);
104
+ if (!device) return c.json({ ok: false }, 404);
105
+ deps.service.phoneStreams.disconnectPrincipal(device.id);
106
+ c.header("Cache-Control", "no-store");
107
+ return c.json({
108
+ ok: true,
109
+ payload: {
110
+ id: device.id,
111
+ scopes: device.scopes
59
112
  }
60
- }, 403);
61
- return next();
113
+ });
62
114
  });
63
115
  registerPhoneSetupRoutes(app, deps);
64
116
  registerPhoneWirelessRoutes(app, deps, runtime);
117
+ app.get("/api/phone/devices/:id/environment", (c) => {
118
+ const id = z.uuid().parse(c.req.param("id"));
119
+ const device = runtime.repository.get(id);
120
+ c.header("Cache-Control", "no-store");
121
+ return c.json({
122
+ ok: true,
123
+ payload: {
124
+ ...runtime.environment.status(id),
125
+ supported: device.connection?.kind === "aliyun-adb"
126
+ }
127
+ });
128
+ });
129
+ app.post("/api/phone/devices/:id/environment/cleanup", strictRateLimitMiddleware, async (c) => {
130
+ const id = z.uuid().parse(c.req.param("id"));
131
+ runtime.repository.get(id);
132
+ const state = runtime.environment.status(id);
133
+ const cleared = state.shareId ? await runtime.environment.clear(state.shareId, id) : true;
134
+ return c.json({
135
+ ok: true,
136
+ payload: {
137
+ cleared,
138
+ ...runtime.environment.status(id)
139
+ }
140
+ });
141
+ });
142
+ const connectionReports = () => {
143
+ const reports = runtime.reports().filter((report) => report.status !== "closed");
144
+ for (const wait of pendingPhoneAssistance()) if (!reports.some((report) => report.deviceId === wait.checkpoint.report.deviceId)) reports.push(phoneAssistanceReport(wait));
145
+ return reports.map((report) => {
146
+ const wait = phoneAssistance(report.owner);
147
+ return wait && ["open", "queued"].includes(wait.status) ? {
148
+ ...report,
149
+ assistanceId: wait.id,
150
+ ...wait.status === "open" && report.controlOwner !== "human" ? { status: "needs_user" } : {}
151
+ } : report;
152
+ });
153
+ };
154
+ const liveStatus = (owner, id, context, client) => {
155
+ const state = runtime.liveStatus(owner, id, context, client);
156
+ const wait = phoneAssistance(owner);
157
+ return wait && ["open", "queued"].includes(wait.status) ? {
158
+ ...state,
159
+ report: {
160
+ ...state.report,
161
+ assistanceId: wait.id,
162
+ ...wait.status === "open" && state.report.controlOwner !== "human" ? { status: "needs_user" } : {}
163
+ }
164
+ } : state;
165
+ };
65
166
  app.get("/api/phone/connections", async (c) => {
66
167
  c.header("Cache-Control", "no-store");
67
- const payload = await Promise.all(runtime.reports().filter((report) => report.status !== "closed").map(async (report) => {
168
+ const payload = await Promise.all(connectionReports().map(async (report) => {
68
169
  const source = report.sourceConversationId ?? report.owner;
69
170
  const conversation = /^[\da-f]{8}-[\da-f-]{27}$/i.test(source) ? await service.sessions.getSession(source) : void 0;
70
171
  const { facts: _facts, readings: _readings, steps: _steps, task: _task, feedback: _feedback, ...metadata } = report;
@@ -235,6 +336,7 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
235
336
  ...patch.allowedApps && patch.appAccess === void 0 ? { appAccess: "selected" } : {}
236
337
  });
237
338
  await runtime.stopDevice(id);
339
+ if (previous.connection) await runtime.environment.recover(id, true);
238
340
  return c.json({
239
341
  ok: true,
240
342
  payload: runtime.repository.save(next, id)
@@ -244,6 +346,7 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
244
346
  const id = c.req.param("id");
245
347
  const device = runtime.repository.get(id);
246
348
  await runtime.stopDevice(id);
349
+ if (device.connection) await runtime.environment.recover(id, true);
247
350
  await runtime.cloud.remove(device);
248
351
  runtime.repository.remove(id);
249
352
  return c.json({ ok: true });
@@ -332,6 +435,7 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
332
435
  clientId: liveClient,
333
436
  operationId: z.string().uuid(),
334
437
  epoch: z.number().int().positive(),
438
+ assistanceId: z.string().uuid().optional(),
335
439
  op: z.enum([
336
440
  "takeover",
337
441
  "release",
@@ -342,6 +446,7 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
342
446
  "input",
343
447
  "recover"
344
448
  ]),
449
+ expectedTranscriptId: z.uuid().optional(),
345
450
  frameSeq: z.number().int().positive().optional(),
346
451
  geometry: z.number().int().positive().optional(),
347
452
  action: PhoneActionSchema.optional()
@@ -349,20 +454,22 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
349
454
  async function conversationPhone(conversationId, requestedSessionId) {
350
455
  if (conversationId.startsWith("device:")) {
351
456
  const deviceId = z.string().uuid().parse(conversationId.slice(7));
352
- const report = runtime.reports().find((report) => report.deviceId === deviceId && report.status !== "closed");
457
+ const report = connectionReports().find((report) => report.deviceId === deviceId);
353
458
  if (!report || requestedSessionId && report.sessionId !== requestedSessionId) throw new PhoneError("PHONE_SESSION_NOT_FOUND", "Phone connection changed. Refresh the phone panel.", 404);
354
459
  const conversation = /^[\da-f]{8}-[\da-f-]{27}$/i.test(report.owner) ? await service.sessions.getSession(report.owner) : void 0;
355
460
  return {
356
461
  owner: report.owner,
357
462
  report,
358
463
  transcriptId: conversation?.transcriptId,
359
- context: runtime.deviceContext(deviceId, service.currentConfig)
464
+ context: runtime.status(report.owner) && runtime.status(report.owner)?.status !== "closed" ? runtime.deviceContext(deviceId, service.currentConfig) : phoneExecutionContext(service.currentConfig, report.agentId)
360
465
  };
361
466
  }
362
467
  z.string().uuid().parse(conversationId);
363
468
  const conversation = await service.sessions.getSession(conversationId);
364
469
  if (!conversation) throw new PhoneError("PHONE_CONVERSATION_NOT_FOUND", "Conversation not found", 404);
365
- const report = runtime.status(conversationId);
470
+ const connected = runtime.status(conversationId);
471
+ const wait = phoneAssistance(conversationId);
472
+ const report = connected && connected.status !== "closed" ? connected : wait && ["open", "queued"].includes(wait.status) ? phoneAssistanceReport(wait) : void 0;
366
473
  if (requestedSessionId && report?.sessionId !== requestedSessionId) throw new PhoneError("PHONE_SESSION_NOT_FOUND", "Phone session not found", 404);
367
474
  if (report && report.agentId !== conversation.agentId) throw new PhoneError("PHONE_ACCESS_CHANGED", "Conversation Agent changed", 403);
368
475
  return {
@@ -372,6 +479,41 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
372
479
  context: phoneExecutionContext(service.currentConfig, conversation.agentId)
373
480
  };
374
481
  }
482
+ app.get("/api/phone/conversations/:conversationId/summary", async (c) => {
483
+ const principal = getGatewayPrincipal(c);
484
+ const id = c.req.param("conversationId");
485
+ const { report, transcriptId } = await conversationPhone(id);
486
+ let access = "none";
487
+ try {
488
+ authorizePhoneAccess(principal);
489
+ access = "view";
490
+ } catch {}
491
+ if (access === "view") try {
492
+ authorizePhoneAccess(principal, true);
493
+ access = "control";
494
+ } catch {}
495
+ const payload = {
496
+ available: Boolean(report),
497
+ access,
498
+ needsUser: Boolean(report && access !== "none" && report.status === "needs_user")
499
+ };
500
+ if (report && access !== "none") {
501
+ payload.deviceName = report.deviceName;
502
+ payload.taskState = report.status;
503
+ payload.updatedAt = report.updatedAt;
504
+ if (transcriptId && report.deviceId) payload.binding = {
505
+ conversationId: id,
506
+ transcriptId,
507
+ phoneSessionId: report.sessionId,
508
+ phoneDeviceId: report.deviceId
509
+ };
510
+ }
511
+ c.header("Cache-Control", "no-store");
512
+ return c.json({
513
+ ok: true,
514
+ payload
515
+ });
516
+ });
375
517
  app.get("/api/phone/conversations/:conversationId", async (c) => {
376
518
  let owner = c.req.param("conversationId");
377
519
  const client = liveClient.parse(c.req.query("clientId"));
@@ -380,7 +522,11 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
380
522
  c.header("Cache-Control", "no-store");
381
523
  return c.json({
382
524
  ok: true,
383
- payload: report ? runtime.liveStatus(owner, report.sessionId, context, `${getGatewayPrincipal(c).principalId}:${client}${c.req.param("conversationId").startsWith("device:") ? ":viewer" : ""}`) : null
525
+ payload: report ? runtime.status(owner)?.status !== "closed" && runtime.status(owner) ? liveStatus(owner, report.sessionId, context, `${getGatewayPrincipal(c).principalId}:${client}${c.req.param("conversationId").startsWith("device:") ? ":viewer" : ""}`) : {
526
+ report,
527
+ ownControl: false,
528
+ frame: null
529
+ } : null
384
530
  });
385
531
  });
386
532
  app.post("/api/phone/conversations/:conversationId/:sessionId/execution-mode", strictRateLimitMiddleware, async (c) => {
@@ -397,15 +543,23 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
397
543
  c.header("Cache-Control", "no-store");
398
544
  return c.json({
399
545
  ok: true,
400
- payload: runtime.liveStatus(owner, c.req.param("sessionId"), context, `${getGatewayPrincipal(c).principalId}:${input.clientId}`)
546
+ payload: liveStatus(owner, c.req.param("sessionId"), context, `${getGatewayPrincipal(c).principalId}:${input.clientId}`)
401
547
  });
402
548
  });
403
549
  app.get("/api/phone/conversations/:conversationId/:sessionId/frame", async (c) => {
404
550
  let owner = c.req.param("conversationId");
405
551
  const id = c.req.param("sessionId");
406
- const { context, owner: resolvedOwner } = await conversationPhone(owner, id);
552
+ const { context, transcriptId, owner: resolvedOwner } = await conversationPhone(owner, id);
407
553
  owner = resolvedOwner;
554
+ const principal = getGatewayPrincipal(c);
555
+ if (principal.kind === "device" && c.req.query("expectedTranscriptId") !== transcriptId) throw new PhoneError("PHONE_BINDING_CHANGED", "Conversation changed", 409);
408
556
  const frame = await runtime.liveFrame(owner, id, context, c.req.raw.signal);
557
+ try {
558
+ authorizePhoneAccess(principal);
559
+ } catch (error) {
560
+ frame.frame.fill(0);
561
+ throw error;
562
+ }
409
563
  c.header("Cache-Control", "no-store");
410
564
  c.header("Content-Type", "image/png");
411
565
  c.header("X-Content-Type-Options", "nosniff");
@@ -421,15 +575,32 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
421
575
  app.post("/api/phone/conversations/:conversationId/:sessionId/video-ticket", strictRateLimitMiddleware, async (c) => {
422
576
  const address = c.req.param("conversationId");
423
577
  const id = c.req.param("sessionId");
424
- const { clientId } = z.object({ clientId: liveClient }).strict().parse(await c.req.json());
425
- await conversationPhone(address, id);
578
+ const { clientId, purpose, expectedTranscriptId, epoch } = z.object({
579
+ clientId: liveClient,
580
+ purpose: z.enum(["view", "control"]).optional(),
581
+ expectedTranscriptId: z.uuid().optional(),
582
+ epoch: z.number().int().positive().optional()
583
+ }).strict().parse(await c.req.json());
584
+ const initial = await conversationPhone(address, id);
426
585
  const principal = getGatewayPrincipal(c);
427
- const client = `${principal.principalId}:${clientId}${c.req.param("conversationId").startsWith("device:") ? ":viewer" : ""}`;
586
+ const client = `${principal.principalId}:${clientId}${address.startsWith("device:") || principal.kind === "device" && purpose !== "control" ? ":viewer" : ""}`;
587
+ const native = principal.kind === "device";
588
+ const interactive = native ? purpose === "control" : purpose !== "view" && !address.startsWith("device:");
589
+ if (native && (!expectedTranscriptId || expectedTranscriptId !== initial.transcriptId)) throw new PhoneError("PHONE_BINDING_CHANGED", "Conversation changed; refresh the phone", 409);
428
590
  const validate = async () => {
591
+ authorizePhoneAccess(principal, interactive);
429
592
  const resolved = await conversationPhone(address, id);
430
- runtime.liveStatus(resolved.owner, id, resolved.context, client);
593
+ if (resolved.transcriptId !== initial.transcriptId) throw new PhoneError("PHONE_BINDING_CHANGED", "Conversation changed", 409);
594
+ const state = runtime.liveStatus(resolved.owner, id, resolved.context, client);
595
+ if (native && interactive && (!state.ownControl || epoch !== state.report.controlEpoch)) throw new PhoneError("PHONE_CONTROL_CHANGED", "Take over before opening an interactive stream", 409);
431
596
  };
597
+ if (native) await validate();
432
598
  const issued = service.phoneStreams.issue({
599
+ ...native ? {
600
+ deviceId: principal.deviceId,
601
+ readOnly: !interactive,
602
+ inputEpoch: interactive ? epoch : void 0
603
+ } : { readOnly: !interactive },
433
604
  origin: new URL(c.req.url).origin,
434
605
  principal: principal.principalId,
435
606
  client,
@@ -439,8 +610,7 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
439
610
  return runtime.liveVideo(resolved.owner, id, resolved.context);
440
611
  },
441
612
  disconnect: async () => {
442
- const resolved = await conversationPhone(address, id).catch(() => void 0);
443
- if (resolved) await runtime.disconnectVideo(resolved.owner, id, client);
613
+ await runtime.disconnectVideo(initial.owner, id, client, native ? epoch : void 0);
444
614
  }
445
615
  });
446
616
  c.header("Cache-Control", "no-store");
@@ -457,22 +627,64 @@ function registerPhoneRoutes(parent, deps, runtime = getPhoneRuntime()) {
457
627
  if (c.req.param("conversationId").startsWith("device:")) throw new PhoneError("PHONE_OBSERVE_ONLY", "The global phone viewer is read only. Use the controlling conversation for input.", 403);
458
628
  let owner = c.req.param("conversationId");
459
629
  const id = c.req.param("sessionId");
460
- const { context, transcriptId, owner: resolvedOwner } = await conversationPhone(owner, id);
630
+ const actor = getGatewayPrincipal(c);
631
+ const { clientId, assistanceId, expectedTranscriptId, ...input } = liveControlInput.parse(await c.req.json());
632
+ const requestedWait = phoneAssistance(owner);
633
+ const allowRecovery = assistanceId && requestedWait?.id === assistanceId && requestedWait.checkpoint.report.sessionId === id && ["takeover", "handback"].includes(input.op);
634
+ const { context, transcriptId, owner: resolvedOwner } = await conversationPhone(owner, allowRecovery ? void 0 : id);
461
635
  owner = resolvedOwner;
462
- const { clientId, ...input } = liveControlInput.parse(await c.req.json());
463
- const result = await runtime.liveControl(owner, id, context, `${getGatewayPrincipal(c).principalId}:${clientId}`, input);
464
- if (transcriptId && input.op === "handback" && result.resumeTurnRequired && !service.sessions.getActiveRun(owner).active) {
465
- if (!(await service.submitSessionInput({
466
- conversationId: owner,
467
- expectedTranscriptId: transcriptId,
468
- clientMessageId: input.operationId,
469
- delivery: "next",
470
- content: "手机已交还,请先确认当前页面,继续未完成的任务;已完成的步骤不要重复,结束后释放操作权,保持手机连接。",
471
- origin: {
472
- type: "system",
473
- source: "internal"
636
+ if (getGatewayPrincipal(c).kind === "device" && (!expectedTranscriptId || expectedTranscriptId !== transcriptId)) throw new PhoneError("PHONE_BINDING_CHANGED", "Conversation changed; refresh the phone", 409);
637
+ const wait = phoneAssistance(owner);
638
+ if (assistanceId && (!wait || wait.id !== assistanceId || ![
639
+ "open",
640
+ "queued",
641
+ "resuming",
642
+ "completed"
643
+ ].includes(wait.status))) throw new PhoneError("PHONE_ASSISTANCE_CHANGED", "The phone task changed. Refresh before continuing.", 409);
644
+ if (input.op === "handback" && assistanceId && wait?.status !== "open") {
645
+ service.resumePhoneAssistance(owner, assistanceId);
646
+ return c.json({
647
+ ok: true,
648
+ payload: runtime.status(owner) && runtime.status(owner)?.status !== "closed" ? liveStatus(owner, runtime.status(owner).sessionId, context, `${getGatewayPrincipal(c).principalId}:${clientId}`) : {
649
+ report: phoneAssistanceReport(wait),
650
+ ownControl: false,
651
+ frame: null
474
652
  }
475
- })).ok) throw new PhoneError("PHONE_RESUME_FAILED", "Phone control returned. Send Continue in chat to resume the task.", 409);
653
+ });
654
+ }
655
+ let sessionId = id;
656
+ if (wait?.status === "open" && ["takeover", "handback"].includes(input.op)) {
657
+ const restored = await runtime.restoreAssistance(wait.checkpoint, context, c.req.raw.signal, wait.id);
658
+ if (restored.sessionId !== id) {
659
+ sessionId = restored.sessionId;
660
+ input.epoch = restored.controlEpoch;
661
+ }
662
+ }
663
+ let result;
664
+ try {
665
+ const current = runtime.status(owner);
666
+ result = input.op === "handback" && wait?.status === "open" && current?.status === "ready" && current.controlOwner === "agent" ? liveStatus(owner, sessionId, context, `${getGatewayPrincipal(c).principalId}:${clientId}`) : await runtime.liveControl(owner, sessionId, context, `${getGatewayPrincipal(c).principalId}:${clientId}`, input, () => authorizePhoneAccess(actor, true));
667
+ } catch (error) {
668
+ const latest = phoneAssistance(owner);
669
+ if (input.op !== "handback" || !wait || latest?.id !== wait.id || latest.status === "open" || !(error instanceof PhoneError) || !["PHONE_CONTROL_CHANGED", "PHONE_CONTROL_BUSY"].includes(error.code)) throw error;
670
+ result = liveStatus(owner, sessionId, context, `${getGatewayPrincipal(c).principalId}:${clientId}`);
671
+ }
672
+ if (input.op === "cancel") cancelPhoneAssistance(owner);
673
+ if (input.op === "handback") {
674
+ if (wait?.status === "open") service.resumePhoneAssistance(owner, wait.id);
675
+ else if (transcriptId && result.resumeTurnRequired) {
676
+ if (!(await service.submitSessionInput({
677
+ conversationId: owner,
678
+ expectedTranscriptId: transcriptId,
679
+ clientMessageId: `phone-handback:${sessionId}:${input.epoch}`,
680
+ delivery: "next",
681
+ content: "手机已交还,请先确认当前页面,继续未完成的任务;已完成的步骤不要重复。",
682
+ origin: {
683
+ type: "system",
684
+ source: "internal"
685
+ }
686
+ })).ok) throw new PhoneError("PHONE_RESUME_FAILED", "Phone control returned. Send Continue in chat to resume the task.", 409);
687
+ }
476
688
  }
477
689
  c.header("Cache-Control", "no-store");
478
690
  return c.json({
@@ -114,7 +114,7 @@ async function handleSessionCommand(c, deps, materialize = false) {
114
114
  const payload = await receiveSessionCommand(deps.service, id.data, principal.principalId, command, async () => {
115
115
  if (!("input" in command)) return [];
116
116
  const endpoint = command.origin.type === "endpoint" ? deps.service.endpointTools.registry.get(command.origin.endpointId) : void 0;
117
- const contexts = endpoint ? [deviceTurnSourceContext(endpoint, command.input.endpointContext)] : [];
117
+ const contexts = endpoint ? [deviceTurnSourceContext(endpoint, command.input.endpointContext, deps.service.endpointTools.contexts?.view(endpoint.endpointId), deps.service.endpointTools.locations?.list(endpoint.endpointId, id.data))] : [];
118
118
  contexts.push(...(command.input.browserContexts ?? []).map(browserPageContextToAgentContext));
119
119
  if (command.input.appContext) contexts.push(await deps.service.prepareSessionAppContext(command.input.appContext, principal, id.data, command.clientMessageId));
120
120
  return contexts;
@@ -193,7 +193,8 @@ async function submitSessionInput(c, deps, conversationId, options) {
193
193
  }, 409);
194
194
  }
195
195
  }
196
- const sourceContexts = [deviceTurnSourceContext(deps.service.endpointTools.registry.get(origin.data.endpointId), environment.data), ...browserContexts.data.map(browserPageContextToAgentContext)];
196
+ const endpoint = deps.service.endpointTools.registry.get(origin.data.endpointId);
197
+ const sourceContexts = [deviceTurnSourceContext(endpoint, environment.data, deps.service.endpointTools.contexts?.view(endpoint.endpointId), deps.service.endpointTools.locations?.list(endpoint.endpointId, conversationId)), ...browserContexts.data.map(browserPageContextToAgentContext)];
197
198
  if (body.appContext !== void 0) try {
198
199
  sourceContexts.push(await deps.service.prepareSessionAppContext(body.appContext, getGatewayPrincipal(c), conversationId, typeof body.clientMessageId === "string" ? body.clientMessageId.trim() : ""));
199
200
  } catch (error) {
@@ -1,6 +1,7 @@
1
1
  import { createLogger } from "../../../utils/logger/index.js";
2
2
  import { init_logger } from "../../../utils/logger.js";
3
3
  import { init_public_url, validatePublicUrl } from "../../../config/public-url.js";
4
+ import { TunnelRecoveryProofRejectedError, TunnelRegistrationKeyRejectedError } from "../../../tunnel/broker-client.js";
4
5
  import { TUNNEL_REGISTRATION_SECRET_REQUIRED_CODE, TunnelRegistrationSecretError, getTunnelRegistrationSecretMeta, readTunnelRegistrationSecretFromConfigOnly, resolveTunnelBrokerUrl } from "../../../tunnel/env.js";
5
6
  import { logTunnelAudit } from "../../../tunnel/tunnel-audit.js";
6
7
  import { getTunnelService, hashGatewayToken } from "../../../tunnel/tunnel-service.js";
@@ -258,6 +259,15 @@ function registerTunnelRoutes(authenticated, deps) {
258
259
  });
259
260
  } catch (err) {
260
261
  const message = err instanceof Error ? err.message : String(err);
262
+ log.warn({
263
+ err,
264
+ errorMessage: message,
265
+ phase: "tunnel_start"
266
+ }, `Tunnel start failed: ${message}`);
267
+ if (err instanceof TunnelRegistrationKeyRejectedError || err instanceof TunnelRecoveryProofRejectedError) return c.json({
268
+ error: message,
269
+ code: err.code
270
+ }, 409);
261
271
  if (err instanceof TunnelRegistrationSecretError) return c.json({
262
272
  error: message,
263
273
  code: TUNNEL_REGISTRATION_SECRET_REQUIRED_CODE
@@ -17,7 +17,13 @@ function requiredGatewayScope(method, path) {
17
17
  if (path === "/api/realtime/tickets" || path.startsWith("/api/status")) return "gateway.status";
18
18
  if (path === "/api/device-auth/refresh" || path === "/api/devices/me") return "device.self";
19
19
  if (path.startsWith("/api/devices/me/push")) return "notifications.self";
20
+ if (/^\/api\/phone\/conversations\/[^/]+\/summary$/.test(path) && method === "GET") return "sessions.read";
21
+ if (/^\/api\/phone\/conversations\/[^/]+$/.test(path) && method === "GET") return "phone.view";
22
+ if (/^\/api\/phone\/conversations\/[^/]+\/[^/]+\/frame$/.test(path) && method === "GET") return "phone.view";
23
+ if (/^\/api\/phone\/conversations\/[^/]+\/[^/]+\/video-ticket$/.test(path) && method === "POST") return "phone.view";
24
+ if (/^\/api\/phone\/conversations\/[^/]+\/[^/]+\/control$/.test(path) && method === "POST") return "phone.control";
20
25
  if (path.startsWith("/api/endpoint-tools")) return "device.self";
26
+ if (path === "/api/user-context/environment" || path.startsWith("/api/user-context/environment/")) return "device.self";
21
27
  if (path === "/api/personal-agent/activity") return "tasks.read";
22
28
  if (path === "/api/personal-agent" || path.startsWith("/api/personal-agent/")) return methodScope(method, "sessions.read", "sessions.write");
23
29
  if (path.startsWith("/api/browser/recordings/")) return "device.self";
@@ -0,0 +1,4 @@
1
+ import type { GatewayPrincipal } from './gateway-principal.js';
2
+ export declare function phoneAdministrator(principal: GatewayPrincipal): boolean;
3
+ /** Reload mutable device grants even for already established streams. */
4
+ export declare function authorizePhoneAccess(principal: GatewayPrincipal, control?: boolean): void;