jonsoc 1.1.50 → 1.1.51

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 (420) hide show
  1. package/AGENTS.md +27 -0
  2. package/Dockerfile +18 -0
  3. package/PUBLISHING_GUIDE.md +151 -0
  4. package/README.md +58 -0
  5. package/bin/jonsoc +256 -256
  6. package/bunfig.toml +7 -0
  7. package/package.json +142 -8
  8. package/package.json.placeholder +11 -0
  9. package/parsers-config.ts +253 -0
  10. package/script/build.ts +115 -0
  11. package/script/publish-registries.ts +197 -0
  12. package/script/publish.ts +149 -0
  13. package/script/schema.ts +47 -0
  14. package/script/seed-e2e.ts +50 -0
  15. package/src/acp/README.md +164 -0
  16. package/src/acp/agent.ts +1437 -0
  17. package/src/acp/session.ts +105 -0
  18. package/src/acp/types.ts +22 -0
  19. package/src/agent/agent.ts +345 -0
  20. package/src/agent/generate.txt +75 -0
  21. package/src/agent/prompt/compaction.txt +12 -0
  22. package/src/agent/prompt/explore.txt +18 -0
  23. package/src/agent/prompt/summary.txt +11 -0
  24. package/src/agent/prompt/title.txt +44 -0
  25. package/src/auth/index.ts +73 -0
  26. package/src/brand/index.ts +89 -0
  27. package/src/bun/index.ts +139 -0
  28. package/src/bus/bus-event.ts +43 -0
  29. package/src/bus/global.ts +10 -0
  30. package/src/bus/index.ts +105 -0
  31. package/src/cli/bootstrap.ts +17 -0
  32. package/src/cli/cmd/acp.ts +69 -0
  33. package/src/cli/cmd/agent.ts +257 -0
  34. package/src/cli/cmd/auth.ts +405 -0
  35. package/src/cli/cmd/cmd.ts +7 -0
  36. package/src/cli/cmd/debug/agent.ts +166 -0
  37. package/src/cli/cmd/debug/config.ts +16 -0
  38. package/src/cli/cmd/debug/file.ts +97 -0
  39. package/src/cli/cmd/debug/index.ts +48 -0
  40. package/src/cli/cmd/debug/lsp.ts +52 -0
  41. package/src/cli/cmd/debug/ripgrep.ts +87 -0
  42. package/src/cli/cmd/debug/scrap.ts +16 -0
  43. package/src/cli/cmd/debug/skill.ts +16 -0
  44. package/src/cli/cmd/debug/snapshot.ts +52 -0
  45. package/src/cli/cmd/export.ts +88 -0
  46. package/src/cli/cmd/generate.ts +38 -0
  47. package/src/cli/cmd/github.ts +1547 -0
  48. package/src/cli/cmd/import.ts +99 -0
  49. package/src/cli/cmd/mcp.ts +765 -0
  50. package/src/cli/cmd/models.ts +77 -0
  51. package/src/cli/cmd/pr.ts +112 -0
  52. package/src/cli/cmd/run.ts +395 -0
  53. package/src/cli/cmd/serve.ts +20 -0
  54. package/src/cli/cmd/session.ts +135 -0
  55. package/src/cli/cmd/stats.ts +402 -0
  56. package/src/cli/cmd/tui/app.tsx +923 -0
  57. package/src/cli/cmd/tui/attach.ts +39 -0
  58. package/src/cli/cmd/tui/component/border.tsx +21 -0
  59. package/src/cli/cmd/tui/component/dialog-agent.tsx +31 -0
  60. package/src/cli/cmd/tui/component/dialog-command.tsx +162 -0
  61. package/src/cli/cmd/tui/component/dialog-error-log.tsx +155 -0
  62. package/src/cli/cmd/tui/component/dialog-mcp.tsx +86 -0
  63. package/src/cli/cmd/tui/component/dialog-model.tsx +234 -0
  64. package/src/cli/cmd/tui/component/dialog-provider.tsx +256 -0
  65. package/src/cli/cmd/tui/component/dialog-session-list.tsx +114 -0
  66. package/src/cli/cmd/tui/component/dialog-session-rename.tsx +31 -0
  67. package/src/cli/cmd/tui/component/dialog-stash.tsx +87 -0
  68. package/src/cli/cmd/tui/component/dialog-status.tsx +164 -0
  69. package/src/cli/cmd/tui/component/dialog-tag.tsx +44 -0
  70. package/src/cli/cmd/tui/component/dialog-theme-list.tsx +50 -0
  71. package/src/cli/cmd/tui/component/dynamic-layout.tsx +86 -0
  72. package/src/cli/cmd/tui/component/inspector-overlay.tsx +247 -0
  73. package/src/cli/cmd/tui/component/logo.tsx +88 -0
  74. package/src/cli/cmd/tui/component/prompt/autocomplete.tsx +653 -0
  75. package/src/cli/cmd/tui/component/prompt/frecency.tsx +89 -0
  76. package/src/cli/cmd/tui/component/prompt/history.tsx +108 -0
  77. package/src/cli/cmd/tui/component/prompt/index.tsx +1347 -0
  78. package/src/cli/cmd/tui/component/prompt/stash.tsx +101 -0
  79. package/src/cli/cmd/tui/component/textarea-keybindings.ts +73 -0
  80. package/src/cli/cmd/tui/component/tips.tsx +153 -0
  81. package/src/cli/cmd/tui/component/todo-item.tsx +32 -0
  82. package/src/cli/cmd/tui/context/args.tsx +14 -0
  83. package/src/cli/cmd/tui/context/directory.ts +13 -0
  84. package/src/cli/cmd/tui/context/error-log.tsx +56 -0
  85. package/src/cli/cmd/tui/context/exit.tsx +26 -0
  86. package/src/cli/cmd/tui/context/helper.tsx +25 -0
  87. package/src/cli/cmd/tui/context/inspector.tsx +57 -0
  88. package/src/cli/cmd/tui/context/keybind.tsx +108 -0
  89. package/src/cli/cmd/tui/context/kv.tsx +53 -0
  90. package/src/cli/cmd/tui/context/layout.tsx +240 -0
  91. package/src/cli/cmd/tui/context/local.tsx +402 -0
  92. package/src/cli/cmd/tui/context/prompt.tsx +18 -0
  93. package/src/cli/cmd/tui/context/route.tsx +51 -0
  94. package/src/cli/cmd/tui/context/sdk.tsx +94 -0
  95. package/src/cli/cmd/tui/context/sync.tsx +449 -0
  96. package/src/cli/cmd/tui/context/theme/aura.json +69 -0
  97. package/src/cli/cmd/tui/context/theme/ayu.json +80 -0
  98. package/src/cli/cmd/tui/context/theme/carbonfox.json +248 -0
  99. package/src/cli/cmd/tui/context/theme/catppuccin-frappe.json +233 -0
  100. package/src/cli/cmd/tui/context/theme/catppuccin-macchiato.json +233 -0
  101. package/src/cli/cmd/tui/context/theme/catppuccin.json +112 -0
  102. package/src/cli/cmd/tui/context/theme/cobalt2.json +228 -0
  103. package/src/cli/cmd/tui/context/theme/cursor.json +249 -0
  104. package/src/cli/cmd/tui/context/theme/dracula.json +219 -0
  105. package/src/cli/cmd/tui/context/theme/everforest.json +241 -0
  106. package/src/cli/cmd/tui/context/theme/flexoki.json +237 -0
  107. package/src/cli/cmd/tui/context/theme/github.json +233 -0
  108. package/src/cli/cmd/tui/context/theme/gruvbox.json +242 -0
  109. package/src/cli/cmd/tui/context/theme/jonsoc.json +245 -0
  110. package/src/cli/cmd/tui/context/theme/kanagawa.json +77 -0
  111. package/src/cli/cmd/tui/context/theme/lucent-orng.json +237 -0
  112. package/src/cli/cmd/tui/context/theme/material.json +235 -0
  113. package/src/cli/cmd/tui/context/theme/matrix.json +77 -0
  114. package/src/cli/cmd/tui/context/theme/mercury.json +252 -0
  115. package/src/cli/cmd/tui/context/theme/monokai.json +221 -0
  116. package/src/cli/cmd/tui/context/theme/nightowl.json +221 -0
  117. package/src/cli/cmd/tui/context/theme/nord.json +223 -0
  118. package/src/cli/cmd/tui/context/theme/one-dark.json +84 -0
  119. package/src/cli/cmd/tui/context/theme/orng.json +249 -0
  120. package/src/cli/cmd/tui/context/theme/osaka-jade.json +93 -0
  121. package/src/cli/cmd/tui/context/theme/palenight.json +222 -0
  122. package/src/cli/cmd/tui/context/theme/rosepine.json +234 -0
  123. package/src/cli/cmd/tui/context/theme/solarized.json +223 -0
  124. package/src/cli/cmd/tui/context/theme/synthwave84.json +226 -0
  125. package/src/cli/cmd/tui/context/theme/tokyonight.json +243 -0
  126. package/src/cli/cmd/tui/context/theme/vercel.json +245 -0
  127. package/src/cli/cmd/tui/context/theme/vesper.json +218 -0
  128. package/src/cli/cmd/tui/context/theme/zenburn.json +223 -0
  129. package/src/cli/cmd/tui/context/theme.tsx +1152 -0
  130. package/src/cli/cmd/tui/event.ts +48 -0
  131. package/src/cli/cmd/tui/hooks/use-command-registry.tsx +184 -0
  132. package/src/cli/cmd/tui/routes/home.tsx +198 -0
  133. package/src/cli/cmd/tui/routes/session/dialog-fork-from-timeline.tsx +64 -0
  134. package/src/cli/cmd/tui/routes/session/dialog-message.tsx +109 -0
  135. package/src/cli/cmd/tui/routes/session/dialog-subagent.tsx +26 -0
  136. package/src/cli/cmd/tui/routes/session/dialog-timeline.tsx +47 -0
  137. package/src/cli/cmd/tui/routes/session/footer.tsx +91 -0
  138. package/src/cli/cmd/tui/routes/session/git-commit.tsx +59 -0
  139. package/src/cli/cmd/tui/routes/session/git-history.tsx +122 -0
  140. package/src/cli/cmd/tui/routes/session/header.tsx +185 -0
  141. package/src/cli/cmd/tui/routes/session/index.tsx +2363 -0
  142. package/src/cli/cmd/tui/routes/session/navigator-ui.tsx +214 -0
  143. package/src/cli/cmd/tui/routes/session/navigator.tsx +1124 -0
  144. package/src/cli/cmd/tui/routes/session/panel-explorer.tsx +553 -0
  145. package/src/cli/cmd/tui/routes/session/panel-viewer.tsx +386 -0
  146. package/src/cli/cmd/tui/routes/session/permission.tsx +501 -0
  147. package/src/cli/cmd/tui/routes/session/question.tsx +507 -0
  148. package/src/cli/cmd/tui/routes/session/sidebar.tsx +365 -0
  149. package/src/cli/cmd/tui/routes/session/vcs-diff-viewer.tsx +37 -0
  150. package/src/cli/cmd/tui/routes/ui-settings.tsx +449 -0
  151. package/src/cli/cmd/tui/thread.ts +172 -0
  152. package/src/cli/cmd/tui/ui/dialog-alert.tsx +90 -0
  153. package/src/cli/cmd/tui/ui/dialog-confirm.tsx +83 -0
  154. package/src/cli/cmd/tui/ui/dialog-export-options.tsx +204 -0
  155. package/src/cli/cmd/tui/ui/dialog-help.tsx +38 -0
  156. package/src/cli/cmd/tui/ui/dialog-prompt.tsx +77 -0
  157. package/src/cli/cmd/tui/ui/dialog-select.tsx +384 -0
  158. package/src/cli/cmd/tui/ui/dialog.tsx +170 -0
  159. package/src/cli/cmd/tui/ui/link.tsx +28 -0
  160. package/src/cli/cmd/tui/ui/spinner.ts +375 -0
  161. package/src/cli/cmd/tui/ui/toast.tsx +100 -0
  162. package/src/cli/cmd/tui/util/clipboard.ts +255 -0
  163. package/src/cli/cmd/tui/util/editor.ts +32 -0
  164. package/src/cli/cmd/tui/util/signal.ts +7 -0
  165. package/src/cli/cmd/tui/util/terminal.ts +114 -0
  166. package/src/cli/cmd/tui/util/transcript.ts +98 -0
  167. package/src/cli/cmd/tui/worker.ts +152 -0
  168. package/src/cli/cmd/uninstall.ts +362 -0
  169. package/src/cli/cmd/upgrade.ts +73 -0
  170. package/src/cli/cmd/web.ts +81 -0
  171. package/src/cli/error.ts +57 -0
  172. package/src/cli/network.ts +53 -0
  173. package/src/cli/ui.ts +119 -0
  174. package/src/cli/upgrade.ts +25 -0
  175. package/src/command/index.ts +131 -0
  176. package/src/command/template/initialize.txt +10 -0
  177. package/src/command/template/review.txt +99 -0
  178. package/src/config/config.ts +1404 -0
  179. package/src/config/markdown.ts +93 -0
  180. package/src/env/index.ts +26 -0
  181. package/src/file/ignore.ts +83 -0
  182. package/src/file/index.ts +432 -0
  183. package/src/file/ripgrep.ts +407 -0
  184. package/src/file/time.ts +69 -0
  185. package/src/file/watcher.ts +127 -0
  186. package/src/flag/flag.ts +80 -0
  187. package/src/format/formatter.ts +357 -0
  188. package/src/format/index.ts +137 -0
  189. package/src/global/index.ts +58 -0
  190. package/src/id/id.ts +83 -0
  191. package/src/ide/index.ts +76 -0
  192. package/src/index.ts +208 -0
  193. package/src/installation/index.ts +258 -0
  194. package/src/lsp/client.ts +252 -0
  195. package/src/lsp/index.ts +485 -0
  196. package/src/lsp/language.ts +119 -0
  197. package/src/lsp/server.ts +2046 -0
  198. package/src/mcp/auth.ts +135 -0
  199. package/src/mcp/index.ts +934 -0
  200. package/src/mcp/oauth-callback.ts +200 -0
  201. package/src/mcp/oauth-provider.ts +155 -0
  202. package/src/patch/index.ts +680 -0
  203. package/src/permission/arity.ts +163 -0
  204. package/src/permission/index.ts +210 -0
  205. package/src/permission/next.ts +280 -0
  206. package/src/plugin/codex.ts +500 -0
  207. package/src/plugin/copilot.ts +283 -0
  208. package/src/plugin/index.ts +135 -0
  209. package/src/project/bootstrap.ts +35 -0
  210. package/src/project/instance.ts +91 -0
  211. package/src/project/project.ts +371 -0
  212. package/src/project/state.ts +66 -0
  213. package/src/project/vcs.ts +151 -0
  214. package/src/provider/auth.ts +147 -0
  215. package/src/provider/models-macro.ts +14 -0
  216. package/src/provider/models.ts +114 -0
  217. package/src/provider/provider.ts +1220 -0
  218. package/src/provider/sdk/openai-compatible/src/README.md +5 -0
  219. package/src/provider/sdk/openai-compatible/src/index.ts +2 -0
  220. package/src/provider/sdk/openai-compatible/src/openai-compatible-provider.ts +100 -0
  221. package/src/provider/sdk/openai-compatible/src/responses/convert-to-openai-responses-input.ts +303 -0
  222. package/src/provider/sdk/openai-compatible/src/responses/map-openai-responses-finish-reason.ts +22 -0
  223. package/src/provider/sdk/openai-compatible/src/responses/openai-config.ts +18 -0
  224. package/src/provider/sdk/openai-compatible/src/responses/openai-error.ts +22 -0
  225. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-api-types.ts +207 -0
  226. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-language-model.ts +1732 -0
  227. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-prepare-tools.ts +177 -0
  228. package/src/provider/sdk/openai-compatible/src/responses/openai-responses-settings.ts +1 -0
  229. package/src/provider/sdk/openai-compatible/src/responses/tool/code-interpreter.ts +88 -0
  230. package/src/provider/sdk/openai-compatible/src/responses/tool/file-search.ts +128 -0
  231. package/src/provider/sdk/openai-compatible/src/responses/tool/image-generation.ts +115 -0
  232. package/src/provider/sdk/openai-compatible/src/responses/tool/local-shell.ts +65 -0
  233. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search-preview.ts +104 -0
  234. package/src/provider/sdk/openai-compatible/src/responses/tool/web-search.ts +103 -0
  235. package/src/provider/transform.ts +742 -0
  236. package/src/pty/index.ts +241 -0
  237. package/src/question/index.ts +176 -0
  238. package/src/scheduler/index.ts +61 -0
  239. package/src/server/error.ts +36 -0
  240. package/src/server/event.ts +7 -0
  241. package/src/server/mdns.ts +59 -0
  242. package/src/server/routes/config.ts +92 -0
  243. package/src/server/routes/experimental.ts +208 -0
  244. package/src/server/routes/file.ts +227 -0
  245. package/src/server/routes/global.ts +135 -0
  246. package/src/server/routes/mcp.ts +225 -0
  247. package/src/server/routes/permission.ts +68 -0
  248. package/src/server/routes/project.ts +82 -0
  249. package/src/server/routes/provider.ts +165 -0
  250. package/src/server/routes/pty.ts +169 -0
  251. package/src/server/routes/question.ts +98 -0
  252. package/src/server/routes/session.ts +939 -0
  253. package/src/server/routes/tui.ts +379 -0
  254. package/src/server/server.ts +663 -0
  255. package/src/session/compaction.ts +225 -0
  256. package/src/session/index.ts +498 -0
  257. package/src/session/llm.ts +288 -0
  258. package/src/session/message-v2.ts +740 -0
  259. package/src/session/message.ts +189 -0
  260. package/src/session/processor.ts +406 -0
  261. package/src/session/prompt/anthropic-20250930.txt +168 -0
  262. package/src/session/prompt/anthropic.txt +172 -0
  263. package/src/session/prompt/anthropic_spoof.txt +1 -0
  264. package/src/session/prompt/beast.txt +149 -0
  265. package/src/session/prompt/build-switch.txt +5 -0
  266. package/src/session/prompt/codex_header.txt +81 -0
  267. package/src/session/prompt/copilot-gpt-5.txt +145 -0
  268. package/src/session/prompt/gemini.txt +157 -0
  269. package/src/session/prompt/max-steps.txt +16 -0
  270. package/src/session/prompt/plan-reminder-anthropic.txt +67 -0
  271. package/src/session/prompt/plan.txt +26 -0
  272. package/src/session/prompt/qwen.txt +111 -0
  273. package/src/session/prompt.ts +1815 -0
  274. package/src/session/retry.ts +90 -0
  275. package/src/session/revert.ts +121 -0
  276. package/src/session/status.ts +76 -0
  277. package/src/session/summary.ts +150 -0
  278. package/src/session/system.ts +156 -0
  279. package/src/session/todo.ts +37 -0
  280. package/src/share/share-next.ts +205 -0
  281. package/src/share/share.ts +95 -0
  282. package/src/shell/shell.ts +67 -0
  283. package/src/skill/index.ts +1 -0
  284. package/src/skill/skill.ts +135 -0
  285. package/src/snapshot/index.ts +236 -0
  286. package/src/storage/storage.ts +227 -0
  287. package/src/tool/apply_patch.ts +279 -0
  288. package/src/tool/apply_patch.txt +33 -0
  289. package/src/tool/bash.ts +258 -0
  290. package/src/tool/bash.txt +115 -0
  291. package/src/tool/batch.ts +175 -0
  292. package/src/tool/batch.txt +24 -0
  293. package/src/tool/codesearch.ts +132 -0
  294. package/src/tool/codesearch.txt +12 -0
  295. package/src/tool/edit.ts +645 -0
  296. package/src/tool/edit.txt +10 -0
  297. package/src/tool/external-directory.ts +32 -0
  298. package/src/tool/glob.ts +77 -0
  299. package/src/tool/glob.txt +6 -0
  300. package/src/tool/grep.ts +154 -0
  301. package/src/tool/grep.txt +8 -0
  302. package/src/tool/invalid.ts +17 -0
  303. package/src/tool/ls.ts +121 -0
  304. package/src/tool/ls.txt +1 -0
  305. package/src/tool/lsp.ts +96 -0
  306. package/src/tool/lsp.txt +19 -0
  307. package/src/tool/multiedit.ts +46 -0
  308. package/src/tool/multiedit.txt +41 -0
  309. package/src/tool/plan-enter.txt +14 -0
  310. package/src/tool/plan-exit.txt +13 -0
  311. package/src/tool/plan.ts +130 -0
  312. package/src/tool/question.ts +33 -0
  313. package/src/tool/question.txt +10 -0
  314. package/src/tool/read.ts +202 -0
  315. package/src/tool/read.txt +12 -0
  316. package/src/tool/registry.ts +162 -0
  317. package/src/tool/skill.ts +82 -0
  318. package/src/tool/task.ts +188 -0
  319. package/src/tool/task.txt +60 -0
  320. package/src/tool/todo.ts +53 -0
  321. package/src/tool/todoread.txt +14 -0
  322. package/src/tool/todowrite.txt +167 -0
  323. package/src/tool/tool.ts +88 -0
  324. package/src/tool/truncation.ts +106 -0
  325. package/src/tool/webfetch.ts +182 -0
  326. package/src/tool/webfetch.txt +13 -0
  327. package/src/tool/websearch.ts +150 -0
  328. package/src/tool/websearch.txt +14 -0
  329. package/src/tool/write.ts +80 -0
  330. package/src/tool/write.txt +8 -0
  331. package/src/util/archive.ts +16 -0
  332. package/src/util/color.ts +19 -0
  333. package/src/util/context.ts +25 -0
  334. package/src/util/defer.ts +12 -0
  335. package/src/util/eventloop.ts +20 -0
  336. package/src/util/filesystem.ts +93 -0
  337. package/src/util/fn.ts +11 -0
  338. package/src/util/format.ts +20 -0
  339. package/src/util/iife.ts +3 -0
  340. package/src/util/keybind.ts +103 -0
  341. package/src/util/lazy.ts +18 -0
  342. package/src/util/locale.ts +81 -0
  343. package/src/util/lock.ts +98 -0
  344. package/src/util/log.ts +180 -0
  345. package/src/util/queue.ts +32 -0
  346. package/src/util/rpc.ts +66 -0
  347. package/src/util/scrap.ts +10 -0
  348. package/src/util/signal.ts +12 -0
  349. package/src/util/timeout.ts +14 -0
  350. package/src/util/token.ts +7 -0
  351. package/src/util/wildcard.ts +56 -0
  352. package/src/worktree/index.ts +524 -0
  353. package/sst-env.d.ts +9 -0
  354. package/test/acp/agent-interface.test.ts +51 -0
  355. package/test/acp/event-subscription.test.ts +436 -0
  356. package/test/agent/agent.test.ts +638 -0
  357. package/test/bun.test.ts +53 -0
  358. package/test/cli/cmd/tui/fileref.test.ts +30 -0
  359. package/test/cli/github-action.test.ts +129 -0
  360. package/test/cli/github-remote.test.ts +80 -0
  361. package/test/cli/tui/navigator_logic.test.ts +99 -0
  362. package/test/cli/tui/transcript.test.ts +297 -0
  363. package/test/cli/ui.test.ts +80 -0
  364. package/test/config/agent-color.test.ts +66 -0
  365. package/test/config/config.test.ts +1613 -0
  366. package/test/config/fixtures/empty-frontmatter.md +4 -0
  367. package/test/config/fixtures/frontmatter.md +28 -0
  368. package/test/config/fixtures/no-frontmatter.md +1 -0
  369. package/test/config/markdown.test.ts +192 -0
  370. package/test/file/ignore.test.ts +10 -0
  371. package/test/file/path-traversal.test.ts +198 -0
  372. package/test/fixture/fixture.ts +45 -0
  373. package/test/fixture/lsp/fake-lsp-server.js +77 -0
  374. package/test/ide/ide.test.ts +82 -0
  375. package/test/keybind.test.ts +421 -0
  376. package/test/lsp/client.test.ts +95 -0
  377. package/test/mcp/headers.test.ts +153 -0
  378. package/test/mcp/oauth-browser.test.ts +261 -0
  379. package/test/patch/patch.test.ts +348 -0
  380. package/test/permission/arity.test.ts +33 -0
  381. package/test/permission/next.test.ts +690 -0
  382. package/test/permission-task.test.ts +319 -0
  383. package/test/plugin/codex.test.ts +123 -0
  384. package/test/preload.ts +67 -0
  385. package/test/project/project.test.ts +120 -0
  386. package/test/provider/amazon-bedrock.test.ts +268 -0
  387. package/test/provider/gitlab-duo.test.ts +286 -0
  388. package/test/provider/provider.test.ts +2149 -0
  389. package/test/provider/transform.test.ts +1631 -0
  390. package/test/question/question.test.ts +300 -0
  391. package/test/scheduler.test.ts +73 -0
  392. package/test/server/session-list.test.ts +39 -0
  393. package/test/server/session-select.test.ts +78 -0
  394. package/test/session/compaction.test.ts +293 -0
  395. package/test/session/llm.test.ts +90 -0
  396. package/test/session/message-v2.test.ts +786 -0
  397. package/test/session/retry.test.ts +131 -0
  398. package/test/session/revert-compact.test.ts +285 -0
  399. package/test/session/session.test.ts +71 -0
  400. package/test/skill/skill.test.ts +185 -0
  401. package/test/snapshot/snapshot.test.ts +939 -0
  402. package/test/tool/__snapshots__/tool.test.ts.snap +9 -0
  403. package/test/tool/apply_patch.test.ts +499 -0
  404. package/test/tool/bash.test.ts +320 -0
  405. package/test/tool/external-directory.test.ts +126 -0
  406. package/test/tool/fixtures/large-image.png +0 -0
  407. package/test/tool/fixtures/models-api.json +33453 -0
  408. package/test/tool/grep.test.ts +109 -0
  409. package/test/tool/question.test.ts +105 -0
  410. package/test/tool/read.test.ts +332 -0
  411. package/test/tool/registry.test.ts +76 -0
  412. package/test/tool/truncation.test.ts +159 -0
  413. package/test/util/filesystem.test.ts +39 -0
  414. package/test/util/format.test.ts +59 -0
  415. package/test/util/iife.test.ts +36 -0
  416. package/test/util/lazy.test.ts +50 -0
  417. package/test/util/lock.test.ts +72 -0
  418. package/test/util/timeout.test.ts +21 -0
  419. package/test/util/wildcard.test.ts +75 -0
  420. package/tsconfig.json +16 -0
