@songsid/agend 2.3.4-beta.7 → 2.3.5-alpha.3

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 (457) hide show
  1. package/README.md +2 -0
  2. package/README.zh-TW.md +2 -0
  3. package/THIRD_PARTY_NOTICES.md +53 -0
  4. package/dist/agent-endpoint.d.ts +5 -1
  5. package/dist/agent-endpoint.js +12 -2
  6. package/dist/agent-endpoint.js.map +1 -1
  7. package/dist/auth-api.d.ts +21 -0
  8. package/dist/auth-api.js +89 -2
  9. package/dist/auth-api.js.map +1 -1
  10. package/dist/authority/web-authority.d.ts +12 -2
  11. package/dist/authority/web-authority.js +25 -4
  12. package/dist/authority/web-authority.js.map +1 -1
  13. package/dist/backend/claude-code.d.ts +15 -12
  14. package/dist/backend/claude-code.js +152 -133
  15. package/dist/backend/claude-code.js.map +1 -1
  16. package/dist/backend/codex-package.d.ts +5 -2
  17. package/dist/backend/codex-package.js +1 -5
  18. package/dist/backend/codex-package.js.map +1 -1
  19. package/dist/backend/codex.d.ts +136 -113
  20. package/dist/backend/codex.js +1281 -1219
  21. package/dist/backend/codex.js.map +1 -1
  22. package/dist/backend/grok-model-cache.d.ts +7 -0
  23. package/dist/backend/grok-model-cache.js +65 -0
  24. package/dist/backend/grok-model-cache.js.map +1 -0
  25. package/dist/backend/grok.d.ts +2 -0
  26. package/dist/backend/grok.js +22 -0
  27. package/dist/backend/grok.js.map +1 -1
  28. package/dist/backend/native-pane.d.ts +9 -0
  29. package/dist/backend/native-pane.js +59 -0
  30. package/dist/backend/native-pane.js.map +1 -0
  31. package/dist/backend/types.d.ts +7 -0
  32. package/dist/backend/types.js.map +1 -1
  33. package/dist/channel/ipc-bridge.d.ts +2 -0
  34. package/dist/channel/mcp-tools.js +1 -1
  35. package/dist/channel/mcp-tools.js.map +1 -1
  36. package/dist/cli.js +3 -0
  37. package/dist/cli.js.map +1 -1
  38. package/dist/config-validator.js +71 -1
  39. package/dist/config-validator.js.map +1 -1
  40. package/dist/config.js +16 -0
  41. package/dist/config.js.map +1 -1
  42. package/dist/daemon.d.ts +67 -5
  43. package/dist/daemon.js +823 -266
  44. package/dist/daemon.js.map +1 -1
  45. package/dist/delivery-consumed-watch.d.ts +15 -3
  46. package/dist/delivery-consumed-watch.js +23 -1
  47. package/dist/delivery-consumed-watch.js.map +1 -1
  48. package/dist/delivery-outbox.d.ts +5 -0
  49. package/dist/delivery-outbox.js +32 -4
  50. package/dist/delivery-outbox.js.map +1 -1
  51. package/dist/delivery-reconciliation.d.ts +2 -35
  52. package/dist/delivery-reconciliation.js +2 -156
  53. package/dist/delivery-reconciliation.js.map +1 -1
  54. package/dist/fleet-context.d.ts +2 -2
  55. package/dist/fleet-level-config.d.ts +1 -1
  56. package/dist/fleet-level-config.js +2 -0
  57. package/dist/fleet-level-config.js.map +1 -1
  58. package/dist/fleet-manager.d.ts +238 -3
  59. package/dist/fleet-manager.js +1826 -104
  60. package/dist/fleet-manager.js.map +1 -1
  61. package/dist/fleet-windows-runtime.d.ts +92 -0
  62. package/dist/fleet-windows-runtime.js +380 -0
  63. package/dist/fleet-windows-runtime.js.map +1 -0
  64. package/dist/general-binding.d.ts +85 -0
  65. package/dist/general-binding.js +298 -0
  66. package/dist/general-binding.js.map +1 -0
  67. package/dist/general-host-owner.d.ts +8 -0
  68. package/dist/general-host-owner.js +26 -0
  69. package/dist/general-host-owner.js.map +1 -0
  70. package/dist/general-instance.d.ts +7 -0
  71. package/dist/general-instance.js +20 -3
  72. package/dist/general-instance.js.map +1 -1
  73. package/dist/general-role.d.ts +5 -0
  74. package/dist/general-role.js +26 -0
  75. package/dist/general-role.js.map +1 -0
  76. package/dist/instance-config-impact.js +4 -0
  77. package/dist/instance-config-impact.js.map +1 -1
  78. package/dist/instance-lifecycle.d.ts +21 -3
  79. package/dist/instance-lifecycle.js +378 -162
  80. package/dist/instance-lifecycle.js.map +1 -1
  81. package/dist/instructions.d.ts +2 -0
  82. package/dist/instructions.js +6 -0
  83. package/dist/instructions.js.map +1 -1
  84. package/dist/local-pane-endpoint.d.ts +46 -0
  85. package/dist/local-pane-endpoint.js +189 -0
  86. package/dist/local-pane-endpoint.js.map +1 -0
  87. package/dist/local-pane-launcher.d.ts +2 -0
  88. package/dist/local-pane-launcher.js +38 -0
  89. package/dist/local-pane-launcher.js.map +1 -0
  90. package/dist/local-pane-stage.ps1 +101 -0
  91. package/dist/locale.js +85 -0
  92. package/dist/locale.js.map +1 -1
  93. package/dist/model-catalog-defaults.d.ts +14 -0
  94. package/dist/model-catalog-defaults.js +20 -0
  95. package/dist/model-catalog-defaults.js.map +1 -0
  96. package/dist/native-agent-admission.d.ts +7 -0
  97. package/dist/native-agent-admission.js +26 -0
  98. package/dist/native-agent-admission.js.map +1 -0
  99. package/dist/native-daemon-client.d.ts +13 -0
  100. package/dist/native-daemon-client.js +28 -0
  101. package/dist/native-daemon-client.js.map +1 -0
  102. package/dist/native-instance-api.d.ts +14 -0
  103. package/dist/native-instance-api.js +205 -0
  104. package/dist/native-instance-api.js.map +1 -0
  105. package/dist/native-instance-input.d.ts +84 -0
  106. package/dist/native-instance-input.js +54 -0
  107. package/dist/native-instance-input.js.map +1 -0
  108. package/dist/native-instance-registry.d.ts +32 -0
  109. package/dist/native-instance-registry.js +105 -0
  110. package/dist/native-instance-registry.js.map +1 -0
  111. package/dist/native-mcp.d.ts +40 -0
  112. package/dist/native-mcp.js +278 -0
  113. package/dist/native-mcp.js.map +1 -0
  114. package/dist/native-model-catalog.d.ts +5 -0
  115. package/dist/native-model-catalog.js +76 -0
  116. package/dist/native-model-catalog.js.map +1 -0
  117. package/dist/native-pane-crash-budget.d.ts +20 -0
  118. package/dist/native-pane-crash-budget.js +60 -0
  119. package/dist/native-pane-crash-budget.js.map +1 -0
  120. package/dist/native-pane-create.d.ts +26 -0
  121. package/dist/native-pane-create.js +53 -0
  122. package/dist/native-pane-create.js.map +1 -0
  123. package/dist/native-pane-lifecycle.d.ts +65 -0
  124. package/dist/native-pane-lifecycle.js +230 -0
  125. package/dist/native-pane-lifecycle.js.map +1 -0
  126. package/dist/native-pane-manager.d.ts +59 -0
  127. package/dist/native-pane-manager.js +584 -0
  128. package/dist/native-pane-manager.js.map +1 -0
  129. package/dist/native-pane-output-log.d.ts +15 -0
  130. package/dist/native-pane-output-log.js +108 -0
  131. package/dist/native-pane-output-log.js.map +1 -0
  132. package/dist/native-pane-reconciliation.d.ts +4 -0
  133. package/dist/native-pane-reconciliation.js +40 -0
  134. package/dist/native-pane-reconciliation.js.map +1 -0
  135. package/dist/native-pane-recovery.d.ts +12 -0
  136. package/dist/native-pane-recovery.js +10 -0
  137. package/dist/native-pane-recovery.js.map +1 -0
  138. package/dist/native-pane-tools.d.ts +2 -0
  139. package/dist/native-pane-tools.js +14 -0
  140. package/dist/native-pane-tools.js.map +1 -0
  141. package/dist/needs-you-hub.d.ts +2 -0
  142. package/dist/needs-you-hub.js +2 -1
  143. package/dist/needs-you-hub.js.map +1 -1
  144. package/dist/needs-you.d.ts +19 -1
  145. package/dist/needs-you.js +12 -2
  146. package/dist/needs-you.js.map +1 -1
  147. package/dist/outbound-handlers.d.ts +16 -2
  148. package/dist/outbound-handlers.js +67 -3
  149. package/dist/outbound-handlers.js.map +1 -1
  150. package/dist/outbound-schemas.d.ts +38 -0
  151. package/dist/outbound-schemas.js +12 -0
  152. package/dist/outbound-schemas.js.map +1 -1
  153. package/dist/pane-port.d.ts +118 -0
  154. package/dist/pane-port.js +2 -0
  155. package/dist/pane-port.js.map +1 -0
  156. package/dist/public-web-gateway.js +9 -0
  157. package/dist/public-web-gateway.js.map +1 -1
  158. package/dist/public-web-link.d.ts +5 -0
  159. package/dist/public-web-link.js +4 -0
  160. package/dist/public-web-link.js.map +1 -1
  161. package/dist/quickstart-api.js +9 -5
  162. package/dist/quickstart-api.js.map +1 -1
  163. package/dist/quickstart.d.ts +1 -0
  164. package/dist/quickstart.js +4 -1
  165. package/dist/quickstart.js.map +1 -1
  166. package/dist/runtime-api.d.ts +8 -0
  167. package/dist/runtime-api.js +96 -0
  168. package/dist/runtime-api.js.map +1 -0
  169. package/dist/runtime-assets/@xterm/addon-serialize/LICENSE +21 -0
  170. package/dist/runtime-assets/@xterm/addon-serialize/lib/addon-serialize.js +2 -0
  171. package/dist/runtime-assets/@xterm/addon-serialize/lib/addon-serialize.mjs +19 -0
  172. package/dist/runtime-assets/@xterm/addon-serialize/package.json +29 -0
  173. package/dist/runtime-assets/@xterm/headless/LICENSE +21 -0
  174. package/dist/runtime-assets/@xterm/headless/lib-headless/xterm-headless.js +2 -0
  175. package/dist/runtime-assets/@xterm/headless/lib-headless/xterm-headless.mjs +46 -0
  176. package/dist/runtime-assets/@xterm/headless/package.json +29 -0
  177. package/dist/runtime-assets/node-pty/CONPTY-LICENSE +21 -0
  178. package/dist/runtime-assets/node-pty/CONPTY-NOTICE.md +503 -0
  179. package/dist/runtime-assets/node-pty/LICENSE +69 -0
  180. package/dist/runtime-assets/node-pty/lib/conpty_console_list_agent.js +16 -0
  181. package/dist/runtime-assets/node-pty/lib/eventEmitter2.js +47 -0
  182. package/dist/runtime-assets/node-pty/lib/index.js +52 -0
  183. package/dist/runtime-assets/node-pty/lib/interfaces.js +7 -0
  184. package/dist/runtime-assets/node-pty/lib/shared/conout.js +11 -0
  185. package/dist/runtime-assets/node-pty/lib/terminal.js +190 -0
  186. package/dist/runtime-assets/node-pty/lib/types.js +7 -0
  187. package/dist/runtime-assets/node-pty/lib/unixTerminal.js +346 -0
  188. package/dist/runtime-assets/node-pty/lib/utils.js +39 -0
  189. package/dist/runtime-assets/node-pty/lib/windowsConoutConnection.js +125 -0
  190. package/dist/runtime-assets/node-pty/lib/windowsPtyAgent.js +320 -0
  191. package/dist/runtime-assets/node-pty/lib/windowsTerminal.js +199 -0
  192. package/dist/runtime-assets/node-pty/lib/worker/conoutSocketWorker.js +22 -0
  193. package/dist/runtime-assets/node-pty/package.json +64 -0
  194. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  195. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  196. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty.node +0 -0
  197. package/dist/runtime-assets/node-pty/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  198. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  199. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  200. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty.node +0 -0
  201. package/dist/runtime-assets/node-pty/prebuilds/win32-x64/conpty_console_list.node +0 -0
  202. package/dist/runtime-bundle.d.ts +17 -0
  203. package/dist/runtime-bundle.js +150 -0
  204. package/dist/runtime-bundle.js.map +1 -0
  205. package/dist/runtime-cli.d.ts +2 -0
  206. package/dist/runtime-cli.js +117 -0
  207. package/dist/runtime-cli.js.map +1 -0
  208. package/dist/runtime-client-store.d.ts +49 -0
  209. package/dist/runtime-client-store.js +292 -0
  210. package/dist/runtime-client-store.js.map +1 -0
  211. package/dist/runtime-client.d.ts +100 -0
  212. package/dist/runtime-client.js +700 -0
  213. package/dist/runtime-client.js.map +1 -0
  214. package/dist/runtime-coordinator.d.ts +82 -0
  215. package/dist/runtime-coordinator.js +864 -0
  216. package/dist/runtime-coordinator.js.map +1 -0
  217. package/dist/runtime-general-protocol.d.ts +22 -0
  218. package/dist/runtime-general-protocol.js +57 -0
  219. package/dist/runtime-general-protocol.js.map +1 -0
  220. package/dist/runtime-general-workspace.d.ts +17 -0
  221. package/dist/runtime-general-workspace.js +213 -0
  222. package/dist/runtime-general-workspace.js.map +1 -0
  223. package/dist/runtime-pane-assets.d.ts +17 -0
  224. package/dist/runtime-pane-assets.js +23 -0
  225. package/dist/runtime-pane-assets.js.map +1 -0
  226. package/dist/runtime-pane-boot.d.ts +2 -0
  227. package/dist/runtime-pane-boot.js +24 -0
  228. package/dist/runtime-pane-boot.js.map +1 -0
  229. package/dist/runtime-pane-codex-index.d.ts +1 -0
  230. package/dist/runtime-pane-codex-index.js +47 -0
  231. package/dist/runtime-pane-codex-index.js.map +1 -0
  232. package/dist/runtime-pane-config.d.ts +16 -0
  233. package/dist/runtime-pane-config.js +54 -0
  234. package/dist/runtime-pane-config.js.map +1 -0
  235. package/dist/runtime-pane-host.d.ts +44 -0
  236. package/dist/runtime-pane-host.js +424 -0
  237. package/dist/runtime-pane-host.js.map +1 -0
  238. package/dist/runtime-pane-job-owner.d.ts +1 -0
  239. package/dist/runtime-pane-job-owner.js +29 -0
  240. package/dist/runtime-pane-job-owner.js.map +1 -0
  241. package/dist/runtime-pane-job.ps1 +116 -0
  242. package/dist/runtime-pane-link.d.ts +40 -0
  243. package/dist/runtime-pane-link.js +246 -0
  244. package/dist/runtime-pane-link.js.map +1 -0
  245. package/dist/runtime-pane-mcp-protocol.d.ts +32 -0
  246. package/dist/runtime-pane-mcp-protocol.js +39 -0
  247. package/dist/runtime-pane-mcp-protocol.js.map +1 -0
  248. package/dist/runtime-pane-mcp-relay.d.ts +17 -0
  249. package/dist/runtime-pane-mcp-relay.js +70 -0
  250. package/dist/runtime-pane-mcp-relay.js.map +1 -0
  251. package/dist/runtime-pane-mcp.d.ts +51 -0
  252. package/dist/runtime-pane-mcp.js +150 -0
  253. package/dist/runtime-pane-mcp.js.map +1 -0
  254. package/dist/runtime-pane-native.d.ts +45 -0
  255. package/dist/runtime-pane-native.js +65 -0
  256. package/dist/runtime-pane-native.js.map +1 -0
  257. package/dist/runtime-pane-output.d.ts +19 -0
  258. package/dist/runtime-pane-output.js +53 -0
  259. package/dist/runtime-pane-output.js.map +1 -0
  260. package/dist/runtime-pane-port.d.ts +139 -0
  261. package/dist/runtime-pane-port.js +558 -0
  262. package/dist/runtime-pane-port.js.map +1 -0
  263. package/dist/runtime-pane-private.d.ts +14 -0
  264. package/dist/runtime-pane-private.js +51 -0
  265. package/dist/runtime-pane-private.js.map +1 -0
  266. package/dist/runtime-pane-private.ps1 +14 -0
  267. package/dist/runtime-pane-process.d.ts +4 -0
  268. package/dist/runtime-pane-process.js +108 -0
  269. package/dist/runtime-pane-process.js.map +1 -0
  270. package/dist/runtime-pane-protocol.d.ts +172 -0
  271. package/dist/runtime-pane-protocol.js +195 -0
  272. package/dist/runtime-pane-protocol.js.map +1 -0
  273. package/dist/runtime-pane-screen.d.ts +19 -0
  274. package/dist/runtime-pane-screen.js +76 -0
  275. package/dist/runtime-pane-screen.js.map +1 -0
  276. package/dist/runtime-pane-service.d.ts +11 -0
  277. package/dist/runtime-pane-service.js +221 -0
  278. package/dist/runtime-pane-service.js.map +1 -0
  279. package/dist/runtime-pane-stdio-protocol.d.ts +54 -0
  280. package/dist/runtime-pane-stdio-protocol.js +94 -0
  281. package/dist/runtime-pane-stdio-protocol.js.map +1 -0
  282. package/dist/runtime-pane-stdio.d.ts +3 -0
  283. package/dist/runtime-pane-stdio.js +123 -0
  284. package/dist/runtime-pane-stdio.js.map +1 -0
  285. package/dist/runtime-pane-store.d.ts +33 -0
  286. package/dist/runtime-pane-store.js +164 -0
  287. package/dist/runtime-pane-store.js.map +1 -0
  288. package/dist/runtime-pane-transcript-protocol.d.ts +43 -0
  289. package/dist/runtime-pane-transcript-protocol.js +58 -0
  290. package/dist/runtime-pane-transcript-protocol.js.map +1 -0
  291. package/dist/runtime-pane-transcript.d.ts +45 -0
  292. package/dist/runtime-pane-transcript.js +605 -0
  293. package/dist/runtime-pane-transcript.js.map +1 -0
  294. package/dist/runtime-pane-worker.d.ts +1 -0
  295. package/dist/runtime-pane-worker.js +154 -0
  296. package/dist/runtime-pane-worker.js.map +1 -0
  297. package/dist/runtime-protocol.d.ts +149 -0
  298. package/dist/runtime-protocol.js +19 -0
  299. package/dist/runtime-protocol.js.map +1 -0
  300. package/dist/runtime-switches.d.ts +79 -0
  301. package/dist/runtime-switches.js +90 -0
  302. package/dist/runtime-switches.js.map +1 -0
  303. package/dist/runtime-transcript-delta-reader.d.ts +23 -0
  304. package/dist/runtime-transcript-delta-reader.js +74 -0
  305. package/dist/runtime-transcript-delta-reader.js.map +1 -0
  306. package/dist/runtime-transcript-source.d.ts +36 -0
  307. package/dist/runtime-transcript-source.js +189 -0
  308. package/dist/runtime-transcript-source.js.map +1 -0
  309. package/dist/runtime-windows-bridge.d.ts +41 -0
  310. package/dist/runtime-windows-bridge.js +157 -0
  311. package/dist/runtime-windows-bridge.js.map +1 -0
  312. package/dist/settings-api.d.ts +5 -0
  313. package/dist/settings-api.js +95 -1
  314. package/dist/settings-api.js.map +1 -1
  315. package/dist/settings-baseline.d.ts +1 -0
  316. package/dist/settings-baseline.js +1 -1
  317. package/dist/settings-baseline.js.map +1 -1
  318. package/dist/settings-change.js +28 -0
  319. package/dist/settings-change.js.map +1 -1
  320. package/dist/settings-confirmation.d.ts +16 -1
  321. package/dist/settings-confirmation.js +47 -9
  322. package/dist/settings-confirmation.js.map +1 -1
  323. package/dist/settings-effect.d.ts +4 -0
  324. package/dist/settings-effect.js +58 -1
  325. package/dist/settings-effect.js.map +1 -1
  326. package/dist/settings-http-confirmation.d.ts +1 -0
  327. package/dist/settings-http-confirmation.js +15 -2
  328. package/dist/settings-http-confirmation.js.map +1 -1
  329. package/dist/settings-request-capability.d.ts +2 -0
  330. package/dist/settings-request-capability.js +4 -0
  331. package/dist/settings-request-capability.js.map +1 -1
  332. package/dist/settings-route-lifetime.d.ts +14 -0
  333. package/dist/settings-route-lifetime.js +48 -0
  334. package/dist/settings-route-lifetime.js.map +1 -0
  335. package/dist/settings-transaction.d.ts +4 -0
  336. package/dist/settings-transaction.js +9 -0
  337. package/dist/settings-transaction.js.map +1 -1
  338. package/dist/setup-form.js +6 -3
  339. package/dist/setup-form.js.map +1 -1
  340. package/dist/setup-i18n.js +3 -0
  341. package/dist/setup-i18n.js.map +1 -1
  342. package/dist/tmux-control.d.ts +2 -1
  343. package/dist/tmux-control.js.map +1 -1
  344. package/dist/tmux-manager.d.ts +2 -1
  345. package/dist/tmux-manager.js.map +1 -1
  346. package/dist/tmux-pane-host.d.ts +26 -0
  347. package/dist/tmux-pane-host.js +25 -0
  348. package/dist/tmux-pane-host.js.map +1 -0
  349. package/dist/tool-permissions.js +2 -1
  350. package/dist/tool-permissions.js.map +1 -1
  351. package/dist/topic-commands.js +3 -0
  352. package/dist/topic-commands.js.map +1 -1
  353. package/dist/transcript-delta-reader.d.ts +1 -1
  354. package/dist/transcript-delta-reader.js +1 -1
  355. package/dist/transcript-delta-reader.js.map +1 -1
  356. package/dist/transcript-monitor.d.ts +3 -0
  357. package/dist/transcript-monitor.js +22 -46
  358. package/dist/transcript-monitor.js.map +1 -1
  359. package/dist/transcript-needles.d.ts +35 -0
  360. package/dist/transcript-needles.js +158 -0
  361. package/dist/transcript-needles.js.map +1 -0
  362. package/dist/transcript-records.d.ts +21 -0
  363. package/dist/transcript-records.js +140 -0
  364. package/dist/transcript-records.js.map +1 -0
  365. package/dist/transcript-sources.d.ts +5 -0
  366. package/dist/transcript-sources.js +8 -79
  367. package/dist/transcript-sources.js.map +1 -1
  368. package/dist/types.d.ts +23 -0
  369. package/dist/ui/agent-proposals.js +90 -0
  370. package/dist/ui/agent-runtime.js +106 -0
  371. package/dist/ui/chat-store.js +13 -2
  372. package/dist/ui/chat-strings.js +48 -0
  373. package/dist/ui/cli-picker.js +42 -0
  374. package/dist/ui/general-location.js +71 -0
  375. package/dist/ui/native-instance-settings.js +47 -0
  376. package/dist/ui/native-pane-recovery.js +45 -0
  377. package/dist/ui/panel-chat.js +63 -32
  378. package/dist/ui/panel-details.js +2 -1
  379. package/dist/ui/panel-fleet.js +99 -18
  380. package/dist/ui/panel-needs.js +154 -3
  381. package/dist/ui/panel-runtimes.js +231 -0
  382. package/dist/ui/panel-settings.js +19 -9
  383. package/dist/ui/panel-windows-agent.js +86 -0
  384. package/dist/ui/panel-windows-cli.js +143 -0
  385. package/dist/ui/provider-marks.js +83 -0
  386. package/dist/ui/runtime-catalog.js +55 -0
  387. package/dist/ui/settings-catalog.js +37 -10
  388. package/dist/ui/settings-confirm.js +3 -1
  389. package/dist/ui/settings-dialogs.js +22 -7
  390. package/dist/ui/settings-model.js +2 -1
  391. package/dist/ui/settings-outside.js +176 -0
  392. package/dist/ui/settings-registry.js +6 -0
  393. package/dist/ui/settings-strings.js +16 -0
  394. package/dist/ui/shared/app-i18n.js +2 -2
  395. package/dist/ui/shared/app-route.js +6 -2
  396. package/dist/ui/shared/app-shell.js +3 -2
  397. package/dist/ui/shared/app-store.js +1 -0
  398. package/dist/ui/shared/app-stream.js +3 -1
  399. package/dist/ui/shared/app.css +301 -0
  400. package/dist/ui/shared/app.js +4 -0
  401. package/dist/ui/shared/header-tools.js +6 -4
  402. package/dist/ui/shared/instance-nav.js +33 -7
  403. package/dist/ui/shared/instance-switch.js +4 -3
  404. package/dist/ui/shared/qrcode.module.js +2237 -0
  405. package/dist/ui/shared/signin.js +39 -5
  406. package/dist/ui/shared/ui-menu.js +28 -8
  407. package/dist/ui/shared/vendor/qrcode-generator.LICENSE +27 -0
  408. package/dist/ui/shared/vendor/vendor.json +19 -2
  409. package/dist/ui/shared/view-strings.js +8 -0
  410. package/dist/ui/windows-agents-nav.js +2 -0
  411. package/dist/ui/windows-cli-catalog.js +79 -0
  412. package/dist/web-api.d.ts +37 -0
  413. package/dist/web-api.js +248 -6
  414. package/dist/web-api.js.map +1 -1
  415. package/dist/web-chat-history.d.ts +19 -2
  416. package/dist/web-chat-history.js +72 -3
  417. package/dist/web-chat-history.js.map +1 -1
  418. package/dist/web-only-fleet.d.ts +20 -0
  419. package/dist/web-only-fleet.js +21 -0
  420. package/dist/web-only-fleet.js.map +1 -1
  421. package/dist/web-remote-access.d.ts +152 -0
  422. package/dist/web-remote-access.js +368 -0
  423. package/dist/web-remote-access.js.map +1 -0
  424. package/dist/web-session.d.ts +7 -0
  425. package/dist/web-session.js +2 -0
  426. package/dist/web-session.js.map +1 -1
  427. package/dist/web-shell-routes.d.ts +4 -1
  428. package/dist/web-shell-routes.js +7 -2
  429. package/dist/web-shell-routes.js.map +1 -1
  430. package/dist/windows-agents.d.ts +124 -0
  431. package/dist/windows-agents.js +487 -0
  432. package/dist/windows-agents.js.map +1 -0
  433. package/dist/windows-cli-api.d.ts +23 -0
  434. package/dist/windows-cli-api.js +158 -0
  435. package/dist/windows-cli-api.js.map +1 -0
  436. package/dist/windows-cli-providers.d.ts +115 -0
  437. package/dist/windows-cli-providers.js +429 -0
  438. package/dist/windows-cli-providers.js.map +1 -0
  439. package/dist/windows-cli-worker.d.ts +58 -0
  440. package/dist/windows-cli-worker.js +479 -0
  441. package/dist/windows-cli-worker.js.map +1 -0
  442. package/dist/windows-cli.d.ts +115 -0
  443. package/dist/windows-cli.js +402 -0
  444. package/dist/windows-cli.js.map +1 -0
  445. package/dist/windows-native-mcp.d.ts +19 -0
  446. package/dist/windows-native-mcp.js +143 -0
  447. package/dist/windows-native-mcp.js.map +1 -0
  448. package/dist/windows-pane-mcp.d.ts +26 -0
  449. package/dist/windows-pane-mcp.js +187 -0
  450. package/dist/windows-pane-mcp.js.map +1 -0
  451. package/package.json +9 -3
  452. package/templates/runtime-assets/conpty-LICENSE +21 -0
  453. package/templates/runtime-assets/conpty-NOTICE.md +503 -0
  454. package/templates/runtime-assets/local-pane-stage.ps1 +101 -0
  455. package/templates/runtime-assets/runtime-pane-job.ps1 +116 -0
  456. package/templates/runtime-assets/runtime-pane-private.ps1 +14 -0
  457. package/templates/runtime-assets/xterm-LICENSE +21 -0
