@toddzheng024/dscode-desktop 0.0.0-stage → 0.7.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -2
  3. package/THIRD_PARTY_NOTICES.md +30 -0
  4. package/bin/apply_patch +9 -0
  5. package/cordis.patch.yml +433 -0
  6. package/docs/CHANGELOG.md +641 -0
  7. package/docs/account-login.md +44 -0
  8. package/docs/auto-review.md +128 -0
  9. package/docs/browser-use.md +783 -0
  10. package/docs/computer-use.md +81 -0
  11. package/docs/custom-providers.md +88 -0
  12. package/docs/demo.md +76 -0
  13. package/docs/distribution.md +58 -0
  14. package/docs/dscode-ultra.md +75 -0
  15. package/docs/email.md +296 -0
  16. package/docs/exec.md +40 -0
  17. package/docs/hub-distribution.md +190 -0
  18. package/docs/memory.md +121 -0
  19. package/docs/opencode-go.md +61 -0
  20. package/docs/plugin-hub.md +68 -0
  21. package/docs/releases/0.2.0.md +28 -0
  22. package/docs/releases/0.3.0.md +21 -0
  23. package/docs/releases/0.4.0.md +20 -0
  24. package/docs/releases/0.5.0.md +19 -0
  25. package/docs/releases/0.6.0.md +20 -0
  26. package/docs/releases/0.7.0.md +22 -0
  27. package/docs/releases/0.7.1.md +20 -0
  28. package/docs/releases/0.7.10.md +10 -0
  29. package/docs/releases/0.7.11.md +17 -0
  30. package/docs/releases/0.7.12.md +11 -0
  31. package/docs/releases/0.7.13.md +12 -0
  32. package/docs/releases/0.7.14.md +11 -0
  33. package/docs/releases/0.7.15.md +11 -0
  34. package/docs/releases/0.7.16.md +10 -0
  35. package/docs/releases/0.7.17.md +12 -0
  36. package/docs/releases/0.7.18.md +13 -0
  37. package/docs/releases/0.7.19.md +8 -0
  38. package/docs/releases/0.7.2.md +19 -0
  39. package/docs/releases/0.7.20.md +10 -0
  40. package/docs/releases/0.7.21.md +9 -0
  41. package/docs/releases/0.7.22.md +11 -0
  42. package/docs/releases/0.7.23.md +14 -0
  43. package/docs/releases/0.7.24.md +11 -0
  44. package/docs/releases/0.7.25.md +8 -0
  45. package/docs/releases/0.7.26.md +18 -0
  46. package/docs/releases/0.7.27.md +8 -0
  47. package/docs/releases/0.7.28.md +22 -0
  48. package/docs/releases/0.7.29.md +12 -0
  49. package/docs/releases/0.7.3.md +23 -0
  50. package/docs/releases/0.7.30.md +19 -0
  51. package/docs/releases/0.7.31.md +14 -0
  52. package/docs/releases/0.7.32.md +14 -0
  53. package/docs/releases/0.7.33.md +30 -0
  54. package/docs/releases/0.7.4.md +16 -0
  55. package/docs/releases/0.7.5.md +18 -0
  56. package/docs/releases/0.7.6.md +29 -0
  57. package/docs/releases/0.7.7.md +36 -0
  58. package/docs/releases/0.7.8.md +14 -0
  59. package/docs/releases/0.7.9.md +15 -0
  60. package/docs/session-bridge.md +80 -0
  61. package/docs/session-cards.md +53 -0
  62. package/docs/session-communication.md +186 -0
  63. package/docs/session-metrics.md +41 -0
  64. package/docs/skills.md +81 -0
  65. package/docs/triggers.md +338 -0
  66. package/docs/tui-commands.md +204 -0
  67. package/extensions/browser/manifest.json +22 -0
  68. package/extensions/browser/popup.css +6 -0
  69. package/extensions/browser/popup.html +11 -0
  70. package/extensions/browser/popup.mjs +47 -0
  71. package/extensions/browser/protocol.mjs +168 -0
  72. package/extensions/browser/worker.mjs +94 -0
  73. package/icon.svg +7 -0
  74. package/locale/en.json +6 -0
  75. package/locale/zh-cn.json +6 -0
  76. package/node_modules/@deepseek-ai/node-addon-system/LICENSE +21 -0
  77. package/node_modules/@deepseek-ai/node-addon-system/README.i18n.yaml +6 -0
  78. package/node_modules/@deepseek-ai/node-addon-system/README.md +15 -0
  79. package/node_modules/@deepseek-ai/node-addon-system/README.zh.md +15 -0
  80. package/node_modules/@deepseek-ai/node-addon-system/lib/flock.d.ts +13 -0
  81. package/node_modules/@deepseek-ai/node-addon-system/lib/flock.js +51 -0
  82. package/node_modules/@deepseek-ai/node-addon-system/lib/index.d.ts +73 -0
  83. package/node_modules/@deepseek-ai/node-addon-system/lib/index.js +98 -0
  84. package/node_modules/@deepseek-ai/node-addon-system/package.json +45 -0
  85. package/node_modules/@deepseek-ai/node-addon-system/src/flock.c +164 -0
  86. package/node_modules/@deepseek-ai/node-addon-system/src/main.c +298 -0
  87. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/LICENSE +28 -0
  88. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.i18n.yaml +6 -0
  89. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.md +9 -0
  90. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/README.zh.md +9 -0
  91. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/bin/system.node +0 -0
  92. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/package.json +31 -0
  93. package/node_modules/@deepseek-ai/node-addon-system-darwin-arm64/prebuilds.json +6 -0
  94. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/LICENSE +28 -0
  95. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.i18n.yaml +6 -0
  96. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.md +9 -0
  97. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/README.zh.md +9 -0
  98. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/bin/system.node +0 -0
  99. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/package.json +31 -0
  100. package/node_modules/@deepseek-ai/node-addon-system-darwin-x64/prebuilds.json +6 -0
  101. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/LICENSE +28 -0
  102. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.i18n.yaml +6 -0
  103. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.md +11 -0
  104. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/README.zh.md +11 -0
  105. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/glibc/system.node +0 -0
  106. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/landlock-run +0 -0
  107. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/bin/musl/system.node +0 -0
  108. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/package.json +31 -0
  109. package/node_modules/@deepseek-ai/node-addon-system-linux-arm64/prebuilds.json +24 -0
  110. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/LICENSE +28 -0
  111. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.i18n.yaml +6 -0
  112. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.md +11 -0
  113. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/README.zh.md +11 -0
  114. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/glibc/system.node +0 -0
  115. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/landlock-run +0 -0
  116. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/bin/musl/system.node +0 -0
  117. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/package.json +31 -0
  118. package/node_modules/@deepseek-ai/node-addon-system-linux-x64/prebuilds.json +24 -0
  119. package/package.json +156 -4
  120. package/plugins/account/index.mjs +178 -0
  121. package/plugins/account/state.mjs +123 -0
  122. package/plugins/auto-review/audit.mjs +24 -0
  123. package/plugins/auto-review/index.mjs +267 -0
  124. package/plugins/auto-review/policy.mjs +92 -0
  125. package/plugins/browser/SKILL.md +158 -0
  126. package/plugins/browser/access.mjs +143 -0
  127. package/plugins/browser/config.mjs +60 -0
  128. package/plugins/browser/connection.mjs +385 -0
  129. package/plugins/browser/desktop-client.mjs +282 -0
  130. package/plugins/browser/desktop-host.mjs +74 -0
  131. package/plugins/browser/document-identity.mjs +57 -0
  132. package/plugins/browser/extension-relay.mjs +66 -0
  133. package/plugins/browser/files.mjs +32 -0
  134. package/plugins/browser/index.mjs +235 -0
  135. package/plugins/browser/mcp-entry.mjs +18 -0
  136. package/plugins/browser/mcp-tools.mjs +21 -0
  137. package/plugins/browser/presentation.mjs +45 -0
  138. package/plugins/browser/preview.mjs +77 -0
  139. package/plugins/browser/review.mjs +20 -0
  140. package/plugins/browser/screenshots.mjs +35 -0
  141. package/plugins/clipboard-image/clipboard-image.swift +56 -0
  142. package/plugins/clipboard-image/index.mjs +70 -0
  143. package/plugins/code-review/baseline.mjs +143 -0
  144. package/plugins/code-review/git.mjs +163 -0
  145. package/plugins/code-review/index.mjs +236 -0
  146. package/plugins/compaction/engine.mjs +304 -0
  147. package/plugins/compaction/tetris.mjs +65 -0
  148. package/plugins/compaction/threshold.mjs +98 -0
  149. package/plugins/computer-use/DESKTOP-SKILL.md +64 -0
  150. package/plugins/computer-use/desktop-host.mjs +75 -0
  151. package/plugins/computer-use/desktop-skill.mjs +28 -0
  152. package/plugins/computer-use/desktop-upstream.mjs +3 -0
  153. package/plugins/computer-use/index.mjs +37 -0
  154. package/plugins/cordis-config/plain.mjs +31 -0
  155. package/plugins/credentials/index.mjs +73 -0
  156. package/plugins/custom/adapter.mjs +110 -0
  157. package/plugins/custom/config.mjs +85 -0
  158. package/plugins/custom/desktop-client.mjs +150 -0
  159. package/plugins/custom/desktop-host.mjs +78 -0
  160. package/plugins/custom/images.mjs +32 -0
  161. package/plugins/custom/index.mjs +145 -0
  162. package/plugins/custom/wire.mjs +179 -0
  163. package/plugins/desktop/client.mjs +1041 -0
  164. package/plugins/desktop/index.mjs +10 -0
  165. package/plugins/desktop/shell-environment.mjs +9 -0
  166. package/plugins/desktop-workspace/hooks.mjs +29 -0
  167. package/plugins/desktop-workspace/index.mjs +37 -0
  168. package/plugins/dscode/board.mjs +260 -0
  169. package/plugins/dscode/child-target.mjs +11 -0
  170. package/plugins/dscode/control.mjs +17 -0
  171. package/plugins/dscode/desktop-client.mjs +55 -0
  172. package/plugins/dscode/desktop-host.mjs +37 -0
  173. package/plugins/dscode/index.mjs +270 -0
  174. package/plugins/email/cli.mjs +32 -0
  175. package/plugins/email/contacts.mjs +36 -0
  176. package/plugins/email/desktop-client.mjs +117 -0
  177. package/plugins/email/desktop-host.mjs +54 -0
  178. package/plugins/email/desktop-service.mjs +106 -0
  179. package/plugins/email/gmail-oauth.mjs +69 -0
  180. package/plugins/email/gmail-store.mjs +2 -0
  181. package/plugins/email/gmail.mjs +194 -0
  182. package/plugins/email/imap.mjs +136 -0
  183. package/plugins/email/inbox.d.mts +25 -0
  184. package/plugins/email/inbox.mjs +76 -0
  185. package/plugins/email/smtp.mjs +70 -0
  186. package/plugins/email/store.mjs +32 -0
  187. package/plugins/email-tools/index.mjs +46 -0
  188. package/plugins/exec/cli.mjs +64 -0
  189. package/plugins/exec/index.mjs +112 -0
  190. package/plugins/grok/adapter.mjs +114 -0
  191. package/plugins/grok/auth.mjs +76 -0
  192. package/plugins/grok/billing.mjs +146 -0
  193. package/plugins/grok/index.mjs +122 -0
  194. package/plugins/grok/models.mjs +129 -0
  195. package/plugins/grok/status.mjs +28 -0
  196. package/plugins/grok/wire.mjs +268 -0
  197. package/plugins/hub/catalog.mjs +82 -0
  198. package/plugins/hub/desktop-client.mjs +114 -0
  199. package/plugins/hub/desktop-host.mjs +129 -0
  200. package/plugins/i18n/messages.d.mts +21 -0
  201. package/plugins/i18n/messages.mjs +537 -0
  202. package/plugins/jev/approval.mjs +131 -0
  203. package/plugins/jev/client.mjs +74 -0
  204. package/plugins/jev/index.mjs +99 -0
  205. package/plugins/memory/content.mjs +57 -0
  206. package/plugins/memory/desktop-host.mjs +3 -0
  207. package/plugins/memory/index.mjs +168 -0
  208. package/plugins/memory/pipeline.mjs +79 -0
  209. package/plugins/memory/store.mjs +93 -0
  210. package/plugins/message-source/kind.mjs +20 -0
  211. package/plugins/opencode-go/adapter.mjs +96 -0
  212. package/plugins/opencode-go/command.mjs +128 -0
  213. package/plugins/opencode-go/index.mjs +120 -0
  214. package/plugins/opencode-go/models.mjs +58 -0
  215. package/plugins/opencode-go/oauth.mjs +194 -0
  216. package/plugins/opencode-go/search.mjs +86 -0
  217. package/plugins/opencode-go/usage.mjs +119 -0
  218. package/plugins/opencode-go/version.mjs +10 -0
  219. package/plugins/opencode-go/wire.mjs +73 -0
  220. package/plugins/openrouter/adapter.mjs +232 -0
  221. package/plugins/openrouter/index.mjs +123 -0
  222. package/plugins/openrouter/models.mjs +157 -0
  223. package/plugins/openrouter/search.mjs +113 -0
  224. package/plugins/openrouter/wire.mjs +101 -0
  225. package/plugins/providers/catalog.mjs +160 -0
  226. package/plugins/providers/chat-messages.mjs +120 -0
  227. package/plugins/providers/chat-stream.mjs +174 -0
  228. package/plugins/providers/desktop-client.mjs +84 -0
  229. package/plugins/providers/desktop-host.mjs +63 -0
  230. package/plugins/providers/effort.mjs +35 -0
  231. package/plugins/providers/http-errors.mjs +50 -0
  232. package/plugins/providers/openrouter-account.mjs +171 -0
  233. package/plugins/session-bridge/client.mjs +106 -0
  234. package/plugins/session-bridge/communication.mjs +260 -0
  235. package/plugins/session-bridge/index.mjs +68 -0
  236. package/plugins/session-bridge/mailbox.mjs +267 -0
  237. package/plugins/session-bridge/paths.mjs +21 -0
  238. package/plugins/session-bridge/server.mjs +172 -0
  239. package/plugins/session-bridge/tasks.mjs +229 -0
  240. package/plugins/session-cards/content.mjs +64 -0
  241. package/plugins/session-cards/index.mjs +38 -0
  242. package/plugins/session-cards/manager.mjs +140 -0
  243. package/plugins/session-metrics/attribution.mjs +30 -0
  244. package/plugins/session-metrics/balance.mjs +81 -0
  245. package/plugins/session-metrics/desktop-client.mjs +62 -0
  246. package/plugins/session-metrics/desktop-host.mjs +46 -0
  247. package/plugins/session-metrics/index.mjs +96 -0
  248. package/plugins/session-metrics/pricing.mjs +84 -0
  249. package/plugins/session-metrics/rate.mjs +59 -0
  250. package/plugins/session-metrics/store.mjs +75 -0
  251. package/plugins/session-metrics/turns.mjs +134 -0
  252. package/plugins/session-metrics/view.mjs +271 -0
  253. package/plugins/time-marks/desktop-host.mjs +2 -0
  254. package/plugins/time-marks/index.mjs +116 -0
  255. package/plugins/time-marks/marks.mjs +152 -0
  256. package/plugins/triggers/cli.mjs +558 -0
  257. package/plugins/triggers/commands.mjs +143 -0
  258. package/plugins/triggers/config.mjs +264 -0
  259. package/plugins/triggers/desktop-client.mjs +155 -0
  260. package/plugins/triggers/desktop-host.mjs +88 -0
  261. package/plugins/triggers/desktop-management.mjs +97 -0
  262. package/plugins/triggers/desktop-scheduler.mjs +125 -0
  263. package/plugins/triggers/host.mjs +24 -0
  264. package/plugins/triggers/index.mjs +27 -0
  265. package/plugins/triggers/job-cli.mjs +110 -0
  266. package/plugins/triggers/jobs.mjs +156 -0
  267. package/plugins/triggers/launchd.mjs +101 -0
  268. package/plugins/triggers/lease.mjs +24 -0
  269. package/plugins/triggers/log.mjs +104 -0
  270. package/plugins/triggers/management.mjs +181 -0
  271. package/plugins/triggers/options.mjs +117 -0
  272. package/plugins/triggers/overlay.mjs +7 -0
  273. package/plugins/triggers/poll.mjs +65 -0
  274. package/plugins/triggers/run.mjs +157 -0
  275. package/plugins/triggers/schedule.mjs +40 -0
  276. package/plugins/triggers/scheduler-service.mjs +46 -0
  277. package/plugins/triggers/scheduler.mjs +92 -0
  278. package/plugins/triggers/session-run.mjs +125 -0
  279. package/plugins/triggers/session.mjs +48 -0
  280. package/plugins/triggers/source-emit.mjs +19 -0
  281. package/plugins/triggers/source-host.mjs +78 -0
  282. package/plugins/triggers/source-ingress.mjs +70 -0
  283. package/plugins/triggers/source-sandbox.mjs +35 -0
  284. package/plugins/triggers/sources.mjs +45 -0
  285. package/plugins/triggers/spool.mjs +145 -0
  286. package/plugins/triggers/tools.mjs +67 -0
  287. package/plugins/triggers/unattended.mjs +18 -0
  288. package/plugins/tui-tools/composition.mjs +28 -0
  289. package/plugins/tui-tools/desktop-host.mjs +2 -0
  290. package/plugins/tui-tools/doctor-cli.mjs +22 -0
  291. package/plugins/tui-tools/doctor.mjs +148 -0
  292. package/plugins/tui-tools/hook-sources.mjs +113 -0
  293. package/plugins/tui-tools/hooks.mjs +23 -0
  294. package/plugins/tui-tools/index.mjs +268 -0
  295. package/plugins/tui-tools/sandbox-runner.mjs +123 -0
  296. package/plugins/tui-tools/shell.mjs +27 -0
  297. package/plugins/tui-tools/update.mjs +111 -0
  298. package/plugins/tui-tools/workspace-discovery.mjs +129 -0
  299. package/plugins/ultra/policy.mjs +42 -0
  300. package/plugins/worktree-subagent/worktree.mjs +56 -0
  301. package/runtime-sources.json +94 -0
  302. package/vendor/bash/LICENSE +21 -0
  303. package/vendor/bash/index.js +717 -0
  304. package/vendor/bash/types/background.d.ts +50 -0
  305. package/vendor/bash/types/index.d.ts +38 -0
  306. package/vendor/bash/types/render.d.ts +57 -0
  307. package/vendor/command-goal/LICENSE +21 -0
  308. package/vendor/command-goal/index.js +210 -0
  309. package/vendor/command-goal/types/index.d.ts +10 -0
  310. package/vendor/computer-use/LICENSE +21 -0
  311. package/vendor/computer-use/lib/approval-policy.js +12 -0
  312. package/vendor/computer-use/lib/approval-policy.js.map +1 -0
  313. package/vendor/computer-use/lib/artifacts.js +79 -0
  314. package/vendor/computer-use/lib/artifacts.js.map +1 -0
  315. package/vendor/computer-use/lib/backend.js +3 -0
  316. package/vendor/computer-use/lib/backend.js.map +1 -0
  317. package/vendor/computer-use/lib/client.js +369 -0
  318. package/vendor/computer-use/lib/client.js.map +1 -0
  319. package/vendor/computer-use/lib/config.js +159 -0
  320. package/vendor/computer-use/lib/config.js.map +1 -0
  321. package/vendor/computer-use/lib/confirmations.js +99 -0
  322. package/vendor/computer-use/lib/confirmations.js.map +1 -0
  323. package/vendor/computer-use/lib/diff.js +58 -0
  324. package/vendor/computer-use/lib/diff.js.map +1 -0
  325. package/vendor/computer-use/lib/errors.js +22 -0
  326. package/vendor/computer-use/lib/errors.js.map +1 -0
  327. package/vendor/computer-use/lib/exposure.js +244 -0
  328. package/vendor/computer-use/lib/exposure.js.map +1 -0
  329. package/vendor/computer-use/lib/index.js +66 -0
  330. package/vendor/computer-use/lib/index.js.map +1 -0
  331. package/vendor/computer-use/lib/leases.js +262 -0
  332. package/vendor/computer-use/lib/leases.js.map +1 -0
  333. package/vendor/computer-use/lib/providers/macos.js +243 -0
  334. package/vendor/computer-use/lib/providers/macos.js.map +1 -0
  335. package/vendor/computer-use/lib/providers/native-helper.js +726 -0
  336. package/vendor/computer-use/lib/providers/native-helper.js.map +1 -0
  337. package/vendor/computer-use/lib/providers/unsupported.js +51 -0
  338. package/vendor/computer-use/lib/providers/unsupported.js.map +1 -0
  339. package/vendor/computer-use/lib/service.js +608 -0
  340. package/vendor/computer-use/lib/service.js.map +1 -0
  341. package/vendor/computer-use/lib/skill.js +136 -0
  342. package/vendor/computer-use/lib/skill.js.map +1 -0
  343. package/vendor/computer-use/lib/target-resolver.js +180 -0
  344. package/vendor/computer-use/lib/target-resolver.js.map +1 -0
  345. package/vendor/computer-use/lib/tools.js +511 -0
  346. package/vendor/computer-use/lib/tools.js.map +1 -0
  347. package/vendor/computer-use/lib/types/approval-policy.d.ts +13 -0
  348. package/vendor/computer-use/lib/types/approval-policy.d.ts.map +1 -0
  349. package/vendor/computer-use/lib/types/artifacts.d.ts +10 -0
  350. package/vendor/computer-use/lib/types/artifacts.d.ts.map +1 -0
  351. package/vendor/computer-use/lib/types/backend.d.ts +124 -0
  352. package/vendor/computer-use/lib/types/backend.d.ts.map +1 -0
  353. package/vendor/computer-use/lib/types/client/index.d.ts +83 -0
  354. package/vendor/computer-use/lib/types/client/index.d.ts.map +1 -0
  355. package/vendor/computer-use/lib/types/config.d.ts +94 -0
  356. package/vendor/computer-use/lib/types/config.d.ts.map +1 -0
  357. package/vendor/computer-use/lib/types/confirmations.d.ts +23 -0
  358. package/vendor/computer-use/lib/types/confirmations.d.ts.map +1 -0
  359. package/vendor/computer-use/lib/types/diff.d.ts +5 -0
  360. package/vendor/computer-use/lib/types/diff.d.ts.map +1 -0
  361. package/vendor/computer-use/lib/types/errors.d.ts +15 -0
  362. package/vendor/computer-use/lib/types/errors.d.ts.map +1 -0
  363. package/vendor/computer-use/lib/types/exposure.d.ts +30 -0
  364. package/vendor/computer-use/lib/types/exposure.d.ts.map +1 -0
  365. package/vendor/computer-use/lib/types/index.d.ts +21 -0
  366. package/vendor/computer-use/lib/types/index.d.ts.map +1 -0
  367. package/vendor/computer-use/lib/types/leases.d.ts +81 -0
  368. package/vendor/computer-use/lib/types/leases.d.ts.map +1 -0
  369. package/vendor/computer-use/lib/types/providers/macos.d.ts +39 -0
  370. package/vendor/computer-use/lib/types/providers/macos.d.ts.map +1 -0
  371. package/vendor/computer-use/lib/types/providers/native-helper.d.ts +48 -0
  372. package/vendor/computer-use/lib/types/providers/native-helper.d.ts.map +1 -0
  373. package/vendor/computer-use/lib/types/providers/unsupported.d.ts +23 -0
  374. package/vendor/computer-use/lib/types/providers/unsupported.d.ts.map +1 -0
  375. package/vendor/computer-use/lib/types/service.d.ts +58 -0
  376. package/vendor/computer-use/lib/types/service.d.ts.map +1 -0
  377. package/vendor/computer-use/lib/types/skill.d.ts +14 -0
  378. package/vendor/computer-use/lib/types/skill.d.ts.map +1 -0
  379. package/vendor/computer-use/lib/types/target-resolver.d.ts +38 -0
  380. package/vendor/computer-use/lib/types/target-resolver.d.ts.map +1 -0
  381. package/vendor/computer-use/lib/types/tools.d.ts +6 -0
  382. package/vendor/computer-use/lib/types/tools.d.ts.map +1 -0
  383. package/vendor/computer-use/lib/types/types.d.ts +270 -0
  384. package/vendor/computer-use/lib/types/types.d.ts.map +1 -0
  385. package/vendor/computer-use/lib/types/web.d.ts +33 -0
  386. package/vendor/computer-use/lib/types/web.d.ts.map +1 -0
  387. package/vendor/computer-use/lib/types.js +9 -0
  388. package/vendor/computer-use/lib/types.js.map +1 -0
  389. package/vendor/computer-use/lib/web.js +188 -0
  390. package/vendor/computer-use/lib/web.js.map +1 -0
  391. package/vendor/computer-use/native/macos/Sources/Fixture/main.swift +412 -0
  392. package/vendor/computer-use/native/macos/Sources/Helper/CursorImage.swift +11 -0
  393. package/vendor/computer-use/native/macos/Sources/Helper/CursorMotion.swift +67 -0
  394. package/vendor/computer-use/native/macos/Sources/Helper/CursorOverlay.swift +840 -0
  395. package/vendor/computer-use/native/macos/Sources/Helper/TargetedPointer.swift +327 -0
  396. package/vendor/computer-use/native/macos/Sources/Helper/WindowNumberMatcher.swift +29 -0
  397. package/vendor/computer-use/native/macos/Sources/Helper/main.swift +1244 -0
  398. package/vendor/computer-use/native/macos/Sources/Monitor/main.swift +153 -0
  399. package/vendor/computer-use/native/macos/bin/dsh-computer-use-helper +0 -0
  400. package/vendor/computer-use/native/macos/manifest.json +14 -0
  401. package/vendor/persistent/LICENSE +21 -0
  402. package/vendor/persistent/index.js +411 -0
  403. package/vendor/persistent/types/index.d.ts +24 -0
  404. package/vendor/subagent/LICENSE +21 -0
  405. package/vendor/subagent/index.js +694 -0
  406. package/vendor/subagent/invariant.js +52 -0
  407. package/vendor/subagent/model-selection-settings.js +68 -0
  408. package/vendor/subagent/types/index.d.ts +82 -0
  409. package/vendor/subagent/types/invariant.d.ts +16 -0
  410. package/vendor/subagent/types/list-models.d.ts +10 -0
  411. package/vendor/subagent/types/model-selection-settings.d.ts +45 -0
  412. package/vendor/subagent/types/model-selection-state.d.ts +48 -0
  413. package/vendor/subagent/types/model-selection.d.ts +81 -0
  414. package/vendor/subagent-core/LICENSE +21 -0
  415. package/vendor/subagent-core/index.js +3202 -0
  416. package/vendor/subagent-core/invariant.js +76 -0
  417. package/vendor/subagent-core/typert.host.d.ts +3 -0
  418. package/vendor/subagent-core/typert.host.js +978 -0
  419. package/vendor/subagent-core/typert.remote-client.d.ts +25 -0
  420. package/vendor/subagent-core/typert.remote-client.js +114 -0
  421. package/vendor/subagent-core/types/archive-admission.d.ts +16 -0
  422. package/vendor/subagent-core/types/archive-admission.js +151 -0
  423. package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
  424. package/vendor/subagent-core/types/assistant-output.js +73 -0
  425. package/vendor/subagent-core/types/catalog.d.ts +84 -0
  426. package/vendor/subagent-core/types/catalog.js +109 -0
  427. package/vendor/subagent-core/types/child-agent.d.ts +156 -0
  428. package/vendor/subagent-core/types/child-agent.js +213 -0
  429. package/vendor/subagent-core/types/client.d.ts +8 -0
  430. package/vendor/subagent-core/types/client.js +7 -0
  431. package/vendor/subagent-core/types/continuation-activation.d.ts +267 -0
  432. package/vendor/subagent-core/types/continuation-activation.js +700 -0
  433. package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
  434. package/vendor/subagent-core/types/continuation-messages.js +106 -0
  435. package/vendor/subagent-core/types/continuation.d.ts +124 -0
  436. package/vendor/subagent-core/types/continuation.js +455 -0
  437. package/vendor/subagent-core/types/control-types.d.ts +135 -0
  438. package/vendor/subagent-core/types/control-types.js +8 -0
  439. package/vendor/subagent-core/types/control.d.ts +45 -0
  440. package/vendor/subagent-core/types/control.js +79 -0
  441. package/vendor/subagent-core/types/depth.d.ts +31 -0
  442. package/vendor/subagent-core/types/depth.js +39 -0
  443. package/vendor/subagent-core/types/descriptor.d.ts +144 -0
  444. package/vendor/subagent-core/types/descriptor.js +193 -0
  445. package/vendor/subagent-core/types/error.d.ts +11 -0
  446. package/vendor/subagent-core/types/error.js +14 -0
  447. package/vendor/subagent-core/types/inbox.d.ts +43 -0
  448. package/vendor/subagent-core/types/inbox.js +61 -0
  449. package/vendor/subagent-core/types/index.d.ts +320 -0
  450. package/vendor/subagent-core/types/index.js +475 -0
  451. package/vendor/subagent-core/types/internal.d.ts +58 -0
  452. package/vendor/subagent-core/types/internal.js +58 -0
  453. package/vendor/subagent-core/types/invariant.d.ts +13 -0
  454. package/vendor/subagent-core/types/invariant.js +91 -0
  455. package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
  456. package/vendor/subagent-core/types/lifecycle.js +180 -0
  457. package/vendor/subagent-core/types/list-children.d.ts +36 -0
  458. package/vendor/subagent-core/types/list-children.js +166 -0
  459. package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
  460. package/vendor/subagent-core/types/out-of-process.js +219 -0
  461. package/vendor/subagent-core/types/projection-types.d.ts +82 -0
  462. package/vendor/subagent-core/types/projection-types.js +7 -0
  463. package/vendor/subagent-core/types/projection.d.ts +100 -0
  464. package/vendor/subagent-core/types/projection.js +157 -0
  465. package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
  466. package/vendor/subagent-core/types/run-settlement.js +70 -0
  467. package/vendor/subagent-core/types/types.d.ts +377 -0
  468. package/vendor/subagent-core/types/types.js +19 -0
  469. package/vendor/subagent-driver/LICENSE +21 -0
  470. package/vendor/subagent-driver/index.js +255 -0
  471. package/vendor/subagent-driver/types/index.d.ts +33 -0
  472. package/vendor/subagent-driver/types/structured.d.ts +42 -0
  473. package/vendor/subagent-fork/LICENSE +21 -0
  474. package/vendor/subagent-fork/index.js +61 -0
  475. package/vendor/subagent-fork/types/index.d.ts +20 -0
  476. package/vendor/subagent-spawn/LICENSE +21 -0
  477. package/vendor/subagent-spawn/index.js +45 -0
  478. package/vendor/subagent-spawn/types/index.d.ts +19 -0
  479. package/vendor/terminal/LICENSE +21 -0
  480. package/vendor/terminal/index.js +1093 -0
  481. package/vendor/terminal/types/config.d.ts +82 -0
  482. package/vendor/terminal/types/index.d.ts +36 -0
  483. package/vendor/terminal/types/sanitize.d.ts +47 -0
  484. package/vendor/terminal/types/session.d.ts +87 -0
