@psnext/slingcli 2.4.20260525-4 → 2.4.20260527-2

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 (243) hide show
  1. package/bin/sling.js +4 -1
  2. package/node_modules/@aws-sdk/core/package.json +2 -2
  3. package/node_modules/@aws-sdk/credential-provider-env/package.json +2 -2
  4. package/node_modules/@aws-sdk/credential-provider-http/dist-cjs/fromHttp/fromHttp.js +12 -6
  5. package/node_modules/@aws-sdk/credential-provider-http/dist-es/fromHttp/fromHttp.js +12 -6
  6. package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -2
  7. package/node_modules/@aws-sdk/credential-provider-ini/package.json +9 -9
  8. package/node_modules/@aws-sdk/credential-provider-login/package.json +3 -3
  9. package/node_modules/@aws-sdk/credential-provider-node/package.json +7 -7
  10. package/node_modules/@aws-sdk/credential-provider-process/package.json +2 -2
  11. package/node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers/package.json +3 -3
  12. package/node_modules/@aws-sdk/credential-provider-sso/package.json +4 -4
  13. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +3 -3
  14. package/node_modules/@aws-sdk/middleware-websocket/package.json +2 -2
  15. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/cognito-identity/index.js +1 -1
  16. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/signin/index.js +1 -1
  17. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso/index.js +1 -1
  18. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sso-oidc/index.js +1 -1
  19. package/node_modules/@aws-sdk/nested-clients/dist-cjs/submodules/sts/index.js +1 -1
  20. package/node_modules/@aws-sdk/nested-clients/package.json +3 -3
  21. package/node_modules/@aws-sdk/signature-v4-multi-region/package.json +1 -2
  22. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  23. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +18 -24
  24. package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
  25. package/node_modules/@earendil-works/pi-ai/dist/cli.js +14 -0
  26. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +78 -63
  27. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +2 -1
  28. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +8 -22
  29. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +1 -1
  30. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +1 -1
  31. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +60 -40
  32. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +1 -1
  33. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +1 -1
  34. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +55 -0
  35. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +45 -69
  36. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -0
  37. package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +5 -2
  38. package/node_modules/@earendil-works/pi-ai/package.json +4 -3
  39. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/file-processor.js +2 -3
  40. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +18 -12
  41. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-runtime.js +2 -1
  42. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +3 -2
  43. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +8 -2
  44. package/node_modules/@earendil-works/pi-coding-agent/dist/core/auth-storage.js +2 -1
  45. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +18 -24
  46. package/node_modules/@earendil-works/pi-coding-agent/dist/core/export-html/index.js +8 -6
  47. package/node_modules/@earendil-works/pi-coding-agent/dist/core/export-html/template.js +6 -3
  48. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/loader.js +12 -29
  49. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +5 -1
  50. package/node_modules/@earendil-works/pi-coding-agent/dist/core/output-guard.js +52 -22
  51. package/node_modules/@earendil-works/pi-coding-agent/dist/core/package-manager.js +63 -36
  52. package/node_modules/@earendil-works/pi-coding-agent/dist/core/prompt-templates.js +6 -20
  53. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resource-loader.js +38 -31
  54. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +9 -4
  55. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +32 -24
  56. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +6 -13
  57. package/node_modules/@earendil-works/pi-coding-agent/dist/core/skills.js +8 -22
  58. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/bash.js +54 -53
  59. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit-diff.js +8 -1
  60. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +44 -81
  61. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/file-mutation-queue.js +27 -12
  62. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js +2 -3
  63. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js +3 -3
  64. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -5
  65. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/output-accumulator.js +9 -3
  66. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/path-utils.js +39 -21
  67. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +9 -8
  68. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/truncate.js +12 -2
  69. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +20 -35
  70. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +5 -6
  71. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/config-selector.js +1 -1
  72. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/footer.js +14 -5
  73. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +29 -4
  74. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
  75. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -4
  76. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +37 -28
  77. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-client.js +64 -7
  78. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +15 -3
  79. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/clipboard-native.js +14 -8
  80. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-core.js +124 -0
  81. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize-worker.js +31 -0
  82. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/image-resize.js +75 -115
  83. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/paths.js +33 -7
  84. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +13 -26
  85. package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
  86. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +40 -55
  87. package/node_modules/@earendil-works/pi-tui/dist/components/input.js +2 -2
  88. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +12 -2
  89. package/node_modules/@earendil-works/pi-tui/dist/native-modifiers.js +53 -0
  90. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +4 -1
  91. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +38 -16
  92. package/node_modules/@earendil-works/pi-tui/dist/utils.js +19 -12
  93. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-modifiers.node +0 -0
  94. package/node_modules/@earendil-works/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-modifiers.node +0 -0
  95. package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-arm64/win32-console-mode.node +0 -0
  96. package/node_modules/@earendil-works/pi-tui/native/win32/prebuilds/win32-x64/win32-console-mode.node +0 -0
  97. package/node_modules/@earendil-works/pi-tui/package.json +3 -5
  98. package/node_modules/@smithy/node-http-handler/package.json +2 -2
  99. package/node_modules/undici/lib/api/api-request.js +1 -1
  100. package/node_modules/undici/lib/cache/sqlite-cache-store.js +3 -3
  101. package/node_modules/undici/lib/core/connect.js +16 -0
  102. package/node_modules/undici/lib/core/request.js +17 -2
  103. package/node_modules/undici/lib/core/socks5-client.js +10 -5
  104. package/node_modules/undici/lib/core/socks5-utils.js +17 -22
  105. package/node_modules/undici/lib/dispatcher/client-h1.js +64 -20
  106. package/node_modules/undici/lib/dispatcher/client.js +6 -2
  107. package/node_modules/undici/lib/dispatcher/h2c-client.js +1 -1
  108. package/node_modules/undici/lib/mock/mock-call-history.js +15 -15
  109. package/node_modules/undici/lib/util/cache.js +8 -7
  110. package/node_modules/undici/lib/web/fetch/formdata-parser.js +17 -6
  111. package/node_modules/undici/lib/web/fetch/index.js +5 -2
  112. package/node_modules/undici/lib/web/webidl/index.js +5 -5
  113. package/node_modules/undici/lib/web/websocket/stream/websocketstream.js +1 -7
  114. package/node_modules/undici/package.json +1 -1
  115. package/package.json +6 -6
  116. package/slingshot/index.js +269 -266
  117. package/node_modules/koffi/CHANGELOG.md +0 -1093
  118. package/node_modules/koffi/LICENSE.txt +0 -22
  119. package/node_modules/koffi/README.md +0 -43
  120. package/node_modules/koffi/build/koffi/darwin_arm64/koffi.node +0 -0
  121. package/node_modules/koffi/build/koffi/darwin_x64/koffi.node +0 -0
  122. package/node_modules/koffi/build/koffi/freebsd_arm64/koffi.node +0 -0
  123. package/node_modules/koffi/build/koffi/freebsd_ia32/koffi.node +0 -0
  124. package/node_modules/koffi/build/koffi/freebsd_x64/koffi.node +0 -0
  125. package/node_modules/koffi/build/koffi/linux_arm64/koffi.node +0 -0
  126. package/node_modules/koffi/build/koffi/linux_armhf/koffi.node +0 -0
  127. package/node_modules/koffi/build/koffi/linux_ia32/koffi.node +0 -0
  128. package/node_modules/koffi/build/koffi/linux_loong64/koffi.node +0 -0
  129. package/node_modules/koffi/build/koffi/linux_riscv64d/koffi.node +0 -0
  130. package/node_modules/koffi/build/koffi/linux_x64/koffi.node +0 -0
  131. package/node_modules/koffi/build/koffi/musl_arm64/koffi.node +0 -0
  132. package/node_modules/koffi/build/koffi/musl_x64/koffi.node +0 -0
  133. package/node_modules/koffi/build/koffi/openbsd_ia32/koffi.node +0 -0
  134. package/node_modules/koffi/build/koffi/openbsd_x64/koffi.node +0 -0
  135. package/node_modules/koffi/build/koffi/win32_arm64/koffi.exp +0 -0
  136. package/node_modules/koffi/build/koffi/win32_arm64/koffi.lib +0 -0
  137. package/node_modules/koffi/build/koffi/win32_arm64/koffi.node +0 -0
  138. package/node_modules/koffi/build/koffi/win32_ia32/koffi.exp +0 -0
  139. package/node_modules/koffi/build/koffi/win32_ia32/koffi.lib +0 -0
  140. package/node_modules/koffi/build/koffi/win32_ia32/koffi.node +0 -0
  141. package/node_modules/koffi/build/koffi/win32_x64/koffi.exp +0 -0
  142. package/node_modules/koffi/build/koffi/win32_x64/koffi.lib +0 -0
  143. package/node_modules/koffi/build/koffi/win32_x64/koffi.node +0 -0
  144. package/node_modules/koffi/doc/benchmarks.md +0 -126
  145. package/node_modules/koffi/doc/callbacks.md +0 -210
  146. package/node_modules/koffi/doc/contribute.md +0 -148
  147. package/node_modules/koffi/doc/functions.md +0 -250
  148. package/node_modules/koffi/doc/index.md +0 -61
  149. package/node_modules/koffi/doc/input.md +0 -471
  150. package/node_modules/koffi/doc/migration.md +0 -159
  151. package/node_modules/koffi/doc/misc.md +0 -180
  152. package/node_modules/koffi/doc/output.md +0 -305
  153. package/node_modules/koffi/doc/packaging.md +0 -88
  154. package/node_modules/koffi/doc/platforms.md +0 -36
  155. package/node_modules/koffi/doc/pointers.md +0 -328
  156. package/node_modules/koffi/doc/start.md +0 -118
  157. package/node_modules/koffi/doc/unions.md +0 -186
  158. package/node_modules/koffi/doc/variables.md +0 -102
  159. package/node_modules/koffi/index.d.ts +0 -288
  160. package/node_modules/koffi/index.js +0 -634
  161. package/node_modules/koffi/indirect.js +0 -533
  162. package/node_modules/koffi/lib/native/base/base.cc +0 -11015
  163. package/node_modules/koffi/lib/native/base/base.hh +0 -6003
  164. package/node_modules/koffi/lib/native/base/crc.inc +0 -2214
  165. package/node_modules/koffi/lib/native/base/crc_gen.py +0 -72
  166. package/node_modules/koffi/lib/native/base/mimetypes.inc +0 -1248
  167. package/node_modules/koffi/lib/native/base/mimetypes_gen.py +0 -58
  168. package/node_modules/koffi/lib/native/base/tower.cc +0 -821
  169. package/node_modules/koffi/lib/native/base/tower.hh +0 -81
  170. package/node_modules/koffi/lib/native/base/unicode.inc +0 -408
  171. package/node_modules/koffi/lib/native/base/unicode_gen.py +0 -152
  172. package/node_modules/koffi/package.json +0 -38
  173. package/node_modules/koffi/src/cnoke/LICENSE.txt +0 -22
  174. package/node_modules/koffi/src/cnoke/README.md +0 -99
  175. package/node_modules/koffi/src/cnoke/assets/FindCNoke.cmake +0 -127
  176. package/node_modules/koffi/src/cnoke/assets/toolchains.json +0 -126
  177. package/node_modules/koffi/src/cnoke/assets/win_delay_hook.c +0 -36
  178. package/node_modules/koffi/src/cnoke/cnoke.js +0 -170
  179. package/node_modules/koffi/src/cnoke/package.json +0 -24
  180. package/node_modules/koffi/src/cnoke/src/builder.js +0 -511
  181. package/node_modules/koffi/src/cnoke/src/index.js +0 -10
  182. package/node_modules/koffi/src/cnoke/src/tools.js +0 -407
  183. package/node_modules/koffi/src/koffi/CMakeLists.txt +0 -182
  184. package/node_modules/koffi/src/koffi/src/abi_arm32.cc +0 -1018
  185. package/node_modules/koffi/src/koffi/src/abi_arm32_asm.S +0 -169
  186. package/node_modules/koffi/src/koffi/src/abi_arm64.cc +0 -1295
  187. package/node_modules/koffi/src/koffi/src/abi_arm64_asm.S +0 -195
  188. package/node_modules/koffi/src/koffi/src/abi_arm64_asm.asm +0 -174
  189. package/node_modules/koffi/src/koffi/src/abi_loong64.cc +0 -5
  190. package/node_modules/koffi/src/koffi/src/abi_loong64_asm.S +0 -204
  191. package/node_modules/koffi/src/koffi/src/abi_riscv64.cc +0 -915
  192. package/node_modules/koffi/src/koffi/src/abi_riscv64_asm.S +0 -203
  193. package/node_modules/koffi/src/koffi/src/abi_x64_sysv.cc +0 -939
  194. package/node_modules/koffi/src/koffi/src/abi_x64_sysv_asm.S +0 -231
  195. package/node_modules/koffi/src/koffi/src/abi_x64_win.cc +0 -715
  196. package/node_modules/koffi/src/koffi/src/abi_x64_win_asm.S +0 -166
  197. package/node_modules/koffi/src/koffi/src/abi_x64_win_asm.asm +0 -192
  198. package/node_modules/koffi/src/koffi/src/abi_x86.cc +0 -860
  199. package/node_modules/koffi/src/koffi/src/abi_x86_asm.S +0 -193
  200. package/node_modules/koffi/src/koffi/src/abi_x86_asm.asm +0 -177
  201. package/node_modules/koffi/src/koffi/src/call.cc +0 -1326
  202. package/node_modules/koffi/src/koffi/src/call.hh +0 -179
  203. package/node_modules/koffi/src/koffi/src/errno.inc +0 -462
  204. package/node_modules/koffi/src/koffi/src/ffi.cc +0 -2702
  205. package/node_modules/koffi/src/koffi/src/ffi.hh +0 -354
  206. package/node_modules/koffi/src/koffi/src/init.js +0 -105
  207. package/node_modules/koffi/src/koffi/src/parser.cc +0 -220
  208. package/node_modules/koffi/src/koffi/src/parser.hh +0 -54
  209. package/node_modules/koffi/src/koffi/src/util.cc +0 -1807
  210. package/node_modules/koffi/src/koffi/src/util.hh +0 -221
  211. package/node_modules/koffi/src/koffi/src/uv.cc +0 -193
  212. package/node_modules/koffi/src/koffi/src/uv.def +0 -10
  213. package/node_modules/koffi/src/koffi/src/uv.hh +0 -40
  214. package/node_modules/koffi/src/koffi/src/win32.cc +0 -198
  215. package/node_modules/koffi/src/koffi/src/win32.hh +0 -119
  216. package/node_modules/koffi/src/koffi/tools/write_trampolines.js +0 -77
  217. package/node_modules/koffi/vendor/node-addon-api/LICENSE.md +0 -9
  218. package/node_modules/koffi/vendor/node-addon-api/README.md +0 -95
  219. package/node_modules/koffi/vendor/node-addon-api/napi-inl.deprecated.h +0 -186
  220. package/node_modules/koffi/vendor/node-addon-api/napi-inl.h +0 -7033
  221. package/node_modules/koffi/vendor/node-addon-api/napi.h +0 -3309
  222. package/node_modules/koffi/vendor/node-api-headers/LICENSE +0 -21
  223. package/node_modules/koffi/vendor/node-api-headers/README.md +0 -95
  224. package/node_modules/koffi/vendor/node-api-headers/def/js_native_api.def +0 -125
  225. package/node_modules/koffi/vendor/node-api-headers/def/node_api.def +0 -157
  226. package/node_modules/koffi/vendor/node-api-headers/include/js_native_api.h +0 -591
  227. package/node_modules/koffi/vendor/node-api-headers/include/js_native_api_types.h +0 -210
  228. package/node_modules/koffi/vendor/node-api-headers/include/node_api.h +0 -265
  229. package/node_modules/koffi/vendor/node-api-headers/include/node_api_types.h +0 -58
  230. package/node_modules/koffi/vendor/node-api-headers/include/uv/aix.h +0 -32
  231. package/node_modules/koffi/vendor/node-api-headers/include/uv/bsd.h +0 -34
  232. package/node_modules/koffi/vendor/node-api-headers/include/uv/darwin.h +0 -61
  233. package/node_modules/koffi/vendor/node-api-headers/include/uv/errno.h +0 -483
  234. package/node_modules/koffi/vendor/node-api-headers/include/uv/linux.h +0 -34
  235. package/node_modules/koffi/vendor/node-api-headers/include/uv/os390.h +0 -33
  236. package/node_modules/koffi/vendor/node-api-headers/include/uv/posix.h +0 -31
  237. package/node_modules/koffi/vendor/node-api-headers/include/uv/sunos.h +0 -44
  238. package/node_modules/koffi/vendor/node-api-headers/include/uv/threadpool.h +0 -37
  239. package/node_modules/koffi/vendor/node-api-headers/include/uv/tree.h +0 -521
  240. package/node_modules/koffi/vendor/node-api-headers/include/uv/unix.h +0 -512
  241. package/node_modules/koffi/vendor/node-api-headers/include/uv/version.h +0 -43
  242. package/node_modules/koffi/vendor/node-api-headers/include/uv/win.h +0 -698
  243. package/node_modules/koffi/vendor/node-api-headers/include/uv.h +0 -1990