@@ -11,7 +11,11 @@ import { appStore, useStore } from "/assets/app-store.js";
11
11
  import { useLease } from "/assets/app-ctx.js";
12
12
  import { PanelHeader, setTitle } from "/assets/app-shell.js";
13
13
  import { HeaderTools } from "/assets/header-tools.js";
14
- import { renavigate } from "/assets/app-nav.js";
14
+ import { navigate, renavigate } from "/assets/app-nav.js";
15
+ import { RuntimePicker, AgentDraftAssistant, NativeAgendToolsHint, tr } from "./agent-runtime.js";
16
+ import { CliPicker, cliLabel as productLabel } from "./cli-picker.js";
17
+ import { useWindowsCliCatalog, WindowsCliDiscoveryStatus, detectionText } from "./windows-cli-catalog.js";
18
+ import { useRuntimeCatalog } from "./runtime-catalog.js";
15
19
  import { chatPath, fleetPath, FLEET_TABS, rememberFleetTab } from "/assets/app-route.js";
16
20
  import { Dialog } from "/assets/ui-dialog.js";
17
21
  import { Empty, ErrorState, Skeleton } from "/assets/ui-states.js";
@@ -266,7 +270,7 @@ function Cache({ lease }) {
266
270
  * that finishes after that still reports its toast (it may have created something), but never closes or refreshes
267
271
  * whatever is on screen now (#1425 review). `ready` false keeps Create off until the form has what it needs.
268
272
  */
269
- export function FormDialog({ title, onClose, submit, children, ready = true }) {
273
+ export function FormDialog({ title, onClose, submit, children, ready = true, renderActions, onCreated, onSubmit, wide = false }) {
270
274
  const lease = useLease("form-dialog");
271
275
  const [busy, setBusy] = useState(false);
272
276
  async function go() {
@@ -287,13 +291,15 @@ export function FormDialog({ title, onClose, submit, children, ready = true }) {
287
291
  toast(submit.done);
288
292
  if (handedOver || !lease.current()) return;
289
293
  setBusy(false);
294
+ if (onCreated) { onCreated(r); return; }
290
295
  onClose();
291
296
  if (submit.after) submit.after();
297
+ if (submit.afterResult) submit.afterResult(r);
292
298
  }
293
- return html`<${Dialog} title=${title} onClose=${onClose} busy=${busy}
294
- actions=${html`<button type="button" class="btn" onClick=${onClose} disabled=${busy}>${t("fleet.cancel")}</button>
299
+ return html`<${Dialog} title=${title} onClose=${onClose} busy=${busy} wide=${wide}
300
+ actions=${renderActions ? renderActions({ busy, go }) : html`<button type="button" class="btn" onClick=${onClose} disabled=${busy}>${t("fleet.cancel")}</button>
295
301
  <button type="button" class="btn btn-primary" onClick=${go} disabled=${busy || !ready}>${busy ? t("fleet.creating") : submit.label || t("fleet.create")}</button>`}>
296
- <form class="form" onSubmit=${(e) => { e.preventDefault(); go(); }}><fieldset class="form" disabled=${busy}>${children}</fieldset></form></${Dialog}>`;
302
+ <form class="form" onSubmit=${(e) => { e.preventDefault(); if (onSubmit) onSubmit({ busy, go }); else go(); }}><fieldset class="form" disabled=${busy}>${children}</fieldset></form></${Dialog}>`;
297
303
  }
298
304
  const field = (label, input) => html`<label class="field"><span>${label}</span>${input}</label>`;
299
305
 
@@ -418,9 +424,26 @@ function CreateTeam({ onClose, onDone, team = null }) {
418
424
  export function CreateInstanceDialog({ onClose }) {
419
425
  const lease = useLease("create-instance");
420
426
  const [backends, setBackends] = useState(null);
427
+ const { windowsCli } = useStore(appStore);
428
+ const [runtime,setRuntime] = useState("");
429
+ const [machineId,setMachineId] = useState("");
430
+ const [nativeAdapter,setNativeAdapter]=useState("exec");
431
+ const machineCatalog = useRuntimeCatalog();
432
+ const machines = machineCatalog.data?.machines || [];
433
+ const machine = machines.find(item => item.id === machineId);
434
+ const [step,setStep] = useState(1), [created,setCreated] = useState(null);
435
+ const drafts = useRef({}), draftGoals = useRef({}), heading = useRef(null);
436
+ const discovery = useWindowsCliCatalog(windowsCli === true);
437
+ const native = machineId ? machine?.inventory : discovery.data;
438
+ const [assistBusy,setAssistBusy] = useState(false);
439
+ const windows = runtime === "windows";
421
440
  // The backend "fleet default" means (#2098 review P3-3): its models are the ones the model list offers then.
422
441
  const [defaultBackend, setDefaultBackend] = useState("claude-code");
423
442
  const [f, setF] = useState({ dir: "", topic: "", desc: "", backend: "", model: "", branch: "", tags: "", prompt: "" });
443
+ useEffect(() => {
444
+ heading.current?.focus({ preventScroll:true });
445
+ heading.current?.closest(".dlg-body")?.scrollTo?.({ top:0 });
446
+ },[step]);
424
447
  useEffect(() => {
425
448
  (async () => {
426
449
  try {
@@ -430,15 +453,43 @@ export function CreateInstanceDialog({ onClose }) {
430
453
  const first = list.find(b => b.installed && !b.deprecated) || list.find(b => b.installed);
431
454
  if (typeof bd.defaultBackend === "string" && bd.defaultBackend) setDefaultBackend(bd.defaultBackend);
432
455
  setBackends(list);
433
- setF(x => ({ ...x, backend: first ? first.name : "" }));
456
+ setF(x => ({ ...x, backend: x.backend || (first ? first.name : "") }));
434
457
  } catch {
435
458
  // The list could not be read: offer the known backends, and keep the explicit choice "fleet default" selected.
436
- if (lease.current()) { setBackends(BACKENDS.map(name => ({ name, installed: true }))); setF(x => ({ ...x, backend: "" })); }
459
+ if (lease.current()) { setBackends(BACKENDS.map(name => ({ name, installed: true, fallback: true }))); setF(x => ({ ...x, backend: "" })); }
437
460
  }
438
461
  })();
439
462
  }, [lease]);
440
463
  const set = (k) => (e) => setF({ ...f, [k]: e.target.value });
441
- const submit = { path: "/ui/instances", done: t("fleet.instanceCreated"), collect: () => {
464
+ const targetKey = `${runtime}:${machineId || "local"}`;
465
+ const chooseRuntime = (value, nextMachineId = "") => {
466
+ if (value === runtime && nextMachineId === machineId) return;
467
+ if (runtime) drafts.current[targetKey] = { form:{...f}, sandbox,nativeAdapter };
468
+ const saved = drafts.current[`${value}:${nextMachineId || "local"}`];
469
+ const nextInventory = nextMachineId ? machines.find(item => item.id === nextMachineId)?.inventory : discovery.data;
470
+ const { sandbox: savedFileAccess } = saved || {};
471
+ setRuntime(value);
472
+ setMachineId(nextMachineId);
473
+ setF(saved?.form || {dir:"",topic:"",desc:"",prompt:"",tags:"",branch:"",model:"",backend:value === "windows" ? nextInventory?.clis?.find(b => b.path && b.runnable)?.id || "codex" : backends?.find(b => b.installed && !b.deprecated && !b.fallback)?.name || ""});
474
+ setSandbox(savedFileAccess || "read-only");setNativeAdapter(saved?.nativeAdapter||"exec");
475
+ };
476
+ const [sandbox,setSandbox] = useState("read-only");
477
+ const nativeCli = native?.clis?.find(cli => cli.id === f.backend);
478
+ const nativeChoices = (native?.clis || []).filter(cli => cli.path && cli.supports?.execution !== false && cli.supports?.resume !== false).map(cli => ({value:cli.id,label:productLabel(cli.id),disabled:!cli.runnable,description:cli.authenticated === false ? t("fleet.notSignedIn") : cli.version || "Windows"}));
479
+ useEffect(() => {
480
+ if(nativeAdapter==="pane"&&!['codex','claude-code'].includes(f.backend))setNativeAdapter("exec");
481
+ if (windows && native && !nativeChoices.some(choice => choice.value === f.backend)) {
482
+ const first = nativeChoices.find(choice => !choice.disabled) || nativeChoices[0];
483
+ if (first) setF(current => ({...current,backend:first.value,model:""}));
484
+ }
485
+ },[native,runtime,machineId,f.backend,nativeAdapter]);
486
+ const submit = { path: "/ui/instances", done: windows ? tr("created") : t("fleet.instanceCreated"),
487
+ collect: () => {
488
+ if (windows) {
489
+ const name = f.topic.trim() || f.dir.trim().replace(/[\\/]+$/, "").split(/[\\/]/).pop();
490
+ if (!name) { toast(tr("required"),false); return null; }
491
+ return {runtime:"windows",...(nativeAdapter==="pane"?{native_adapter:"pane"}:{}),...(machineId ? {machineId} : {}),topic_name:name,backend:f.backend,...(f.model.trim() ? {model:f.model.trim()} : {}),...(f.dir.trim() ? {directory:f.dir.trim()} : {}),description:f.desc.trim(),systemPrompt:f.prompt.trim(),sandbox};
492
+ }
442
493
  if (!f.dir.trim() && !f.topic.trim()) { toast(t("fleet.topicRequired"), false); return null; }
443
494
  const body = {};
444
495
  if (f.dir.trim()) body.directory = f.dir.trim();
@@ -451,18 +502,48 @@ export function CreateInstanceDialog({ onClose }) {
451
502
  if (f.prompt.trim()) body.systemPrompt = f.prompt.trim();
452
503
  return body;
453
504
  } };
454
- // Create waits for the backend list: a submission before it would go without a backend, and the list arriving
455
- // afterwards would change the shown choice under a request already sent (#1425 review).
456
- return html`<${FormDialog} title=${t("fleet.newInstance")} onClose=${onClose} submit=${submit} ready=${backends !== null}>
457
- ${field(t("fleet.directory"), html`<input value=${f.dir} onInput=${set("dir")} placeholder=${t("fleet.directoryHint")} />`)}
458
- ${field(`${t("fleet.topic")}${f.dir.trim() ? "" : " *"}`, html`<input value=${f.topic} onInput=${set("topic")} placeholder=${t("fleet.topicHint")} />`)}
505
+ const canNext = !!runtime && (!machineId || machine?.status === "online") && (windows ? nativeCli?.runnable === true : backends !== null);
506
+ const permissionReady = !windows || sandbox !== "read-only" || nativeCli?.readOnlySupport !== false;
507
+ const canCreate = step === 2 && canNext && permissionReady && !assistBusy && (!windows || !!(f.topic.trim() || f.dir.trim()));
508
+ const advance = () => { if (canNext && !assistBusy) setStep(2); };
509
+ const destination = created?.name ? chatPath(created.name) : created?.agent?.id ? `/ui/windows-agents/${created.agent.id}` : null;
510
+ const createdName = created?.agent?.name || created?.name || f.topic || f.dir.replace(/[\\/]+$/, "").split(/[\\/]/).pop();
511
+ const runtimeLabel = machineId ? `${machine?.name || machineId} · ${machine?.platform || tr(runtime)}` : runtime ? tr(runtime) : "";
512
+ const cliLabel = productLabel(f.backend) || `${t("fleet.fleetDefault")} (${productLabel(defaultBackend)})`;
513
+ const backendField = windows ? html`<div class="field"><div class="cli-discovery-heading"><span>${tr("backend")}</span>${native && !machineId ? html`<button type="button" class="btn btn-ghost btn-sm" disabled=${discovery.loading} onClick=${discovery.refresh}><${Icon} name="restart" size=${14} />${detectionText("refresh")}</button>` : null}</div>
514
+ <div aria-busy=${!machineId && discovery.loading ? "true" : "false"}>${native ? html`<${CliPicker} label=${tr("backend")} value=${f.backend} choices=${nativeChoices} onChange=${value => setF(x => ({...x,backend:value,model:""}))} disabled=${!nativeChoices.length || !!machineId && machine?.status !== "online"} />` : null}</div>
515
+ ${machineId ? html`<p class="note">${tr(!nativeChoices.length ? "noRemoteCli" : "remotePolicy")}</p>${machine?.inventoryUpdatedAt ? html`<p class="note">${t("runtime.inventoryAt",new Date(machine.inventoryUpdatedAt).toLocaleString())}</p>` : null}` : html`<${WindowsCliDiscoveryStatus} state=${discovery} />`}
516
+ ${!machineId && native && !discovery.loading && !discovery.error ? html`<p class="note">${!nativeChoices.length ? tr("noCli") : tr("nativeHint")}</p>` : null}</div>`
517
+ : field(tr("backend"),backends ? html`<${CliPicker} label=${tr("backend")} value=${f.backend} choices=${[{value:"",label:t("fleet.fleetDefault")},...backends.filter(b => backendState(b) !== "not_installed" && !b.deprecated).map(b => ({value:b.name,label:productLabel(b.name),disabled:backendBlocked(b),description:backendNote(b)}))]} onChange=${value => setF(x => ({...x,backend:value,model:""}))} />` : html`<div role="status" aria-busy="true"><${Skeleton} lines=${1} /><span class="note">${tr("loadingClis")}</span></div>`);
518
+ const actions = ({busy,go}) => step === 3 ? html`<button type="button" class="btn" onClick=${onClose}>${tr("finish")}</button><button type="button" class="btn btn-primary" onClick=${() => { onClose(); navigate(destination || "/settings/agents"); }}>${tr(destination ? "openChat" : "viewAgents")}<${Icon} name="forward" size=${16} /></button>`
519
+ : html`<button type="button" class="btn" disabled=${busy || assistBusy} onClick=${step === 1 ? onClose : () => setStep(1)}>${step === 1 ? t("fleet.cancel") : tr("back")}</button>
520
+ <button type="button" class="btn btn-primary" disabled=${busy || (step === 1 ? !canNext : !canCreate)} onClick=${step === 1 ? advance : go}>${step === 1 ? tr("next") : busy ? t("fleet.creating") : t("fleet.create")}${step === 1 ? html`<${Icon} name="forward" size=${16} />` : null}</button>`;
521
+ return html`<${FormDialog} title=${tr("title")} onClose=${onClose} submit=${submit} ready=${canCreate} wide=${true} renderActions=${actions}
522
+ onSubmit=${({busy,go}) => { if (!busy) { if (step === 1) advance(); else if (step === 2) go(); } }}
523
+ onCreated=${result => { setCreated(result); setStep(3); }}>
524
+ <div class="agent-create-wizard" data-step=${step}>
525
+ <ol class="agent-create-steps" aria-label=${tr("progress")}>${["runtimeStep","configureStep","doneStep"].map((label,index) => html`<li key=${label} class=${index+1 === step ? "current" : index+1 < step ? "complete" : ""} aria-current=${index+1 === step ? "step" : undefined}><span class="agent-create-step-number">${index+1 < step ? html`<${Icon} name="check" size=${13} />` : index+1}</span><span>${tr(label)}</span></li>`)}</ol>
526
+ ${step === 1 ? html`<section class="agent-create-stage"><h3 ref=${heading} tabindex="-1">${tr("where")}</h3><p class="note">${tr("runtimeLead")}</p>
527
+ <${RuntimePicker} value=${runtime} onChange=${chooseRuntime} windowsEnabled=${windowsCli} legend=${tr("environment")} machineId=${machineId} machines=${machines} onMachineChange=${id => chooseRuntime("windows",id)} />
528
+ ${machineCatalog.loading && !machineCatalog.data ? html`<p class="note" role="status">${tr("machineLoading")}</p>` : null}
529
+ ${machineCatalog.error ? html`<p class="note" role="alert">${tr("machineFailed")} <button type="button" class="btn btn-ghost btn-sm" onClick=${machineCatalog.refresh}>${tr("machineRetry")}</button></p>` : null}
530
+ <a class="note runtime-manage-link" href="/settings/runtimes">${tr("manage")}</a>
531
+ ${runtime ? html`<div class="agent-create-cli">${backendField}</div>` : null}
532
+ </section>` : step === 2 ? html`<section class="agent-create-stage"><h3 ref=${heading} tabindex="-1">${tr("configureStep")}</h3><p class="note">${tr("configureLead")}</p>
533
+ <div class="agent-create-selection"><${Icon} name=${windows ? "view" : "code"} size=${19} /><div><strong>${runtimeLabel}</strong><span>${cliLabel}</span></div><button type="button" class="btn btn-ghost btn-sm" disabled=${assistBusy} onClick=${() => setStep(1)}>${tr("changeRuntime")}</button></div>
534
+ ${machineId ? html`<p class="note">${tr("remoteDraft")}</p>` : windowsCli ? html`<${AgentDraftAssistant} key=${targetKey} runtime=${runtime} probe=${native} initialGoal=${draftGoals.current[targetKey] || ""} onGoalChange=${value => { draftGoals.current[targetKey] = value; }} onBusy=${setAssistBusy} onDraft=${draft => setF(x => ({...x,topic:draft.name,dir:draft.cwd,desc:draft.description,prompt:draft.instructions}))} />` : null}
535
+ <fieldset class="form agent-runtime-fields" disabled=${assistBusy}>
536
+ ${field(machineId ? t("runtime.remoteDirectory",machine?.name || machineId) : windows ? tr("directory") : t("fleet.directory"), html`<input value=${f.dir} onInput=${set("dir")} placeholder=${windows ? tr("directoryHint") : t("fleet.directoryHint")} />`)}
537
+ ${field(`${t("fleet.topic")}${f.dir.trim() ? "" : " *"}`, html`<input value=${f.topic} onInput=${set("topic")} placeholder=${windows ? tr("nameHint") : t("fleet.topicHint")} />`)}
459
538
  ${field(t("fleet.description"), html`<input value=${f.desc} onInput=${set("desc")} placeholder=${t("fleet.descriptionHint")} />`)}
460
- ${field(t("fleet.backend"), backends ? html`<select value=${f.backend} onChange=${set("backend")}><option value="">${t("fleet.fleetDefault")}</option>
461
- ${backends.map(b => html`<option key=${b.name} value=${b.name} disabled=${backendBlocked(b)}>${b.name}${b.deprecated ? ` ${t("fleet.deprecated")}` : ""}${backendNote(b)}</option>`)}</select>` : html`<${Skeleton} lines=${1} />`)}
462
- ${field(t("fleet.model"), html`<${ModelSelect} value=${f.model} onChange=${(v) => setF(x => ({ ...x, model: v }))} backend=${f.backend || defaultBackend} inherit=${t("fleet.fleetDefault")} />`)}
463
- ${field(t("fleet.branch"), html`<input value=${f.branch} onInput=${set("branch")} placeholder=${t("fleet.branchHint")} />`)}
464
- ${field(t("fleet.tags"), html`<input value=${f.tags} onInput=${set("tags")} placeholder=${t("fleet.tagsHint")} />`)}
539
+ ${windows ? html`${field(tr("adapter"),html`<select id="native-create-adapter" value=${nativeAdapter} onChange=${e=>setNativeAdapter(e.target.value)}><option value="exec">${tr("adapterExec")}</option><option value="pane" disabled=${!["codex","claude-code"].includes(f.backend)}>${tr("adapterPane")}</option></select>`)}<p class="note">${tr(nativeAdapter==="pane"?"paneTopic":"execTopic")}</p>${field(t("fleet.model"),html`<${ModelSelect} key=${`${targetKey}:${f.backend}`} value=${f.model} onChange=${value => setF(x => ({...x,model:value}))} backend=${f.backend} runtime="windows" machineId=${machineId} inherit=${tr("model")} />`)}${field(tr("access"),html`<select id="native-create-sandbox" value=${sandbox} onChange=${e => setSandbox(e.target.value)}><option value="read-only" disabled=${nativeCli?.readOnlySupport === false}>${tr("read")}</option><option value="workspace-write">${tr("write")}</option></select>`)}<p class="note">${!permissionReady ? tr("noReadOnly") : sandbox === "workspace-write" ? tr(nativeAdapter==="pane"?"panePolicy":nativeCli?.id === "claude-code" ? "nativePolicyClaude" : "nativePolicy") : ""}</p><${NativeAgendToolsHint} cli=${nativeCli} sandbox=${sandbox} />` : html`
540
+ ${field(t("fleet.model"), html`<${ModelSelect} value=${f.model} onChange=${(v) => setF(x => ({ ...x, model: v }))} backend=${f.backend || defaultBackend} inherit=${t("fleet.fleetDefault")} />`)}
541
+ ${field(t("fleet.branch"), html`<input value=${f.branch} onInput=${set("branch")} placeholder=${t("fleet.branchHint")} />`)}
542
+ ${field(t("fleet.tags"), html`<input value=${f.tags} onInput=${set("tags")} placeholder=${t("fleet.tagsHint")} />`)}
543
+ `}
465
544
  ${field(t("fleet.systemPrompt"), html`<textarea rows="3" value=${f.prompt} onInput=${set("prompt")} placeholder=${t("fleet.systemPromptHint")}></textarea>`)}
545
+ </fieldset></section>` : html`<section class="agent-create-stage agent-create-success"><span class="agent-create-success-icon"><${Icon} name="check" size=${28} /></span><h3 ref=${heading} tabindex="-1">${tr("success")}</h3><p class="note">${tr("successLead")}</p><dl><dt>${t("fleet.topic")}</dt><dd>${createdName}</dd><dt>Runtime</dt><dd>${runtimeLabel} · ${cliLabel}</dd><dt>${t("fleet.directory")}</dt><dd><code>${created?.agent?.cwd || created?.worktree_path || f.dir || tr("autoWorkspace")}</code></dd></dl></section>`}
546
+ </div>
466
547
  </${FormDialog}>`;
467
548
  }
468
549
 
@@ -9,6 +9,9 @@
9
9
  // - Acknowledge on a delivery (POST /ui/needs/ack), which clears it everywhere;
10
10
  // - Open: that instance's chat.
11
11
  // Something resolved anywhere (Discord, Telegram, the web) leaves the list by itself.
12
+ // alpha.2 (M-2300): an agent's Windows request waiting for a web-only fleet's owner is the app store's `proposals`, read
13
+ // by agent-proposals.js (owner only, on the stream's `agent_proposals` ping) — Approve / Reject POST its decision. Only
14
+ // on a tab opened before an upgrade (app.js never installed it) does this panel install it, once.
12
15
  import { html, useEffect, useState } from "/assets/app-html.js";
13
16
  import { t, register } from "/assets/app-i18n.js";
14
17
  import { appStore, createStore, useStore } from "/assets/app-store.js";
@@ -21,6 +24,8 @@ import { Icon } from "/assets/ui-icons.js";
21
24
  import { toast } from "/assets/ui-toast.js";
22
25
  import { notifyStore, notifySupport, configDetail, reasonText, refreshNotify, setNotify } from "/assets/app-needs.js";
23
26
  import { openSignIn, signInOffered } from "./backend-signin.js";
27
+ import { decideProposal, installProposals } from "./agent-proposals.js";
28
+ import { GeneralLocation } from "./general-location.js";
24
29
 
25
30
  register("needs", {
26
31
  en: {
@@ -35,6 +40,18 @@ register("needs", {
35
40
  notifyInsecure: "Notifications need a secure address (localhost or the HTTPS public link), not a plain-HTTP LAN address.",
36
41
  notifyUnsupported: "This browser cannot show notifications.", turnOn: "Turn on", turnOff: "Turn off",
37
42
  typePrompt: "Fleet prompt", typeAwaiting: "At its terminal", typeInstance: "Instance", typeDelivery: "Delivery",
43
+ proposals: "Agent requests", proposalFrom: "Request from {0}", proposalHint: "Nothing is created or changed until you approve. When you do, AgEnD checks the request, the target machine and your sign-in again, then runs it once.",
44
+ approve: "Approve", reject: "Reject", deciding: "Working…", expiresIn: "expires in {0} min", expiresSoon: "expires in under a minute",
45
+ applying: "Being applied…", openAgent: "Open the new agent's chat", decided: "Decided here", failedReason: "Reason: {0}",
46
+ f_runtime: "Runs on", f_machine: "Machine", f_thisPc: "This PC (Windows)", f_topic_name: "Name", f_backend: "CLI", f_model: "Model", f_directory: "Folder",
47
+ f_sandbox: "Access", f_description: "Description", f_display_name: "Display name", f_tags: "Tags", sb_read_only: "read-only", sb_workspace_write: "can write in its folder",
48
+ createWindows: "Create a Windows agent", changeAgent: "Change {0}",
49
+ r_applied: "Approved: the change is applied.", r_rejected: "Rejected: nothing was changed.", r_withdrawn: "Withdrawn by the agent: nothing was changed.",
50
+ r_expired: "This request ran out before it was decided: nothing was changed.", r_fleet_stopped: "The fleet stopped before it was applied: nothing was changed.",
51
+ r_request_no_longer_current: "The request is no longer current (the fleet or the Windows switch changed): nothing was changed.",
52
+ r_settings_changed: "The settings changed since the request: nothing was changed.", r_apply_failed: "It could not be applied.",
53
+ e_owner_required: "Only this fleet's owner, signed in on the AgEnD computer itself, can decide an agent's request.",
54
+ e_confirmation_not_pending: "This request was already decided or ran out.", e_not_found: "This request is no longer here.",
38
55
  },
39
56
  "zh-TW": {
40
57
  title: "等你處理", empty: "目前沒有需要你處理的事", emptyHint: "agent 在等你時,會出現在這裡——也會出現在聊天 app 的 General。", emptyHintWeb: "agent 在等你時,會出現在這裡。",
@@ -48,6 +65,18 @@ register("needs", {
48
65
  notifyInsecure: "通知需要安全的網址(localhost 或 HTTPS 公開連結),區網的一般 HTTP 網址不行。",
49
66
  notifyUnsupported: "這個瀏覽器無法顯示通知。", turnOn: "開啟", turnOff: "關閉",
50
67
  typePrompt: "Fleet 提示", typeAwaiting: "在終端機上", typeInstance: "Instance", typeDelivery: "傳送",
68
+ proposals: "代理人的請求", proposalFrom: "{0} 的請求", proposalHint: "在你核准之前,不會建立或修改任何東西。核准時,AgEnD 會再次檢查這個請求、目標電腦和你的登入,然後只執行一次。",
69
+ approve: "核准", reject: "拒絕", deciding: "處理中…", expiresIn: "{0} 分鐘後過期", expiresSoon: "不到一分鐘後過期",
70
+ applying: "正在套用…", openAgent: "開啟新 agent 的聊天", decided: "已在這裡決定", failedReason: "原因:{0}",
71
+ f_runtime: "執行於", f_machine: "電腦", f_thisPc: "這台電腦(Windows)", f_topic_name: "名稱", f_backend: "CLI", f_model: "模型", f_directory: "資料夾",
72
+ f_sandbox: "存取權限", f_description: "說明", f_display_name: "顯示名稱", f_tags: "標籤", sb_read_only: "唯讀", sb_workspace_write: "可寫入它的資料夾",
73
+ createWindows: "建立 Windows agent", changeAgent: "修改 {0}",
74
+ r_applied: "已核准:變更已套用。", r_rejected: "已拒絕:沒有任何變更。", r_withdrawn: "agent 已撤回:沒有任何變更。",
75
+ r_expired: "這個請求在決定前就過期了:沒有任何變更。", r_fleet_stopped: "套用前 fleet 已停止:沒有任何變更。",
76
+ r_request_no_longer_current: "這個請求已不再有效(fleet 或 Windows 開關已改變):沒有任何變更。",
77
+ r_settings_changed: "提出請求後設定已變更:沒有任何變更。", r_apply_failed: "無法套用。",
78
+ e_owner_required: "只有在 AgEnD 這台電腦上登入的 fleet 擁有者,才能決定 agent 的請求。",
79
+ e_confirmation_not_pending: "這個請求已經被決定或已過期。", e_not_found: "這個請求已不在這裡。",
51
80
  },
52
81
  });
53
82
  const tn = (k, ...v) => t(`needs.${k}`, ...v);
@@ -123,9 +152,21 @@ export function groupNeeds(items) {
123
152
  return [...groups.values()];
124
153
  }
125
154
 
155
+ /**
156
+ * alpha.2 (M-2300): what this page decided, kept for the life of the page — the request's id → "busy" while its POST is
157
+ * out, then the server's answer ({ view, agent, message }): it stays shown after the list drops the request.
158
+ */
159
+ export const decisions = createStore({});
160
+
126
161
  export function NeedsPanel({ navKey }) {
127
162
  const lease = useLease(navKey);
128
- const { needs, chatOwner: owner, instances, connections } = useStore(appStore);
163
+ const { needs, chatOwner: owner, instances, connections, proposals } = useStore(appStore);
164
+ // A tab opened before an upgrade has this panel but not the app.js that installs the list (it never set `proposals`):
165
+ // install it here then. On a current page app.js already did, and this panel reads nothing itself (#1374).
166
+ useEffect(() => { if (appStore.get().proposals === undefined) installProposals(); }, []);
167
+ const asks = Array.isArray(proposals) ? proposals : [];
168
+ const done = useStore(decisions);
169
+ const decidedHere = Object.entries(done).filter(([id, d]) => d && d !== "busy" && !asks.some((p) => p.id === id));
129
170
  // #1854: a fleet with no chat connection (web only, or not known yet) has no General to point at.
130
171
  const chatApp = connections > 0;
131
172
  const names = useStore(namesStore);
@@ -141,9 +182,14 @@ export function NeedsPanel({ navKey }) {
141
182
  const groups = groupNeeds(items);
142
183
  const nowMs = Date.now();
143
184
  return html`<div data-effect-panel="needs" class="panel p-needs">
144
- <${PanelHeader} title=${tn("title")} sub=${items.length ? t("app.needsCount", items.length) : null} />
185
+ <${PanelHeader} title=${tn("title")} sub=${items.length + asks.length ? t("app.needsCount", items.length + asks.length) : null} />
145
186
  <div data-trust="panel-content" class="panel-body"><div class="col">
146
- ${!items.length ? html`<${Empty} icon="check" title=${tn("empty")} hint=${tn(chatApp ? "emptyHint" : "emptyHintWeb")} />`
187
+ ${asks.length || decidedHere.length ? html`<section class="n-group n-proposals" aria-label=${tn("proposals")}>
188
+ <h2 class="n-group-head">${tn("proposals")}</h2>
189
+ ${asks.map((p) => html`<${ProposalItem} key=${p.id} proposal=${p} nowMs=${nowMs} />`)}
190
+ ${decidedHere.map(([id, d]) => html`<${ProposalResult} key=${id} result=${d} />`)}
191
+ </section>` : null}
192
+ ${!items.length && !asks.length && !decidedHere.length ? html`<${Empty} icon="check" title=${tn("empty")} hint=${tn(chatApp ? "emptyHint" : "emptyHintWeb")} />`
147
193
  : groups.map((g) => html`<section key=${JSON.stringify([g.instance, g.items[0]?.type === "config"])} class="n-group" aria-label=${g.instance}>
148
194
  <h2 class="n-group-head">${g.instance ? html`<a href=${chatPath(g.instance)} title=${g.instance}>${nameFor(g.instance)}</a>` : g.items[0]?.type === "config" ? t("app.settings") : tn(g.items.some(i => i.type === "backend") ? "fleetSignIns" : "noAssignee")}</h2>
149
195
  ${g.items.map((item) => html`<${NeedsItem} key=${item.id} item=${item} nowMs=${nowMs} owner=${owner} />`)}
@@ -197,6 +243,7 @@ function NeedsItem({ item, nowMs, owner }) {
197
243
  <div class="n-body">
198
244
  <div class="n-title"><strong>${reasonText(item)}</strong><span class="n-age">${age(item.since, nowMs)}</span></div>
199
245
  ${detailOf(item) ? html`<p class="n-detail">${detailOf(item)}</p>` : null}
246
+ ${item.generalLocation ? html`<${GeneralLocation} name=${item.instance} attentionOnly=${true} />` : null}
200
247
  <div class="n-actions">
201
248
  ${item.type === "prompt" && Array.isArray(item.actions) ? item.actions.filter((a) => !a.input).map((a) => html`<button key=${a.id} type="button" class="btn btn-sm"
202
249
  disabled=${promptBusy} onClick=${() => answer(a.id)}>${(p ? p.busy : fallback === "busy") ? tn("answering") : a.label}</button>`) : null}
@@ -210,6 +257,110 @@ function NeedsItem({ item, nowMs, owner }) {
210
257
  </article>`;
211
258
  }
212
259
 
260
+ /**
261
+ * alpha.2 (M-2300): the request's summary as the owner reads it (junsion's §6: the machine, the CLI, the model, the
262
+ * folder, the access). The server's lines are the settings diff, escaped for a chat's markdown ("new\_instance.directory:
263
+ * absent → C:\\work"): here, unescaped and named — a create's fields as "Folder: C:\work", "Machine: This PC" when it
264
+ * names none; a change's as "Model: a → b"; any other line as it is. Text only (rendered as text, never markup).
265
+ */
266
+ export function proposalLines(summary) {
267
+ const unescape = (s) => String(s).replace(/\\([\\`*_~[\]()<>|])/g, "$1").replace(/\[at\]/g, "@");
268
+ const lines = (Array.isArray(summary) ? summary : []).map(unescape);
269
+ const create = lines.some((l) => /^POST \/ui\/instances$/.test(l));
270
+ const out = [], label = (k) => { const key = `f_${k}`, s = tn(key); return s === `needs.${key}` ? k : s; };
271
+ // The access field's values, in words (matched by value: the two the request's schema allows).
272
+ const ACCESS = { "read-only": "sb_read_only", "workspace-write": "sb_workspace_write" };
273
+ const value = (_k, v) => (Object.hasOwn(ACCESS, v) ? tn(ACCESS[v]) : v);
274
+ let machine = false;
275
+ for (const l of lines) {
276
+ if (/^POST \/ui\/instances$/.test(l)) continue;
277
+ const m = /^new_instance\.([A-Za-z_]+): absent → (.*)$/.exec(l);
278
+ if (m) { if (m[1] === "machineId") machine = true; out.push(`${label(m[1] === "machineId" ? "machine" : m[1])}: ${value(m[1], m[2])}`); continue; }
279
+ const ch = /^(\S+) ([A-Za-z_]+): (.*) → (.*)$/.exec(l);
280
+ if (ch) { out.push(`${tn("changeAgent", ch[1])} · ${label(ch[2])}: ${ch[3]} → ${ch[4]}`); continue; }
281
+ out.push(l);
282
+ }
283
+ if (create && !machine) out.splice(1, 0, `${label("machine")}: ${tn("f_thisPc")}`);
284
+ return create ? [tn("createWindows"), ...out] : out;
285
+ }
286
+
287
+ /**
288
+ * alpha.2 polish: a decided request's outcome in the PAGE's language (the server says it in the fleet's — an English page
289
+ * read 「變更已套用。」): by its reason code, else its state; the server's words only for a code this page does not know.
290
+ */
291
+ export function outcomeText(outcome) {
292
+ if (!outcome) return t("app.failed");
293
+ for (const code of [outcome.reason_code, outcome.state]) {
294
+ if (typeof code !== "string") continue;
295
+ const key = `r_${code}`, s = tn(key);
296
+ if (s !== `needs.${key}`) return s;
297
+ }
298
+ return outcome.message || t("app.failed");
299
+ }
300
+ /** Why a click decided nothing, in the page's language (by the server's error code; its words only as a fallback). */
301
+ export function decideErrorText(r) {
302
+ const key = r && r.error ? `e_${r.error}` : "";
303
+ const s = key ? tn(key) : "";
304
+ return key && s !== `needs.${key}` ? s : (r && r.message) || t("app.failed");
305
+ }
306
+
307
+ /**
308
+ * alpha.2 (M-2300): one agent's request waiting for this web-only fleet's owner — what it would do (the server's own
309
+ * summary: the machine, the CLI, the model, the folder, the access), when it runs out, and Approve / Reject. One click
310
+ * per request on this page (claimed before the POST); the answer is the server's: applied, rejected, run out, already
311
+ * decided elsewhere, or failed with its reason.
312
+ */
313
+ function ProposalItem({ proposal: p, nowMs }) {
314
+ const d = useStore(decisions)[p.id];
315
+ const busy = d === "busy" || p.state === "applying";
316
+ const [failed, setFailed] = useState(null);
317
+ const decide = async (decision) => {
318
+ if (decisions.get()[p.id]) return; // one POST in flight per request on this page
319
+ setFailed(null);
320
+ decisions.set((s) => ({ ...s, [p.id]: "busy" }));
321
+ const r = await decideProposal(p.id, decision);
322
+ // #2997 review (Prism P2): nothing decided (the network failed, the owner was refused, a bad answer) and the request
323
+ // still waits — the claim is released and why is said here, so the next click is taken; a decided one is kept.
324
+ const decided = r.view && r.view.state !== "pending";
325
+ if (!decided) {
326
+ decisions.set((s) => { const next = { ...s }; delete next[p.id]; return next; });
327
+ setFailed(decideErrorText(r));
328
+ return;
329
+ }
330
+ decisions.set((s) => ({ ...s, [p.id]: { ...r, decision } }));
331
+ toast(r.view.outcome ? outcomeText(r.view.outcome) : decideErrorText(r), r.view.state === "applied");
332
+ };
333
+ const minutes = Math.floor((p.remaining_ms || 0) / 60_000);
334
+ return html`<article data-trust="permission" class="n-item">
335
+ <span class="n-icon"><${Icon} name="alert" size=${18} /></span>
336
+ <div class="n-body">
337
+ <div class="n-title"><strong>${tn("proposalFrom", p.requested_by)}</strong><span class="n-age">${age(p.requested_at, nowMs)} · ${minutes >= 1 ? tn("expiresIn", minutes) : tn("expiresSoon")}</span></div>
338
+ <ul class="n-detail">${proposalLines(p.summary).map((line, i) => html`<li key=${i}>${line}</li>`)}</ul>
339
+ <p class="note">${tn("proposalHint")}</p>
340
+ ${failed ? html`<p class="note n-proposal-error" role="alert">${failed}</p>` : null}
341
+ <div class="n-actions">
342
+ <button type="button" class="btn btn-sm btn-primary" disabled=${busy} onClick=${() => decide("confirm")}>${busy ? (p.state === "applying" ? tn("applying") : tn("deciding")) : tn("approve")}</button>
343
+ <button type="button" class="btn btn-sm" disabled=${busy} onClick=${() => decide("reject")}>${tn("reject")}</button>
344
+ </div>
345
+ </div>
346
+ </article>`;
347
+ }
348
+
349
+ /** A request decided on this page: the server's outcome (and its reason), and the new agent's chat when one was created. */
350
+ function ProposalResult({ result: r }) {
351
+ const v = r.view, outcome = v && v.outcome;
352
+ const ok = !!(v && v.state === "applied");
353
+ return html`<article data-trust="permission" class=${`n-item${ok || (v && v.state === "rejected") ? "" : " bad"}`}>
354
+ <span class="n-icon"><${Icon} name=${ok ? "check" : "alert"} size=${18} /></span>
355
+ <div class="n-body">
356
+ <div class="n-title"><strong>${outcome ? outcomeText(outcome) : decideErrorText(r)}</strong><span class="n-age">${tn("decided")}</span></div>
357
+ ${v ? html`<ul class="n-detail">${proposalLines(v.summary).map((line, i) => html`<li key=${i}>${line}</li>`)}</ul>` : null}
358
+ ${outcome && outcome.detail ? html`<p class="note">${tn("failedReason", outcome.detail)}</p>` : null}
359
+ ${ok && r.agent ? html`<div class="n-actions"><a class="btn btn-sm btn-primary" href=${chatPath(r.agent)} title=${r.agent}>${tn("openAgent")}</a></div>` : null}
360
+ </div>
361
+ </article>`;
362
+ }
363
+
213
364
  /** The device's choice, as the page knows it (app-needs.js notifyStore): every mounted toggle shows the same. */
214
365
  function NotifyToggle() {
215
366
  const support = notifySupport();