@turmind/halo 0.1.9

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 (296) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +143 -0
  3. package/admin-out/404.html +1 -0
  4. package/admin-out/_next/static/IBP_mwBDf-cPwZSZZGpi8/_buildManifest.js +1 -0
  5. package/admin-out/_next/static/IBP_mwBDf-cPwZSZZGpi8/_ssgManifest.js +1 -0
  6. package/admin-out/_next/static/chunks/1d2d5650-810a3ca1ae20cab5.js +18 -0
  7. package/admin-out/_next/static/chunks/200.3b8f8a74f005a134.js +1 -0
  8. package/admin-out/_next/static/chunks/220.3dc41cd6269b88e6.js +1 -0
  9. package/admin-out/_next/static/chunks/298-d6b224b569da4de0.js +1 -0
  10. package/admin-out/_next/static/chunks/304eda7d.b1ee7f523653e027.js +1 -0
  11. package/admin-out/_next/static/chunks/330.3b784cf0dcd69163.js +1 -0
  12. package/admin-out/_next/static/chunks/442.f4302087bddb1ec1.js +1 -0
  13. package/admin-out/_next/static/chunks/443.d1b289781793f8de.js +25 -0
  14. package/admin-out/_next/static/chunks/503-7c6d9935df6e0cea.js +1 -0
  15. package/admin-out/_next/static/chunks/533.5f2d4bfe3d076095.js +1 -0
  16. package/admin-out/_next/static/chunks/579.a2718ddd395a2f3a.js +1 -0
  17. package/admin-out/_next/static/chunks/635-3dd0043ed0520b9d.js +1 -0
  18. package/admin-out/_next/static/chunks/65.859665ba6717967a.js +1 -0
  19. package/admin-out/_next/static/chunks/661.a4fe93f3f2a5e871.js +1 -0
  20. package/admin-out/_next/static/chunks/688.4e014ac6cfc7e152.js +1 -0
  21. package/admin-out/_next/static/chunks/868.0c95dfe283400a00.js +1 -0
  22. package/admin-out/_next/static/chunks/app/_not-found/page-8e35399c8fd5016d.js +1 -0
  23. package/admin-out/_next/static/chunks/app/layout-58f773336e6fce61.js +1 -0
  24. package/admin-out/_next/static/chunks/app/page-cc8043335282d745.js +1 -0
  25. package/admin-out/_next/static/chunks/db534642.09d3c650ff587175.js +1 -0
  26. package/admin-out/_next/static/chunks/fb4ec4d6-3fa44f69484f91b9.js +1 -0
  27. package/admin-out/_next/static/chunks/framework-c3031ae54a63fe16.js +1 -0
  28. package/admin-out/_next/static/chunks/main-14b48e3c2588354f.js +1 -0
  29. package/admin-out/_next/static/chunks/main-app-483b436873410ddc.js +1 -0
  30. package/admin-out/_next/static/chunks/pages/_app-b2fc6e5f920d1b1a.js +1 -0
  31. package/admin-out/_next/static/chunks/pages/_error-f3696a8f3d67d150.js +1 -0
  32. package/admin-out/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  33. package/admin-out/_next/static/chunks/webpack-8bd7ef88a6527feb.js +1 -0
  34. package/admin-out/_next/static/css/659eccb5db697b76.css +1 -0
  35. package/admin-out/_next/static/css/8fce4e1a54dac12a.css +3 -0
  36. package/admin-out/_next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
  37. package/admin-out/_next/static/media/21350d82a1f187e9-s.woff2 +0 -0
  38. package/admin-out/_next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  39. package/admin-out/_next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
  40. package/admin-out/_next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
  41. package/admin-out/_next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  42. package/admin-out/_next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  43. package/admin-out/favicon.ico +0 -0
  44. package/admin-out/icon.svg +18 -0
  45. package/admin-out/index.html +1 -0
  46. package/admin-out/index.txt +23 -0
  47. package/admin-out/monaco/vs/_commonjsHelpers-CT9FvmAN.js +1 -0
  48. package/admin-out/monaco/vs/abap-D-t0cyap.js +1 -0
  49. package/admin-out/monaco/vs/apex-CcIm7xu6.js +1 -0
  50. package/admin-out/monaco/vs/assets/css.worker-HnVq6Ewq.js +93 -0
  51. package/admin-out/monaco/vs/assets/editor.worker-Be8ye1pW.js +26 -0
  52. package/admin-out/monaco/vs/assets/html.worker-B51mlPHg.js +470 -0
  53. package/admin-out/monaco/vs/assets/json.worker-DKiEKt88.js +58 -0
  54. package/admin-out/monaco/vs/assets/ts.worker-CMbG-7ft.js +67731 -0
  55. package/admin-out/monaco/vs/azcli-BA0tQDCg.js +1 -0
  56. package/admin-out/monaco/vs/basic-languages/monaco.contribution.js +1 -0
  57. package/admin-out/monaco/vs/bat-C397hTD6.js +1 -0
  58. package/admin-out/monaco/vs/bicep-DF5aW17k.js +2 -0
  59. package/admin-out/monaco/vs/cameligo-plsz8qhj.js +1 -0
  60. package/admin-out/monaco/vs/clojure-Y2auQMzK.js +1 -0
  61. package/admin-out/monaco/vs/coffee-Bu45yuWE.js +1 -0
  62. package/admin-out/monaco/vs/cpp-CkKPQIni.js +1 -0
  63. package/admin-out/monaco/vs/csharp-CX28MZyh.js +1 -0
  64. package/admin-out/monaco/vs/csp-D8uWnyxW.js +1 -0
  65. package/admin-out/monaco/vs/css-CaeNmE3S.js +3 -0
  66. package/admin-out/monaco/vs/cssMode-CjiAH6dQ.js +1 -0
  67. package/admin-out/monaco/vs/cypher-DVThT8BS.js +1 -0
  68. package/admin-out/monaco/vs/dart-CmGfCvrO.js +1 -0
  69. package/admin-out/monaco/vs/dockerfile-CZqqYdch.js +1 -0
  70. package/admin-out/monaco/vs/ecl-30fUercY.js +1 -0
  71. package/admin-out/monaco/vs/editor/editor.main.css +1 -0
  72. package/admin-out/monaco/vs/editor/editor.main.js +5 -0
  73. package/admin-out/monaco/vs/editor.api-CalNCsUg.js +903 -0
  74. package/admin-out/monaco/vs/elixir-xjPaIfzF.js +1 -0
  75. package/admin-out/monaco/vs/flow9-DqtmStfK.js +1 -0
  76. package/admin-out/monaco/vs/freemarker2-Cz_sV6Md.js +3 -0
  77. package/admin-out/monaco/vs/fsharp-BOMdg4U1.js +1 -0
  78. package/admin-out/monaco/vs/go-D_hbi-Jt.js +1 -0
  79. package/admin-out/monaco/vs/graphql-CKUU4kLG.js +1 -0
  80. package/admin-out/monaco/vs/handlebars-OwglfO-1.js +1 -0
  81. package/admin-out/monaco/vs/hcl-DTaboeZW.js +1 -0
  82. package/admin-out/monaco/vs/html-Pa1xEWsY.js +1 -0
  83. package/admin-out/monaco/vs/htmlMode-Bz67EXwp.js +1 -0
  84. package/admin-out/monaco/vs/ini-CsNwO04R.js +1 -0
  85. package/admin-out/monaco/vs/java-CI4ZMsH9.js +1 -0
  86. package/admin-out/monaco/vs/javascript-PczUCGdz.js +1 -0
  87. package/admin-out/monaco/vs/jsonMode-DULH5oaX.js +7 -0
  88. package/admin-out/monaco/vs/julia-BwzEvaQw.js +1 -0
  89. package/admin-out/monaco/vs/kotlin-IUYPiTV8.js +1 -0
  90. package/admin-out/monaco/vs/language/css/monaco.contribution.js +1 -0
  91. package/admin-out/monaco/vs/language/html/monaco.contribution.js +1 -0
  92. package/admin-out/monaco/vs/language/json/monaco.contribution.js +1 -0
  93. package/admin-out/monaco/vs/language/typescript/monaco.contribution.js +1 -0
  94. package/admin-out/monaco/vs/less-C0eDYdqa.js +2 -0
  95. package/admin-out/monaco/vs/lexon-iON-Kj97.js +1 -0
  96. package/admin-out/monaco/vs/liquid-DqKjdPGy.js +1 -0
  97. package/admin-out/monaco/vs/loader.js +1368 -0
  98. package/admin-out/monaco/vs/lspLanguageFeatures-kM9O9rjY.js +4 -0
  99. package/admin-out/monaco/vs/lua-DtygF91M.js +1 -0
  100. package/admin-out/monaco/vs/m3-CsR4AuFi.js +1 -0
  101. package/admin-out/monaco/vs/markdown-C_rD0bIw.js +1 -0
  102. package/admin-out/monaco/vs/mdx-DEWtB1K5.js +1 -0
  103. package/admin-out/monaco/vs/mips-CiYP61RB.js +1 -0
  104. package/admin-out/monaco/vs/monaco.contribution-D2OdxNBt.js +1 -0
  105. package/admin-out/monaco/vs/monaco.contribution-DO3azKX8.js +1 -0
  106. package/admin-out/monaco/vs/monaco.contribution-EcChJV6a.js +1 -0
  107. package/admin-out/monaco/vs/monaco.contribution-qLAYrEOP.js +1 -0
  108. package/admin-out/monaco/vs/msdax-C38-sJlp.js +1 -0
  109. package/admin-out/monaco/vs/mysql-CdtbpvbG.js +1 -0
  110. package/admin-out/monaco/vs/nls.messages-loader.js +1 -0
  111. package/admin-out/monaco/vs/nls.messages.cs.js.js +17 -0
  112. package/admin-out/monaco/vs/nls.messages.de.js.js +17 -0
  113. package/admin-out/monaco/vs/nls.messages.es.js.js +17 -0
  114. package/admin-out/monaco/vs/nls.messages.fr.js.js +15 -0
  115. package/admin-out/monaco/vs/nls.messages.it.js.js +15 -0
  116. package/admin-out/monaco/vs/nls.messages.ja.js.js +17 -0
  117. package/admin-out/monaco/vs/nls.messages.js.js +10 -0
  118. package/admin-out/monaco/vs/nls.messages.ko.js.js +25 -0
  119. package/admin-out/monaco/vs/nls.messages.pl.js.js +17 -0
  120. package/admin-out/monaco/vs/nls.messages.pt-br.js.js +6 -0
  121. package/admin-out/monaco/vs/nls.messages.ru.js.js +17 -0
  122. package/admin-out/monaco/vs/nls.messages.tr.js.js +15 -0
  123. package/admin-out/monaco/vs/nls.messages.zh-cn.js.js +17 -0
  124. package/admin-out/monaco/vs/nls.messages.zh-tw.js.js +15 -0
  125. package/admin-out/monaco/vs/objective-c-CntZFaHX.js +1 -0
  126. package/admin-out/monaco/vs/pascal-r6kuqfl_.js +1 -0
  127. package/admin-out/monaco/vs/pascaligo-BiXoTmXh.js +1 -0
  128. package/admin-out/monaco/vs/perl-DABw_TcH.js +1 -0
  129. package/admin-out/monaco/vs/pgsql-me_jFXeX.js +1 -0
  130. package/admin-out/monaco/vs/php-D_kh-9LK.js +1 -0
  131. package/admin-out/monaco/vs/pla-VfZjczW0.js +1 -0
  132. package/admin-out/monaco/vs/postiats-BBSzz8Pk.js +1 -0
  133. package/admin-out/monaco/vs/powerquery-Dt-g_2cc.js +1 -0
  134. package/admin-out/monaco/vs/powershell-B-7ap1zc.js +1 -0
  135. package/admin-out/monaco/vs/protobuf-BmtuEB1A.js +2 -0
  136. package/admin-out/monaco/vs/pug-BRpRNeEb.js +1 -0
  137. package/admin-out/monaco/vs/python-Cr0UkIbn.js +1 -0
  138. package/admin-out/monaco/vs/qsharp-BzsFaUU9.js +1 -0
  139. package/admin-out/monaco/vs/r-f8dDdrp4.js +1 -0
  140. package/admin-out/monaco/vs/razor-BYAHOTkz.js +1 -0
  141. package/admin-out/monaco/vs/redis-fvZQY4PI.js +1 -0
  142. package/admin-out/monaco/vs/redshift-45Et0LQi.js +1 -0
  143. package/admin-out/monaco/vs/restructuredtext-C7UUFKFD.js +1 -0
  144. package/admin-out/monaco/vs/ruby-CZO8zYTz.js +1 -0
  145. package/admin-out/monaco/vs/rust-Bfetafyc.js +1 -0
  146. package/admin-out/monaco/vs/sb-3GYllVck.js +1 -0
  147. package/admin-out/monaco/vs/scala-foMgrKo1.js +1 -0
  148. package/admin-out/monaco/vs/scheme-CHdMtr7p.js +1 -0
  149. package/admin-out/monaco/vs/scss-C1cmLt9V.js +3 -0
  150. package/admin-out/monaco/vs/shell-ClXCKCEW.js +1 -0
  151. package/admin-out/monaco/vs/solidity-MZ6ExpPy.js +1 -0
  152. package/admin-out/monaco/vs/sophia-DWkuSsPQ.js +1 -0
  153. package/admin-out/monaco/vs/sparql-AUGFYSyk.js +1 -0
  154. package/admin-out/monaco/vs/sql-32GpJSV2.js +1 -0
  155. package/admin-out/monaco/vs/st-CuDFIVZ_.js +1 -0
  156. package/admin-out/monaco/vs/swift-n-2HociN.js +3 -0
  157. package/admin-out/monaco/vs/systemverilog-Ch4vA8Yt.js +1 -0
  158. package/admin-out/monaco/vs/tcl-D74tq1nH.js +1 -0
  159. package/admin-out/monaco/vs/tsMode-CZz1Umrk.js +11 -0
  160. package/admin-out/monaco/vs/twig-C6taOxMV.js +1 -0
  161. package/admin-out/monaco/vs/typescript-DfOrAzoV.js +1 -0
  162. package/admin-out/monaco/vs/typespec-D-PIh9Xw.js +1 -0
  163. package/admin-out/monaco/vs/vb-Dyb2648j.js +1 -0
  164. package/admin-out/monaco/vs/wgsl-BhLXMOR0.js +298 -0
  165. package/admin-out/monaco/vs/workers-DcJshg-q.js +1 -0
  166. package/admin-out/monaco/vs/xml-CdsdnY8S.js +1 -0
  167. package/admin-out/monaco/vs/yaml-DYGvmE88.js +1 -0
  168. package/bin/halo.js +9 -0
  169. package/bundled-docs/design/agent.md +145 -0
  170. package/bundled-docs/design/architecture.md +270 -0
  171. package/bundled-docs/design/background-dispatch.md +151 -0
  172. package/bundled-docs/design/command.md +58 -0
  173. package/bundled-docs/design/cron.md +88 -0
  174. package/bundled-docs/design/evolution.md +383 -0
  175. package/bundled-docs/design/express-self.md +145 -0
  176. package/bundled-docs/design/feishu.md +224 -0
  177. package/bundled-docs/design/halo-city.md +112 -0
  178. package/bundled-docs/design/prompt-system.md +411 -0
  179. package/bundled-docs/design/session.md +321 -0
  180. package/bundled-docs/design/slack.md +212 -0
  181. package/bundled-docs/design/storage.md +578 -0
  182. package/bundled-docs/design/telegram.md +161 -0
  183. package/bundled-docs/design/web.md +222 -0
  184. package/bundled-docs/design/wechat.md +146 -0
  185. package/bundled-docs/design/ws.md +144 -0
  186. package/bundled-docs/dev/acp-adapter.md +337 -0
  187. package/bundled-docs/dev/add-channel.md +376 -0
  188. package/bundled-docs/dev/add-model-provider.md +386 -0
  189. package/bundled-docs/dev/api.md +686 -0
  190. package/bundled-docs/dev/deploy.md +198 -0
  191. package/bundled-docs/dev/desktop-packaging.md +327 -0
  192. package/bundled-docs/dev/env.md +158 -0
  193. package/bundled-docs/dev/logging.md +85 -0
  194. package/bundled-docs/dev/previews.md +225 -0
  195. package/bundled-docs/dev/tools.md +331 -0
  196. package/bundled-docs/guide/README.md +29 -0
  197. package/bundled-docs/guide/agents.md +264 -0
  198. package/bundled-docs/guide/channels/README.md +62 -0
  199. package/bundled-docs/guide/channels/acp.md +150 -0
  200. package/bundled-docs/guide/channels/feishu.md +154 -0
  201. package/bundled-docs/guide/channels/slack.md +156 -0
  202. package/bundled-docs/guide/channels/telegram.md +112 -0
  203. package/bundled-docs/guide/channels/web.md +149 -0
  204. package/bundled-docs/guide/channels/wechat.md +110 -0
  205. package/bundled-docs/guide/chat.md +112 -0
  206. package/bundled-docs/guide/cli.md +197 -0
  207. package/bundled-docs/guide/getting-started.md +93 -0
  208. package/bundled-docs/guide/secrets-and-credentials.md +161 -0
  209. package/bundled-docs/guide/sessions.md +104 -0
  210. package/bundled-docs/guide/skills.md +302 -0
  211. package/bundled-docs/guide/testing-agents-and-skills.md +136 -0
  212. package/bundled-docs/guide/workspace.md +131 -0
  213. package/bundled-docs/plans/cron-tasks.md +362 -0
  214. package/bundled-docs/plans/design-suggestions.md +203 -0
  215. package/bundled-docs/plans/issue-session-deep-nesting.md +208 -0
  216. package/bundled-docs/plans/launch-plan.md +111 -0
  217. package/bundled-docs/plans/md-and-agent-refactor.md +197 -0
  218. package/bundled-docs/plans/remote-mac-worker.md +196 -0
  219. package/bundled-docs/plans/roadmap.md +40 -0
  220. package/bundled-docs/plans/self-evolution.md +1379 -0
  221. package/bundled-docs/plans/todo.md +32 -0
  222. package/bundled-docs/plans/weixin-channel.md +255 -0
  223. package/bundled-docs/requirements/agent.md +92 -0
  224. package/bundled-docs/requirements/chat.md +81 -0
  225. package/bundled-docs/requirements/command.md +130 -0
  226. package/bundled-docs/requirements/editor.md +82 -0
  227. package/bundled-docs/requirements/explorer.md +89 -0
  228. package/bundled-docs/requirements/overview.md +62 -0
  229. package/bundled-docs/requirements/session.md +73 -0
  230. package/bundled-docs/requirements/settings.md +224 -0
  231. package/bundled-docs/requirements/skill.md +125 -0
  232. package/bundled-docs/requirements/source-control.md +82 -0
  233. package/bundled-docs/requirements/terminal.md +118 -0
  234. package/bundled-docs/requirements/workspace.md +80 -0
  235. package/bundled-docs/test/docs-seeding.md +101 -0
  236. package/bundled-docs/test/session.md +374 -0
  237. package/dist/index.js +26750 -0
  238. package/package.json +67 -0
  239. package/templates/INSTRUCTIONS.md +25 -0
  240. package/templates/agents/__apply_agent__/AGENT.md +229 -0
  241. package/templates/agents/__apply_agent__/agent.yaml +30 -0
  242. package/templates/agents/__evo_agent__/AGENT.md +323 -0
  243. package/templates/agents/__evo_agent__/agent.yaml +29 -0
  244. package/templates/agents/__score__/AGENT.md +177 -0
  245. package/templates/agents/__score__/agent.yaml +29 -0
  246. package/templates/agents/deep-executor/AGENT.md +60 -0
  247. package/templates/agents/deep-executor/agent.yaml +25 -0
  248. package/templates/agents/default/AGENT.md +38 -0
  249. package/templates/agents/default/agent.yaml +51 -0
  250. package/templates/agents/executor/AGENT.md +38 -0
  251. package/templates/agents/executor/agent.yaml +25 -0
  252. package/templates/aliases.yaml +26 -0
  253. package/templates/canvas/self.html +660 -0
  254. package/templates/config.yaml +69 -0
  255. package/templates/models/anthropic.yaml +47 -0
  256. package/templates/models/aws-bedrock-claude-invoke.yaml +156 -0
  257. package/templates/models/aws-bedrock-mantle.yaml +89 -0
  258. package/templates/models/deepseek.yaml +62 -0
  259. package/templates/models/doubao.yaml +137 -0
  260. package/templates/models/hunyuan.yaml +56 -0
  261. package/templates/models/kimi.yaml +41 -0
  262. package/templates/models/mimo-token-plan-china.yaml +61 -0
  263. package/templates/models/minimax.yaml +80 -0
  264. package/templates/models/openai.yaml +51 -0
  265. package/templates/models/qwen.yaml +78 -0
  266. package/templates/optional-skills/tavily-web-search/SKILL.md +91 -0
  267. package/templates/optional-skills/tavily-web-search/config.yaml +10 -0
  268. package/templates/prompts/all/TOOL_GUIDELINES.md +35 -0
  269. package/templates/prompts/all/TOOL_SHELL.md +4 -0
  270. package/templates/prompts/all/TOOL_SHELL.windows.md +7 -0
  271. package/templates/prompts/bootstrap/BOOTSTRAP.md +26 -0
  272. package/templates/prompts/root/WORKSPACE_MEMORY.md +11 -0
  273. package/templates/schema.sql +30 -0
  274. package/templates/skills/acp/SKILL.md +236 -0
  275. package/templates/skills/acp/templates/SKILL.md.tmpl +74 -0
  276. package/templates/skills/acp/templates/ask.py +176 -0
  277. package/templates/skills/acp/templates/config.yaml.tmpl +33 -0
  278. package/templates/skills/agent/SKILL.md +128 -0
  279. package/templates/skills/aws-knowledge/SKILL.md +82 -0
  280. package/templates/skills/aws-knowledge/scripts/aws_kb.py +61 -0
  281. package/templates/skills/cron/SKILL.md +217 -0
  282. package/templates/skills/cron/manage-cron.py +434 -0
  283. package/templates/skills/halo/SKILL.md +98 -0
  284. package/templates/skills/nova-web-search/SKILL.md +65 -0
  285. package/templates/skills/self/SKILL.md +139 -0
  286. package/templates/skills/send-file/SKILL.md +28 -0
  287. package/templates/skills/send-file/feishu.md +16 -0
  288. package/templates/skills/send-file/slack.md +7 -0
  289. package/templates/skills/send-file/telegram.md +9 -0
  290. package/templates/skills/send-file/web.md +6 -0
  291. package/templates/skills/send-file/wechat.md +8 -0
  292. package/templates/skills/skill/SKILL.md +131 -0
  293. package/templates/skills/workspace/SKILL.md +28 -0
  294. package/templates/skills/workspace/setup-tidy.md +265 -0
  295. package/templates/skills/workspace/share.md +187 -0
  296. package/templates/skills/workspace/stage.py +487 -0
