@beeos-ai/device-agent 0.4.0

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 (398) hide show
  1. package/.pi/extensions/android-tools.ts +139 -0
  2. package/.pi/skills/.gitkeep +0 -0
  3. package/.pi/skills/ground-mobile-fallback/SKILL.md +50 -0
  4. package/LICENSE +201 -0
  5. package/dist/action/handler.d.ts +9 -0
  6. package/dist/action/handler.js +124 -0
  7. package/dist/action/handler.js.map +1 -0
  8. package/dist/adapters/agent-gateway-client.d.ts +256 -0
  9. package/dist/adapters/agent-gateway-client.js +332 -0
  10. package/dist/adapters/agent-gateway-client.js.map +1 -0
  11. package/dist/adapters/agentcore-inner-loop.d.ts +29 -0
  12. package/dist/adapters/agentcore-inner-loop.js +72 -0
  13. package/dist/adapters/agentcore-inner-loop.js.map +1 -0
  14. package/dist/adapters/agentcore-pi.d.ts +215 -0
  15. package/dist/adapters/agentcore-pi.js +464 -0
  16. package/dist/adapters/agentcore-pi.js.map +1 -0
  17. package/dist/adapters/agentcore-runner.d.ts +70 -0
  18. package/dist/adapters/agentcore-runner.js +255 -0
  19. package/dist/adapters/agentcore-runner.js.map +1 -0
  20. package/dist/adapters/device-android-adb.d.ts +41 -0
  21. package/dist/adapters/device-android-adb.js +279 -0
  22. package/dist/adapters/device-android-adb.js.map +1 -0
  23. package/dist/adapters/device-desktop.d.ts +37 -0
  24. package/dist/adapters/device-desktop.js +101 -0
  25. package/dist/adapters/device-desktop.js.map +1 -0
  26. package/dist/adapters/identity-file.d.ts +30 -0
  27. package/dist/adapters/identity-file.js +50 -0
  28. package/dist/adapters/identity-file.js.map +1 -0
  29. package/dist/adapters/transport-bridge-ws.d.ts +39 -0
  30. package/dist/adapters/transport-bridge-ws.js +49 -0
  31. package/dist/adapters/transport-bridge-ws.js.map +1 -0
  32. package/dist/adapters/vlm-inner-loop.d.ts +88 -0
  33. package/dist/adapters/vlm-inner-loop.js +199 -0
  34. package/dist/adapters/vlm-inner-loop.js.map +1 -0
  35. package/dist/agent-runtime/adapters/base.d.ts +145 -0
  36. package/dist/agent-runtime/adapters/base.js +29 -0
  37. package/dist/agent-runtime/adapters/base.js.map +1 -0
  38. package/dist/agent-runtime/adapters/index.d.ts +17 -0
  39. package/dist/agent-runtime/adapters/index.js +17 -0
  40. package/dist/agent-runtime/adapters/index.js.map +1 -0
  41. package/dist/agent-runtime/adapters/mock.d.ts +44 -0
  42. package/dist/agent-runtime/adapters/mock.js +54 -0
  43. package/dist/agent-runtime/adapters/mock.js.map +1 -0
  44. package/dist/agent-runtime/adapters/openai.d.ts +63 -0
  45. package/dist/agent-runtime/adapters/openai.js +302 -0
  46. package/dist/agent-runtime/adapters/openai.js.map +1 -0
  47. package/dist/agent-runtime/adapters/registry.d.ts +49 -0
  48. package/dist/agent-runtime/adapters/registry.js +129 -0
  49. package/dist/agent-runtime/adapters/registry.js.map +1 -0
  50. package/dist/agent-runtime/adapters/ui-tars.d.ts +13 -0
  51. package/dist/agent-runtime/adapters/ui-tars.js +22 -0
  52. package/dist/agent-runtime/adapters/ui-tars.js.map +1 -0
  53. package/dist/agent-runtime/agent-runner.d.ts +149 -0
  54. package/dist/agent-runtime/agent-runner.js +356 -0
  55. package/dist/agent-runtime/agent-runner.js.map +1 -0
  56. package/dist/agent-runtime/core.d.ts +170 -0
  57. package/dist/agent-runtime/core.js +624 -0
  58. package/dist/agent-runtime/core.js.map +1 -0
  59. package/dist/agent-runtime/index.d.ts +16 -0
  60. package/dist/agent-runtime/index.js +17 -0
  61. package/dist/agent-runtime/index.js.map +1 -0
  62. package/dist/agent-runtime/plan-executor.d.ts +118 -0
  63. package/dist/agent-runtime/plan-executor.js +501 -0
  64. package/dist/agent-runtime/plan-executor.js.map +1 -0
  65. package/dist/agent-runtime/planner/base.d.ts +128 -0
  66. package/dist/agent-runtime/planner/base.js +157 -0
  67. package/dist/agent-runtime/planner/base.js.map +1 -0
  68. package/dist/agent-runtime/planner/llm-planner.d.ts +58 -0
  69. package/dist/agent-runtime/planner/llm-planner.js +112 -0
  70. package/dist/agent-runtime/planner/llm-planner.js.map +1 -0
  71. package/dist/agent-runtime/planner/noop-planner.d.ts +13 -0
  72. package/dist/agent-runtime/planner/noop-planner.js +30 -0
  73. package/dist/agent-runtime/planner/noop-planner.js.map +1 -0
  74. package/dist/agent-runtime/planner/prompts.d.ts +33 -0
  75. package/dist/agent-runtime/planner/prompts.js +165 -0
  76. package/dist/agent-runtime/planner/prompts.js.map +1 -0
  77. package/dist/agent-runtime/reflection.d.ts +81 -0
  78. package/dist/agent-runtime/reflection.js +189 -0
  79. package/dist/agent-runtime/reflection.js.map +1 -0
  80. package/dist/agent-runtime/reflectors/action-reflector.d.ts +97 -0
  81. package/dist/agent-runtime/reflectors/action-reflector.js +233 -0
  82. package/dist/agent-runtime/reflectors/action-reflector.js.map +1 -0
  83. package/dist/agent-runtime/reflectors/policy.d.ts +53 -0
  84. package/dist/agent-runtime/reflectors/policy.js +106 -0
  85. package/dist/agent-runtime/reflectors/policy.js.map +1 -0
  86. package/dist/agent-runtime/reflectors/trajectory-reflector.d.ts +94 -0
  87. package/dist/agent-runtime/reflectors/trajectory-reflector.js +223 -0
  88. package/dist/agent-runtime/reflectors/trajectory-reflector.js.map +1 -0
  89. package/dist/agent-runtime/skills/embedding.d.ts +53 -0
  90. package/dist/agent-runtime/skills/embedding.js +134 -0
  91. package/dist/agent-runtime/skills/embedding.js.map +1 -0
  92. package/dist/agent-runtime/skills/fs-store.d.ts +88 -0
  93. package/dist/agent-runtime/skills/fs-store.js +483 -0
  94. package/dist/agent-runtime/skills/fs-store.js.map +1 -0
  95. package/dist/agent-runtime/skills/index.d.ts +10 -0
  96. package/dist/agent-runtime/skills/index.js +10 -0
  97. package/dist/agent-runtime/skills/index.js.map +1 -0
  98. package/dist/agent-runtime/skills/matcher-evolver.d.ts +88 -0
  99. package/dist/agent-runtime/skills/matcher-evolver.js +110 -0
  100. package/dist/agent-runtime/skills/matcher-evolver.js.map +1 -0
  101. package/dist/agent-runtime/skills/memory-store.d.ts +23 -0
  102. package/dist/agent-runtime/skills/memory-store.js +94 -0
  103. package/dist/agent-runtime/skills/memory-store.js.map +1 -0
  104. package/dist/agent-runtime/skills/normalise.d.ts +40 -0
  105. package/dist/agent-runtime/skills/normalise.js +152 -0
  106. package/dist/agent-runtime/skills/normalise.js.map +1 -0
  107. package/dist/agent-runtime/skills/replay.d.ts +46 -0
  108. package/dist/agent-runtime/skills/replay.js +106 -0
  109. package/dist/agent-runtime/skills/replay.js.map +1 -0
  110. package/dist/agent-runtime/skills/sqlite-store.d.ts +60 -0
  111. package/dist/agent-runtime/skills/sqlite-store.js +234 -0
  112. package/dist/agent-runtime/skills/sqlite-store.js.map +1 -0
  113. package/dist/agent-runtime/skills/types.d.ts +99 -0
  114. package/dist/agent-runtime/skills/types.js +14 -0
  115. package/dist/agent-runtime/skills/types.js.map +1 -0
  116. package/dist/agent.d.ts +110 -0
  117. package/dist/agent.js +162 -0
  118. package/dist/agent.js.map +1 -0
  119. package/dist/api.d.ts +27 -0
  120. package/dist/api.js +48 -0
  121. package/dist/api.js.map +1 -0
  122. package/dist/app/agent-host.d.ts +59 -0
  123. package/dist/app/agent-host.js +263 -0
  124. package/dist/app/agent-host.js.map +1 -0
  125. package/dist/app/device-manager.d.ts +28 -0
  126. package/dist/app/device-manager.js +64 -0
  127. package/dist/app/device-manager.js.map +1 -0
  128. package/dist/app/message-store.d.ts +55 -0
  129. package/dist/app/message-store.js +99 -0
  130. package/dist/app/message-store.js.map +1 -0
  131. package/dist/app/session-manager.d.ts +132 -0
  132. package/dist/app/session-manager.js +350 -0
  133. package/dist/app/session-manager.js.map +1 -0
  134. package/dist/bootstrap.d.ts +94 -0
  135. package/dist/bootstrap.js +459 -0
  136. package/dist/bootstrap.js.map +1 -0
  137. package/dist/chat.d.ts +16 -0
  138. package/dist/chat.js +175 -0
  139. package/dist/chat.js.map +1 -0
  140. package/dist/config/loader.d.ts +77 -0
  141. package/dist/config/loader.js +292 -0
  142. package/dist/config/loader.js.map +1 -0
  143. package/dist/config/schema.d.ts +162 -0
  144. package/dist/config/schema.js +243 -0
  145. package/dist/config/schema.js.map +1 -0
  146. package/dist/core/actions.d.ts +60 -0
  147. package/dist/core/actions.js +120 -0
  148. package/dist/core/actions.js.map +1 -0
  149. package/dist/core/errors.d.ts +8 -0
  150. package/dist/core/errors.js +9 -0
  151. package/dist/core/errors.js.map +1 -0
  152. package/dist/core/screen.d.ts +7 -0
  153. package/dist/core/screen.js +8 -0
  154. package/dist/core/screen.js.map +1 -0
  155. package/dist/core/session.d.ts +42 -0
  156. package/dist/core/session.js +29 -0
  157. package/dist/core/session.js.map +1 -0
  158. package/dist/debug/dump-system-prompt.d.ts +1 -0
  159. package/dist/debug/dump-system-prompt.js +34 -0
  160. package/dist/debug/dump-system-prompt.js.map +1 -0
  161. package/dist/device/android.d.ts +25 -0
  162. package/dist/device/android.js +231 -0
  163. package/dist/device/android.js.map +1 -0
  164. package/dist/device/apps.d.ts +3 -0
  165. package/dist/device/apps.js +77 -0
  166. package/dist/device/apps.js.map +1 -0
  167. package/dist/device/base.d.ts +20 -0
  168. package/dist/device/base.js +2 -0
  169. package/dist/device/base.js.map +1 -0
  170. package/dist/device/ui-xml.d.ts +29 -0
  171. package/dist/device/ui-xml.js +194 -0
  172. package/dist/device/ui-xml.js.map +1 -0
  173. package/dist/fleet/adapters/process/node-process-manager.d.ts +157 -0
  174. package/dist/fleet/adapters/process/node-process-manager.js +664 -0
  175. package/dist/fleet/adapters/process/node-process-manager.js.map +1 -0
  176. package/dist/fleet/adapters/sources/local-adb.d.ts +105 -0
  177. package/dist/fleet/adapters/sources/local-adb.js +353 -0
  178. package/dist/fleet/adapters/sources/local-adb.js.map +1 -0
  179. package/dist/fleet/adapters/sources/remote-adb.d.ts +97 -0
  180. package/dist/fleet/adapters/sources/remote-adb.js +138 -0
  181. package/dist/fleet/adapters/sources/remote-adb.js.map +1 -0
  182. package/dist/fleet/adapters/state/beeos-cli-store.d.ts +72 -0
  183. package/dist/fleet/adapters/state/beeos-cli-store.js +250 -0
  184. package/dist/fleet/adapters/state/beeos-cli-store.js.map +1 -0
  185. package/dist/fleet/adapters/state/port-allocator.d.ts +43 -0
  186. package/dist/fleet/adapters/state/port-allocator.js +173 -0
  187. package/dist/fleet/adapters/state/port-allocator.js.map +1 -0
  188. package/dist/fleet/domain/device.d.ts +138 -0
  189. package/dist/fleet/domain/device.js +49 -0
  190. package/dist/fleet/domain/device.js.map +1 -0
  191. package/dist/fleet/domain/events.d.ts +102 -0
  192. package/dist/fleet/domain/events.js +15 -0
  193. package/dist/fleet/domain/events.js.map +1 -0
  194. package/dist/fleet/domain/fsm.d.ts +122 -0
  195. package/dist/fleet/domain/fsm.js +475 -0
  196. package/dist/fleet/domain/fsm.js.map +1 -0
  197. package/dist/fleet/http/status-client.d.ts +31 -0
  198. package/dist/fleet/http/status-client.js +115 -0
  199. package/dist/fleet/http/status-client.js.map +1 -0
  200. package/dist/fleet/http/status-server.d.ts +64 -0
  201. package/dist/fleet/http/status-server.js +200 -0
  202. package/dist/fleet/http/status-server.js.map +1 -0
  203. package/dist/fleet/index.d.ts +27 -0
  204. package/dist/fleet/index.js +17 -0
  205. package/dist/fleet/index.js.map +1 -0
  206. package/dist/fleet/installer/index.d.ts +12 -0
  207. package/dist/fleet/installer/index.js +13 -0
  208. package/dist/fleet/installer/index.js.map +1 -0
  209. package/dist/fleet/installer/launchd-mac.d.ts +73 -0
  210. package/dist/fleet/installer/launchd-mac.js +291 -0
  211. package/dist/fleet/installer/launchd-mac.js.map +1 -0
  212. package/dist/fleet/installer/service-spec.d.ts +70 -0
  213. package/dist/fleet/installer/service-spec.js +43 -0
  214. package/dist/fleet/installer/service-spec.js.map +1 -0
  215. package/dist/fleet/installer/spawn-env.d.ts +45 -0
  216. package/dist/fleet/installer/spawn-env.js +224 -0
  217. package/dist/fleet/installer/spawn-env.js.map +1 -0
  218. package/dist/fleet/ports/clock.d.ts +19 -0
  219. package/dist/fleet/ports/clock.js +26 -0
  220. package/dist/fleet/ports/clock.js.map +1 -0
  221. package/dist/fleet/ports/device-source.d.ts +28 -0
  222. package/dist/fleet/ports/device-source.js +18 -0
  223. package/dist/fleet/ports/device-source.js.map +1 -0
  224. package/dist/fleet/ports/process-manager.d.ts +110 -0
  225. package/dist/fleet/ports/process-manager.js +27 -0
  226. package/dist/fleet/ports/process-manager.js.map +1 -0
  227. package/dist/fleet/ports/state-registry.d.ts +49 -0
  228. package/dist/fleet/ports/state-registry.js +12 -0
  229. package/dist/fleet/ports/state-registry.js.map +1 -0
  230. package/dist/fleet/supervisor.d.ts +107 -0
  231. package/dist/fleet/supervisor.js +508 -0
  232. package/dist/fleet/supervisor.js.map +1 -0
  233. package/dist/grounding/grounder.d.ts +46 -0
  234. package/dist/grounding/grounder.js +82 -0
  235. package/dist/grounding/grounder.js.map +1 -0
  236. package/dist/inbound/acp/handlers/device.d.ts +43 -0
  237. package/dist/inbound/acp/handlers/device.js +153 -0
  238. package/dist/inbound/acp/handlers/device.js.map +1 -0
  239. package/dist/inbound/acp/handlers/initialize.d.ts +71 -0
  240. package/dist/inbound/acp/handlers/initialize.js +53 -0
  241. package/dist/inbound/acp/handlers/initialize.js.map +1 -0
  242. package/dist/inbound/acp/handlers/models.d.ts +16 -0
  243. package/dist/inbound/acp/handlers/models.js +23 -0
  244. package/dist/inbound/acp/handlers/models.js.map +1 -0
  245. package/dist/inbound/acp/handlers/session.d.ts +51 -0
  246. package/dist/inbound/acp/handlers/session.js +61 -0
  247. package/dist/inbound/acp/handlers/session.js.map +1 -0
  248. package/dist/inbound/acp/handlers/skills.d.ts +8 -0
  249. package/dist/inbound/acp/handlers/skills.js +9 -0
  250. package/dist/inbound/acp/handlers/skills.js.map +1 -0
  251. package/dist/inbound/acp/notifier.d.ts +35 -0
  252. package/dist/inbound/acp/notifier.js +45 -0
  253. package/dist/inbound/acp/notifier.js.map +1 -0
  254. package/dist/inbound/acp/router.d.ts +67 -0
  255. package/dist/inbound/acp/router.js +179 -0
  256. package/dist/inbound/acp/router.js.map +1 -0
  257. package/dist/inbound/cli/fleet-command.d.ts +34 -0
  258. package/dist/inbound/cli/fleet-command.js +792 -0
  259. package/dist/inbound/cli/fleet-command.js.map +1 -0
  260. package/dist/inbound/cli/main.d.ts +38 -0
  261. package/dist/inbound/cli/main.js +364 -0
  262. package/dist/inbound/cli/main.js.map +1 -0
  263. package/dist/inbound/cli/run-command.d.ts +101 -0
  264. package/dist/inbound/cli/run-command.js +405 -0
  265. package/dist/inbound/cli/run-command.js.map +1 -0
  266. package/dist/inbound/cli/skills-command.d.ts +39 -0
  267. package/dist/inbound/cli/skills-command.js +333 -0
  268. package/dist/inbound/cli/skills-command.js.map +1 -0
  269. package/dist/inbound/http/server.d.ts +7 -0
  270. package/dist/inbound/http/server.js +8 -0
  271. package/dist/inbound/http/server.js.map +1 -0
  272. package/dist/index.d.ts +66 -0
  273. package/dist/index.js +48 -0
  274. package/dist/index.js.map +1 -0
  275. package/dist/logger/index.d.ts +37 -0
  276. package/dist/logger/index.js +84 -0
  277. package/dist/logger/index.js.map +1 -0
  278. package/dist/mcp-client/autospawn.d.ts +67 -0
  279. package/dist/mcp-client/autospawn.js +173 -0
  280. package/dist/mcp-client/autospawn.js.map +1 -0
  281. package/dist/mcp-client/client.d.ts +78 -0
  282. package/dist/mcp-client/client.js +168 -0
  283. package/dist/mcp-client/client.js.map +1 -0
  284. package/dist/mcp-client/index.d.ts +7 -0
  285. package/dist/mcp-client/index.js +4 -0
  286. package/dist/mcp-client/index.js.map +1 -0
  287. package/dist/mcp-client/inproc.d.ts +47 -0
  288. package/dist/mcp-client/inproc.js +229 -0
  289. package/dist/mcp-client/inproc.js.map +1 -0
  290. package/dist/mcp-client/runtime.d.ts +34 -0
  291. package/dist/mcp-client/runtime.js +15 -0
  292. package/dist/mcp-client/runtime.js.map +1 -0
  293. package/dist/model/adapters/autoglm.d.ts +31 -0
  294. package/dist/model/adapters/autoglm.js +409 -0
  295. package/dist/model/adapters/autoglm.js.map +1 -0
  296. package/dist/model/adapters/base.d.ts +13 -0
  297. package/dist/model/adapters/base.js +27 -0
  298. package/dist/model/adapters/base.js.map +1 -0
  299. package/dist/model/adapters/guiowl.d.ts +1 -0
  300. package/dist/model/adapters/guiowl.js +253 -0
  301. package/dist/model/adapters/guiowl.js.map +1 -0
  302. package/dist/model/adapters/index.d.ts +6 -0
  303. package/dist/model/adapters/index.js +8 -0
  304. package/dist/model/adapters/index.js.map +1 -0
  305. package/dist/model/adapters/maiui.d.ts +1 -0
  306. package/dist/model/adapters/maiui.js +117 -0
  307. package/dist/model/adapters/maiui.js.map +1 -0
  308. package/dist/model/adapters/qwenvl.d.ts +1 -0
  309. package/dist/model/adapters/qwenvl.js +108 -0
  310. package/dist/model/adapters/qwenvl.js.map +1 -0
  311. package/dist/model/adapters/showui.d.ts +1 -0
  312. package/dist/model/adapters/showui.js +132 -0
  313. package/dist/model/adapters/showui.js.map +1 -0
  314. package/dist/model/adapters/tool-call.d.ts +6 -0
  315. package/dist/model/adapters/tool-call.js +102 -0
  316. package/dist/model/adapters/tool-call.js.map +1 -0
  317. package/dist/model/adapters/uitars.d.ts +1 -0
  318. package/dist/model/adapters/uitars.js +180 -0
  319. package/dist/model/adapters/uitars.js.map +1 -0
  320. package/dist/model/base.d.ts +32 -0
  321. package/dist/model/base.js +2 -0
  322. package/dist/model/base.js.map +1 -0
  323. package/dist/model/client.d.ts +26 -0
  324. package/dist/model/client.js +300 -0
  325. package/dist/model/client.js.map +1 -0
  326. package/dist/model/image/compress.d.ts +53 -0
  327. package/dist/model/image/compress.js +89 -0
  328. package/dist/model/image/compress.js.map +1 -0
  329. package/dist/model/image/transport.d.ts +134 -0
  330. package/dist/model/image/transport.js +154 -0
  331. package/dist/model/image/transport.js.map +1 -0
  332. package/dist/orchestrator-system-prompt.d.ts +6 -0
  333. package/dist/orchestrator-system-prompt.js +81 -0
  334. package/dist/orchestrator-system-prompt.js.map +1 -0
  335. package/dist/pi-context.d.ts +82 -0
  336. package/dist/pi-context.js +62 -0
  337. package/dist/pi-context.js.map +1 -0
  338. package/dist/pi-local-skills.d.ts +17 -0
  339. package/dist/pi-local-skills.js +24 -0
  340. package/dist/pi-local-skills.js.map +1 -0
  341. package/dist/plugins/acp/index.d.ts +46 -0
  342. package/dist/plugins/acp/index.js +111 -0
  343. package/dist/plugins/acp/index.js.map +1 -0
  344. package/dist/plugins/agent-sync/index.d.ts +40 -0
  345. package/dist/plugins/agent-sync/index.js +98 -0
  346. package/dist/plugins/agent-sync/index.js.map +1 -0
  347. package/dist/plugins/http-debug/index.d.ts +30 -0
  348. package/dist/plugins/http-debug/index.js +64 -0
  349. package/dist/plugins/http-debug/index.js.map +1 -0
  350. package/dist/plugins/http-debug/server.d.ts +92 -0
  351. package/dist/plugins/http-debug/server.js +464 -0
  352. package/dist/plugins/http-debug/server.js.map +1 -0
  353. package/dist/ports/agent-core.d.ts +158 -0
  354. package/dist/ports/agent-core.js +2 -0
  355. package/dist/ports/agent-core.js.map +1 -0
  356. package/dist/ports/agent-host.d.ts +125 -0
  357. package/dist/ports/agent-host.js +23 -0
  358. package/dist/ports/agent-host.js.map +1 -0
  359. package/dist/ports/device.d.ts +53 -0
  360. package/dist/ports/device.js +13 -0
  361. package/dist/ports/device.js.map +1 -0
  362. package/dist/ports/identity.d.ts +22 -0
  363. package/dist/ports/identity.js +9 -0
  364. package/dist/ports/identity.js.map +1 -0
  365. package/dist/ports/plugin.d.ts +62 -0
  366. package/dist/ports/plugin.js +35 -0
  367. package/dist/ports/plugin.js.map +1 -0
  368. package/dist/ports/transport.d.ts +32 -0
  369. package/dist/ports/transport.js +12 -0
  370. package/dist/ports/transport.js.map +1 -0
  371. package/dist/ports/vlm.d.ts +59 -0
  372. package/dist/ports/vlm.js +14 -0
  373. package/dist/ports/vlm.js.map +1 -0
  374. package/dist/test-lan-autoglm.d.ts +7 -0
  375. package/dist/test-lan-autoglm.js +46 -0
  376. package/dist/test-lan-autoglm.js.map +1 -0
  377. package/dist/test-mem-breakdown.d.ts +1 -0
  378. package/dist/test-mem-breakdown.js +103 -0
  379. package/dist/test-mem-breakdown.js.map +1 -0
  380. package/dist/test-mem.d.ts +1 -0
  381. package/dist/test-mem.js +60 -0
  382. package/dist/test-mem.js.map +1 -0
  383. package/dist/test-mobile-use.d.ts +1 -0
  384. package/dist/test-mobile-use.js +18 -0
  385. package/dist/test-mobile-use.js.map +1 -0
  386. package/dist/test-screenshot-loop.d.ts +1 -0
  387. package/dist/test-screenshot-loop.js +43 -0
  388. package/dist/test-screenshot-loop.js.map +1 -0
  389. package/dist/test-screenshot.d.ts +1 -0
  390. package/dist/test-screenshot.js +10 -0
  391. package/dist/test-screenshot.js.map +1 -0
  392. package/dist/test-ui-xml-dump.d.ts +15 -0
  393. package/dist/test-ui-xml-dump.js +49 -0
  394. package/dist/test-ui-xml-dump.js.map +1 -0
  395. package/dist/types.d.ts +69 -0
  396. package/dist/types.js +23 -0
  397. package/dist/types.js.map +1 -0
  398. package/package.json +94 -0