@@ -68,7 +68,7 @@ export class LoginDialogComponent extends Container {
68
68
  /**
69
69
  * Called by onAuth callback - show URL and optional instructions
70
70
  */
71
- showAuth(url, instructions) {
71
+ showAuth(url, instructions, options = {}) {
72
72
  this.contentContainer.clear();
73
73
  this.contentContainer.addChild(new Spacer(1));
74
74
  const linkedUrl = `\x1b]8;;${url}\x07${url}\x1b]8;;\x07`;
@@ -80,11 +80,36 @@ export class LoginDialogComponent extends Container {
80
80
  this.contentContainer.addChild(new Spacer(1));
81
81
  this.contentContainer.addChild(new Text(theme.fg("warning", instructions), 1, 0));
82
82
  }
83
- // Try to open browser
84
- const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
85
- exec(`${openCmd} "${url}"`);
83
+ if (options.autoOpenBrowser ?? true) {
84
+ this.openUrl(url);
85
+ }
86
+ this.tui.requestRender();
87
+ }
88
+ /**
89
+ * Called by onDeviceCode callback - show URL and user code.
90
+ */
91
+ showDeviceCode(info) {
92
+ this.contentContainer.clear();
93
+ this.contentContainer.addChild(new Spacer(1));
94
+ const linkedUrl = `\x1b]8;;${info.verificationUri}\x07${info.verificationUri}\x1b]8;;\x07`;
95
+ this.contentContainer.addChild(new Text(theme.fg("accent", linkedUrl), 1, 0));
96
+ const clickHint = process.platform === "darwin" ? "Cmd+click to open" : "Ctrl+click to open";
97
+ const hyperlink = `\x1b]8;;${info.verificationUri}\x07${clickHint}\x1b]8;;\x07`;
98
+ this.contentContainer.addChild(new Text(theme.fg("dim", hyperlink), 1, 0));
99
+ this.contentContainer.addChild(new Spacer(1));
100
+ this.contentContainer.addChild(new Text(theme.fg("warning", `Enter code: ${info.userCode}`), 1, 0));
101
+ this.openUrl(info.verificationUri);
86
102
  this.tui.requestRender();
87
103
  }
104
+ openUrl(url) {
105
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
106
+ try {
107
+ exec(`${openCmd} "${url}"`, () => { });
108
+ }
109
+ catch {
110
+ // Ignore browser launch failures. The URL remains visible for manual opening/copying.
111
+ }
112
+ }
88
113
  /**
89
114
  * Show input for manual code/URL entry (for callback server providers)
90
115
  */
@@ -13,7 +13,7 @@ export class UserMessageComponent extends Container {
13
13
  this.contentBox = new Box(1, 1, (content) => theme.bg("userMessageBg", content));
14
14
  this.contentBox.addChild(new Markdown(text, 0, 0, markdownTheme, {
15
15
  color: (content) => theme.fg("userMessageText", content),
16
- }));
16
+ }, { preserveOrderedListMarkers: true }));
17
17
  this.addChild(this.contentBox);