@@ -0,0 +1,149 @@
1
+ # Web
2
+
3
+ Talk to a halo agent over plain HTTP from any client you control — a browser, a curl script, a custom frontend, your own mobile app. The Web channel is the "build your own UI" channel: it gives you a token, you give the token to whatever client you wrote.
4
+
5
+ > If you want a ready-made browser frontend without writing code, halo ships `packages/web-demo` — a tiny Express app that wraps the Web channel with its own password gate. See "Standalone web-demo frontend" at the bottom.
6
+
7
+ ## What you'll end up with
8
+
9
+ - A 24-byte random token (base64url-encoded) bound to one workspace
10
+ - A few public HTTP endpoints under `/api/web/*` that accept that token
11
+
12
+ The token is **the** credential — anyone holding it can talk to the agent at the bound workspace's access level. Treat it like a password.
13
+
14
+ ## Step 1 — Create an account
15
+
16
+ Open halo admin → **Channels** → **Web** → **Add Account**:
17
+
18
+ | Field | Value |
19
+ |---|---|
20
+ | Workspace path | absolute path, e.g. `/home/ubuntu/my-project` |
21
+ | Label | optional |
22
+ | Access level | `readonly` (default), `workspace`, or `full` |
23
+ | Language | `en` or `zh` |
24
+
25
+ Click **Create**. The success screen shows the auto-generated token **once** — copy it now, you can't retrieve it again. (You can always delete the account and create a new one if you lose the token.)
26
+
27
+ ## Step 2 — Use the token
28
+
29
+ All public endpoints require an `x-token: <token>` header (or `?token=<token>` query for endpoints that can't easily set headers, like SSE in browsers).
30
+
31
+ ### Send a message (SSE stream back)
32
+
33
+ ```bash
34
+ curl -N -H "x-token: $TOKEN" -H "Content-Type: application/json" \
35
+ -d '{"message":"hello"}' \
36
+ http://localhost:9527/api/web/chat
37
+ ```
38
+
39
+ Response is a stream of `data: {json}\n\n` SSE frames:
40
+
41
+ ```
42
+ data: {"type":"session","sessionId":"web_abc123_m1xyz"}
43
+ data: {"type":"thinking","text":"..."}
44
+ data: {"type":"tool_call","toolName":"file_read","toolInput":{...}}
45
+ data: {"type":"tool_result","toolName":"file_read","result":"..."}
46
+ data: {"type":"stream","text":"Hello! "}
47
+ data: {"type":"stream","text":"How can I help?"}
48
+ data: {"type":"complete"}
49
+ ```
50
+
51
+ Parse the `type` field on each event to render text vs tool calls vs completion.
52
+
53
+ ### Other endpoints
54
+
55
+ | Method | Path | Purpose |
56
+ |---|---|---|
57
+ | `POST /api/web/chat` | Send a message; SSE response |
58
+ | `POST /api/web/stop` | Cancel the running task |
59
+ | `GET /api/web/history` | Fetch session message history |
60
+ | `GET /api/web/subscribe` | Reconnect to a running session's SSE stream |
61
+
62
+ All four accept the same auth header.
63
+
64
+ ### Per-request overrides
65
+
66
+ By default each token is locked to the workspace and active session set by the admin. External integrations (notably the [ACP adapter](acp.md)) need finer control:
67
+
68
+ - `workspace` — server-side absolute path, **gated on `accessLevel === 'full'`** (readonly / workspace tokens can't escape their bound workspace; the override is rejected)
69
+ - `sessionId` — explicit halo session id; lets clients pre-mint stable ids and address them across reconnects
70
+ - `agentId` — only used when the request creates a new session
71
+
72
+ These can be passed as POST body fields, headers (`x-workspace`, `x-session-id`, `x-agent-id`), or query params (`?workspace=…&sessionId=…&agentId=…`). POST body wins on conflict.
73
+
74
+ For browser apps you almost never want these — leave them off and use the per-token defaults.
75
+
76
+ ## Step 3 — Send images / files
77
+
78
+ `/api/web/chat` accepts an optional `images` array, base64-encoded:
79
+
80
+ ```json
81
+ {
82
+ "message": "what's in this picture?",
83
+ "images": [
84
+ { "data": "<base64>", "mimeType": "image/png" }
85
+ ]
86
+ }
87
+ ```
88
+
89
+ Images go to the LLM as multimodal content. Audio and other binary uploads aren't supported on this endpoint directly — for those, save the file to `<workspace>/.halo/assets/web/inbound/<accountId>/<date>/` first (out-of-band) and reference its path in your message text.
90
+
91
+ The standalone web-demo handles voice + arbitrary files for you; if you want that, use it as a reference implementation.
92
+
93
+ ## Slash commands
94
+
95
+ Slash commands are intercepted before they reach the agent — same set as every other channel:
96
+
97
+ | Command | Effect |
98
+ |---|---|
99
+ | `/session <verb>` | Session lifecycle: `new` / `list` / `switch <n>` / `stop` / `interrupt` / `compact` / `context` |
100
+ | `/agent <verb>` | Manage agents (`list` / `switch` / `desc` open to all; `delete` full; `create` / `update` via skill, full) |
101
+ | `/skill <verb>` | Manage skills (`list` / `desc` open; `disable` / `enable` workspace; `delete` full; `create` / `update` via skill, full) |
102
+ | `/workspace <verb>` | Workspace: `info` (all) / `switch <path>` (full) / `setup` / `tidy` (workspace) / `share` (full) |
103
+ | `/help` | List commands — object commands show only the verbs you can run |
104
+
105
+ Send a slash command exactly like a normal message — the server detects the leading `/`.
106
+
107
+ ## Common problems
108
+
109
+ | Symptom | Cause / fix |
110
+ |---|---|
111
+ | `401` on every call | Missing `x-token` header, or token is for a deleted account |
112
+ | `403` when passing `workspace=…` | Token is `readonly` / `workspace` access — only `full` can override |
113
+ | SSE stream hangs forever | Reverse proxy buffering. Disable buffering for `text/event-stream` (nginx: `proxy_buffering off`, Cloudflare: enable streaming) |
114
+ | Token leaked accidentally | Delete the account in admin, create a new one. The old token is invalidated immediately |
115
+ | Want to share one token across multiple users | Don't — every request would land on the same active session. Create one account per user / app |
116
+
117
+ ## Standalone web-demo frontend
118
+
119
+ If you want a browser UI with login, image upload, voice recording, and multi-language support without writing it yourself:
120
+
121
+ ```bash
122
+ cd packages/web-demo
123
+ node server.js
124
+ ```
125
+
126
+ Environment variables:
127
+
128
+ | Variable | Required | Description |
129
+ |---|---|---|
130
+ | `HALO_API` | yes | Halo server URL, e.g. `http://localhost:9527` |
131
+ | `HALO_TOKEN` | yes | The web-channel token from Step 1 |
132
+ | `HALO_WEB_DEMO_PASSWORD` | no | Password gate; empty means open access |
133
+ | `PORT` | no | Listen port; default `9528` |
134
+
135
+ The demo holds your token server-side and exposes its own password-based session — the browser never sees the halo token. Open `http://localhost:9528` to use it.
136
+
137
+ ## Security notes
138
+
139
+ - **Tokens are unhashed** in `~/.halo/secrets/channels/channels.db`. Restrict that file to the user that runs halo
140
+ - **No rate limit at the channel level** — if you expose the API on the public internet, put a reverse proxy with rate limits in front
141
+ - **Admin endpoints** (`POST /api/web/accounts`, `PATCH`, `DELETE`) require admin cookie auth, **not** the token. They're for the admin panel, not for the token holder
142
+ - A `full`-access token can call `/workspace <abs-path>` to switch the bound workspace database-side. If you don't want that, give out `workspace` or `readonly` tokens instead
143
+
144
+ ## Reference
145
+
146
+ - Code: `packages/server/src/channels/web/`
147
+ - Routes: `packages/server/src/routes/web.ts`
148
+ - Admin UI: `packages/admin/src/features/web/web-settings.tsx`
149
+ - Design notes: [../../design/web.md](../../design/web.md)
@@ -0,0 +1,110 @@
1
+ # WeChat (微信)
2
+
3
+ Talk to a halo agent from WeChat on your phone. Halo registers an **iLink-style bot** with `ilinkai.weixin.qq.com` and you bind it by **scanning a QR code with WeChat** — no developer registration, no public webhook needed.
4
+
5
+ > The iLink bot is a personal-account bot, not a Public Account / Mini Program. The bot you scan-bind to is the account you'll DM in WeChat — there's no separate "follow this bot" step.
6
+
7
+ ## What you'll end up with
8
+
9
+ - A bot account row keyed by your WeChat user id (the one that scanned the QR)
10
+ - An `ilinkai` long-poll loop pulling messages on behalf of that bot
11
+ - Bot owner = whoever scanned the QR. The same WeChat ID is used as the default cron-job recipient
12
+
13
+ ## Step 1 — Create a workspace folder
14
+
15
+ You need an existing absolute path on the server before scanning. Either:
16
+
17
+ - Open the workspace in halo's web UI (the `.halo/` folder gets auto-created), then copy the absolute path
18
+ - Or `mkdir -p /home/ubuntu/my-project` from a terminal
19
+
20
+ Halo auto-creates `.halo/` inside the folder if it doesn't exist; the path itself must already exist.
21
+
22
+ ## Step 2 — Open the admin scan flow
23
+
24
+ Open halo admin → **Channels** → **WeChat** → **Add Account**.
25
+
26
+ The form is **just the workspace + label + access level + language** — no bot token field, because the token comes from the scan:
27
+
28
+ | Field | Value |
29
+ |---|---|
30
+ | Workspace path | absolute path from Step 1, e.g. `/home/ubuntu/my-project` |
31
+ | Label | optional, shown in admin's account list |
32
+ | Access level | `readonly` (default), `workspace`, or `full` |
33
+ | Language | `en` or `zh` |
34
+
35
+ Click **Generate QR**. Halo hits `ilinkai.weixin.qq.com` to mint a fresh QR code and starts a poll loop waiting for the scan.
36
+
37
+ ## Step 3 — Scan with WeChat
38
+
39
+ 1. Open WeChat on your phone
40
+ 2. Tap the `+` in the top right → **Scan / 扫一扫**
41
+ 3. Aim at the QR shown in the admin UI
42
+ 4. Tap **Confirm Login / 确认登录** on the phone
43
+
44
+ Within a few seconds the admin UI shows "登录成功" / "Logged in" and switches to the success page. Behind the scenes:
45
+
46
+ - iLink returns the bot's token, the IDC-specific `baseUrl`, and your WeChat-side `ilink_user_id`
47
+ - Halo writes those into the new account row
48
+ - The long-poll loop starts immediately — the bot is now live
49
+
50
+ The QR is valid for ~3 minutes; if it expires the admin UI auto-refreshes. If you cancel and come back later, just open the form again — a new QR is minted.
51
+
52
+ ## Step 4 — Test it
53
+
54
+ The bot's name in your WeChat contacts is whatever the iLink platform set it to (typically a generic placeholder like `小助手`; you can rename it locally). Open the bot's chat in WeChat and send `hello` → expect a streamed reply.
55
+
56
+ If nothing happens, check halo server logs for `[weixin]` lines.
57
+
58
+ ## How halo handles inbound
59
+
60
+ - **Text** — sent to the agent
61
+ - **Images** — passed to the LLM as multimodal content
62
+ - **Voice** — decrypted, saved under `<workspace>/.halo/assets/weixin/inbound/<accountId>/<date>/`, path included in the agent's input
63
+ - **Video / files** — same as voice
64
+ - **Group chats** — not supported in v1 (group messages are dropped)
65
+ - **Self-loop** — bot-authored messages are filtered out
66
+
67
+ ## Slash commands
68
+
69
+ Same set as the other channels — type as plain text in your WeChat DM with the bot:
70
+
71
+ | Command | Effect |
72
+ |---|---|
73
+ | `/session <verb>` | Session lifecycle: `new` / `list` / `switch <n>` / `stop` / `interrupt` / `compact` / `context` |
74
+ | `/agent <verb>` | Manage agents (`list` / `switch` / `desc` open to all; `delete` full; `create` / `update` via skill, full) |
75
+ | `/skill <verb>` | Manage skills (`list` / `desc` open; `disable` / `enable` workspace; `delete` full; `create` / `update` via skill, full) |
76
+ | `/workspace <verb>` | Workspace: `info` (all) / `switch <path>` (full) / `setup` / `tidy` (workspace) / `share` (full) |
77
+ | `/help` | List commands — object commands show only the verbs you can run |
78
+ | `/qr [level]` | Generate an invite QR (admin only) |
79
+
80
+ ## Cron jobs targeting WeChat
81
+
82
+ WeChat is single-recipient — cron output goes to the QR-bind owner (the WeChat user who scanned in Step 3). The dispatcher resolves recipients in this order:
83
+
84
+ 1. Explicit `chatId` on the cron target row (set when the cron is created from inside WeChat)
85
+ 2. The QR-bind owner (`account.userId`) — the "report to me on a schedule" default
86
+ 3. Most-recent inbound chat ID, as a fallback for shared bots
87
+
88
+ Fan-out across multiple WeChat users is not supported — one bot, one owner.
89
+
90
+ ## Common problems
91
+
92
+ | Symptom | Cause / fix |
93
+ |---|---|
94
+ | QR shows but scan does nothing | iLink platform thinks the QR is for a different account. Cancel and regenerate |
95
+ | "二维码已过期" / QR expired | Admin UI should auto-refresh. If not, click Generate again |
96
+ | Bot stops responding after a few hours | Long-poll likely lost its `syncBuf`. Restart the server; reconnect is automatic |
97
+ | Two halo processes both poll the same bot | Each process gets a copy of every message, replied twice. Make sure only one server runs — see `~/.halo/global/server.pid` |
98
+ | Group chat doesn't trigger the bot | Expected — groups aren't supported in v1 |
99
+ | Sent voice message returns no reply | Check that the account has `workspace` or `full` access; readonly cannot save inbound media |
100
+
101
+ ## Multi-workspace / multi-bot
102
+
103
+ Each scan = one account = one workspace binding. To use a second workspace, open the admin form again and scan a second time (with the same WeChat user or a different one). Each scan mints a fresh `ilink_bot_id` even from the same WeChat account, so the two are independent.
104
+
105
+ ## Reference
106
+
107
+ - Code: `packages/server/src/channels/wechat/`
108
+ - Login flow: `packages/server/src/channels/wechat/login.ts`
109
+ - Admin UI: `packages/admin/src/features/weixin/weixin-settings.tsx`
110
+ - Design notes: [../../design/wechat.md](../../design/wechat.md)
@@ -0,0 +1,112 @@
1
+ # Chat — User Guide
2
+
3
+ The Chat panel at the bottom is the main surface for talking to an agent.
4
+
5
+ ## Picking an agent
6
+
7
+ The dropdown to the left of the input lists every agent (global + workspace).
8
+
9
+ - The agent with the highest `priority` is auto-selected for new sessions. The seed `Default` agent uses `priority: 99`, so it wins until you raise another agent above it.
10
+ - Once you manually pick an agent, that choice is remembered across `clear` / new sessions until you pick something else.
11
+ - **A conversation is locked to one agent**: once you start chatting, the dropdown locks. To change agent, start a new session (`/session new`).
12
+
13
+ ## Sending messages
14
+
15
+ - Enter to send
16
+ - Shift+Enter for a newline
17
+ - The agent streams its reply; tool calls render inline as cards
18
+
19
+ ## Context injection
20
+
21
+ Next to the chat is a `📎 Context` toggle (on by default). When on, Halo auto-injects:
22
+ - The currently open file path: `[Currently viewing: src/foo.ts]`
23
+ - The editor's current selection: `[Selected text in foo.ts:10-25]\n\`\`\`...\n\`\`\``
24
+
25
+ Turn it off if you don't want that context injected.
26
+
27
+ ## `@` file mention
28
+
29
+ Typing `@` in the input opens a file search:
30
+ - Real-time fuzzy matching (150 ms debounce)
31
+ - Selecting inserts a path chip
32
+ - You can `@` multiple files back-to-back
33
+
34
+ The search scans the whole project on the server — independent of Explorer expansion state.
35
+
36
+ ## Attachments
37
+
38
+ - **Drag**: drop files onto the input
39
+ - **Paste**: paste an image from the clipboard
40
+ - **Button**: click the 📎 on the left
41
+
42
+ Images are sent to the agent as base64, with multimodal support (Claude 4.6 can see images).
43
+
44
+ ## Slash commands
45
+
46
+ Typing `/` opens autocomplete.
47
+
48
+ Most commands are noun-verb **object commands**: `/<obj> <verb> [args]`. Bare `/<obj>` (or `/<obj> help`) lists the verbs you're allowed to run.
49
+
50
+ | Command | Purpose |
51
+ |---|---|
52
+ | `/session <verb>` | Manage sessions — `new` / `list` / `switch <n>` / `stop` / `interrupt` / `compact` / `context`. All built-in, available to everyone. `new` starts a fresh conversation (old session stays in the sidebar; running sub-agents keep going); `compact` keeps the most recent N messages intact (N defaults to 5, `general.compact.keep_messages`); `context` shows token usage, agent info, and available tools |
53
+ | `/clear` | Admin-UI alias for `/session new` |
54
+ | `/agent <verb>` | Manage agents — `list` / `switch <name\|index>` / `desc` (built-in, open to all) · `delete` (built-in, full access) · `create` / `update` (handled by the `agent` skill, full access) |
55
+ | `/skill <verb>` | Manage skills — `list` / `desc` (built-in, open to all) · `disable` / `enable` (built-in, workspace access) · `delete` (built-in, full access) · `create` / `update` (handled by the `skill` skill, full access) |
56
+ | `/workspace <verb>` | Manage the workspace — `info` (built-in, open to all) · `switch <path>` (built-in, full access) · `setup` / `tidy` (workspace skill, workspace access; init / reorganize `.halo/` INDEX.md / INSTRUCTIONS.md / memory/) · `share` (workspace skill, full access; export a shareable bundle) |
57
+ | `/cron <verb>` | Scheduled agent runs — `create` / `list` / `update` / `enable` / `disable` / `delete` (cron skill, full access) |
58
+ | `/acp <verb>` | Talk to other agents over ACP — `kiro <q>` / `claude <q>` ask a local agent directly; `add` / `list` / `remove` manage generated `ask-<label>` bindings (acp skill, full access) |
59
+ | `/evo [hint]` | Queue a self-evolution run on this session (full access only) |
60
+ | `/help` | List every command — object commands only show the verbs you can run |
61
+
62
+ Skills can also register slash commands (put `command: /xxx` in the SKILL.md frontmatter).
63
+
64
+ ### WeChat channel commands
65
+
66
+ If you're chatting from WeChat, the same shared commands are available (routed through the common command dispatcher), plus one WeChat-specific extra:
67
+
68
+ | Command | Purpose |
69
+ |---|---|
70
+ | `/session new` | Create a new session; old sessions stay accessible via `/session list` + `/session switch` (nothing is archived) |
71
+ | `/session list` | List recent sessions (newest first); the active one is marked `→` |
72
+ | `/session switch <index>` | Switch the active session to the indexed one (readonly bot 仅能切到自己的 [我] 会话) |
73
+ | `/workspace info` / `/workspace switch <path>` | Show or switch workspace (absolute path; 切换仅 full 权限 bot 可用) |
74
+ | `/qr [level]` | Generate an invite QR for a new bot account (full 权限 bot 专用) |
75
+ | `/help` | Show help |
76
+
77
+ If the session is currently compacting or busy when your message arrives, you'll see a hint — ("⏳ integrating context…" / "🔄 queued…") — and the message is queued (while compacting it's dropped; while busy it's kept).
78
+
79
+ ## Interrupt vs Stop
80
+
81
+ Two ways to interrupt the agent:
82
+
83
+ **Graceful interrupt**: send another message during streaming. The message is queued on the server; at the next tool-call checkpoint, the agent wraps up the current turn and then runs the queued message. Multiple messages can queue in order.
84
+
85
+ **Hard stop**: click the red ⏹ button. Immediate abort, queue cleared, no checkpoint waiting.
86
+
87
+ ## Token ring
88
+
89
+ The ring in the bottom-right of the input shows context window usage:
90
+ - Green: < 50%
91
+ - Yellow: 50–70%
92
+ - Orange: 70–90%
93
+ - Red: > 90%
94
+
95
+ Reaching `compressAt` (default 70%) auto-triggers compact. While the agent is running you can't click the TokenRing (guarded by `isStreaming`).
96
+
97
+ ## Session history
98
+
99
+ Next to the header is the session-list dropdown:
100
+ - Lists every session in the current workspace
101
+ - Click to switch (the current one auto-saves + detaches)
102
+ - Sub-agent sessions show as indented entries
103
+
104
+ For full inspection, use the Activity Bar's "Sessions" tab — Debug mode lets you inspect tool calls, system prompts, usage, etc.
105
+
106
+ ## Common situations
107
+
108
+ **"Queued" hint**: the previous turn hasn't finished; your message is queued and will run next turn.
109
+
110
+ **"Rate limited, retrying in Xs..."**: Bedrock throttled; automatic exponential backoff (up to 5 retries).
111
+
112
+ **A sudden `[Message from xxx]`**: a sub-agent finished and auto-reported back to the parent agent's conversation.
@@ -0,0 +1,197 @@
1
+ # CLI / TUI
2
+
3
+ Standalone terminal client for Halo. Runs the agent loop directly in the CLI process — no server required. Shares the same agent core, tools, session management, and command system as the admin panel and other channels.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm --filter @turmind/halo-cli build
9
+ ```
10
+
11
+ The binary is at `packages/cli/bin/halo.js`. For global access, link it:
12
+
13
+ ```bash
14
+ pnpm --filter @turmind/halo-cli link --global
15
+ ```
16
+
17
+ ### Publishing to npm (maintainers)
18
+
19
+ The published package is `@turmind/halo` — a self-contained esbuild bundle
20
+ (CLI + server + admin-out + templates), staged under `packages/cli/dist-pub/`
21
+ by `scripts/build-bundle.mjs`. The workspace `@turmind/halo-cli` can't be
22
+ published directly (it has `workspace:*` deps); the bundle flattens them.
23
+
24
+ ```bash
25
+ # 1. bump packages/cli/package.json "version" (e.g. 0.1.2)
26
+ # 2. build the upstream artifacts the bundle consumes
27
+ pnpm --filter @turmind/halo-core build
28
+ pnpm --filter @turmind/halo-server build
29
+ cd packages/admin && npx next build --no-lint && node scripts/copy-monaco.mjs && cd ../..
30
+ # 3. stage the release bundle — HALO_RELEASE=1 stamps the bare version
31
+ # (0.1.2), NOT the default <version>-<sha>: a `-<sha>` suffix is a semver
32
+ # prerelease that `npm install` skips and never tags as `latest`.
33
+ HALO_RELEASE=1 node packages/cli/scripts/build-bundle.mjs
34
+ # 4. preview + publish
35
+ cd packages/cli/dist-pub
36
+ npm pack --dry-run # inspect tarball contents
37
+ npm publish # @turmind/halo@<version>, tag latest, public
38
+ ```
39
+
40
+ npm versions are immutable — a published version can never be overwritten,
41
+ so bump first and verify with `npm pack --dry-run` before `npm publish`.
42
+ End users then install with `npm install -g @turmind/halo`.
43
+
44
+ ## CLI Mode (non-interactive)
45
+
46
+ Run a one-shot prompt and exit:
47
+
48
+ ```bash
49
+ halo "review this PR"
50
+ halo -w /path/to/workspace "analyze code"
51
+ echo "review the changes" | halo
52
+ cat prompt.txt | halo -w /path/to/review-ws
53
+ ```
54
+
55
+ ### Options
56
+
57
+ | Flag | Short | Default | Description |
58
+ |---|---|---|---|
59
+ | `--workspace` | `-w` | cwd | Workspace path |
60
+ | `--agent` | `-a` | `default` | Agent ID |
61
+ | `--session` | `-s` | auto | Resume session by ID |
62
+ | `--format` | `-f` | `text` | Output format: `text` or `json` |
63
+ | `--verbose` | `-v` | off | Show thinking, tool calls, usage on stderr |
64
+ | `--access` | | `full` | Access level: `full`, `workspace`, `readonly` |
65
+ | `--agents` | | | List available agents and exit |
66
+ | `--sessions` | | | List recent sessions and exit |
67
+ | `--lang` | | `en` | Language: `en` or `zh` |
68
+
69
+ ### Output
70
+
71
+ - **text format**: Agent response is rendered as styled markdown (headings, bold, code blocks, tables) on stdout. Tool calls, thinking, usage go to stderr (visible with `-v`).
72
+
73
+ Usage line mirrors the admin chat-panel badge format (timestamp / in / out / ctx / read / write / cache% / ttft / e2e / think / model). `ctx` is the rolled-up context size — `inputTokens + cacheRead + cacheWrite + outputTokens` — so it doesn't look misleading next to a large cache hit:
74
+
75
+ ```
76
+ [ 17:23:02 in 0.0K out 0.1K ctx 5.8K read 5.3K write 0.3K cache 94% e2e 3.3s think medium claude-sonnet-4-6 ]
77
+ ```
78
+ - **json format**: Single JSON object on stdout after completion:
79
+
80
+ ```json
81
+ {
82
+ "text": "...",
83
+ "sessionId": "cli_abc123",
84
+ "toolCalls": [{ "name": "file_list", "durationMs": 1 }],
85
+ "usage": { "inputTokens": 6, "outputTokens": 42, "cacheReadInputTokens": 10000, "modelId": "..." },
86
+ "error": null
87
+ }
88
+ ```
89
+
90
+ ### Pipeline integration
91
+
92
+ ```bash
93
+ # Code review in CI
94
+ halo -w /path/to/review-ws "review the diff" --format json | jq '.text'
95
+
96
+ # Pipe content in
97
+ git diff HEAD~1 | halo -w /path/to/review-ws "review this diff"
98
+
99
+ # Exit code: 0 = success, 1 = error, 130 = SIGINT
100
+ halo "check for issues" && echo "OK" || echo "FAILED"
101
+ ```
102
+
103
+ ## TUI Mode (interactive)
104
+
105
+ ```bash
106
+ halo -i
107
+ halo -i -w /path/to/workspace
108
+ halo -i -s sid_abc123 # resume session
109
+ ```
110
+
111
+ Multi-turn conversation. Supports all standard Halo slash commands:
112
+
113
+ | Command | Description |
114
+ |---|---|
115
+ | `/help` | Show available commands |
116
+ | `/session new` | Start a new session |
117
+ | `/session list` | List recent sessions |
118
+ | `/session switch <n>` | Switch to session by number |
119
+ | `/session stop` | Stop current agent task (ends the turn, no re-run) |
120
+ | `/session interrupt` | Interrupt the running turn now (aborts a command mid-run); any messages queued while busy then run as one follow-up turn |
121
+ | `/session compact` | Compact session context |
122
+ | `/session context` | Show context window + agent info |
123
+ | `/agent <verb>` | Manage agents: `list` / `switch <name\|index>` / `desc` / `delete` / `create` / `update` |
124
+ | `/skill <verb>` | Manage skills: `list` / `desc` / `disable` / `enable` / `delete` / `create` / `update` |
125
+ | `/workspace info` | Show current workspace |
126
+ | `/workspace switch <path>` | Switch workspace (full access only) |
127
+ | `/workspace setup` / `/workspace tidy` / `/workspace share` | Set up / tidy the `.halo/` knowledge files, or export a shareable bundle (workspace skill) |
128
+ | `/cron <verb>` | Manage scheduled agent runs: `create` / `list` / `update` / `enable` / `disable` / `delete` |
129
+ | `/acp <verb>` | Ask other agents over ACP (`kiro <q>` / `claude <q>`) and manage `ask-*` bindings (`add` / `list` / `remove`) |
130
+ | `/evo [hint]` | Queue a self-evolution run on this session (full access only) |
131
+ | `/quit` | Exit |
132
+
133
+ Bare `/<obj>` (or `/<obj> help`) lists the verbs you may run. Verbs gated above your access level are hidden.
134
+
135
+ ### Keybindings
136
+
137
+ | Key | Action |
138
+ |---|---|
139
+ | `Esc` (while running) | Interrupt the current turn immediately — aborts a command mid-execution, then any messages typed while it was running are folded into one follow-up turn. Same as `/session interrupt`. |
140
+ | `Ctrl+C` | Graceful exit; press twice to force |
141
+ | `Ctrl+O` | Toggle the sub-agent navigator — lists every sub-agent spawned this session, each showing its agent name, task title (same as the session list), and status (`●` running green / `○` idle grey / `✕` stopped red, plus a `▢ archived` marker when the session is archived); `↑↓` to move, `Enter` to view that sub-agent's log, `Esc`/`q` to close. (Was `Shift+Tab`, but Windows terminals consume that as backtab.) The log viewer auto-refreshes while the viewed session is still running (a `● live` hint shows in the header) and follows the bottom as new output lands — unless you've scrolled up to read, in which case it stays put (`G` jumps back to the bottom and resumes following). |
142
+ | `↑` / `↓` | Walk input history (when no popup is open) |
143
+
144
+ On resume (`-s <id>`, or the default latest session), the TUI replays the session's prior conversation on screen so you see where you left off. `shell_exec` output is shown inline by default (other tools' output needs `-v`).
145
+
146
+ ## File, Image, and Scope References
147
+
148
+ Attach files or images to your message with `@file` and `@image`, or pull a directory's instructions into the turn with `@scope`:
149
+
150
+ ```
151
+ > summarize @file src/index.ts
152
+ > compare @file a.ts and @file b.ts
153
+ > describe @image screenshot.png
154
+ > review @file "path with spaces/readme.md"
155
+ > @scope packages/server refactor the session manager
156
+ ```
157
+
158
+ - `@file path` — reads the file and inlines its content in the message as `<file>` block
159
+ - `@image path` — reads the image as base64 and sends it via the model's vision input
160
+ - `@file photo.png` — image extensions (`.png`, `.jpg`, `.gif`, `.webp`, `.bmp`) are auto-detected as images
161
+ - `@scope dir` — injects the directory-scoped `.halo/INSTRUCTIONS.md` along the path from the workspace root down to `dir` (root level excluded — it's already in the system prompt) into **this turn only**. Use it to bring a sub-directory's conventions into scope for one request. It does not change where tools run.
162
+ - Paths are relative to the workspace; absolute paths also work
163
+ - Quoted paths supported for filenames with spaces: `@file "my file.txt"`
164
+ - **Tab completion** in TUI mode: type `@file ` (or `@scope `, which lists directories only) then press Tab to browse
165
+
166
+ ### Limits
167
+
168
+ - **Text files**: truncated at 100KB with a `[truncated]` marker
169
+ - **Images**: skipped if larger than 5MB
170
+ - If the current model does not support vision, a warning is shown and images are ignored
171
+
172
+ ## Architecture
173
+
174
+ ```
175
+ packages/cli/
176
+ src/
177
+ index.ts — Entry: arg parsing, mode dispatch, SIGINT handling
178
+ harness.ts — Shared agent harness wrapping SessionManager
179
+ cli.ts — Non-interactive: stdin/args → agent → stdout → exit
180
+ tui.ts — Interactive: readline loop + event display + commands
181
+ format-usage.ts — Usage-line formatter (mirrors admin UsageLine badge order)
182
+ resolve-refs.ts — @file / @image reference resolution with size limits
183
+ render-md.ts — Terminal markdown rendering (marked + marked-terminal)
184
+ ```
185
+
186
+ The CLI directly imports server agent-core modules (`SessionManager`, `dispatchCommand`, tools, config, DB) via `@turmind/halo-server/*` subpath exports. No HTTP/WS layer is involved.
187
+
188
+ Session prefix: `cli_`. Sessions are persisted to `<workspace>/.halo/sessions/` and visible in the admin panel.
189
+
190
+ ### Initialization
191
+
192
+ The CLI replicates the server's init sequence:
193
+ 1. `initLogger()` — redirect console to stderr + file logger
194
+ 2. `ensureHaloHome()` — ensure `~/.halo/` structure
195
+ 3. `initBwrapCheck()` — probe sandbox availability
196
+ 4. `setSandboxHiddenPaths()` — configure sandbox paths
197
+ 5. `new SessionManager(workspace)` — create agent session manager
@@ -0,0 +1,93 @@
1
+ # Getting Started
2
+
3
+ What to do the first time you open Halo.
4
+
5
+ ## Log in
6
+
7
+ Open `http://localhost:9527` (or your deployment URL) in a browser and enter the password.
8
+
9
+ - The default password is printed to the **server console** (auto-generated if you haven't set `HALO_PASSWORD`)
10
+ - You can also pin a password via `server.password` in `~/.halo/secrets/config.yaml`
11
+
12
+ ## Open a workspace
13
+
14
+ After login, you land in the workspace. A URL with `?folder=/abs/path` opens that directory directly; without `?folder`, Halo falls back to your home directory as the workspace — everything still works.
15
+
16
+ The Explorer top bar has two ways to switch workspace:
17
+ - **Type an absolute path** + Enter — invalid paths raise an error
18
+ - **Click the 📁🔍 button** — opens a VS Code-style directory picker: single click to select, double click to enter, ArrowUp to go up, 🏠 for home, paste paths into the top input
19
+
20
+ Halo auto-creates a `.halo/` subdirectory in the target folder (for sessions, agents, skills, memory). If `.halo/` already exists, opening the folder just works.
21
+
22
+ ## First conversation (bootstrap)
23
+
24
+ The first time a new user chats with the Default agent, the agent asks a few questions:
25
+ - What should I call you?
26
+ - What would you like to call me?
27
+ - Preferred communication style (formal/casual, English/other language, etc.)
28
+
29
+ Your answers are written to `~/.halo/global/USER.md`; from then on every root agent reads that user profile.
30
+
31
+ > Don't want the bootstrap flow? Create `~/.halo/global/USER.md` manually (any content) and the agent will skip the guided flow.
32
+
33
+ ### Workspace onboarding
34
+
35
+ The global `INSTRUCTIONS.md` template explains Halo's `.halo/` conventions (`INDEX.md`, `INSTRUCTIONS.md`, `memory/`). When the current workspace has no `INDEX.md`, the system prompt also nudges the agent to offer drafting one from the README / package.json. If you want a guided setup, type `/workspace setup`; to clean up an existing workspace later, type `/workspace tidy` — both backed by the `workspace` skill (setup: interview + draft; tidy: review + prune + reshape).
36
+
37
+ ## Send a message
38
+
39
+ In the bottom Chat panel:
40
+ 1. Type in the input
41
+ 2. Enter to send (Shift+Enter for newline)
42
+ 3. The agent streams its reply, showing text + tool call cards
43
+
44
+ You can keep typing while it replies — messages queue and run at the next safe checkpoint.
45
+
46
+ **Stop button** (red): interrupt immediately, no checkpoint waiting.
47
+
48
+ ## Handy shortcuts
49
+
50
+ | Action | Shortcut / Method |
51
+ |---|---|
52
+ | File mention | Type `@` in the input, pick a file |
53
+ | Slash command | Type `/`, auto-complete pops up (`/session`, `/agent`, …) |
54
+ | Quick find file | `Cmd/Ctrl+P` |
55
+ | Save file | `Cmd/Ctrl+S` |
56
+ | New conversation | `/session new` |
57
+ | Compact context | `/session compact` |
58
+ | Set up / reorganize workspace | `/workspace setup` / `/workspace tidy` |
59
+
60
+ ## What `~/.halo/` looks like
61
+
62
+ After `halo setup`:
63
+
64
+ ```
65
+ ~/.halo/
66
+ ├── global/ ← server-managed, see overwrite policy below
67
+ │ ├── INSTRUCTIONS.md ← refreshed on upgrade
68
+ │ ├── prompts/{bootstrap,all,root}/ ← refreshed on upgrade
69
+ │ ├── models/<provider>.yaml ← refreshed on upgrade
70
+ │ ├── docs/ ← refreshed on upgrade (bundled platform docs)
71
+ │ ├── agents/ ← built-in ids refreshed; user-added ones untouched
72
+ │ └── skills/ ← built-in ids refreshed; user-added ones untouched
73
+ └── secrets/ ← never overwritten after first creation
74
+ ├── config.yaml ← leaf-merged: new server knobs added, existing values kept
75
+ ├── settings.yaml ← created empty if missing; otherwise untouched
76
+ └── channels/channels.db ← per-channel account state
77
+ ```
78
+
79
+ **When does "refreshed on upgrade" actually run?** `halo setup` always re-runs the seed; the server's startup check also re-runs it automatically when `~/.halo/global/.template-version` is behind the bundled `TEMPLATE_VERSION`. So the routine flow `halo upgrade && halo server restart` is enough — no need to remember `halo setup`.
80
+
81
+ **Server-refreshed**: `INSTRUCTIONS.md`, `prompts/`, `models/`, `docs/`, the built-in agent ids (`default`, `executor`, `deep-executor`, `__evo_agent__`, `__score__`, `__apply_agent__`), and the built-in skill ids (`agent`, `skill`, `workspace`, `cron`, `acp`, `send-file`, `self`, `aws-knowledge`, `nova-web-search`, `halo`). To customize one, copy it into the workspace scope (`<project>/.halo/...`) — workspace replaces global at runtime.
82
+
83
+ **Never overwritten**: anything else under `agents/` or `skills/` (your own creations), and everything under `secrets/`.
84
+
85
+ **`secrets/config.yaml`** is leaf-merged on each refresh — new keys introduced by a server upgrade are added, your existing `value`s (password, port, jwt_secret) are kept.
86
+
87
+ ## Next
88
+
89
+ - [chat.md](chat.md) — everything the chat panel does
90
+ - [agents.md](agents.md) — managing agents
91
+ - [skills.md](skills.md) — what skills are and how to use them
92
+ - [sessions.md](sessions.md) — viewing session history, debugging
93
+ - [workspace.md](workspace.md) — the overall interface