@@ -0,0 +1,300 @@
1
+ import OpenAI from "openai";
2
+ import { detectAdapter, getAdapter } from "./adapters/base.js";
3
+ import "./adapters/index.js"; // register all adapters
4
+ const ACTION_MARKERS = ["finish(message=", "do(action=", "<tool_call>", "<answer>"];
5
+ export class OpenAIClient {
6
+ openai;
7
+ config;
8
+ adapter;
9
+ constructor(opts = {}) {
10
+ this.config = {
11
+ baseUrl: normalizeBaseUrl(opts.baseUrl ?? process.env.GUI_AGENT_BASE_URL ?? "https://api.openai.com/v1"),
12
+ apiKey: opts.apiKey ?? process.env.GUI_AGENT_API_KEY ?? "EMPTY",
13
+ modelName: opts.modelName ?? process.env.GUI_AGENT_MODEL ?? "gpt-4o",
14
+ maxTokens: opts.maxTokens ?? 3000,
15
+ temperature: opts.temperature ?? 0,
16
+ topP: opts.topP ?? 0.85,
17
+ };
18
+ this.openai = new OpenAI({
19
+ baseURL: this.config.baseUrl,
20
+ apiKey: this.config.apiKey,
21
+ timeout: 120_000,
22
+ maxRetries: 4,
23
+ });
24
+ this.adapter =
25
+ typeof opts.adapter === "string" ? getAdapter(opts.adapter)
26
+ : opts.adapter instanceof Object && "name" in opts.adapter ? opts.adapter
27
+ : detectAdapter(this.config.modelName);
28
+ }
29
+ get modelName() { return this.config.modelName; }
30
+ get adapterName() { return this.adapter.name; }
31
+ buildMessages(task, screenInfo, context, isFirst, lang) {
32
+ return this.adapter.buildMessages(task, screenInfo, context, isFirst, lang);
33
+ }
34
+ async request(messages, verboseOrOptions = false, signalArg) {
35
+ const opts = typeof verboseOrOptions === "boolean"
36
+ ? { verbose: verboseOrOptions, signal: signalArg }
37
+ : { ...verboseOrOptions, signal: verboseOrOptions.signal ?? signalArg };
38
+ const verbose = opts.verbose ?? false;
39
+ const signal = opts.signal;
40
+ const onTextDelta = opts.onTextDelta;
41
+ const emitDelta = (s) => {
42
+ if (!s || !onTextDelta)
43
+ return;
44
+ try {
45
+ const ret = onTextDelta(s);
46
+ if (ret && typeof ret.then === "function") {
47
+ ret.catch(() => { });
48
+ }
49
+ }
50
+ catch {
51
+ // hook failures must not abort the model stream
52
+ }
53
+ };
54
+ // Some providers (e.g. Zhipu) occasionally RESET long streaming responses.
55
+ // Allow disabling streaming via env for robustness.
56
+ const useStream = process.env.GUI_AGENT_STREAM !== "0";
57
+ if (!useStream) {
58
+ const resp = await this.openai.chat.completions.create({
59
+ model: this.config.modelName,
60
+ messages: messages,
61
+ max_tokens: this.config.maxTokens,
62
+ temperature: this.config.temperature,
63
+ top_p: this.config.topP,
64
+ }, { signal });
65
+ const rawContent = resp.choices?.[0]?.message?.content ?? "";
66
+ if (verbose)
67
+ process.stdout.write(rawContent);
68
+ emitDelta(rawContent);
69
+ const [thinking, action] = splitRaw(rawContent);
70
+ return { rawContent, thinking, action };
71
+ }
72
+ // ── streaming path with chunk-level watchdog ───────────────────────────
73
+ //
74
+ // ARouter / OpenRouter occasionally hold a request in `: OPENROUTER PROCESSING`
75
+ // SSE-comment heartbeats while the upstream model is stuck. The OpenAI SDK's
76
+ // socket timeout never fires (bytes ARE flowing — they're just comments the
77
+ // SSE parser discards), and the `for await` yields zero chunks indefinitely.
78
+ // To bound the worst case we layer two watchdog timers on top of the SDK:
79
+ //
80
+ // • first-chunk: aborts if no SSE chunk (delta-bearing or empty) lands within
81
+ // `GUI_AGENT_FIRST_CHUNK_TIMEOUT_MS` (default 30s).
82
+ // • inter-chunk: once the first chunk lands, aborts if subsequent chunks
83
+ // stall for `GUI_AGENT_INTER_CHUNK_TIMEOUT_MS` (default 60s).
84
+ //
85
+ // Both are converted to `Error("model stream stalled …")` so upstream
86
+ // `agent-runtime/adapters/openai.ts` logs `vlm.predict.failed` and the
87
+ // SessionManager `onError` fallback surfaces a `task:notice` to the UI
88
+ // instead of leaving the worker silently parked.
89
+ const FIRST_CHUNK_TIMEOUT_MS = readPositiveInt(process.env.GUI_AGENT_FIRST_CHUNK_TIMEOUT_MS, 30_000);
90
+ const INTER_CHUNK_TIMEOUT_MS = readPositiveInt(process.env.GUI_AGENT_INTER_CHUNK_TIMEOUT_MS, 60_000);
91
+ // The watchdog runs side-by-side with the iterator: every `iter.next()`
92
+ // (and the initial `create()`) is wrapped in `withStallTimeout` which
93
+ // fires a `setTimeout` and races it against the underlying promise. If
94
+ // the timer wins, the wrapper rejects with a stall error AND aborts the
95
+ // SDK's signal — both paths are needed because some iterators (mocks,
96
+ // and providers that send `: OPENROUTER PROCESSING` SSE comments to
97
+ // keep sockets warm) don't surface AbortSignal cancellation cleanly,
98
+ // so the bare SDK idle timer never fires.
99
+ const controller = new AbortController();
100
+ const externalAbortHandler = () => {
101
+ controller.abort(signal.reason);
102
+ };
103
+ if (signal) {
104
+ if (signal.aborted) {
105
+ controller.abort(signal.reason);
106
+ }
107
+ else {
108
+ signal.addEventListener("abort", externalAbortHandler, { once: true });
109
+ }
110
+ }
111
+ let phase = "first";
112
+ const cleanup = () => {
113
+ signal?.removeEventListener("abort", externalAbortHandler);
114
+ };
115
+ const withStallTimeout = (work) => {
116
+ const ms = phase === "first" ? FIRST_CHUNK_TIMEOUT_MS : INTER_CHUNK_TIMEOUT_MS;
117
+ return new Promise((resolve, reject) => {
118
+ let settled = false;
119
+ const timer = setTimeout(() => {
120
+ if (settled)
121
+ return;
122
+ settled = true;
123
+ const reason = phase === "first"
124
+ ? `model stream stalled: no chunk within ${ms}ms (first-chunk timeout)`
125
+ : `model stream stalled: no chunk within ${ms}ms after partial output (inter-chunk timeout)`;
126
+ const err = new Error(reason);
127
+ controller.abort(err);
128
+ reject(err);
129
+ }, ms);
130
+ work.then((v) => {
131
+ if (settled)
132
+ return;
133
+ settled = true;
134
+ clearTimeout(timer);
135
+ resolve(v);
136
+ }, (e) => {
137
+ if (settled)
138
+ return;
139
+ settled = true;
140
+ clearTimeout(timer);
141
+ reject(e);
142
+ });
143
+ });
144
+ };
145
+ let stream;
146
+ try {
147
+ stream = (await withStallTimeout(this.openai.chat.completions.create({
148
+ model: this.config.modelName,
149
+ messages: messages,
150
+ max_tokens: this.config.maxTokens,
151
+ temperature: this.config.temperature,
152
+ top_p: this.config.topP,
153
+ stream: true,
154
+ }, { signal: controller.signal })));
155
+ }
156
+ catch (e) {
157
+ cleanup();
158
+ throw e;
159
+ }
160
+ let rawContent = "";
161
+ let buffer = "";
162
+ let inAction = false;
163
+ const iter = stream[Symbol.asyncIterator]();
164
+ try {
165
+ while (true) {
166
+ const result = await withStallTimeout(iter.next());
167
+ if (result.done)
168
+ break;
169
+ const chunk = result.value;
170
+ // Any SSE chunk (even an empty role-only frame) means the upstream is
171
+ // still alive — swap to the inter-chunk budget for the next wait.
172
+ phase = "inter";
173
+ if (signal?.aborted) {
174
+ const e = new Error("aborted");
175
+ e.name = "AbortError";
176
+ throw e;
177
+ }
178
+ if (!chunk.choices.length)
179
+ continue;
180
+ const delta = chunk.choices[0].delta;
181
+ // Reasoning models (MAI-UI etc.) emit reasoning_content before content
182
+ const reasoning = delta.reasoning_content;
183
+ if (typeof reasoning === "string" && reasoning) {
184
+ rawContent += reasoning;
185
+ if (!inAction) {
186
+ if (verbose)
187
+ process.stdout.write(reasoning);
188
+ emitDelta(reasoning);
189
+ }
190
+ }
191
+ const content = delta.content ?? "";
192
+ if (!content)
193
+ continue;
194
+ rawContent += content;
195
+ if (inAction)
196
+ continue;
197
+ buffer += content;
198
+ let markerFound = false;
199
+ for (const marker of ACTION_MARKERS) {
200
+ if (buffer.includes(marker)) {
201
+ const pre = buffer.slice(0, buffer.indexOf(marker));
202
+ if (verbose) {
203
+ process.stdout.write(pre);
204
+ process.stdout.write("\n");
205
+ }
206
+ emitDelta(pre);
207
+ inAction = true;
208
+ markerFound = true;
209
+ break;
210
+ }
211
+ }
212
+ if (!markerFound) {
213
+ // Only flush buffer if no partial marker at end
214
+ const partialMatch = ACTION_MARKERS.some((m) => Array.from({ length: m.length - 1 }, (_, k) => k + 1)
215
+ .some((k) => buffer.endsWith(m.slice(0, k))));
216
+ if (!partialMatch) {
217
+ if (verbose)
218
+ process.stdout.write(buffer);
219
+ emitDelta(buffer);
220
+ buffer = "";
221
+ }
222
+ }
223
+ }
224
+ }
225
+ catch (e) {
226
+ cleanup();
227
+ // Best-effort cancel the underlying stream so the SDK / fetch socket
228
+ // is freed even when our watchdog fires while the iterator is still
229
+ // parked.
230
+ try {
231
+ await iter.return?.(undefined);
232
+ }
233
+ catch { /* ignore */ }
234
+ throw e;
235
+ }
236
+ cleanup();
237
+ const [thinking, action] = splitRaw(rawContent);
238
+ return { rawContent, thinking, action };
239
+ }
240
+ parseResponse(raw) {
241
+ return this.adapter.parseResponse(raw);
242
+ }
243
+ updateContext(context, response, parsed) {
244
+ return this.adapter.updateContext(context, response, parsed);
245
+ }
246
+ }
247
+ /**
248
+ * Ensure the OpenAI baseURL ends with a versioned API path. A bare host
249
+ * like `https://api.arouter.ai` causes the SDK to POST `/chat/completions`,
250
+ * which ARouter's edge maps to the wrong upstream and surfaces as
251
+ * `HTTP 502 status code (no body)`. The canonical OpenAI-compatible path
252
+ * is `/v1/chat/completions`, so when the supplied baseURL has no path
253
+ * (just origin), append `/v1`. Anything that already has a path
254
+ * (e.g. custom `/api/v2`, Azure deployments) is left untouched.
255
+ */
256
+ function normalizeBaseUrl(input) {
257
+ if (!input)
258
+ return input;
259
+ let url;
260
+ try {
261
+ url = new URL(input);
262
+ }
263
+ catch {
264
+ return input;
265
+ }
266
+ const path = url.pathname.replace(/\/+$/, "");
267
+ if (path === "" || path === "/") {
268
+ url.pathname = "/v1";
269
+ return url.toString().replace(/\/+$/, "");
270
+ }
271
+ return input.replace(/\/+$/, "");
272
+ }
273
+ function readPositiveInt(raw, fallback) {
274
+ if (!raw)
275
+ return fallback;
276
+ const n = Number(raw);
277
+ if (!Number.isFinite(n) || n <= 0)
278
+ return fallback;
279
+ return Math.floor(n);
280
+ }
281
+ function splitRaw(content) {
282
+ const tcM = content.match(/<tool_call>([\s\S]*?)<\/tool_call>/);
283
+ if (tcM)
284
+ return [content.slice(0, tcM.index).trim(), tcM[0]];
285
+ if (content.includes("<answer>")) {
286
+ const [pre, post] = content.split("<answer>", 2);
287
+ return [pre.replace(/<\/?think>/g, "").trim(), post.replace("</answer>", "").trim()];
288
+ }
289
+ const lastDo = content.lastIndexOf("do(action=");
290
+ const lastFin = content.lastIndexOf("finish(message=");
291
+ const idx = lastDo >= 0 && lastFin >= 0 ? Math.max(lastDo, lastFin)
292
+ : lastDo >= 0 ? lastDo
293
+ : lastFin >= 0 ? lastFin
294
+ : -1;
295
+ if (idx >= 0) {
296
+ return [content.slice(0, idx).trim(), content.slice(idx)];
297
+ }
298
+ return ["", content];
299
+ }
300
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/model/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * VLM image compression — single-purpose utility that produces an
3
+ * ARouter / llama.cpp friendly JPEG from raw screenshot bytes.
4
+ *
5
+ * Why this lives here and not in `device-mcp-server`:
6
+ * - mcp-server is a protocol-layer service. Other consumers (debug
7
+ * viewers, e2e recordings, research tools) want 1:1 high-fidelity
8
+ * captures. Compression is a VLM-specific application-layer concern.
9
+ * - The boundary `mcp-server v0.2.3` deliberately defaults
10
+ * `SS_MAX_EDGE=Infinity` to push compression up the stack — this
11
+ * module fulfils that contract on the device-agent side.
12
+ *
13
+ * Why 1280-edge JPEG q80:
14
+ * - AutoGLM-Phone-9B (= GLM-4.1V-9B-Thinking) vision encoder uses 14-px
15
+ * patches with `image_size=336` and dynamic resize. A 1280-edge input
16
+ * is already past the model's effective perception ceiling — bigger
17
+ * bytes are pure waste.
18
+ * - mozjpeg q80 yields ~20× compression vs raw PNG with no measurable
19
+ * visual loss for UI screenshots (high-frequency text rendering is
20
+ * the worst case and stays sharp at q80).
21
+ * - The combination keeps post-base64 body under ~330KB, well below
22
+ * ARouter's 5MB body limit and llama.cpp's 10MB image cap.
23
+ */
24
+ export interface CompressedImage {
25
+ bytes: Buffer;
26
+ mime: "image/jpeg";
27
+ width: number;
28
+ height: number;
29
+ }
30
+ export interface CompressOptions {
31
+ /** Override `BEEOS_VLM_MAX_EDGE` env (default 1280). */
32
+ maxEdge?: number;
33
+ /** Override `BEEOS_VLM_JPEG_QUALITY` env (default 80, range 1-100). */
34
+ jpegQuality?: number;
35
+ }
36
+ /**
37
+ * Resize (long edge ≤ `maxEdge`) and re-encode an image as mozjpeg
38
+ * `image/jpeg`. Idempotent on already-compressed JPEGs that fit under
39
+ * `maxEdge`: sharp will still re-encode but bytes converge fast.
40
+ *
41
+ * Inputs are accepted in any sharp-readable format (PNG, JPEG, WebP, ...).
42
+ * Output MIME is always `image/jpeg` — this is intentional, see module
43
+ * docstring.
44
+ *
45
+ * Resilience: if `sharp` cannot decode the input (e.g. truncated bytes,
46
+ * corrupt frames, or test-fixture sentinels like `"AAAA"`), the
47
+ * function returns the input bytes unchanged tagged as `image/jpeg`
48
+ * with `width=height=0`. The caller's transport then ships them as-is
49
+ * — letting the upstream model surface the decoding error rather than
50
+ * silently dropping the screenshot. This matches the legacy
51
+ * "wrap-and-forward" semantics of pre-A1 device-agent.
52
+ */
53
+ export declare function compressForVlm(buf: Buffer, opts?: CompressOptions): Promise<CompressedImage>;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * VLM image compression — single-purpose utility that produces an
3
+ * ARouter / llama.cpp friendly JPEG from raw screenshot bytes.
4
+ *
5
+ * Why this lives here and not in `device-mcp-server`:
6
+ * - mcp-server is a protocol-layer service. Other consumers (debug
7
+ * viewers, e2e recordings, research tools) want 1:1 high-fidelity
8
+ * captures. Compression is a VLM-specific application-layer concern.
9
+ * - The boundary `mcp-server v0.2.3` deliberately defaults
10
+ * `SS_MAX_EDGE=Infinity` to push compression up the stack — this
11
+ * module fulfils that contract on the device-agent side.
12
+ *
13
+ * Why 1280-edge JPEG q80:
14
+ * - AutoGLM-Phone-9B (= GLM-4.1V-9B-Thinking) vision encoder uses 14-px
15
+ * patches with `image_size=336` and dynamic resize. A 1280-edge input
16
+ * is already past the model's effective perception ceiling — bigger
17
+ * bytes are pure waste.
18
+ * - mozjpeg q80 yields ~20× compression vs raw PNG with no measurable
19
+ * visual loss for UI screenshots (high-frequency text rendering is
20
+ * the worst case and stays sharp at q80).
21
+ * - The combination keeps post-base64 body under ~330KB, well below
22
+ * ARouter's 5MB body limit and llama.cpp's 10MB image cap.
23
+ */
24
+ import sharp from "sharp";
25
+ const DEFAULT_MAX_EDGE = 1280;
26
+ const DEFAULT_JPEG_QUALITY = 80;
27
+ /**
28
+ * Resize (long edge ≤ `maxEdge`) and re-encode an image as mozjpeg
29
+ * `image/jpeg`. Idempotent on already-compressed JPEGs that fit under
30
+ * `maxEdge`: sharp will still re-encode but bytes converge fast.
31
+ *
32
+ * Inputs are accepted in any sharp-readable format (PNG, JPEG, WebP, ...).
33
+ * Output MIME is always `image/jpeg` — this is intentional, see module
34
+ * docstring.
35
+ *
36
+ * Resilience: if `sharp` cannot decode the input (e.g. truncated bytes,
37
+ * corrupt frames, or test-fixture sentinels like `"AAAA"`), the
38
+ * function returns the input bytes unchanged tagged as `image/jpeg`
39
+ * with `width=height=0`. The caller's transport then ships them as-is
40
+ * — letting the upstream model surface the decoding error rather than
41
+ * silently dropping the screenshot. This matches the legacy
42
+ * "wrap-and-forward" semantics of pre-A1 device-agent.
43
+ */
44
+ export async function compressForVlm(buf, opts = {}) {
45
+ const maxEdge = resolveInt(opts.maxEdge, "BEEOS_VLM_MAX_EDGE", DEFAULT_MAX_EDGE);
46
+ const jpegQuality = clampQuality(resolveInt(opts.jpegQuality, "BEEOS_VLM_JPEG_QUALITY", DEFAULT_JPEG_QUALITY));
47
+ try {
48
+ const meta = await sharp(buf, { failOn: "none" }).metadata();
49
+ const srcW = meta.width ?? 0;
50
+ const srcH = meta.height ?? 0;
51
+ const longEdge = Math.max(srcW, srcH);
52
+ let pipeline = sharp(buf, { failOn: "none" });
53
+ if (longEdge > maxEdge) {
54
+ pipeline = srcW >= srcH
55
+ ? pipeline.resize({ width: maxEdge, withoutEnlargement: true })
56
+ : pipeline.resize({ height: maxEdge, withoutEnlargement: true });
57
+ }
58
+ const bytes = await pipeline.jpeg({ quality: jpegQuality, mozjpeg: true }).toBuffer();
59
+ const out = await sharp(bytes).metadata();
60
+ return {
61
+ bytes,
62
+ mime: "image/jpeg",
63
+ width: out.width ?? srcW,
64
+ height: out.height ?? srcH,
65
+ };
66
+ }
67
+ catch {
68
+ return { bytes: buf, mime: "image/jpeg", width: 0, height: 0 };
69
+ }
70
+ }
71
+ function resolveInt(explicit, envKey, fallback) {
72
+ if (typeof explicit === "number" && Number.isFinite(explicit) && explicit > 0)
73
+ return explicit;
74
+ const raw = process.env[envKey];
75
+ if (!raw)
76
+ return fallback;
77
+ const parsed = parseInt(raw, 10);
78
+ if (!Number.isFinite(parsed) || parsed <= 0)
79
+ return fallback;
80
+ return parsed;
81
+ }
82
+ function clampQuality(q) {
83
+ if (q < 1)
84
+ return 1;
85
+ if (q > 100)
86
+ return 100;
87
+ return Math.round(q);
88
+ }
89
+ //# sourceMappingURL=compress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.js","sourceRoot":"","sources":["../../../src/model/image/compress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * ImageTransport — strategy abstraction for delivering a compressed VLM
3
+ * image to the model.
4
+ *
5
+ * bytes ──▶ Transport ──▶ ImageRef
6
+ *
7
+ * Two concrete strategies live in the codebase:
8
+ * - `DataUrlTransport` (Phase A) → inline `data:<mime>;base64,...`
9
+ * - `HttpUrlTransport` (Phase B) → presign + PUT to S3, return signed
10
+ * GET URL
11
+ *
12
+ * `FallbackTransport` composes any two strategies so production traffic
13
+ * can be configured to "prefer http-url, gracefully degrade to data-url
14
+ * on transient upload failure" — keeping a hard correctness floor while
15
+ * still gaining the body-size win when everything is healthy.
16
+ */
17
+ import { type AgentGatewayIdentity, type PresignFilePair } from "../../adapters/agent-gateway-client.js";
18
+ import type { ImageRef } from "../../types.js";
19
+ export type ImageMime = "image/jpeg" | "image/png";
20
+ export interface ImageTransport {
21
+ /** Stable, log-friendly identifier — useful for metrics/labels. */
22
+ readonly name: string;
23
+ send(bytes: Buffer, mime: ImageMime): Promise<ImageRef>;
24
+ }
25
+ /**
26
+ * Inline-base64 transport. Always succeeds (modulo OOM); the body bloat
27
+ * is bounded only by the input bytes — pair this with `compressForVlm`
28
+ * upstream to stay below ARouter's 5MB body cap.
29
+ */
30
+ export declare class DataUrlTransport implements ImageTransport {
31
+ readonly name = "data-url";
32
+ send(bytes: Buffer, mime: ImageMime): Promise<ImageRef>;
33
+ }
34
+ export interface HttpUrlFileClient {
35
+ presignFileUpload(args: {
36
+ fileName: string;
37
+ mimeType: string;
38
+ }): Promise<PresignFilePair>;
39
+ putPresignedBytes(args: {
40
+ uploadUrl: string;
41
+ bytes: Uint8Array;
42
+ mimeType: string;
43
+ }): Promise<void>;
44
+ }
45
+ export interface HttpUrlTransportOptions {
46
+ /**
47
+ * Object-name prefix passed as `fileName` to `presignFileUpload`.
48
+ * Defaults to `vlm-screenshots/`. Lifecycle rules in Phase B8 attach
49
+ * to this prefix for automatic 24h cleanup.
50
+ */
51
+ keyPrefix?: string;
52
+ /** Test seam — defaults to `crypto.randomUUID()`. */
53
+ randomUUID?: () => string;
54
+ /** Test seam — defaults to `Date.now()`. */
55
+ now?: () => number;
56
+ }
57
+ /**
58
+ * Adapter implementation of `HttpUrlFileClient` that hits the live
59
+ * Agent Gateway over HTTP/1.1 with Ed25519 auth. Suitable for
60
+ * production wiring; tests should pass a mock `HttpUrlFileClient`.
61
+ */
62
+ export declare class AgentGatewayFileClient implements HttpUrlFileClient {
63
+ private readonly opts;
64
+ constructor(opts: {
65
+ agentGatewayUrl: string;
66
+ identity: AgentGatewayIdentity;
67
+ timeoutMs?: number;
68
+ });
69
+ presignFileUpload(args: {
70
+ fileName: string;
71
+ mimeType: string;
72
+ }): Promise<PresignFilePair>;
73
+ putPresignedBytes(args: {
74
+ uploadUrl: string;
75
+ bytes: Uint8Array;
76
+ mimeType: string;
77
+ }): Promise<void>;
78
+ }
79
+ /**
80
+ * Resource-link transport — pre-signs an S3/MinIO PUT URL via Agent
81
+ * Gateway, uploads the (already-compressed) image bytes, and returns
82
+ * the paired pre-signed GET URL as an `kind: "http-url"` `ImageRef`.
83
+ *
84
+ * Why this exists:
85
+ *
86
+ * - ARouter / Cloudfront / nginx in front of `llama.cpp` cap request
87
+ * bodies at ≈5 MB. A raw 1080×1920 PNG screenshot base64-encoded
88
+ * in a chat-completion message routinely overflows that cap, so
89
+ * the only robust path for production traffic is to ship a URL,
90
+ * not bytes.
91
+ * - `llama.cpp`'s vision server fetches `image_url`s natively
92
+ * (subject to its own ≈10 MB / 10 s download caps), making this a
93
+ * transport-only change — no model-side adapter rewrite required.
94
+ *
95
+ * Errors:
96
+ * - Both steps surface `AgentGatewayError`. Compose with
97
+ * `FallbackTransport(http, data)` if the caller wants a graceful
98
+ * degradation to inline base64 on transient upload failure.
99
+ *
100
+ * Body sigv4 caveat: the `Content-Type` MUST equal what was passed at
101
+ * presign time, otherwise S3 returns 403 (signature mismatch). We
102
+ * forward `mime` to both calls so this is automatic.
103
+ */
104
+ export declare class HttpUrlTransport implements ImageTransport {
105
+ private readonly client;
106
+ readonly name = "http-url";
107
+ private readonly keyPrefix;
108
+ private readonly randomUUID;
109
+ private readonly now;
110
+ constructor(client: HttpUrlFileClient, opts?: HttpUrlTransportOptions);
111
+ send(bytes: Buffer, mime: ImageMime): Promise<ImageRef>;
112
+ }
113
+ export interface FallbackTransportLogger {
114
+ warn(msg: string, fields?: Record<string, unknown>): void;
115
+ }
116
+ export interface FallbackTransportOptions {
117
+ logger?: FallbackTransportLogger;
118
+ /** Hook for monitoring — invoked once per fallback path taken. */
119
+ onFallback?: (reason: unknown) => void;
120
+ }
121
+ /**
122
+ * Try `primary`; if it throws, log and fall back to `fallback`. The
123
+ * second transport's failure propagates to the caller — we never silently
124
+ * swallow a degraded-mode error.
125
+ */
126
+ export declare class FallbackTransport implements ImageTransport {
127
+ private readonly primary;
128
+ private readonly fallback;
129
+ readonly name: string;
130
+ private readonly logger;
131
+ private readonly onFallback?;
132
+ constructor(primary: ImageTransport, fallback: ImageTransport, opts?: FallbackTransportOptions);
133
+ send(bytes: Buffer, mime: ImageMime): Promise<ImageRef>;
134
+ }