@@ -0,0 +1,449 @@
1
+ import { createSignal, createMemo, For, Show } from "solid-js"
2
+ import { useRoute, useRouteData } from "@tui/context/route"
3
+ import { useLayout, type PanelType } from "@tui/context/layout"
4
+ import { useTheme } from "@tui/context/theme"
5
+ import { useTerminalDimensions } from "@opentui/solid"
6
+ import { TextAttributes, RGBA } from "@opentui/core"
7
+ import { useKeyboard } from "@opentui/solid"
8
+
9
+ const PANEL_COLORS: Record<PanelType, [number, number, number]> = {
10
+ chat: [100, 200, 100],
11
+ explorer: [255, 200, 100],
12
+ viewer: [100, 150, 255],
13
+ }
14
+
15
+ function getPanelColor(type: PanelType, alpha: number): RGBA {
16
+ const [r, g, b] = PANEL_COLORS[type]
17
+ return RGBA.fromInts(r, g, b, Math.floor(alpha * 255))
18
+ }
19
+
20
+ const PANEL_NAMES: Record<PanelType, string> = {
21
+ chat: "CHAT",
22
+ explorer: "EXPLORER",
23
+ viewer: "VIEWER",
24
+ }
25
+
26
+ const PANEL_DESC: Record<PanelType, string> = {
27
+ chat: "Conversation & Prompt",
28
+ explorer: "File Tree & Git Status",
29
+ viewer: "File Editor & Preview",
30
+ }
31
+
32
+ export function UISettings() {
33
+ const route = useRouteData("ui-settings")
34
+ const { navigate } = useRoute()
35
+ const layout = useLayout()
36
+ const { theme } = useTheme()
37
+ const dimensions = useTerminalDimensions()
38
+
39
+ // Click-to-swap state
40
+ const [selectedPanel, setSelectedPanel] = createSignal<PanelType | null>(null)
41
+
42
+ // Width adjustment step
43
+ const WIDTH_STEP = 5
44
+
45
+ const safeDimensions = createMemo(() => {
46
+ const dims = dimensions()
47
+ return {
48
+ width: dims?.width ?? 80,
49
+ height: dims?.height ?? 24,
50
+ }
51
+ })
52
+
53
+ // Preview dimensions: match terminal aspect ratio exactly
54
+ const previewDimensions = createMemo(() => {
55
+ const termWidth = safeDimensions().width - 4 // Account for padding
56
+ const termHeight = safeDimensions().height - 8 // Account for header/footer
57
+
58
+ // Use 60% of available space for preview to leave room for controls
59
+ const maxWidth = Math.floor(termWidth * 0.6)
60
+ const maxHeight = Math.floor(termHeight * 0.6)
61
+
62
+ // Calculate aspect ratio of terminal
63
+ const aspectRatio = termWidth / termHeight
64
+
65
+ // Calculate preview dimensions maintaining exact aspect ratio
66
+ let previewWidth = maxWidth
67
+ let previewHeight = Math.floor(previewWidth / aspectRatio)
68
+
69
+ // If height exceeds max, scale down proportionally
70
+ if (previewHeight > maxHeight) {
71
+ previewHeight = maxHeight
72
+ previewWidth = Math.floor(previewHeight * aspectRatio)
73
+ }
74
+
75
+ // Ensure minimum dimensions
76
+ previewWidth = Math.max(30, previewWidth)
77
+ previewHeight = Math.max(8, previewHeight)
78
+
79
+ return { width: previewWidth, height: previewHeight }
80
+ })
81
+
82
+ // Get visible panels sorted by position for layout preview
83
+ const visiblePanels = createMemo(() => layout.panels.filter((p) => p.visible).sort((a, b) => a.position - b.position))
84
+
85
+ // Calculate proportional width for each visible panel in the preview
86
+ const getPanelPreviewWidth = (panel: { visible: boolean; width: number }) => {
87
+ if (!panel.visible) return 0
88
+ const totalVisibleWidth = visiblePanels().reduce((sum, p) => sum + p.width, 0)
89
+ if (totalVisibleWidth === 0) return 0
90
+ // Proportional width based on visible panels only
91
+ return Math.floor((previewDimensions().width * panel.width) / totalVisibleWidth)
92
+ }
93
+
94
+ // Handle click-to-swap panel selection
95
+ const handlePanelClick = (type: PanelType) => {
96
+ const currentSelected = selectedPanel()
97
+
98
+ if (currentSelected === null) {
99
+ // First click - select this panel
100
+ setSelectedPanel(type)
101
+ } else if (currentSelected === type) {
102
+ // Clicked same panel - deselect
103
+ setSelectedPanel(null)
104
+ } else {
105
+ // Clicked different panel - swap them
106
+ const panel1 = layout.getPanelByType(currentSelected)
107
+ const panel2 = layout.getPanelByType(type)
108
+ if (panel1 && panel2) {
109
+ layout.swapPanels(panel1.position, panel2.position)
110
+ }
111
+ setSelectedPanel(null)
112
+ }
113
+ }
114
+
115
+ // Handle width adjustment with +/- buttons - transfers width between adjacent panels
116
+ const adjustWidth = (type: PanelType, direction: "minus" | "plus") => {
117
+ const panel = layout.getPanelByType(type)
118
+ if (!panel || !panel.visible) return
119
+
120
+ // Find adjacent visible panels
121
+ const sortedVisible = layout.panels.filter((p) => p.visible).sort((a, b) => a.position - b.position)
122
+ const panelIndex = sortedVisible.findIndex((p) => p.type === type)
123
+
124
+ if (panelIndex === -1) return
125
+
126
+ if (direction === "minus") {
127
+ // Decreasing: give space to the panel on the right (if exists), otherwise left
128
+ const recipientIndex = panelIndex < sortedVisible.length - 1 ? panelIndex + 1 : panelIndex - 1
129
+ if (recipientIndex < 0 || recipientIndex >= sortedVisible.length) return
130
+
131
+ const recipient = sortedVisible[recipientIndex]
132
+ const canDecrease = panel.width - 5 >= WIDTH_STEP
133
+ const canReceive = recipient.width + WIDTH_STEP <= 90
134
+
135
+ if (canDecrease && canReceive) {
136
+ layout.setPanelWidth(type, panel.width - WIDTH_STEP)
137
+ layout.setPanelWidth(recipient.type, recipient.width + WIDTH_STEP)
138
+ }
139
+ } else {
140
+ // Increasing: take space from the panel on the right (if exists), otherwise left
141
+ const donorIndex = panelIndex < sortedVisible.length - 1 ? panelIndex + 1 : panelIndex - 1
142
+ if (donorIndex < 0 || donorIndex >= sortedVisible.length) return
143
+
144
+ const donor = sortedVisible[donorIndex]
145
+ const canIncrease = panel.width + WIDTH_STEP <= 90
146
+ const canGive = donor.width - 5 >= WIDTH_STEP
147
+
148
+ if (canIncrease && canGive) {
149
+ layout.setPanelWidth(type, panel.width + WIDTH_STEP)
150
+ layout.setPanelWidth(donor.type, donor.width - WIDTH_STEP)
151
+ }
152
+ }
153
+ }
154
+
155
+ const totalPercent = createMemo(() => layout.panels.reduce((sum, p) => sum + (p.visible ? p.width : 0), 0))
156
+
157
+ const isLayoutValid = createMemo(() => totalPercent() === 100)
158
+
159
+ const handleReturn = () => {
160
+ // Only allow exit if layout totals exactly 100%
161
+ if (!isLayoutValid()) return
162
+
163
+ if (route.returnTo) {
164
+ navigate(route.returnTo)
165
+ } else {
166
+ navigate({ type: "home" })
167
+ }
168
+ }
169
+
170
+ const handleReset = () => {
171
+ layout.resetToDefault()
172
+ setSelectedPanel(null)
173
+ }
174
+
175
+ useKeyboard((e) => {
176
+ if (e.name === "escape") {
177
+ setSelectedPanel(null)
178
+ return
179
+ }
180
+ })
181
+
182
+ return (
183
+ <box
184
+ width={safeDimensions().width}
185
+ height={safeDimensions().height}
186
+ flexDirection="column"
187
+ backgroundColor={theme.background}
188
+ >
189
+ {/* Header */}
190
+ <box
191
+ flexShrink={0}
192
+ paddingTop={1}
193
+ paddingBottom={1}
194
+ paddingLeft={2}
195
+ paddingRight={2}
196
+ flexDirection="row"
197
+ justifyContent="space-between"
198
+ alignItems="center"
199
+ border={["bottom"]}
200
+ borderColor={theme.border}
201
+ >
202
+ <box flexDirection="row" gap={1} alignItems="center">
203
+ <text fg={theme.text} attributes={TextAttributes.BOLD}>
204
+ Layout Configuration
205
+ </text>
206
+ <Show when={selectedPanel()}>
207
+ <text fg={theme.warning}>(Selected: {PANEL_NAMES[selectedPanel()!]} - click another to swap)</text>
208
+ </Show>
209
+ </box>
210
+ <box flexDirection="row" gap={3}>
211
+ <text fg={theme.textMuted} onMouseUp={handleReset}>
212
+ [Reset]
213
+ </text>
214
+ <text
215
+ fg={isLayoutValid() ? theme.primary : theme.textMuted}
216
+ attributes={isLayoutValid() ? TextAttributes.BOLD : undefined}
217
+ onMouseUp={handleReturn}
218
+ >
219
+ {isLayoutValid() ? "[Done]" : "[Done] (needs 100%)"}
220
+ </text>
221
+ </box>
222
+ </box>
223
+
224
+ {/* Instructions */}
225
+ <box
226
+ flexShrink={0}
227
+ paddingTop={1}
228
+ paddingBottom={1}
229
+ paddingLeft={2}
230
+ paddingRight={2}
231
+ backgroundColor={theme.backgroundPanel}
232
+ >
233
+ <text fg={theme.textMuted}>
234
+ Click panels to select and swap positions. Use +/- to adjust widths. Toggle visibility below.
235
+ </text>
236
+ </box>
237
+
238
+ {/* Layout Preview */}
239
+ <box
240
+ flexShrink={0}
241
+ paddingTop={1}
242
+ paddingBottom={1}
243
+ paddingLeft={2}
244
+ paddingRight={2}
245
+ flexDirection="column"
246
+ gap={1}
247
+ >
248
+ <box
249
+ width={previewDimensions().width}
250
+ height={previewDimensions().height}
251
+ flexDirection="row"
252
+ border={["left", "right", "top", "bottom"]}
253
+ borderColor={theme.border}
254
+ padding={0}
255
+ gap={0}
256
+ >
257
+ <For each={visiblePanels()}>
258
+ {(panel) => {
259
+ const isSelected = createMemo(() => selectedPanel() === panel.type)
260
+ const canSwapHere = createMemo(() => {
261
+ const selected = selectedPanel()
262
+ if (!selected) return false
263
+ const selectedPanelObj = layout.getPanelByType(selected)
264
+ return selectedPanelObj && selectedPanelObj.position !== panel.position
265
+ })
266
+ const width = createMemo(() => getPanelPreviewWidth(panel))
267
+
268
+ return (
269
+ <box
270
+ width={width()}
271
+ height="100%"
272
+ backgroundColor={getPanelColor(panel.type, isSelected() ? 0.7 : 1.0)}
273
+ border={
274
+ isSelected()
275
+ ? ["left", "right", "top", "bottom"]
276
+ : canSwapHere()
277
+ ? ["left", "right", "top", "bottom"]
278
+ : []
279
+ }
280
+ borderColor={isSelected() ? theme.warning : canSwapHere() ? theme.success : theme.border}
281
+ flexDirection="column"
282
+ justifyContent="center"
283
+ alignItems="center"
284
+ gap={1}
285
+ onMouseUp={() => handlePanelClick(panel.type)}
286
+ >
287
+ {/* Panel Header */}
288
+ <box
289
+ paddingLeft={1}
290
+ paddingRight={1}
291
+ paddingTop={0}
292
+ paddingBottom={0}
293
+ backgroundColor={theme.background}
294
+ >
295
+ <text fg={getPanelColor(panel.type, 1.0)} attributes={TextAttributes.BOLD}>
296
+ {PANEL_NAMES[panel.type]}
297
+ </text>
298
+ </box>
299
+
300
+ {/* Description */}
301
+ <text fg={theme.text}>{PANEL_DESC[panel.type]}</text>
302
+
303
+ {/* Selected indicator */}
304
+ <Show when={isSelected()}>
305
+ <box marginTop={1} paddingLeft={1} paddingRight={1} backgroundColor={theme.warning}>
306
+ <text fg={theme.background} attributes={TextAttributes.BOLD}>
307
+ Selected (click another to swap)
308
+ </text>
309
+ </box>
310
+ </Show>
311
+
312
+ {/* Swap hint */}
313
+ <Show when={canSwapHere() && !isSelected()}>
314
+ <box marginTop={1} paddingLeft={1} paddingRight={1} backgroundColor={theme.success}>
315
+ <text fg={theme.background} attributes={TextAttributes.BOLD}>
316
+ Click to swap
317
+ </text>
318
+ </box>
319
+ </Show>
320
+
321
+ {/* Hide button */}
322
+ <box
323
+ marginTop={2}
324
+ paddingLeft={2}
325
+ paddingRight={2}
326
+ paddingTop={0}
327
+ paddingBottom={0}
328
+ backgroundColor={theme.backgroundElement}
329
+ onMouseUp={(e) => {
330
+ e.stopPropagation()
331
+ layout.togglePanel(panel.type)
332
+ }}
333
+ >
334
+ <text fg={theme.textMuted}>[Hide]</text>
335
+ </box>
336
+ </box>
337
+ )
338
+ }}
339
+ </For>
340
+
341
+ {/* Show hidden panels as thin collapsed strips */}
342
+ <For each={layout.panels.filter((p) => !p.visible)}>
343
+ {(panel) => {
344
+ const isSelected = createMemo(() => selectedPanel() === panel.type)
345
+
346
+ return (
347
+ <box
348
+ width={3}
349
+ height="100%"
350
+ backgroundColor={theme.backgroundElement}
351
+ border={isSelected() ? ["left", "right", "top", "bottom"] : ["left"]}
352
+ borderColor={isSelected() ? theme.warning : theme.border}
353
+ flexDirection="column"
354
+ justifyContent="center"
355
+ alignItems="center"
356
+ onMouseUp={() => {
357
+ // Clicking hidden panel while another is selected just deselects
358
+ if (selectedPanel()) {
359
+ setSelectedPanel(null)
360
+ }
361
+ }}
362
+ >
363
+ {/* Vertical text for hidden panel */}
364
+ <text fg={theme.textMuted} attributes={TextAttributes.BOLD}>
365
+ {PANEL_NAMES[panel.type][0]}
366
+ </text>
367
+ <Show when={isSelected()}>
368
+ <box marginTop={1} backgroundColor={theme.warning}>
369
+ <text fg={theme.background}>!</text>
370
+ </box>
371
+ </Show>
372
+ </box>
373
+ )
374
+ }}
375
+ </For>
376
+ </box>
377
+
378
+ {/* Legend with Visibility Toggles - One panel per line */}
379
+ <box flexDirection="column" gap={1} paddingTop={1} paddingLeft={1} paddingRight={1}>
380
+ <For each={layout.panels}>
381
+ {(panel) => (
382
+ <box flexDirection="row" gap={2} alignItems="center">
383
+ {/* Panel header */}
384
+ <box flexDirection="row" gap={1} alignItems="center" width={16}>
385
+ <box width={3} height={1} backgroundColor={getPanelColor(panel.type, 1.0)} />
386
+ <text fg={theme.text}>{PANEL_NAMES[panel.type]}</text>
387
+ </box>
388
+
389
+ {/* Visibility toggle */}
390
+ <box
391
+ paddingLeft={1}
392
+ paddingRight={1}
393
+ backgroundColor={panel.visible ? theme.success : theme.backgroundElement}
394
+ onMouseUp={() => layout.togglePanel(panel.type)}
395
+ >
396
+ <text fg={panel.visible ? theme.background : theme.textMuted}>
397
+ {panel.visible ? "[show]" : "[hide]"}
398
+ </text>
399
+ </box>
400
+
401
+ {/* Width controls with +/- (only for visible panels) */}
402
+ <Show when={panel.visible}>
403
+ <box flexDirection="row" gap={1} alignItems="center">
404
+ <text
405
+ fg={theme.primary}
406
+ onMouseUp={(e) => {
407
+ e.stopPropagation()
408
+ adjustWidth(panel.type, "minus")
409
+ }}
410
+ >
411
+ [-]
412
+ </text>
413
+ <text
414
+ fg={theme.primary}
415
+ onMouseUp={(e) => {
416
+ e.stopPropagation()
417
+ adjustWidth(panel.type, "plus")
418
+ }}
419
+ >
420
+ [+]
421
+ </text>
422
+ </box>
423
+ </Show>
424
+ </box>
425
+ )}
426
+ </For>
427
+ </box>
428
+ </box>
429
+
430
+ {/* Footer */}
431
+ <box
432
+ flexShrink={0}
433
+ paddingTop={1}
434
+ paddingBottom={1}
435
+ paddingLeft={2}
436
+ paddingRight={2}
437
+ border={["top"]}
438
+ borderColor={theme.border}
439
+ flexDirection="row"
440
+ justifyContent="space-between"
441
+ >
442
+ <text fg={theme.textMuted}>Click panels to swap. [Done] to apply. ESC to cancel.</text>
443
+ <text fg={theme.textMuted}>
444
+ Total: {Math.round(layout.panels.reduce((sum, p) => sum + (p.visible ? p.width : 0), 0))}%
445
+ </text>
446
+ </box>
447
+ </box>
448
+ )
449
+ }
@@ -0,0 +1,172 @@
1
+ import { cmd } from "@/cli/cmd/cmd"
2
+ import { tui } from "./app"
3
+ import { Rpc } from "@/util/rpc"
4
+ import { type rpc } from "./worker"
5
+ import path from "path"
6
+ import { UI } from "@/cli/ui"
7
+ import { iife } from "@/util/iife"
8
+ import { Log } from "@/util/log"
9
+ import { withNetworkOptions, resolveNetworkOptions } from "@/cli/network"
10
+ import type { Event } from "@jonsoc/sdk/v2"
11
+ import type { EventSource } from "./context/sdk"
12
+
13
+ declare global {
14
+ const OPENCODE_WORKER_PATH: string
15
+ }
16
+
17
+ type RpcClient = ReturnType<typeof Rpc.client<typeof rpc>>
18
+
19
+ function createWorkerFetch(client: RpcClient): typeof fetch {
20
+ const fn = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {
21
+ const request = new Request(input, init)
22
+ const body = request.body ? await request.text() : undefined
23
+ const result = await client.call("fetch", {
24
+ url: request.url,
25
+ method: request.method,
26
+ headers: Object.fromEntries(request.headers.entries()),
27
+ body,
28
+ })
29
+ return new Response(result.body, {
30
+ status: result.status,
31
+ headers: result.headers,
32
+ })
33
+ }
34
+ return fn as typeof fetch
35
+ }
36
+
37
+ function createEventSource(client: RpcClient): EventSource {
38
+ return {
39
+ on: (handler) => client.on<Event>("event", handler),
40
+ }
41
+ }
42
+
43
+ export const TuiThreadCommand = cmd({
44
+ command: "$0 [project]",
45
+ describe: "start jonsoc tui",
46
+ builder: (yargs) =>
47
+ withNetworkOptions(yargs)
48
+ .positional("project", {
49
+ type: "string",
50
+ describe: "path to start jonsoc in",
51
+ })
52
+ .option("model", {
53
+ type: "string",
54
+ alias: ["m"],
55
+ describe: "model to use in the format of provider/model",
56
+ })
57
+ .option("continue", {
58
+ alias: ["c"],
59
+ describe: "continue the last session",
60
+ type: "boolean",
61
+ })
62
+ .option("session", {
63
+ alias: ["s"],
64
+ type: "string",
65
+ describe: "session id to continue",
66
+ })
67
+ .option("prompt", {
68
+ type: "string",
69
+ describe: "prompt to use",
70
+ })
71
+ .option("agent", {
72
+ type: "string",
73
+ describe: "agent to use",
74
+ }),
75
+ handler: async (args) => {
76
+ // Resolve relative paths against PWD to preserve behavior when using --cwd flag
77
+ const baseCwd = process.env.PWD ?? process.cwd()
78
+
79
+ // If args.project is "tui", it means no project was specified (tui was treated as positional arg)
80
+ const projectArg = args.project === "tui" ? undefined : args.project
81
+
82
+ const cwd = projectArg ? path.resolve(baseCwd, projectArg) : process.cwd()
83
+ const localWorker = new URL("./worker.ts", import.meta.url)
84
+ const distWorker = new URL("./cli/cmd/tui/worker.js", import.meta.url)
85
+ const workerPath = await iife(async () => {
86
+ if (typeof OPENCODE_WORKER_PATH !== "undefined") return OPENCODE_WORKER_PATH
87
+ if (await Bun.file(distWorker).exists()) return distWorker
88
+ return localWorker
89
+ })
90
+ try {
91
+ process.chdir(cwd)
92
+ } catch (e) {
93
+ UI.error("Failed to change directory to " + cwd)
94
+ return
95
+ }
96
+
97
+ const worker = new Worker(workerPath, {
98
+ env: {
99
+ ...Object.fromEntries(
100
+ Object.entries(process.env).filter((entry): entry is [string, string] => entry[1] !== undefined),
101
+ ),
102
+ PRINT_LOGS: process.argv.includes("--print-logs") ? "1" : "0",
103
+ },
104
+ })
105
+ worker.onerror = (e) => {
106
+ Log.Default.error(e)
107
+ }
108
+ const client = Rpc.client<typeof rpc>(worker)
109
+ process.on("uncaughtException", (e) => {
110
+ Log.Default.error(e)
111
+ })
112
+ process.on("unhandledRejection", (e) => {
113
+ Log.Default.error(e)
114
+ })
115
+ process.on("SIGUSR2", async () => {
116
+ await client.call("reload", undefined)
117
+ })
118
+
119
+ const prompt = await iife(async () => {
120
+ const piped = !process.stdin.isTTY ? await Bun.stdin.text() : undefined
121
+ if (!args.prompt) return piped
122
+ return piped ? piped + "\n" + args.prompt : args.prompt
123
+ })
124
+
125
+ // Check if server should be started (port or hostname explicitly set in CLI or config)
126
+ const networkOpts = await resolveNetworkOptions(args)
127
+ const shouldStartServer =
128
+ process.argv.includes("--port") ||
129
+ process.argv.includes("--hostname") ||
130
+ process.argv.includes("--mdns") ||
131
+ networkOpts.mdns ||
132
+ networkOpts.port !== 0 ||
133
+ networkOpts.hostname !== "127.0.0.1"
134
+
135
+ let url: string
136
+ let customFetch: typeof fetch | undefined
137
+ let events: EventSource | undefined
138
+
139
+ if (shouldStartServer) {
140
+ // Start HTTP server for external access
141
+ const server = await client.call("server", networkOpts)
142
+ url = server.url
143
+ } else {
144
+ // Use direct RPC communication (no HTTP)
145
+ url = "http://jonsoc.internal"
146
+ customFetch = createWorkerFetch(client)
147
+ events = createEventSource(client)
148
+ }
149
+
150
+ const tuiPromise = tui({
151
+ url,
152
+ fetch: customFetch,
153
+ events,
154
+ args: {
155
+ continue: args.continue,
156
+ sessionID: args.session,
157
+ agent: args.agent,
158
+ model: args.model,
159
+ prompt,
160
+ },
161
+ onExit: async () => {
162
+ await client.call("shutdown", undefined)
163
+ },
164
+ })
165
+
166
+ setTimeout(() => {
167
+ client.call("checkUpgrade", { directory: cwd }).catch(() => {})
168
+ }, 1000)
169
+
170
+ await tuiPromise
171
+ },
172
+ })