18
18
  }
19
19
  render(width) {
@@ -3995,12 +3995,12 @@ export class InteractiveMode {
3995
3995
  }
3996
3996
  });
3997
3997
  }
3998
- else if (providerId === "github-copilot") {
3999
- // GitHub Copilot polls after onAuth
4000
- dialog.showWaiting("Waiting for browser authentication...");
4001
- }
4002
3998
  // For Anthropic: onPrompt is called immediately after
4003
3999
  },
4000
+ onDeviceCode: (info) => {
4001
+ dialog.showDeviceCode(info);
4002
+ dialog.showWaiting("Waiting for authentication...");
4003
+ },
4004
4004
  onPrompt: async (prompt) => {
4005
4005
  return dialog.showPrompt(prompt.message, prompt.placeholder);
4006
4006
  },
@@ -328,47 +328,56 @@ function getBuiltinThemes() {
328
328
  return BUILTIN_THEMES;
329
329
  }
330
330
  export function getAvailableThemes() {
331
- const themes = new Set(Object.keys(getBuiltinThemes()));
332
- const customThemesDir = getCustomThemesDir();
333
- if (fs.existsSync(customThemesDir)) {
334
- const files = fs.readdirSync(customThemesDir);
335
- for (const file of files) {
336
- if (file.endsWith(".json")) {
337
- themes.add(file.slice(0, -5));
338
- }
339
- }
340
- }
341
- for (const name of registeredThemes.keys()) {
342
- themes.add(name);
343
- }
344
- return Array.from(themes).sort();
331
+ return getAvailableThemesWithPaths().map(({ name }) => name);
345
332
  }