@@ -0,0 +1,840 @@
1
+ import AppKit
2
+ import CoreGraphics
3
+ import Darwin
4
+ import Foundation
5
+ import QuartzCore
6
+
7
+ private struct CursorOverlayCommand {
8
+ let operation: String
9
+ let point: CGPoint?
10
+ let durationMs: Int?
11
+ let speedPxPerSecond: Double?
12
+ let accelerationPxPerSecondSquared: Double?
13
+ let autoHideMs: Int
14
+ let targetPid: pid_t?
15
+ let targetWindowNumber: Int64?
16
+ let targetWindowFrame: CGRect?
17
+ let sustainedPress: Bool
18
+
19
+ private static let maximumCoordinateMagnitude = 100_000.0
20
+ private static let maximumDurationMs = 2_000
21
+ private static let maximumSpeedPxPerSecond = 50_000.0
22
+ private static let maximumAccelerationPxPerSecondSquared = 500_000.0
23
+ private static let maximumAutoHideMs = 30_000
24
+
25
+ private static func number(_ object: Any?, field: String) throws -> NSNumber? {
26
+ guard let object else { return nil }
27
+ guard let value = object as? NSNumber,
28
+ CFGetTypeID(value) != CFBooleanGetTypeID() else {
29
+ throw CursorOverlayError(message: "cursor overlay \(field) must be numeric")
30
+ }
31
+ return value
32
+ }
33
+
34
+ private static func integer(_ object: Any?, field: String, fallback: Int) throws -> Int {
35
+ guard let value = try number(object, field: field) else { return fallback }
36
+ let doubleValue = value.doubleValue
37
+ guard doubleValue.isFinite, doubleValue.rounded(.towardZero) == doubleValue,
38
+ doubleValue >= Double(Int.min), doubleValue <= Double(Int.max) else {
39
+ throw CursorOverlayError(message: "cursor overlay \(field) must be an integer")
40
+ }
41
+ return Int(doubleValue)
42
+ }
43
+
44
+ init(_ object: [String: Any]) throws {
45
+ guard let operation = object["op"] as? String else {
46
+ throw CursorOverlayError(message: "cursor overlay command is missing op")
47
+ }
48
+ self.operation = operation
49
+ let x = try Self.number(object["x"], field: "x")
50
+ let y = try Self.number(object["y"], field: "y")
51
+ if let x, let y {
52
+ let xValue = x.doubleValue
53
+ let yValue = y.doubleValue
54
+ guard xValue.isFinite, yValue.isFinite,
55
+ abs(xValue) <= Self.maximumCoordinateMagnitude,
56
+ abs(yValue) <= Self.maximumCoordinateMagnitude else {
57
+ throw CursorOverlayError(message: "cursor overlay coordinates are outside the supported range")
58
+ }
59
+ self.point = CGPoint(x: xValue, y: yValue)
60
+ } else {
61
+ self.point = nil
62
+ }
63
+ let durationMs = object["durationMs"] == nil
64
+ ? nil
65
+ : try Self.integer(object["durationMs"], field: "durationMs", fallback: 180)
66
+ let autoHideMs = try Self.integer(object["autoHideMs"], field: "autoHideMs", fallback: 0)
67
+ guard durationMs == nil || (durationMs! >= 0 && durationMs! <= Self.maximumDurationMs),
68
+ autoHideMs >= 0, autoHideMs <= Self.maximumAutoHideMs else {
69
+ throw CursorOverlayError(message: "cursor overlay timing is outside the supported range")
70
+ }
71
+ self.durationMs = durationMs
72
+ self.autoHideMs = autoHideMs
73
+ let speed = try Self.number(object["speedPxPerSecond"], field: "speedPxPerSecond")?.doubleValue
74
+ let acceleration = try Self.number(
75
+ object["accelerationPxPerSecondSquared"],
76
+ field: "accelerationPxPerSecondSquared"
77
+ )?.doubleValue
78
+ guard (speed == nil) == (acceleration == nil) else {
79
+ throw CursorOverlayError(message: "cursor overlay speed and acceleration must be provided together")
80
+ }
81
+ guard speed == nil || (speed!.isFinite && speed! >= 100 && speed! <= Self.maximumSpeedPxPerSecond),
82
+ acceleration == nil || (acceleration!.isFinite && acceleration! >= 100
83
+ && acceleration! <= Self.maximumAccelerationPxPerSecondSquared) else {
84
+ throw CursorOverlayError(message: "cursor overlay physical motion is outside the supported range")
85
+ }
86
+ self.speedPxPerSecond = speed
87
+ self.accelerationPxPerSecondSquared = acceleration
88
+
89
+ if let rawPid = try Self.number(object["targetPid"], field: "targetPid") {
90
+ let pidValue = rawPid.doubleValue
91
+ guard pidValue.isFinite, pidValue.rounded(.towardZero) == pidValue,
92
+ pidValue > 0, pidValue <= Double(Int32.max) else {
93
+ throw CursorOverlayError(message: "cursor overlay targetPid is invalid")
94
+ }
95
+ self.targetPid = pid_t(pidValue)
96
+ } else {
97
+ self.targetPid = nil
98
+ }
99
+ if let rawWindowNumber = try Self.number(object["targetWindowNumber"], field: "targetWindowNumber") {
100
+ let windowValue = rawWindowNumber.doubleValue
101
+ guard windowValue.isFinite, windowValue.rounded(.towardZero) == windowValue,
102
+ windowValue > 0, windowValue <= Double(Int64.max) else {
103
+ throw CursorOverlayError(message: "cursor overlay targetWindowNumber is invalid")
104
+ }
105
+ self.targetWindowNumber = Int64(windowValue)
106
+ } else {
107
+ self.targetWindowNumber = nil
108
+ }
109
+ if let frame = object["targetWindowFrame"] as? [String: Any] {
110
+ guard let x = try Self.number(frame["x"], field: "targetWindowFrame.x"),
111
+ let y = try Self.number(frame["y"], field: "targetWindowFrame.y"),
112
+ let width = try Self.number(frame["width"], field: "targetWindowFrame.width"),
113
+ let height = try Self.number(frame["height"], field: "targetWindowFrame.height") else {
114
+ throw CursorOverlayError(message: "cursor overlay targetWindowFrame is incomplete")
115
+ }
116
+ let values = [x.doubleValue, y.doubleValue, width.doubleValue, height.doubleValue]
117
+ guard values.allSatisfy(\.isFinite), width.doubleValue > 0, height.doubleValue > 0,
118
+ values.allSatisfy({ abs($0) <= Self.maximumCoordinateMagnitude }) else {
119
+ throw CursorOverlayError(message: "cursor overlay targetWindowFrame is invalid")
120
+ }
121
+ self.targetWindowFrame = CGRect(
122
+ x: x.doubleValue,
123
+ y: y.doubleValue,
124
+ width: width.doubleValue,
125
+ height: height.doubleValue
126
+ )
127
+ } else {
128
+ self.targetWindowFrame = nil
129
+ }
130
+ if let sustainedPress = object["sustainedPress"] {
131
+ guard let value = sustainedPress as? Bool else {
132
+ throw CursorOverlayError(message: "cursor overlay sustainedPress must be boolean")
133
+ }
134
+ self.sustainedPress = value
135
+ } else {
136
+ self.sustainedPress = false
137
+ }
138
+ }
139
+ }
140
+
141
+ private struct CursorOverlayError: Error {
142
+ let message: String
143
+ }
144
+
145
+ private final class CursorPanel: NSPanel {
146
+ override var canBecomeKey: Bool { false }
147
+ override var canBecomeMain: Bool { false }
148
+ }
149
+
150
+ private final class CursorView: NSView {
151
+ override var isFlipped: Bool { true }
152
+
153
+ private let image: NSImage? = EmbeddedCursorImage.image
154
+
155
+ var pressed = false {
156
+ didSet { needsDisplay = true }
157
+ }
158
+
159
+ override var isOpaque: Bool { false }
160
+
161
+ override func draw(_ dirtyRect: NSRect) {
162
+ super.draw(dirtyRect)
163
+ guard let image else { return }
164
+ let imageRect = pressed ? bounds.insetBy(dx: 2, dy: 2) : bounds
165
+ image.draw(
166
+ in: imageRect,
167
+ from: .zero,
168
+ operation: .sourceOver,
169
+ fraction: pressed ? 0.85 : 1,
170
+ respectFlipped: true,
171
+ hints: nil
172
+ )
173
+ }
174
+ }
175
+
176
+ @MainActor
177
+ private final class CursorOverlayController: NSObject {
178
+ private static let size = NSSize(width: 28, height: 28)
179
+
180
+ private let window: CursorPanel
181
+ private let cursorView: CursorView
182
+ private var hideWork: DispatchWorkItem?
183
+ private var releaseWork: DispatchWorkItem?
184
+ private var targetCheckTimer: Timer?
185
+ private var glideTimer: Timer?
186
+ private var glideCompletion: ((Bool) -> Void)?
187
+ private var hasPosition = false
188
+ private var currentQuartzPoint: CGPoint?
189
+ private var targetPid: pid_t?
190
+ private var targetWindowNumber: Int64?
191
+ private var targetWindowFrame: CGRect?
192
+
193
+ override init() {
194
+ cursorView = CursorView(frame: NSRect(origin: .zero, size: Self.size))
195
+ window = CursorPanel(
196
+ contentRect: NSRect(origin: .zero, size: Self.size),
197
+ styleMask: [.borderless, .nonactivatingPanel],
198
+ backing: .buffered,
199
+ defer: false
200
+ )
201
+ super.init()
202
+ window.title = "DSH Computer Use Cursor"
203
+ window.contentView = cursorView
204
+ window.isOpaque = false
205
+ window.backgroundColor = .clear
206
+ window.hasShadow = false
207
+ // Target loss must remove the indicator immediately, without AppKit's
208
+ // panel fade leaving it visible over an unrelated foreground app.
209
+ window.animationBehavior = .none
210
+ window.ignoresMouseEvents = true
211
+ window.hidesOnDeactivate = false
212
+ window.becomesKeyOnlyIfNeeded = true
213
+ window.level = .floating
214
+ window.collectionBehavior = [.fullScreenAuxiliary, .stationary, .ignoresCycle]
215
+ window.isReleasedWhenClosed = false
216
+ window.sharingType = .readOnly
217
+ NSWorkspace.shared.notificationCenter.addObserver(
218
+ self,
219
+ selector: #selector(frontmostApplicationChanged(_:)),
220
+ name: NSWorkspace.didActivateApplicationNotification,
221
+ object: nil
222
+ )
223
+ }
224
+
225
+ deinit {
226
+ NSWorkspace.shared.notificationCenter.removeObserver(self)
227
+ }
228
+
229
+ /// Outcome of a placement request, so the caller can distinguish a cursor
230
+ /// that moved from one that was hidden because its window binding no
231
+ /// longer holds. Reporting success for the second is how a live session
232
+ /// ends up with a frozen agent cursor and no error anywhere.
233
+ enum Placement {
234
+ case shown
235
+ case targetNotFrontmost
236
+ case targetUnavailable
237
+ }
238
+
239
+ func show(
240
+ at quartzPoint: CGPoint,
241
+ durationMs: Int?,
242
+ speedPxPerSecond: Double?,
243
+ accelerationPxPerSecondSquared: Double?,
244
+ autoHideMs: Int,
245
+ targetPid: pid_t?,
246
+ targetWindowNumber: Int64?,
247
+ targetWindowFrame: CGRect?,
248
+ completion: @escaping (Placement) -> Void
249
+ ) {
250
+ hideWork?.cancel()
251
+ let placement = targetPlacement(pid: targetPid, windowNumber: targetWindowNumber, expectedFrame: targetWindowFrame)
252
+ guard placement == .shown else {
253
+ hide()
254
+ completion(placement)
255
+ return
256
+ }
257
+ self.targetPid = targetPid
258
+ self.targetWindowNumber = targetWindowNumber
259
+ self.targetWindowFrame = targetWindowFrame
260
+ scheduleTargetChecks()
261
+ if !hasPosition {
262
+ let mouse = NSEvent.mouseLocation
263
+ window.setFrameOrigin(NSPoint(x: mouse.x, y: mouse.y - Self.size.height))
264
+ currentQuartzPoint = self.quartzPoint(fromAppKit: mouse)
265
+ hasPosition = true
266
+ }
267
+ window.orderFrontRegardless()
268
+ let shownPlacement = targetPlacement(pid: targetPid, windowNumber: targetWindowNumber, expectedFrame: targetWindowFrame)
269
+ guard shownPlacement == .shown else {
270
+ hide()
271
+ completion(shownPlacement)
272
+ return
273
+ }
274
+ glide(
275
+ from: currentQuartzPoint ?? quartzPoint,
276
+ to: quartzPoint,
277
+ durationMs: durationMs,
278
+ speedPxPerSecond: speedPxPerSecond,
279
+ accelerationPxPerSecondSquared: accelerationPxPerSecondSquared
280
+ ) { [weak self] reached in
281
+ guard let self else {
282
+ completion(.targetUnavailable)
283
+ return
284
+ }
285
+ let finalPlacement = self.targetPlacement(
286
+ pid: targetPid,
287
+ windowNumber: targetWindowNumber,
288
+ expectedFrame: targetWindowFrame
289
+ )
290
+ guard reached, finalPlacement == .shown else {
291
+ self.hide()
292
+ completion(finalPlacement == .shown ? .targetUnavailable : finalPlacement)
293
+ return
294
+ }
295
+ self.scheduleHide(after: autoHideMs)
296
+ completion(.shown)
297
+ }
298
+ }
299
+
300
+ /// Travel to `targetOrigin`, interpolated on the main run loop.
301
+ ///
302
+ /// `window.animator().setFrameOrigin` does not move this panel: the overlay
303
+ /// runs with `.prohibited` activation policy, and the implicit animator
304
+ /// silently does nothing there. Because the animated branch only ran once
305
+ /// the panel was already visible, the first placement worked and every
306
+ /// later move was a no-op — a cursor that appears once and then never
307
+ /// follows the agent again.
308
+ ///
309
+ /// Stepping the origin directly is the same call the first placement
310
+ /// already proved works, so the glide is both visible and correct.
311
+ private func glide(
312
+ from origin: CGPoint,
313
+ to target: CGPoint,
314
+ durationMs: Int?,
315
+ speedPxPerSecond: Double?,
316
+ accelerationPxPerSecondSquared: Double?,
317
+ completion: @escaping (Bool) -> Void
318
+ ) {
319
+ finishGlide(reached: false)
320
+ guard origin != target else {
321
+ currentQuartzPoint = target
322
+ window.setFrameOrigin(panelOrigin(fromQuartz: target))
323
+ window.orderFrontRegardless()
324
+ completion(true)
325
+ return
326
+ }
327
+ let distance = hypot(target.x - origin.x, target.y - origin.y)
328
+ let duration = motionDuration(
329
+ distance: distance,
330
+ explicitDurationMs: durationMs,
331
+ speedPxPerSecond: speedPxPerSecond,
332
+ accelerationPxPerSecondSquared: accelerationPxPerSecondSquared
333
+ )
334
+ guard duration > 0 else {
335
+ currentQuartzPoint = target
336
+ window.setFrameOrigin(panelOrigin(fromQuartz: target))
337
+ window.orderFrontRegardless()
338
+ completion(true)
339
+ return
340
+ }
341
+ let started = CACurrentMediaTime()
342
+ glideCompletion = completion
343
+ let timer = Timer(timeInterval: 1.0 / 120.0, repeats: true) { [weak self] timer in
344
+ MainActor.assumeIsolated {
345
+ guard let self else { timer.invalidate(); return }
346
+ if let targetPid = self.targetPid,
347
+ NSWorkspace.shared.frontmostApplication?.processIdentifier != targetPid {
348
+ self.hide()
349
+ return
350
+ }
351
+ let elapsed = CACurrentMediaTime() - started
352
+ if elapsed >= duration {
353
+ self.currentQuartzPoint = target
354
+ self.window.setFrameOrigin(self.panelOrigin(fromQuartz: target))
355
+ self.hasPosition = true
356
+ self.finishGlide(reached: true)
357
+ return
358
+ }
359
+ let linear = elapsed / duration
360
+ let fraction: Double
361
+ if let speedPxPerSecond, let accelerationPxPerSecondSquared {
362
+ fraction = cursorMotionFraction(
363
+ progress: linear,
364
+ distance: distance,
365
+ speed: speedPxPerSecond,
366
+ acceleration: accelerationPxPerSecondSquared
367
+ )
368
+ } else {
369
+ fraction = linear * linear * (3 - 2 * linear)
370
+ }
371
+ let point = cursorMotionPoint(from: origin, to: target, fraction: fraction)
372
+ self.currentQuartzPoint = point
373
+ self.window.setFrameOrigin(self.panelOrigin(fromQuartz: point))
374
+ }
375
+ }
376
+ glideTimer = timer
377
+ RunLoop.main.add(timer, forMode: .common)
378
+ }
379
+
380
+ private func motionDuration(
381
+ distance: Double,
382
+ explicitDurationMs: Int?,
383
+ speedPxPerSecond: Double?,
384
+ accelerationPxPerSecondSquared: Double?
385
+ ) -> Double {
386
+ if let explicitDurationMs { return Double(explicitDurationMs) / 1000 }
387
+ guard let speedPxPerSecond, let accelerationPxPerSecondSquared else { return 0.18 }
388
+ return cursorMotionDuration(
389
+ distance: distance,
390
+ speed: speedPxPerSecond,
391
+ acceleration: accelerationPxPerSecondSquared
392
+ )
393
+ }
394
+
395
+ private func finishGlide(reached: Bool) {
396
+ glideTimer?.invalidate()
397
+ glideTimer = nil
398
+ let completion = glideCompletion
399
+ glideCompletion = nil
400
+ completion?(reached)
401
+ }
402
+
403
+ func press(autoHideMs: Int, sustained: Bool) {
404
+ guard window.isVisible else { return }
405
+ releaseWork?.cancel()
406
+ releaseWork = nil
407
+ cursorView.pressed = true
408
+ if !sustained {
409
+ let work = DispatchWorkItem { [weak self] in
410
+ self?.cursorView.pressed = false
411
+ }
412
+ releaseWork = work
413
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(150), execute: work)
414
+ }
415
+ scheduleHide(after: autoHideMs)
416
+ }
417
+
418
+ func release(autoHideMs: Int) {
419
+ releaseWork?.cancel()
420
+ releaseWork = nil
421
+ cursorView.pressed = false
422
+ scheduleHide(after: autoHideMs)
423
+ }
424
+
425
+ var isVisible: Bool { window.isVisible }
426
+
427
+ @discardableResult
428
+ func validateTarget(pid: pid_t?, windowNumber: Int64?, expectedFrame: CGRect?) -> Placement {
429
+ guard window.isVisible else { return .targetUnavailable }
430
+ let placement = targetPlacement(pid: pid, windowNumber: windowNumber, expectedFrame: expectedFrame)
431
+ if placement != .shown {
432
+ hide()
433
+ return placement
434
+ }
435
+ return .shown
436
+ }
437
+
438
+ func hide() {
439
+ finishGlide(reached: false)
440
+ hideWork?.cancel()
441
+ hideWork = nil
442
+ releaseWork?.cancel()
443
+ releaseWork = nil
444
+ targetCheckTimer?.invalidate()
445
+ targetCheckTimer = nil
446
+ targetPid = nil
447
+ targetWindowNumber = nil
448
+ targetWindowFrame = nil
449
+ cursorView.pressed = false
450
+ window.orderOut(nil)
451
+ }
452
+
453
+ func stop() {
454
+ hide()
455
+ NSApp.stop(nil)
456
+ if let wakeEvent = NSEvent.otherEvent(
457
+ with: .applicationDefined,
458
+ location: .zero,
459
+ modifierFlags: [],
460
+ timestamp: ProcessInfo.processInfo.systemUptime,
461
+ windowNumber: 0,
462
+ context: nil,
463
+ subtype: 0,
464
+ data1: 0,
465
+ data2: 0
466
+ ) {
467
+ NSApp.postEvent(wakeEvent, atStart: true)
468
+ }
469
+ }
470
+
471
+ private func scheduleHide(after milliseconds: Int) {
472
+ hideWork?.cancel()
473
+ guard milliseconds > 0 else { return }
474
+ let work = DispatchWorkItem { [weak self] in self?.hide() }
475
+ hideWork = work
476
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(milliseconds), execute: work)
477
+ }
478
+
479
+ private func scheduleTargetChecks() {
480
+ guard targetCheckTimer == nil else { return }
481
+ targetCheckTimer = Timer.scheduledTimer(withTimeInterval: 0.25, repeats: true) { [weak self] _ in
482
+ Task { @MainActor [weak self] in
483
+ guard let self, self.window.isVisible else { return }
484
+ if self.targetPlacement(
485
+ pid: self.targetPid,
486
+ windowNumber: self.targetWindowNumber,
487
+ expectedFrame: self.targetWindowFrame
488
+ ) != .shown {
489
+ self.hide()
490
+ }
491
+ }
492
+ }
493
+ }
494
+
495
+ @objc private func frontmostApplicationChanged(_ notification: Notification) {
496
+ guard window.isVisible, let targetPid else { return }
497
+ if NSWorkspace.shared.frontmostApplication?.processIdentifier != targetPid {
498
+ hide()
499
+ }
500
+ }
501
+
502
+ private func appKitPoint(fromQuartz point: CGPoint) -> NSPoint {
503
+ for screen in NSScreen.screens {
504
+ guard let screenNumber = (screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber)?.uint32Value else {
505
+ continue
506
+ }
507
+ let quartzFrame = CGDisplayBounds(CGDirectDisplayID(screenNumber))
508
+ if quartzFrame.contains(point) {
509
+ return NSPoint(
510
+ x: screen.frame.origin.x + (point.x - quartzFrame.origin.x),
511
+ y: screen.frame.maxY - (point.y - quartzFrame.origin.y)
512
+ )
513
+ }
514
+ }
515
+ let mainDisplay = CGMainDisplayID()
516
+ let quartzFrame = CGDisplayBounds(mainDisplay)
517
+ let screen = NSScreen.screens.first { candidate in
518
+ (candidate.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber)?.uint32Value == mainDisplay
519
+ } ?? NSScreen.main
520
+ let appKitFrame = screen?.frame ?? .zero
521
+ return NSPoint(
522
+ x: appKitFrame.origin.x + (point.x - quartzFrame.origin.x),
523
+ y: appKitFrame.maxY - (point.y - quartzFrame.origin.y)
524
+ )
525
+ }
526
+
527
+ private func quartzPoint(fromAppKit point: NSPoint) -> CGPoint {
528
+ for screen in NSScreen.screens {
529
+ guard screen.frame.contains(point),
530
+ let screenNumber = screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber else {
531
+ continue
532
+ }
533
+ let quartzFrame = CGDisplayBounds(CGDirectDisplayID(screenNumber.uint32Value))
534
+ return CGPoint(
535
+ x: quartzFrame.origin.x + (point.x - screen.frame.origin.x),
536
+ y: quartzFrame.origin.y + (screen.frame.maxY - point.y)
537
+ )
538
+ }
539
+ let mainDisplay = CGMainDisplayID()
540
+ let quartzFrame = CGDisplayBounds(mainDisplay)
541
+ let appKitFrame = NSScreen.main?.frame ?? NSRect(
542
+ x: quartzFrame.origin.x,
543
+ y: quartzFrame.origin.y,
544
+ width: quartzFrame.width,
545
+ height: quartzFrame.height
546
+ )
547
+ return CGPoint(
548
+ x: quartzFrame.origin.x + (point.x - appKitFrame.origin.x),
549
+ y: quartzFrame.origin.y + (appKitFrame.maxY - point.y)
550
+ )
551
+ }
552
+
553
+ private func panelOrigin(fromQuartz point: CGPoint) -> NSPoint {
554
+ let appKit = appKitPoint(fromQuartz: point)
555
+ return NSPoint(x: appKit.x, y: appKit.y - Self.size.height)
556
+ }
557
+
558
+ private func targetPlacement(pid: pid_t?, windowNumber: Int64?, expectedFrame: CGRect?) -> Placement {
559
+ guard let pid, let windowNumber, let expectedFrame else { return .targetUnavailable }
560
+ guard NSWorkspace.shared.frontmostApplication?.processIdentifier == pid else { return .targetNotFrontmost }
561
+ guard let rawWindows = CGWindowListCopyWindowInfo(
562
+ [.optionOnScreenOnly, .excludeDesktopElements],
563
+ kCGNullWindowID
564
+ ) as? [[String: Any]] else {
565
+ return .targetUnavailable
566
+ }
567
+ let matches = rawWindows.contains { window in
568
+ guard (window[kCGWindowOwnerPID as String] as? NSNumber)?.int32Value == pid,
569
+ (window[kCGWindowNumber as String] as? NSNumber)?.int64Value == windowNumber,
570
+ let bounds = window[kCGWindowBounds as String] as? [String: Any],
571
+ let currentFrame = CGRect(dictionaryRepresentation: bounds as CFDictionary) else { return false }
572
+ let tolerance: CGFloat = 2
573
+ return abs(currentFrame.minX - expectedFrame.minX) <= tolerance
574
+ && abs(currentFrame.minY - expectedFrame.minY) <= tolerance
575
+ && abs(currentFrame.width - expectedFrame.width) <= tolerance
576
+ && abs(currentFrame.height - expectedFrame.height) <= tolerance
577
+ }
578
+ return matches ? .shown : .targetUnavailable
579
+ }
580
+ }
581
+
582
+ @MainActor
583
+ enum CursorOverlayRuntime {
584
+ static func run() {
585
+ let app = NSApplication.shared
586
+ app.setActivationPolicy(.prohibited)
587
+ let controller = CursorOverlayController()
588
+ let dispatcher = CursorCommandDispatcher(controller: controller)
589
+ let input = FileHandle.standardInput
590
+ let parser = CursorCommandParser { object in
591
+ DispatchQueue.main.async {
592
+ dispatcher.enqueue(object)
593
+ }
594
+ } onEnd: {
595
+ DispatchQueue.main.async { dispatcher.endInput() }
596
+ } onInvalid: { message in
597
+ DispatchQueue.main.async {
598
+ dispatcher.invalidate(message)
599
+ }
600
+ }
601
+ input.readabilityHandler = { handle in parser.consume(handle.availableData) }
602
+ emitCursorResponse(["ok": true, "ready": true, "pid": ProcessInfo.processInfo.processIdentifier])
603
+ app.run()
604
+ input.readabilityHandler = nil
605
+ }
606
+ }
607
+
608
+ @MainActor
609
+ private final class CursorCommandDispatcher {
610
+ private let controller: CursorOverlayController
611
+ private var commands: [[String: Any]] = []
612
+ private var processing = false
613
+ private var inputEnded = false
614
+ private var terminated = false
615
+
616
+ init(controller: CursorOverlayController) {
617
+ self.controller = controller
618
+ }
619
+
620
+ func enqueue(_ object: [String: Any]) {
621
+ guard !inputEnded, !terminated else { return }
622
+ commands.append(object)
623
+ if object["op"] as? String == "stop", processing {
624
+ controller.hide()
625
+ }
626
+ drain()
627
+ }
628
+
629
+ func endInput() {
630
+ guard !inputEnded, !terminated else { return }
631
+ inputEnded = true
632
+ if commands.contains(where: { $0["op"] as? String == "stop" }) {
633
+ if processing { controller.hide() }
634
+ drain()
635
+ } else {
636
+ terminated = true
637
+ commands.removeAll()
638
+ controller.stop()
639
+ }
640
+ }
641
+
642
+ func invalidate(_ message: String) {
643
+ guard !terminated else { return }
644
+ inputEnded = true
645
+ terminated = true
646
+ commands.removeAll()
647
+ controller.hide()
648
+ emitCursorResponse(["ok": false, "error": message])
649
+ controller.stop()
650
+ }
651
+
652
+ private func drain() {
653
+ guard !terminated, !processing, !commands.isEmpty else { return }
654
+ processing = true
655
+ let command = commands.removeFirst()
656
+ let stopsRuntime = command["op"] as? String == "stop"
657
+ handleCursorCommand(command, controller: controller) { [weak self] in
658
+ guard let self else { return }
659
+ self.processing = false
660
+ if stopsRuntime {
661
+ self.terminated = true
662
+ self.commands.removeAll()
663
+ return
664
+ }
665
+ DispatchQueue.main.async { [weak self] in self?.drain() }
666
+ }
667
+ }
668
+ }
669
+
670
+ private final class CursorCommandParser: @unchecked Sendable {
671
+ private static let maximumLineBytes = 16 * 1024
672
+ private let queue = DispatchQueue(label: "dsh-computer-use.cursor-protocol")
673
+ private let onObject: @Sendable ([String: Any]) -> Void
674
+ private let onEnd: @Sendable () -> Void
675
+ private let onInvalid: @Sendable (String) -> Void
676
+ private var buffer = Data()
677
+ private var ended = false
678
+
679
+ init(
680
+ onObject: @escaping @Sendable ([String: Any]) -> Void,
681
+ onEnd: @escaping @Sendable () -> Void,
682
+ onInvalid: @escaping @Sendable (String) -> Void
683
+ ) {
684
+ self.onObject = onObject
685
+ self.onEnd = onEnd
686
+ self.onInvalid = onInvalid
687
+ }
688
+
689
+ func consume(_ data: Data) {
690
+ queue.async { [self] in
691
+ guard !ended, !data.isEmpty else {
692
+ guard !ended else { return }
693
+ ended = true
694
+ onEnd()
695
+ return
696
+ }
697
+ buffer.append(data)
698
+ if buffer.count > Self.maximumLineBytes, buffer.firstIndex(of: 0x0a) == nil {
699
+ ended = true
700
+ buffer.removeAll()
701
+ onInvalid("cursor overlay command exceeded the protocol limit")
702
+ return
703
+ }
704
+ while let newline = buffer.firstIndex(of: 0x0a) {
705
+ let line = buffer[..<newline]
706
+ buffer.removeSubrange(...newline)
707
+ if line.count > Self.maximumLineBytes {
708
+ ended = true
709
+ onInvalid("cursor overlay command exceeded the protocol limit")
710
+ return
711
+ }
712
+ guard !line.isEmpty else { continue }
713
+ guard let object = try? JSONSerialization.jsonObject(with: Data(line)) as? [String: Any] else {
714
+ ended = true
715
+ onInvalid("cursor overlay command is not valid JSON")
716
+ return
717
+ }
718
+ onObject(object)
719
+ }
720
+ }
721
+ }
722
+ }
723
+
724
+ @MainActor
725
+ private func handleCursorCommand(
726
+ _ object: [String: Any],
727
+ controller: CursorOverlayController,
728
+ completion: @escaping () -> Void
729
+ ) {
730
+ do {
731
+ let command = try CursorOverlayCommand(object)
732
+ // Whether the panel is actually on screen after this command. A hidden
733
+ // overlay still leaves native input working, so the operation is not an
734
+ // error -- but the caller must be able to tell, or the user silently
735
+ // loses sight of where the agent is acting.
736
+ var visible = true
737
+ var reasonCode: String?
738
+ switch command.operation {
739
+ case "show", "move":
740
+ guard let point = command.point else {
741
+ throw CursorOverlayError(message: "cursor overlay command needs x and y")
742
+ }
743
+ controller.show(
744
+ at: point,
745
+ durationMs: command.durationMs,
746
+ speedPxPerSecond: command.speedPxPerSecond,
747
+ accelerationPxPerSecondSquared: command.accelerationPxPerSecondSquared,
748
+ autoHideMs: command.autoHideMs,
749
+ targetPid: command.targetPid,
750
+ targetWindowNumber: command.targetWindowNumber,
751
+ targetWindowFrame: command.targetWindowFrame
752
+ ) { placement in
753
+ let shown = placement == .shown
754
+ var response: [String: Any] = ["ok": true, "op": command.operation, "visible": shown]
755
+ if !shown {
756
+ response["reasonCode"] = cursorReasonCode(placement)
757
+ response["reason"] = cursorReason(placement)
758
+ }
759
+ emitCursorResponse(response)
760
+ completion()
761
+ }
762
+ return
763
+ case "press":
764
+ let placement = controller.validateTarget(
765
+ pid: command.targetPid,
766
+ windowNumber: command.targetWindowNumber,
767
+ expectedFrame: command.targetWindowFrame
768
+ )
769
+ visible = placement == .shown
770
+ reasonCode = cursorReasonCode(placement)
771
+ controller.press(autoHideMs: command.autoHideMs, sustained: command.sustainedPress)
772
+ case "release":
773
+ let placement = controller.validateTarget(
774
+ pid: command.targetPid,
775
+ windowNumber: command.targetWindowNumber,
776
+ expectedFrame: command.targetWindowFrame
777
+ )
778
+ visible = placement == .shown
779
+ reasonCode = cursorReasonCode(placement)
780
+ controller.release(autoHideMs: command.autoHideMs)
781
+ case "validate":
782
+ let placement = controller.validateTarget(
783
+ pid: command.targetPid,
784
+ windowNumber: command.targetWindowNumber,
785
+ expectedFrame: command.targetWindowFrame
786
+ )
787
+ visible = placement == .shown
788
+ reasonCode = cursorReasonCode(placement)
789
+ case "hide":
790
+ controller.hide()
791
+ visible = false
792
+ case "stop":
793
+ controller.stop()
794
+ visible = false
795
+ case "ping":
796
+ visible = controller.isVisible
797
+ default:
798
+ throw CursorOverlayError(message: "unknown cursor overlay operation")
799
+ }
800
+ var response: [String: Any] = ["ok": true, "op": command.operation, "visible": visible]
801
+ if !visible && (command.operation == "show" || command.operation == "move"
802
+ || command.operation == "press" || command.operation == "release"
803
+ || command.operation == "validate") {
804
+ response["reasonCode"] = reasonCode
805
+ response["reason"] = reasonCode == "target-not-frontmost"
806
+ ? "the bound target application is not frontmost; the agent cursor is hidden"
807
+ : "the bound target window no longer matches; the agent cursor is hidden"
808
+ }
809
+ emitCursorResponse(response)
810
+ completion()
811
+ } catch let error as CursorOverlayError {
812
+ emitCursorResponse(["ok": false, "error": error.message])
813
+ completion()
814
+ } catch {
815
+ emitCursorResponse(["ok": false, "error": String(describing: error)])
816
+ completion()
817
+ }
818
+ }
819
+
820
+ private func cursorReasonCode(_ placement: CursorOverlayController.Placement) -> String? {
821
+ switch placement {
822
+ case .shown: return nil
823
+ case .targetNotFrontmost: return "target-not-frontmost"
824
+ case .targetUnavailable: return "target-invalid"
825
+ }
826
+ }
827
+
828
+ private func cursorReason(_ placement: CursorOverlayController.Placement) -> String? {
829
+ switch placement {
830
+ case .shown: return nil
831
+ case .targetNotFrontmost: return "the bound target application is not frontmost; the agent cursor is hidden"
832
+ case .targetUnavailable: return "the bound target window no longer matches; the agent cursor is hidden"
833
+ }
834
+ }
835
+
836
+ private func emitCursorResponse(_ payload: [String: Any]) {
837
+ guard let data = try? JSONSerialization.data(withJSONObject: payload, options: [.sortedKeys]) else { return }
838
+ FileHandle.standardOutput.write(data)
839
+ FileHandle.standardOutput.write(Data("\n".utf8))
840
+ }