@xopcai/xopc 0.0.413 → 0.0.414

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 (204) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BT6oqCMD.js → agent-avatar-dicebear-ClobpdW3.js} +1 -1
  4. package/dist/gateway/static/root/assets/{agent-defaults-settings-panel-BFmRRD_4.js → agent-defaults-settings-panel-mf0jgEPE.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-CKhZ4UYQ.js +77 -0
  6. package/dist/gateway/static/root/assets/{app-management-settings-panel-BdCgtTfT.js → app-management-settings-panel-CLunLNGp.js} +1 -1
  7. package/dist/gateway/static/root/assets/app-window-DXFNqt_0.js +1 -0
  8. package/dist/gateway/static/root/assets/{appearance-settings-C3-hCFlF.js → appearance-settings-DBEgoE9g.js} +1 -1
  9. package/dist/gateway/static/root/assets/apps-page-BZ_MaQJf.js +1 -0
  10. package/dist/gateway/static/root/assets/{archive-plugin-BviFGCy4.js → archive-plugin-JElK4Goq.js} +1 -1
  11. package/dist/gateway/static/root/assets/{automations-page-CfzazXE5.js → automations-page-CZ0UqwyU.js} +1 -1
  12. package/dist/gateway/static/root/assets/automations-workspace-CHUDHNVL.js +8 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-Dp-gtJEk.js → binary-plugins-CXFawow6.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-D-DEPdpi.js → block-editor-BoduwSYI.js} +30 -30
  15. package/dist/gateway/static/root/assets/browser-automations-page-DStDm9y1.js +3 -0
  16. package/dist/gateway/static/root/assets/browser-settings-page-6I4oetKt.js +3 -0
  17. package/dist/gateway/static/root/assets/capabilities-page-C-EecWbS.js +2 -0
  18. package/dist/gateway/static/root/assets/capabilities-settings-panel-BQoCPk3x.js +8 -0
  19. package/dist/gateway/static/root/assets/{capability-header-actions-CP2fI9Fe.js → capability-header-actions-BasrAWA0.js} +1 -1
  20. package/dist/gateway/static/root/assets/{channels-DWlrUKBr.js → channels-BKf_-Mdt.js} +1 -1
  21. package/dist/gateway/static/root/assets/{chat-terminal-dock-BL3tFntQ.js → chat-terminal-dock-CwQbzcZ_.js} +1 -1
  22. package/dist/gateway/static/root/assets/chevron-down-ccbiQQz_.js +1 -0
  23. package/dist/gateway/static/root/assets/{computer-settings-page-DEQ5GYfC.js → computer-settings-page-DNWeJKfF.js} +1 -1
  24. package/dist/gateway/static/root/assets/{connector-service-page-CecwMnC5.js → connector-service-page-CxHgC5RM.js} +1 -1
  25. package/dist/gateway/static/root/assets/connectors-page-CUBg8spT.js +1 -0
  26. package/dist/gateway/static/root/assets/{date-picker-N5jnlvPs.js → date-picker-CXxLbLJb.js} +1 -1
  27. package/dist/gateway/static/root/assets/dependency-picker-DVuWMrSj.js +1 -0
  28. package/dist/gateway/static/root/assets/desktop-pet-KbVLtAlO.js +1 -0
  29. package/dist/gateway/static/root/assets/desktop-pet-settings-BDlg9g4s.js +1 -0
  30. package/dist/gateway/static/root/assets/device-pairing-wizard-PmP_vGem.js +1 -0
  31. package/dist/gateway/static/root/assets/{directory-picker-path-field-CbMbPimD.js → directory-picker-path-field-a7xEodzo.js} +1 -1
  32. package/dist/gateway/static/root/assets/ellipsis-0k4rZLoy.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-debug-page-OE1nJMQ8.js → extension-debug-page-CHelH5u_.js} +1 -1
  34. package/dist/gateway/static/root/assets/{extension-page-BEomiKhy.js → extension-page-CrVHmS9-.js} +1 -1
  35. package/dist/gateway/static/root/assets/{extension-settings-page-BFOjQeSX.js → extension-settings-page-CiMybi0r.js} +1 -1
  36. package/dist/gateway/static/root/assets/eye-CABVeTq0.js +1 -0
  37. package/dist/gateway/static/root/assets/folder-open-CyzJ19I9.js +1 -0
  38. package/dist/gateway/static/root/assets/{gateway-settings-CR4CsfNN.js → gateway-settings-DnrQ28E2.js} +1 -1
  39. package/dist/gateway/static/root/assets/{highlight-code-6ONPRH5r.js → highlight-code-AMjU04kR.js} +1 -1
  40. package/dist/gateway/static/root/assets/{highlighted-body-KQOG7T2V-EJ9Kg4iQ.js → highlighted-body-KQOG7T2V-8ACAVktj.js} +1 -1
  41. package/dist/gateway/static/root/assets/home-page-pTwVME-g.js +2 -0
  42. package/dist/gateway/static/root/assets/{image-generation-api-D0HNic89.js → image-generation-api-CVBaWmrV.js} +1 -1
  43. package/dist/gateway/static/root/assets/imports-page-C5IP3e6d.js +1 -0
  44. package/dist/gateway/static/root/assets/{index-D_7q1UkI.css → index-BLL0wKRZ.css} +1 -1
  45. package/dist/gateway/static/root/assets/index-ygkHNYyo.js +710 -0
  46. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-Cmi-2SIh.js → keyboard-shortcuts-settings-BhU6VYvd.js} +1 -1
  47. package/dist/gateway/static/root/assets/local-app-workbench-page-Cwl6EvuX.js +1 -0
  48. package/dist/gateway/static/root/assets/{local-apps-page-jgaogH9Z.js → local-apps-page-DcP1Bdlk.js} +1 -1
  49. package/dist/gateway/static/root/assets/logs-page-CS3hcTOq.js +2 -0
  50. package/dist/gateway/static/root/assets/{management-settings-Dc1opXVr.js → management-settings-DC-Y_-GP.js} +1 -1
  51. package/dist/gateway/static/root/assets/{media-plugins-BRS9puQV.js → media-plugins-BnPpcJ2J.js} +1 -1
  52. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-vckgHpON.js +1 -0
  53. package/dist/gateway/static/root/assets/note-detail-panel-C7u4dxEk.js +5 -0
  54. package/dist/gateway/static/root/assets/note-image-lightbox-jvqYtySx.js +1 -0
  55. package/dist/gateway/static/root/assets/notes-page-Bs7F5Hpf.js +8 -0
  56. package/dist/gateway/static/root/assets/page-context-capture-button-DO_yhXS1.js +1 -0
  57. package/dist/gateway/static/root/assets/personal-page-BexL2-PQ.js +1 -0
  58. package/dist/gateway/static/root/assets/{phone-dependencies-card-DhEsfEUN.js → phone-dependencies-card-ChFtdFhA.js} +1 -1
  59. package/dist/gateway/static/root/assets/phone-model-picker-CZoIAQ1j.js +1 -0
  60. package/dist/gateway/static/root/assets/phone-settings-page-DRyK0nHH.js +1 -0
  61. package/dist/gateway/static/root/assets/{plugin-details-dialog-1BwvmKZi.js → plugin-details-dialog-B-N61jJH.js} +1 -1
  62. package/dist/gateway/static/root/assets/{preview-open-alternatives-DaTaSKox.js → preview-open-alternatives-FGqN-mQx.js} +1 -1
  63. package/dist/gateway/static/root/assets/{product-open-page-wYlC0IVZ.js → product-open-page-CwnHLfdL.js} +1 -1
  64. package/dist/gateway/static/root/assets/{product-preview-content-Bxur-p6S.js → product-preview-content-BD6k5hF9.js} +1 -1
  65. package/dist/gateway/static/root/assets/project-detail-page-DtKmFBml.js +7 -0
  66. package/dist/gateway/static/root/assets/projects-page-CFZIz9mc.js +1 -0
  67. package/dist/gateway/static/root/assets/remote-access-hub-CWEc7W0m.js +1 -0
  68. package/dist/gateway/static/root/assets/{runtime-tools-settings-panel-DXNidliV.js → runtime-tools-settings-panel-q_oswAdV.js} +1 -1
  69. package/dist/gateway/static/root/assets/{schema-form-DeSZ7SiO.js → schema-form-DoVn5jJK.js} +1 -1
  70. package/dist/gateway/static/root/assets/sessions-page-BuPqNxpd.js +1 -0
  71. package/dist/gateway/static/root/assets/settings-advanced-gate-QTVDCGJG.js +1 -0
  72. package/dist/gateway/static/root/assets/{settings-form-section-BNYQjZU4.js → settings-form-section-Ce8vVv-9.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-29Ix0jSQ.js → settings-page-DP2w3ejC.js} +1 -1
  74. package/dist/gateway/static/root/assets/{setup-status-panel-COQZgKX9.js → setup-status-panel-ZmlE8jIE.js} +1 -1
  75. package/dist/gateway/static/root/assets/{share-preview-page-CwMRULXc.js → share-preview-page-DV4dKrmG.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-CtNxWqW-.js +1 -0
  77. package/dist/gateway/static/root/assets/{skill-api-xfB5fUAh.js → skill-api-DTdejInH.js} +1 -1
  78. package/dist/gateway/static/root/assets/{skill-reload-api-Bq-3_MCt.js → skill-reload-api-Egaf8PqZ.js} +1 -1
  79. package/dist/gateway/static/root/assets/skills-page-C6FKxf4J.js +2 -0
  80. package/dist/gateway/static/root/assets/{system-settings-panel-DRJu1ehM.js → system-settings-panel-Baxkhov7.js} +1 -1
  81. package/dist/gateway/static/root/assets/task-detail-page-C77-rpkt.js +2 -0
  82. package/dist/gateway/static/root/assets/{task-result-evidence-C4o_Yue_.js → task-result-evidence-DIGSC4qF.js} +1 -1
  83. package/dist/gateway/static/root/assets/{tracing-settings-page-CYslh-Pu.js → tracing-settings-page-BaU8frtc.js} +1 -1
  84. package/dist/gateway/static/root/assets/{tunnel-api-Bi_kw6bv.js → tunnel-api-BCcOUsqu.js} +1 -1
  85. package/dist/gateway/static/root/assets/usage-page-BFeIbpbi.js +1 -0
  86. package/dist/gateway/static/root/assets/{use-autosave-BkB9uD93.js → use-autosave-C1X47WVb.js} +1 -1
  87. package/dist/gateway/static/root/assets/user-model-page-u8zY5jea.js +2 -0
  88. package/dist/gateway/static/root/assets/{voice-api-key-field-bt8_Agih.js → voice-api-key-field-Bk4DQMTw.js} +1 -1
  89. package/dist/gateway/static/root/assets/{work-discovery-overlay-D3NG14dX.js → work-discovery-overlay-B7_NmTB5.js} +1 -1
  90. package/dist/gateway/static/root/assets/{xopc-cloud-account-card-B2OUKOQi.js → xopc-cloud-account-card-CJ_akAvc.js} +1 -1
  91. package/dist/gateway/static/root/index.html +7 -2
  92. package/dist/package.js +1 -1
  93. package/dist/src/agent/agent-manager.js +1 -1
  94. package/dist/src/agent/background-review/run-background-review.js +1 -1
  95. package/dist/src/agent/external-tools/cliProvider.js +2 -2
  96. package/dist/src/agent/external-tools/composio-provider.js +2 -2
  97. package/dist/src/agent/external-tools/endpoint-provider.js +2 -2
  98. package/dist/src/agent/service.js +1 -1
  99. package/dist/src/agent/skills/index.js +1 -1
  100. package/dist/src/agent/skills/managed-store.js +1 -1
  101. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  102. package/dist/src/agent/tool-manuals/phone.d.ts +1 -1
  103. package/dist/src/agent/tool-manuals/phone.js +2 -2
  104. package/dist/src/agent/tools/personal-read-tool.js +1 -1
  105. package/dist/src/agent/tools/phone-use-tool.js +2 -2
  106. package/dist/src/agent/tools/xopc-use-tool.js +2 -2
  107. package/dist/src/agent-catalog/capabilities.js +2 -2
  108. package/dist/src/agent-catalog/repository.js +1 -1
  109. package/dist/src/automations/capabilities/drafts.js +1 -1
  110. package/dist/src/browser/providers/browser-ext-install.js +1 -1
  111. package/dist/src/capabilities/runtime/dispatcher.js +1 -1
  112. package/dist/src/capabilities/runtime/product.js +1 -1
  113. package/dist/src/cli/commands/agents.js +1 -1
  114. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  115. package/dist/src/cli/commands/extension.js +2 -2
  116. package/dist/src/cli/commands/models.js +1 -1
  117. package/dist/src/cli/commands/onboard/model.js +1 -1
  118. package/dist/src/cli/commands/onboard.js +1 -1
  119. package/dist/src/cli/utils/init-workspace-core.js +1 -1
  120. package/dist/src/config/agent-profile.js +1 -1
  121. package/dist/src/execution-environments/local-worktree-manager.js +1 -1
  122. package/dist/src/extensions/agent-plugins/skill-catalog.js +1 -1
  123. package/dist/src/extensions/agent-plugins/validation.js +1 -1
  124. package/dist/src/extensions/update.js +1 -1
  125. package/dist/src/gateway/agents-admin.js +2 -2
  126. package/dist/src/gateway/global-defaults-admin.js +1 -1
  127. package/dist/src/gateway/hono/routes/agents.js +1 -1
  128. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  129. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  130. package/dist/src/gateway/hono/routes/notes.js +2 -2
  131. package/dist/src/gateway/hono/routes/phone.js +25 -4
  132. package/dist/src/gateway/hono/routes/projects.js +2 -2
  133. package/dist/src/gateway/hono/routes/session-input-handler.js +1 -1
  134. package/dist/src/gateway/hono/routes/tasks.js +1 -1
  135. package/dist/src/gateway/image-generation-setup.js +1 -1
  136. package/dist/src/gateway/service/config-coordinator.js +1 -1
  137. package/dist/src/gateway/service.js +2 -2
  138. package/dist/src/gateway/xopc-cloud-capability-setup.js +1 -1
  139. package/dist/src/imports/importService.js +1 -1
  140. package/dist/src/infra/update-runner.js +1 -1
  141. package/dist/src/local-apps/service.js +1 -1
  142. package/dist/src/personal-agent/service.js +1 -1
  143. package/dist/src/phone/adb-driver.d.ts +5 -2
  144. package/dist/src/phone/adb-driver.js +25 -1
  145. package/dist/src/phone/app-access.d.ts +10 -0
  146. package/dist/src/phone/app-access.js +21 -0
  147. package/dist/src/phone/applications.d.ts +4 -0
  148. package/dist/src/phone/applications.js +49 -0
  149. package/dist/src/phone/cloud-adb.d.ts +1 -0
  150. package/dist/src/phone/cloud-adb.js +52 -2
  151. package/dist/src/phone/cloud-phones.js +2 -1
  152. package/dist/src/phone/cloud-scrcpy.js +2 -1
  153. package/dist/src/phone/contracts.d.ts +9 -1
  154. package/dist/src/phone/contracts.js +2 -1
  155. package/dist/src/phone/model-adapter.d.ts +8 -2
  156. package/dist/src/phone/model-adapter.js +14 -4
  157. package/dist/src/phone/repository.js +4 -3
  158. package/dist/src/phone/runtime.d.ts +6 -1
  159. package/dist/src/phone/runtime.js +36 -8
  160. package/dist/src/phone/scrcpy-assets.d.ts +4 -0
  161. package/dist/src/phone/scrcpy-assets.js +16 -0
  162. package/dist/src/phone/scrcpy.d.ts +1 -4
  163. package/dist/src/phone/scrcpy.js +3 -11
  164. package/dist/src/runtime-tools/archive.js +1 -1
  165. package/dist/src/tasks/capabilities/read.js +2 -2
  166. package/dist/src/tasks/capabilities/write.js +1 -1
  167. package/dist/src/tui/backends/embedded-backend.js +1 -1
  168. package/dist/src/voice/realtime/persona-context.js +1 -1
  169. package/package.json +3 -3
  170. package/dist/gateway/static/root/assets/agents-Clwskw2J.js +0 -77
  171. package/dist/gateway/static/root/assets/apps-page-DJbKg3va.js +0 -1
  172. package/dist/gateway/static/root/assets/automations-workspace-D_X0_1X3.js +0 -8
  173. package/dist/gateway/static/root/assets/browser-automations-page-BI-ep6uM.js +0 -3
  174. package/dist/gateway/static/root/assets/browser-settings-page-BTyQ4-vN.js +0 -3
  175. package/dist/gateway/static/root/assets/capabilities-page-GNS95mG9.js +0 -2
  176. package/dist/gateway/static/root/assets/capabilities-settings-panel-DBiv1HN-.js +0 -8
  177. package/dist/gateway/static/root/assets/connectors-page-BcpUvrtl.js +0 -1
  178. package/dist/gateway/static/root/assets/dependency-picker-C4jddxFl.js +0 -1
  179. package/dist/gateway/static/root/assets/desktop-pet-BCbiUNQG.js +0 -1
  180. package/dist/gateway/static/root/assets/desktop-pet-settings-CkKU0JMY.js +0 -1
  181. package/dist/gateway/static/root/assets/device-pairing-wizard--E2GQoY1.js +0 -1
  182. package/dist/gateway/static/root/assets/home-page-B9w3a6r2.js +0 -2
  183. package/dist/gateway/static/root/assets/imports-page-bxTINe-2.js +0 -1
  184. package/dist/gateway/static/root/assets/index-D1oivYvN.js +0 -710
  185. package/dist/gateway/static/root/assets/local-app-workbench-page-NGCmXpa_.js +0 -1
  186. package/dist/gateway/static/root/assets/logs-page-drrr-c2W.js +0 -2
  187. package/dist/gateway/static/root/assets/mermaid-MCJ5UELQ-B--edI1I.js +0 -1
  188. package/dist/gateway/static/root/assets/note-detail-panel-C3s4-ytB.js +0 -5
  189. package/dist/gateway/static/root/assets/note-image-lightbox-D7q5-KuS.js +0 -1
  190. package/dist/gateway/static/root/assets/notes-page-qVxoErUS.js +0 -8
  191. package/dist/gateway/static/root/assets/page-context-capture-button-D_VOB2_C.js +0 -1
  192. package/dist/gateway/static/root/assets/personal-page-B-T8NzQo.js +0 -1
  193. package/dist/gateway/static/root/assets/phone-model-picker-J4mFDk21.js +0 -1
  194. package/dist/gateway/static/root/assets/phone-settings-page-BLflz8CQ.js +0 -1
  195. package/dist/gateway/static/root/assets/project-detail-page-DwowzxzD.js +0 -7
  196. package/dist/gateway/static/root/assets/projects-page-Bwvn4i_e.js +0 -1
  197. package/dist/gateway/static/root/assets/remote-access-hub-DrHisOUe.js +0 -1
  198. package/dist/gateway/static/root/assets/sessions-page-seP7t0kv.js +0 -1
  199. package/dist/gateway/static/root/assets/settings-advanced-gate-VqBu7gHu.js +0 -1
  200. package/dist/gateway/static/root/assets/shares-settings-BWaykw9E.js +0 -1
  201. package/dist/gateway/static/root/assets/skills-page-C3LfWsAZ.js +0 -2
  202. package/dist/gateway/static/root/assets/task-detail-page-XCJFP-Aa.js +0 -2
  203. package/dist/gateway/static/root/assets/usage-page-CTTmklCs.js +0 -1
  204. package/dist/gateway/static/root/assets/user-model-page-BDqguzRE.js +0 -2
@@ -0,0 +1,49 @@
1
+ import { PhoneError, init_contracts } from "./contracts.js";
2
+ import { SCRCPY_VERSION } from "../runtime-tools/phone-dependency-catalog.js";
3
+ //#region src/phone/applications.ts
4
+ init_contracts();
5
+ const packageName = /^[a-zA-Z]\w*(?:\.\w+)+$/;
6
+ function phoneApplicationsCommand(remote) {
7
+ return [
8
+ "env",
9
+ `CLASSPATH=${remote}`,
10
+ "app_process",
11
+ "/",
12
+ "com.genymobile.scrcpy.Server",
13
+ SCRCPY_VERSION,
14
+ "list_apps=true",
15
+ "video=false",
16
+ "audio=false",
17
+ "control=false"
18
+ ];
19
+ }
20
+ /** Parse the pinned scrcpy server's app list, including wrapped long labels. */
21
+ function parsePhoneApplications(raw) {
22
+ const text = raw.replace(/\u001b\[[\d;]*m/g, "");
23
+ if (text.length > 1024 * 1024 || !text.includes("List of apps:")) throw new PhoneError("PHONE_APPS_UNAVAILABLE", "Unable to read the phone application list. Check the phone connection and scrcpy dependency.");
24
+ const apps = /* @__PURE__ */ new Map();
25
+ let pending;
26
+ for (const line of text.split(/\r?\n/)) {
27
+ const entry = /^\s*[*-]\s+(.+)$/.exec(line);
28
+ if (entry) {
29
+ const match = /^(.*?)\s+([a-zA-Z]\w*(?:\.\w+)+)$/.exec(entry[1].trim());
30
+ if (match) {
31
+ pending = void 0;
32
+ apps.set(match[2], {
33
+ packageName: match[2],
34
+ label: match[1].trim().slice(0, 120) || match[2]
35
+ });
36
+ } else pending = entry[1].trim().slice(0, 120);
37
+ } else if (pending && packageName.test(line.trim())) {
38
+ apps.set(line.trim(), {
39
+ packageName: line.trim(),
40
+ label: pending
41
+ });
42
+ pending = void 0;
43
+ }
44
+ if (apps.size > 500) throw new PhoneError("PHONE_APPS_LIMIT", "Phone application list exceeds 500 entries");
45
+ }
46
+ return [...apps.values()].sort((a, b) => a.label.localeCompare(b.label));
47
+ }
48
+ //#endregion
49
+ export { parsePhoneApplications, phoneApplicationsCommand };
@@ -30,5 +30,6 @@ export declare class CloudAdbConnection {
30
30
  client(): Promise<Adb>;
31
31
  private open;
32
32
  command(_path: string, args: string[], signal?: AbortSignal, timeout?: number): Promise<Buffer>;
33
+ applications(signal: AbortSignal): Promise<import("./contracts.js").PhoneApplication[]>;
33
34
  driver(): AdbPhoneDriver;
34
35
  }
@@ -1,5 +1,7 @@
1
1
  import { init_paths, resolveCredentialsDir } from "../config/paths.js";
2
2
  import { PhoneError, init_contracts } from "./contracts.js";
3
+ import { readScrcpyServer } from "./scrcpy-assets.js";
4
+ import { parsePhoneApplications, phoneApplicationsCommand } from "./applications.js";
3
5
  import { AdbPhoneDriver } from "./adb-driver.js";
4
6
  import { join } from "node:path";
5
7
  import { createPrivateKey, randomUUID } from "node:crypto";
@@ -66,7 +68,7 @@ var PhoneCloudKeyStore = class {
66
68
  }
67
69
  };
68
70
  /** Direct daemon transport never starts or modifies the host ADB server. */
69
- var CloudAdbConnection = class {
71
+ var CloudAdbConnection = class CloudAdbConnection {
70
72
  socket;
71
73
  adb;
72
74
  pending;
@@ -215,8 +217,56 @@ var CloudAdbConnection = class {
215
217
  this.idle.unref();
216
218
  }
217
219
  }
220
+ async applications(signal) {
221
+ const combined = AbortSignal.any([signal, AbortSignal.timeout(3e4)]);
222
+ const abort = () => this.close();
223
+ combined.addEventListener("abort", abort, { once: true });
224
+ const remote = `/data/local/tmp/xopc-apps-${randomUUID()}.jar`;
225
+ try {
226
+ combined.throwIfAborted();
227
+ const binary = await readScrcpyServer();
228
+ const adb = await this.client();
229
+ combined.throwIfAborted();
230
+ const sync = await adb.sync();
231
+ try {
232
+ await sync.write({
233
+ filename: remote,
234
+ permission: 384,
235
+ file: new ReadableStream({ start(controller) {
236
+ controller.enqueue(binary);
237
+ controller.close();
238
+ } })
239
+ });
240
+ } finally {
241
+ await sync.dispose();
242
+ }
243
+ return parsePhoneApplications((await this.command("", [
244
+ "-s",
245
+ this.endpoint,
246
+ "shell",
247
+ ...phoneApplicationsCommand(remote)
248
+ ], combined)).toString());
249
+ } finally {
250
+ combined.removeEventListener("abort", abort);
251
+ await this.command("", [
252
+ "-s",
253
+ this.endpoint,
254
+ "shell",
255
+ "rm",
256
+ "-f",
257
+ remote
258
+ ], void 0, 3e3).catch(() => {});
259
+ }
260
+ }
218
261
  driver() {
219
- return new AdbPhoneDriver("", this.command.bind(this), false);
262
+ return new AdbPhoneDriver("", this.command.bind(this), false, async (signal) => {
263
+ const listing = new CloudAdbConnection(this.endpoint, Buffer.from(this.key));
264
+ try {
265
+ return await listing.applications(signal);
266
+ } finally {
267
+ listing.dispose();
268
+ }
269
+ });
220
270
  }
221
271
  };
222
272
  //#endregion
@@ -90,7 +90,8 @@ var CloudPhones = class {
90
90
  serial: draft.endpoint,
91
91
  name,
92
92
  enabled: true,
93
- allowedApps: ["com.android.settings"],
93
+ appAccess: "all",
94
+ allowedApps: [],
94
95
  connection: {
95
96
  kind: "aliyun-adb",
96
97
  endpoint: draft.endpoint,
@@ -1,6 +1,7 @@
1
1
  import { PhoneError, init_contracts } from "./contracts.js";
2
2
  import { SCRCPY_VERSION } from "../runtime-tools/phone-dependency-catalog.js";
3
- import { ScrcpyProvider, ScrcpyVideoParser, readScrcpyServer } from "./scrcpy.js";
3
+ import { readScrcpyServer } from "./scrcpy-assets.js";
4
+ import { ScrcpyProvider, ScrcpyVideoParser } from "./scrcpy.js";
4
5
  import { CloudAdbConnection } from "./cloud-adb.js";
5
6
  import { randomBytes } from "node:crypto";
6
7
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
@@ -25,7 +25,11 @@ export declare const PhoneDeviceSchema: z.ZodObject<{
25
25
  serial: z.ZodString;
26
26
  name: z.ZodString;
27
27
  enabled: z.ZodDefault<z.ZodBoolean>;
28
- allowedApps: z.ZodArray<z.ZodString>;
28
+ appAccess: z.ZodOptional<z.ZodEnum<{
29
+ all: "all";
30
+ selected: "selected";
31
+ }>>;
32
+ allowedApps: z.ZodDefault<z.ZodArray<z.ZodString>>;
29
33
  connection: z.ZodOptional<z.ZodObject<{
30
34
  kind: z.ZodLiteral<"aliyun-adb">;
31
35
  endpoint: z.ZodString;
@@ -35,6 +39,10 @@ export declare const PhoneDeviceSchema: z.ZodObject<{
35
39
  revision: z.ZodNumber;
36
40
  }, z.core.$strict>;
37
41
  export type PhoneDevice = z.infer<typeof PhoneDeviceSchema>;
42
+ export type PhoneApplication = {
43
+ packageName: string;
44
+ label: string;
45
+ };
38
46
  export type DiscoveredPhone = {
39
47
  serial: string;
40
48
  state: string;
@@ -20,7 +20,8 @@ var init_contracts = __esmMin((() => {
20
20
  serial: z.string().min(1).max(200),
21
21
  name: z.string().trim().min(1).max(100),
22
22
  enabled: z.boolean().default(true),
23
- allowedApps: z.array(z.string().regex(/^[a-zA-Z][\w]*(?:\.[\w]+)+$/)).min(1).max(50),
23
+ appAccess: z.enum(["all", "selected"]).optional(),
24
+ allowedApps: z.array(z.string().regex(/^[a-zA-Z][\w]*(?:\.[\w]+)+$/)).max(500).default([]),
24
25
  connection: z.object({
25
26
  kind: z.literal("aliyun-adb"),
26
27
  endpoint: z.string().max(200),
@@ -1,5 +1,6 @@
1
+ import { type PhoneAppAccess } from './app-access.js';
1
2
  import type { Config } from '../config/schema.js';
2
- import { type PhoneAction, type PhoneDecision, type PhoneObservation } from './contracts.js';
3
+ import { type PhoneAction, type PhoneApplication, type PhoneDecision, type PhoneObservation } from './contracts.js';
3
4
  export declare function phoneModelProfile(model: unknown): "autoglm-phone-v1" | "structured-phone-v1";
4
5
  export declare function validatePhoneModelChange(next: {
5
6
  primary: string;
@@ -7,11 +8,16 @@ export declare function validatePhoneModelChange(next: {
7
8
  primary: string;
8
9
  } | null): void;
9
10
  /** Parse only a function name and literal keyword arguments; model text is never executable code. */
10
- export declare function parseAutoGlmResponse(raw: string, allowedApps: string[]): PhoneDecision;
11
+ export declare function parseAutoGlmResponse(raw: string, allowedApps: string[], options?: {
12
+ appAccess?: PhoneAppAccess['appAccess'];
13
+ applications?: PhoneApplication[];
14
+ }): PhoneDecision;
11
15
  export interface PhonePrediction {
12
16
  goal: string;
13
17
  observation: PhoneObservation;
14
18
  allowedApps: string[];
19
+ appAccess?: PhoneAppAccess['appAccess'];
20
+ applications?: PhoneApplication[];
15
21
  history: PhoneAction['type'][];
16
22
  scenario?: 'settings-about';
17
23
  }
@@ -1,5 +1,6 @@
1
1
  import { PhoneDecisionSchema, PhoneError, PhoneModelMetadataSchema, init_contracts } from "./contracts.js";
2
2
  import { getApiKey, init_providers, resolveModel } from "../providers/index.js";
3
+ import { phoneAllowsApp } from "./app-access.js";
3
4
  import { z } from "zod";
4
5
  //#region src/phone/model-adapter.ts
5
6
  init_providers();
@@ -17,7 +18,7 @@ function validatePhoneModelChange(next, previous) {
17
18
  throw new PhoneError("PHONE_MODEL_INCOMPATIBLE", "Select a model with a supported Phone Use profile");
18
19
  }
19
20
  /** Parse only a function name and literal keyword arguments; model text is never executable code. */
20
- function parseAutoGlmResponse(raw, allowedApps) {
21
+ function parseAutoGlmResponse(raw, allowedApps, options) {
21
22
  let text = raw.trim();
22
23
  if (text.includes("<answer>")) text = text.split("<answer>").at(-1).replace(/<\/answer>[\s\S]*$/, "").trim();
23
24
  else {
@@ -133,8 +134,15 @@ function parseAutoGlmResponse(raw, allowedApps) {
133
134
  let action;
134
135
  switch (args.action) {
135
136
  case "Launch": {
136
- const app = args.app === "设置" || args.app === "Settings" ? "com.android.settings" : args.app;
137
- if (typeof app !== "string" || !allowedApps.includes(app)) throw new PhoneError("PHONE_APP_DENIED", "Model requested an application outside the device allowlist");
137
+ let app = args.app === "设置" || args.app === "Settings" ? "com.android.settings" : args.app;
138
+ if (typeof app === "string" && !/^[a-zA-Z]\w*(?:\.\w+)+$/.test(app)) {
139
+ const matches = options?.applications?.filter((candidate) => candidate.label.toLocaleLowerCase() === String(app).toLocaleLowerCase()) ?? [];
140
+ if (matches.length === 1) app = matches[0].packageName;
141
+ }
142
+ if (typeof app !== "string" || !/^[a-zA-Z]\w*(?:\.\w+)+$/.test(app) || !phoneAllowsApp({
143
+ allowedApps,
144
+ appAccess: options?.appAccess ?? "selected"
145
+ }, app)) throw new PhoneError("PHONE_APP_DENIED", "Model requested an application outside the device allowlist");
138
146
  action = {
139
147
  type: "launch",
140
148
  package: app
@@ -314,7 +322,9 @@ async function createPhoneModel(modelRef, config, agentId) {
314
322
  type: "text",
315
323
  text: JSON.stringify({
316
324
  goal: input.goal,
325
+ appAccess: input.appAccess ?? "selected",
317
326
  allowedApps: input.allowedApps,
327
+ applications: input.applications?.slice(0, 100),
318
328
  currentApp: input.observation.package,
319
329
  recentActions: input.history.slice(-6)
320
330
  })
@@ -328,7 +338,7 @@ async function createPhoneModel(modelRef, config, agentId) {
328
338
  const payload = z.object({ choices: z.array(z.object({ message: z.object({ content: z.string() }) })).min(1) }).safeParse(await boundedJson(response));
329
339
  if (!payload.success) throw new PhoneError("PHONE_MODEL_PROTOCOL", "Phone model returned no action");
330
340
  const text = payload.data.choices[0].message.content;
331
- if (profile === "autoglm-phone-v1") return parseAutoGlmResponse(text, input.allowedApps);
341
+ if (profile === "autoglm-phone-v1") return parseAutoGlmResponse(text, input.allowedApps, input);
332
342
  try {
333
343
  return PhoneDecisionSchema.parse(JSON.parse(text));
334
344
  } catch {
@@ -1,11 +1,12 @@
1
1
  import { PhoneDeviceSchema, PhoneError, init_contracts } from "./contracts.js";
2
+ import { normalizePhoneAppAccess } from "./app-access.js";
2
3
  import { DurableState } from "../storage/sqlite/durable-state.js";
3
4
  import { randomUUID } from "node:crypto";
4
5
  //#region src/phone/repository.ts
5
6
  init_contracts();
6
7
  function parseDevice(value) {
7
8
  const { agentIds: _removed, ...device } = value;
8
- return PhoneDeviceSchema.parse(device);
9
+ return normalizePhoneAppAccess(PhoneDeviceSchema.parse(device));
9
10
  }
10
11
  /** Small settings and latest metadata-only reports; pixels and input text are never stored. */
11
12
  var PhoneRepository = class {
@@ -24,12 +25,12 @@ var PhoneRepository = class {
24
25
  save(input, id) {
25
26
  const previous = id ? this.get(id) : void 0;
26
27
  if (this.list().some((device) => device.serial === input.serial && device.id !== id)) throw new PhoneError("PHONE_DEVICE_DUPLICATE", "This ADB device is already registered");
27
- const next = PhoneDeviceSchema.parse({
28
+ const next = normalizePhoneAppAccess(PhoneDeviceSchema.parse({
28
29
  ...input,
29
30
  id: id ?? randomUUID(),
30
31
  createdAt: previous?.createdAt ?? Date.now(),
31
32
  revision: (previous?.revision ?? 0) + 1
32
- });
33
+ }));
33
34
  this.devices.set(next.id, next);
34
35
  return next;
35
36
  }
@@ -5,7 +5,7 @@ import { CloudPhones } from './cloud-phones.js';
5
5
  import { type PhoneDriver } from './adb-driver.js';
6
6
  import { createPhoneModel } from './model-adapter.js';
7
7
  import { PhoneRepository } from './repository.js';
8
- import { type PhoneAction, type PhoneDevice, type PhoneInput, type PhoneObservation, type PhoneReport } from './contracts.js';
8
+ import { type PhoneAction, type PhoneDevice, type PhoneInput, type PhoneApplication, type PhoneObservation, type PhoneReport } from './contracts.js';
9
9
  type ExecutionContext = {
10
10
  config: Config;
11
11
  agentId: string;
@@ -26,6 +26,10 @@ export declare class PhoneRuntime {
26
26
  constructor(repository?: PhoneRepository, driverFactory?: (path: string) => PhoneDriver, modelFactory?: typeof createPhoneModel, interactiveFactory?: (adb: string, serial: string, failed: () => void) => PhoneInteractiveProvider);
27
27
  driverFor(device: PhoneDevice, config: Config): Promise<PhoneDriver>;
28
28
  discover(config: Config, signal?: AbortSignal): Promise<import("./contracts.js").DiscoveredPhone[]>;
29
+ applications(input: {
30
+ deviceId?: string;
31
+ serial?: string;
32
+ }, config: Config, signal: AbortSignal): Promise<PhoneApplication[]>;
29
33
  preview(id: string, config: Config, signal: AbortSignal): Promise<PhoneObservation>;
30
34
  previewSession(owner: string, context: ExecutionContext, signal: AbortSignal): Promise<PhoneObservation>;
31
35
  reports(): PhoneReport[];
@@ -50,6 +54,7 @@ export declare class PhoneRuntime {
50
54
  report: PhoneReport;
51
55
  ownControl: boolean;
52
56
  allowedApps: string[];
57
+ appAccess: "all" | "selected";
53
58
  frame: {
54
59
  seq: number;
55
60
  capturedAt: number;
@@ -2,6 +2,7 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { MOCK_PHONE_MODEL, PhoneError, PhoneInputSchema, init_contracts } from "./contracts.js";
4
4
  import { resolveEffectiveAgentConfigForAgent } from "../config/agent-profile.js";
5
+ import { phoneAllowsApp, phoneAppAccess } from "./app-access.js";
5
6
  import { PhoneFrameCache, PhoneOperationBudget } from "./live-state.js";
6
7
  import { PhoneInteractiveSession } from "./interactive-session.js";
7
8
  import { AdbPhoneDriver, resolveAdbPath } from "./adb-driver.js";
@@ -40,13 +41,30 @@ var PhoneRuntime = class {
40
41
  async discover(config, signal) {
41
42
  return this.driverFactory(resolveAdbPath(config.phone.adbPath)).discover(signal);
42
43
  }
44
+ async applications(input, config, signal) {
45
+ let driver;
46
+ let serial;
47
+ if (input.deviceId) {
48
+ const device = this.repository.get(input.deviceId);
49
+ if (!device.enabled) throw new PhoneError("PHONE_DEVICE_DENIED", "Phone access is disabled", 403);
50
+ driver = await this.driverFor(device, config);
51
+ serial = device.serial;
52
+ } else {
53
+ const found = (await this.discover(config, signal)).find((device) => device.serial === input.serial && device.state === "device");
54
+ if (!found) throw new PhoneError("PHONE_DEVICE_OFFLINE", "Choose a connected and authorized phone");
55
+ driver = this.driverFactory(resolveAdbPath(config.phone.adbPath));
56
+ serial = found.serial;
57
+ }
58
+ if (!driver.applications) throw new PhoneError("PHONE_APPS_UNAVAILABLE", "The phone provider cannot list applications");
59
+ return driver.applications(serial, signal);
60
+ }
43
61
  async preview(id, config, signal) {
44
62
  const device = this.repository.get(id);
45
63
  if (!device.enabled) throw new PhoneError("PHONE_DEVICE_DENIED", "Phone access is disabled", 403);
46
64
  const lease = this.repository.acquire(device.serial);
47
65
  try {
48
66
  const observation = await (await this.driverFor(device, config)).observe(device.serial, signal);
49
- if (!device.allowedApps.includes(observation.package)) {
67
+ if (!phoneAllowsApp(device, observation.package)) {
50
68
  observation.frame.fill(0);
51
69
  throw new PhoneError("PHONE_APP_DENIED", "Open an allowed app before previewing the screen");
52
70
  }
@@ -91,7 +109,7 @@ var PhoneRuntime = class {
91
109
  this.repository.renew(session.device.serial, session.lease);
92
110
  }
93
111
  allowedScreen(session, observation) {
94
- if (!session.device.allowedApps.includes(observation.package)) throw new PhoneError("PHONE_APP_DENIED", "The foreground application is outside this phone session allowlist. Open an allowed app or reopen with appPackage.");
112
+ if (!phoneAllowsApp(session.device, observation.package)) throw new PhoneError("PHONE_APP_DENIED", "The foreground application is outside this phone session allowlist. Open an allowed app or reopen with appPackage.");
95
113
  }
96
114
  async execute(owner, raw, context, signal = new AbortController().signal) {
97
115
  const input = PhoneInputSchema.parse(raw);
@@ -132,6 +150,12 @@ var PhoneRuntime = class {
132
150
  try {
133
151
  const adapter = await this.modelFactory(modelRef, context.config, context.agentId);
134
152
  signal.throwIfAborted();
153
+ let applications = [];
154
+ if (input.mode === "control" && modelRef !== "phone-mock/settings-about" && driver.applications) try {
155
+ applications = await driver.applications(device.serial, signal);
156
+ } catch {
157
+ signal.throwIfAborted();
158
+ }
135
159
  const now = Date.now();
136
160
  const session = {
137
161
  device,
@@ -143,6 +167,7 @@ var PhoneRuntime = class {
143
167
  modelRef,
144
168
  adbPath,
145
169
  context,
170
+ applications,
146
171
  frames: new PhoneFrameCache(),
147
172
  io: Promise.resolve(),
148
173
  ioBusy: false,
@@ -174,7 +199,7 @@ var PhoneRuntime = class {
174
199
  };
175
200
  this.sessions.set(owner, session);
176
201
  if (input.appPackage) {
177
- if (input.mode !== "control" || !device.allowedApps.includes(input.appPackage)) throw new PhoneError("PHONE_APP_DENIED", "Launching requires control mode and an allowed application");
202
+ if (input.mode !== "control" || !phoneAllowsApp(device, input.appPackage)) throw new PhoneError("PHONE_APP_DENIED", "Launching requires control mode and an allowed application");
178
203
  const epoch = session.report.controlEpoch;
179
204
  const observation = await this.observe(session, signal);
180
205
  try {
@@ -291,6 +316,8 @@ var PhoneRuntime = class {
291
316
  goal: input.goal,
292
317
  observation,
293
318
  allowedApps: session.device.allowedApps,
319
+ appAccess: phoneAppAccess(session.device),
320
+ applications: session.applications.filter((app) => phoneAllowsApp(session.device, app.packageName)),
294
321
  history: session.report.steps.map((step) => step.action),
295
322
  scenario: input.scenario
296
323
  }, AbortSignal.any([signal, session.prediction.signal]));
@@ -416,8 +443,8 @@ var PhoneRuntime = class {
416
443
  if (session.human && Date.now() > (session.humanExpiresAt ?? 0)) throw new PhoneError("PHONE_CONTROL_REQUIRED", "Manual control expired", 409);
417
444
  if (!session.human && session.report.actions - (session.report.humanActions ?? 0) >= context.config.phone.maxActionsPerSession) throw new PhoneError("PHONE_ACTION_LIMIT", "Phone action limit reached");
418
445
  if (session.human && (session.report.humanActions ?? 0) >= 1200) throw new PhoneError("PHONE_ACTION_LIMIT", "Manual input limit reached; reopen the session");
419
- if (action.type === "launch" && !session.device.allowedApps.includes(action.package)) throw new PhoneError("PHONE_APP_DENIED", "Application is not authorized");
420
- if (action.type === "home") throw new PhoneError("PHONE_APP_DENIED", "Home leaves the app allowlist");
446
+ if (action.type === "launch" && !phoneAllowsApp(session.device, action.package)) throw new PhoneError("PHONE_APP_DENIED", "Application is not authorized");
447
+ if (action.type === "home" && phoneAppAccess(session.device) !== "all") throw new PhoneError("PHONE_APP_DENIED", "Home leaves the app allowlist");
421
448
  if (action.type === "typeText" && !observation.elements.some((node) => node.focused && node.editable && !node.password)) throw new PhoneError("PHONE_INPUT_NOT_FOCUSED", "Focus a non-password editable field before typing", 409);
422
449
  const step = {
423
450
  action: action.type,
@@ -497,7 +524,7 @@ var PhoneRuntime = class {
497
524
  return this.io(session, async () => {
498
525
  signal.throwIfAborted();
499
526
  const observation = await (forText && session.driver.observeForText ? session.driver.observeForText : session.driver.observe).call(session.driver, session.device.serial, signal);
500
- if (session.device.allowedApps.includes(observation.package)) {
527
+ if (phoneAllowsApp(session.device, observation.package)) {
501
528
  if (Date.now() - session.viewedAt < 3e4 && !terminal.has(session.report.status)) session.frames.set(observation);
502
529
  } else session.frames.clear();
503
530
  return observation;
@@ -597,6 +624,7 @@ var PhoneRuntime = class {
597
624
  report: structuredClone(session.report),
598
625
  ownControl: Boolean(session.human === client),
599
626
  allowedApps: [...session.device.allowedApps],
627
+ appAccess: phoneAppAccess(session.device),
600
628
  frame: session.frames.get() ? {
601
629
  seq: session.frames.get().seq,
602
630
  capturedAt: session.frames.get().capturedAt
@@ -631,7 +659,7 @@ var PhoneRuntime = class {
631
659
  if (terminal.has(session.report.status)) throw new PhoneError("PHONE_VIDEO_ENDED", "Phone session ended", 409);
632
660
  this.guard(session, session.context);
633
661
  const app = await provider.foreground(AbortSignal.timeout(2e3));
634
- if (!session.device.allowedApps.includes(app)) throw new PhoneError("PHONE_APP_DENIED", "Current page is outside the authorized applications", 403);
662
+ if (!phoneAllowsApp(session.device, app)) throw new PhoneError("PHONE_APP_DENIED", "Current page is outside the authorized applications", 403);
635
663
  session.viewedAt = Date.now();
636
664
  }, (client, epoch) => {
637
665
  if (terminal.has(session.report.status) || session.report.handoff !== "idle" || session.report.controlOwner !== "human" || session.human !== client || session.report.controlEpoch !== epoch || Date.now() > (session.humanExpiresAt ?? 0)) throw new PhoneError("PHONE_CONTROL_CHANGED", "Manual control is no longer available", 409);
@@ -811,7 +839,7 @@ var PhoneRuntime = class {
811
839
  for (const wake of session.wake) wake();
812
840
  } else if (input.op === "recover") {
813
841
  if (session.human !== client || Date.now() > (session.humanExpiresAt ?? 0)) throw new PhoneError("PHONE_CONTROL_REQUIRED", "Take over the phone first", 409);
814
- if (input.action?.type !== "launch" || !session.device.allowedApps.includes(input.action.package)) throw new PhoneError("PHONE_APP_DENIED", "Choose an authorized recovery application", 403);
842
+ if (input.action?.type !== "launch" || !phoneAllowsApp(session.device, input.action.package)) throw new PhoneError("PHONE_APP_DENIED", "Choose an authorized recovery application", 403);
815
843
  const observation = await this.io(session, () => session.driver.capture ? session.driver.capture(session.device.serial, session.controller.signal) : session.driver.observe(session.device.serial, session.controller.signal));
816
844
  try {
817
845
  if (!await this.dispatch(session, input.action, observation, context, session.controller.signal, input.epoch, true)) throw new PhoneError("PHONE_CONTROL_CHANGED", "Control changed before recovery", 409);
@@ -0,0 +1,4 @@
1
+ import { SCRCPY_SHA256, SCRCPY_VERSION } from '../runtime-tools/phone-dependency-catalog.js';
2
+ export { SCRCPY_SHA256, SCRCPY_VERSION };
3
+ export declare const scrcpyServerPath: (stateDir?: string) => string;
4
+ export declare function readScrcpyServer(): Promise<Buffer>;
@@ -0,0 +1,16 @@
1
+ import { PhoneError, init_contracts } from "./contracts.js";
2
+ import { SCRCPY_SHA256, SCRCPY_VERSION, managedScrcpyServerPath } from "../runtime-tools/phone-dependency-catalog.js";
3
+ import { createHash } from "node:crypto";
4
+ import { readFile } from "node:fs/promises";
5
+ //#region src/phone/scrcpy-assets.ts
6
+ init_contracts();
7
+ const scrcpyServerPath = managedScrcpyServerPath;
8
+ async function readScrcpyServer() {
9
+ const binary = await readFile(scrcpyServerPath()).catch(() => {
10
+ throw new PhoneError("PHONE_VIDEO_SETUP_REQUIRED", "Install scrcpy server in Settings → Phone Use → Dependencies");
11
+ });
12
+ if (createHash("sha256").update(binary).digest("hex") !== "7e70323ba7f259649dd4acce97ac4fefbae8102b2c6d91e2e7be613fd5354be0") throw new PhoneError("PHONE_VIDEO_HASH_MISMATCH", "Phone video server checksum mismatch");
13
+ return binary;
14
+ }
15
+ //#endregion
16
+ export { SCRCPY_SHA256, SCRCPY_VERSION, readScrcpyServer, scrcpyServerPath };
@@ -1,7 +1,5 @@
1
- import { SCRCPY_SHA256, SCRCPY_VERSION } from '../runtime-tools/phone-dependency-catalog.js';
2
1
  import type { PhoneInteractiveProvider, PhonePointer, PhoneVideoGeometry, PhoneVideoPacket } from './live-provider.js';
3
- export { SCRCPY_VERSION, SCRCPY_SHA256 };
4
- export declare const scrcpyServerPath: (stateDir?: string) => string;
2
+ export { readScrcpyServer, scrcpyServerPath, SCRCPY_VERSION, SCRCPY_SHA256 } from './scrcpy-assets.js';
5
3
  /** The pinned server sends codec metadata followed by bounded, length-prefixed packets. */
6
4
  export declare class ScrcpyVideoParser {
7
5
  private buffer;
@@ -9,7 +7,6 @@ export declare class ScrcpyVideoParser {
9
7
  push(chunk: Buffer, packet: (packet: PhoneVideoPacket) => void): void;
10
8
  }
11
9
  export declare function scrcpyTouch(phase: PhonePointer['phase'], x: number, y: number, width: number, height: number): Buffer;
12
- export declare function readScrcpyServer(): Promise<Buffer>;
13
10
  /** Local and cloud transports share geometry, gesture sequencing and revocation. */
14
11
  export declare abstract class ScrcpyProvider implements PhoneInteractiveProvider {
15
12
  private onFailure;
@@ -1,15 +1,14 @@
1
1
  import { PhoneError, init_contracts } from "./contracts.js";
2
2
  import { spawnPhoneCommand } from "../process/phone-process.js";
3
- import { SCRCPY_SHA256, SCRCPY_VERSION, managedScrcpyServerPath } from "../runtime-tools/phone-dependency-catalog.js";
3
+ import { SCRCPY_SHA256, SCRCPY_VERSION } from "../runtime-tools/phone-dependency-catalog.js";
4
+ import { readScrcpyServer, scrcpyServerPath } from "./scrcpy-assets.js";
4
5
  import { AdbPhoneDriver, runAdb } from "./adb-driver.js";
5
- import { createHash, randomBytes } from "node:crypto";
6
- import { readFile } from "node:fs/promises";
6
+ import { randomBytes } from "node:crypto";
7
7
  import { connect } from "node:net";
8
8
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
9
9
  import { h264ParseConfiguration } from "@yume-chan/scrcpy";
10
10
  //#region src/phone/scrcpy.ts
11
11
  init_contracts();
12
- const scrcpyServerPath = managedScrcpyServerPath;
13
12
  /** The pinned server sends codec metadata followed by bounded, length-prefixed packets. */
14
13
  var ScrcpyVideoParser = class {
15
14
  buffer = Buffer.alloc(0);
@@ -55,13 +54,6 @@ function scrcpyTouch(phase, x, y, width, height) {
55
54
  buffer.writeUInt16BE(phase === "up" || phase === "cancel" ? 0 : 65535, 22);
56
55
  return buffer;
57
56
  }
58
- async function readScrcpyServer() {
59
- const binary = await readFile(scrcpyServerPath()).catch(() => {
60
- throw new PhoneError("PHONE_VIDEO_SETUP_REQUIRED", "Install scrcpy server in Settings → Phone Use → Dependencies");
61
- });
62
- if (createHash("sha256").update(binary).digest("hex") !== "7e70323ba7f259649dd4acce97ac4fefbae8102b2c6d91e2e7be613fd5354be0") throw new PhoneError("PHONE_VIDEO_HASH_MISMATCH", "Phone video server checksum mismatch");
63
- return binary;
64
- }
65
57
  /** Local and cloud transports share geometry, gesture sequencing and revocation. */
66
58
  var ScrcpyProvider = class {
67
59
  descriptor = {
@@ -1,8 +1,8 @@
1
1
  import { RuntimeError } from "./errors.js";
2
2
  import { isAbsolute, join, posix, relative, resolve } from "node:path";
3
3
  import { spawn } from "node:child_process";
4
- import AdmZip from "adm-zip";
5
4
  import { lstat, mkdir, readdir, readlink, rename, rm, stat } from "node:fs/promises";
5
+ import AdmZip from "adm-zip";
6
6
  //#region src/runtime-tools/archive.ts
7
7
  const MAX_ARCHIVE_ENTRIES = 5e4;
8
8
  const MAX_TAR_OUTPUT_BYTES = 16 * 1024 * 1024;
@@ -2,10 +2,10 @@ import { ProductReadContracts } from "../../../packages/gateway-contract/src/cap
2
2
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
3
  import { TaskRepository, init_task_repository } from "../task-repository.js";
4
4
  import { TaskRunRepository, init_task_run_repository } from "../task-run-repository.js";
5
- import { TaskReadModelProjector } from "../task-read-model-projector.js";
6
- import { TaskConversationRepository } from "../task-conversation-repository.js";
7
5
  import { CapabilityError } from "../../capabilities/runtime/errors.js";
8
6
  import { defineReadCapability } from "../../capabilities/runtime/dispatcher.js";
7
+ import { TaskReadModelProjector } from "../task-read-model-projector.js";
8
+ import { TaskConversationRepository } from "../task-conversation-repository.js";
9
9
  import { TaskContextRepository } from "../task-context-repository.js";
10
10
  import { TaskDependencyService } from "../task-dependency-service.js";
11
11
  import { TaskCriterionReviewRepository } from "../task-criterion-review-repository.js";
@@ -2,9 +2,9 @@ import { TaskCommandRequestSchema, TaskCreateRequestSchema, TaskDetailResponseSc
2
2
  import { init_src } from "../../../packages/gateway-contract/src/index.js";
3
3
  import { TaskRepository, init_task_repository } from "../task-repository.js";
4
4
  import { TaskRunRepository, init_task_run_repository } from "../task-run-repository.js";
5
- import { resolveTaskLocale } from "../task-language.js";
6
5
  import { CapabilityError } from "../../capabilities/runtime/errors.js";
7
6
  import { defineAtomicCapability } from "../../capabilities/runtime/dispatcher.js";
7
+ import { resolveTaskLocale } from "../task-language.js";
8
8
  import { resolveProjectAgentId } from "../../projects/project-agent.js";
9
9
  import { resolveResponseLanguageForSession } from "../../agent/prompt/response-language.js";
10
10
  import { TaskApplicationService } from "../task-application-service.js";
@@ -10,6 +10,7 @@ import { getSessionMetadata } from "../../storage/sqlite/session-read-repository
10
10
  import { init_sqlite } from "../../storage/sqlite/index.js";
11
11
  import { normalizeAgentId } from "../../agent-catalog/id.js";
12
12
  import { init_agent_scope, listAgentEntries } from "../../agent/agent-scope.js";
13
+ import { AgentCatalogService } from "../../agent-catalog/service.js";
13
14
  import { init_paths } from "../../config/paths.js";
14
15
  import { getAgentDefaultModelRef, init_schema } from "../../config/schema.js";
15
16
  import { resolveEffectiveAgentProfile } from "../../config/agent-profile.js";
@@ -22,7 +23,6 @@ import { buildSessionTimeline } from "../../session/transcript-outline.js";
22
23
  import { transcriptRowsToClientHistory } from "../../session/client-history.js";
23
24
  import { createCreateShareTool, isShareToolAvailable } from "../../agent/tools/create-share-tool.js";
24
25
  import { evictEmbeddedSessionRunner } from "../../agent/embedded/session-runner.js";
25
- import { AgentCatalogService } from "../../agent-catalog/service.js";
26
26
  import { SessionIndex } from "../../session/manager.js";
27
27
  import "../../session/index.js";
28
28
  import { parseModelRef } from "../../agent/models/selection.js";
@@ -1,6 +1,6 @@
1
1
  import { init_agent_scope, resolveAgentProfileDir } from "../../agent/agent-scope.js";
2
- import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
3
2
  import { DEFAULT_SOUL_FILENAME } from "../../agent/context/workspace.js";
3
+ import { resolveEffectiveAgentProfileForSession } from "../../config/agent-profile.js";
4
4
  import { loadProfileBootstrapFiles } from "../../agent/bootstrap/load-bootstrap-files.js";
5
5
  import { join } from "node:path";
6
6
  import { statSync } from "node:fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xopcai/xopc",
3
- "version": "0.0.413",
3
+ "version": "0.0.414",
4
4
  "description": "Local-first personal AI with Ada, task delegation, files, projects and automations. Use cloud or local models.",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -172,10 +172,10 @@
172
172
  "xlsx": "file:web/vendor/xlsx-0.20.3.tgz",
173
173
  "@xopcai/browser-control-contract": "0.1.0",
174
174
  "@xopcai/computer-control-contract": "0.1.0",
175
- "@xopcai/endpoint-tools-protocol": "0.0.0",
176
- "@xopcai/gateway-contract": "0.0.0",
177
175
  "@xopcai/endpoint-tools-client": "0.0.0",
176
+ "@xopcai/endpoint-tools-protocol": "0.0.0",
178
177
  "@xopcai/image-providers": "0.1.0",
178
+ "@xopcai/gateway-contract": "0.0.0",
179
179
  "@xopcai/realtime-client": "0.0.0",
180
180
  "@xopcai/realtime-protocol": "0.0.0"
181
181
  },