346
333
  export function getAvailableThemesWithPaths() {
347
334
  const themesDir = getThemesDir();
348
- const customThemesDir = getCustomThemesDir();
349
335
  const result = [];
336
+ const seen = new Set();
337
+ const addTheme = (themeInfo) => {
338
+ if (seen.has(themeInfo.name)) {
339
+ return;
340
+ }
341
+ seen.add(themeInfo.name);
342
+ result.push(themeInfo);
343
+ };
350
344
  // Built-in themes
351
345
  for (const name of Object.keys(getBuiltinThemes())) {
352
- result.push({ name, path: path.join(themesDir, `${name}.json`) });
346
+ addTheme({ name, path: path.join(themesDir, `${name}.json`) });
353
347
  }
354
348
  // Custom themes
355
- if (fs.existsSync(customThemesDir)) {
356
- for (const file of fs.readdirSync(customThemesDir)) {
357
- if (file.endsWith(".json")) {
358
- const name = file.slice(0, -5);
359
- if (!result.some((t) => t.name === name)) {
360
- result.push({ name, path: path.join(customThemesDir, file) });
361
- }
362
- }
363
- }
349
+ for (const themeInfo of getCustomThemeInfos()) {
350
+ addTheme(themeInfo);
364
351
  }
365
352
  for (const [name, theme] of registeredThemes.entries()) {
366
- if (!result.some((t) => t.name === name)) {
367
- result.push({ name, path: theme.sourcePath });
368
- }
353
+ addTheme({ name, path: theme.sourcePath });
369
354
  }
370
355
  return result.sort((a, b) => a.name.localeCompare(b.name));
371
356
  }
357
+ function getCustomThemeInfos() {
358
+ const customThemesDir = getCustomThemesDir();
359
+ const result = [];
360
+ if (!fs.existsSync(customThemesDir)) {
361
+ return result;
362
+ }
363
+ for (const file of fs.readdirSync(customThemesDir)) {
364
+ if (!file.endsWith(".json")) {
365
+ continue;
366
+ }
367
+ const themePath = path.join(customThemesDir, file);
368
+ try {
369
+ const customTheme = loadThemeFromPath(themePath);
370
+ if (customTheme.name) {
371
+ result.push({ name: customTheme.name, path: themePath });
372
+ }
373
+ }
374
+ catch {
375
+ // Invalid themes are ignored here; the resource loader reports them
376
+ // during normal startup/reload.
377
+ }
378
+ }
379
+ return result;
380
+ }
372
381
  function parseThemeJson(label, json) {
373
382
  if (!validateThemeJson.Check(json)) {
374
383
  const errors = Array.from(validateThemeJson.Errors(json));
@@ -15,6 +15,7 @@ export class RpcClient {
15
15
  pendingRequests = new Map();
16
16
  requestId = 0;
17
17
  stderr = "";
18
+ exitError = null;
18
19
  options;
19
20
  constructor(options = {}) {
20
21
  this.options = options;
@@ -26,6 +27,7 @@ export class RpcClient {
26
27
  if (this.process) {
27
28
  throw new Error("Client already started");
28
29
  }
30
+ this.exitError = null;
29
31
  const cliPath = this.options.cliPath ?? "dist/cli.js";
30
32
  const args = ["--mode", "rpc"];
31
33
  if (this.options.provider) {
@@ -37,24 +39,48 @@ export class RpcClient {
37
39
  if (this.options.args) {
38
40
  args.push(...this.options.args);
39
41
  }
40
- this.process = spawn("node", [cliPath, ...args], {
42
+ const childProcess = spawn("node", [cliPath, ...args], {
41
43
  cwd: this.options.cwd,
42
44
  env: { ...process.env, ...this.options.env },
43
45
  stdio: ["pipe", "pipe", "pipe"],
44
46
  });
47
+ this.process = childProcess;
45
48
  // Collect stderr for debugging
46
- this.process.stderr?.on("data", (data) => {
49
+ childProcess.stderr?.on("data", (data) => {
47
50
  this.stderr += data.toString();
48
51
  process.stderr.write(data);
49
52
  });
53
+ childProcess.once("exit", (code, signal) => {
54
+ if (this.process !== childProcess)
55
+ return;
56
+ const error = this.createProcessExitError(code, signal);
57
+ this.exitError = error;
58
+ this.rejectPendingRequests(error);
59
+ });
60
+ childProcess.once("error", (error) => {
61
+ if (this.process !== childProcess)
62
+ return;
63
+ const processError = new Error(`Agent process error: ${error.message}. Stderr: ${this.stderr}`);
64
+ this.exitError = processError;
65
+ this.rejectPendingRequests(processError);
66
+ });
67
+ childProcess.stdin?.on("error", (error) => {
68
+ if (this.process !== childProcess)
69
+ return;
70
+ const stdinError = this.exitError ?? new Error(`Agent process stdin error: ${error.message}. Stderr: ${this.stderr}`);
71
+ this.exitError = stdinError;
72
+ this.rejectPendingRequests(stdinError);
73
+ });
50
74
  // Set up strict JSONL reader for stdout.
51
- this.stopReadingStdout = attachJsonlLineReader(this.process.stdout, (line) => {
75
+ this.stopReadingStdout = attachJsonlLineReader(childProcess.stdout, (line) => {
52
76
  this.handleLine(line);
53
77
  });
54
78
  // Wait a moment for process to initialize
55
79
  await new Promise((resolve) => setTimeout(resolve, 100));
56
80
  if (this.process.exitCode !== null) {
57
- throw new Error(`Agent process exited immediately with code ${this.process.exitCode}. Stderr: ${this.stderr}`);
81
+ const error = this.exitError ?? this.createProcessExitError(this.process.exitCode, this.process.signalCode);
82
+ this.exitError = error;
83
+ throw error;
58
84
  }
59
85
  }
60
86
  /**
@@ -371,14 +397,37 @@ export class RpcClient {
371
397
  // Ignore non-JSON lines
372
398
  }
373
399
  }
400
+ createProcessExitError(code, signal) {
401
+ return new Error(`Agent process exited (code=${code} signal=${signal}). Stderr: ${this.stderr}`);
402
+ }
403
+ rejectPendingRequests(error) {
404
+ for (const pending of this.pendingRequests.values()) {
405
+ pending.reject(error);
406
+ }
407
+ this.pendingRequests.clear();
408
+ }
374
409
  async send(command) {
375
- if (!this.process?.stdin) {
410
+ const childProcess = this.process;
411
+ const stdin = childProcess?.stdin;
412
+ if (!childProcess || !stdin) {
376
413
  throw new Error("Client not started");
377
414
  }
415
+ if (this.exitError) {
416
+ throw this.exitError;
417
+ }
418
+ if (childProcess.exitCode !== null) {
419
+ const error = this.createProcessExitError(childProcess.exitCode, childProcess.signalCode);
420
+ this.exitError = error;
421
+ throw error;
422
+ }
423
+ if (stdin.destroyed || !stdin.writable) {
424
+ const error = new Error(`Agent process stdin is not writable. Stderr: ${this.stderr}`);
425
+ this.exitError = error;
426
+ throw error;
427
+ }
378
428
  const id = `req_${++this.requestId}`;
379
429
  const fullCommand = { ...command, id };
380
430
  return new Promise((resolve, reject) => {
381
- this.pendingRequests.set(id, { resolve, reject });
382
431
  const timeout = setTimeout(() => {
383
432
  this.pendingRequests.delete(id);
384
433
  reject(new Error(`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`));
@@ -393,7 +442,15 @@ export class RpcClient {
393
442
  reject(error);
394
443
  },
395
444
  });
396
- this.process.stdin.write(serializeJsonLine(fullCommand));
445
+ try {
446
+ stdin.write(serializeJsonLine(fullCommand));
447
+ }
448
+ catch (error) {
449
+ const writeError = error instanceof Error ? error : new Error(String(error));
450
+ const pending = this.pendingRequests.get(id);
451
+ this.pendingRequests.delete(id);
452
+ pending?.reject(writeError);
453
+ }
397
454
  });
398
455
  }
399
456
  getData(response) {
@@ -11,7 +11,7 @@
11
11
  * - Extension UI: Extension UI requests are emitted, client responds with extension_ui_response
12
12
  */
13
13
  import * as crypto from "node:crypto";
14
- import { takeOverStdout, writeRawStdout } from "../../core/output-guard.js";
14
+ import { flushRawStdout, takeOverStdout, waitForRawStdoutBackpressure, writeRawStdout, } from "../../core/output-guard.js";
15
15
  import { killTrackedDetachedChildren } from "../../utils/shell.js";
16
16
  import { theme } from "../interactive/theme/theme.js";
17
17
  import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
@@ -23,6 +23,7 @@ export async function runRpcMode(runtimeHost) {
23
23
  takeOverStdout();
24
24
  let session = runtimeHost.session;
25
25
  let unsubscribe;
26
+ let unsubscribeBackpressure;
26
27
  const output = (obj) => {
27
28
  writeRawStdout(serializeJsonLine(obj));
28
29
  };
@@ -258,9 +259,13 @@ export async function runRpcMode(runtimeHost) {
258
259
  },
259
260
  });
260
261
  unsubscribe?.();
262
+ unsubscribeBackpressure?.();
261
263
  unsubscribe = session.subscribe((event) => {
262
264
  output(event);
263
265
  });
266
+ unsubscribeBackpressure = session.agent.subscribe(async () => {
267
+ await waitForRawStdoutBackpressure();
268
+ });
264
269
  };
265
270
  const registerSignalHandlers = () => {
266
271
  const signals = ["SIGTERM"];
@@ -270,7 +275,7 @@ export async function runRpcMode(runtimeHost) {
270
275
  for (const signal of signals) {
271
276
  const handler = () => {
272
277
  killTrackedDetachedChildren();
273
- void shutdown(signal === "SIGHUP" ? 129 : 143);
278
+ void shutdown(signal === "SIGHUP" ? 129 : 143, signal);
274
279
  };
275
280
  process.on(signal, handler);
276
281
  signalCleanupHandlers.push(() => process.off(signal, handler));
@@ -529,7 +534,7 @@ export async function runRpcMode(runtimeHost) {
529
534
  * Called after handling each command when waiting for the next command.
530
535
  */
531
536
  let detachInput = () => { };
532
- async function shutdown(exitCode = 0) {
537
+ async function shutdown(exitCode = 0, signal) {
533
538
  if (shuttingDown) {
534
539
  process.exit(exitCode);
535
540
  }
@@ -538,9 +543,13 @@ export async function runRpcMode(runtimeHost) {
538
543
  cleanup();
539
544
  }
540
545
  unsubscribe?.();
546
+ unsubscribeBackpressure?.();
541
547
  await runtimeHost.dispose();
542
548
  detachInput();
543
549
  process.stdin.pause();
550
+ if (signal !== "SIGTERM") {
551
+ await flushRawStdout();
552
+ }
544
553
  process.exit(exitCode);
545
554
  }
546
555
  async function checkShutdownRequested() {
@@ -555,6 +564,7 @@ export async function runRpcMode(runtimeHost) {
555
564
  }
556
565
  catch (parseError) {
557
566
  output(error(undefined, "parse", `Failed to parse command: ${parseError instanceof Error ? parseError.message : String(parseError)}`));
567
+ await waitForRawStdoutBackpressure();
558
568
  return;
559
569
  }
560
570
  // Handle extension UI responses
@@ -575,11 +585,13 @@ export async function runRpcMode(runtimeHost) {
575
585
  const response = await handleCommand(command);
576
586
  if (response) {
577
587
  output(response);
588
+ await waitForRawStdoutBackpressure();
578
589
  }
579
590
  await checkShutdownRequested();
580
591
  }
581
592
  catch (commandError) {
582
593
  output(error(command.id, command.type, commandError instanceof Error ? commandError.message : String(commandError)));
594
+ await waitForRawStdoutBackpressure();
583
595
  }
584
596
  };
585
597
  const onInputEnd = () => {
@@ -1,14 +1,20 @@
1
1
  import { createRequire } from "module";
2
- const require = createRequire(import.meta.url);
3
- let clipboard = null;
2
+ import { dirname, join } from "path";
3
+ import { pathToFileURL } from "url";
4
+ const moduleRequire = createRequire(import.meta.url);
5
+ const executableDirRequire = createRequire(pathToFileURL(join(dirname(process.execPath), "package.json")).href);
4
6
  const hasDisplay = process.platform !== "linux" || Boolean(process.env.DISPLAY || process.env.WAYLAND_DISPLAY);
5
- if (!process.env.TERMUX_VERSION && hasDisplay) {
6
- try {
7
- clipboard = require("@mariozechner/clipboard");
8
- }
9
- catch {
10
- clipboard = null;
7
+ export function loadClipboardNative(requires = [moduleRequire, executableDirRequire]) {
8
+ for (const requireClipboard of requires) {
9
+ try {
10
+ return requireClipboard("@mariozechner/clipboard");
11
+ }
12
+ catch {
13
+ // Try the next resolution root.
14
+ }
11
15
  }
16
+ return null;
12
17
  }
18
+ const clipboard = !process.env.TERMUX_VERSION && hasDisplay ? loadClipboardNative() : null;
13
19
  export { clipboard };
14
20
  //# sourceMappingURL=clipboard-native.js.map
@@ -0,0 +1,124 @@
1
+ import { applyExifOrientation } from "./exif-orientation.js";
2
+ import { loadPhoton } from "./photon.js";
3
+ // 4.5MB of base64 payload. Provides headroom below Anthropic's 5MB limit.
4
+ const DEFAULT_MAX_BYTES = 4.5 * 1024 * 1024;
5
+ const DEFAULT_OPTIONS = {
6
+ maxWidth: 2000,
7
+ maxHeight: 2000,
8
+ maxBytes: DEFAULT_MAX_BYTES,
9
+ jpegQuality: 80,
10
+ };
11
+ function encodeCandidate(buffer, mimeType) {
12
+ const data = Buffer.from(buffer).toString("base64");
13
+ return {
14
+ data,
15
+ encodedSize: Buffer.byteLength(data, "utf-8"),
16
+ mimeType,
17
+ };
18
+ }
19
+ /**
20
+ * Resize an image to fit within the specified max dimensions and encoded file size.
21
+ * Returns null if the image cannot be resized below maxBytes.
22
+ *
23
+ * Uses Photon (Rust/WASM) for image processing. If Photon is not available,
24
+ * returns null.
25
+ *
26
+ * Strategy for staying under maxBytes:
27
+ * 1. First resize to maxWidth/maxHeight
28
+ * 2. Try both PNG and JPEG formats, pick the smaller one
29
+ * 3. If still too large, try JPEG with decreasing quality
30
+ * 4. If still too large, progressively reduce dimensions until 1x1
31
+ */
32
+ export async function resizeImageInProcess(inputBytes, mimeType, options) {
33
+ const opts = { ...DEFAULT_OPTIONS, ...options };
34
+ const inputBase64Size = Math.ceil(inputBytes.byteLength / 3) * 4;
35
+ const photon = await loadPhoton();
36
+ if (!photon) {
37
+ return null;
38
+ }
39
+ let image;
40
+ try {
41
+ const rawImage = photon.PhotonImage.new_from_byteslice(inputBytes);
42
+ image = applyExifOrientation(photon, rawImage, inputBytes);
43
+ if (image !== rawImage)
44
+ rawImage.free();
45
+ const originalWidth = image.get_width();
46
+ const originalHeight = image.get_height();
47
+ const format = mimeType.split("/")[1] ?? "png";
48
+ // Check if already within all limits (dimensions AND encoded size)
49
+ if (originalWidth <= opts.maxWidth && originalHeight <= opts.maxHeight && inputBase64Size < opts.maxBytes) {
50
+ return {
51
+ data: Buffer.from(inputBytes).toString("base64"),
52
+ mimeType: mimeType || `image/${format}`,
53
+ originalWidth,
54
+ originalHeight,
55
+ width: originalWidth,
56
+ height: originalHeight,
57
+ wasResized: false,
58
+ };
59
+ }
60
+ // Calculate initial dimensions respecting max limits
61
+ let targetWidth = originalWidth;
62
+ let targetHeight = originalHeight;
63
+ if (targetWidth > opts.maxWidth) {
64
+ targetHeight = Math.round((targetHeight * opts.maxWidth) / targetWidth);
65
+ targetWidth = opts.maxWidth;
66
+ }
67
+ if (targetHeight > opts.maxHeight) {
68
+ targetWidth = Math.round((targetWidth * opts.maxHeight) / targetHeight);
69
+ targetHeight = opts.maxHeight;
70
+ }
71
+ function tryEncodings(width, height, jpegQualities) {
72
+ const resized = photon.resize(image, width, height, photon.SamplingFilter.Lanczos3);
73
+ try {
74
+ const candidates = [encodeCandidate(resized.get_bytes(), "image/png")];
75
+ for (const quality of jpegQualities) {
76
+ candidates.push(encodeCandidate(resized.get_bytes_jpeg(quality), "image/jpeg"));
77
+ }
78
+ return candidates;
79
+ }
80
+ finally {
81
+ resized.free();
82
+ }
83
+ }
84
+ const qualitySteps = Array.from(new Set([opts.jpegQuality, 85, 70, 55, 40]));
85
+ let currentWidth = targetWidth;
86
+ let currentHeight = targetHeight;
87
+ while (true) {
88
+ const candidates = tryEncodings(currentWidth, currentHeight, qualitySteps);
89
+ for (const candidate of candidates) {
90
+ if (candidate.encodedSize < opts.maxBytes) {
91
+ return {
92
+ data: candidate.data,
93
+ mimeType: candidate.mimeType,
94
+ originalWidth,
95
+ originalHeight,
96
+ width: currentWidth,
97
+ height: currentHeight,
98
+ wasResized: true,
99
+ };
100
+ }
101
+ }
102
+ if (currentWidth === 1 && currentHeight === 1) {
103
+ break;
104
+ }
105
+ const nextWidth = currentWidth === 1 ? 1 : Math.max(1, Math.floor(currentWidth * 0.75));
106
+ const nextHeight = currentHeight === 1 ? 1 : Math.max(1, Math.floor(currentHeight * 0.75));
107
+ if (nextWidth === currentWidth && nextHeight === currentHeight) {
108
+ break;
109
+ }
110
+ currentWidth = nextWidth;
111
+ currentHeight = nextHeight;
112
+ }
113
+ return null;
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ finally {
119
+ if (image) {
120
+ image.free();
121
+ }
122
+ }
123
+ }
124
+ //# sourceMappingURL=image-resize-core.js.map
@@ -0,0 +1,31 @@
1
+ import { parentPort } from "node:worker_threads";
2
+ import { resizeImageInProcess } from "./image-resize-core.js";
3
+ function isResizeImageWorkerRequest(value) {
4
+ if (!value || typeof value !== "object")
5
+ return false;
6
+ const record = value;
7
+ return record.inputBytes instanceof Uint8Array && typeof record.mimeType === "string";
8
+ }
9
+ const port = parentPort;
10
+ if (!port) {
11
+ throw new Error("image resize worker requires parentPort");
12
+ }
13
+ port.once("message", (message) => {
14
+ void (async () => {
15
+ try {
16
+ if (!isResizeImageWorkerRequest(message)) {
17
+ throw new Error("Invalid image resize worker request");
18
+ }
19
+ const result = await resizeImageInProcess(message.inputBytes, message.mimeType, message.options);
20
+ const response = { result };
21
+ port.postMessage(response);
22
+ }
23
+ catch (error) {
24
+ const response = {
25
+ error: error instanceof Error ? error.message : String(error),
26
+ };
27
+ port.postMessage(response);
28
+ }
29
+ })();
30
+ });
31
+ //# sourceMappingURL=image-resize-worker.js.map